@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/dist/overlay.js CHANGED
@@ -8093,41 +8093,8 @@
8093
8093
  }
8094
8094
 
8095
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;
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 BAR (One-Shot Build Mode)
11083
+ COMMAND SIDEBAR (One-Shot Build Mode)
11084
11084
  ========================================================== */
11085
11085
 
11086
- .lasso-command-backdrop {
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: 0;
11103
- left: 0;
11104
- right: 0;
11105
- bottom: 0;
11106
- z-index: 101;
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: 20px;
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: translateY(12px) scale(0.98);
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
- margin-bottom: 16px;
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: 28px;
11161
- height: 28px;
11138
+ width: 24px;
11139
+ height: 24px;
11162
11140
  }
11163
11141
 
11164
11142
  .lasso-command-brand-title {
11165
- font-size: 15px;
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 isOpen2 = state.openThreadUid === thread.root.uid;
17382
- pin.className = `lasso-comment-pin${isResolved ? " resolved" : ""}${isOpen2 ? " active" : ""}`;
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
- state.selectedModel = state.MODELS.find((m) => m.id === storedModelId()) || state.MODELS[0];
19023
- rememberModel(state.selectedModel);
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
- 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>`;
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/toolbar/toolbar.ts
21644
- 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>`;
21645
- var COMMENT_CURSOR_URL = `url("data:image/svg+xml,${encodeURIComponent(COMMENT_CURSOR_SVG)}") 4 2, crosshair`;
21646
- var COMMENT_CURSOR_STYLE_ID = "lasso-comment-cursor-style";
21647
- function setCommentCursor(active) {
21648
- let style = document.getElementById(COMMENT_CURSOR_STYLE_ID);
21649
- if (active) {
21650
- if (!style) {
21651
- style = document.createElement("style");
21652
- style.id = COMMENT_CURSOR_STYLE_ID;
21653
- document.head.appendChild(style);
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 toolbar = document.createElement("div");
21688
- toolbar.className = "lasso-toolbar";
21689
- toolbar.innerHTML = `
21690
- <button class="lasso-tool-btn select-tool" type="button" aria-label="Select element" title="Select">
21691
- <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">
21692
- <path d="M4 4l7.07 17 2.51-7.39L21 11.07 4 4z"/>
21693
- </svg>
21694
- <span class="lasso-tool-label">Select</span>
21695
- </button>
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...&#10;&#10;Examples:&#10;\u2022 Build a settings page with profile, notifications and security sections&#10;\u2022 Add authentication with login and signup&#10;\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.innerHTML = `
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
- const newPageBtn = miniToolbar.querySelector(".lasso-new-page-btn");
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...&#10;&#10;Examples:&#10;\u2022 Build a settings page with profile, notifications and security sections&#10;\u2022 Add authentication with login and signup&#10;\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() {