@lasso-ai/cli 1.0.12 → 1.0.13
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.d.ts +1 -1
- package/dist/cli/agent.js +65 -35
- package/dist/cli/bridge.d.ts +1 -0
- package/dist/cli/bridge.js +24 -7
- package/dist/overlay.js +240 -57
- package/package.json +1 -1
package/dist/cli/agent.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export type AgentConfig = {
|
|
|
44
44
|
baseUrl?: string;
|
|
45
45
|
};
|
|
46
46
|
export type LocalAgent = "claude-code" | "codex" | "opencode";
|
|
47
|
-
export type AgentProgress = (message: string) => void;
|
|
47
|
+
export type AgentProgress = (message: string, detail?: string) => void;
|
|
48
48
|
export type AgentAnswer = {
|
|
49
49
|
question: string;
|
|
50
50
|
context?: AgentInput["context"];
|
package/dist/cli/agent.js
CHANGED
|
@@ -27,7 +27,11 @@ async function detectLocalAgents() {
|
|
|
27
27
|
}
|
|
28
28
|
const ignored = new Set(["node_modules", ".git", ".next", "dist", "build", ".turbo"]);
|
|
29
29
|
const sourceExtensions = /\.(tsx?|jsx?|vue|svelte|css|scss|html)$/i;
|
|
30
|
+
const sourceFileCache = new Map();
|
|
30
31
|
async function sourceFiles(directory) {
|
|
32
|
+
const cached = sourceFileCache.get(directory);
|
|
33
|
+
if (cached && cached.expiresAt > Date.now())
|
|
34
|
+
return cached.files;
|
|
31
35
|
const entries = await promises_1.default.readdir(directory, { withFileTypes: true });
|
|
32
36
|
const files = [];
|
|
33
37
|
for (const entry of entries) {
|
|
@@ -38,28 +42,43 @@ async function sourceFiles(directory) {
|
|
|
38
42
|
files.push(...(await sourceFiles(fullPath)));
|
|
39
43
|
else if (sourceExtensions.test(entry.name))
|
|
40
44
|
files.push(fullPath);
|
|
41
|
-
if (files.length >=
|
|
45
|
+
if (files.length >= 40)
|
|
42
46
|
break;
|
|
43
47
|
}
|
|
48
|
+
sourceFileCache.set(directory, { expiresAt: Date.now() + 5000, files });
|
|
44
49
|
return files;
|
|
45
50
|
}
|
|
46
51
|
async function contextFor(cwd, element) {
|
|
47
|
-
const files = await sourceFiles(cwd);
|
|
48
52
|
const needle = element.sourceHint || element.label.replace(/^[^.#]+[.#]?/, "");
|
|
49
|
-
const
|
|
53
|
+
const hintedPath = element.sourceHint?.split(":")[0];
|
|
54
|
+
const sourceFile = hintedPath ? node_path_1.default.basename(hintedPath) : "";
|
|
55
|
+
if (hintedPath) {
|
|
56
|
+
const candidate = node_path_1.default.isAbsolute(hintedPath) ? hintedPath : node_path_1.default.resolve(cwd, hintedPath);
|
|
57
|
+
try {
|
|
58
|
+
const content = await promises_1.default.readFile(candidate, "utf8");
|
|
59
|
+
return `FILE: ${node_path_1.default.relative(cwd, candidate)}\n${content.slice(0, 16000)}`;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Fall back to the indexed search when the runtime source hint is stale.
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const files = await sourceFiles(cwd);
|
|
50
66
|
const snippets = [];
|
|
51
|
-
|
|
52
|
-
if (snippets.length >= 8)
|
|
53
|
-
break;
|
|
67
|
+
const results = await Promise.all(files.map(async (file) => {
|
|
54
68
|
try {
|
|
55
69
|
const content = await promises_1.default.readFile(file, "utf8");
|
|
56
70
|
if (!needle || (sourceFile && file.endsWith(sourceFile)) || content.includes(needle) || content.includes(element.label)) {
|
|
57
|
-
|
|
71
|
+
return `FILE: ${node_path_1.default.relative(cwd, file)}\n${content.slice(0, 8000)}`;
|
|
58
72
|
}
|
|
59
73
|
}
|
|
60
74
|
catch {
|
|
61
75
|
// A file can disappear while a dev server is rebuilding; skip it.
|
|
62
76
|
}
|
|
77
|
+
return null;
|
|
78
|
+
}));
|
|
79
|
+
for (const result of results) {
|
|
80
|
+
if (result && snippets.length < 6)
|
|
81
|
+
snippets.push(result);
|
|
63
82
|
}
|
|
64
83
|
return snippets.join("\n\n---\n\n");
|
|
65
84
|
}
|
|
@@ -122,86 +141,93 @@ function extractLocalAgentText(raw, provider) {
|
|
|
122
141
|
}
|
|
123
142
|
return texts.at(-1) || raw;
|
|
124
143
|
}
|
|
125
|
-
/** Truncate a detail string to a readable length. */
|
|
126
144
|
function snippet(value, max = 80) {
|
|
127
145
|
const s = String(value ?? "").trim().replace(/\s+/g, " ");
|
|
128
146
|
return s.length > max ? `${s.slice(0, max)}…` : s;
|
|
129
147
|
}
|
|
148
|
+
function progressEvent(message, detail) {
|
|
149
|
+
const value = detail == null ? "" : String(detail).trim();
|
|
150
|
+
return value ? { message, detail: value } : { message };
|
|
151
|
+
}
|
|
130
152
|
function progressFromLine(raw, provider) {
|
|
131
153
|
try {
|
|
132
154
|
const event = JSON.parse(raw);
|
|
133
155
|
const item = event.item;
|
|
134
156
|
if (provider === "claude-code") {
|
|
135
157
|
if (event.type === "system")
|
|
136
|
-
return "Claude Code connected";
|
|
158
|
+
return progressEvent("Claude Code connected");
|
|
137
159
|
// tool_use blocks inside assistant messages
|
|
138
160
|
const toolBlock = event.message?.content?.find?.((p) => p.type === "tool_use");
|
|
139
161
|
if (toolBlock) {
|
|
140
162
|
const toolName = toolBlock.name || "tool";
|
|
141
163
|
const inp = toolBlock.input;
|
|
142
164
|
const detail = inp?.file_path ?? inp?.path ?? inp?.command ?? inp?.query ?? inp?.url ?? "";
|
|
143
|
-
return detail
|
|
165
|
+
return progressEvent(detail
|
|
144
166
|
? `Claude Code · ${toolName} ${snippet(detail)}`
|
|
145
|
-
: `Claude Code · ${toolName}
|
|
167
|
+
: `Claude Code · ${toolName}`, detail);
|
|
146
168
|
}
|
|
147
169
|
// thinking blocks inside assistant messages
|
|
148
170
|
const thinkBlock = event.message?.content?.find?.((p) => p.type === "thinking");
|
|
149
171
|
if (thinkBlock?.thinking) {
|
|
150
|
-
return `Claude Code · ${snippet(thinkBlock.thinking
|
|
172
|
+
return progressEvent(`Claude Code · ${snippet(thinkBlock.thinking)}`, thinkBlock.thinking);
|
|
151
173
|
}
|
|
152
174
|
// top-level tool event fields (stream-json verbose format)
|
|
153
175
|
const tool = event.tool_name || event.name || event.tool?.name;
|
|
154
176
|
if (tool) {
|
|
155
177
|
const inp = event.tool_input;
|
|
156
178
|
const detail = inp?.file_path ?? inp?.path ?? inp?.command ?? inp?.query ?? inp?.url ?? "";
|
|
157
|
-
return detail
|
|
179
|
+
return progressEvent(detail
|
|
158
180
|
? `Claude Code · ${tool} ${snippet(detail)}`
|
|
159
|
-
: `Claude Code · ${tool}
|
|
181
|
+
: `Claude Code · ${tool}`, detail);
|
|
182
|
+
}
|
|
183
|
+
if (event.type === "result" || event.result) {
|
|
184
|
+
return progressEvent("Claude Code · preparing the proposal");
|
|
160
185
|
}
|
|
161
|
-
if (event.type === "result" || event.result)
|
|
162
|
-
return "Claude Code · preparing the proposal";
|
|
163
186
|
if (event.type === "assistant")
|
|
164
|
-
return "Claude Code · reasoning about the change";
|
|
187
|
+
return progressEvent("Claude Code · reasoning about the change");
|
|
165
188
|
}
|
|
166
189
|
else if (provider === "codex") {
|
|
167
190
|
const type = item?.type || event.type || "";
|
|
168
191
|
if (type === "command_execution" || type === "command_execution_output") {
|
|
169
192
|
const cmd = item?.command || event.command || "";
|
|
170
|
-
return cmd ? `Codex · Bash ${snippet(cmd)}` : "Codex · running a command";
|
|
193
|
+
return progressEvent(cmd ? `Codex · Bash ${snippet(cmd)}` : "Codex · running a command", cmd);
|
|
171
194
|
}
|
|
172
195
|
if (type === "file_read" || type === "read_file") {
|
|
173
196
|
const fp = item?.path || event.path || "";
|
|
174
|
-
return fp ? `Codex · Read ${snippet(fp)}` : "Codex · reading a file";
|
|
197
|
+
return progressEvent(fp ? `Codex · Read ${snippet(fp)}` : "Codex · reading a file", fp);
|
|
198
|
+
}
|
|
199
|
+
if (type === "agent_message" || type === "message") {
|
|
200
|
+
return progressEvent("Codex · drafting the proposal");
|
|
175
201
|
}
|
|
176
|
-
if (type === "agent_message" || type === "message")
|
|
177
|
-
return "Codex · drafting the proposal";
|
|
178
202
|
if (type === "reasoning") {
|
|
179
203
|
const text = item?.content || event.content || "";
|
|
180
|
-
return text ? `Codex · ${snippet(text
|
|
204
|
+
return progressEvent(text ? `Codex · ${snippet(text)}` : "Codex · reasoning", text);
|
|
205
|
+
}
|
|
206
|
+
if (type === "turn.started" || type === "turn_start") {
|
|
207
|
+
return progressEvent("Codex · starting a turn");
|
|
208
|
+
}
|
|
209
|
+
if (type === "turn.completed" || type === "turn_complete") {
|
|
210
|
+
return progressEvent("Codex · preparing the proposal");
|
|
181
211
|
}
|
|
182
|
-
if (type === "turn.started" || type === "turn_start")
|
|
183
|
-
return "Codex · starting a turn";
|
|
184
|
-
if (type === "turn.completed" || type === "turn_complete")
|
|
185
|
-
return "Codex · preparing the proposal";
|
|
186
212
|
}
|
|
187
213
|
else if (provider === "opencode") {
|
|
188
214
|
const part = event.part;
|
|
189
215
|
if (event.type === "step-start")
|
|
190
|
-
return "OpenCode · starting a step";
|
|
216
|
+
return progressEvent("OpenCode · starting a step");
|
|
191
217
|
if (part?.type === "tool") {
|
|
192
218
|
const toolName = part.tool || "tool";
|
|
193
219
|
const inp = part.input;
|
|
194
220
|
const detail = inp?.file_path ?? inp?.path ?? inp?.command ?? inp?.query ?? inp?.url ?? "";
|
|
195
|
-
return detail
|
|
221
|
+
return progressEvent(detail
|
|
196
222
|
? `OpenCode · ${toolName} ${snippet(detail)}`
|
|
197
|
-
: `OpenCode · ${toolName}
|
|
223
|
+
: `OpenCode · ${toolName}`, detail);
|
|
198
224
|
}
|
|
199
225
|
if (part?.type === "text") {
|
|
200
226
|
const text = part.text || "";
|
|
201
|
-
return text ? `OpenCode · ${snippet(text
|
|
227
|
+
return progressEvent(text ? `OpenCode · ${snippet(text)}` : "OpenCode · drafting the response", text);
|
|
202
228
|
}
|
|
203
229
|
if (event.type === "step-finish")
|
|
204
|
-
return "OpenCode · finalizing the response";
|
|
230
|
+
return progressEvent("OpenCode · finalizing the response");
|
|
205
231
|
}
|
|
206
232
|
}
|
|
207
233
|
catch {
|
|
@@ -253,7 +279,7 @@ async function proposeWithLocalAgent(cwd, instruction, context, config, signal,
|
|
|
253
279
|
stdout += `${line}\n`;
|
|
254
280
|
const progress = progressFromLine(line, config.provider);
|
|
255
281
|
if (progress)
|
|
256
|
-
onProgress?.(progress);
|
|
282
|
+
onProgress?.(progress.message, progress.detail);
|
|
257
283
|
}
|
|
258
284
|
};
|
|
259
285
|
child.stdout.on("data", consume);
|
|
@@ -273,7 +299,7 @@ async function proposeWithLocalAgent(cwd, instruction, context, config, signal,
|
|
|
273
299
|
stdout += pending;
|
|
274
300
|
const progress = progressFromLine(pending, config.provider);
|
|
275
301
|
if (progress)
|
|
276
|
-
onProgress?.(progress);
|
|
302
|
+
onProgress?.(progress.message, progress.detail);
|
|
277
303
|
}
|
|
278
304
|
if (exitCode !== 0)
|
|
279
305
|
throw new Error(localAgentError(command, stderr, exitCode));
|
|
@@ -360,7 +386,7 @@ async function answerQuestion(cwd, input, config, signal, onProgress) {
|
|
|
360
386
|
output += `${line}\n`;
|
|
361
387
|
const progress = progressFromLine(line, config.provider);
|
|
362
388
|
if (progress)
|
|
363
|
-
onProgress?.(progress);
|
|
389
|
+
onProgress?.(progress.message, progress.detail);
|
|
364
390
|
}
|
|
365
391
|
};
|
|
366
392
|
child.stdout.on("data", consume);
|
|
@@ -371,8 +397,12 @@ async function answerQuestion(cwd, input, config, signal, onProgress) {
|
|
|
371
397
|
child.once("error", reject);
|
|
372
398
|
child.once("close", (status) => resolve(status ?? 1));
|
|
373
399
|
});
|
|
374
|
-
if (pending.trim())
|
|
400
|
+
if (pending.trim()) {
|
|
375
401
|
output += pending;
|
|
402
|
+
const progress = progressFromLine(pending, config.provider);
|
|
403
|
+
if (progress)
|
|
404
|
+
onProgress?.(progress.message, progress.detail);
|
|
405
|
+
}
|
|
376
406
|
if (code !== 0)
|
|
377
407
|
throw new Error(localAgentError(command, stderr, code));
|
|
378
408
|
return extractLocalAgentText(output, config.provider).trim();
|
package/dist/cli/bridge.d.ts
CHANGED
package/dist/cli/bridge.js
CHANGED
|
@@ -65,13 +65,30 @@ function occurrenceCount(content, needle) {
|
|
|
65
65
|
from = index + needle.length;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
+
function escapeRegExp(value) {
|
|
69
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
70
|
+
}
|
|
71
|
+
function whitespaceEquivalentRange(content, oldString) {
|
|
72
|
+
const trimmed = oldString.trim();
|
|
73
|
+
if (!trimmed)
|
|
74
|
+
return null;
|
|
75
|
+
const pattern = trimmed.split(/\s+/).map(escapeRegExp).join("\\s+");
|
|
76
|
+
const matches = Array.from(content.matchAll(new RegExp(pattern, "g")));
|
|
77
|
+
if (matches.length !== 1 || matches[0].index === undefined)
|
|
78
|
+
return null;
|
|
79
|
+
const start = matches[0].index;
|
|
80
|
+
return { start, end: start + matches[0][0].length };
|
|
81
|
+
}
|
|
68
82
|
function prepareChange(content, change) {
|
|
69
83
|
const lineEnding = fileLineEnding(content);
|
|
70
84
|
const oldString = withLineEnding(change.oldString, lineEnding);
|
|
71
85
|
const newString = withLineEnding(change.newString, lineEnding);
|
|
72
86
|
const matches = occurrenceCount(content, oldString);
|
|
73
87
|
if (matches === 0) {
|
|
74
|
-
|
|
88
|
+
const range = whitespaceEquivalentRange(content, oldString);
|
|
89
|
+
if (range)
|
|
90
|
+
return { ...range, oldString: content.slice(range.start, range.end), newString };
|
|
91
|
+
throw new Error(`Could not safely apply ${change.filePath}. The source changed after the suggestion was generated. Regenerate the review so it uses the current source.`);
|
|
75
92
|
}
|
|
76
93
|
if (matches > 1) {
|
|
77
94
|
throw new Error(`Could not safely apply ${change.filePath}. The selected code is not unique (${matches} matches).`);
|
|
@@ -244,9 +261,9 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
244
261
|
const selectedConfig = localProvider
|
|
245
262
|
? { provider: cliProvider, model: msg.model }
|
|
246
263
|
: { ...agentConfig, provider: (msg.provider || agentConfig.provider), model: msg.model };
|
|
247
|
-
void (0, agent_1.answerQuestion)(cwd, { question: msg.question, context: msg.context, element: msg.element, messages: msg.messages }, selectedConfig, controller.signal, (message) => {
|
|
264
|
+
void (0, agent_1.answerQuestion)(cwd, { question: msg.question, context: msg.context, element: msg.element, messages: msg.messages }, selectedConfig, controller.signal, (message, detail) => {
|
|
248
265
|
if (!controller.signal.aborted && socket.readyState === socket.OPEN)
|
|
249
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "working", message }));
|
|
266
|
+
socket.send(JSON.stringify({ type: "agent_status", status: "working", message, detail }));
|
|
250
267
|
}).then((answer) => {
|
|
251
268
|
if (!controller.signal.aborted)
|
|
252
269
|
socket.send(JSON.stringify({ type: "assistant_message", message: answer }));
|
|
@@ -275,9 +292,9 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
275
292
|
const selectedConfig = localProvider
|
|
276
293
|
? { provider: cliProvider, model: msg.model }
|
|
277
294
|
: { ...agentConfig, provider: (msg.provider || agentConfig.provider), model: msg.model };
|
|
278
|
-
void (0, agent_1.proposeChanges)(cwd, msg, selectedConfig, controller.signal, (message) => {
|
|
295
|
+
void (0, agent_1.proposeChanges)(cwd, msg, selectedConfig, controller.signal, (message, detail) => {
|
|
279
296
|
if (!controller.signal.aborted && socket.readyState === socket.OPEN) {
|
|
280
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "working", message }));
|
|
297
|
+
socket.send(JSON.stringify({ type: "agent_status", status: "working", message, detail }));
|
|
281
298
|
}
|
|
282
299
|
})
|
|
283
300
|
.then((proposal) => {
|
|
@@ -320,9 +337,9 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
320
337
|
activeAgentController?.abort();
|
|
321
338
|
activeAgentController = controller;
|
|
322
339
|
socket.send(JSON.stringify({ type: "agent_status", status: "thinking", message: "Generating a commit message…" }));
|
|
323
|
-
void getGitState(cwd).then((git) => (0, agent_1.generateCommitMessage)(cwd, git.status || [], selectedConfig, controller.signal, (message) => {
|
|
340
|
+
void getGitState(cwd).then((git) => (0, agent_1.generateCommitMessage)(cwd, git.status || [], selectedConfig, controller.signal, (message, detail) => {
|
|
324
341
|
if (!controller.signal.aborted && socket.readyState === socket.OPEN)
|
|
325
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "working", message }));
|
|
342
|
+
socket.send(JSON.stringify({ type: "agent_status", status: "working", message, detail }));
|
|
326
343
|
})).then((message) => {
|
|
327
344
|
if (!controller.signal.aborted)
|
|
328
345
|
socket.send(JSON.stringify({ type: "git_commit_message", message }));
|
package/dist/overlay.js
CHANGED
|
@@ -9830,6 +9830,16 @@
|
|
|
9830
9830
|
background: rgba(242, 139, 130, 0.12);
|
|
9831
9831
|
}
|
|
9832
9832
|
|
|
9833
|
+
.lasso-chat-message code {
|
|
9834
|
+
padding: 1px 4px;
|
|
9835
|
+
border-radius: 3px;
|
|
9836
|
+
background: var(--lo-surface-2);
|
|
9837
|
+
color: #a5b4fc;
|
|
9838
|
+
font-family: var(--lo-font-mono);
|
|
9839
|
+
font-size: 0.92em;
|
|
9840
|
+
white-space: pre-wrap;
|
|
9841
|
+
}
|
|
9842
|
+
|
|
9833
9843
|
/* CLI / Terminal Thinking Mode */
|
|
9834
9844
|
.lasso-agent-status {
|
|
9835
9845
|
display: flex;
|
|
@@ -9906,6 +9916,43 @@
|
|
|
9906
9916
|
color: #f87171;
|
|
9907
9917
|
}
|
|
9908
9918
|
|
|
9919
|
+
.lasso-agent-status-badge.complete {
|
|
9920
|
+
background: rgba(16, 185, 129, 0.16);
|
|
9921
|
+
color: #34d399;
|
|
9922
|
+
}
|
|
9923
|
+
|
|
9924
|
+
.lasso-agent-log-toggle {
|
|
9925
|
+
display: inline-flex;
|
|
9926
|
+
align-items: center;
|
|
9927
|
+
gap: 3px;
|
|
9928
|
+
padding: 2px 5px;
|
|
9929
|
+
border: 0;
|
|
9930
|
+
border-radius: 4px;
|
|
9931
|
+
background: transparent;
|
|
9932
|
+
color: #64748b;
|
|
9933
|
+
font: inherit;
|
|
9934
|
+
font-size: 9.5px;
|
|
9935
|
+
cursor: pointer;
|
|
9936
|
+
}
|
|
9937
|
+
|
|
9938
|
+
.lasso-agent-log-toggle:hover {
|
|
9939
|
+
background: rgba(255, 255, 255, 0.06);
|
|
9940
|
+
color: #cbd5e1;
|
|
9941
|
+
}
|
|
9942
|
+
|
|
9943
|
+
.lasso-agent-log-toggle[hidden] {
|
|
9944
|
+
display: none;
|
|
9945
|
+
}
|
|
9946
|
+
|
|
9947
|
+
.lasso-agent-log-chevron {
|
|
9948
|
+
display: inline-block;
|
|
9949
|
+
transition: transform 140ms ease;
|
|
9950
|
+
}
|
|
9951
|
+
|
|
9952
|
+
.lasso-agent-log-toggle[aria-expanded="true"] .lasso-agent-log-chevron {
|
|
9953
|
+
transform: rotate(180deg);
|
|
9954
|
+
}
|
|
9955
|
+
|
|
9909
9956
|
.lasso-agent-status-line {
|
|
9910
9957
|
display: flex;
|
|
9911
9958
|
align-items: center;
|
|
@@ -9921,13 +9968,52 @@
|
|
|
9921
9968
|
}
|
|
9922
9969
|
|
|
9923
9970
|
.lasso-agent-status-message {
|
|
9971
|
+
flex: 1;
|
|
9972
|
+
min-width: 0;
|
|
9924
9973
|
overflow: hidden;
|
|
9925
9974
|
text-overflow: ellipsis;
|
|
9926
9975
|
white-space: nowrap;
|
|
9927
9976
|
}
|
|
9928
9977
|
|
|
9929
|
-
/* The status line is the single latest activity message. */
|
|
9930
9978
|
.lasso-agent-log {
|
|
9979
|
+
display: flex;
|
|
9980
|
+
flex-direction: column;
|
|
9981
|
+
gap: 5px;
|
|
9982
|
+
max-height: 180px;
|
|
9983
|
+
margin-top: 8px;
|
|
9984
|
+
padding-top: 7px;
|
|
9985
|
+
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
|
9986
|
+
overflow: auto;
|
|
9987
|
+
color: #64748b;
|
|
9988
|
+
font-size: 10px;
|
|
9989
|
+
}
|
|
9990
|
+
|
|
9991
|
+
.lasso-agent-log[hidden] {
|
|
9992
|
+
display: none;
|
|
9993
|
+
}
|
|
9994
|
+
|
|
9995
|
+
.lasso-agent-log-line {
|
|
9996
|
+
display: flex;
|
|
9997
|
+
gap: 5px;
|
|
9998
|
+
line-height: 1.45;
|
|
9999
|
+
}
|
|
10000
|
+
|
|
10001
|
+
.lasso-agent-log-prefix {
|
|
10002
|
+
flex: 0 0 auto;
|
|
10003
|
+
color: #475569;
|
|
10004
|
+
}
|
|
10005
|
+
|
|
10006
|
+
.lasso-agent-log-text {
|
|
10007
|
+
min-width: 0;
|
|
10008
|
+
white-space: pre-wrap;
|
|
10009
|
+
overflow-wrap: anywhere;
|
|
10010
|
+
}
|
|
10011
|
+
|
|
10012
|
+
.lasso-agent-status[data-status="complete"] .lasso-agent-status-line {
|
|
10013
|
+
animation: none;
|
|
10014
|
+
}
|
|
10015
|
+
|
|
10016
|
+
.lasso-agent-status[data-status="complete"] .lasso-agent-cursor {
|
|
9931
10017
|
display: none;
|
|
9932
10018
|
}
|
|
9933
10019
|
|
|
@@ -9945,40 +10031,11 @@
|
|
|
9945
10031
|
50% { opacity: 0; }
|
|
9946
10032
|
}
|
|
9947
10033
|
|
|
9948
|
-
.lasso-agent-log {
|
|
9949
|
-
display: flex;
|
|
9950
|
-
flex-direction: column;
|
|
9951
|
-
gap: 2px;
|
|
9952
|
-
margin-top: 6px;
|
|
9953
|
-
max-height: 80px;
|
|
9954
|
-
overflow-y: auto;
|
|
9955
|
-
font-size: 10px;
|
|
9956
|
-
color: #64748b;
|
|
9957
|
-
}
|
|
9958
|
-
|
|
9959
|
-
.lasso-agent-log-line {
|
|
9960
|
-
display: flex;
|
|
9961
|
-
gap: 5px;
|
|
9962
|
-
overflow: hidden;
|
|
9963
|
-
text-overflow: ellipsis;
|
|
9964
|
-
white-space: nowrap;
|
|
9965
|
-
animation: lasso-agent-log-in 180ms ease-out both;
|
|
9966
|
-
}
|
|
9967
|
-
|
|
9968
|
-
.lasso-agent-log-prefix {
|
|
9969
|
-
color: #475569;
|
|
9970
|
-
}
|
|
9971
|
-
|
|
9972
10034
|
@keyframes lasso-agent-line-pulse {
|
|
9973
10035
|
0%, 100% { opacity: .72; }
|
|
9974
10036
|
50% { opacity: 1; }
|
|
9975
10037
|
}
|
|
9976
10038
|
|
|
9977
|
-
@keyframes lasso-agent-log-in {
|
|
9978
|
-
from { opacity: 0; transform: translateY(3px); }
|
|
9979
|
-
to { opacity: 1; transform: translateY(0); }
|
|
9980
|
-
}
|
|
9981
|
-
|
|
9982
10039
|
.lasso-prompt-actions {
|
|
9983
10040
|
display: flex;
|
|
9984
10041
|
align-items: center;
|
|
@@ -12002,6 +12059,30 @@
|
|
|
12002
12059
|
};
|
|
12003
12060
|
var terminal_default = data4;
|
|
12004
12061
|
|
|
12062
|
+
// src/overlay/notifications.ts
|
|
12063
|
+
var permissionRequest = null;
|
|
12064
|
+
function requestAgentNotificationPermission() {
|
|
12065
|
+
if (typeof window === "undefined" || !("Notification" in window)) return;
|
|
12066
|
+
if (Notification.permission !== "default" || permissionRequest) return;
|
|
12067
|
+
permissionRequest = Notification.requestPermission().finally(() => {
|
|
12068
|
+
permissionRequest = null;
|
|
12069
|
+
});
|
|
12070
|
+
}
|
|
12071
|
+
async function notifyAgent(title, body) {
|
|
12072
|
+
if (typeof window === "undefined" || !("Notification" in window)) return;
|
|
12073
|
+
let permission = Notification.permission;
|
|
12074
|
+
if (permission === "default") permission = await (permissionRequest || Notification.requestPermission());
|
|
12075
|
+
if (permission !== "granted") return;
|
|
12076
|
+
try {
|
|
12077
|
+
const notification = new Notification(title, { body: body.slice(0, 240) });
|
|
12078
|
+
notification.onclick = () => {
|
|
12079
|
+
window.focus();
|
|
12080
|
+
notification.close();
|
|
12081
|
+
};
|
|
12082
|
+
} catch {
|
|
12083
|
+
}
|
|
12084
|
+
}
|
|
12085
|
+
|
|
12005
12086
|
// node_modules/.pnpm/engine.io-parser@5.2.3/node_modules/engine.io-parser/build/esm/commons.js
|
|
12006
12087
|
var PACKET_TYPES = /* @__PURE__ */ Object.create(null);
|
|
12007
12088
|
PACKET_TYPES["open"] = "0";
|
|
@@ -18095,6 +18176,9 @@
|
|
|
18095
18176
|
var agentStatusElement = null;
|
|
18096
18177
|
var agentStatusMessage = null;
|
|
18097
18178
|
var agentLogElement = null;
|
|
18179
|
+
var agentLogToggle = null;
|
|
18180
|
+
var agentLogLines = [];
|
|
18181
|
+
var agentLogExpanded = false;
|
|
18098
18182
|
var reviewPanel = null;
|
|
18099
18183
|
var modelBtn = null;
|
|
18100
18184
|
var modelName = null;
|
|
@@ -18153,13 +18237,17 @@
|
|
|
18153
18237
|
</div>
|
|
18154
18238
|
<span class="lasso-agent-status-kicker">lasso-agent</span>
|
|
18155
18239
|
<span class="lasso-agent-status-badge">active</span>
|
|
18240
|
+
<button class="lasso-agent-log-toggle" type="button" aria-label="Show agent activity" aria-expanded="false" hidden>
|
|
18241
|
+
<span>Activity</span>
|
|
18242
|
+
<span class="lasso-agent-log-chevron">\u2304</span>
|
|
18243
|
+
</button>
|
|
18156
18244
|
</div>
|
|
18157
18245
|
<div class="lasso-agent-status-line">
|
|
18158
18246
|
<span class="lasso-agent-terminal-prompt">\u276F</span>
|
|
18159
18247
|
<span class="lasso-agent-status-message"></span>
|
|
18160
18248
|
<span class="lasso-agent-cursor"></span>
|
|
18161
18249
|
</div>
|
|
18162
|
-
<div class="lasso-agent-log" aria-label="Agent activity"></div>
|
|
18250
|
+
<div class="lasso-agent-log" aria-label="Agent activity" hidden></div>
|
|
18163
18251
|
</div>
|
|
18164
18252
|
|
|
18165
18253
|
<textarea class="lasso-prompt-input" placeholder="Ask anything about this element\u2026" rows="1"></textarea>
|
|
@@ -18213,9 +18301,15 @@
|
|
|
18213
18301
|
agentStatusElement = el.querySelector(".lasso-agent-status");
|
|
18214
18302
|
agentStatusMessage = el.querySelector(".lasso-agent-status-message");
|
|
18215
18303
|
agentLogElement = el.querySelector(".lasso-agent-log");
|
|
18304
|
+
agentLogToggle = el.querySelector(".lasso-agent-log-toggle");
|
|
18216
18305
|
modelBtn = el.querySelector(".lasso-prompt-model");
|
|
18217
18306
|
modelName = el.querySelector(".lasso-prompt-model-name");
|
|
18218
18307
|
modelMenu = el.querySelector(".lasso-prompt-model-menu");
|
|
18308
|
+
agentLogToggle.addEventListener("click", (event) => {
|
|
18309
|
+
event.preventDefault();
|
|
18310
|
+
event.stopPropagation();
|
|
18311
|
+
setAgentLogExpanded(!agentLogExpanded);
|
|
18312
|
+
});
|
|
18219
18313
|
const rev = document.createElement("div");
|
|
18220
18314
|
rev.className = "lasso-review";
|
|
18221
18315
|
rev.hidden = true;
|
|
@@ -18367,6 +18461,7 @@
|
|
|
18367
18461
|
});
|
|
18368
18462
|
rev.querySelector(".lasso-review-apply").addEventListener("click", () => {
|
|
18369
18463
|
if (!state.bridgeSocket || state.bridgeSocket.readyState !== WebSocket.OPEN || !state.pendingChanges.length) return;
|
|
18464
|
+
requestAgentNotificationPermission();
|
|
18370
18465
|
state.bridgeSocket.send(JSON.stringify({ type: "apply", changes: state.pendingChanges }));
|
|
18371
18466
|
appendChat("assistant", "Applying the reviewed change\u2026");
|
|
18372
18467
|
});
|
|
@@ -18478,11 +18573,74 @@
|
|
|
18478
18573
|
return {};
|
|
18479
18574
|
}
|
|
18480
18575
|
}
|
|
18576
|
+
async function captureElementScreenshot(el) {
|
|
18577
|
+
const options = {
|
|
18578
|
+
backgroundColor: null,
|
|
18579
|
+
useCORS: true,
|
|
18580
|
+
logging: false,
|
|
18581
|
+
scale: Math.min(window.devicePixelRatio || 1, 1),
|
|
18582
|
+
ignoreElements: (node) => node.id === "lasso-root" || Boolean(node.closest?.("#lasso-root"))
|
|
18583
|
+
};
|
|
18584
|
+
try {
|
|
18585
|
+
const canvas = await (0, import_html2canvas.default)(el, options);
|
|
18586
|
+
return { element: canvas.toDataURL("image/jpeg", 0.78) };
|
|
18587
|
+
} catch (error) {
|
|
18588
|
+
console.warn("[lasso] element screenshot unavailable", error);
|
|
18589
|
+
return {};
|
|
18590
|
+
}
|
|
18591
|
+
}
|
|
18592
|
+
function setAgentLogExpanded(expanded) {
|
|
18593
|
+
agentLogExpanded = expanded && agentLogLines.length > 0;
|
|
18594
|
+
if (agentLogElement) agentLogElement.hidden = !agentLogExpanded;
|
|
18595
|
+
if (agentLogToggle) {
|
|
18596
|
+
agentLogToggle.hidden = agentLogLines.length === 0;
|
|
18597
|
+
agentLogToggle.setAttribute("aria-expanded", String(agentLogExpanded));
|
|
18598
|
+
agentLogToggle.setAttribute("aria-label", agentLogExpanded ? "Hide agent activity" : "Show agent activity");
|
|
18599
|
+
}
|
|
18600
|
+
}
|
|
18601
|
+
function clearAgentLog() {
|
|
18602
|
+
agentLogLines = [];
|
|
18603
|
+
agentLogExpanded = false;
|
|
18604
|
+
if (agentLogElement) {
|
|
18605
|
+
agentLogElement.replaceChildren();
|
|
18606
|
+
agentLogElement.hidden = true;
|
|
18607
|
+
}
|
|
18608
|
+
if (agentLogToggle) {
|
|
18609
|
+
agentLogToggle.hidden = true;
|
|
18610
|
+
agentLogToggle.setAttribute("aria-expanded", "false");
|
|
18611
|
+
agentLogToggle.setAttribute("aria-label", "Show agent activity");
|
|
18612
|
+
}
|
|
18613
|
+
if (agentStatusElement) {
|
|
18614
|
+
agentStatusElement.hidden = true;
|
|
18615
|
+
agentStatusElement.dataset.status = "idle";
|
|
18616
|
+
}
|
|
18617
|
+
}
|
|
18618
|
+
function appendAgentLog(message) {
|
|
18619
|
+
const value2 = message.trim();
|
|
18620
|
+
if (!value2) return;
|
|
18621
|
+
const previous = agentLogLines[agentLogLines.length - 1];
|
|
18622
|
+
if (previous === value2) return;
|
|
18623
|
+
agentLogLines.push(value2);
|
|
18624
|
+
if (agentLogElement) {
|
|
18625
|
+
const line = document.createElement("div");
|
|
18626
|
+
line.className = "lasso-agent-log-line";
|
|
18627
|
+
const prefix = document.createElement("span");
|
|
18628
|
+
prefix.className = "lasso-agent-log-prefix";
|
|
18629
|
+
prefix.textContent = "\u203A";
|
|
18630
|
+
const text = document.createElement("span");
|
|
18631
|
+
text.className = "lasso-agent-log-text";
|
|
18632
|
+
text.textContent = value2;
|
|
18633
|
+
line.append(prefix, text);
|
|
18634
|
+
agentLogElement.append(line);
|
|
18635
|
+
if (agentLogExpanded) agentLogElement.scrollTop = agentLogElement.scrollHeight;
|
|
18636
|
+
}
|
|
18637
|
+
if (agentLogToggle) agentLogToggle.hidden = false;
|
|
18638
|
+
}
|
|
18481
18639
|
function appendChat(role, text) {
|
|
18482
18640
|
const thread = promptEl?.querySelector(".lasso-chat-thread");
|
|
18483
18641
|
if (!thread || !text.trim()) return;
|
|
18484
18642
|
const previous = thread.lastElementChild;
|
|
18485
|
-
if (previous?.
|
|
18643
|
+
if (previous?.classList.contains(role) && previous.dataset.rawText === text) return;
|
|
18486
18644
|
state.chatHistory.push({
|
|
18487
18645
|
role,
|
|
18488
18646
|
content: text,
|
|
@@ -18491,15 +18649,36 @@
|
|
|
18491
18649
|
});
|
|
18492
18650
|
const item = document.createElement("div");
|
|
18493
18651
|
item.className = `lasso-chat-message ${role}`;
|
|
18494
|
-
item.
|
|
18652
|
+
item.dataset.rawText = text;
|
|
18653
|
+
renderChatText(item, text);
|
|
18495
18654
|
thread.appendChild(item);
|
|
18496
18655
|
while (thread.children.length > 6) thread.firstElementChild?.remove();
|
|
18497
18656
|
thread.scrollTop = thread.scrollHeight;
|
|
18498
18657
|
}
|
|
18499
|
-
function
|
|
18658
|
+
function renderChatText(container, text) {
|
|
18659
|
+
const codePattern = /(`+)([\s\S]*?)\1/g;
|
|
18660
|
+
let lastIndex = 0;
|
|
18661
|
+
for (const match of text.matchAll(codePattern)) {
|
|
18662
|
+
const index = match.index ?? 0;
|
|
18663
|
+
if (index > lastIndex) {
|
|
18664
|
+
container.append(document.createTextNode(text.slice(lastIndex, index)));
|
|
18665
|
+
}
|
|
18666
|
+
const code = document.createElement("code");
|
|
18667
|
+
code.textContent = match[2] ?? "";
|
|
18668
|
+
container.append(code);
|
|
18669
|
+
lastIndex = index + match[0].length;
|
|
18670
|
+
}
|
|
18671
|
+
if (lastIndex < text.length) {
|
|
18672
|
+
container.append(document.createTextNode(text.slice(lastIndex)));
|
|
18673
|
+
}
|
|
18674
|
+
}
|
|
18675
|
+
function setAgentStatus(status, message, detail) {
|
|
18500
18676
|
if (!agentStatusElement || !agentStatusMessage || !sendButton) return;
|
|
18501
|
-
|
|
18502
|
-
|
|
18677
|
+
const logMessage = detail?.trim() || message.trim();
|
|
18678
|
+
const lastLog = agentLogLines[agentLogLines.length - 1];
|
|
18679
|
+
if (agentStatusElement.dataset.status === status && agentStatusMessage.textContent === message && (status === "thinking" || status === "working") && (!logMessage || lastLog === logMessage)) return;
|
|
18680
|
+
appendAgentLog(logMessage);
|
|
18681
|
+
agentStatusElement.hidden = status === "review";
|
|
18503
18682
|
agentStatusElement.dataset.status = status;
|
|
18504
18683
|
agentStatusMessage.textContent = message;
|
|
18505
18684
|
const badgeEl = agentStatusElement.querySelector(".lasso-agent-status-badge");
|
|
@@ -18508,12 +18687,6 @@
|
|
|
18508
18687
|
badgeEl.className = `lasso-agent-status-badge ${status}`;
|
|
18509
18688
|
}
|
|
18510
18689
|
state.agentRunning = status === "thinking" || status === "working";
|
|
18511
|
-
if (state.agentRunning && agentLogElement) {
|
|
18512
|
-
const line = document.createElement("div");
|
|
18513
|
-
line.className = "lasso-agent-log-line";
|
|
18514
|
-
line.innerHTML = `<span class="lasso-agent-log-prefix">\u203A</span> <span class="lasso-agent-log-text">${escapeHtml4(message)}</span>`;
|
|
18515
|
-
agentLogElement.replaceChildren(line);
|
|
18516
|
-
}
|
|
18517
18690
|
sendButton.classList.toggle("loading", state.agentRunning);
|
|
18518
18691
|
if (stopButton) stopButton.hidden = !state.agentRunning;
|
|
18519
18692
|
if (promptInput) promptInput.disabled = state.agentRunning;
|
|
@@ -18528,11 +18701,6 @@
|
|
|
18528
18701
|
appendChat(status === "error" ? "error" : "assistant", message);
|
|
18529
18702
|
}
|
|
18530
18703
|
}
|
|
18531
|
-
function escapeHtml4(text) {
|
|
18532
|
-
const div = document.createElement("div");
|
|
18533
|
-
div.textContent = text;
|
|
18534
|
-
return div.innerHTML;
|
|
18535
|
-
}
|
|
18536
18704
|
function syncSendButtonState() {
|
|
18537
18705
|
if (!promptInput || !sendButton) return;
|
|
18538
18706
|
const hasInstruction = Boolean(promptInput.value.trim()) || sendButton.dataset.state === "retry" && Boolean(state.lastInstruction?.trim());
|
|
@@ -18541,11 +18709,19 @@
|
|
|
18541
18709
|
}
|
|
18542
18710
|
function resetAgentState() {
|
|
18543
18711
|
state.agentRunning = false;
|
|
18712
|
+
const hasLog = agentLogLines.length > 0;
|
|
18544
18713
|
if (agentStatusElement) {
|
|
18545
|
-
agentStatusElement.hidden =
|
|
18546
|
-
agentStatusElement.dataset.status = "idle";
|
|
18714
|
+
agentStatusElement.hidden = !hasLog;
|
|
18715
|
+
agentStatusElement.dataset.status = hasLog ? "complete" : "idle";
|
|
18716
|
+
}
|
|
18717
|
+
if (hasLog && agentStatusMessage) agentStatusMessage.textContent = "Agent complete";
|
|
18718
|
+
if (hasLog) {
|
|
18719
|
+
const badgeEl = agentStatusElement?.querySelector(".lasso-agent-status-badge");
|
|
18720
|
+
if (badgeEl) {
|
|
18721
|
+
badgeEl.textContent = "done";
|
|
18722
|
+
badgeEl.className = "lasso-agent-status-badge complete";
|
|
18723
|
+
}
|
|
18547
18724
|
}
|
|
18548
|
-
if (agentLogElement) agentLogElement.replaceChildren();
|
|
18549
18725
|
if (sendButton) {
|
|
18550
18726
|
sendButton.classList.remove("loading");
|
|
18551
18727
|
sendButton.dataset.state = "idle";
|
|
@@ -18641,6 +18817,8 @@
|
|
|
18641
18817
|
promptInput.focus();
|
|
18642
18818
|
return;
|
|
18643
18819
|
}
|
|
18820
|
+
clearAgentLog();
|
|
18821
|
+
requestAgentNotificationPermission();
|
|
18644
18822
|
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);
|
|
18645
18823
|
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);
|
|
18646
18824
|
const wantsAnswer = isQuestion && !/\b(can|could|would|please)\s+you\s+(change|edit|update|add|fix|make)\b/i.test(instruction) || !isExplicitEdit && !isQuestion;
|
|
@@ -18672,7 +18850,8 @@
|
|
|
18672
18850
|
const attributes = Object.fromEntries(
|
|
18673
18851
|
Array.from(state.selected.attributes).map((attr) => [attr.name, attr.value])
|
|
18674
18852
|
);
|
|
18675
|
-
const
|
|
18853
|
+
const needsVisualContext = /\b(look|visual|appearance|color|colour|background|image|icon|spacing|layout|position|align|responsive|style|restyle|font|size)\b/i.test(instruction);
|
|
18854
|
+
const screenshots = needsVisualContext && state.selected ? await captureElementScreenshot(state.selected) : await state.screenshotPromise;
|
|
18676
18855
|
state.bridgeSocket.send(
|
|
18677
18856
|
JSON.stringify({
|
|
18678
18857
|
type: wantsAnswer ? "ask" : "edit",
|
|
@@ -18725,6 +18904,7 @@
|
|
|
18725
18904
|
}
|
|
18726
18905
|
function openPromptForSelected(selected) {
|
|
18727
18906
|
if (!promptEl || !promptElement) return;
|
|
18907
|
+
clearAgentLog();
|
|
18728
18908
|
promptElement.textContent = getElementLabel(selected);
|
|
18729
18909
|
positionPrompt(selected);
|
|
18730
18910
|
promptEl.classList.add("visible");
|
|
@@ -19547,7 +19727,7 @@
|
|
|
19547
19727
|
return { code, badge, badgeClass, path: filePath, dir, name };
|
|
19548
19728
|
});
|
|
19549
19729
|
}
|
|
19550
|
-
function
|
|
19730
|
+
function escapeHtml4(text) {
|
|
19551
19731
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
19552
19732
|
}
|
|
19553
19733
|
function buildGitPanel() {
|
|
@@ -19802,9 +19982,9 @@
|
|
|
19802
19982
|
(f) => `
|
|
19803
19983
|
<div class="lasso-git-file-row">
|
|
19804
19984
|
<span class="lasso-git-file-badge ${f.badgeClass}" title="${f.code}">${f.badge}</span>
|
|
19805
|
-
<span class="lasso-git-file-path" title="${
|
|
19806
|
-
${f.dir ? `<span class="lasso-git-file-dir">${
|
|
19807
|
-
<span class="lasso-git-file-name">${
|
|
19985
|
+
<span class="lasso-git-file-path" title="${escapeHtml4(f.path)}">
|
|
19986
|
+
${f.dir ? `<span class="lasso-git-file-dir">${escapeHtml4(f.dir)}</span>` : ""}
|
|
19987
|
+
<span class="lasso-git-file-name">${escapeHtml4(f.name)}</span>
|
|
19808
19988
|
</span>
|
|
19809
19989
|
</div>
|
|
19810
19990
|
`
|
|
@@ -20174,9 +20354,10 @@
|
|
|
20174
20354
|
setGeneratedCommitMessage(message.message || "", message.error);
|
|
20175
20355
|
}
|
|
20176
20356
|
if (message.type === "agent_status" && message.status && message.message) {
|
|
20177
|
-
setAgentStatus(message.status, message.message);
|
|
20357
|
+
setAgentStatus(message.status, message.message, message.detail);
|
|
20178
20358
|
setDragCardStatus(message.status, message.message);
|
|
20179
20359
|
if (message.status === "review" && message.changes?.length) {
|
|
20360
|
+
void notifyAgent("Review requested", message.message);
|
|
20180
20361
|
state.pendingChanges = message.changes;
|
|
20181
20362
|
state.changesHistory.push({
|
|
20182
20363
|
summary: message.message,
|
|
@@ -20187,10 +20368,12 @@
|
|
|
20187
20368
|
}
|
|
20188
20369
|
}
|
|
20189
20370
|
if (message.type === "assistant_message" && message.message) {
|
|
20371
|
+
void notifyAgent("Agent complete", message.message);
|
|
20190
20372
|
appendChat("assistant", message.message);
|
|
20191
20373
|
resetAgentState();
|
|
20192
20374
|
}
|
|
20193
20375
|
if (message.type === "applied" || message.type === "undone") {
|
|
20376
|
+
void notifyAgent(message.type === "applied" ? "Changes applied" : "Change undone", message.message || "Done.");
|
|
20194
20377
|
appendChat("assistant", message.message || "Done.");
|
|
20195
20378
|
releaseHeldLock();
|
|
20196
20379
|
if (state.collabSocket?.connected && state.collabJoined) {
|
|
@@ -20290,7 +20473,7 @@
|
|
|
20290
20473
|
state.selectionId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
20291
20474
|
state.chatHistory = [];
|
|
20292
20475
|
state.changesHistory = [];
|
|
20293
|
-
state.screenshotPromise =
|
|
20476
|
+
state.screenshotPromise = Promise.resolve({});
|
|
20294
20477
|
dom.hoverBox.style.display = "none";
|
|
20295
20478
|
updateSelectedVisual2();
|
|
20296
20479
|
openPromptForSelected(target);
|
package/package.json
CHANGED