@lasso-ai/cli 2.1.12 → 2.1.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/bridge.js
CHANGED
|
@@ -22,6 +22,19 @@ const backends_1 = require("./backends");
|
|
|
22
22
|
const local_runtime_1 = require("./local-runtime");
|
|
23
23
|
exports.DEFAULT_BRIDGE_PORT = 3056;
|
|
24
24
|
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
25
|
+
/** Map overlay chat history to the runtime conversation shape. */
|
|
26
|
+
function toRuntimeConversation(messages) {
|
|
27
|
+
if (!Array.isArray(messages) || messages.length === 0)
|
|
28
|
+
return undefined;
|
|
29
|
+
const turns = messages
|
|
30
|
+
.filter((m) => typeof m?.content === "string" && m.content.trim())
|
|
31
|
+
.map((m) => ({
|
|
32
|
+
role: (m.role === "user" ? "user" : m.role === "assistant" ? "assistant" : "system"),
|
|
33
|
+
content: m.content,
|
|
34
|
+
timestamp: m.createdAt ? Date.parse(m.createdAt) || Date.now() : Date.now(),
|
|
35
|
+
}));
|
|
36
|
+
return turns.length > 0 ? turns : undefined;
|
|
37
|
+
}
|
|
25
38
|
function isConversationalPrompt(prompt) {
|
|
26
39
|
const p = prompt.trim().toLowerCase().replace(/[!?.,;:]+$/, "");
|
|
27
40
|
// 1. Direct greetings and conversational niceties
|
|
@@ -626,6 +639,7 @@ async function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort
|
|
|
626
639
|
const backendModelId = (0, backends_1.modelIdForBackend)(model || "", provider || "");
|
|
627
640
|
const sessionInput = {
|
|
628
641
|
userPrompt: instruction,
|
|
642
|
+
conversation: toRuntimeConversation(messages),
|
|
629
643
|
project: {
|
|
630
644
|
projectId,
|
|
631
645
|
framework,
|
|
@@ -17,6 +17,24 @@ exports.LocalRuntime = void 0;
|
|
|
17
17
|
exports.getLocalRuntime = getLocalRuntime;
|
|
18
18
|
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
19
19
|
const index_js_1 = require("../runtime/index.js");
|
|
20
|
+
/**
|
|
21
|
+
* Seed a session's conversation from the caller's history plus the current
|
|
22
|
+
* user prompt. Skipping the history makes every follow-up a blank-slate run
|
|
23
|
+
* ("try again" becomes a literal search instead of a retry).
|
|
24
|
+
*/
|
|
25
|
+
function seedConversation(input, timestamp) {
|
|
26
|
+
const history = (input.conversation || []).map((msg) => ({
|
|
27
|
+
id: node_crypto_1.default.randomUUID(),
|
|
28
|
+
role: msg.role,
|
|
29
|
+
content: msg.content,
|
|
30
|
+
timestamp: msg.timestamp || timestamp,
|
|
31
|
+
}));
|
|
32
|
+
const last = history[history.length - 1];
|
|
33
|
+
if (!last || last.role !== "user" || last.content !== input.userPrompt) {
|
|
34
|
+
history.push({ id: node_crypto_1.default.randomUUID(), role: "user", content: input.userPrompt, timestamp });
|
|
35
|
+
}
|
|
36
|
+
return history;
|
|
37
|
+
}
|
|
20
38
|
class LocalRuntime {
|
|
21
39
|
sessions = new Map();
|
|
22
40
|
abortControllers = new Map();
|
|
@@ -37,9 +55,7 @@ class LocalRuntime {
|
|
|
37
55
|
iteration: 0,
|
|
38
56
|
userPrompt: input.userPrompt,
|
|
39
57
|
mode: input.mode || "task",
|
|
40
|
-
conversation:
|
|
41
|
-
{ id: node_crypto_1.default.randomUUID(), role: "user", content: input.userPrompt, timestamp: now.getTime() },
|
|
42
|
-
],
|
|
58
|
+
conversation: seedConversation(input, now.getTime()),
|
|
43
59
|
observations: [],
|
|
44
60
|
actions: [],
|
|
45
61
|
completedActions: [],
|
|
@@ -117,7 +133,9 @@ class LocalRuntime {
|
|
|
117
133
|
content: msg.content,
|
|
118
134
|
timestamp: msg.timestamp,
|
|
119
135
|
})),
|
|
120
|
-
|
|
136
|
+
// Carry prior observations so the agent knows what was already
|
|
137
|
+
// searched/read instead of re-exploring the project every turn.
|
|
138
|
+
previousObservations: record.observations,
|
|
121
139
|
previousErrors,
|
|
122
140
|
currentPhase: "execute",
|
|
123
141
|
constraints: { safetyLevel: "standard" },
|
package/dist/cli/oneshot.js
CHANGED
|
@@ -82,6 +82,11 @@ async function runOneShotAgent(cwd, prompt, scope, config, signal, onProgress, o
|
|
|
82
82
|
onProgress("thinking", "Creating runtime session...", `Model: ${config.model || "claude-3-5-sonnet-20241022"}`);
|
|
83
83
|
const sessionInput = {
|
|
84
84
|
userPrompt: prompt,
|
|
85
|
+
conversation: Array.isArray(messages) && messages.length > 0
|
|
86
|
+
? messages
|
|
87
|
+
.filter((m) => typeof m?.content === "string" && m.content.trim())
|
|
88
|
+
.map((m) => ({ role: m.role, content: m.content }))
|
|
89
|
+
: undefined,
|
|
85
90
|
project: {
|
|
86
91
|
projectId: "", // TODO: Get from workspace config
|
|
87
92
|
framework,
|
|
@@ -45,6 +45,16 @@ export interface RuntimeSessionInput {
|
|
|
45
45
|
screenshot?: string;
|
|
46
46
|
};
|
|
47
47
|
conversationUid?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Prior turns of the same conversation. Follow-up prompts must carry
|
|
50
|
+
* history here — a session created with only userPrompt gives the agent
|
|
51
|
+
* no idea what was asked or done before.
|
|
52
|
+
*/
|
|
53
|
+
conversation?: Array<{
|
|
54
|
+
role: "user" | "assistant" | "system";
|
|
55
|
+
content: string;
|
|
56
|
+
timestamp?: number;
|
|
57
|
+
}>;
|
|
48
58
|
backendConfig?: {
|
|
49
59
|
type: "hosted_model" | "local_agent";
|
|
50
60
|
provider: "claude_code" | "opencode" | "codex_cli" | "cursor";
|
|
@@ -311,6 +311,20 @@ class LocalAgentAdapter {
|
|
|
311
311
|
lines.push("2. All file changes will be captured as a diff, reviewed by the user, and only applied if approved.");
|
|
312
312
|
lines.push("3. Do not commit, push, or perform operations outside this project directory.");
|
|
313
313
|
lines.push("");
|
|
314
|
+
// Retry/continuation replies ("try again", "continue", …) must resume
|
|
315
|
+
// the previous request instead of being treated as a literal task —
|
|
316
|
+
// otherwise the agent greps for words like "again".
|
|
317
|
+
const normalizedPrompt = context.userPrompt.trim().replace(/[.!]+$/, "").toLowerCase();
|
|
318
|
+
const isContinuation = /^(continue|proceed|go on|go ahead|keep going|yes|yep|yup|sure|ok|okay|alright|do it|carry on|resume|next|try again|again|retry|re-try|do it again|run again|run it again|one more time|same again)$/.test(normalizedPrompt) ||
|
|
319
|
+
/^(try|do|run|go)\s+(it\s+|that\s+)?again$|^one more time$|^retry(\s+it)?$/i.test(normalizedPrompt);
|
|
320
|
+
if (isContinuation) {
|
|
321
|
+
const priorUserMessages = context.conversation.filter((m) => m.role === "user" && m.content.trim() && m.content.trim() !== context.userPrompt.trim());
|
|
322
|
+
const prior = priorUserMessages[priorUserMessages.length - 1];
|
|
323
|
+
if (prior) {
|
|
324
|
+
lines.push(`The user is continuing/retrying. Resume this previous request: ${prior.content}`);
|
|
325
|
+
lines.push("");
|
|
326
|
+
}
|
|
327
|
+
}
|
|
314
328
|
lines.push(`User request: ${context.userPrompt}`);
|
|
315
329
|
lines.push("");
|
|
316
330
|
lines.push("Project context:");
|
package/package.json
CHANGED