@lasso-ai/cli 1.4.5 → 2.0.0

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.
Files changed (59) hide show
  1. package/dist/cli/agent.d.ts +10 -89
  2. package/dist/cli/agent.js +66 -1412
  3. package/dist/cli/backends.d.ts +53 -0
  4. package/dist/cli/backends.js +267 -0
  5. package/dist/cli/bridge-old.d.ts +259 -0
  6. package/dist/cli/bridge-old.js +1350 -0
  7. package/dist/cli/bridge.d.ts +22 -12
  8. package/dist/cli/bridge.js +824 -1174
  9. package/dist/cli/host/install.js +12 -1
  10. package/dist/cli/host/next-host-entry.js +0 -2
  11. package/dist/cli/host/vite-host-entry.js +1 -3
  12. package/dist/cli/local-runtime.d.ts +28 -0
  13. package/dist/cli/local-runtime.js +294 -0
  14. package/dist/cli/oneshot.js +177 -961
  15. package/dist/cli/runtime-client.d.ts +310 -0
  16. package/dist/cli/runtime-client.js +178 -0
  17. package/dist/cli/snapshot.d.ts +3 -1
  18. package/dist/cli/snapshot.js +8 -1
  19. package/dist/overlay.js +44 -28
  20. package/dist/runtime/__tests__/adapter-normalization.test.d.ts +1 -0
  21. package/dist/runtime/__tests__/adapter-normalization.test.js +392 -0
  22. package/dist/runtime/__tests__/state-machine.test.d.ts +1 -0
  23. package/dist/runtime/__tests__/state-machine.test.js +107 -0
  24. package/dist/runtime/__tests__/verification-engine.test.d.ts +1 -0
  25. package/dist/runtime/__tests__/verification-engine.test.js +91 -0
  26. package/dist/runtime/__tests__/workspace-guard.test.d.ts +1 -0
  27. package/dist/runtime/__tests__/workspace-guard.test.js +104 -0
  28. package/dist/runtime/adapters/claude-code-adapter.d.ts +46 -0
  29. package/dist/runtime/adapters/claude-code-adapter.js +230 -0
  30. package/dist/runtime/adapters/codex-cli-adapter.d.ts +44 -0
  31. package/dist/runtime/adapters/codex-cli-adapter.js +202 -0
  32. package/dist/runtime/adapters/cursor-adapter.d.ts +47 -0
  33. package/dist/runtime/adapters/cursor-adapter.js +214 -0
  34. package/dist/runtime/adapters/factory.d.ts +19 -0
  35. package/dist/runtime/adapters/factory.js +48 -0
  36. package/dist/runtime/adapters/local-agent-adapter.d.ts +143 -0
  37. package/dist/runtime/adapters/local-agent-adapter.js +408 -0
  38. package/dist/runtime/adapters/opencode-adapter.d.ts +43 -0
  39. package/dist/runtime/adapters/opencode-adapter.js +210 -0
  40. package/dist/runtime/agent-runtime.d.ts +286 -0
  41. package/dist/runtime/agent-runtime.js +8 -0
  42. package/dist/runtime/agent-state-machine.d.ts +67 -0
  43. package/dist/runtime/agent-state-machine.js +234 -0
  44. package/dist/runtime/backend-interface.d.ts +272 -0
  45. package/dist/runtime/backend-interface.js +38 -0
  46. package/dist/runtime/event-mapper.d.ts +11 -0
  47. package/dist/runtime/event-mapper.js +40 -0
  48. package/dist/runtime/index.d.ts +20 -0
  49. package/dist/runtime/index.js +43 -0
  50. package/dist/runtime/local-session-runner.d.ts +60 -0
  51. package/dist/runtime/local-session-runner.js +185 -0
  52. package/dist/runtime/review.d.ts +24 -0
  53. package/dist/runtime/review.js +30 -0
  54. package/dist/runtime/verification-engine.d.ts +71 -0
  55. package/dist/runtime/verification-engine.js +374 -0
  56. package/dist/runtime/workspace-guard.d.ts +70 -0
  57. package/dist/runtime/workspace-guard.js +321 -0
  58. package/docs/local-coding-agents.md +183 -0
  59. package/package.json +22 -3
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Lasso Runtime Client
3
+ *
4
+ * Client for the new Lasso Agentic Runtime
5
+ * Uses SSE for real-time progress events
6
+ */
7
+ export type RuntimeProvider = "anthropic" | "openai" | "google" | "nvidia" | "ollama" | "claude_code" | "opencode" | "codex_cli" | "cursor";
8
+ export interface RuntimeSessionInput {
9
+ userPrompt: string;
10
+ project: {
11
+ projectId: string;
12
+ framework?: string;
13
+ hasTypeScript?: boolean;
14
+ hasReact?: boolean;
15
+ hasNext?: boolean;
16
+ hasVite?: boolean;
17
+ files?: string[];
18
+ currentRoute?: string;
19
+ };
20
+ model: {
21
+ provider: RuntimeProvider;
22
+ id: string;
23
+ name?: string;
24
+ };
25
+ selection?: {
26
+ element?: {
27
+ tag?: string;
28
+ text?: string;
29
+ source?: string;
30
+ attributes?: Record<string, string>;
31
+ };
32
+ viewport?: {
33
+ width: number;
34
+ height: number;
35
+ scrollY?: number;
36
+ scrollHeight?: number;
37
+ };
38
+ route?: string;
39
+ screenshot?: string;
40
+ };
41
+ conversationUid?: string;
42
+ backendConfig?: {
43
+ type: "hosted_model" | "local_agent";
44
+ provider: "claude_code" | "opencode" | "codex_cli" | "cursor";
45
+ modelId?: string;
46
+ projectPath?: string;
47
+ };
48
+ }
49
+ export interface RuntimeSession {
50
+ id: string;
51
+ phase: "understand" | "inspect" | "plan" | "execute" | "verify" | "recover" | "complete";
52
+ status: "running" | "waiting" | "completed" | "failed" | "cancelled";
53
+ iteration: number;
54
+ userPrompt: string;
55
+ conversation: Array<{
56
+ id: string;
57
+ role: "user" | "assistant" | "system" | "tool";
58
+ content: string;
59
+ timestamp: number;
60
+ metadata?: Record<string, unknown>;
61
+ }>;
62
+ observations: Array<{
63
+ id: string;
64
+ type: string;
65
+ summary: string;
66
+ data?: unknown;
67
+ timestamp: number;
68
+ phase?: string;
69
+ actionId?: string;
70
+ }>;
71
+ actions: Array<{
72
+ id: string;
73
+ type: string;
74
+ data: Record<string, unknown>;
75
+ }>;
76
+ completedActions: Array<{
77
+ id: string;
78
+ type: string;
79
+ data: Record<string, unknown>;
80
+ }>;
81
+ errors: Array<{
82
+ id: string;
83
+ type: string;
84
+ message: string;
85
+ phase: string;
86
+ actionId?: string;
87
+ timestamp: number;
88
+ recoverable: boolean;
89
+ }>;
90
+ plan?: {
91
+ id: string;
92
+ goal: string;
93
+ steps: Array<{
94
+ id: string;
95
+ description: string;
96
+ status: string;
97
+ actionCount?: number;
98
+ }>;
99
+ estimatedActions?: number;
100
+ };
101
+ selection?: RuntimeSessionInput["selection"];
102
+ project: RuntimeSessionInput["project"];
103
+ model: RuntimeSessionInput["model"];
104
+ conversationUid?: string;
105
+ createdAt: Date;
106
+ updatedAt: Date;
107
+ /** Runtime-owned metadata: pendingChanges, backendConfig, backendSessionId, … */
108
+ metadata?: Record<string, unknown>;
109
+ }
110
+ /** Result of post-apply verification (typecheck/build via VerificationEngine). */
111
+ export interface SessionVerificationResult {
112
+ passed: boolean;
113
+ errors: Array<{
114
+ id: string;
115
+ type: string;
116
+ message: string;
117
+ phase: string;
118
+ timestamp: number;
119
+ recoverable: boolean;
120
+ }>;
121
+ observations: Array<{
122
+ id: string;
123
+ type: string;
124
+ summary: string;
125
+ timestamp: number;
126
+ }>;
127
+ command?: string;
128
+ requiresFix: boolean;
129
+ }
130
+ /**
131
+ * The session surface shared by RuntimeClient (hosted, via Lasso server) and
132
+ * LocalRuntime (local coding agents, executed in this process).
133
+ */
134
+ export interface RuntimeFacade {
135
+ createSession(input: RuntimeSessionInput): Promise<RuntimeSession>;
136
+ runSession(sessionId: string, projectPath: string, onEvent: RuntimeEventHandler, signal?: AbortSignal): Promise<void>;
137
+ getSession(sessionId: string): Promise<RuntimeSession>;
138
+ verifySession(sessionId: string, projectPath: string): Promise<SessionVerificationResult>;
139
+ switchModel(sessionId: string, model: {
140
+ provider: string;
141
+ id: string;
142
+ name?: string;
143
+ }, apiKey?: string, backendConfig?: RuntimeSessionInput["backendConfig"]): Promise<void>;
144
+ cancelSession(sessionId: string): Promise<void>;
145
+ }
146
+ export type RuntimeEvent = {
147
+ type: "agent_started";
148
+ sessionId: string;
149
+ data: {};
150
+ timestamp: number;
151
+ } | {
152
+ type: "agent_reasoning";
153
+ sessionId: string;
154
+ data: {
155
+ summary: string;
156
+ };
157
+ timestamp: number;
158
+ } | {
159
+ type: "phase_changed";
160
+ sessionId: string;
161
+ data: {
162
+ from: string;
163
+ to: string;
164
+ };
165
+ timestamp: number;
166
+ } | {
167
+ type: "tool_started";
168
+ sessionId: string;
169
+ data: {
170
+ actionType: string;
171
+ };
172
+ timestamp: number;
173
+ } | {
174
+ type: "tool_completed";
175
+ sessionId: string;
176
+ data: {
177
+ actionType: string;
178
+ success: boolean;
179
+ };
180
+ timestamp: number;
181
+ } | {
182
+ type: "observation";
183
+ sessionId: string;
184
+ data: {
185
+ observationType: string;
186
+ summary: string;
187
+ };
188
+ timestamp: number;
189
+ } | {
190
+ type: "verification_started";
191
+ sessionId: string;
192
+ data: {
193
+ verificationType: string;
194
+ };
195
+ timestamp: number;
196
+ } | {
197
+ type: "verification_completed";
198
+ sessionId: string;
199
+ data: {
200
+ verificationType: string;
201
+ success: boolean;
202
+ };
203
+ timestamp: number;
204
+ } | {
205
+ type: "waiting_for_user";
206
+ sessionId: string;
207
+ data: {
208
+ question: string;
209
+ };
210
+ timestamp: number;
211
+ } | {
212
+ type: "error";
213
+ sessionId: string;
214
+ data: Record<string, unknown>;
215
+ timestamp: number;
216
+ } | {
217
+ type: "model_changed";
218
+ sessionId: string;
219
+ data: {
220
+ from: any;
221
+ to: any;
222
+ };
223
+ timestamp: number;
224
+ } | {
225
+ type: "agent_completed";
226
+ sessionId: string;
227
+ data: Record<string, unknown>;
228
+ timestamp: number;
229
+ } | {
230
+ type: "agent_cancelled";
231
+ sessionId: string;
232
+ data: Record<string, unknown>;
233
+ timestamp: number;
234
+ } | {
235
+ type: "agent_failed";
236
+ sessionId: string;
237
+ data: Record<string, unknown>;
238
+ timestamp: number;
239
+ } | {
240
+ type: "file_changed";
241
+ sessionId: string;
242
+ data: Record<string, unknown>;
243
+ timestamp: number;
244
+ } | {
245
+ type: "started";
246
+ sessionId: string;
247
+ } | {
248
+ type: "completed";
249
+ sessionId: string;
250
+ };
251
+ export type RuntimeEventHandler = (event: RuntimeEvent) => void | Promise<void>;
252
+ export declare class RuntimeClient {
253
+ private serverUrl;
254
+ private apiKey?;
255
+ constructor(serverUrl: string, apiKey?: string);
256
+ /**
257
+ * Create a new runtime session
258
+ */
259
+ createSession(input: RuntimeSessionInput): Promise<RuntimeSession>;
260
+ /**
261
+ * Get a session by ID
262
+ */
263
+ getSession(sessionId: string): Promise<RuntimeSession>;
264
+ /**
265
+ * Run a session with SSE event streaming
266
+ */
267
+ runSession(sessionId: string, projectPath: string, onEvent: RuntimeEventHandler, signal?: AbortSignal): Promise<void>;
268
+ /**
269
+ * Cancel a running session
270
+ */
271
+ cancelSession(sessionId: string): Promise<void>;
272
+ /**
273
+ * Switch model/backend for a session
274
+ */
275
+ switchModel(sessionId: string, model: {
276
+ provider: string;
277
+ id: string;
278
+ name?: string;
279
+ }, apiKey?: string, backendConfig?: RuntimeSessionInput["backendConfig"]): Promise<void>;
280
+ /**
281
+ * Verify the workspace for a session (after reviewed changes were applied).
282
+ *
283
+ * Returns whether verification passed; on failure the session keeps the
284
+ * verification errors so a corrective re-run can fix them.
285
+ */
286
+ verifySession(sessionId: string, projectPath: string): Promise<SessionVerificationResult>;
287
+ /**
288
+ * List available backends from the server (hosted providers + local agents).
289
+ */
290
+ listBackends(projectPath?: string): Promise<{
291
+ backends: Array<{
292
+ provider: string;
293
+ type: string;
294
+ available: boolean;
295
+ authenticated: boolean;
296
+ installed?: boolean;
297
+ version?: string;
298
+ error?: string;
299
+ fixInstructions?: string;
300
+ models?: Array<{
301
+ id: string;
302
+ label: string;
303
+ }>;
304
+ }>;
305
+ }>;
306
+ /**
307
+ * Delete a session
308
+ */
309
+ deleteSession(sessionId: string): Promise<void>;
310
+ }
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ /**
3
+ * Lasso Runtime Client
4
+ *
5
+ * Client for the new Lasso Agentic Runtime
6
+ * Uses SSE for real-time progress events
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.RuntimeClient = void 0;
10
+ class RuntimeClient {
11
+ serverUrl;
12
+ apiKey;
13
+ constructor(serverUrl, apiKey) {
14
+ this.serverUrl = serverUrl;
15
+ this.apiKey = apiKey;
16
+ }
17
+ /**
18
+ * Create a new runtime session
19
+ */
20
+ async createSession(input) {
21
+ const response = await fetch(`${this.serverUrl}/api/v1/agent-runtime/sessions`, {
22
+ method: "POST",
23
+ headers: {
24
+ "Content-Type": "application/json",
25
+ ...(this.apiKey && { "Authorization": `Bearer ${this.apiKey}` }),
26
+ },
27
+ body: JSON.stringify(input),
28
+ });
29
+ if (!response.ok) {
30
+ throw new Error(`Failed to create session: ${response.statusText}`);
31
+ }
32
+ const data = await response.json();
33
+ return data;
34
+ }
35
+ /**
36
+ * Get a session by ID
37
+ */
38
+ async getSession(sessionId) {
39
+ const response = await fetch(`${this.serverUrl}/api/v1/agent-runtime/sessions/${sessionId}`, {
40
+ headers: {
41
+ ...(this.apiKey && { "Authorization": `Bearer ${this.apiKey}` }),
42
+ },
43
+ });
44
+ if (!response.ok) {
45
+ throw new Error(`Failed to get session: ${response.statusText}`);
46
+ }
47
+ const data = await response.json();
48
+ return data;
49
+ }
50
+ /**
51
+ * Run a session with SSE event streaming
52
+ */
53
+ async runSession(sessionId, projectPath, onEvent, signal) {
54
+ const response = await fetch(`${this.serverUrl}/api/v1/agent-runtime/sessions/${sessionId}/run`, {
55
+ method: "POST",
56
+ headers: {
57
+ "Content-Type": "application/json",
58
+ ...(this.apiKey && { "Authorization": `Bearer ${this.apiKey}` }),
59
+ },
60
+ body: JSON.stringify({ projectPath }),
61
+ signal,
62
+ });
63
+ if (!response.ok) {
64
+ throw new Error(`Failed to run session: ${response.statusText}`);
65
+ }
66
+ const reader = response.body?.getReader();
67
+ if (!reader) {
68
+ throw new Error("No response body");
69
+ }
70
+ const decoder = new TextDecoder();
71
+ try {
72
+ while (true) {
73
+ const { done, value } = await reader.read();
74
+ if (done)
75
+ break;
76
+ const chunk = decoder.decode(value);
77
+ const lines = chunk.split("\n");
78
+ for (const line of lines) {
79
+ if (!line.trim() || !line.startsWith("data: "))
80
+ continue;
81
+ const data = line.slice(6);
82
+ if (data === "[DONE]")
83
+ continue;
84
+ try {
85
+ const event = JSON.parse(data);
86
+ await onEvent(event);
87
+ }
88
+ catch (error) {
89
+ console.error("Failed to parse SSE event:", error);
90
+ }
91
+ }
92
+ }
93
+ }
94
+ finally {
95
+ reader.releaseLock();
96
+ }
97
+ }
98
+ /**
99
+ * Cancel a running session
100
+ */
101
+ async cancelSession(sessionId) {
102
+ const response = await fetch(`${this.serverUrl}/api/v1/agent-runtime/sessions/${sessionId}/cancel`, {
103
+ method: "POST",
104
+ headers: {
105
+ ...(this.apiKey && { "Authorization": `Bearer ${this.apiKey}` }),
106
+ },
107
+ });
108
+ if (!response.ok) {
109
+ throw new Error(`Failed to cancel session: ${response.statusText}`);
110
+ }
111
+ }
112
+ /**
113
+ * Switch model/backend for a session
114
+ */
115
+ async switchModel(sessionId, model, apiKey, backendConfig) {
116
+ const response = await fetch(`${this.serverUrl}/api/v1/agent-runtime/sessions/${sessionId}/model`, {
117
+ method: "POST",
118
+ headers: {
119
+ "Content-Type": "application/json",
120
+ ...(this.apiKey && { "Authorization": `Bearer ${this.apiKey}` }),
121
+ },
122
+ body: JSON.stringify({ ...model, apiKey, backendConfig }),
123
+ });
124
+ if (!response.ok) {
125
+ throw new Error(`Failed to switch model: ${response.statusText}`);
126
+ }
127
+ }
128
+ /**
129
+ * Verify the workspace for a session (after reviewed changes were applied).
130
+ *
131
+ * Returns whether verification passed; on failure the session keeps the
132
+ * verification errors so a corrective re-run can fix them.
133
+ */
134
+ async verifySession(sessionId, projectPath) {
135
+ const response = await fetch(`${this.serverUrl}/api/v1/agent-runtime/sessions/${sessionId}/verify`, {
136
+ method: "POST",
137
+ headers: {
138
+ "Content-Type": "application/json",
139
+ ...(this.apiKey && { "Authorization": `Bearer ${this.apiKey}` }),
140
+ },
141
+ body: JSON.stringify({ projectPath }),
142
+ });
143
+ if (!response.ok) {
144
+ throw new Error(`Failed to verify session: ${response.statusText}`);
145
+ }
146
+ return (await response.json());
147
+ }
148
+ /**
149
+ * List available backends from the server (hosted providers + local agents).
150
+ */
151
+ async listBackends(projectPath) {
152
+ const url = `${this.serverUrl}/api/v1/agent-runtime/backends${projectPath ? `?projectPath=${encodeURIComponent(projectPath)}` : ""}`;
153
+ const response = await fetch(url, {
154
+ headers: {
155
+ ...(this.apiKey && { "Authorization": `Bearer ${this.apiKey}` }),
156
+ },
157
+ });
158
+ if (!response.ok) {
159
+ throw new Error(`Failed to list backends: ${response.statusText}`);
160
+ }
161
+ return (await response.json());
162
+ }
163
+ /**
164
+ * Delete a session
165
+ */
166
+ async deleteSession(sessionId) {
167
+ const response = await fetch(`${this.serverUrl}/api/v1/agent-runtime/sessions/${sessionId}`, {
168
+ method: "DELETE",
169
+ headers: {
170
+ ...(this.apiKey && { "Authorization": `Bearer ${this.apiKey}` }),
171
+ },
172
+ });
173
+ if (!response.ok) {
174
+ throw new Error(`Failed to delete session: ${response.statusText}`);
175
+ }
176
+ }
177
+ }
178
+ exports.RuntimeClient = RuntimeClient;
@@ -7,6 +7,7 @@ export type FileSnapshot = {
7
7
  export type TimelineSnapshot = {
8
8
  id: string;
9
9
  taskId: string;
10
+ sessionId?: string;
10
11
  summary: string;
11
12
  files: FileSnapshot[];
12
13
  createdAt: string;
@@ -19,7 +20,7 @@ export type ConflictInfo = {
19
20
  originalContent: string;
20
21
  currentContent: string;
21
22
  };
22
- export declare function createSnapshot(cwd: string, taskId: string, summary: string, filePaths: string[], parentSnapshotId?: string): TimelineSnapshot;
23
+ export declare function createSnapshot(cwd: string, taskId: string, summary: string, filePaths: string[], parentSnapshotId?: string, sessionId?: string): TimelineSnapshot;
23
24
  export declare function restoreSnapshot(cwd: string, snapshotId: string): boolean;
24
25
  export declare function detectConflicts(cwd: string, expectedFiles: Array<{
25
26
  filePath: string;
@@ -30,4 +31,5 @@ export declare function getTimeline(cwd: string, limit?: number): TimelineSnapsh
30
31
  export declare function deleteSnapshot(cwd: string, snapshotId: string): boolean;
31
32
  export declare function clearSnapshots(cwd: string): void;
32
33
  export declare function getSnapshotByTaskId(cwd: string, taskId: string): TimelineSnapshot | undefined;
34
+ export declare function getSnapshotBySessionId(cwd: string, sessionId: string): TimelineSnapshot | undefined;
33
35
  export declare function getLatestSnapshot(cwd: string): TimelineSnapshot | undefined;
@@ -10,6 +10,7 @@ exports.getTimeline = getTimeline;
10
10
  exports.deleteSnapshot = deleteSnapshot;
11
11
  exports.clearSnapshots = clearSnapshots;
12
12
  exports.getSnapshotByTaskId = getSnapshotByTaskId;
13
+ exports.getSnapshotBySessionId = getSnapshotBySessionId;
13
14
  exports.getLatestSnapshot = getLatestSnapshot;
14
15
  // src/cli/snapshot.ts
15
16
  // Local history snapshot system for safe concurrent edits
@@ -59,7 +60,7 @@ function saveTimeline(cwd, timeline) {
59
60
  }
60
61
  }
61
62
  // Create a snapshot of current file states
62
- function createSnapshot(cwd, taskId, summary, filePaths, parentSnapshotId) {
63
+ function createSnapshot(cwd, taskId, summary, filePaths, parentSnapshotId, sessionId) {
63
64
  ensureSnapshotsDir(cwd);
64
65
  const snapshotId = generateSnapshotId();
65
66
  const files = [];
@@ -87,6 +88,7 @@ function createSnapshot(cwd, taskId, summary, filePaths, parentSnapshotId) {
87
88
  const snapshot = {
88
89
  id: snapshotId,
89
90
  taskId,
91
+ sessionId,
90
92
  summary,
91
93
  files,
92
94
  createdAt: timestamp,
@@ -218,6 +220,11 @@ function getSnapshotByTaskId(cwd, taskId) {
218
220
  const timeline = loadTimeline(cwd);
219
221
  return timeline.find((s) => s.taskId === taskId);
220
222
  }
223
+ // Get snapshot by session ID
224
+ function getSnapshotBySessionId(cwd, sessionId) {
225
+ const timeline = loadTimeline(cwd);
226
+ return timeline.find((s) => s.sessionId === sessionId);
227
+ }
221
228
  // Get latest snapshot
222
229
  function getLatestSnapshot(cwd) {
223
230
  const timeline = loadTimeline(cwd);