@lasso-ai/cli 1.2.6 → 1.3.1
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 +175 -31
- package/dist/cli/bridge.d.ts +9 -2
- package/dist/cli/bridge.js +199 -50
- package/dist/cli/host/next-host-entry.js +1 -1
- package/dist/cli/host/vite-host-entry.js +1 -1
- package/dist/cli/index.js +18 -1
- package/dist/cli/oneshot.d.ts +0 -1
- package/dist/cli/oneshot.js +137 -75
- package/dist/cli/project.d.ts +28 -0
- package/dist/cli/project.js +57 -0
- package/dist/overlay.js +49 -1
- package/package.json +1 -1
package/dist/cli/bridge.js
CHANGED
|
@@ -147,6 +147,91 @@ function proposalMatchesCurrentSource(cwd, changes) {
|
|
|
147
147
|
return false;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
+
async function validateBuild(cwd) {
|
|
151
|
+
const pkgPath = node_path_1.default.join(cwd, "package.json");
|
|
152
|
+
if (!node_fs_1.default.existsSync(pkgPath)) {
|
|
153
|
+
return { passed: true, errors: [], command: "none" };
|
|
154
|
+
}
|
|
155
|
+
const pkg = JSON.parse(node_fs_1.default.readFileSync(pkgPath, "utf8"));
|
|
156
|
+
const scripts = pkg.scripts || {};
|
|
157
|
+
// Determine which build command to run
|
|
158
|
+
let buildCommand = "";
|
|
159
|
+
if (scripts.build) {
|
|
160
|
+
buildCommand = "build";
|
|
161
|
+
}
|
|
162
|
+
else if (scripts["build:cli"] || scripts["build:overlay"]) {
|
|
163
|
+
// Monorepo with separate build scripts
|
|
164
|
+
buildCommand = scripts["build:cli"] ? "build:cli" : "build:overlay";
|
|
165
|
+
}
|
|
166
|
+
else if (scripts.compile) {
|
|
167
|
+
buildCommand = "compile";
|
|
168
|
+
}
|
|
169
|
+
else if (scripts.check) {
|
|
170
|
+
buildCommand = "check";
|
|
171
|
+
}
|
|
172
|
+
else if (scripts.lint) {
|
|
173
|
+
buildCommand = "lint";
|
|
174
|
+
}
|
|
175
|
+
else if (scripts.typecheck) {
|
|
176
|
+
buildCommand = "typecheck";
|
|
177
|
+
}
|
|
178
|
+
else if (node_fs_1.default.existsSync(node_path_1.default.join(cwd, "tsconfig.json"))) {
|
|
179
|
+
buildCommand = "tsc"; // Run TypeScript compiler directly
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
// No suitable build command found
|
|
183
|
+
return { passed: true, errors: [], command: "none" };
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
const result = await execFileAsync(buildCommand === "tsc" ? "tsc" : "npm", buildCommand === "tsc" ? [] : ["run", buildCommand], { cwd, maxBuffer: 1024 * 1024 * 10, timeout: 60000 });
|
|
187
|
+
const output = result.stdout + result.stderr;
|
|
188
|
+
const errors = [];
|
|
189
|
+
// Parse TypeScript errors
|
|
190
|
+
if (output.includes("error TS")) {
|
|
191
|
+
const tsErrors = output.match(/error TS\d+.*$/gm) || [];
|
|
192
|
+
errors.push(...tsErrors);
|
|
193
|
+
}
|
|
194
|
+
// Parse general build errors
|
|
195
|
+
if (output.includes("Error:") || output.includes("error:")) {
|
|
196
|
+
const lines = output.split("\n");
|
|
197
|
+
for (const line of lines) {
|
|
198
|
+
if (line.includes("Error:") || line.includes("error:")) {
|
|
199
|
+
errors.push(line.trim());
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
passed: errors.length === 0,
|
|
205
|
+
errors,
|
|
206
|
+
command: buildCommand === "tsc" ? "tsc" : `npm run ${buildCommand}`
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
const stderr = error.stderr || "";
|
|
211
|
+
const errors = [];
|
|
212
|
+
if (stderr.includes("error TS")) {
|
|
213
|
+
const tsErrors = stderr.match(/error TS\d+.*$/gm) || [];
|
|
214
|
+
errors.push(...tsErrors);
|
|
215
|
+
}
|
|
216
|
+
if (stderr.includes("Error:") || stderr.includes("error:")) {
|
|
217
|
+
const lines = stderr.split("\n");
|
|
218
|
+
for (const line of lines) {
|
|
219
|
+
if (line.includes("Error:") || line.includes("error:")) {
|
|
220
|
+
errors.push(line.trim());
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// If no specific errors found, include the full stderr
|
|
225
|
+
if (errors.length === 0 && stderr) {
|
|
226
|
+
errors.push(stderr);
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
passed: false,
|
|
230
|
+
errors,
|
|
231
|
+
command: buildCommand === "tsc" ? "tsc" : `npm run ${buildCommand}`
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
150
235
|
function readEnvFile(cwd, filename) {
|
|
151
236
|
try {
|
|
152
237
|
return node_fs_1.default.readFileSync(node_path_1.default.join(cwd, filename), "utf8").split(/\r?\n/).reduce((values, line) => {
|
|
@@ -164,7 +249,7 @@ function readEnvFile(cwd, filename) {
|
|
|
164
249
|
return {};
|
|
165
250
|
}
|
|
166
251
|
}
|
|
167
|
-
function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = exports.DEFAULT_BRIDGE_PORT) {
|
|
252
|
+
async function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = exports.DEFAULT_BRIDGE_PORT) {
|
|
168
253
|
const bridgeServer = node_http_1.default.createServer(); // dedicated, empty HTTP server
|
|
169
254
|
const wss = new ws_1.WebSocketServer({ server: bridgeServer });
|
|
170
255
|
let overlaySocket = null;
|
|
@@ -179,7 +264,10 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
179
264
|
...readEnvFile(root, ".env.local"),
|
|
180
265
|
...readEnvFile(root, ".env.production"),
|
|
181
266
|
}), {});
|
|
182
|
-
|
|
267
|
+
// Prioritize CLI auth credentials over env vars
|
|
268
|
+
const cliCredentials = (0, auth_1.loadCredentials)();
|
|
269
|
+
const resolvedLassoKey = cliCredentials?.apiKey ||
|
|
270
|
+
(0, project_1.resolveLassoApiKey)(fileEnv) ||
|
|
183
271
|
process.env.LASSO_API_KEY ||
|
|
184
272
|
fileEnv.LASSO_API_KEY ||
|
|
185
273
|
process.env.VITE_LASSO_API_KEY ||
|
|
@@ -188,6 +276,19 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
188
276
|
fileEnv.NEXT_LASSO_API_KEY ||
|
|
189
277
|
"";
|
|
190
278
|
const lassoKeyConfigured = Boolean(resolvedLassoKey);
|
|
279
|
+
// Fetch workspace configuration from server (dashboard-configured providers)
|
|
280
|
+
let workspaceConfig = null;
|
|
281
|
+
if (lassoKeyConfigured) {
|
|
282
|
+
workspaceConfig = await (0, project_1.resolveWorkspaceConfig)(fileEnv);
|
|
283
|
+
}
|
|
284
|
+
// Fetch available models from server
|
|
285
|
+
let dynamicModels = { anthropic: [], openai: [], google: [], nvidia: [] };
|
|
286
|
+
try {
|
|
287
|
+
dynamicModels = await (0, project_1.fetchModels)(fileEnv);
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
console.warn('[Lasso] Failed to fetch dynamic models, using fallback');
|
|
291
|
+
}
|
|
191
292
|
const localProviderKeys = {
|
|
192
293
|
google: process.env.GOOGLE_GENERATIVE_AI_API_KEY || fileEnv.GOOGLE_GENERATIVE_AI_API_KEY || process.env.GEMINI_API_KEY || fileEnv.GEMINI_API_KEY,
|
|
193
294
|
openai: process.env.OPENAI_API_KEY || fileEnv.OPENAI_API_KEY,
|
|
@@ -197,8 +298,9 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
197
298
|
};
|
|
198
299
|
let agentConfig = (() => {
|
|
199
300
|
const provider = (process.env.LASSO_AGENT_PROVIDER || fileEnv.LASSO_AGENT_PROVIDER || process.env.AI_PROVIDER || fileEnv.AI_PROVIDER || "").toLowerCase();
|
|
200
|
-
const selectedProvider = provider === "google" || provider === "gemini" ? "google" : provider === "openai" ? "openai" : provider === "ollama" ? "ollama" : provider === "anthropic" ? "anthropic" : provider === "nvidia" ? "nvidia" : localProviderKeys.ollama ? "ollama" : localProviderKeys.nvidia ? "nvidia" : localProviderKeys.google ? "google" : localProviderKeys.openai ? "openai" : localProviderKeys.anthropic ? "anthropic" : "google";
|
|
301
|
+
const selectedProvider = provider === "google" || provider === "gemini" ? "google" : provider === "openai" ? "openai" : provider === "ollama" ? "ollama" : provider === "anthropic" ? "anthropic" : provider === "nvidia" ? "nvidia" : localProviderKeys.ollama ? "ollama" : localProviderKeys.nvidia ? "nvidia" : localProviderKeys.google ? "google" : localProviderKeys.openai ? "openai" : localProviderKeys.anthropic ? "anthropic" : (cliCredentials ? "anthropic" : "google");
|
|
201
302
|
const apiKey = selectedProvider === "ollama" ? "ollama" : localProviderKeys[selectedProvider];
|
|
303
|
+
// If user has CLI auth, use Lasso gateway by default
|
|
202
304
|
if (!apiKey && !lassoKeyConfigured)
|
|
203
305
|
return null;
|
|
204
306
|
return {
|
|
@@ -301,7 +403,7 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
301
403
|
return [];
|
|
302
404
|
}
|
|
303
405
|
}
|
|
304
|
-
const availableModels = async (collabConfig = null) => {
|
|
406
|
+
const availableModels = async (collabConfig = null, workspaceConfig = null) => {
|
|
305
407
|
localAgents = await (0, agent_1.detectLocalAgents)();
|
|
306
408
|
const locals = await localModels();
|
|
307
409
|
const discoveredOpenCodeModels = await openCodeModels();
|
|
@@ -310,51 +412,67 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
310
412
|
const base = process.env.OLLAMA_BASE_URL || fileEnv.OLLAMA_BASE_URL || "http://localhost:11434/api";
|
|
311
413
|
agentConfig = { provider: "ollama", apiKey: "ollama", model: process.env.OLLAMA_MODEL || fileEnv.OLLAMA_MODEL, baseUrl: `${base.replace(/\/api\/?$/, "")}/v1` };
|
|
312
414
|
}
|
|
313
|
-
|
|
314
|
-
const
|
|
415
|
+
// Check if user has CLI auth credentials (lasso auth login)
|
|
416
|
+
const cliCredentials = (0, auth_1.loadCredentials)();
|
|
417
|
+
const hasCliAuth = Boolean(cliCredentials?.apiKey);
|
|
418
|
+
// Prioritize workspace config (dashboard) over project config
|
|
419
|
+
// Workspace config is fetched independently of project config
|
|
420
|
+
const workspacePlan = (workspaceConfig?.plan || "free").toLowerCase();
|
|
421
|
+
const workspaceProviders = workspaceConfig?.configuredProviders || [];
|
|
422
|
+
const projectPlan = (collabConfig?.plan || "free").toLowerCase();
|
|
423
|
+
const projectProviders = collabConfig?.configuredProviders || [];
|
|
424
|
+
// Use the highest-tier plan available
|
|
425
|
+
const isPaidPlan = workspacePlan !== "free" || projectPlan !== "free";
|
|
426
|
+
// Use workspace providers if available, otherwise fall back to project providers
|
|
427
|
+
const configuredProviders = workspaceProviders.length > 0 ? workspaceProviders : projectProviders;
|
|
428
|
+
// Build model list from dynamic server fetch, falling back to hardcoded models
|
|
315
429
|
const allModels = [
|
|
316
|
-
//
|
|
317
|
-
{ id:
|
|
318
|
-
{ id:
|
|
319
|
-
{ id:
|
|
320
|
-
{ id:
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
430
|
+
// Dynamic models from server API
|
|
431
|
+
...dynamicModels.anthropic.map(m => ({ id: m.id, label: m.name, provider: m.provider })),
|
|
432
|
+
...dynamicModels.openai.map(m => ({ id: m.id, label: m.name, provider: m.provider })),
|
|
433
|
+
...dynamicModels.google.map(m => ({ id: m.id, label: m.name, provider: m.provider })),
|
|
434
|
+
...dynamicModels.nvidia.map(m => ({ id: m.id, label: m.name, provider: m.provider })),
|
|
435
|
+
// Fallback hardcoded models (only if dynamic fetch failed)
|
|
436
|
+
...(dynamicModels.anthropic.length === 0 ? [
|
|
437
|
+
{ id: "claude-opus-4-5-20251101", label: "Claude Opus 4.5", provider: "anthropic" },
|
|
438
|
+
{ id: "claude-sonnet-4-5-20250929", label: "Claude Sonnet 4.5", provider: "anthropic" },
|
|
439
|
+
{ id: "claude-haiku-4-5-20251015", label: "Claude Haiku 4.5", provider: "anthropic" },
|
|
440
|
+
] : []),
|
|
441
|
+
...(dynamicModels.openai.length === 0 ? [
|
|
442
|
+
{ id: "gpt-5.1", label: "GPT-5.1", provider: "openai" },
|
|
443
|
+
{ id: "gpt-5.1-codex", label: "GPT-5.1 Codex", provider: "openai" },
|
|
444
|
+
{ id: "gpt-5.1-codex-mini", label: "GPT-5.1 Codex Mini", provider: "openai" },
|
|
445
|
+
{ id: "o3", label: "OpenAI o3", provider: "openai" },
|
|
446
|
+
{ id: "o3-mini", label: "OpenAI o3-mini", provider: "openai" },
|
|
447
|
+
] : []),
|
|
448
|
+
...(dynamicModels.google.length === 0 ? [
|
|
449
|
+
{ id: "gemini-3-pro-preview", label: "Gemini 3 Pro", provider: "google" },
|
|
450
|
+
{ id: "gemini-3-flash-preview", label: "Gemini 3 Flash", provider: "google" },
|
|
451
|
+
{ id: "gemini-2.5-flash-preview-09-2025", label: "Gemini 2.5 Flash", provider: "google" },
|
|
452
|
+
{ id: "gemini-2.5-flash-lite-preview-09-2025", label: "Gemini 2.5 Flash Lite", provider: "google" },
|
|
453
|
+
] : []),
|
|
454
|
+
...(dynamicModels.nvidia.length === 0 ? [
|
|
455
|
+
{ id: "nvidia/llama-3.3-nemotron-super-49b-v1", label: "Llama 3.3 Nemotron Super 49B", provider: "nvidia" },
|
|
456
|
+
{ id: "deepseek-ai/deepseek-r1-distill-llama-70b", label: "DeepSeek R1 Distill Llama 70B", provider: "nvidia" },
|
|
457
|
+
{ id: "deepseek-ai/deepseek-r1-distill-llama-8b", label: "DeepSeek R1 Distill Llama 8B", provider: "nvidia" },
|
|
458
|
+
{ id: "google/gemma-3-1b-it", label: "Gemma 3 1B Instruct", provider: "nvidia" },
|
|
459
|
+
{ id: "openai/gpt-oss-120b", label: "GPT-OSS 120B", provider: "nvidia" },
|
|
460
|
+
] : []),
|
|
461
|
+
// Local CLI agents (always included)
|
|
344
462
|
...(localAgents.has("claude-code") ? [
|
|
345
|
-
{ id: "claude-code:sonnet", label: "Claude Code · Sonnet", provider: "cli" },
|
|
346
|
-
{ id: "claude-code:opus", label: "Claude Code · Opus", provider: "cli" },
|
|
347
|
-
{ id: "claude-code:haiku", label: "Claude Code · Haiku", provider: "cli" },
|
|
463
|
+
{ id: "claude-code:sonnet", label: "Claude Code · Sonnet 4.5", provider: "cli" },
|
|
464
|
+
{ id: "claude-code:opus", label: "Claude Code · Opus 4.5", provider: "cli" },
|
|
465
|
+
{ id: "claude-code:haiku", label: "Claude Code · Haiku 4.5", provider: "cli" },
|
|
348
466
|
] : []),
|
|
349
467
|
...(localAgents.has("codex") ? [
|
|
350
|
-
{ id: "codex:gpt-5", label: "Codex · GPT-5", provider: "cli" },
|
|
351
|
-
{ id: "codex:gpt-5-codex", label: "Codex · GPT-5-Codex", provider: "cli" },
|
|
468
|
+
{ id: "codex:gpt-5.1", label: "Codex · GPT-5.1", provider: "cli" },
|
|
469
|
+
{ id: "codex:gpt-5.1-codex", label: "Codex · GPT-5.1-Codex", provider: "cli" },
|
|
352
470
|
] : []),
|
|
353
471
|
...(localAgents.has("opencode") ? [
|
|
354
472
|
{ id: "opencode:opencode/big-pickle", label: "OpenCode · Big Pickle", provider: "cli" },
|
|
355
473
|
{ id: "opencode:deepseek/deepseek-chat", label: "OpenCode · DeepSeek Chat", provider: "cli" },
|
|
356
|
-
{ id: "opencode:anthropic/claude-sonnet-4-5", label: "OpenCode · Claude Sonnet", provider: "cli" },
|
|
357
|
-
{ id: "opencode:openai/gpt-5", label: "OpenCode · GPT-5", provider: "cli" },
|
|
474
|
+
{ id: "opencode:anthropic/claude-sonnet-4-5", label: "OpenCode · Claude Sonnet 4.5", provider: "cli" },
|
|
475
|
+
{ id: "opencode:openai/gpt-5.1", label: "OpenCode · GPT-5.1", provider: "cli" },
|
|
358
476
|
] : []),
|
|
359
477
|
...(localAgents.has("cursor") ? [
|
|
360
478
|
{ id: "cursor:claude-sonnet-4.5", label: "Cursor · Claude Sonnet 4.5", provider: "cli" },
|
|
@@ -387,16 +505,33 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
387
505
|
return model;
|
|
388
506
|
}
|
|
389
507
|
// Free plans: check if provider is configured
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
508
|
+
let isConfigured = false;
|
|
509
|
+
let lockedReason = "Configure your API key in the dashboard to use this model";
|
|
510
|
+
if (hasCliAuth) {
|
|
511
|
+
// User has CLI auth: check dashboard-configured providers first
|
|
512
|
+
isConfigured = configuredProviders.includes(model.provider);
|
|
513
|
+
lockedReason = "Configure this provider in your workspace dashboard to use this model";
|
|
514
|
+
}
|
|
515
|
+
// If not configured via dashboard, fall back to env-based detection
|
|
516
|
+
if (!isConfigured) {
|
|
517
|
+
const envKey = providerKeyMapping[model.provider];
|
|
518
|
+
isConfigured = Boolean(process.env[envKey]) ||
|
|
519
|
+
Boolean(fileEnv[envKey]) ||
|
|
520
|
+
Boolean(localProviderKeys[model.provider]);
|
|
521
|
+
if (!isConfigured) {
|
|
522
|
+
lockedReason = hasCliAuth
|
|
523
|
+
? "Configure this provider in your workspace dashboard, or set the provider API key in your .env file"
|
|
524
|
+
: "Run `lasso auth login` to configure providers in your dashboard, or set the provider API key in your .env file";
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
lockedReason = "";
|
|
528
|
+
}
|
|
529
|
+
}
|
|
395
530
|
if (!isConfigured) {
|
|
396
531
|
return {
|
|
397
532
|
...model,
|
|
398
533
|
locked: true,
|
|
399
|
-
lockedReason: "Configure your API key
|
|
534
|
+
lockedReason: lockedReason || "Configure your API key to use this model",
|
|
400
535
|
};
|
|
401
536
|
}
|
|
402
537
|
return model;
|
|
@@ -410,7 +545,7 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
410
545
|
? { name: creds.userName, email: creds.userEmail }
|
|
411
546
|
: (process.env.USER ? { name: process.env.USER } : null);
|
|
412
547
|
socket.send(JSON.stringify({ type: "config", apiKeyConfigured: lassoKeyConfigured, agentConfigured: lassoKeyConfigured || Boolean(agentConfig) || localAgents.size > 0, models: [], collab: collabConfig?.registered ? { ...collabConfig, plan: collabConfig.plan, configuredProviders: collabConfig.configuredProviders } : null, user: userInfo }));
|
|
413
|
-
void availableModels(collabConfig).then((models) => {
|
|
548
|
+
void availableModels(collabConfig, workspaceConfig).then((models) => {
|
|
414
549
|
if (socket.readyState === socket.OPEN)
|
|
415
550
|
socket.send(JSON.stringify({ type: "config", apiKeyConfigured: lassoKeyConfigured, agentConfigured: lassoKeyConfigured || Boolean(agentConfig) || localAgents.size > 0, models, collab: collabConfig?.registered ? { ...collabConfig, plan: collabConfig.plan, configuredProviders: collabConfig.configuredProviders } : null, user: userInfo }));
|
|
416
551
|
});
|
|
@@ -763,7 +898,14 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
763
898
|
return;
|
|
764
899
|
}
|
|
765
900
|
const provider = (msg.provider || agentConfig?.provider || "google");
|
|
766
|
-
const model = msg.model || agentConfig?.model
|
|
901
|
+
const model = msg.model || agentConfig?.model;
|
|
902
|
+
if (!model) {
|
|
903
|
+
socket.send(JSON.stringify({
|
|
904
|
+
type: "error",
|
|
905
|
+
message: "No model selected. Please select a model in settings."
|
|
906
|
+
}));
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
767
909
|
const localKey = localProviderKeys[provider];
|
|
768
910
|
const serverUrl = collabConfig?.serverUrl || (0, auth_1.serverUrlFrom)(fileEnv);
|
|
769
911
|
const targetApiUrl = (serverUrl.includes("collab.lasso.byorello.space") ? "https://api.lasso.byorello.space" : serverUrl).replace(/\/api\/v1\/?$/, "");
|
|
@@ -852,7 +994,14 @@ function startBridge(cwd = process.cwd(), collabConfig = null, bridgePort = expo
|
|
|
852
994
|
node_fs_1.default.mkdirSync(node_path_1.default.dirname(filePath), { recursive: true });
|
|
853
995
|
node_fs_1.default.writeFileSync(filePath, nextContent);
|
|
854
996
|
}
|
|
855
|
-
|
|
997
|
+
// Run build validation after applying changes
|
|
998
|
+
const validation = await validateBuild(cwd);
|
|
999
|
+
socket.send(JSON.stringify({
|
|
1000
|
+
type: "applied",
|
|
1001
|
+
taskId: msg.taskId,
|
|
1002
|
+
message: `${msg.changes.length} file${msg.changes.length === 1 ? "" : "s"} updated. Your dev server will reload.`,
|
|
1003
|
+
validation
|
|
1004
|
+
}));
|
|
856
1005
|
}
|
|
857
1006
|
catch (error) {
|
|
858
1007
|
// Validation happens before writes, but restore this task's snapshot
|
|
@@ -75,7 +75,7 @@ void (async () => {
|
|
|
75
75
|
const nextBin = node_path_1.default.join(cwd, "node_modules", ".bin", "next");
|
|
76
76
|
if (!node_fs_1.default.existsSync(nextBin))
|
|
77
77
|
throw new Error("Next.js is not installed in this project.");
|
|
78
|
-
const bridge = (0, bridge_1.startBridge)(cwd, null, bridgePort);
|
|
78
|
+
const bridge = await (0, bridge_1.startBridge)(cwd, null, bridgePort);
|
|
79
79
|
const nextProcess = (0, node_child_process_1.spawn)(nextBin, ["dev", "--port", String(nextPort), "--hostname", "127.0.0.1"], {
|
|
80
80
|
cwd,
|
|
81
81
|
env: { ...process.env, PORT: String(nextPort) },
|
|
@@ -27,7 +27,7 @@ function lassoOverlayPlugin() {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
void (async () => {
|
|
30
|
-
const bridge = (0, bridge_1.startBridge)(cwd, null, bridgePort);
|
|
30
|
+
const bridge = await (0, bridge_1.startBridge)(cwd, null, bridgePort);
|
|
31
31
|
const require = (0, node_module_1.createRequire)(node_path_1.default.join(cwd, "package.json"));
|
|
32
32
|
const viteEntry = require.resolve("vite");
|
|
33
33
|
const { createServer } = await import((0, node_url_1.pathToFileURL)(viteEntry).href);
|
package/dist/cli/index.js
CHANGED
|
@@ -94,6 +94,23 @@ program.command("create [name]")
|
|
|
94
94
|
}
|
|
95
95
|
});
|
|
96
96
|
// prettier-ignore
|
|
97
|
+
program.command("whoami")
|
|
98
|
+
.description("Show the currently authenticated Lasso user")
|
|
99
|
+
.action(() => {
|
|
100
|
+
const credentials = (0, auth_1.loadCredentials)();
|
|
101
|
+
if (!credentials) {
|
|
102
|
+
console.log(chalk_1.default.dim("Not authenticated. Run ") + chalk_1.default.cyan("lasso auth login") + chalk_1.default.dim(" to sign in."));
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const summary = (0, auth_1.credentialSummary)(credentials);
|
|
107
|
+
console.log(chalk_1.default.green("✓") + ` Authenticated as ${chalk_1.default.bold(summary.userEmail || "your account")}` + (summary.userName ? ` (${summary.userName})` : ""));
|
|
108
|
+
if (summary.workspaceName)
|
|
109
|
+
console.log(chalk_1.default.dim(`Workspace: ${summary.workspaceName} (${summary.workspaceId})`));
|
|
110
|
+
if (summary.masked)
|
|
111
|
+
console.log(chalk_1.default.dim("Credential: ") + summary.masked);
|
|
112
|
+
});
|
|
113
|
+
// prettier-ignore
|
|
97
114
|
const daemon = program.command("daemon [action]")
|
|
98
115
|
.description("Start/stop Lasso Host — the local .lasso domain server (start|status|stop|restart|install|uninstall)")
|
|
99
116
|
.usage("[action]")
|
|
@@ -439,7 +456,7 @@ program.command("dev", { isDefault: true }).description("Start your dev server w
|
|
|
439
456
|
else {
|
|
440
457
|
console.log(chalk_1.default.yellow("!") + ` No ${chalk_1.default.bold(project_1.LASSO_CONFIG_FILE)} found. Run ${chalk_1.default.cyan("npx @lasso-ai/cli init")} to enable realtime collaboration.`);
|
|
441
458
|
}
|
|
442
|
-
(0, bridge_1.startBridge)(cwd, collabConfig);
|
|
459
|
+
await (0, bridge_1.startBridge)(cwd, collabConfig);
|
|
443
460
|
switch (framework) {
|
|
444
461
|
case "vite":
|
|
445
462
|
console.log(chalk_1.default.green("✓") + " Detected: Vite");
|
package/dist/cli/oneshot.d.ts
CHANGED
|
@@ -31,5 +31,4 @@ export interface ConversationMessage {
|
|
|
31
31
|
role: "user" | "assistant";
|
|
32
32
|
content: string;
|
|
33
33
|
}
|
|
34
|
-
export declare function isConversationalPrompt(prompt: string): boolean;
|
|
35
34
|
export declare function runOneShotAgent(cwd: string, prompt: string, scope: "project" | "component", config: AgentConfig, signal: AbortSignal, onProgress: ProgressCallback, onPrompt: PromptCallback, messages?: ConversationMessage[], serverUrl?: string, apiKey?: string, taskId?: string, pageContext?: any): Promise<OneShotResult>;
|