@lasso-ai/cli 1.1.5 → 1.2.0

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
@@ -11078,6 +11078,252 @@
11078
11078
  .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; }
11079
11079
  .lasso-agent-prompt-actions button:hover { filter: brightness(1.12); }
11080
11080
  .lasso-agent-prompt-actions button:active { transform: scale(0.97); }
11081
+
11082
+ /* ==========================================================
11083
+ COMMAND BAR (One-Shot Build Mode)
11084
+ ========================================================== */
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 {
11101
+ 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);
11121
+ display: flex;
11122
+ flex-direction: column;
11123
+ padding: 20px;
11124
+ border: 1px solid var(--lo-border);
11125
+ border-radius: var(--lo-radius-xl);
11126
+ background: rgba(24, 25, 29, 0.98);
11127
+ backdrop-filter: blur(24px);
11128
+ -webkit-backdrop-filter: blur(24px);
11129
+ color: var(--lo-text);
11130
+ box-shadow: 0 24px 56px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.08);
11131
+ pointer-events: auto;
11132
+ animation: lasso-command-in 200ms cubic-bezier(0.16, 1, 0.3, 1);
11133
+ }
11134
+
11135
+ @keyframes lasso-command-in {
11136
+ from {
11137
+ opacity: 0;
11138
+ transform: translateY(12px) scale(0.98);
11139
+ }
11140
+ to {
11141
+ opacity: 1;
11142
+ transform: none;
11143
+ }
11144
+ }
11145
+
11146
+ .lasso-command-header {
11147
+ display: flex;
11148
+ align-items: center;
11149
+ justify-content: space-between;
11150
+ margin-bottom: 16px;
11151
+ }
11152
+
11153
+ .lasso-command-brand {
11154
+ display: flex;
11155
+ align-items: center;
11156
+ gap: 10px;
11157
+ }
11158
+
11159
+ .lasso-command-brand-logo {
11160
+ width: 28px;
11161
+ height: 28px;
11162
+ }
11163
+
11164
+ .lasso-command-brand-title {
11165
+ font-size: 15px;
11166
+ font-weight: 600;
11167
+ letter-spacing: -0.01em;
11168
+ }
11169
+
11170
+ .lasso-command-close {
11171
+ width: 28px;
11172
+ height: 28px;
11173
+ display: flex;
11174
+ align-items: center;
11175
+ justify-content: center;
11176
+ border: 0;
11177
+ border-radius: var(--lo-radius-md);
11178
+ background: transparent;
11179
+ color: var(--lo-text-3);
11180
+ cursor: pointer;
11181
+ transition: background 120ms ease, color 120ms ease;
11182
+ }
11183
+
11184
+ .lasso-command-close:hover {
11185
+ background: var(--lo-surface-hover);
11186
+ color: var(--lo-text);
11187
+ }
11188
+
11189
+ .lasso-command-body {
11190
+ display: flex;
11191
+ flex-direction: column;
11192
+ gap: 12px;
11193
+ }
11194
+
11195
+ .lasso-command-input {
11196
+ width: 100%;
11197
+ min-height: 80px;
11198
+ padding: 12px 14px;
11199
+ border: 1px solid var(--lo-border);
11200
+ border-radius: var(--lo-radius-lg);
11201
+ background: var(--lo-surface-2);
11202
+ color: var(--lo-text);
11203
+ font-family: inherit;
11204
+ font-size: 13px;
11205
+ line-height: 1.5;
11206
+ resize: none;
11207
+ outline: none;
11208
+ transition: border-color 140ms ease, box-shadow 140ms ease;
11209
+ }
11210
+
11211
+ .lasso-command-input:focus {
11212
+ border-color: var(--lo-primary);
11213
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--lo-primary) 16%, transparent);
11214
+ }
11215
+
11216
+ .lasso-command-input::placeholder {
11217
+ color: var(--lo-text-3);
11218
+ }
11219
+
11220
+ .lasso-command-actions {
11221
+ display: flex;
11222
+ align-items: center;
11223
+ justify-content: space-between;
11224
+ gap: 10px;
11225
+ }
11226
+
11227
+ .lasso-command-icon-group {
11228
+ display: flex;
11229
+ align-items: center;
11230
+ gap: 6px;
11231
+ }
11232
+
11233
+ .lasso-command-voice {
11234
+ width: 32px;
11235
+ height: 32px;
11236
+ display: flex;
11237
+ align-items: center;
11238
+ justify-content: center;
11239
+ border: 0;
11240
+ border-radius: var(--lo-radius-md);
11241
+ background: transparent;
11242
+ color: var(--lo-text-3);
11243
+ cursor: pointer;
11244
+ transition: background 120ms ease, color 120ms ease;
11245
+ }
11246
+
11247
+ .lasso-command-voice:hover {
11248
+ background: var(--lo-surface-hover);
11249
+ color: var(--lo-text);
11250
+ }
11251
+
11252
+ .lasso-command-voice.recording {
11253
+ color: #ea4335 !important;
11254
+ background: rgba(234, 67, 53, 0.16) !important;
11255
+ border: 1px solid rgba(234, 67, 53, 0.45) !important;
11256
+ animation: lasso-pulse-recording 1.2s infinite ease-in-out;
11257
+ }
11258
+
11259
+ .lasso-command-voice.transcribing {
11260
+ color: #fbbc04 !important;
11261
+ background: rgba(251, 188, 4, 0.16) !important;
11262
+ border: 1px solid rgba(251, 188, 4, 0.45) !important;
11263
+ animation: lasso-pulse-transcribing 0.9s infinite alternate ease-in-out;
11264
+ }
11265
+
11266
+ .lasso-command-submit {
11267
+ height: 36px;
11268
+ display: flex;
11269
+ align-items: center;
11270
+ justify-content: center;
11271
+ gap: 8px;
11272
+ padding: 0 20px;
11273
+ border: 0;
11274
+ border-radius: var(--lo-radius-full);
11275
+ background: var(--lo-primary);
11276
+ color: #111214;
11277
+ font-family: inherit;
11278
+ font-size: 13px;
11279
+ font-weight: 600;
11280
+ cursor: pointer;
11281
+ transition: all 140ms ease;
11282
+ }
11283
+
11284
+ .lasso-command-submit:hover {
11285
+ background: var(--lo-primary-hover);
11286
+ transform: translateY(-1px);
11287
+ }
11288
+
11289
+ .lasso-command-submit:active {
11290
+ transform: scale(0.96);
11291
+ }
11292
+
11293
+ .lasso-command-submit.primary {
11294
+ background: var(--lo-primary);
11295
+ }
11296
+
11297
+ .lasso-command-shortcuts {
11298
+ display: flex;
11299
+ align-items: center;
11300
+ gap: 16px;
11301
+ padding-top: 8px;
11302
+ border-top: 1px solid var(--lo-border-subtle);
11303
+ }
11304
+
11305
+ .lasso-command-shortcut {
11306
+ display: flex;
11307
+ align-items: center;
11308
+ gap: 6px;
11309
+ color: var(--lo-text-3);
11310
+ font-size: 11px;
11311
+ }
11312
+
11313
+ .lasso-command-shortcut kbd {
11314
+ display: inline-flex;
11315
+ align-items: center;
11316
+ justify-content: center;
11317
+ min-width: 20px;
11318
+ height: 20px;
11319
+ padding: 0 5px;
11320
+ border: 1px solid var(--lo-border-subtle);
11321
+ border-radius: 4px;
11322
+ background: var(--lo-surface-2);
11323
+ font-family: var(--lo-font-mono);
11324
+ font-size: 10px;
11325
+ font-weight: 500;
11326
+ }
11081
11327
  .lasso-agent-prompt-actions button.primary { background: var(--lo-primary); color: #111214; font-weight: 600; }
11082
11328
 
11083
11329
  .lasso-todo-header {
@@ -17132,8 +17378,8 @@
17132
17378
  const pin = document.createElement("button");
17133
17379
  pin.type = "button";
17134
17380
  const isResolved = thread.root.status === "RESOLVED";
17135
- const isOpen = state.openThreadUid === thread.root.uid;
17136
- pin.className = `lasso-comment-pin${isResolved ? " resolved" : ""}${isOpen ? " active" : ""}`;
17381
+ const isOpen2 = state.openThreadUid === thread.root.uid;
17382
+ pin.className = `lasso-comment-pin${isResolved ? " resolved" : ""}${isOpen2 ? " active" : ""}`;
17137
17383
  pin.dataset.commentUid = thread.root.uid;
17138
17384
  const authorColor = userNameColor(thread.root.author?.id || "");
17139
17385
  const authorInitials = initials(thread.root.author?.name || "");
@@ -21707,6 +21953,190 @@
21707
21953
  return { toolbar, voiceBar };
21708
21954
  }
21709
21955
 
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
+
21710
22140
  // src/overlay/index.ts
21711
22141
  console.log("[lasso] overlay initializing");
21712
22142
  function init() {
@@ -21726,6 +22156,7 @@
21726
22156
  buildPagePanel();
21727
22157
  buildPrompt();
21728
22158
  buildDrag();
22159
+ buildCommandBar();
21729
22160
  initErrorListeners();
21730
22161
  connectBridge();
21731
22162
  initCollabPagehide();
@@ -21788,7 +22219,21 @@
21788
22219
  true
21789
22220
  );
21790
22221
  document.addEventListener("keydown", (event) => {
22222
+ if ((event.metaKey || event.ctrlKey) && event.key === "k") {
22223
+ event.preventDefault();
22224
+ event.stopPropagation();
22225
+ if (isCommandBarOpen()) {
22226
+ closeCommandBar();
22227
+ } else {
22228
+ openCommandBar();
22229
+ }
22230
+ return;
22231
+ }
21791
22232
  if (event.key !== "Escape") return;
22233
+ if (isCommandBarOpen()) {
22234
+ closeCommandBar();
22235
+ return;
22236
+ }
21792
22237
  if (isPinComposeOpen()) {
21793
22238
  closePinCompose();
21794
22239
  setCommentMode(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lasso-ai/cli",
3
- "version": "1.1.5",
3
+ "version": "1.2.0",
4
4
  "description": "Select any part of your running app, describe a change, and let AI edit the real source code.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/cli/index.js",
@@ -81,6 +81,7 @@
81
81
  "commander": "^15.0.0",
82
82
  "http-proxy": "^1.18.1",
83
83
  "open": "^11.0.4",
84
+ "prompts": "^2.4.2",
84
85
  "socket.io-client": "^4.8.3",
85
86
  "vite": "^7.0.0",
86
87
  "ws": "^8.21.3"
@@ -96,6 +97,7 @@
96
97
  "devDependencies": {
97
98
  "@types/http-proxy": "^1.17.17",
98
99
  "@types/node": "^26.6.1",
100
+ "@types/prompts": "^2.4.9",
99
101
  "@types/ws": "^8.5.13",
100
102
  "esbuild": "^0.24.0",
101
103
  "html2canvas": "^1.4.1",