lynxprompt 0.5.4 → 0.5.6

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/index.js CHANGED
@@ -2952,6 +2952,41 @@ function generateFileContent(options, platform2) {
2952
2952
  sections.push(`# ${projectName} - AI Assistant Configuration`);
2953
2953
  sections.push("");
2954
2954
  }
2955
+ if (options.enableAutoUpdate && options.blueprintId && (isMarkdown || isMdc)) {
2956
+ const bpId = options.blueprintId.startsWith("bp_") ? options.blueprintId : `bp_${options.blueprintId}`;
2957
+ const fileName = platform2 === "cursor" ? ".cursor/rules/agents.mdc" : "AGENTS.md";
2958
+ const devOS = Array.isArray(options.devOS) ? options.devOS[0] : options.devOS || "linux";
2959
+ sections.push("<!--");
2960
+ sections.push("This file is synced with LynxPrompt. To update it via API:");
2961
+ sections.push("");
2962
+ if (devOS === "windows") {
2963
+ sections.push("# PowerShell (Windows)");
2964
+ sections.push(`$content = (Get-Content "${fileName}" -Raw) -replace '"', '\\"'`);
2965
+ sections.push(`$body = @{ content = $content } | ConvertTo-Json`);
2966
+ sections.push(`Invoke-RestMethod -Uri "https://lynxprompt.com/api/v1/blueprints/${bpId}" \``);
2967
+ sections.push(' -Method PUT -Headers @{ "Authorization" = "Bearer $env:LYNXPROMPT_API_TOKEN" } `');
2968
+ sections.push(' -ContentType "application/json" -Body $body');
2969
+ } else if (devOS === "wsl" || devOS === "linux" || devOS === "macos" || devOS === "multi") {
2970
+ sections.push("# Bash (Linux/macOS/WSL)");
2971
+ sections.push(`curl -X PUT "https://lynxprompt.com/api/v1/blueprints/${bpId}" \\`);
2972
+ sections.push(' -H "Authorization: Bearer $LYNXPROMPT_API_TOKEN" \\');
2973
+ sections.push(' -H "Content-Type: application/json" \\');
2974
+ sections.push(` -d "{\\"content\\": \\"$(cat ${fileName} | jq -Rs .)\\"}"`);
2975
+ sections.push("");
2976
+ sections.push("# Note: Install jq if not present: sudo apt install jq (Linux) or brew install jq (macOS)");
2977
+ } else {
2978
+ sections.push("# Bash");
2979
+ sections.push(`curl -X PUT "https://lynxprompt.com/api/v1/blueprints/${bpId}" \\`);
2980
+ sections.push(' -H "Authorization: Bearer $LYNXPROMPT_API_TOKEN" \\');
2981
+ sections.push(' -H "Content-Type: application/json" \\');
2982
+ sections.push(` -d "{\\"content\\": \\"$(cat ${fileName} | jq -Rs .)\\"}"`);
2983
+ }
2984
+ sections.push("");
2985
+ sections.push("Generate an API token at: https://lynxprompt.com/settings");
2986
+ sections.push("Docs: https://lynxprompt.com/docs/api");
2987
+ sections.push("-->");
2988
+ sections.push("");
2989
+ }
2955
2990
  if (options.projectType) {
2956
2991
  const typeContexts = {
2957
2992
  work: "This is a professional/enterprise project. Follow strict procedures and maintain high code quality.",
@@ -2969,14 +3004,22 @@ function generateFileContent(options, platform2) {
2969
3004
  }
2970
3005
  }
2971
3006
  }
2972
- const personaDesc = PERSONA_DESCRIPTIONS[options.persona] || options.persona;
3007
+ const personaDesc = options.userPersona || PERSONA_DESCRIPTIONS[options.persona] || options.persona || "";
2973
3008
  const projectDesc = bpVar(bp, "PROJECT_DESCRIPTION", options.description || "");
2974
3009
  if (isMarkdown || isMdc) {
2975
3010
  sections.push("## Persona");
2976
3011
  sections.push("");
2977
- sections.push(`You are ${personaDesc}. You assist developers working on ${projectName}.`);
3012
+ if (personaDesc) {
3013
+ sections.push(`You are ${personaDesc}. You assist developers working on ${projectName}.`);
3014
+ } else {
3015
+ sections.push(`You assist developers working on ${projectName}.`);
3016
+ }
2978
3017
  } else {
2979
- sections.push(`You are ${personaDesc}. You assist developers working on ${projectName}.`);
3018
+ if (personaDesc) {
3019
+ sections.push(`You are ${personaDesc}. You assist developers working on ${projectName}.`);
3020
+ } else {
3021
+ sections.push(`You assist developers working on ${projectName}.`);
3022
+ }
2980
3023
  }
