@lasso-ai/cli 1.0.6 → 1.0.7

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/README.md CHANGED
@@ -186,6 +186,17 @@ Point the overlay at a different realtime server with any of
186
186
  `LASSO_REALTIME_URL`, `REALTIME_URL`, or `NEXT_PUBLIC_REALTIME_URL`
187
187
  (default: `http://localhost:3007`).
188
188
 
189
+ If the overlay connection gets stuck while `lasso dev` is running, reset it
190
+ without restarting your framework with:
191
+
192
+ ```bash
193
+ lasso bridge restart
194
+ ```
195
+
196
+ The command closes the current overlay WebSocket, cancels any active agent
197
+ request, and lets the overlay reconnect to the existing bridge. Use
198
+ `--port <port>` when the bridge is running on a custom port.
199
+
189
200
  ---
190
201
 
191
202
  ## Local domains with Lasso Host
@@ -1,5 +1,6 @@
1
1
  import { type SourceChange } from "./agent";
2
2
  import type { CollabConfig } from "./project";
3
+ export declare const DEFAULT_BRIDGE_PORT = 3056;
3
4
  type GitState = {
4
5
  isRepo: boolean;
5
6
  branch?: string;
@@ -153,6 +154,10 @@ export type ServerBridgeMessage = {
153
154
  provider?: string;
154
155
  error?: string;
155
156
  };
157
+ export declare function restartBridge(port?: number): Promise<{
158
+ ok: boolean;
159
+ error?: string;
160
+ }>;
156
161
  export declare function startBridge(cwd?: string, collabConfig?: CollabConfig | null, bridgePort?: number): {
157
162
  send: (msg: ServerBridgeMessage) => void;
158
163
  close(): void;
@@ -3,6 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DEFAULT_BRIDGE_PORT = void 0;
7
+ exports.restartBridge = restartBridge;
6
8
  exports.startBridge = startBridge;
7
9
  // src/cli/bridge.ts
8
10
  const ws_1 = require("ws");
@@ -14,8 +16,20 @@ const node_util_1 = require("node:util");
14
16
  const chalk_1 = __importDefault(require("chalk"));
15
17
  const agent_1 = require("./agent");
16
18
  const auth_1 = require("./auth");
17
- const DEFAULT_BRIDGE_PORT = 3056;
19
+ exports.DEFAULT_BRIDGE_PORT = 3056;
18
20
  const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
21
+ async function restartBridge(port = exports.DEFAULT_BRIDGE_PORT) {
22
+ try {
23
+ const response = await fetch(`http://127.0.0.1:${port}/__lasso/bridge/restart`, { method: "POST" });
24
+ const body = await response.json().catch(() => ({}));
25
+ if (!response.ok || !body.ok)
26
+ return { ok: false, error: body.error || "The bridge rejected the restart request." };
27
+ return { ok: true };
28
+ }
29
+ catch {
30
+ return { ok: false, error: `No Lasso bridge is listening on 127.0.0.1:${port}. Start your project with ${chalk_1.default.cyan("lasso dev")} first.` };
31
+ }
32
+ }
19
33
  async function gitCommand(cwd, args) {
20
34
  const result = await execFileAsync("git", args, { cwd, maxBuffer: 1024 * 1024 });
21
35
  return result.stdout.trim();
@@ -82,7 +96,7 @@ function readEnvFile(cwd, filename) {
82
96
  return {};
83
97
  }
84
98
  }
85
- function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = DEFAULT_BRIDGE_PORT) {
99
+ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = exports.DEFAULT_BRIDGE_PORT) {
86
100
  const bridgeServer = node_http_1.default.createServer(); // dedicated, empty HTTP server
87
101
  const wss = new ws_1.WebSocketServer({ server: bridgeServer });
88
102
  let overlaySocket = null;
@@ -116,6 +130,16 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = DEFA
116
130
  })();
117
131
  let activeAgentController = null;
118
132
  let localAgents = new Set();
