@lasso-ai/cli 1.0.19 → 1.0.21
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/bridge.d.ts +3 -0
- package/dist/cli/bridge.js +6 -5
- package/dist/overlay.js +335 -119
- package/package.json +1 -1
package/dist/cli/bridge.d.ts
CHANGED
package/dist/cli/bridge.js
CHANGED
|
@@ -277,8 +277,8 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
277
277
|
taskControllers.get(request.taskId)?.abort();
|
|
278
278
|
const controller = new AbortController();
|
|
279
279
|
taskControllers.set(request.taskId, controller);
|
|
280
|
-
if (
|
|
281
|
-
socket.send(JSON.stringify({ type: "agent_status", taskId: request.taskId, status: "working", message: statusMessage }));
|
|
280
|
+
if (socket.readyState === socket.OPEN) {
|
|
281
|
+
socket.send(JSON.stringify({ type: "agent_status", taskId: request.taskId, status: "working", message: statusMessage || "Starting agent…" }));
|
|
282
282
|
}
|
|
283
283
|
void (0, agent_1.proposeChanges)(cwd, request, config, controller.signal, (message, detail) => {
|
|
284
284
|
if (!controller.signal.aborted && socket.readyState === socket.OPEN) {
|
|
@@ -336,6 +336,7 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
336
336
|
const selectedConfig = localProvider
|
|
337
337
|
? { provider: cliProvider, model: msg.model }
|
|
338
338
|
: { ...agentConfig, provider: (msg.provider || agentConfig.provider), model: msg.model };
|
|
339
|
+
socket.send(JSON.stringify({ type: "agent_status", taskId: msg.taskId, status: "working", message: "Starting agent…" }));
|
|
339
340
|
void (0, agent_1.answerQuestion)(cwd, { question: msg.question, context: msg.context, element: msg.element, messages: msg.messages }, selectedConfig, controller.signal, (message, detail) => {
|
|
340
341
|
if (!controller.signal.aborted && socket.readyState === socket.OPEN)
|
|
341
342
|
socket.send(JSON.stringify({ type: "agent_status", taskId: msg.taskId, status: "working", message, detail }));
|
|
@@ -396,10 +397,10 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
396
397
|
const controller = new AbortController();
|
|
397
398
|
activeAgentController?.abort();
|
|
398
399
|
activeAgentController = controller;
|
|
399
|
-
socket.send(JSON.stringify({ type: "
|
|
400
|
+
socket.send(JSON.stringify({ type: "git_progress", message: "Generating a commit message…" }));
|
|
400
401
|
void getGitState(cwd).then((git) => (0, agent_1.generateCommitMessage)(cwd, git.status || [], selectedConfig, controller.signal, (message, detail) => {
|
|
401
402
|
if (!controller.signal.aborted && socket.readyState === socket.OPEN)
|
|
402
|
-
socket.send(JSON.stringify({ type: "
|
|
403
|
+
socket.send(JSON.stringify({ type: "git_progress", message: detail ? `${message} · ${detail}` : message }));
|
|
403
404
|
})).then((message) => {
|
|
404
405
|
if (!controller.signal.aborted)
|
|
405
406
|
socket.send(JSON.stringify({ type: "git_commit_message", message }));
|
|
@@ -518,7 +519,7 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
518
519
|
runEditReview(editRequest, editConfig, "The source changed. Refreshing the review against the current file…");
|
|
519
520
|
}
|
|
520
521
|
else {
|
|
521
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "error", message }));
|
|
522
|
+
socket.send(JSON.stringify({ type: "agent_status", taskId: msg.taskId, status: "error", message }));
|
|
522
523
|
}
|
|
523
524
|
}
|
|
524
525
|
}
|
package/dist/overlay.js
CHANGED
|
@@ -7880,6 +7880,7 @@
|
|
|
7880
7880
|
pendingChanges = [];
|
|
7881
7881
|
agentTasks = [];
|
|
7882
7882
|
activeTaskId = null;
|
|
7883
|
+
promptTaskId = null;
|
|
7883
7884
|
runtimeErrors = [];
|
|
7884
7885
|
screenshotPromise = Promise.resolve({});
|
|
7885
7886
|
// Agent State
|
|
@@ -7904,7 +7905,7 @@
|
|
|
7904
7905
|
myUser = null;
|
|
7905
7906
|
presenceUsers = /* @__PURE__ */ new Map();
|
|
7906
7907
|
lockMap = /* @__PURE__ */ new Map();
|
|
7907
|
-
|
|
7908
|
+
heldLockElements = /* @__PURE__ */ new Set();
|
|
7908
7909
|
spotlightUserId = null;
|
|
7909
7910
|
// Comments
|
|
7910
7911
|
commentThreads = /* @__PURE__ */ new Map();
|
|
@@ -10933,6 +10934,7 @@
|
|
|
10933
10934
|
.lasso-task-detail-status { color: var(--lo-primary); font-size: 11px; font-weight: 600; }
|
|
10934
10935
|
.lasso-task-prompt { margin: 0 0 10px; font-size: 13px; line-height: 1.45; }
|
|
10935
10936
|
.lasso-task-message { margin: 0 0 12px; line-height: 1.45; }
|
|
10937
|
+
.lasso-task-activity { display: flex; flex-direction: column; gap: 4px; max-height: 130px; margin: 0 0 12px; padding: 8px; overflow: auto; border-radius: var(--lo-radius-md); background: var(--lo-surface-2); color: var(--lo-text-3); font-size: 10.5px; line-height: 1.35; }
|
|
10936
10938
|
.lasso-task-changes { margin-bottom: 10px; color: var(--lo-text-2); font-size: 11px; }
|
|
10937
10939
|
.lasso-task-apply { padding: 7px 11px; border: 0; border-radius: var(--lo-radius-full); background: var(--lo-primary); color: #111214; font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; }
|
|
10938
10940
|
|
|
@@ -12125,6 +12127,7 @@
|
|
|
12125
12127
|
var list = null;
|
|
12126
12128
|
var detail = null;
|
|
12127
12129
|
var badge = null;
|
|
12130
|
+
var selectionListeners = /* @__PURE__ */ new Set();
|
|
12128
12131
|
var statusLabel = {
|
|
12129
12132
|
queued: "Queued",
|
|
12130
12133
|
thinking: "Thinking",
|
|
@@ -12137,9 +12140,36 @@
|
|
|
12137
12140
|
function taskId() {
|
|
12138
12141
|
return `task-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
|
|
12139
12142
|
}
|
|
12140
|
-
function
|
|
12143
|
+
function sameChangeList(left, right) {
|
|
12144
|
+
return left.length === right.length && left.every((change, index) => {
|
|
12145
|
+
const other = right[index];
|
|
12146
|
+
return Boolean(other) && change.filePath === other.filePath && change.oldString === other.oldString && change.newString === other.newString;
|
|
12147
|
+
});
|
|
12148
|
+
}
|
|
12149
|
+
function onAgentTaskSelected(listener) {
|
|
12150
|
+
selectionListeners.add(listener);
|
|
12151
|
+
return () => selectionListeners.delete(listener);
|
|
12152
|
+
}
|
|
12153
|
+
function notifyTaskSelection(task) {
|
|
12154
|
+
for (const listener of selectionListeners) listener(task);
|
|
12155
|
+
}
|
|
12156
|
+
function createAgentTask(instruction, messages = state.chatHistory, changesHistory = state.changesHistory, element = state.selected, selectionId = state.selectionId) {
|
|
12141
12157
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12142
|
-
const task = {
|
|
12158
|
+
const task = {
|
|
12159
|
+
id: taskId(),
|
|
12160
|
+
instruction,
|
|
12161
|
+
status: "queued",
|
|
12162
|
+
message: "Queued",
|
|
12163
|
+
pendingChanges: [],
|
|
12164
|
+
messages: messages.map((message) => ({ ...message })),
|
|
12165
|
+
changesHistory: changesHistory.map((entry) => ({ ...entry, changes: entry.changes.map((change) => ({ ...change })) })),
|
|
12166
|
+
activity: ["Queued"],
|
|
12167
|
+
lastInstruction: instruction,
|
|
12168
|
+
selectionId,
|
|
12169
|
+
element: element || void 0,
|
|
12170
|
+
createdAt: now,
|
|
12171
|
+
updatedAt: now
|
|
12172
|
+
};
|
|
12143
12173
|
state.agentTasks.unshift(task);
|
|
12144
12174
|
state.activeTaskId = task.id;
|
|
12145
12175
|
renderTasks();
|
|
@@ -12155,9 +12185,41 @@
|
|
|
12155
12185
|
Object.assign(task, patch, { updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
12156
12186
|
renderTasks();
|
|
12157
12187
|
}
|
|
12188
|
+
function recordTaskActivity(id, text) {
|
|
12189
|
+
const task = getAgentTask(id);
|
|
12190
|
+
const value2 = text.trim();
|
|
12191
|
+
if (!task || !value2 || task.activity[task.activity.length - 1] === value2) return;
|
|
12192
|
+
updateAgentTask(id, { activity: [...task.activity, value2].slice(-200) });
|
|
12193
|
+
}
|
|
12194
|
+
function recordTaskChangeHistory(id, summary, changes) {
|
|
12195
|
+
const task = getAgentTask(id);
|
|
12196
|
+
if (!task) return;
|
|
12197
|
+
const previous = task.changesHistory[task.changesHistory.length - 1];
|
|
12198
|
+
if (previous?.summary === summary && sameChangeList(previous.changes, changes)) return;
|
|
12199
|
+
updateAgentTask(id, {
|
|
12200
|
+
changesHistory: [...task.changesHistory, { summary, changes: changes.map((change) => ({ ...change })), createdAt: (/* @__PURE__ */ new Date()).toISOString() }]
|
|
12201
|
+
});
|
|
12202
|
+
}
|
|
12203
|
+
function appendTaskMessage(id, role, text) {
|
|
12204
|
+
const task = getAgentTask(id);
|
|
12205
|
+
const content = text.trim();
|
|
12206
|
+
if (!task || !content) return;
|
|
12207
|
+
const previous = task.messages[task.messages.length - 1];
|
|
12208
|
+
if (previous?.role === role && previous.content === content) return;
|
|
12209
|
+
const message = {
|
|
12210
|
+
role,
|
|
12211
|
+
content,
|
|
12212
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12213
|
+
contextId: task.selectionId || void 0
|
|
12214
|
+
};
|
|
12215
|
+
updateAgentTask(task.id, { messages: [...task.messages, message] });
|
|
12216
|
+
return message;
|
|
12217
|
+
}
|
|
12158
12218
|
function selectAgentTask(id) {
|
|
12159
|
-
|
|
12160
|
-
state.activeTaskId = id;
|
|
12219
|
+
const task = getAgentTask(id);
|
|
12220
|
+
state.activeTaskId = task?.id || null;
|
|
12221
|
+
state.promptTaskId = task?.id || null;
|
|
12222
|
+
notifyTaskSelection(task || null);
|
|
12161
12223
|
renderTasks();
|
|
12162
12224
|
}
|
|
12163
12225
|
function toggleTaskPanel(force) {
|
|
@@ -12194,9 +12256,11 @@
|
|
|
12194
12256
|
}
|
|
12195
12257
|
function renderTasks() {
|
|
12196
12258
|
if (!list || !detail || !badge) return;
|
|
12197
|
-
const
|
|
12259
|
+
const activeCount = state.agentTasks.filter((task) => task.status !== "complete" && task.status !== "error" && task.status !== "stopped").length;
|
|
12198
12260
|
badge.hidden = state.agentTasks.length === 0;
|
|
12199
|
-
badge.textContent = String(
|
|
12261
|
+
badge.textContent = String(activeCount || state.agentTasks.length);
|
|
12262
|
+
const navBadge = getDOM().shadow.querySelector(".lasso-agent-tasks-badge");
|
|
12263
|
+
if (navBadge) navBadge.hidden = activeCount === 0;
|
|
12200
12264
|
list.replaceChildren();
|
|
12201
12265
|
if (!state.agentTasks.length) {
|
|
12202
12266
|
list.innerHTML = `<div class="lasso-task-empty">Prompt an element to start a task.</div>`;
|
|
@@ -12221,10 +12285,7 @@
|
|
|
12221
12285
|
const heading = document.createElement("div");
|
|
12222
12286
|
heading.className = "lasso-task-detail-heading";
|
|
12223
12287
|
heading.innerHTML = `<span class="lasso-task-detail-status ${selected.status}">${statusLabel[selected.status]}</span><button type="button" class="lasso-task-back">All tasks</button>`;
|
|
12224
|
-
heading.querySelector("button").addEventListener("click", () =>
|
|
12225
|
-
state.activeTaskId = null;
|
|
12226
|
-
renderTasks();
|
|
12227
|
-
});
|
|
12288
|
+
heading.querySelector("button").addEventListener("click", () => selectAgentTask(null));
|
|
12228
12289
|
const prompt = document.createElement("p");
|
|
12229
12290
|
prompt.className = "lasso-task-prompt";
|
|
12230
12291
|
prompt.textContent = selected.instruction;
|
|
@@ -12232,10 +12293,21 @@
|
|
|
12232
12293
|
activity.className = "lasso-task-message";
|
|
12233
12294
|
activity.textContent = selected.response || selected.message;
|
|
12234
12295
|
detail.append(heading, prompt, activity);
|
|
12235
|
-
if (selected.
|
|
12296
|
+
if (selected.activity.length) {
|
|
12297
|
+
const activityList = document.createElement("div");
|
|
12298
|
+
activityList.className = "lasso-task-activity";
|
|
12299
|
+
for (const entry of selected.activity.slice(-8)) {
|
|
12300
|
+
const line = document.createElement("div");
|
|
12301
|
+
line.textContent = entry;
|
|
12302
|
+
activityList.appendChild(line);
|
|
12303
|
+
}
|
|
12304
|
+
detail.appendChild(activityList);
|
|
12305
|
+
}
|
|
12306
|
+
const pendingChanges = selected.pendingChanges.length ? selected.pendingChanges : selected.changes || [];
|
|
12307
|
+
if (pendingChanges.length) {
|
|
12236
12308
|
const changes = document.createElement("div");
|
|
12237
12309
|
changes.className = "lasso-task-changes";
|
|
12238
|
-
changes.textContent = `${
|
|
12310
|
+
changes.textContent = `${pendingChanges.length} proposed file change${pendingChanges.length === 1 ? "" : "s"}`;
|
|
12239
12311
|
detail.appendChild(changes);
|
|
12240
12312
|
if (selected.status === "review") {
|
|
12241
12313
|
const apply = document.createElement("button");
|
|
@@ -12244,8 +12316,8 @@
|
|
|
12244
12316
|
apply.textContent = "Apply changes";
|
|
12245
12317
|
apply.addEventListener("click", () => {
|
|
12246
12318
|
if (state.bridgeSocket?.readyState !== WebSocket.OPEN) return;
|
|
12247
|
-
state.bridgeSocket.send(JSON.stringify({ type: "apply", taskId: selected.id, changes:
|
|
12248
|
-
updateAgentTask(selected.id, { message: "Applying changes\u2026" });
|
|
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"] });
|
|
12249
12321
|
});
|
|
12250
12322
|
detail.appendChild(apply);
|
|
12251
12323
|
}
|
|
@@ -18236,10 +18308,10 @@
|
|
|
18236
18308
|
state: "online",
|
|
18237
18309
|
selection: currentSelectionPayload()
|
|
18238
18310
|
});
|
|
18239
|
-
|
|
18311
|
+
for (const elementId of state.heldLockElements) {
|
|
18240
18312
|
collabEmit("lock:extend", {
|
|
18241
18313
|
sessionId: state.collabProjectId,
|
|
18242
|
-
elementId
|
|
18314
|
+
elementId
|
|
18243
18315
|
});
|
|
18244
18316
|
}
|
|
18245
18317
|
}, 3e4);
|
|
@@ -18292,7 +18364,7 @@
|
|
|
18292
18364
|
}
|
|
18293
18365
|
const key = elementKey(state.selected);
|
|
18294
18366
|
const lock = state.lockMap.get(key);
|
|
18295
|
-
const mine = state.
|
|
18367
|
+
const mine = state.heldLockElements.has(key);
|
|
18296
18368
|
if (lock) {
|
|
18297
18369
|
dom.heldLockChip.hidden = false;
|
|
18298
18370
|
dom.heldLockChip.classList.toggle("held", mine);
|
|
@@ -18327,7 +18399,7 @@
|
|
|
18327
18399
|
},
|
|
18328
18400
|
(res) => {
|
|
18329
18401
|
if (res.ok && res.lock) {
|
|
18330
|
-
state.
|
|
18402
|
+
state.heldLockElements.add(key);
|
|
18331
18403
|
state.lockMap.set(key, res.lock);
|
|
18332
18404
|
updateLockChip();
|
|
18333
18405
|
resolve(true);
|
|
@@ -18346,14 +18418,16 @@
|
|
|
18346
18418
|
);
|
|
18347
18419
|
});
|
|
18348
18420
|
}
|
|
18349
|
-
function releaseHeldLock() {
|
|
18350
|
-
|
|
18351
|
-
const
|
|
18352
|
-
|
|
18353
|
-
|
|
18354
|
-
|
|
18355
|
-
|
|
18421
|
+
function releaseHeldLock(elementId) {
|
|
18422
|
+
const elementIds = elementId ? [elementId] : Array.from(state.heldLockElements);
|
|
18423
|
+
for (const id of elementIds) {
|
|
18424
|
+
if (!state.heldLockElements.delete(id)) continue;
|
|
18425
|
+
state.lockMap.delete(id);
|
|
18426
|
+
if (state.collabSocket?.connected && state.collabJoined) {
|
|
18427
|
+
collabEmit("lock:release", { sessionId: state.collabProjectId, elementId: id });
|
|
18428
|
+
}
|
|
18356
18429
|
}
|
|
18430
|
+
updateLockChip();
|
|
18357
18431
|
}
|
|
18358
18432
|
|
|
18359
18433
|
// src/overlay/icons/lasso.ts
|
|
@@ -18522,6 +18596,10 @@
|
|
|
18522
18596
|
`;
|
|
18523
18597
|
dom.shadow.appendChild(rev);
|
|
18524
18598
|
reviewPanel = rev;
|
|
18599
|
+
onAgentTaskSelected((task) => {
|
|
18600
|
+
if (task) restoreTaskPrompt(task);
|
|
18601
|
+
else resetPromptSession();
|
|
18602
|
+
});
|
|
18525
18603
|
const promptTop = el.querySelector(".lasso-prompt-top");
|
|
18526
18604
|
let dragState = null;
|
|
18527
18605
|
promptTop.addEventListener("pointerdown", (event) => {
|
|
@@ -18583,10 +18661,19 @@
|
|
|
18583
18661
|
stopButton.addEventListener("click", (event) => {
|
|
18584
18662
|
event.preventDefault();
|
|
18585
18663
|
event.stopPropagation();
|
|
18664
|
+
const taskId2 = state.promptTaskId || void 0;
|
|
18665
|
+
const task = taskId2 ? getAgentTask(taskId2) : void 0;
|
|
18586
18666
|
if (state.bridgeSocket?.readyState === WebSocket.OPEN) {
|
|
18587
|
-
state.bridgeSocket.send(JSON.stringify({ type: "stop", taskId:
|
|
18667
|
+
state.bridgeSocket.send(JSON.stringify({ type: "stop", taskId: taskId2 }));
|
|
18668
|
+
}
|
|
18669
|
+
if (taskId2) {
|
|
18670
|
+
appendChat("assistant", "Agent stopped.", taskId2);
|
|
18671
|
+
if (task) {
|
|
18672
|
+
updateAgentTask(task.id, { status: "stopped", message: "Agent stopped." });
|
|
18673
|
+
recordTaskActivity(task.id, "Agent stopped.");
|
|
18674
|
+
}
|
|
18588
18675
|
}
|
|
18589
|
-
|
|
18676
|
+
if (task?.element) releaseHeldLock(elementKey(task.element));
|
|
18590
18677
|
resetAgentState();
|
|
18591
18678
|
});
|
|
18592
18679
|
const voiceBtn = el.querySelector(".lasso-prompt-voice");
|
|
@@ -18643,20 +18730,22 @@
|
|
|
18643
18730
|
});
|
|
18644
18731
|
rev.querySelector(".lasso-review-close").addEventListener("click", closeReview);
|
|
18645
18732
|
rev.querySelector(".lasso-review-undo").addEventListener("click", () => {
|
|
18733
|
+
const taskId2 = state.promptTaskId || void 0;
|
|
18646
18734
|
if (state.pendingChanges.length && rev.querySelector(".lasso-review-apply").hidden) {
|
|
18647
18735
|
if (state.bridgeSocket?.readyState === WebSocket.OPEN) {
|
|
18648
|
-
state.bridgeSocket.send(JSON.stringify({ type: "undo", taskId:
|
|
18736
|
+
state.bridgeSocket.send(JSON.stringify({ type: "undo", taskId: taskId2 }));
|
|
18649
18737
|
}
|
|
18650
18738
|
return;
|
|
18651
18739
|
}
|
|
18652
18740
|
closeReview();
|
|
18653
|
-
appendChat("assistant", "Kept as a proposal. Nothing was changed.");
|
|
18741
|
+
appendChat("assistant", "Kept as a proposal. Nothing was changed.", taskId2);
|
|
18654
18742
|
});
|
|
18655
18743
|
rev.querySelector(".lasso-review-apply").addEventListener("click", () => {
|
|
18656
|
-
|
|
18744
|
+
const taskId2 = state.promptTaskId;
|
|
18745
|
+
if (!taskId2 || !state.bridgeSocket || state.bridgeSocket.readyState !== WebSocket.OPEN || !state.pendingChanges.length) return;
|
|
18657
18746
|
requestAgentNotificationPermission();
|
|
18658
|
-
state.bridgeSocket.send(JSON.stringify({ type: "apply", taskId:
|
|
18659
|
-
appendChat("assistant", "Applying the reviewed change\u2026");
|
|
18747
|
+
state.bridgeSocket.send(JSON.stringify({ type: "apply", taskId: taskId2, changes: state.pendingChanges }));
|
|
18748
|
+
appendChat("assistant", "Applying the reviewed change\u2026", taskId2);
|
|
18660
18749
|
});
|
|
18661
18750
|
return { prompt: el, review: rev };
|
|
18662
18751
|
}
|
|
@@ -18825,29 +18914,50 @@
|
|
|
18825
18914
|
text.textContent = value2;
|
|
18826
18915
|
line.append(prefix, text);
|
|
18827
18916
|
agentLogElement.append(line);
|
|
18828
|
-
|
|
18917
|
+
agentLogElement.scrollTop = agentLogElement.scrollHeight;
|
|
18829
18918
|
}
|
|
18830
18919
|
if (agentLogToggle) agentLogToggle.hidden = false;
|
|
18831
18920
|
}
|
|
18832
|
-
function
|
|
18921
|
+
function loadAgentLog(lines) {
|
|
18922
|
+
clearAgentLog();
|
|
18923
|
+
for (const line of lines) appendAgentLog(line);
|
|
18924
|
+
}
|
|
18925
|
+
function renderChatThread() {
|
|
18833
18926
|
const thread = promptEl?.querySelector(".lasso-chat-thread");
|
|
18834
|
-
if (!thread
|
|
18835
|
-
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
role
|
|
18839
|
-
content
|
|
18840
|
-
|
|
18841
|
-
|
|
18842
|
-
}
|
|
18843
|
-
const item = document.createElement("div");
|
|
18844
|
-
item.className = `lasso-chat-message ${role}`;
|
|
18845
|
-
item.dataset.rawText = text;
|
|
18846
|
-
renderChatText(item, text);
|
|
18847
|
-
thread.appendChild(item);
|
|
18848
|
-
while (thread.children.length > 6) thread.firstElementChild?.remove();
|
|
18927
|
+
if (!thread) return;
|
|
18928
|
+
thread.replaceChildren();
|
|
18929
|
+
for (const message of state.chatHistory.slice(-6)) {
|
|
18930
|
+
const item = document.createElement("div");
|
|
18931
|
+
item.className = `lasso-chat-message ${message.role}`;
|
|
18932
|
+
item.dataset.rawText = message.content;
|
|
18933
|
+
renderChatText(item, message.content);
|
|
18934
|
+
thread.appendChild(item);
|
|
18935
|
+
}
|
|
18849
18936
|
thread.scrollTop = thread.scrollHeight;
|
|
18850
18937
|
}
|
|
18938
|
+
function appendChat(role, text, taskId2 = state.promptTaskId) {
|
|
18939
|
+
const content = text.trim();
|
|
18940
|
+
if (!content) return;
|
|
18941
|
+
const task = taskId2 ? getAgentTask(taskId2) : void 0;
|
|
18942
|
+
if (taskId2 && !task) return;
|
|
18943
|
+
if (task) {
|
|
18944
|
+
const previous = task.messages[task.messages.length - 1];
|
|
18945
|
+
if (previous?.role === role && previous.content === content) return;
|
|
18946
|
+
const message = appendTaskMessage(task.id, role, content);
|
|
18947
|
+
if (!message || state.promptTaskId !== task.id) return;
|
|
18948
|
+
state.chatHistory = [...task.messages];
|
|
18949
|
+
} else {
|
|
18950
|
+
const previous = state.chatHistory[state.chatHistory.length - 1];
|
|
18951
|
+
if (previous?.role === role && previous.content === content) return;
|
|
18952
|
+
state.chatHistory.push({
|
|
18953
|
+
role,
|
|
18954
|
+
content,
|
|
18955
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18956
|
+
contextId: state.selectionId || void 0
|
|
18957
|
+
});
|
|
18958
|
+
}
|
|
18959
|
+
renderChatThread();
|
|
18960
|
+
}
|
|
18851
18961
|
function renderChatText(container, text) {
|
|
18852
18962
|
const codePattern = /(`+)([\s\S]*?)\1/g;
|
|
18853
18963
|
let lastIndex = 0;
|
|
@@ -18865,33 +18975,35 @@
|
|
|
18865
18975
|
container.append(document.createTextNode(text.slice(lastIndex)));
|
|
18866
18976
|
}
|
|
18867
18977
|
}
|
|
18868
|
-
function setAgentStatus(status, message, detail2) {
|
|
18978
|
+
function setAgentStatus(status, message, detail2, taskId2 = state.promptTaskId, appendMessage = true) {
|
|
18869
18979
|
if (!agentStatusElement || !agentStatusMessage || !sendButton) return;
|
|
18870
18980
|
const logMessage = detail2?.trim() || message.trim();
|
|
18871
18981
|
const lastLog = agentLogLines[agentLogLines.length - 1];
|
|
18872
|
-
if (agentStatusElement.dataset.status === status && agentStatusMessage.textContent === message && (
|
|
18982
|
+
if (agentStatusElement.dataset.status === status && agentStatusMessage.textContent === message && (!logMessage || lastLog === logMessage)) return;
|
|
18873
18983
|
appendAgentLog(logMessage);
|
|
18984
|
+
if (taskId2) recordTaskActivity(taskId2, logMessage);
|
|
18985
|
+
const running = status === "thinking" || status === "working";
|
|
18874
18986
|
agentStatusElement.hidden = status === "review";
|
|
18875
18987
|
agentStatusElement.dataset.status = status;
|
|
18876
18988
|
agentStatusMessage.textContent = message;
|
|
18877
18989
|
const badgeEl = agentStatusElement.querySelector(".lasso-agent-status-badge");
|
|
18878
18990
|
if (badgeEl) {
|
|
18879
|
-
badgeEl.textContent = status === "thinking" ? "thinking" : status === "working" ? "executing" : status;
|
|
18991
|
+
badgeEl.textContent = status === "thinking" ? "thinking" : status === "working" ? "executing" : status === "complete" ? "done" : status;
|
|
18880
18992
|
badgeEl.className = `lasso-agent-status-badge ${status}`;
|
|
18881
18993
|
}
|
|
18882
|
-
state.agentRunning =
|
|
18883
|
-
sendButton.classList.toggle("loading",
|
|
18884
|
-
if (stopButton) stopButton.hidden = !
|
|
18994
|
+
state.agentRunning = running;
|
|
18995
|
+
sendButton.classList.toggle("loading", running);
|
|
18996
|
+
if (stopButton) stopButton.hidden = !running;
|
|
18885
18997
|
if (promptInput) promptInput.disabled = false;
|
|
18886
18998
|
const label = sendButton.querySelector("span");
|
|
18887
18999
|
if (label) {
|
|
18888
|
-
label.textContent = status === "review" ? "Review" : status === "error" ? "Retry" :
|
|
19000
|
+
label.textContent = status === "review" ? "Review" : status === "error" ? "Retry" : running ? "" : "Send";
|
|
18889
19001
|
}
|
|
18890
|
-
sendButton.setAttribute("aria-label",
|
|
18891
|
-
sendButton.dataset.state = status === "error" ? "retry" :
|
|
19002
|
+
sendButton.setAttribute("aria-label", running ? "Agent is working" : status === "error" ? "Retry request" : "Send request");
|
|
19003
|
+
sendButton.dataset.state = status === "error" ? "retry" : running ? "working" : status;
|
|
18892
19004
|
syncSendButtonState();
|
|
18893
|
-
if (status === "review" || status === "error" || status === "stopped") {
|
|
18894
|
-
appendChat(status === "error" ? "error" : "assistant", message);
|
|
19005
|
+
if (appendMessage && (status === "review" || status === "error" || status === "stopped")) {
|
|
19006
|
+
appendChat(status === "error" ? "error" : "assistant", message, taskId2);
|
|
18895
19007
|
}
|
|
18896
19008
|
}
|
|
18897
19009
|
function syncSendButtonState() {
|
|
@@ -18926,6 +19038,64 @@
|
|
|
18926
19038
|
if (stopButton) stopButton.hidden = true;
|
|
18927
19039
|
if (promptInput) promptInput.disabled = false;
|
|
18928
19040
|
}
|
|
19041
|
+
function hideReview() {
|
|
19042
|
+
if (reviewPanel) reviewPanel.hidden = true;
|
|
19043
|
+
}
|
|
19044
|
+
function resetPromptSession() {
|
|
19045
|
+
state.promptTaskId = null;
|
|
19046
|
+
state.chatHistory = [];
|
|
19047
|
+
state.changesHistory = [];
|
|
19048
|
+
state.pendingChanges = [];
|
|
19049
|
+
state.lastInstruction = "";
|
|
19050
|
+
state.selectionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
19051
|
+
state.screenshotPromise = Promise.resolve({});
|
|
19052
|
+
hideReview();
|
|
19053
|
+
clearAgentLog();
|
|
19054
|
+
resetAgentState();
|
|
19055
|
+
renderChatThread();
|
|
19056
|
+
if (promptInput) {
|
|
19057
|
+
promptInput.value = "";
|
|
19058
|
+
syncSendButtonState();
|
|
19059
|
+
}
|
|
19060
|
+
}
|
|
19061
|
+
function restoreTaskPrompt(task) {
|
|
19062
|
+
state.activeTaskId = task.id;
|
|
19063
|
+
state.promptTaskId = task.id;
|
|
19064
|
+
state.chatHistory = [...task.messages];
|
|
19065
|
+
state.changesHistory = task.changesHistory.map((entry) => ({ ...entry, changes: entry.changes.map((change) => ({ ...change })) }));
|
|
19066
|
+
state.pendingChanges = [...task.pendingChanges];
|
|
19067
|
+
state.lastInstruction = task.lastInstruction;
|
|
19068
|
+
state.selectionId = task.selectionId;
|
|
19069
|
+
state.screenshotPromise = Promise.resolve({});
|
|
19070
|
+
hideReview();
|
|
19071
|
+
clearAgentLog();
|
|
19072
|
+
loadAgentLog(task.activity);
|
|
19073
|
+
renderChatThread();
|
|
19074
|
+
const dom = getDOM();
|
|
19075
|
+
if (task.element?.isConnected) {
|
|
19076
|
+
state.selected = task.element;
|
|
19077
|
+
state.elementRegistry.set(elementKey(task.element), task.element);
|
|
19078
|
+
updateSelectedVisual();
|
|
19079
|
+
updateLockChip();
|
|
19080
|
+
if (promptElement) promptElement.textContent = getElementLabel(task.element);
|
|
19081
|
+
positionPrompt(task.element);
|
|
19082
|
+
} else {
|
|
19083
|
+
state.selected = null;
|
|
19084
|
+
dom.selectedBox.style.display = "none";
|
|
19085
|
+
dom.label.style.display = "none";
|
|
19086
|
+
if (promptElement) promptElement.textContent = "Agent task";
|
|
19087
|
+
if (promptEl) {
|
|
19088
|
+
promptEl.style.left = `${Math.max(12, (window.innerWidth - 360) / 2)}px`;
|
|
19089
|
+
promptEl.style.top = `${Math.max(12, (window.innerHeight - 200) / 2)}px`;
|
|
19090
|
+
}
|
|
19091
|
+
updateLockChip();
|
|
19092
|
+
}
|
|
19093
|
+
if (promptEl) promptEl.classList.add("visible");
|
|
19094
|
+
setSelectMode(false);
|
|
19095
|
+
if (task.status === "review" && state.pendingChanges.length) showReview(state.pendingChanges, task.message);
|
|
19096
|
+
setAgentStatus(task.status, task.message, task.detail, task.id, false);
|
|
19097
|
+
requestAnimationFrame(() => promptInput?.focus());
|
|
19098
|
+
}
|
|
18929
19099
|
function showReview(changes, summary) {
|
|
18930
19100
|
if (!reviewPanel) return;
|
|
18931
19101
|
const subtitle = reviewPanel.querySelector(".lasso-review-subtitle");
|
|
@@ -18959,7 +19129,7 @@
|
|
|
18959
19129
|
reviewPanel.style.top = `${top}px`;
|
|
18960
19130
|
}
|
|
18961
19131
|
function closeReview() {
|
|
18962
|
-
|
|
19132
|
+
hideReview();
|
|
18963
19133
|
resetAgentState();
|
|
18964
19134
|
}
|
|
18965
19135
|
function positionPrompt(el) {
|
|
@@ -18990,11 +19160,10 @@
|
|
|
18990
19160
|
promptEl.classList.remove("visible");
|
|
18991
19161
|
if (promptInput) promptInput.value = "";
|
|
18992
19162
|
sendPresenceUpdate({ selection: null });
|
|
18993
|
-
if (state.heldLockElement) releaseHeldLock();
|
|
18994
|
-
updateLockChip();
|
|
18995
19163
|
renderRemoteBoxes();
|
|
18996
19164
|
renderComments();
|
|
18997
19165
|
state.selected = null;
|
|
19166
|
+
updateLockChip();
|
|
18998
19167
|
getDOM().selectedBox.style.display = "none";
|
|
18999
19168
|
getDOM().label.style.display = "none";
|
|
19000
19169
|
if (reenter) {
|
|
@@ -19004,18 +19173,19 @@
|
|
|
19004
19173
|
async function handleSend(event) {
|
|
19005
19174
|
event.preventDefault();
|
|
19006
19175
|
event.stopPropagation();
|
|
19007
|
-
|
|
19176
|
+
const selectedElement = state.selected;
|
|
19177
|
+
if (!selectedElement || !promptInput || !sendButton) return;
|
|
19008
19178
|
const instruction = promptInput.value.trim() || (sendButton.dataset.state === "retry" ? state.lastInstruction : "");
|
|
19009
19179
|
if (!instruction) {
|
|
19010
19180
|
promptInput.focus();
|
|
19011
19181
|
return;
|
|
19012
19182
|
}
|
|
19013
|
-
clearAgentLog();
|
|
19014
19183
|
requestAgentNotificationPermission();
|
|
19015
19184
|
const isQuestion = /^(hi|hello|hey|thanks|thank you|what|why|how|when|where|who|which|is|are|does|do|can|could|would|should|tell me|explain|describe)\b/i.test(instruction) || /\?$/.test(instruction);
|
|
19016
19185
|
const isExplicitEdit = /\b(change|edit|update|make|add|remove|delete|fix|replace|turn|convert|style|restyle|move|rename|implement|build|create|increase|decrease|hide|show|align|resize|set|enable|disable)\b/i.test(instruction);
|
|
19017
19186
|
const wantsAnswer = isQuestion && !/\b(can|could|would|please)\s+you\s+(change|edit|update|add|fix|make)\b/i.test(instruction) || !isExplicitEdit && !isQuestion;
|
|
19018
|
-
|
|
19187
|
+
const bridgeSocket = state.bridgeSocket;
|
|
19188
|
+
if (!bridgeSocket || bridgeSocket.readyState !== WebSocket.OPEN) {
|
|
19019
19189
|
setAgentStatus(
|
|
19020
19190
|
"error",
|
|
19021
19191
|
"The Lasso agent bridge is not connected. Start Lasso with your dev server and try again."
|
|
@@ -19023,41 +19193,54 @@
|
|
|
19023
19193
|
return;
|
|
19024
19194
|
}
|
|
19025
19195
|
if (!wantsAnswer) {
|
|
19026
|
-
const ownershipGranted = await acquireOwnership(
|
|
19196
|
+
const ownershipGranted = await acquireOwnership(selectedElement);
|
|
19027
19197
|
if (!ownershipGranted) return;
|
|
19028
19198
|
}
|
|
19029
19199
|
if (!wantsAnswer && state.collabSocket?.connected && state.collabJoined) {
|
|
19030
19200
|
collabEmit("collab:action", {
|
|
19031
19201
|
sessionId: state.collabProjectId,
|
|
19032
19202
|
status: "preparing",
|
|
19033
|
-
elementId: elementKey(
|
|
19203
|
+
elementId: elementKey(selectedElement),
|
|
19034
19204
|
summary: `Edits for ${instruction.slice(0, 80)}`
|
|
19035
19205
|
});
|
|
19036
19206
|
}
|
|
19207
|
+
const selectionId = state.selectionId;
|
|
19208
|
+
const model = state.selectedModel;
|
|
19209
|
+
const screenshotPromise = state.screenshotPromise;
|
|
19037
19210
|
appendChat("user", instruction);
|
|
19038
|
-
const
|
|
19039
|
-
|
|
19211
|
+
const messages = state.chatHistory.map((message) => ({ ...message }));
|
|
19212
|
+
const changesHistory = state.changesHistory.map((entry) => ({ ...entry, changes: entry.changes.map((change) => ({ ...change })) }));
|
|
19213
|
+
const task = createAgentTask(instruction, messages, changesHistory, selectedElement, selectionId);
|
|
19214
|
+
updateAgentTask(task.id, { status: "thinking", message: "Thinking\u2026", activity: [...task.activity, "Thinking\u2026"] });
|
|
19215
|
+
resetPromptSession();
|
|
19216
|
+
state.promptTaskId = task.id;
|
|
19040
19217
|
state.lastInstruction = instruction;
|
|
19041
|
-
|
|
19042
|
-
const
|
|
19043
|
-
const computed = getComputedStyle(state.selected);
|
|
19218
|
+
const rect = selectedElement.getBoundingClientRect();
|
|
19219
|
+
const computed = getComputedStyle(selectedElement);
|
|
19044
19220
|
const attributes = Object.fromEntries(
|
|
19045
|
-
Array.from(
|
|
19221
|
+
Array.from(selectedElement.attributes).map((attr) => [attr.name, attr.value])
|
|
19046
19222
|
);
|
|
19047
19223
|
const needsVisualContext = /\b(look|visual|appearance|color|colour|background|image|icon|spacing|layout|position|align|responsive|style|restyle|font|size)\b/i.test(instruction);
|
|
19048
|
-
const screenshots = needsVisualContext
|
|
19049
|
-
|
|
19224
|
+
const screenshots = needsVisualContext ? await captureElementScreenshot(selectedElement) : await screenshotPromise;
|
|
19225
|
+
if (bridgeSocket.readyState !== WebSocket.OPEN) {
|
|
19226
|
+
const message = "The Lasso agent bridge disconnected before the task could start.";
|
|
19227
|
+
updateAgentTask(task.id, { status: "error", message });
|
|
19228
|
+
appendChat("error", message, task.id);
|
|
19229
|
+
if (!wantsAnswer) releaseHeldLock(elementKey(selectedElement));
|
|
19230
|
+
return;
|
|
19231
|
+
}
|
|
19232
|
+
bridgeSocket.send(
|
|
19050
19233
|
JSON.stringify({
|
|
19051
19234
|
type: wantsAnswer ? "ask" : "edit",
|
|
19052
19235
|
taskId: task.id,
|
|
19053
19236
|
question: wantsAnswer ? instruction : void 0,
|
|
19054
19237
|
instruction,
|
|
19055
|
-
messages
|
|
19056
|
-
changesHistory
|
|
19057
|
-
model:
|
|
19058
|
-
provider:
|
|
19238
|
+
messages,
|
|
19239
|
+
changesHistory,
|
|
19240
|
+
model: model.id,
|
|
19241
|
+
provider: model.provider,
|
|
19059
19242
|
context: {
|
|
19060
|
-
selectionId
|
|
19243
|
+
selectionId,
|
|
19061
19244
|
position: {
|
|
19062
19245
|
top: rect.top,
|
|
19063
19246
|
left: rect.left,
|
|
@@ -19088,18 +19271,18 @@
|
|
|
19088
19271
|
screenshots
|
|
19089
19272
|
},
|
|
19090
19273
|
element: {
|
|
19091
|
-
tag:
|
|
19092
|
-
group: getElementGroup(
|
|
19093
|
-
label: getElementLabel(
|
|
19094
|
-
html:
|
|
19095
|
-
sourceHint:
|
|
19274
|
+
tag: selectedElement.tagName.toLowerCase(),
|
|
19275
|
+
group: getElementGroup(selectedElement),
|
|
19276
|
+
label: getElementLabel(selectedElement),
|
|
19277
|
+
html: selectedElement.outerHTML.slice(0, 6e3),
|
|
19278
|
+
sourceHint: selectedElement.getAttribute("data-source") || selectedElement.getAttribute("data-lasso-source") || getSourceHint(selectedElement)
|
|
19096
19279
|
}
|
|
19097
19280
|
})
|
|
19098
19281
|
);
|
|
19099
19282
|
}
|
|
19100
19283
|
function openPromptForSelected(selected) {
|
|
19101
19284
|
if (!promptEl || !promptElement) return;
|
|
19102
|
-
|
|
19285
|
+
resetPromptSession();
|
|
19103
19286
|
promptElement.textContent = getElementLabel(selected);
|
|
19104
19287
|
positionPrompt(selected);
|
|
19105
19288
|
promptEl.classList.add("visible");
|
|
@@ -19838,7 +20021,7 @@
|
|
|
19838
20021
|
state.hovered = el;
|
|
19839
20022
|
updateHoverVisual(state.hovered);
|
|
19840
20023
|
}
|
|
19841
|
-
function
|
|
20024
|
+
function updateSelectedVisual() {
|
|
19842
20025
|
const dom = getDOM();
|
|
19843
20026
|
if (!state.selected) {
|
|
19844
20027
|
dom.selectedBox.style.display = "none";
|
|
@@ -20559,47 +20742,85 @@
|
|
|
20559
20742
|
if (message.type === "git_commit_message") {
|
|
20560
20743
|
setGeneratedCommitMessage(message.message || "", message.error);
|
|
20561
20744
|
}
|
|
20745
|
+
if (message.type === "git_progress" && message.message) {
|
|
20746
|
+
setGitMessage(message.message);
|
|
20747
|
+
}
|
|
20562
20748
|
if (message.type === "agent_status" && message.status && message.message) {
|
|
20749
|
+
const taskId2 = message.taskId;
|
|
20750
|
+
const task = taskId2 ? getAgentTask(taskId2) : void 0;
|
|
20563
20751
|
const taskStatus = message.status === "error" ? "error" : message.status === "stopped" ? "stopped" : message.status;
|
|
20564
|
-
|
|
20565
|
-
|
|
20566
|
-
|
|
20752
|
+
if (task) {
|
|
20753
|
+
const patch = {
|
|
20754
|
+
status: taskStatus,
|
|
20755
|
+
message: message.message,
|
|
20756
|
+
detail: message.detail
|
|
20757
|
+
};
|
|
20758
|
+
if (message.status === "review" && message.changes) {
|
|
20759
|
+
patch.changes = message.changes;
|
|
20760
|
+
patch.pendingChanges = message.changes;
|
|
20761
|
+
recordTaskChangeHistory(task.id, message.message, message.changes);
|
|
20762
|
+
}
|
|
20763
|
+
updateAgentTask(task.id, patch);
|
|
20764
|
+
recordTaskActivity(task.id, message.detail || message.message);
|
|
20765
|
+
}
|
|
20766
|
+
if (message.status === "review") {
|
|
20767
|
+
appendChat("assistant", message.message, taskId2);
|
|
20768
|
+
if (message.changes?.length) void notifyAgent("Review requested", message.message);
|
|
20769
|
+
} else if (message.status === "error" || message.status === "stopped") {
|
|
20770
|
+
appendChat(message.status === "error" ? "error" : "assistant", message.message, taskId2);
|
|
20771
|
+
if (task?.element) releaseHeldLock(elementKey(task.element));
|
|
20772
|
+
void notifyAgent(message.status === "error" ? "Agent error" : "Agent stopped", message.message);
|
|
20773
|
+
}
|
|
20774
|
+
if (taskId2 && taskId2 !== state.promptTaskId) return;
|
|
20775
|
+
setAgentStatus(message.status, message.message, message.detail, taskId2, false);
|
|
20567
20776
|
setDragCardStatus(message.status, message.message);
|
|
20568
20777
|
if (message.status === "review" && message.changes?.length) {
|
|
20569
|
-
|
|
20570
|
-
state.pendingChanges = message.changes;
|
|
20571
|
-
state.changesHistory.push({
|
|
20572
|
-
summary: message.message,
|
|
20573
|
-
changes: message.changes,
|
|
20574
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
20575
|
-
});
|
|
20778
|
+
if (task) state.changesHistory = task.changesHistory.map((entry) => ({ ...entry, changes: entry.changes.map((change) => ({ ...change })) }));
|
|
20779
|
+
state.pendingChanges = [...message.changes];
|
|
20576
20780
|
showReview(message.changes, message.message);
|
|
20577
20781
|
}
|
|
20578
20782
|
}
|
|
20579
20783
|
if (message.type === "assistant_message" && message.message) {
|
|
20580
|
-
|
|
20581
|
-
|
|
20784
|
+
const taskId2 = message.taskId;
|
|
20785
|
+
const task = taskId2 ? getAgentTask(taskId2) : void 0;
|
|
20786
|
+
if (task) {
|
|
20787
|
+
updateAgentTask(task.id, { status: "complete", message: "Complete", response: message.message });
|
|
20788
|
+
recordTaskActivity(task.id, "Agent complete");
|
|
20789
|
+
}
|
|
20790
|
+
appendChat("assistant", message.message, taskId2);
|
|
20791
|
+
if (taskId2 && taskId2 !== state.promptTaskId) {
|
|
20792
|
+
void notifyAgent("Agent complete", message.message);
|
|
20793
|
+
return;
|
|
20794
|
+
}
|
|
20582
20795
|
void notifyAgent("Agent complete", message.message);
|
|
20583
|
-
appendChat("assistant", message.message);
|
|
20584
20796
|
resetAgentState();
|
|
20585
20797
|
}
|
|
20586
20798
|
if (message.type === "applied" || message.type === "undone") {
|
|
20587
|
-
|
|
20588
|
-
|
|
20589
|
-
|
|
20590
|
-
|
|
20591
|
-
|
|
20799
|
+
const taskId2 = message.taskId;
|
|
20800
|
+
const task = taskId2 ? getAgentTask(taskId2) : void 0;
|
|
20801
|
+
if (task) {
|
|
20802
|
+
updateAgentTask(task.id, { status: "complete", message: message.message || "Done.", changes: [], pendingChanges: [] });
|
|
20803
|
+
recordTaskActivity(task.id, message.message || "Done.");
|
|
20804
|
+
}
|
|
20805
|
+
const isPromptTask = !taskId2 || taskId2 === state.promptTaskId;
|
|
20806
|
+
const result = message.message || "Done.";
|
|
20807
|
+
void notifyAgent(message.type === "applied" ? "Changes applied" : "Change undone", result);
|
|
20808
|
+
appendChat("assistant", result, taskId2);
|
|
20809
|
+
if (task?.element) releaseHeldLock(elementKey(task.element));
|
|
20810
|
+
else if (isPromptTask && state.selected) releaseHeldLock(elementKey(state.selected));
|
|
20592
20811
|
if (state.collabSocket?.connected && state.collabJoined) {
|
|
20593
20812
|
collabEmit("collab:action", {
|
|
20594
20813
|
sessionId: state.collabProjectId,
|
|
20595
20814
|
status: "idle",
|
|
20596
|
-
elementId: state.selected ? elementKey(state.selected) : void 0,
|
|
20597
|
-
summary:
|
|
20815
|
+
elementId: task?.element ? elementKey(task.element) : state.selected ? elementKey(state.selected) : void 0,
|
|
20816
|
+
summary: result || (message.type === "undone" ? "Undid the last change" : "Applied the change")
|
|
20598
20817
|
});
|
|
20599
20818
|
}
|
|
20600
|
-
|
|
20601
|
-
|
|
20602
|
-
|
|
20819
|
+
if (isPromptTask) {
|
|
20820
|
+
closeReview();
|
|
20821
|
+
resetDrag(false);
|
|
20822
|
+
state.pendingChanges = [];
|
|
20823
|
+
}
|
|
20603
20824
|
}
|
|
20604
20825
|
} catch {
|
|
20605
20826
|
console.warn("[lasso] Invalid bridge message");
|
|
@@ -20641,7 +20862,7 @@
|
|
|
20641
20862
|
renderCommentPins();
|
|
20642
20863
|
}
|
|
20643
20864
|
if (state.selected) {
|
|
20644
|
-
|
|
20865
|
+
updateSelectedVisual();
|
|
20645
20866
|
if (!state.promptDragged) {
|
|
20646
20867
|
positionPrompt(state.selected);
|
|
20647
20868
|
}
|
|
@@ -20683,13 +20904,8 @@
|
|
|
20683
20904
|
updateLockChip();
|
|
20684
20905
|
sendPresenceUpdate({});
|
|
20685
20906
|
state.promptDragged = false;
|
|
20686
|
-
state.lastInstruction = "";
|
|
20687
|
-
state.selectionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
20688
|
-
state.chatHistory = [];
|
|
20689
|
-
state.changesHistory = [];
|
|
20690
|
-
state.screenshotPromise = Promise.resolve({});
|
|
20691
20907
|
dom.hoverBox.style.display = "none";
|
|
20692
|
-
|
|
20908
|
+
updateSelectedVisual();
|
|
20693
20909
|
openPromptForSelected(target);
|
|
20694
20910
|
},
|
|
20695
20911
|
true
|
package/package.json
CHANGED