@lasso-ai/cli 1.2.1 → 1.2.3
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/CHANGELOG.md +9 -0
- package/README.md +3 -2
- package/dist/cli/agent.d.ts +2 -2
- package/dist/cli/agent.js +53 -16
- package/dist/cli/bridge.js +73 -9
- package/dist/cli/project.d.ts +2 -0
- package/dist/cli/project.js +2 -0
- package/dist/overlay.js +521 -340
- package/package.json +1 -1
package/dist/overlay.js
CHANGED
|
@@ -8093,41 +8093,8 @@
|
|
|
8093
8093
|
}
|
|
8094
8094
|
|
|
8095
8095
|
.lasso-toolbar-mini {
|
|
8096
|
-
|
|
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;
|
|
8096
|
+
display: none;
|
|
8128
8097
|
}
|
|
8129
|
-
.lasso-new-page-btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
|
|
8130
|
-
.lasso-new-page-btn:active { transform: scale(.97); }
|
|
8131
8098
|
|
|
8132
8099
|
/* ==========================================================
|
|
8133
8100
|
NEW PAGE \u2014 nested project explorer
|
|
@@ -8343,6 +8310,26 @@
|
|
|
8343
8310
|
color: var(--lo-error);
|
|
8344
8311
|
}
|
|
8345
8312
|
|
|
8313
|
+
/* Command button */
|
|
8314
|
+
.lasso-tool-btn.command-tool {
|
|
8315
|
+
color: var(--lo-text-2);
|
|
8316
|
+
}
|
|
8317
|
+
|
|
8318
|
+
.lasso-tool-btn.command-tool:hover {
|
|
8319
|
+
color: var(--lo-primary);
|
|
8320
|
+
background: rgba(129, 201, 149, 0.16);
|
|
8321
|
+
}
|
|
8322
|
+
|
|
8323
|
+
/* Page button */
|
|
8324
|
+
.lasso-tool-btn.page-tool {
|
|
8325
|
+
color: var(--lo-text-2);
|
|
8326
|
+
}
|
|
8327
|
+
|
|
8328
|
+
.lasso-tool-btn.page-tool:hover {
|
|
8329
|
+
color: var(--lo-primary);
|
|
8330
|
+
background: rgba(129, 201, 149, 0.16);
|
|
8331
|
+
}
|
|
8332
|
+
|
|
8346
8333
|
/* Badge on comment button */
|
|
8347
8334
|
.lasso-comments-badge {
|
|
8348
8335
|
display: none;
|
|
@@ -8416,7 +8403,6 @@
|
|
|
8416
8403
|
}
|
|
8417
8404
|
|
|
8418
8405
|
@media (max-width: 760px) {
|
|
8419
|
-
.lasso-toolbar-mini { left: 50%; bottom: 82px; transform: translateX(-50%); }
|
|
8420
8406
|
.lasso-new-page-panel { left: 50%; transform: translateX(-50%); }
|
|
8421
8407
|
}
|
|
8422
8408
|
|
|
@@ -9841,6 +9827,15 @@
|
|
|
9841
9827
|
background: var(--lo-surface-hover);
|
|
9842
9828
|
}
|
|
9843
9829
|
|
|
9830
|
+
.lasso-prompt-model-item.locked {
|
|
9831
|
+
cursor: not-allowed;
|
|
9832
|
+
opacity: 0.6;
|
|
9833
|
+
}
|
|
9834
|
+
|
|
9835
|
+
.lasso-prompt-model-item.locked:hover {
|
|
9836
|
+
background: transparent;
|
|
9837
|
+
}
|
|
9838
|
+
|
|
9844
9839
|
.lasso-prompt-model-item .lasso-prompt-model-check {
|
|
9845
9840
|
flex-shrink: 0;
|
|
9846
9841
|
color: var(--lo-primary);
|
|
@@ -9851,6 +9846,11 @@
|
|
|
9851
9846
|
opacity: 1;
|
|
9852
9847
|
}
|
|
9853
9848
|
|
|
9849
|
+
.lasso-prompt-model-item .lasso-prompt-model-lock {
|
|
9850
|
+
flex-shrink: 0;
|
|
9851
|
+
color: var(--lo-text-3);
|
|
9852
|
+
}
|
|
9853
|
+
|
|
9854
9854
|
.lasso-prompt-element {
|
|
9855
9855
|
min-width: 0;
|
|
9856
9856
|
margin-left: auto;
|
|
@@ -11080,47 +11080,19 @@
|
|
|
11080
11080
|
.lasso-agent-prompt-actions button:active { transform: scale(0.97); }
|
|
11081
11081
|
|
|
11082
11082
|
/* ==========================================================
|
|
11083
|
-
COMMAND
|
|
11083
|
+
COMMAND SIDEBAR (One-Shot Build Mode)
|
|
11084
11084
|
========================================================== */
|
|
11085
11085
|
|
|
11086
|
-
.lasso-command-
|
|
11087
|
-
position: fixed;
|
|
11088
|
-
inset: 0;
|
|
11089
|
-
z-index: 100;
|
|
11090
|
-
background: rgba(8, 9, 11, 0.6);
|
|
11091
|
-
backdrop-filter: blur(4px);
|
|
11092
|
-
-webkit-backdrop-filter: blur(4px);
|
|
11093
|
-
pointer-events: auto;
|
|
11094
|
-
}
|
|
11095
|
-
|
|
11096
|
-
.lasso-command-backdrop[hidden] {
|
|
11097
|
-
display: none;
|
|
11098
|
-
}
|
|
11099
|
-
|
|
11100
|
-
.lasso-command-bar {
|
|
11086
|
+
.lasso-command-sidebar {
|
|
11101
11087
|
position: fixed;
|
|
11102
|
-
top:
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11107
|
-
display: flex;
|
|
11108
|
-
align-items: center;
|
|
11109
|
-
justify-content: center;
|
|
11110
|
-
padding: 24px;
|
|
11111
|
-
pointer-events: none;
|
|
11112
|
-
}
|
|
11113
|
-
|
|
11114
|
-
.lasso-command-bar[hidden] {
|
|
11115
|
-
display: none;
|
|
11116
|
-
}
|
|
11117
|
-
|
|
11118
|
-
.lasso-command-card {
|
|
11119
|
-
width: min(600px, calc(100vw - 48px));
|
|
11120
|
-
max-height: calc(100vh - 48px);
|
|
11088
|
+
top: 16px;
|
|
11089
|
+
right: 16px;
|
|
11090
|
+
bottom: 16px;
|
|
11091
|
+
width: 380px;
|
|
11092
|
+
max-width: calc(100vw - 32px);
|
|
11121
11093
|
display: flex;
|
|
11122
11094
|
flex-direction: column;
|
|
11123
|
-
padding:
|
|
11095
|
+
padding: 0;
|
|
11124
11096
|
border: 1px solid var(--lo-border);
|
|
11125
11097
|
border-radius: var(--lo-radius-xl);
|
|
11126
11098
|
background: rgba(24, 25, 29, 0.98);
|
|
@@ -11130,12 +11102,17 @@
|
|
|
11130
11102
|
box-shadow: 0 24px 56px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.08);
|
|
11131
11103
|
pointer-events: auto;
|
|
11132
11104
|
animation: lasso-command-in 200ms cubic-bezier(0.16, 1, 0.3, 1);
|
|
11105
|
+
z-index: 100;
|
|
11106
|
+
}
|
|
11107
|
+
|
|
11108
|
+
.lasso-command-sidebar[hidden] {
|
|
11109
|
+
display: none;
|
|
11133
11110
|
}
|
|
11134
11111
|
|
|
11135
11112
|
@keyframes lasso-command-in {
|
|
11136
11113
|
from {
|
|
11137
11114
|
opacity: 0;
|
|
11138
|
-
transform:
|
|
11115
|
+
transform: translateX(12px);
|
|
11139
11116
|
}
|
|
11140
11117
|
to {
|
|
11141
11118
|
opacity: 1;
|
|
@@ -11143,11 +11120,12 @@
|
|
|
11143
11120
|
}
|
|
11144
11121
|
}
|
|
11145
11122
|
|
|
11146
|
-
.lasso-command-header {
|
|
11123
|
+
.lasso-command-sidebar-header {
|
|
11147
11124
|
display: flex;
|
|
11148
11125
|
align-items: center;
|
|
11149
11126
|
justify-content: space-between;
|
|
11150
|
-
|
|
11127
|
+
padding: 16px 20px;
|
|
11128
|
+
border-bottom: 1px solid var(--lo-border);
|
|
11151
11129
|
}
|
|
11152
11130
|
|
|
11153
11131
|
.lasso-command-brand {
|
|
@@ -11157,12 +11135,12 @@
|
|
|
11157
11135
|
}
|
|
11158
11136
|
|
|
11159
11137
|
.lasso-command-brand-logo {
|
|
11160
|
-
width:
|
|
11161
|
-
height:
|
|
11138
|
+
width: 24px;
|
|
11139
|
+
height: 24px;
|
|
11162
11140
|
}
|
|
11163
11141
|
|
|
11164
11142
|
.lasso-command-brand-title {
|
|
11165
|
-
font-size:
|
|
11143
|
+
font-size: 14px;
|
|
11166
11144
|
font-weight: 600;
|
|
11167
11145
|
letter-spacing: -0.01em;
|
|
11168
11146
|
}
|
|
@@ -11186,10 +11164,124 @@
|
|
|
11186
11164
|
color: var(--lo-text);
|
|
11187
11165
|
}
|
|
11188
11166
|
|
|
11189
|
-
.lasso-command-body {
|
|
11167
|
+
.lasso-command-sidebar-body {
|
|
11168
|
+
display: flex;
|
|
11169
|
+
flex-direction: column;
|
|
11170
|
+
gap: 16px;
|
|
11171
|
+
padding: 20px;
|
|
11172
|
+
flex: 1;
|
|
11173
|
+
overflow-y: auto;
|
|
11174
|
+
}
|
|
11175
|
+
|
|
11176
|
+
.lasso-command-model-select {
|
|
11177
|
+
position: relative;
|
|
11178
|
+
}
|
|
11179
|
+
|
|
11180
|
+
.lasso-command-model-btn {
|
|
11181
|
+
width: 100%;
|
|
11182
|
+
display: flex;
|
|
11183
|
+
align-items: center;
|
|
11184
|
+
gap: 8px;
|
|
11185
|
+
padding: 10px 12px;
|
|
11186
|
+
border: 1px solid var(--lo-border);
|
|
11187
|
+
border-radius: var(--lo-radius-md);
|
|
11188
|
+
background: var(--lo-surface-2);
|
|
11189
|
+
color: var(--lo-text);
|
|
11190
|
+
font-family: inherit;
|
|
11191
|
+
font-size: 12px;
|
|
11192
|
+
font-weight: 500;
|
|
11193
|
+
cursor: pointer;
|
|
11194
|
+
transition: border-color 140ms ease, background 140ms ease;
|
|
11195
|
+
}
|
|
11196
|
+
|
|
11197
|
+
.lasso-command-model-btn:hover {
|
|
11198
|
+
border-color: var(--lo-primary);
|
|
11199
|
+
background: var(--lo-surface-hover);
|
|
11200
|
+
}
|
|
11201
|
+
|
|
11202
|
+
.lasso-command-model-icon {
|
|
11203
|
+
flex: 0 0 auto;
|
|
11204
|
+
}
|
|
11205
|
+
|
|
11206
|
+
.lasso-command-model-label {
|
|
11207
|
+
flex: 1;
|
|
11208
|
+
min-width: 0;
|
|
11209
|
+
overflow: hidden;
|
|
11210
|
+
text-overflow: ellipsis;
|
|
11211
|
+
white-space: nowrap;
|
|
11212
|
+
}
|
|
11213
|
+
|
|
11214
|
+
.lasso-command-model-chevron {
|
|
11215
|
+
flex: 0 0 auto;
|
|
11216
|
+
transition: transform 200ms ease;
|
|
11217
|
+
}
|
|
11218
|
+
|
|
11219
|
+
.lasso-command-model-menu {
|
|
11220
|
+
position: absolute;
|
|
11221
|
+
top: calc(100% + 4px);
|
|
11222
|
+
left: 0;
|
|
11223
|
+
right: 0;
|
|
11224
|
+
max-height: 320px;
|
|
11225
|
+
overflow-y: auto;
|
|
11226
|
+
padding: 8px;
|
|
11227
|
+
border: 1px solid var(--lo-border);
|
|
11228
|
+
border-radius: var(--lo-radius-lg);
|
|
11229
|
+
background: rgba(24, 25, 29, 0.98);
|
|
11230
|
+
backdrop-filter: blur(24px);
|
|
11231
|
+
-webkit-backdrop-filter: blur(24px);
|
|
11232
|
+
color: var(--lo-text);
|
|
11233
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
|
|
11234
|
+
z-index: 10;
|
|
11235
|
+
}
|
|
11236
|
+
|
|
11237
|
+
.lasso-command-model-section {
|
|
11238
|
+
margin-bottom: 8px;
|
|
11239
|
+
}
|
|
11240
|
+
|
|
11241
|
+
.lasso-command-model-section:last-child {
|
|
11242
|
+
margin-bottom: 0;
|
|
11243
|
+
}
|
|
11244
|
+
|
|
11245
|
+
.lasso-command-model-section-header {
|
|
11246
|
+
padding: 4px 8px;
|
|
11247
|
+
font-size: 10px;
|
|
11248
|
+
font-weight: 600;
|
|
11249
|
+
text-transform: uppercase;
|
|
11250
|
+
letter-spacing: 0.05em;
|
|
11251
|
+
color: var(--lo-text-3);
|
|
11252
|
+
}
|
|
11253
|
+
|
|
11254
|
+
.lasso-command-model-item {
|
|
11255
|
+
width: 100%;
|
|
11256
|
+
display: flex;
|
|
11257
|
+
align-items: center;
|
|
11258
|
+
gap: 8px;
|
|
11259
|
+
padding: 6px 8px;
|
|
11260
|
+
border: 0;
|
|
11261
|
+
border-radius: var(--lo-radius-md);
|
|
11262
|
+
background: transparent;
|
|
11263
|
+
color: var(--lo-text);
|
|
11264
|
+
font-family: inherit;
|
|
11265
|
+
font-size: 12px;
|
|
11266
|
+
font-weight: 450;
|
|
11267
|
+
text-align: left;
|
|
11268
|
+
cursor: pointer;
|
|
11269
|
+
transition: background 120ms ease;
|
|
11270
|
+
}
|
|
11271
|
+
|
|
11272
|
+
.lasso-command-model-item:hover {
|
|
11273
|
+
background: var(--lo-surface-hover);
|
|
11274
|
+
}
|
|
11275
|
+
|
|
11276
|
+
.lasso-command-model-item.selected {
|
|
11277
|
+
background: rgba(129, 201, 149, 0.16);
|
|
11278
|
+
color: var(--lo-primary);
|
|
11279
|
+
}
|
|
11280
|
+
|
|
11281
|
+
.lasso-command-input-wrapper {
|
|
11282
|
+
flex: 1;
|
|
11190
11283
|
display: flex;
|
|
11191
11284
|
flex-direction: column;
|
|
11192
|
-
gap: 12px;
|
|
11193
11285
|
}
|
|
11194
11286
|
|
|
11195
11287
|
.lasso-command-input {
|
|
@@ -17378,8 +17470,8 @@
|
|
|
17378
17470
|
const pin = document.createElement("button");
|
|
17379
17471
|
pin.type = "button";
|
|
17380
17472
|
const isResolved = thread.root.status === "RESOLVED";
|
|
17381
|
-
const
|
|
17382
|
-
pin.className = `lasso-comment-pin${isResolved ? " resolved" : ""}${
|
|
17473
|
+
const isOpen = state.openThreadUid === thread.root.uid;
|
|
17474
|
+
pin.className = `lasso-comment-pin${isResolved ? " resolved" : ""}${isOpen ? " active" : ""}`;
|
|
17383
17475
|
pin.dataset.commentUid = thread.root.uid;
|
|
17384
17476
|
const authorColor = userNameColor(thread.root.author?.id || "");
|
|
17385
17477
|
const authorInitials = initials(thread.root.author?.name || "");
|
|
@@ -19019,8 +19111,17 @@
|
|
|
19019
19111
|
}
|
|
19020
19112
|
if (message.type === "config" && message.models?.length) {
|
|
19021
19113
|
state.MODELS = message.models;
|
|
19022
|
-
|
|
19023
|
-
|
|
19114
|
+
const currentLocked = state.selectedModel?.locked;
|
|
19115
|
+
if (currentLocked) {
|
|
19116
|
+
const firstUnlocked = state.MODELS.find((m) => !m.locked);
|
|
19117
|
+
if (firstUnlocked) {
|
|
19118
|
+
state.selectedModel = firstUnlocked;
|
|
19119
|
+
rememberModel(state.selectedModel);
|
|
19120
|
+
}
|
|
19121
|
+
} else {
|
|
19122
|
+
state.selectedModel = state.MODELS.find((m) => m.id === storedModelId()) || state.MODELS.find((m) => !m.locked) || state.MODELS[0];
|
|
19123
|
+
rememberModel(state.selectedModel);
|
|
19124
|
+
}
|
|
19024
19125
|
refreshModelMenu();
|
|
19025
19126
|
}
|
|
19026
19127
|
if (message.type === "git_state" && message.git) {
|
|
@@ -19649,7 +19750,7 @@
|
|
|
19649
19750
|
return;
|
|
19650
19751
|
}
|
|
19651
19752
|
const item = event.target.closest(".lasso-prompt-model-item");
|
|
19652
|
-
if (!item) return;
|
|
19753
|
+
if (!item || item.classList.contains("locked")) return;
|
|
19653
19754
|
const found = state.MODELS.find((m) => m.id === item.dataset.model);
|
|
19654
19755
|
if (!found) return;
|
|
19655
19756
|
state.selectedModel = found;
|
|
@@ -19889,6 +19990,7 @@
|
|
|
19889
19990
|
if (key === "claude-code") return "Claude Code";
|
|
19890
19991
|
if (key === "codex") return "Codex";
|
|
19891
19992
|
if (key === "opencode") return "OpenCode";
|
|
19993
|
+
if (key === "cursor") return "Cursor";
|
|
19892
19994
|
return key;
|
|
19893
19995
|
}
|
|
19894
19996
|
function modelItem(model) {
|
|
@@ -19896,7 +19998,15 @@
|
|
|
19896
19998
|
item.type = "button";
|
|
19897
19999
|
item.className = "lasso-prompt-model-item";
|
|
19898
20000
|
item.dataset.model = model.id;
|
|
19899
|
-
|
|
20001
|
+
if (model.locked) {
|
|
20002
|
+
item.classList.add("locked");
|
|
20003
|
+
item.disabled = true;
|
|
20004
|
+
item.setAttribute("aria-disabled", "true");
|
|
20005
|
+
item.setAttribute("title", model.lockedReason || "This model is locked");
|
|
20006
|
+
item.innerHTML = `${providerIcon(model.provider)}<span>${model.label}</span><svg class="lasso-prompt-model-lock" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>`;
|
|
20007
|
+
} else {
|
|
20008
|
+
item.innerHTML = `${providerIcon(model.provider)}<span>${model.label}</span><svg class="lasso-prompt-model-check" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg>`;
|
|
20009
|
+
}
|
|
19900
20010
|
return item;
|
|
19901
20011
|
}
|
|
19902
20012
|
function syncModelMenu2() {
|
|
@@ -21640,59 +21750,307 @@
|
|
|
21640
21750
|
return panelEl ? !panelEl.hidden : false;
|
|
21641
21751
|
}
|
|
21642
21752
|
|
|
21643
|
-
// src/overlay/
|
|
21644
|
-
var
|
|
21645
|
-
var
|
|
21646
|
-
var
|
|
21647
|
-
|
|
21648
|
-
|
|
21649
|
-
|
|
21650
|
-
|
|
21651
|
-
|
|
21652
|
-
|
|
21653
|
-
|
|
21654
|
-
|
|
21655
|
-
style.textContent = `html.lasso-comment-mode, html.lasso-comment-mode * { cursor: ${COMMENT_CURSOR_URL} !important; }`;
|
|
21656
|
-
document.documentElement.classList.add("lasso-comment-mode");
|
|
21657
|
-
document.documentElement.style.setProperty("cursor", COMMENT_CURSOR_URL, "important");
|
|
21658
|
-
document.body.style.setProperty("cursor", COMMENT_CURSOR_URL, "important");
|
|
21659
|
-
return;
|
|
21660
|
-
}
|
|
21661
|
-
document.documentElement.classList.remove("lasso-comment-mode");
|
|
21662
|
-
document.documentElement.style.removeProperty("cursor");
|
|
21663
|
-
document.body.style.removeProperty("cursor");
|
|
21664
|
-
style?.remove();
|
|
21665
|
-
}
|
|
21666
|
-
function setCommentMode(active) {
|
|
21667
|
-
state.commentMode = active;
|
|
21668
|
-
if (active) state.previewMode = false;
|
|
21669
|
-
const dom = getDOM();
|
|
21670
|
-
const commentBtn = dom.shadow.querySelector(".comment-tool");
|
|
21671
|
-
const previewBtn = dom.shadow.querySelector(".preview-tool");
|
|
21672
|
-
if (commentBtn) commentBtn.classList.toggle("active", active);
|
|
21673
|
-
if (previewBtn) previewBtn.classList.toggle("active", state.previewMode);
|
|
21674
|
-
if (active) {
|
|
21675
|
-
setSelectMode(false);
|
|
21676
|
-
setDragMode(false);
|
|
21677
|
-
setCommentCursor(true);
|
|
21678
|
-
} else {
|
|
21679
|
-
setCommentCursor(false);
|
|
21680
|
-
if (state.selectMode) {
|
|
21681
|
-
document.documentElement.style.cursor = "default";
|
|
21682
|
-
}
|
|
21683
|
-
}
|
|
21684
|
-
}
|
|
21685
|
-
function buildToolbar() {
|
|
21753
|
+
// src/overlay/commandbar/commandbar.ts
|
|
21754
|
+
var commandBarEl = null;
|
|
21755
|
+
var commandInput = null;
|
|
21756
|
+
var commandSubmit = null;
|
|
21757
|
+
var commandVoice = null;
|
|
21758
|
+
var commandClose = null;
|
|
21759
|
+
var commandModelBtn = null;
|
|
21760
|
+
var commandModelMenu = null;
|
|
21761
|
+
var commandModelIcon = null;
|
|
21762
|
+
var commandModelLabel = null;
|
|
21763
|
+
var isOneShotMode = false;
|
|
21764
|
+
function buildCommandBar() {
|
|
21686
21765
|
const dom = getDOM();
|
|
21687
|
-
const
|
|
21688
|
-
|
|
21689
|
-
|
|
21690
|
-
|
|
21691
|
-
|
|
21692
|
-
|
|
21693
|
-
|
|
21694
|
-
|
|
21695
|
-
|
|
21766
|
+
const el = document.createElement("div");
|
|
21767
|
+
el.className = "lasso-command-sidebar";
|
|
21768
|
+
el.hidden = true;
|
|
21769
|
+
el.innerHTML = `
|
|
21770
|
+
<div class="lasso-command-sidebar-header">
|
|
21771
|
+
<div class="lasso-command-brand">
|
|
21772
|
+
<img class="lasso-command-brand-logo" src="${LASSO_ICON_DATA_URL}" alt="Lasso" />
|
|
21773
|
+
<span class="lasso-command-brand-title">Build with AI</span>
|
|
21774
|
+
</div>
|
|
21775
|
+
<button class="lasso-command-close" type="button" aria-label="Close">
|
|
21776
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
21777
|
+
<path d="M18 6L6 18M6 6l12 12"/>
|
|
21778
|
+
</svg>
|
|
21779
|
+
</button>
|
|
21780
|
+
</div>
|
|
21781
|
+
|
|
21782
|
+
<div class="lasso-command-sidebar-body">
|
|
21783
|
+
<div class="lasso-command-model-select">
|
|
21784
|
+
<button class="lasso-command-model-btn" type="button" aria-label="Select model">
|
|
21785
|
+
<span class="lasso-command-model-icon"></span>
|
|
21786
|
+
<span class="lasso-command-model-label"></span>
|
|
21787
|
+
<svg class="lasso-command-model-chevron" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
21788
|
+
<path d="M6 9l6 6 6-6"/>
|
|
21789
|
+
</svg>
|
|
21790
|
+
</button>
|
|
21791
|
+
<div class="lasso-command-model-menu" hidden></div>
|
|
21792
|
+
</div>
|
|
21793
|
+
|
|
21794
|
+
<div class="lasso-command-input-wrapper">
|
|
21795
|
+
<textarea
|
|
21796
|
+
class="lasso-command-input"
|
|
21797
|
+
placeholder="Describe what you want to build... Examples: \u2022 Build a settings page with profile, notifications and security sections \u2022 Add authentication with login and signup \u2022 Create a dashboard with customer table and analytics"
|
|
21798
|
+
rows="6"
|
|
21799
|
+
></textarea>
|
|
21800
|
+
</div>
|
|
21801
|
+
|
|
21802
|
+
<div class="lasso-command-actions">
|
|
21803
|
+
<button class="lasso-command-voice" type="button" aria-label="Voice input" title="Voice input (speech-to-text)">
|
|
21804
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
|
21805
|
+
<rect x="9" y="3" width="6" height="11" rx="3"/>
|
|
21806
|
+
<path d="M5 11a7 7 0 0 0 14 0M12 18v3M8 21h8"/>
|
|
21807
|
+
</svg>
|
|
21808
|
+
</button>
|
|
21809
|
+
|
|
21810
|
+
<button class="lasso-command-submit primary" type="button" aria-label="Build">
|
|
21811
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
21812
|
+
<path d="M5 12h14M12 5l7 7-7 7"/>
|
|
21813
|
+
</svg>
|
|
21814
|
+
<span>Build</span>
|
|
21815
|
+
</button>
|
|
21816
|
+
</div>
|
|
21817
|
+
|
|
21818
|
+
<div class="lasso-command-shortcuts">
|
|
21819
|
+
<span class="lasso-command-shortcut">
|
|
21820
|
+
<kbd>\u2318</kbd><kbd>K</kbd>
|
|
21821
|
+
<span>Toggle one-shot mode</span>
|
|
21822
|
+
</span>
|
|
21823
|
+
<span class="lasso-command-shortcut">
|
|
21824
|
+
<kbd>\u2318</kbd><kbd>\u21B5</kbd>
|
|
21825
|
+
<span>Submit</span>
|
|
21826
|
+
</span>
|
|
21827
|
+
</div>
|
|
21828
|
+
</div>
|
|
21829
|
+
`;
|
|
21830
|
+
dom.shadow.appendChild(el);
|
|
21831
|
+
commandBarEl = el;
|
|
21832
|
+
commandInput = el.querySelector(".lasso-command-input");
|
|
21833
|
+
commandSubmit = el.querySelector(".lasso-command-submit");
|
|
21834
|
+
commandVoice = el.querySelector(".lasso-command-voice");
|
|
21835
|
+
commandClose = el.querySelector(".lasso-command-close");
|
|
21836
|
+
commandModelBtn = el.querySelector(".lasso-command-model-btn");
|
|
21837
|
+
commandModelMenu = el.querySelector(".lasso-command-model-menu");
|
|
21838
|
+
commandModelIcon = el.querySelector(".lasso-command-model-icon");
|
|
21839
|
+
commandModelLabel = el.querySelector(".lasso-command-model-label");
|
|
21840
|
+
commandModelBtn.addEventListener("click", (event) => {
|
|
21841
|
+
event.preventDefault();
|
|
21842
|
+
event.stopPropagation();
|
|
21843
|
+
if (commandModelMenu) commandModelMenu.hidden = !commandModelMenu.hidden;
|
|
21844
|
+
});
|
|
21845
|
+
commandModelMenu.addEventListener("click", (event) => {
|
|
21846
|
+
event.stopPropagation();
|
|
21847
|
+
const item = event.target.closest(".lasso-command-model-item");
|
|
21848
|
+
if (!item) return;
|
|
21849
|
+
const found = state.MODELS.find((m) => m.id === item.dataset.model);
|
|
21850
|
+
if (!found) return;
|
|
21851
|
+
state.selectedModel = found;
|
|
21852
|
+
if (commandModelIcon && commandModelLabel) {
|
|
21853
|
+
commandModelIcon.innerHTML = providerIcon(found.provider, true);
|
|
21854
|
+
commandModelLabel.textContent = found.label;
|
|
21855
|
+
}
|
|
21856
|
+
if (commandModelMenu) commandModelMenu.hidden = true;
|
|
21857
|
+
});
|
|
21858
|
+
document.addEventListener("click", (event) => {
|
|
21859
|
+
if (!commandModelMenu || commandModelMenu.hidden) return;
|
|
21860
|
+
const path = event.composedPath ? event.composedPath() : [];
|
|
21861
|
+
if (path.includes(commandModelBtn) || path.includes(commandModelMenu)) return;
|
|
21862
|
+
const target = event.target;
|
|
21863
|
+
if (commandModelBtn?.contains(target) || commandModelMenu?.contains(target)) return;
|
|
21864
|
+
commandModelMenu.hidden = true;
|
|
21865
|
+
});
|
|
21866
|
+
commandClose.addEventListener("click", (event) => {
|
|
21867
|
+
event.preventDefault();
|
|
21868
|
+
event.stopPropagation();
|
|
21869
|
+
closeCommandBar();
|
|
21870
|
+
});
|
|
21871
|
+
commandVoice.addEventListener("click", async (event) => {
|
|
21872
|
+
event.preventDefault();
|
|
21873
|
+
event.stopPropagation();
|
|
21874
|
+
if (isRecordingVoice()) {
|
|
21875
|
+
commandVoice.classList.remove("recording");
|
|
21876
|
+
commandVoice.classList.add("transcribing");
|
|
21877
|
+
commandVoice.title = "Transcribing\u2026";
|
|
21878
|
+
try {
|
|
21879
|
+
const result = await stopVoiceRecording();
|
|
21880
|
+
if (result.text && commandInput) {
|
|
21881
|
+
const prev = commandInput.value.trim();
|
|
21882
|
+
commandInput.value = prev ? `${prev} ${result.text}` : result.text;
|
|
21883
|
+
commandInput.focus();
|
|
21884
|
+
autoResizeTextarea(commandInput);
|
|
21885
|
+
showActivity("Transcribed", "#81c995");
|
|
21886
|
+
} else {
|
|
21887
|
+
showActivity("No speech detected.", "#fdd663");
|
|
21888
|
+
}
|
|
21889
|
+
} catch (err) {
|
|
21890
|
+
showActivity(err?.message || "Transcription failed", "#f28b82");
|
|
21891
|
+
} finally {
|
|
21892
|
+
commandVoice.classList.remove("transcribing");
|
|
21893
|
+
commandVoice.title = "Voice input";
|
|
21894
|
+
}
|
|
21895
|
+
} else {
|
|
21896
|
+
try {
|
|
21897
|
+
await startVoiceRecording();
|
|
21898
|
+
commandVoice.classList.add("recording");
|
|
21899
|
+
commandVoice.title = "Recording\u2026 Click again to stop";
|
|
21900
|
+
showActivity("Listening\u2026 speak now", "#ea4335");
|
|
21901
|
+
} catch (err) {
|
|
21902
|
+
showActivity(err?.message || "Microphone access denied", "#f28b82");
|
|
21903
|
+
}
|
|
21904
|
+
}
|
|
21905
|
+
});
|
|
21906
|
+
commandInput.addEventListener("keydown", (event) => {
|
|
21907
|
+
if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
|
|
21908
|
+
event.preventDefault();
|
|
21909
|
+
handleSubmit();
|
|
21910
|
+
}
|
|
21911
|
+
});
|
|
21912
|
+
commandSubmit.addEventListener("click", (event) => {
|
|
21913
|
+
event.preventDefault();
|
|
21914
|
+
event.stopPropagation();
|
|
21915
|
+
handleSubmit();
|
|
21916
|
+
});
|
|
21917
|
+
commandInput.addEventListener("input", () => {
|
|
21918
|
+
if (commandInput) autoResizeTextarea(commandInput);
|
|
21919
|
+
});
|
|
21920
|
+
commandInput.addEventListener("keydown", (event) => {
|
|
21921
|
+
if (event.key === "Escape") {
|
|
21922
|
+
event.preventDefault();
|
|
21923
|
+
closeCommandBar();
|
|
21924
|
+
}
|
|
21925
|
+
});
|
|
21926
|
+
}
|
|
21927
|
+
function autoResizeTextarea(textarea) {
|
|
21928
|
+
textarea.style.height = "auto";
|
|
21929
|
+
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
|
21930
|
+
}
|
|
21931
|
+
function openCommandBar() {
|
|
21932
|
+
if (!commandBarEl) return;
|
|
21933
|
+
commandBarEl.hidden = false;
|
|
21934
|
+
isOneShotMode = true;
|
|
21935
|
+
if (commandInput) {
|
|
21936
|
+
commandInput.value = "";
|
|
21937
|
+
commandInput.focus();
|
|
21938
|
+
autoResizeTextarea(commandInput);
|
|
21939
|
+
}
|
|
21940
|
+
if (commandModelIcon && commandModelLabel && state.selectedModel) {
|
|
21941
|
+
commandModelIcon.innerHTML = providerIcon(state.selectedModel.provider, true);
|
|
21942
|
+
commandModelLabel.textContent = state.selectedModel.label;
|
|
21943
|
+
}
|
|
21944
|
+
populateModelMenu();
|
|
21945
|
+
}
|
|
21946
|
+
function closeCommandBar() {
|
|
21947
|
+
if (!commandBarEl) return;
|
|
21948
|
+
commandBarEl.hidden = true;
|
|
21949
|
+
isOneShotMode = false;
|
|
21950
|
+
if (commandInput) {
|
|
21951
|
+
commandInput.value = "";
|
|
21952
|
+
}
|
|
21953
|
+
}
|
|
21954
|
+
function isCommandBarOpen() {
|
|
21955
|
+
return isOneShotMode;
|
|
21956
|
+
}
|
|
21957
|
+
function populateModelMenu() {
|
|
21958
|
+
if (!commandModelMenu) return;
|
|
21959
|
+
commandModelMenu.innerHTML = "";
|
|
21960
|
+
const providers = ["all", ...Array.from(new Set(state.MODELS.map((m) => m.provider)))];
|
|
21961
|
+
for (const provider of providers) {
|
|
21962
|
+
const section = document.createElement("div");
|
|
21963
|
+
section.className = "lasso-command-model-section";
|
|
21964
|
+
if (provider !== "all") {
|
|
21965
|
+
const header = document.createElement("div");
|
|
21966
|
+
header.className = "lasso-command-model-section-header";
|
|
21967
|
+
header.textContent = provider === "anthropic" ? "Anthropic" : provider === "openai" ? "OpenAI" : provider === "google" ? "Google" : provider === "ollama" ? "Ollama" : provider === "cli" ? "Local Agents" : provider;
|
|
21968
|
+
section.appendChild(header);
|
|
21969
|
+
}
|
|
21970
|
+
const models = provider === "all" ? state.MODELS : state.MODELS.filter((m) => m.provider === provider);
|
|
21971
|
+
for (const model of models) {
|
|
21972
|
+
const item = document.createElement("button");
|
|
21973
|
+
item.type = "button";
|
|
21974
|
+
item.className = "lasso-command-model-item";
|
|
21975
|
+
item.dataset.model = model.id;
|
|
21976
|
+
item.innerHTML = `${providerIcon(model.provider)}<span>${model.label}</span>`;
|
|
21977
|
+
if (model.id === state.selectedModel.id) {
|
|
21978
|
+
item.classList.add("selected");
|
|
21979
|
+
}
|
|
21980
|
+
section.appendChild(item);
|
|
21981
|
+
}
|
|
21982
|
+
commandModelMenu.appendChild(section);
|
|
21983
|
+
}
|
|
21984
|
+
}
|
|
21985
|
+
async function handleSubmit() {
|
|
21986
|
+
if (!commandInput) return;
|
|
21987
|
+
const prompt = commandInput.value.trim();
|
|
21988
|
+
if (!prompt) return;
|
|
21989
|
+
closeCommandBar();
|
|
21990
|
+
if (state.bridgeSocket?.readyState === WebSocket.OPEN) {
|
|
21991
|
+
state.bridgeSocket.send(JSON.stringify({
|
|
21992
|
+
type: "oneshot",
|
|
21993
|
+
prompt,
|
|
21994
|
+
scope: "project",
|
|
21995
|
+
model: state.selectedModel.id,
|
|
21996
|
+
provider: state.selectedModel.provider === "cli" ? "cli" : void 0
|
|
21997
|
+
}));
|
|
21998
|
+
}
|
|
21999
|
+
}
|
|
22000
|
+
|
|
22001
|
+
// src/overlay/toolbar/toolbar.ts
|
|
22002
|
+
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>`;
|
|
22003
|
+
var COMMENT_CURSOR_URL = `url("data:image/svg+xml,${encodeURIComponent(COMMENT_CURSOR_SVG)}") 4 2, crosshair`;
|
|
22004
|
+
var COMMENT_CURSOR_STYLE_ID = "lasso-comment-cursor-style";
|
|
22005
|
+
function setCommentCursor(active) {
|
|
22006
|
+
let style = document.getElementById(COMMENT_CURSOR_STYLE_ID);
|
|
22007
|
+
if (active) {
|
|
22008
|
+
if (!style) {
|
|
22009
|
+
style = document.createElement("style");
|
|
22010
|
+
style.id = COMMENT_CURSOR_STYLE_ID;
|
|
22011
|
+
document.head.appendChild(style);
|
|
22012
|
+
}
|
|
22013
|
+
style.textContent = `html.lasso-comment-mode, html.lasso-comment-mode * { cursor: ${COMMENT_CURSOR_URL} !important; }`;
|
|
22014
|
+
document.documentElement.classList.add("lasso-comment-mode");
|
|
22015
|
+
document.documentElement.style.setProperty("cursor", COMMENT_CURSOR_URL, "important");
|
|
22016
|
+
document.body.style.setProperty("cursor", COMMENT_CURSOR_URL, "important");
|
|
22017
|
+
return;
|
|
22018
|
+
}
|
|
22019
|
+
document.documentElement.classList.remove("lasso-comment-mode");
|
|
22020
|
+
document.documentElement.style.removeProperty("cursor");
|
|
22021
|
+
document.body.style.removeProperty("cursor");
|
|
22022
|
+
style?.remove();
|
|
22023
|
+
}
|
|
22024
|
+
function setCommentMode(active) {
|
|
22025
|
+
state.commentMode = active;
|
|
22026
|
+
if (active) state.previewMode = false;
|
|
22027
|
+
const dom = getDOM();
|
|
22028
|
+
const commentBtn = dom.shadow.querySelector(".comment-tool");
|
|
22029
|
+
const previewBtn = dom.shadow.querySelector(".preview-tool");
|
|
22030
|
+
if (commentBtn) commentBtn.classList.toggle("active", active);
|
|
22031
|
+
if (previewBtn) previewBtn.classList.toggle("active", state.previewMode);
|
|
22032
|
+
if (active) {
|
|
22033
|
+
setSelectMode(false);
|
|
22034
|
+
setDragMode(false);
|
|
22035
|
+
setCommentCursor(true);
|
|
22036
|
+
} else {
|
|
22037
|
+
setCommentCursor(false);
|
|
22038
|
+
if (state.selectMode) {
|
|
22039
|
+
document.documentElement.style.cursor = "default";
|
|
22040
|
+
}
|
|
22041
|
+
}
|
|
22042
|
+
}
|
|
22043
|
+
function buildToolbar() {
|
|
22044
|
+
const dom = getDOM();
|
|
22045
|
+
const toolbar = document.createElement("div");
|
|
22046
|
+
toolbar.className = "lasso-toolbar";
|
|
22047
|
+
toolbar.innerHTML = `
|
|
22048
|
+
<button class="lasso-tool-btn select-tool" type="button" aria-label="Select element" title="Select">
|
|
22049
|
+
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
22050
|
+
<path d="M4 4l7.07 17 2.51-7.39L21 11.07 4 4z"/>
|
|
22051
|
+
</svg>
|
|
22052
|
+
<span class="lasso-tool-label">Select</span>
|
|
22053
|
+
</button>
|
|
21696
22054
|
|
|
21697
22055
|
<button class="lasso-tool-btn drag-tool" type="button" aria-label="Drag element to reposition" title="Drag to Reposition">
|
|
21698
22056
|
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
@@ -21767,6 +22125,23 @@
|
|
|
21767
22125
|
</svg>
|
|
21768
22126
|
</button>
|
|
21769
22127
|
|
|
22128
|
+
<button class="lasso-tool-btn command-tool" type="button" aria-label="Command bar" title="Command bar (\u2318K)">
|
|
22129
|
+
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
22130
|
+
<path d="M12 2v20M2 12h20"/>
|
|
22131
|
+
<circle cx="12" cy="12" r="9"/>
|
|
22132
|
+
</svg>
|
|
22133
|
+
<span class="lasso-tool-label">Command</span>
|
|
22134
|
+
</button>
|
|
22135
|
+
|
|
22136
|
+
<button class="lasso-tool-btn page-tool" type="button" aria-label="Create a new page" title="New page">
|
|
22137
|
+
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
22138
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
22139
|
+
<path d="M14 2v6h6"/>
|
|
22140
|
+
<path d="M12 12v6M9 15h6"/>
|
|
22141
|
+
</svg>
|
|
22142
|
+
<span class="lasso-tool-label">New Page</span>
|
|
22143
|
+
</button>
|
|
22144
|
+
|
|
21770
22145
|
<div class="lasso-presence" style="display: none;">
|
|
21771
22146
|
<div class="lasso-presence-avatars"></div>
|
|
21772
22147
|
<span class="lasso-presence-count"></span>
|
|
@@ -21813,16 +22188,7 @@
|
|
|
21813
22188
|
`;
|
|
21814
22189
|
const miniToolbar = document.createElement("div");
|
|
21815
22190
|
miniToolbar.className = "lasso-toolbar-mini";
|
|
21816
|
-
miniToolbar.
|
|
21817
|
-
<button class="lasso-new-page-btn" type="button" aria-label="Create a new page" title="New page">
|
|
21818
|
-
<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">
|
|
21819
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
21820
|
-
<path d="M14 2v6h6"/>
|
|
21821
|
-
<path d="M12 12v6M9 15h6"/>
|
|
21822
|
-
</svg>
|
|
21823
|
-
<span>New Page</span>
|
|
21824
|
-
</button>
|
|
21825
|
-
`;
|
|
22191
|
+
miniToolbar.style.display = "none";
|
|
21826
22192
|
dom.shadow.append(toolbar, miniToolbar, toolbarReopen, voiceBar);
|
|
21827
22193
|
const tooltip = document.createElement("div");
|
|
21828
22194
|
tooltip.className = "lasso-toolbar-tooltip";
|
|
@@ -21854,13 +22220,6 @@
|
|
|
21854
22220
|
target.addEventListener("focusin", () => showTooltip(target));
|
|
21855
22221
|
target.addEventListener("focusout", () => hideTooltip(target));
|
|
21856
22222
|
});
|
|
21857
|
-
miniToolbar.querySelectorAll("[title]").forEach((target) => {
|
|
21858
|
-
target.dataset.tooltip = target.getAttribute("title") || "";
|
|
21859
|
-
target.addEventListener("pointerenter", () => showTooltip(target));
|
|
21860
|
-
target.addEventListener("pointerleave", () => hideTooltip(target));
|
|
21861
|
-
target.addEventListener("focusin", () => showTooltip(target));
|
|
21862
|
-
target.addEventListener("focusout", () => hideTooltip(target));
|
|
21863
|
-
});
|
|
21864
22223
|
const selectBtn = toolbar.querySelector(".select-tool");
|
|
21865
22224
|
const dragBtn = toolbar.querySelector(".drag-tool");
|
|
21866
22225
|
const previewBtn = toolbar.querySelector(".preview-tool");
|
|
@@ -21871,9 +22230,10 @@
|
|
|
21871
22230
|
const notepadBtn = toolbar.querySelector(".notepad-tool");
|
|
21872
22231
|
const clipboardBtn = toolbar.querySelector(".clipboard-tool");
|
|
21873
22232
|
const voiceBtn = toolbar.querySelector(".voice-tool");
|
|
22233
|
+
const commandBtn = toolbar.querySelector(".command-tool");
|
|
22234
|
+
const pageBtn = toolbar.querySelector(".page-tool");
|
|
21874
22235
|
const dismissBtn = toolbar.querySelector(".lasso-toolbar-dismiss");
|
|
21875
|
-
|
|
21876
|
-
newPageBtn.addEventListener("click", (event) => {
|
|
22236
|
+
pageBtn.addEventListener("click", (event) => {
|
|
21877
22237
|
event.preventDefault();
|
|
21878
22238
|
event.stopPropagation();
|
|
21879
22239
|
togglePagePanel();
|
|
@@ -21934,6 +22294,11 @@
|
|
|
21934
22294
|
e.preventDefault();
|
|
21935
22295
|
if (state.voiceOn) setVoiceMuted(!state.voiceMuted);
|
|
21936
22296
|
});
|
|
22297
|
+
commandBtn.addEventListener("click", (event) => {
|
|
22298
|
+
event.preventDefault();
|
|
22299
|
+
event.stopPropagation();
|
|
22300
|
+
openCommandBar();
|
|
22301
|
+
});
|
|
21937
22302
|
dismissBtn.addEventListener("click", () => {
|
|
21938
22303
|
toolbar.classList.add("dismissed");
|
|
21939
22304
|
miniToolbar.classList.add("dismissed");
|
|
@@ -21953,190 +22318,6 @@
|
|
|
21953
22318
|
return { toolbar, voiceBar };
|
|
21954
22319
|
}
|
|
21955
22320
|
|
|
21956
|
-
// src/overlay/commandbar/commandbar.ts
|
|
21957
|
-
var commandBarEl = null;
|
|
21958
|
-
var commandInput = null;
|
|
21959
|
-
var commandBackdrop = null;
|
|
21960
|
-
var commandSubmit = null;
|
|
21961
|
-
var commandVoice = null;
|
|
21962
|
-
var commandClose = null;
|
|
21963
|
-
var isOpen = false;
|
|
21964
|
-
function buildCommandBar() {
|
|
21965
|
-
const dom = getDOM();
|
|
21966
|
-
const backdrop = document.createElement("div");
|
|
21967
|
-
backdrop.className = "lasso-command-backdrop";
|
|
21968
|
-
backdrop.hidden = true;
|
|
21969
|
-
backdrop.innerHTML = ``;
|
|
21970
|
-
dom.shadow.appendChild(backdrop);
|
|
21971
|
-
commandBackdrop = backdrop;
|
|
21972
|
-
const el = document.createElement("div");
|
|
21973
|
-
el.className = "lasso-command-bar";
|
|
21974
|
-
el.hidden = true;
|
|
21975
|
-
el.innerHTML = `
|
|
21976
|
-
<div class="lasso-command-card">
|
|
21977
|
-
<div class="lasso-command-header">
|
|
21978
|
-
<div class="lasso-command-brand">
|
|
21979
|
-
<img class="lasso-command-brand-logo" src="${LASSO_ICON_DATA_URL}" alt="Lasso" />
|
|
21980
|
-
<span class="lasso-command-brand-title">What do you want to build?</span>
|
|
21981
|
-
</div>
|
|
21982
|
-
<button class="lasso-command-close" type="button" aria-label="Close">
|
|
21983
|
-
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
21984
|
-
<path d="M18 6L6 18M6 6l12 12"/>
|
|
21985
|
-
</svg>
|
|
21986
|
-
</button>
|
|
21987
|
-
</div>
|
|
21988
|
-
|
|
21989
|
-
<div class="lasso-command-body">
|
|
21990
|
-
<textarea
|
|
21991
|
-
class="lasso-command-input"
|
|
21992
|
-
placeholder="Describe what you want to build... Examples: \u2022 Build a settings page with profile, notifications and security sections \u2022 Add authentication with login and signup \u2022 Create a dashboard with customer table and analytics"
|
|
21993
|
-
rows="3"
|
|
21994
|
-
></textarea>
|
|
21995
|
-
|
|
21996
|
-
<div class="lasso-command-actions">
|
|
21997
|
-
<div class="lasso-command-icon-group">
|
|
21998
|
-
<button class="lasso-command-voice" type="button" aria-label="Voice input" title="Voice input (speech-to-text)">
|
|
21999
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
|
22000
|
-
<rect x="9" y="3" width="6" height="11" rx="3"/>
|
|
22001
|
-
<path d="M5 11a7 7 0 0 0 14 0M12 18v3M8 21h8"/>
|
|
22002
|
-
</svg>
|
|
22003
|
-
</button>
|
|
22004
|
-
</div>
|
|
22005
|
-
|
|
22006
|
-
<button class="lasso-command-submit primary" type="button" aria-label="Build">
|
|
22007
|
-
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
22008
|
-
<path d="M5 12h14M12 5l7 7-7 7"/>
|
|
22009
|
-
</svg>
|
|
22010
|
-
<span>Build</span>
|
|
22011
|
-
</button>
|
|
22012
|
-
</div>
|
|
22013
|
-
|
|
22014
|
-
<div class="lasso-command-shortcuts">
|
|
22015
|
-
<span class="lasso-command-shortcut">
|
|
22016
|
-
<kbd>\u2318</kbd><kbd>K</kbd>
|
|
22017
|
-
<span>Open command bar</span>
|
|
22018
|
-
</span>
|
|
22019
|
-
<span class="lasso-command-shortcut">
|
|
22020
|
-
<kbd>\u2318</kbd><kbd>\u21B5</kbd>
|
|
22021
|
-
<span>Submit</span>
|
|
22022
|
-
</span>
|
|
22023
|
-
<span class="lasso-command-shortcut">
|
|
22024
|
-
<kbd>Esc</kbd>
|
|
22025
|
-
<span>Close</span>
|
|
22026
|
-
</span>
|
|
22027
|
-
</div>
|
|
22028
|
-
</div>
|
|
22029
|
-
</div>
|
|
22030
|
-
`;
|
|
22031
|
-
dom.shadow.appendChild(el);
|
|
22032
|
-
commandBarEl = el;
|
|
22033
|
-
commandInput = el.querySelector(".lasso-command-input");
|
|
22034
|
-
commandSubmit = el.querySelector(".lasso-command-submit");
|
|
22035
|
-
commandVoice = el.querySelector(".lasso-command-voice");
|
|
22036
|
-
commandClose = el.querySelector(".lasso-command-close");
|
|
22037
|
-
backdrop.addEventListener("click", closeCommandBar);
|
|
22038
|
-
commandClose.addEventListener("click", (event) => {
|
|
22039
|
-
event.preventDefault();
|
|
22040
|
-
event.stopPropagation();
|
|
22041
|
-
closeCommandBar();
|
|
22042
|
-
});
|
|
22043
|
-
commandVoice.addEventListener("click", async (event) => {
|
|
22044
|
-
event.preventDefault();
|
|
22045
|
-
event.stopPropagation();
|
|
22046
|
-
if (isRecordingVoice()) {
|
|
22047
|
-
commandVoice.classList.remove("recording");
|
|
22048
|
-
commandVoice.classList.add("transcribing");
|
|
22049
|
-
commandVoice.title = "Transcribing\u2026";
|
|
22050
|
-
try {
|
|
22051
|
-
const result = await stopVoiceRecording();
|
|
22052
|
-
if (result.text && commandInput) {
|
|
22053
|
-
const prev = commandInput.value.trim();
|
|
22054
|
-
commandInput.value = prev ? `${prev} ${result.text}` : result.text;
|
|
22055
|
-
commandInput.focus();
|
|
22056
|
-
autoResizeTextarea(commandInput);
|
|
22057
|
-
showActivity("Transcribed", "#81c995");
|
|
22058
|
-
} else {
|
|
22059
|
-
showActivity("No speech detected.", "#fdd663");
|
|
22060
|
-
}
|
|
22061
|
-
} catch (err) {
|
|
22062
|
-
showActivity(err?.message || "Transcription failed", "#f28b82");
|
|
22063
|
-
} finally {
|
|
22064
|
-
commandVoice.classList.remove("transcribing");
|
|
22065
|
-
commandVoice.title = "Voice input";
|
|
22066
|
-
}
|
|
22067
|
-
} else {
|
|
22068
|
-
try {
|
|
22069
|
-
await startVoiceRecording();
|
|
22070
|
-
commandVoice.classList.add("recording");
|
|
22071
|
-
commandVoice.title = "Recording\u2026 Click again to stop";
|
|
22072
|
-
showActivity("Listening\u2026 speak now", "#ea4335");
|
|
22073
|
-
} catch (err) {
|
|
22074
|
-
showActivity(err?.message || "Microphone access denied", "#f28b82");
|
|
22075
|
-
}
|
|
22076
|
-
}
|
|
22077
|
-
});
|
|
22078
|
-
commandInput.addEventListener("keydown", (event) => {
|
|
22079
|
-
if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
|
|
22080
|
-
event.preventDefault();
|
|
22081
|
-
handleSubmit();
|
|
22082
|
-
}
|
|
22083
|
-
});
|
|
22084
|
-
commandSubmit.addEventListener("click", (event) => {
|
|
22085
|
-
event.preventDefault();
|
|
22086
|
-
event.stopPropagation();
|
|
22087
|
-
handleSubmit();
|
|
22088
|
-
});
|
|
22089
|
-
commandInput.addEventListener("input", () => {
|
|
22090
|
-
if (commandInput) autoResizeTextarea(commandInput);
|
|
22091
|
-
});
|
|
22092
|
-
commandInput.addEventListener("keydown", (event) => {
|
|
22093
|
-
if (event.key === "Escape") {
|
|
22094
|
-
event.preventDefault();
|
|
22095
|
-
closeCommandBar();
|
|
22096
|
-
}
|
|
22097
|
-
});
|
|
22098
|
-
}
|
|
22099
|
-
function autoResizeTextarea(textarea) {
|
|
22100
|
-
textarea.style.height = "auto";
|
|
22101
|
-
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
|
22102
|
-
}
|
|
22103
|
-
function openCommandBar() {
|
|
22104
|
-
if (!commandBarEl || !commandBackdrop) return;
|
|
22105
|
-
commandBarEl.hidden = false;
|
|
22106
|
-
commandBackdrop.hidden = false;
|
|
22107
|
-
isOpen = true;
|
|
22108
|
-
if (commandInput) {
|
|
22109
|
-
commandInput.value = "";
|
|
22110
|
-
commandInput.focus();
|
|
22111
|
-
autoResizeTextarea(commandInput);
|
|
22112
|
-
}
|
|
22113
|
-
}
|
|
22114
|
-
function closeCommandBar() {
|
|
22115
|
-
if (!commandBarEl || !commandBackdrop) return;
|
|
22116
|
-
commandBarEl.hidden = true;
|
|
22117
|
-
commandBackdrop.hidden = true;
|
|
22118
|
-
isOpen = false;
|
|
22119
|
-
if (commandInput) {
|
|
22120
|
-
commandInput.value = "";
|
|
22121
|
-
}
|
|
22122
|
-
}
|
|
22123
|
-
function isCommandBarOpen() {
|
|
22124
|
-
return isOpen;
|
|
22125
|
-
}
|
|
22126
|
-
async function handleSubmit() {
|
|
22127
|
-
if (!commandInput) return;
|
|
22128
|
-
const prompt = commandInput.value.trim();
|
|
22129
|
-
if (!prompt) return;
|
|
22130
|
-
closeCommandBar();
|
|
22131
|
-
if (state.bridgeSocket?.readyState === WebSocket.OPEN) {
|
|
22132
|
-
state.bridgeSocket.send(JSON.stringify({
|
|
22133
|
-
type: "oneshot",
|
|
22134
|
-
prompt,
|
|
22135
|
-
scope: "project"
|
|
22136
|
-
}));
|
|
22137
|
-
}
|
|
22138
|
-
}
|
|
22139
|
-
|
|
22140
22321
|
// src/overlay/index.ts
|
|
22141
22322
|
console.log("[lasso] overlay initializing");
|
|
22142
22323
|
function init() {
|