133
+ bridgeServer.on("request", (req, res) => {
134
+ if (req.method !== "POST" || req.url?.split("?", 1)[0] !== "/__lasso/bridge/restart")
135
+ return;
136
+ activeAgentController?.abort();
137
+ activeAgentController = null;
138
+ for (const socket of wss.clients)
139
+ socket.close(1000, "Bridge restarted by the CLI");
140
+ res.writeHead(200, { "content-type": "application/json" });
141
+ res.end(JSON.stringify({ ok: true }));
142
+ });
119
143
  async function localModels() {
120
144
  const base = process.env.OLLAMA_BASE_URL || fileEnv.OLLAMA_BASE_URL || "http://localhost:11434/api";
121
145
  try {
@@ -13,6 +13,7 @@ export declare class LassoHost {
13
13
  private readonly resolver;
14
14
  private readonly registry;
15
15
  private readonly running;
16
+ private readonly starting;
16
17
  private readonly crashLog;
17
18
  private readonly proxies;
18
19
  constructor(opts: HostRuntimeOptions);
@@ -52,6 +52,7 @@ class LassoHost {
52
52
  resolver;
53
53
  registry;
54
54
  running = new Map();
55
+ starting = new Map();
55
56
  crashLog = new Map();
56
57
  proxies = new Map();
57
58
  constructor(opts) {
@@ -106,6 +107,9 @@ class LassoHost {
106
107
  const existing = this.running.get(domain);
107
108
  if (existing)
108
109
  return existing;
110
+ const pending = this.starting.get(domain);
111
+ if (pending)
112
+ return pending;
109
113
  const project = this.registry[domain];
110
114
  if (!project)
111
115
  return null;
@@ -114,20 +118,30 @@ class LassoHost {
114
118
  throw new Error(`${domain} kept crashing on startup; not auto-restarting. Fix the project or run "lasso daemon restart".`);
115
119
  }
116
120
  this.crashLog.set(domain, crashes);
117
- const result = await (0, runtime_1.startProjectRuntime)(project.directory);
118
- if (!result.ok || !result.runtime) {
119
- this.crashLog.set(domain, [...crashes, Date.now()]);
120
- throw new Error(result.error || `Could not start ${domain}.`);
121
- }
122
- const runtime = result.runtime;
123
- this.running.set(domain, runtime);
124
- runtime.child.on("exit", (code, signal) => {
125
- if (this.running.get(domain) === runtime) {
126
- this.running.delete(domain);
127
- this.log(`project ${domain} exited (code=${code} signal=${signal})`);
121
+ const startup = (async () => {
122
+ const result = await (0, runtime_1.startProjectRuntime)(project.directory);
123
+ if (!result.ok || !result.runtime) {
124
+ this.crashLog.set(domain, [...crashes, Date.now()]);
125
+ throw new Error(result.error || `Could not start ${domain}.`);
128
126
  }
129
- });
130
- return runtime;
127
+ const runtime = result.runtime;
128
+ this.running.set(domain, runtime);
129
+ runtime.child.on("exit", (code, signal) => {
130
+ if (this.running.get(domain) === runtime) {
131
+ this.running.delete(domain);
132
+ this.log(`project ${domain} exited (code=${code} signal=${signal})`);
133
+ }
134
+ });
135
+ return runtime;
136
+ })();
137
+ this.starting.set(domain, startup);
138
+ try {
139
+ return await startup;
140
+ }
141
+ finally {
142
+ if (this.starting.get(domain) === startup)
143
+ this.starting.delete(domain);
144
+ }
131
145
  }
132
146
  // ---- control surface ---------------------------------------------
133
147
  routes() {
package/dist/cli/index.js CHANGED
@@ -26,6 +26,19 @@ program.name("lasso").description("Select UI in your running app, describe a cha
26
26
  function projectEnv() {
27
27
  return (0, project_1.readProjectEnv)(process.cwd());
28
28
  }
29
+ const bridge = program.command("bridge").description("Manage the Lasso overlay bridge");
30
+ bridge.command("restart")
31
+ .description("Reset the active bridge connection and reconnect the overlay")
32
+ .option("--port <port>", "Bridge port", "3056")
33
+ .action(async (options) => {
34
+ const result = await (0, bridge_1.restartBridge)(Number(options.port));
35
+ if (!result.ok) {
36
+ console.error(chalk_1.default.red("✗") + ` ${result.error}`);
37
+ process.exitCode = 1;
38
+ return;
39
+ }
40
+ console.log(chalk_1.default.green("✓") + " Lasso bridge restarted. The overlay will reconnect automatically.");
41
+ });
29
42
  // prettier-ignore
30
43
  program.command("init")
31
44
  .description("Register this app with your Lasso workspace, create lasso.config.json, and register a local .lasso domain with Lasso Host")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lasso-ai/cli",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Select any part of your running app, describe a change, and let AI edit the real source code.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/cli/index.js",