@lasso-ai/cli 1.2.3 → 1.2.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/ARCHITECTURE.md +10 -3
- package/CHANGELOG.md +38 -0
- package/README.md +23 -3
- package/dist/cli/agent.d.ts +38 -2
- package/dist/cli/agent.js +521 -72
- package/dist/cli/auth.js +3 -1
- package/dist/cli/bridge.d.ts +22 -6
- package/dist/cli/bridge.js +182 -49
- package/dist/cli/index.js +10 -0
- package/dist/cli/oneshot.d.ts +19 -1
- package/dist/cli/oneshot.js +611 -106
- package/dist/cli/project.d.ts +2 -1
- package/dist/cli/project.js +71 -26
- package/dist/overlay.js +8668 -6431
- package/package.json +1 -1
package/dist/cli/project.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export interface CollabConfig {
|
|
|
5
5
|
version?: string;
|
|
6
6
|
realtimeUrl: string;
|
|
7
7
|
apiUrl: string;
|
|
8
|
+
serverUrl: string;
|
|
8
9
|
registered: boolean;
|
|
9
10
|
registeredAt?: string;
|
|
10
11
|
claimed: boolean;
|
|
@@ -48,7 +49,7 @@ export declare function readProjectConfig(cwd: string): {
|
|
|
48
49
|
* running). Only `{ "id": "proj_…", "domain": "….lasso" }` is stored — the API key
|
|
49
50
|
* never touches this file.
|
|
50
51
|
*/
|
|
51
|
-
export declare function initProject(cwd: string, fileEnv: Record<string, string
|
|
52
|
+
export declare function initProject(cwd: string, fileEnv: Record<string, string>, forcedDomain?: string): Promise<InitResult>;
|
|
52
53
|
/**
|
|
53
54
|
* `lasso dev` — consumes `lasso.config.json`: authenticates with the API key, lets the
|
|
54
55
|
* server resolve the key's workspace, validates the project belongs to it, and
|
package/dist/cli/project.js
CHANGED
|
@@ -187,11 +187,21 @@ function promptForApiKey() {
|
|
|
187
187
|
* running). Only `{ "id": "proj_…", "domain": "….lasso" }` is stored — the API key
|
|
188
188
|
* never touches this file.
|
|
189
189
|
*/
|
|
190
|
-
async function initProject(cwd, fileEnv) {
|
|
190
|
+
async function initProject(cwd, fileEnv, forcedDomain) {
|
|
191
191
|
const realtimeUrl = realtimeUrlFrom(fileEnv).replace(/\/$/, "");
|
|
192
|
-
const
|
|
192
|
+
const serverUrl = (0, auth_1.serverUrlFrom)(fileEnv).replace(/\/$/, "");
|
|
193
|
+
const collabApi = `${realtimeUrl}/api/v1`;
|
|
193
194
|
const framework = (0, framework_1.detectFramework)(cwd);
|
|
194
195
|
const { name, payload } = await buildProjectMetadata(cwd, framework);
|
|
196
|
+
const existingConfig = readProjectConfig(cwd);
|
|
197
|
+
if (existingConfig?.id) {
|
|
198
|
+
payload.id = existingConfig.id;
|
|
199
|
+
payload.projectId = existingConfig.id;
|
|
200
|
+
}
|
|
201
|
+
const registry = (0, registry_1.loadRegistry)();
|
|
202
|
+
const existingHost = (0, registry_1.findByDirectory)(registry, cwd);
|
|
203
|
+
const domain = forcedDomain || (existingConfig?.domain ? existingConfig.domain : (existingHost ? existingHost.domain : (0, registry_1.generateUniqueDomain)(cwd, registry)));
|
|
204
|
+
payload.domain = domain;
|
|
195
205
|
let apiKey = resolveLassoApiKey(fileEnv);
|
|
196
206
|
if (!apiKey)
|
|
197
207
|
apiKey = (await promptForApiKey()) || "";
|
|
@@ -199,14 +209,30 @@ async function initProject(cwd, fileEnv) {
|
|
|
199
209
|
return { ok: false, error: "No Lasso API key found. Set LASSO_API_KEY in your environment or paste it when prompted." };
|
|
200
210
|
}
|
|
201
211
|
try {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
212
|
+
let response;
|
|
213
|
+
try {
|
|
214
|
+
// Registration lives on the Lasso API (api.lasso.byorello.space): it owns
|
|
215
|
+
// the workspace's project records and stores the local `.lasso` domain.
|
|
216
|
+
response = await (0, auth_1.fetchWithTimeout)(`${serverUrl}/api/v1/collab/projects/register`, {
|
|
217
|
+
method: "POST",
|
|
218
|
+
headers: {
|
|
219
|
+
"content-type": "application/json",
|
|
220
|
+
authorization: `Bearer ${apiKey}`,
|
|
221
|
+
},
|
|
222
|
+
body: JSON.stringify(payload),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
// Fall back to the realtime/collab server if the API is unreachable
|
|
227
|
+
response = await (0, auth_1.fetchWithTimeout)(`${collabApi}/collab/projects/register`, {
|
|
228
|
+
method: "POST",
|
|
229
|
+
headers: {
|
|
230
|
+
"content-type": "application/json",
|
|
231
|
+
authorization: `Bearer ${apiKey}`,
|
|
232
|
+
},
|
|
233
|
+
body: JSON.stringify(payload),
|
|
234
|
+
});
|
|
235
|
+
}
|
|
210
236
|
const body = (await response.json().catch(() => ({})));
|
|
211
237
|
if (!response.ok) {
|
|
212
238
|
if (response.status === 401) {
|
|
@@ -215,15 +241,13 @@ async function initProject(cwd, fileEnv) {
|
|
|
215
241
|
if (response.status === 403) {
|
|
216
242
|
return { ok: false, error: "Your API key does not have access to a Lasso workspace." };
|
|
217
243
|
}
|
|
218
|
-
|
|
244
|
+
const detail = body.message || body.error;
|
|
245
|
+
return { ok: false, error: detail ? `${detail} (HTTP ${response.status})` : `Project registration failed (${response.status}).` };
|
|
219
246
|
}
|
|
220
|
-
const projectId = body.project?.id;
|
|
247
|
+
const projectId = body.project?.id || existingConfig?.id;
|
|
221
248
|
if (!projectId) {
|
|
222
249
|
return { ok: false, error: "The server did not return a project id." };
|
|
223
250
|
}
|
|
224
|
-
const registry = (0, registry_1.loadRegistry)();
|
|
225
|
-
const existing = (0, registry_1.findByDirectory)(registry, cwd);
|
|
226
|
-
const domain = existing ? existing.domain : (0, registry_1.generateUniqueDomain)(cwd, registry);
|
|
227
251
|
await (0, client_1.registerWithHost)(domain, cwd, projectId, (0, paths_1.hostProxyPort)(fileEnv));
|
|
228
252
|
if (framework === "next") {
|
|
229
253
|
const injected = (0, next_config_1.ensureNextAllowedDevOrigin)(cwd, domain);
|
|
@@ -243,7 +267,7 @@ async function initProject(cwd, fileEnv) {
|
|
|
243
267
|
}
|
|
244
268
|
catch (error) {
|
|
245
269
|
const reason = error instanceof Error ? error.message : "request failed";
|
|
246
|
-
return { ok: false, error: `Could not reach the Lasso
|
|
270
|
+
return { ok: false, error: `Could not reach the Lasso API at ${serverUrl} (${reason}). Is it running?` };
|
|
247
271
|
}
|
|
248
272
|
}
|
|
249
273
|
/**
|
|
@@ -254,12 +278,15 @@ async function initProject(cwd, fileEnv) {
|
|
|
254
278
|
*/
|
|
255
279
|
async function resolveCollabSession(cwd, fileEnv, projectId) {
|
|
256
280
|
const realtimeUrl = realtimeUrlFrom(fileEnv).replace(/\/$/, "");
|
|
257
|
-
const
|
|
281
|
+
const serverUrl = (0, auth_1.serverUrlFrom)(fileEnv).replace(/\/$/, "");
|
|
282
|
+
const collabApi = `${realtimeUrl}/api/v1`;
|
|
283
|
+
const apiUrl = `${serverUrl}/api/v1`;
|
|
258
284
|
const config = {
|
|
259
285
|
projectId,
|
|
260
286
|
name: "",
|
|
261
287
|
version: "",
|
|
262
288
|
realtimeUrl,
|
|
289
|
+
serverUrl,
|
|
263
290
|
apiUrl,
|
|
264
291
|
registered: false,
|
|
265
292
|
claimed: false,
|
|
@@ -270,16 +297,34 @@ async function resolveCollabSession(cwd, fileEnv, projectId) {
|
|
|
270
297
|
return config;
|
|
271
298
|
}
|
|
272
299
|
try {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
300
|
+
let response = null;
|
|
301
|
+
try {
|
|
302
|
+
response = await (0, auth_1.fetchWithTimeout)(`${collabApi}/collab/projects/${encodeURIComponent(projectId)}/session`, {
|
|
303
|
+
method: "POST",
|
|
304
|
+
headers: { authorization: `Bearer ${apiKey}` },
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
// Collab server unreachable, will fall back below
|
|
309
|
+
}
|
|
310
|
+
if (!response || (!response.ok && (response.status === 502 || response.status === 503 || response.status === 504 || response.status === 404))) {
|
|
311
|
+
try {
|
|
312
|
+
response = await (0, auth_1.fetchWithTimeout)(`${serverUrl}/api/v1/collab/projects/${encodeURIComponent(projectId)}/session`, {
|
|
313
|
+
method: "POST",
|
|
314
|
+
headers: { authorization: `Bearer ${apiKey}` },
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
// Both unreachable
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (!response || !response.ok) {
|
|
322
|
+
const status = response?.status;
|
|
323
|
+
const reason = status === 401
|
|
279
324
|
? "Your Lasso API key is invalid or inactive."
|
|
280
|
-
:
|
|
325
|
+
: status === 403
|
|
281
326
|
? "This project belongs to another workspace."
|
|
282
|
-
: `The server rejected the project session (${
|
|
327
|
+
: `The server rejected the project session (${status || "unreachable"}).`;
|
|
283
328
|
console.warn(chalk_1.default.yellow("!") + ` Realtime collaboration unavailable: ${reason}`);
|
|
284
329
|
return config;
|
|
285
330
|
}
|
|
@@ -302,7 +347,7 @@ async function resolveCollabSession(cwd, fileEnv, projectId) {
|
|
|
302
347
|
}
|
|
303
348
|
catch (error) {
|
|
304
349
|
const reason = error instanceof Error ? error.message : "request failed";
|
|
305
|
-
console.warn(chalk_1.default.yellow("!") + ` Realtime collaboration unavailable: cannot reach
|
|
350
|
+
console.warn(chalk_1.default.yellow("!") + ` Realtime collaboration unavailable: cannot reach server (${reason}).`);
|
|
306
351
|
return config;
|
|
307
352
|
}
|
|
308
353
|
}
|