@lasso-ai/cli 1.1.3 → 1.1.5
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 +45 -7
- package/dist/overlay.js +21 -8
- package/package.json +1 -1
package/dist/cli/agent.js
CHANGED
|
@@ -36,6 +36,7 @@ async function detectLocalAgents() {
|
|
|
36
36
|
}
|
|
37
37
|
const ignored = new Set(["node_modules", ".git", ".next", "dist", "build", ".turbo"]);
|
|
38
38
|
const sourceExtensions = /\.(tsx?|jsx?|vue|svelte|css|scss|html)$/i;
|
|
39
|
+
const layoutFiles = /^(layout|_layout|_app|app|_document|document|template|_template)\.(tsx?|jsx?)$/i;
|
|
39
40
|
const sourceFileCache = new Map();
|
|
40
41
|
async function sourceFiles(directory, budget = { remaining: 25 }) {
|
|
41
42
|
if (budget.remaining <= 0)
|
|
@@ -48,6 +49,8 @@ async function sourceFiles(directory, budget = { remaining: 25 }) {
|
|
|
48
49
|
}
|
|
49
50
|
const entries = await promises_1.default.readdir(directory, { withFileTypes: true });
|
|
50
51
|
const files = [];
|
|
52
|
+
const layoutFilesList = [];
|
|
53
|
+
const otherFiles = [];
|
|
51
54
|
for (const entry of entries) {
|
|
52
55
|
if (ignored.has(entry.name) || entry.name.startsWith("."))
|
|
53
56
|
continue;
|
|
@@ -59,10 +62,17 @@ async function sourceFiles(directory, budget = { remaining: 25 }) {
|
|
|
59
62
|
files.push(...nested);
|
|
60
63
|
}
|
|
61
64
|
else if (sourceExtensions.test(entry.name)) {
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
if (layoutFiles.test(entry.name)) {
|
|
66
|
+
layoutFilesList.push(fullPath);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
otherFiles.push(fullPath);
|
|
70
|
+
}
|
|
64
71
|
}
|
|
65
72
|
}
|
|
73
|
+
// Prioritize layout files first, then other files
|
|
74
|
+
files.push(...layoutFilesList, ...otherFiles);
|
|
75
|
+
budget.remaining -= files.length;
|
|
66
76
|
sourceFileCache.set(directory, { expiresAt: Date.now() + 30000, files });
|
|
67
77
|
return files;
|
|
68
78
|
}
|
|
@@ -70,6 +80,11 @@ async function contextFor(cwd, element) {
|
|
|
70
80
|
const needle = element.label.replace(/^[^.#]+[.#]?/, "");
|
|
71
81
|
const hintedPath = element.sourceHint?.split(":")[0];
|
|
72
82
|
const sourceFile = hintedPath ? node_path_1.default.basename(hintedPath) : "";
|
|
83
|
+
// Extract unique class names and attributes from the element for better matching
|
|
84
|
+
const classMatches = element.html?.match(/class="([^"]+)"/);
|
|
85
|
+
const classNames = classMatches ? classMatches[1].split(/\s+/).filter((c) => c.length > 3) : [];
|
|
86
|
+
const hrefMatch = element.html?.match(/href="([^"]+)"/);
|
|
87
|
+
const href = hrefMatch ? hrefMatch[1] : "";
|
|
73
88
|
if (hintedPath) {
|
|
74
89
|
const candidates = [
|
|
75
90
|
node_path_1.default.isAbsolute(hintedPath) ? hintedPath : node_path_1.default.resolve(cwd, hintedPath),
|
|
@@ -91,11 +106,31 @@ async function contextFor(cwd, element) {
|
|
|
91
106
|
}
|
|
92
107
|
const files = await sourceFiles(cwd);
|
|
93
108
|
const snippets = [];
|
|
109
|
+
const scoredFiles = [];
|
|
94
110
|
const results = await Promise.all(files.map(async (file) => {
|
|
95
111
|
try {
|
|
96
112
|
const content = await promises_1.default.readFile(file, "utf8");
|
|
97
|
-
|
|
98
|
-
|
|
113
|
+
let score = 0;
|
|
114
|
+
// Score files based on relevance
|
|
115
|
+
if (sourceFile && file.endsWith(sourceFile))
|
|
116
|
+
score += 10;
|
|
117
|
+
if (content.includes(needle))
|
|
118
|
+
score += 5;
|
|
119
|
+
if (content.includes(element.label))
|
|
120
|
+
score += 5;
|
|
121
|
+
if (href && content.includes(href))
|
|
122
|
+
score += 8;
|
|
123
|
+
// Check for class name matches
|
|
124
|
+
for (const className of classNames) {
|
|
125
|
+
if (content.includes(className))
|
|
126
|
+
score += 3;
|
|
127
|
+
}
|
|
128
|
+
// Boost score for component files
|
|
129
|
+
if (file.includes("component") || file.includes("nav") || file.includes("header") || file.includes("layout")) {
|
|
130
|
+
score += 2;
|
|
131
|
+
}
|
|
132
|
+
if (score > 0) {
|
|
133
|
+
return { file, score, content };
|
|
99
134
|
}
|
|
100
135
|
}
|
|
101
136
|
catch {
|
|
@@ -103,9 +138,12 @@ async function contextFor(cwd, element) {
|
|
|
103
138
|
}
|
|
104
139
|
return null;
|
|
105
140
|
}));
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
141
|
+
// Sort by score and take top files
|
|
142
|
+
const sortedResults = results.filter((r) => r !== null).sort((a, b) => b.score - a.score);
|
|
143
|
+
for (const result of sortedResults) {
|
|
144
|
+
if (snippets.length < 8) {
|
|
145
|
+
snippets.push(`FILE: ${node_path_1.default.relative(cwd, result.file)}\n${result.content.slice(0, 6000)}`);
|
|
146
|
+
}
|
|
109
147
|
}
|
|
110
148
|
return snippets.join("\n\n---\n\n");
|
|
111
149
|
}
|
package/dist/overlay.js
CHANGED
|
@@ -18928,7 +18928,7 @@
|
|
|
18928
18928
|
function findReusableAgentTask(instruction, element) {
|
|
18929
18929
|
const normalized = normalizedInstruction(instruction);
|
|
18930
18930
|
return state.agentTasks.find(
|
|
18931
|
-
(task) =>
|
|
18931
|
+
(task) => normalizedInstruction(task.instruction) === normalized && task.element === (element || void 0)
|
|
18932
18932
|
);
|
|
18933
18933
|
}
|
|
18934
18934
|
function getComponentConversation(selectionId) {
|
|
@@ -20033,18 +20033,31 @@
|
|
|
20033
20033
|
const model = state.selectedModel;
|
|
20034
20034
|
const screenshotPromise = state.screenshotPromise;
|
|
20035
20035
|
const reusableTask = findReusableAgentTask(instruction, selectedElement);
|
|
20036
|
+
let task;
|
|
20036
20037
|
if (reusableTask) {
|
|
20037
20038
|
selectAgentTask(reusableTask.id);
|
|
20038
|
-
|
|
20039
|
+
if (reusableTask.status === "complete" || reusableTask.status === "error" || reusableTask.status === "stopped") {
|
|
20040
|
+
updateAgentTask(reusableTask.id, { status: "thinking", message: "Thinking\u2026", activity: [...reusableTask.activity, "Restarting\u2026"] });
|
|
20041
|
+
appendChat("user", instruction);
|
|
20042
|
+
resetPromptSession(selectedElement);
|
|
20043
|
+
state.promptTaskId = reusableTask.id;
|
|
20044
|
+
state.lastInstruction = instruction;
|
|
20045
|
+
task = reusableTask;
|
|
20046
|
+
} else {
|
|
20047
|
+
return;
|
|
20048
|
+
}
|
|
20049
|
+
} else {
|
|
20050
|
+
appendChat("user", instruction);
|
|
20051
|
+
const messages2 = state.chatHistory.map((message) => ({ ...message }));
|
|
20052
|
+
const changesHistory2 = state.changesHistory.map((entry) => ({ ...entry, changes: entry.changes.map((change) => ({ ...change })) }));
|
|
20053
|
+
task = createAgentTask(instruction, messages2, changesHistory2, selectedElement, selectionId);
|
|
20054
|
+
updateAgentTask(task.id, { status: "thinking", message: "Thinking\u2026", activity: [...task.activity, "Thinking\u2026"] });
|
|
20055
|
+
resetPromptSession(selectedElement);
|
|
20056
|
+
state.promptTaskId = task.id;
|
|
20057
|
+
state.lastInstruction = instruction;
|
|
20039
20058
|
}
|
|
20040
|
-
appendChat("user", instruction);
|
|
20041
20059
|
const messages = state.chatHistory.map((message) => ({ ...message }));
|
|
20042
20060
|
const changesHistory = state.changesHistory.map((entry) => ({ ...entry, changes: entry.changes.map((change) => ({ ...change })) }));
|
|
20043
|
-
const task = createAgentTask(instruction, messages, changesHistory, selectedElement, selectionId);
|
|
20044
|
-
updateAgentTask(task.id, { status: "thinking", message: "Thinking\u2026", activity: [...task.activity, "Thinking\u2026"] });
|
|
20045
|
-
resetPromptSession(selectedElement);
|
|
20046
|
-
state.promptTaskId = task.id;
|
|
20047
|
-
state.lastInstruction = instruction;
|
|
20048
20061
|
const rect = selectedElement.getBoundingClientRect();
|
|
20049
20062
|
const computed = getComputedStyle(selectedElement);
|
|
20050
20063
|
const attributes = Object.fromEntries(
|
package/package.json
CHANGED