@lasso-ai/cli 1.0.16 → 1.0.17
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.js +51 -46
- package/package.json +1 -1
package/dist/cli/bridge.js
CHANGED
|
@@ -114,6 +114,18 @@ function prepareChange(content, change) {
|
|
|
114
114
|
const start = content.indexOf(oldString);
|
|
115
115
|
return { start, end: start + oldString.length, oldString, newString };
|
|
116
116
|
}
|
|
117
|
+
function proposalMatchesCurrentSource(cwd, changes) {
|
|
118
|
+
try {
|
|
119
|
+
for (const change of changes) {
|
|
120
|
+
const filePath = resolveProposedFile(cwd, change.filePath);
|
|
121
|
+
prepareChange(node_fs_1.default.readFileSync(filePath, "utf8"), change);
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
117
129
|
function readEnvFile(cwd, filename) {
|
|
118
130
|
try {
|
|
119
131
|
return node_fs_1.default.readFileSync(node_path_1.default.join(cwd, filename), "utf8").split(/\r?\n/).reduce((values, line) => {
|
|
@@ -257,6 +269,43 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
257
269
|
if (socket.readyState === socket.OPEN)
|
|
258
270
|
socket.send(JSON.stringify({ type: "git_state", git }));
|
|
259
271
|
});
|
|
272
|
+
const runEditReview = (request, config, statusMessage) => {
|
|
273
|
+
activeAgentController?.abort();
|
|
274
|
+
const controller = new AbortController();
|
|
275
|
+
activeAgentController = controller;
|
|
276
|
+
if (statusMessage && socket.readyState === socket.OPEN) {
|
|
277
|
+
socket.send(JSON.stringify({ type: "agent_status", status: "working", message: statusMessage }));
|
|
278
|
+
}
|
|
279
|
+
void (0, agent_1.proposeChanges)(cwd, request, config, controller.signal, (message, detail) => {
|
|
280
|
+
if (!controller.signal.aborted && socket.readyState === socket.OPEN) {
|
|
281
|
+
socket.send(JSON.stringify({ type: "agent_status", status: "working", message, detail }));
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
.then((proposal) => {
|
|
285
|
+
if (controller.signal.aborted || socket.readyState !== socket.OPEN)
|
|
286
|
+
return;
|
|
287
|
+
if (!proposalMatchesCurrentSource(cwd, proposal.changes)) {
|
|
288
|
+
if (reviewRefreshAttempts < 1) {
|
|
289
|
+
reviewRefreshAttempts += 1;
|
|
290
|
+
runEditReview(request, config, "The source changed while the proposal was being prepared. Refreshing the review…");
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
socket.send(JSON.stringify({ type: "agent_status", status: "error", message: "The source is still changing. Stop the dev-server edit or try the request again." }));
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
socket.send(JSON.stringify({ type: "agent_status", status: "review", message: proposal.summary, changes: proposal.changes }));
|
|
298
|
+
})
|
|
299
|
+
.catch((error) => {
|
|
300
|
+
if (!controller.signal.aborted && socket.readyState === socket.OPEN) {
|
|
301
|
+
socket.send(JSON.stringify({ type: "agent_status", status: "error", message: error instanceof Error ? error.message : "The agent could not prepare a change." }));
|
|
302
|
+
}
|
|
303
|
+
})
|
|
304
|
+
.finally(() => {
|
|
305
|
+
if (activeAgentController === controller)
|
|
306
|
+
activeAgentController = null;
|
|
307
|
+
});
|
|
308
|
+
};
|
|
260
309
|
socket.on("message", async (raw) => {
|
|
261
310
|
const msg = JSON.parse(raw.toString());
|
|
262
311
|
if (msg.type === "edit" || msg.type === "ask") {
|
|
@@ -307,34 +356,13 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
307
356
|
socket.send(JSON.stringify({ type: "agent_status", status: "error", message: "Add a supported agent key: GOOGLE_GENERATIVE_AI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY." }));
|
|
308
357
|
return;
|
|
309
358
|
}
|
|
310
|
-
activeAgentController?.abort();
|
|
311
|
-
const controller = new AbortController();
|
|
312
|
-
activeAgentController = controller;
|
|
313
359
|
const selectedConfig = localProvider
|
|
314
360
|
? { provider: cliProvider, model: msg.model }
|
|
315
361
|
: { ...agentConfig, provider: (msg.provider || agentConfig.provider), model: msg.model };
|
|
316
362
|
lastEditRequest = msg;
|
|
317
363
|
lastEditConfig = selectedConfig;
|
|
318
364
|
reviewRefreshAttempts = 0;
|
|
319
|
-
|
|
320
|
-
if (!controller.signal.aborted && socket.readyState === socket.OPEN) {
|
|
321
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "working", message, detail }));
|
|
322
|
-
}
|
|
323
|
-
})
|
|
324
|
-
.then((proposal) => {
|
|
325
|
-
if (!controller.signal.aborted)
|
|
326
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "review", message: proposal.summary, changes: proposal.changes }));
|
|
327
|
-
})
|
|
328
|
-
.catch((error) => {
|
|
329
|
-
if (controller.signal.aborted)
|
|
330
|
-
return;
|
|
331
|
-
const message = error instanceof Error ? error.message : "The agent could not prepare a change.";
|
|
332
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "error", message }));
|
|
333
|
-
})
|
|
334
|
-
.finally(() => {
|
|
335
|
-
if (activeAgentController === controller)
|
|
336
|
-
activeAgentController = null;
|
|
337
|
-
});
|
|
365
|
+
runEditReview(msg, selectedConfig);
|
|
338
366
|
}
|
|
339
367
|
else if (msg.type === "stop") {
|
|
340
368
|
activeAgentController?.abort();
|
|
@@ -472,30 +500,7 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
472
500
|
const message = error instanceof Error ? error.message : "The change could not be applied.";
|
|
473
501
|
const sourceChanged = message.includes("The source changed after the suggestion was generated");
|
|
474
502
|
if (sourceChanged && lastEditRequest && lastEditConfig && reviewRefreshAttempts < 1) {
|
|
475
|
-
|
|
476
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "working", message: "The source changed. Refreshing the review against the current file…" }));
|
|
477
|
-
activeAgentController?.abort();
|
|
478
|
-
const controller = new AbortController();
|
|
479
|
-
activeAgentController = controller;
|
|
480
|
-
void (0, agent_1.proposeChanges)(cwd, lastEditRequest, lastEditConfig, controller.signal, (progress, detail) => {
|
|
481
|
-
if (!controller.signal.aborted && socket.readyState === socket.OPEN) {
|
|
482
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "working", message: progress, detail }));
|
|
483
|
-
}
|
|
484
|
-
})
|
|
485
|
-
.then((proposal) => {
|
|
486
|
-
if (!controller.signal.aborted && socket.readyState === socket.OPEN) {
|
|
487
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "review", message: `Review refreshed: ${proposal.summary}`, changes: proposal.changes }));
|
|
488
|
-
}
|
|
489
|
-
})
|
|
490
|
-
.catch((refreshError) => {
|
|
491
|
-
if (!controller.signal.aborted && socket.readyState === socket.OPEN) {
|
|
492
|
-
socket.send(JSON.stringify({ type: "agent_status", status: "error", message: refreshError instanceof Error ? refreshError.message : "The refreshed review could not be prepared." }));
|
|
493
|
-
}
|
|
494
|
-
})
|
|
495
|
-
.finally(() => {
|
|
496
|
-
if (activeAgentController === controller)
|
|
497
|
-
activeAgentController = null;
|
|
498
|
-
});
|
|
503
|
+
runEditReview(lastEditRequest, lastEditConfig, "The source changed. Refreshing the review against the current file…");
|
|
499
504
|
}
|
|
500
505
|
else {
|
|
501
506
|
socket.send(JSON.stringify({ type: "agent_status", status: "error", message }));
|
package/package.json
CHANGED