@lasso-ai/cli 1.0.26 → 1.0.28
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/cli/agent.js +1 -2
- package/dist/overlay.js +80 -16
- package/package.json +1 -1
package/dist/cli/agent.js
CHANGED
|
@@ -351,7 +351,7 @@ function localCommand(provider, model, prompt) {
|
|
|
351
351
|
return { command: "claude", args: ["-p", prompt || "", "--output-format", "stream-json", "--verbose", "--permission-mode", "plan", "--max-turns", "3", ...(selectedModel ? ["--model", selectedModel] : [])] };
|
|
352
352
|
}
|
|
353
353
|
if (provider === "opencode") {
|
|
354
|
-
return { command: "opencode", args: ["run", "--format", "json", "--
|
|
354
|
+
return { command: "opencode", args: ["run", "--format", "json", "--agent", "plan", ...(selectedModel ? ["--model", selectedModel] : []), prompt || ""] };
|
|
355
355
|
}
|
|
356
356
|
return { command: "codex", args: ["exec", "--json", "--sandbox", "read-only", "--skip-git-repo-check", ...(selectedModel ? ["--model", selectedModel] : []), prompt || ""] };
|
|
357
357
|
}
|
|
@@ -394,7 +394,6 @@ function runLocalCommand(cwd, command, args, provider, signal, onProgress) {
|
|
|
394
394
|
if (progress)
|
|
395
395
|
onProgress?.(progress.message, progress.detail);
|
|
396
396
|
else if (stream === "stderr" && line.trim()) {
|
|
397
|
-
onProgress?.(`${label} · ${snippet(line, 110)}`);
|
|
398
397
|
if (provider === "opencode" && /quota exceeded|authentication failed|invalid api key|unauthorized|forbidden/i.test(line)) {
|
|
399
398
|
onProgress?.("OpenCode · provider rejected the request; stopping this task…");
|
|
400
399
|
child.kill("SIGTERM");
|
package/dist/overlay.js
CHANGED
|
@@ -10916,6 +10916,9 @@
|
|
|
10916
10916
|
.lasso-task-badge { min-width: 18px; padding: 2px 5px; border-radius: 999px; background: var(--lo-indigo); color: #fff; font-size: 10px; text-align: center; }
|
|
10917
10917
|
.lasso-task-close, .lasso-task-back { border: 0; background: transparent; color: var(--lo-text-3); cursor: pointer; }
|
|
10918
10918
|
.lasso-task-close { font-size: 20px; line-height: 20px; }
|
|
10919
|
+
.lasso-task-tabs { display: flex; gap: 4px; margin: 10px 0 8px; padding: 3px; border-radius: var(--lo-radius-md); background: var(--lo-surface-2); }
|
|
10920
|
+
.lasso-task-tab { flex: 1; padding: 6px 8px; border: 0; border-radius: 7px; background: transparent; color: var(--lo-text-3); font: inherit; font-size: 11px; cursor: pointer; }
|
|
10921
|
+
.lasso-task-tab.active { background: var(--lo-surface); color: var(--lo-text); box-shadow: 0 1px 3px rgba(0,0,0,.16); }
|
|
10919
10922
|
.lasso-task-body { min-height: 90px; max-height: 470px; overflow: auto; }
|
|
10920
10923
|
.lasso-task-list { display: flex; flex-direction: column; gap: 3px; }
|
|
10921
10924
|
.lasso-task-row { width: 100%; display: flex; align-items: center; gap: 9px; padding: 9px; border: 0; border-radius: var(--lo-radius-md); background: transparent; color: var(--lo-text); text-align: left; cursor: pointer; }
|
|
@@ -10928,6 +10931,7 @@
|
|
|
10928
10931
|
.lasso-task-row-copy { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
|
|
10929
10932
|
.lasso-task-row-copy strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 500; }
|
|
10930
10933
|
.lasso-task-row-copy small, .lasso-task-message { color: var(--lo-text-3); font-size: 11px; }
|
|
10934
|
+
.lasso-task-review-label { margin-left: auto; padding: 4px 7px; border-radius: var(--lo-radius-full); background: color-mix(in srgb, #fbbf24 16%, transparent); color: #fbbf24; font-size: 10px; font-weight: 600; cursor: pointer; }
|
|
10931
10935
|
.lasso-task-empty { padding: 25px 10px; color: var(--lo-text-3); font-size: 12px; text-align: center; }
|
|
10932
10936
|
.lasso-task-detail { padding: 4px 2px; }
|
|
10933
10937
|
.lasso-task-detail-heading { justify-content: space-between; margin-bottom: 12px; }
|
|
@@ -12128,6 +12132,7 @@
|
|
|
12128
12132
|
var detail = null;
|
|
12129
12133
|
var badge = null;
|
|
12130
12134
|
var selectionListeners = /* @__PURE__ */ new Set();
|
|
12135
|
+
var reviewListeners = /* @__PURE__ */ new Set();
|
|
12131
12136
|
var statusLabel = {
|
|
12132
12137
|
queued: "Queued",
|
|
12133
12138
|
thinking: "Thinking",
|
|
@@ -12146,13 +12151,29 @@
|
|
|
12146
12151
|
return Boolean(other) && change.filePath === other.filePath && change.oldString === other.oldString && change.newString === other.newString;
|
|
12147
12152
|
});
|
|
12148
12153
|
}
|
|
12154
|
+
function normalizedInstruction(value2) {
|
|
12155
|
+
return value2.trim().replace(/\s+/g, " ").toLowerCase();
|
|
12156
|
+
}
|
|
12157
|
+
function findReusableAgentTask(instruction, element) {
|
|
12158
|
+
const normalized = normalizedInstruction(instruction);
|
|
12159
|
+
return state.agentTasks.find(
|
|
12160
|
+
(task) => task.status !== "complete" && task.status !== "error" && task.status !== "stopped" && normalizedInstruction(task.instruction) === normalized && task.element === (element || void 0)
|
|
12161
|
+
);
|
|
12162
|
+
}
|
|
12149
12163
|
function onAgentTaskSelected(listener) {
|
|
12150
12164
|
selectionListeners.add(listener);
|
|
12151
12165
|
return () => selectionListeners.delete(listener);
|
|
12152
12166
|
}
|
|
12167
|
+
function onAgentTaskReviewRequested(listener) {
|
|
12168
|
+
reviewListeners.add(listener);
|
|
12169
|
+
return () => reviewListeners.delete(listener);
|
|
12170
|
+
}
|
|
12153
12171
|
function notifyTaskSelection(task) {
|
|
12154
12172
|
for (const listener of selectionListeners) listener(task);
|
|
12155
12173
|
}
|
|
12174
|
+
function notifyTaskReviewRequested(task) {
|
|
12175
|
+
for (const listener of reviewListeners) listener(task);
|
|
12176
|
+
}
|
|
12156
12177
|
function createAgentTask(instruction, messages = state.chatHistory, changesHistory = state.changesHistory, element = state.selected, selectionId = state.selectionId) {
|
|
12157
12178
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12158
12179
|
const task = {
|
|
@@ -12222,6 +12243,12 @@
|
|
|
12222
12243
|
notifyTaskSelection(task || null);
|
|
12223
12244
|
renderTasks();
|
|
12224
12245
|
}
|
|
12246
|
+
function requestAgentTaskReview(id) {
|
|
12247
|
+
const task = getAgentTask(id);
|
|
12248
|
+
if (!task || task.status !== "review") return;
|
|
12249
|
+
selectAgentTask(task.id);
|
|
12250
|
+
notifyTaskReviewRequested(task);
|
|
12251
|
+
}
|
|
12225
12252
|
function toggleTaskPanel(force) {
|
|
12226
12253
|
if (!panel) return;
|
|
12227
12254
|
panel.hidden = force === void 0 ? !panel.hidden : !force;
|
|
@@ -12241,6 +12268,10 @@
|
|
|
12241
12268
|
</div>
|
|
12242
12269
|
<button class="lasso-task-close" type="button" aria-label="Close tasks">\xD7</button>
|
|
12243
12270
|
</div>
|
|
12271
|
+
<div class="lasso-task-tabs" role="tablist" aria-label="Task status">
|
|
12272
|
+
<button class="lasso-task-tab active" type="button" role="tab" data-task-tab="active" aria-selected="true">In progress</button>
|
|
12273
|
+
<button class="lasso-task-tab" type="button" role="tab" data-task-tab="complete" aria-selected="false">Completed</button>
|
|
12274
|
+
</div>
|
|
12244
12275
|
<div class="lasso-task-body">
|
|
12245
12276
|
<div class="lasso-task-list"></div>
|
|
12246
12277
|
<div class="lasso-task-detail" hidden></div>
|
|
@@ -12251,27 +12282,47 @@
|
|
|
12251
12282
|
detail = panel.querySelector(".lasso-task-detail");
|
|
12252
12283
|
badge = panel.querySelector(".lasso-task-badge");
|
|
12253
12284
|
panel.querySelector(".lasso-task-close").addEventListener("click", () => toggleTaskPanel(false));
|
|
12285
|
+
panel.querySelectorAll(".lasso-task-tab").forEach((tab) => {
|
|
12286
|
+
tab.addEventListener("click", () => {
|
|
12287
|
+
panel?.querySelectorAll(".lasso-task-tab").forEach((item) => {
|
|
12288
|
+
const active = item === tab;
|
|
12289
|
+
item.classList.toggle("active", active);
|
|
12290
|
+
item.setAttribute("aria-selected", String(active));
|
|
12291
|
+
});
|
|
12292
|
+
renderTasks();
|
|
12293
|
+
});
|
|
12294
|
+
});
|
|
12254
12295
|
renderTasks();
|
|
12255
12296
|
return panel;
|
|
12256
12297
|
}
|
|
12257
12298
|
function renderTasks() {
|
|
12258
|
-
|
|
12299
|
+
const panelEl = panel;
|
|
12300
|
+
if (!panelEl || !list || !detail || !badge) return;
|
|
12259
12301
|
const activeCount = state.agentTasks.filter((task) => task.status !== "complete" && task.status !== "error" && task.status !== "stopped").length;
|
|
12260
12302
|
badge.hidden = state.agentTasks.length === 0;
|
|
12261
12303
|
badge.textContent = String(activeCount || state.agentTasks.length);
|
|
12262
12304
|
const navBadge = getDOM().shadow.querySelector(".lasso-agent-tasks-badge");
|
|
12263
12305
|
if (navBadge) navBadge.hidden = activeCount === 0;
|
|
12264
12306
|
list.replaceChildren();
|
|
12265
|
-
|
|
12307
|
+
const activeTab = panelEl.querySelector(".lasso-task-tab.active")?.dataset.taskTab || "active";
|
|
12308
|
+
const visibleTasks = state.agentTasks.filter((task) => activeTab === "complete" ? task.status === "complete" : task.status !== "complete");
|
|
12309
|
+
if (!visibleTasks.length) {
|
|
12266
12310
|
list.innerHTML = `<div class="lasso-task-empty">Prompt an element to start a task.</div>`;
|
|
12267
12311
|
} else {
|
|
12268
|
-
for (const task of
|
|
12312
|
+
for (const task of visibleTasks) {
|
|
12269
12313
|
const button = document.createElement("button");
|
|
12270
12314
|
button.type = "button";
|
|
12271
12315
|
button.className = `lasso-task-row${task.id === state.activeTaskId ? " active" : ""}`;
|
|
12272
|
-
button.innerHTML = `<span class="lasso-task-status ${task.status}"></span><span class="lasso-task-row-copy"><strong></strong><small>${statusLabel[task.status]}</small></span
|
|
12316
|
+
button.innerHTML = `<span class="lasso-task-status ${task.status}"></span><span class="lasso-task-row-copy"><strong></strong><small>${statusLabel[task.status]}</small></span>${task.status === "review" ? '<span class="lasso-task-review-label">Review</span>' : ""}`;
|
|
12273
12317
|
button.querySelector("strong").textContent = task.instruction;
|
|
12274
12318
|
button.addEventListener("click", () => selectAgentTask(task.id));
|
|
12319
|
+
if (task.status === "review") {
|
|
12320
|
+
const review = button.querySelector(".lasso-task-review-label");
|
|
12321
|
+
review.addEventListener("click", (event) => {
|
|
12322
|
+
event.stopPropagation();
|
|
12323
|
+
requestAgentTaskReview(task.id);
|
|
12324
|
+
});
|
|
12325
|
+
}
|
|
12275
12326
|
list.appendChild(button);
|
|
12276
12327
|
}
|
|
12277
12328
|
}
|
|
@@ -12310,16 +12361,12 @@
|
|
|
12310
12361
|
changes.textContent = `${pendingChanges.length} proposed file change${pendingChanges.length === 1 ? "" : "s"}`;
|
|
12311
12362
|
detail.appendChild(changes);
|
|
12312
12363
|
if (selected.status === "review") {
|
|
12313
|
-
const
|
|
12314
|
-
|
|
12315
|
-
|
|
12316
|
-
|
|
12317
|
-
|
|
12318
|
-
|
|
12319
|
-
state.bridgeSocket.send(JSON.stringify({ type: "apply", taskId: selected.id, changes: pendingChanges }));
|
|
12320
|
-
updateAgentTask(selected.id, { status: "working", message: "Applying changes\u2026", activity: [...selected.activity, "Applying changes\u2026"] });
|
|
12321
|
-
});
|
|
12322
|
-
detail.appendChild(apply);
|
|
12364
|
+
const review = document.createElement("button");
|
|
12365
|
+
review.type = "button";
|
|
12366
|
+
review.className = "lasso-task-apply";
|
|
12367
|
+
review.textContent = "Review changes";
|
|
12368
|
+
review.addEventListener("click", () => requestAgentTaskReview(selected.id));
|
|
12369
|
+
detail.appendChild(review);
|
|
12323
12370
|
}
|
|
12324
12371
|
}
|
|
12325
12372
|
}
|
|
@@ -18466,6 +18513,9 @@
|
|
|
18466
18513
|
cli: terminal_default
|
|
18467
18514
|
};
|
|
18468
18515
|
function providerIcon(provider, active = false) {
|
|
18516
|
+
if (provider === "cli") {
|
|
18517
|
+
return `<span class="${active ? "lasso-model-active-icon" : "lasso-model-item-icon"} provider-cli" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" focusable="false"><circle cx="12" cy="12" r="9" fill="currentColor" opacity=".16"/><circle cx="12" cy="9" r="3" fill="currentColor"/><path d="M6.5 18c.9-2.4 2.7-3.6 5.5-3.6s4.6 1.2 5.5 3.6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></span>`;
|
|
18518
|
+
}
|
|
18469
18519
|
const icon = providerIcons[provider];
|
|
18470
18520
|
return `<span class="${active ? "lasso-model-active-icon" : "lasso-model-item-icon"} provider-${provider}" aria-hidden="true"><svg viewBox="0 0 ${icon.width} ${icon.height}" xmlns="http://www.w3.org/2000/svg" focusable="false">${icon.body}</svg></span>`;
|
|
18471
18521
|
}
|
|
@@ -18591,7 +18641,7 @@
|
|
|
18591
18641
|
<div class="lasso-review-files"></div>
|
|
18592
18642
|
<div class="lasso-review-actions">
|
|
18593
18643
|
<button class="lasso-review-undo" type="button">Keep editing</button>
|
|
18594
|
-
<button class="lasso-review-apply primary" type="button">
|
|
18644
|
+
<button class="lasso-review-apply primary" type="button">Accept & apply</button>
|
|
18595
18645
|
</div>
|
|
18596
18646
|
`;
|
|
18597
18647
|
dom.shadow.appendChild(rev);
|
|
@@ -18600,6 +18650,11 @@
|
|
|
18600
18650
|
if (task) restoreTaskPrompt(task);
|
|
18601
18651
|
else resetPromptSession();
|
|
18602
18652
|
});
|
|
18653
|
+
onAgentTaskReviewRequested((task) => {
|
|
18654
|
+
state.promptTaskId = task.id;
|
|
18655
|
+
state.pendingChanges = [...task.pendingChanges.length ? task.pendingChanges : task.changes || []];
|
|
18656
|
+
showReview(state.pendingChanges, task.message);
|
|
18657
|
+
});
|
|
18603
18658
|
const promptTop = el.querySelector(".lasso-prompt-top");
|
|
18604
18659
|
let dragState = null;
|
|
18605
18660
|
promptTop.addEventListener("pointerdown", (event) => {
|
|
@@ -18745,6 +18800,11 @@
|
|
|
18745
18800
|
if (!taskId2 || !state.bridgeSocket || state.bridgeSocket.readyState !== WebSocket.OPEN || !state.pendingChanges.length) return;
|
|
18746
18801
|
requestAgentNotificationPermission();
|
|
18747
18802
|
state.bridgeSocket.send(JSON.stringify({ type: "apply", taskId: taskId2, changes: state.pendingChanges }));
|
|
18803
|
+
updateAgentTask(taskId2, {
|
|
18804
|
+
status: "working",
|
|
18805
|
+
message: "Applying accepted changes\u2026",
|
|
18806
|
+
activity: [...getAgentTask(taskId2)?.activity || [], "Applying accepted changes\u2026"]
|
|
18807
|
+
});
|
|
18748
18808
|
appendChat("assistant", "Applying the reviewed change\u2026", taskId2);
|
|
18749
18809
|
});
|
|
18750
18810
|
return { prompt: el, review: rev };
|
|
@@ -19092,7 +19152,6 @@
|
|
|
19092
19152
|
}
|
|
19093
19153
|
if (promptEl) promptEl.classList.add("visible");
|
|
19094
19154
|
setSelectMode(false);
|
|
19095
|
-
if (task.status === "review" && state.pendingChanges.length) showReview(state.pendingChanges, task.message);
|
|
19096
19155
|
setAgentStatus(task.status, task.message, task.detail, task.id, false);
|
|
19097
19156
|
requestAnimationFrame(() => promptInput?.focus());
|
|
19098
19157
|
}
|
|
@@ -19211,6 +19270,11 @@
|
|
|
19211
19270
|
const selectionId = state.selectionId;
|
|
19212
19271
|
const model = state.selectedModel;
|
|
19213
19272
|
const screenshotPromise = state.screenshotPromise;
|
|
19273
|
+
const reusableTask = findReusableAgentTask(instruction, selectedElement);
|
|
19274
|
+
if (reusableTask) {
|
|
19275
|
+
selectAgentTask(reusableTask.id);
|
|
19276
|
+
return;
|
|
19277
|
+
}
|
|
19214
19278
|
appendChat("user", instruction);
|
|
19215
19279
|
const messages = state.chatHistory.map((message) => ({ ...message }));
|
|
19216
19280
|
const changesHistory = state.changesHistory.map((entry) => ({ ...entry, changes: entry.changes.map((change) => ({ ...change })) }));
|
package/package.json
CHANGED