2981
3024
  if (options.description) {
2982
3025
  sections.push("");
@@ -3155,7 +3198,26 @@ function generateFileContent(options, platform2) {
3155
3198
  if (isMarkdown || isMdc) {
3156
3199
  sections.push("## Commit Identity");
3157
3200
  sections.push("");
3158
- sections.push("> **Personal data enabled:** Use my name and email for git commits when making changes.");
3201
+ if (options.userName || options.userEmail || options.userRole || options.userExpertise) {
3202
+ const identityLines = [];
3203
+ if (options.userName) {
3204
+ identityLines.push(`- **Name:** ${options.userName}`);
3205
+ }
3206
+ if (options.userEmail) {
3207
+ identityLines.push(`- **Email:** ${options.userEmail}`);
3208
+ }
3209
+ if (options.userRole) {
3210
+ identityLines.push(`- **Role:** ${options.userRole}`);
3211
+ }
3212
+ if (options.userExpertise) {
3213
+ identityLines.push(`- **Expertise:** ${options.userExpertise}`);
3214
+ }
3215
+ sections.push(...identityLines);
3216
+ sections.push("");
3217
+ sections.push("> Use this identity for git commits when making changes on my behalf.");
3218
+ } else {
3219
+ sections.push("> **Personal data enabled:** Use my name and email for git commits when making changes.");
3220
+ }
3159
3221
  sections.push("");
3160
3222
  }
3161
3223
  }
@@ -4149,6 +4211,23 @@ process.on("SIGINT", async () => {
4149
4211
  process.exit(0);
4150
4212
  });
4151
4213
  async function wizardCommand(options) {
4214
+ try {
4215
+ await runWizardWithDraftProtection(options);
4216
+ } catch (error) {
4217
+ await saveDraftOnExit();
4218
+ console.error(chalk8.red("\n \u2717 An unexpected error occurred:"));
4219
+ if (error instanceof Error) {
4220
+ console.error(chalk8.gray(` ${error.message}`));
4221
+ }
4222
+ console.log();
4223
+ if (wizardState.stepReached > 0) {
4224
+ console.log(chalk8.yellow(" Your progress has been saved. Resume with the draft command shown above."));
4225
+ }
4226
+ console.log();
4227
+ process.exit(1);
4228
+ }
4229
+ }
4230
+ async function runWizardWithDraftProtection(options) {
4152
4231
  console.log();
4153
4232
  console.log(chalk8.cyan.bold(" \u{1F431} LynxPrompt Wizard"));
4154
4233
  console.log(chalk8.gray(" Generate AI IDE configuration in seconds"));
@@ -4282,7 +4361,8 @@ async function wizardCommand(options) {
4282
4361
  type: "confirm",
4283
4362
  name: "useRemote",
4284
4363
  message: detected ? chalk8.white("\u{1F50D} Analyze a different remote repository instead?") : chalk8.white("\u{1F50D} Analyze a remote repository URL?"),
4285
- initial: !detected
4364
+ initial: false
4365
+ // Default to No - user must explicitly choose Yes
4286
4366
  }, promptConfig);
4287
4367
  if (remoteResponse.useRemote) {
4288
4368
  const urlResponse = await prompts4({
@@ -4344,9 +4424,42 @@ async function wizardCommand(options) {
4344
4424
  const finalConfig = {
4345
4425
  ...config2,
4346
4426
  blueprintMode: options.blueprint || config2.blueprintMode || false,
4347
- variables
4427
+ variables,
4428
+ enableAutoUpdate: false
4429
+ // Don't generate curl header yet
4348
4430
  };
4349
- const files = generateConfig(finalConfig);
4431
+ let files = generateConfig(finalConfig);
4432
+ let savedBlueprintId = null;
4433
+ if (config2.enableAutoUpdate && api) {
4434
+ spinner.text = "Saving blueprint to cloud...";
4435
+ try {
4436
+ const mainFile = Object.entries(files)[0];
4437
+ if (mainFile) {
4438
+ const [_fileName, content] = mainFile;
4439
+ const response = await api.createBlueprint({
4440
+ name: config2.name || "My AI Config",
4441
+ description: config2.description || "Generated with LynxPrompt CLI",
4442
+ content,
4443
+ visibility: "PRIVATE"
4444
+ });
4445
+ savedBlueprintId = response.blueprint.id;
4446
+ const configWithAutoUpdate = {
4447
+ ...finalConfig,
4448
+ enableAutoUpdate: true,
4449
+ blueprintId: savedBlueprintId
4450
+ };
4451
+ files = generateConfig(configWithAutoUpdate);
4452
+ console.log(chalk8.green(` \u2713 Blueprint saved: ${savedBlueprintId}`));
4453
+ }
4454
+ } catch (saveError) {
4455
+ spinner.stop();
4456
+ console.log(chalk8.yellow("\n \u26A0\uFE0F Could not save blueprint to cloud"));
4457
+ if (saveError instanceof Error) {
4458
+ console.log(chalk8.gray(` ${saveError.message}`));
4459
+ }
4460
+ console.log(chalk8.gray(" Continuing without auto-update curl command..."));
4461
+ }
4462
+ }
4350
4463
  spinner.stop();
4351
4464
  console.log();
4352
4465
  console.log(chalk8.green.bold(" \u2705 Generated:"));
@@ -4488,11 +4601,15 @@ async function wizardCommand(options) {
4488
4601
  }
4489
4602
  } catch (error) {
4490
4603
  spinner.fail("Failed to generate files");
4604
+ await saveDraftOnExit();
4491
4605
  console.error(chalk8.red("\n\u2717 An error occurred while generating configuration files."));
4492
4606
  if (error instanceof Error) {
4493
4607
  console.error(chalk8.gray(` ${error.message}`));
4494
4608
  }
4495
4609
  console.error(chalk8.gray("\nTry running with --yes flag for default settings."));
4610
+ if (wizardState.stepReached > 0) {
4611
+ console.log(chalk8.yellow("\n Your wizard progress has been saved to a draft."));
4612
+ }
4496
4613
  process.exit(1);
4497
4614
  }
4498
4615
  }
@@ -5092,6 +5209,35 @@ async function runInteractiveWizard(options, detected, userTier) {
5092
5209
  inactive: "No"
5093
5210
  }, promptConfig);
5094
5211
  answers.includePersonalData = includePersonalResponse.includePersonalData || false;
5212
+ if (answers.includePersonalData && api) {
5213
+ try {
5214
+ console.log(chalk8.gray(" Fetching profile from LynxPrompt..."));
5215
+ const userResponse = await api.getUser();
5216
+ if (userResponse.user) {
5217
+ answers.userName = userResponse.user.name || userResponse.user.display_name || "";
5218
+ answers.userEmail = userResponse.user.email || "";
5219
+ answers.userPersona = userResponse.user.persona || "";
5220
+ answers.userExpertise = userResponse.user.skill_level || "";
5221
+ console.log(chalk8.green(" \u2713 Profile loaded"));
5222
+ }
5223
+ } catch {
5224
+ console.log(chalk8.yellow(" Could not fetch profile data. Using defaults."));
5225
+ }
5226
+ }
5227
+ const enableAutoUpdateResponse = await prompts4({
5228
+ type: "toggle",
5229
+ name: "enableAutoUpdate",
5230
+ message: chalk8.white("Save to cloud & enable auto-update via API?"),
5231
+ initial: false,
5232
+ active: "Yes",
5233
+ inactive: "No"
5234
+ }, promptConfig);
5235
+ answers.enableAutoUpdate = enableAutoUpdateResponse.enableAutoUpdate || false;
5236
+ if (answers.enableAutoUpdate && !api) {
5237
+ console.log(chalk8.yellow(" \u26A0\uFE0F Auto-update requires login. Run 'lynxp login' first."));
5238
+ console.log(chalk8.gray(" Continuing without auto-update..."));
5239
+ answers.enableAutoUpdate = false;
5240
+ }
5095
5241
  if (canAccessTier(userTier, "advanced")) {
5096
5242
  const boundariesStep = getCurrentStep("boundaries");
5097
5243
  showStep(currentStepNum, boundariesStep, userTier);
@@ -5427,6 +5573,11 @@ async function runInteractiveWizard(options, detected, userTier) {
5427
5573
  importantFiles: answers.importantFiles,
5428
5574
  selfImprove: answers.selfImprove,
5429
5575
  includePersonalData: answers.includePersonalData,
5576
+ enableAutoUpdate: answers.enableAutoUpdate,
5577
+ userName: answers.userName,
5578
+ userEmail: answers.userEmail,
5579
+ userPersona: answers.userPersona,
5580
+ userExpertise: answers.userExpertise,
5430
5581
  boundaryAlways: answers.boundaryAlways,
5431
5582
  boundaryNever: answers.boundaryNever,
5432
5583
  boundaryAsk: answers.boundaryAsk,