repowise 0.1.15 → 0.1.17

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.
@@ -39,12 +39,37 @@ var init_env = __esm({
39
39
  }
40
40
  });
41
41
 
42
+ // src/lib/config.ts
43
+ import { readFile, writeFile, mkdir } from "fs/promises";
44
+ import { homedir } from "os";
45
+ import { join } from "path";
46
+ async function getConfig() {
47
+ try {
48
+ const data = await readFile(CONFIG_PATH, "utf-8");
49
+ return JSON.parse(data);
50
+ } catch {
51
+ return {};
52
+ }
53
+ }
54
+ async function saveConfig(config2) {
55
+ await mkdir(CONFIG_DIR, { recursive: true });
56
+ await writeFile(CONFIG_PATH, JSON.stringify(config2, null, 2));
57
+ }
58
+ var CONFIG_DIR, CONFIG_PATH;
59
+ var init_config = __esm({
60
+ "src/lib/config.ts"() {
61
+ "use strict";
62
+ CONFIG_DIR = join(homedir(), ".repowise");
63
+ CONFIG_PATH = join(CONFIG_DIR, "config.json");
64
+ }
65
+ });
66
+
42
67
  // src/lib/auth.ts
43
68
  import { createHash, randomBytes } from "crypto";
44
- import { readFile, writeFile, mkdir, chmod, unlink } from "fs/promises";
69
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, chmod, unlink } from "fs/promises";
45
70
  import http from "http";
46
- import { homedir } from "os";
47
- import { join } from "path";
71
+ import { homedir as homedir2 } from "os";
72
+ import { join as join2 } from "path";
48
73
  function getCognitoConfig() {
49
74
  const env = getEnvConfig();
50
75
  return {
@@ -204,7 +229,7 @@ async function refreshTokens(refreshToken) {
204
229
  }
205
230
  async function getStoredCredentials() {
206
231
  try {
207
- const data = await readFile(CREDENTIALS_PATH, "utf-8");
232
+ const data = await readFile2(CREDENTIALS_PATH, "utf-8");
208
233
  return JSON.parse(data);
209
234
  } catch (err) {
210
235
  if (err.code === "ENOENT" || err instanceof SyntaxError) {
@@ -214,8 +239,8 @@ async function getStoredCredentials() {
214
239
  }
215
240
  }
216
241
  async function storeCredentials(credentials) {
217
- await mkdir(CONFIG_DIR, { recursive: true, mode: 448 });
218
- await writeFile(CREDENTIALS_PATH, JSON.stringify(credentials, null, 2));
242
+ await mkdir2(CONFIG_DIR2, { recursive: true, mode: 448 });
243
+ await writeFile2(CREDENTIALS_PATH, JSON.stringify(credentials, null, 2));
219
244
  await chmod(CREDENTIALS_PATH, 384);
220
245
  }
221
246
  async function clearCredentials() {
@@ -308,13 +333,13 @@ function decodeIdToken(idToken) {
308
333
  return { email: "unknown" };
309
334
  }
310
335
  }
311
- var CONFIG_DIR, CREDENTIALS_PATH, CLI_CALLBACK_PORT, CALLBACK_TIMEOUT_MS;
336
+ var CONFIG_DIR2, CREDENTIALS_PATH, CLI_CALLBACK_PORT, CALLBACK_TIMEOUT_MS;
312
337
  var init_auth = __esm({
313
338
  "src/lib/auth.ts"() {
314
339
  "use strict";
315
340
  init_env();
316
- CONFIG_DIR = join(homedir(), ".repowise");
317
- CREDENTIALS_PATH = join(CONFIG_DIR, "credentials.json");
341
+ CONFIG_DIR2 = join2(homedir2(), ".repowise");
342
+ CREDENTIALS_PATH = join2(CONFIG_DIR2, "credentials.json");
318
343
  CLI_CALLBACK_PORT = 19876;
319
344
  CALLBACK_TIMEOUT_MS = 12e4;
320
345
  }
@@ -363,7 +388,7 @@ var init_api = __esm({
363
388
 
364
389
  // src/lib/prompts.ts
365
390
  import { checkbox, confirm } from "@inquirer/prompts";
366
- import chalk from "chalk";
391
+ import chalk2 from "chalk";
367
392
  async function selectAiTools() {
368
393
  const choices = [
369
394
  { name: "Cursor", value: "cursor" },
@@ -376,9 +401,9 @@ async function selectAiTools() {
376
401
  { name: "Other (manual setup)", value: "other" }
377
402
  ];
378
403
  while (true) {
379
- console.log(chalk.dim(" Use Space to select, Enter to continue.\n"));
404
+ console.log(chalk2.dim(" Use Space to select, Enter to continue.\n"));
380
405
  const selected = await checkbox({
381
- message: chalk.bold("Which AI tools do you use?"),
406
+ message: chalk2.bold("Which AI tools do you use?"),
382
407
  choices
383
408
  });
384
409
  if (selected.length === 0) {
@@ -400,8 +425,8 @@ var init_prompts = __esm({
400
425
  });
401
426
 
402
427
  // src/lib/ai-tools.ts
403
- import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, readdir } from "fs/promises";
404
- import { join as join2, dirname } from "path";
428
+ import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
429
+ import { join as join3, dirname } from "path";
405
430
  function sanitizeRepoName(name) {
406
431
  return name.replace(/[<>[\]`()|\\]/g, "");
407
432
  }
@@ -467,16 +492,16 @@ function generateReference(tool, repoName, contextFolder, contextFiles) {
467
492
  }
468
493
  async function updateToolConfig(repoRoot, tool, repoName, contextFolder, contextFiles) {
469
494
  const config2 = AI_TOOL_CONFIG[tool];
470
- const fullPath = join2(repoRoot, config2.filePath);
495
+ const fullPath = join3(repoRoot, config2.filePath);
471
496
  const dir = dirname(fullPath);
472
497
  if (dir !== repoRoot) {
473
- await mkdir2(dir, { recursive: true });
498
+ await mkdir3(dir, { recursive: true });
474
499
  }
475
500
  const referenceBlock = generateReference(tool, repoName, contextFolder, contextFiles);
476
501
  let existing = "";
477
502
  let created = true;
478
503
  try {
479
- existing = await readFile2(fullPath, "utf-8");
504
+ existing = await readFile3(fullPath, "utf-8");
480
505
  created = false;
481
506
  } catch (err) {
482
507
  if (err.code !== "ENOENT") throw err;
@@ -492,11 +517,11 @@ async function updateToolConfig(repoRoot, tool, repoName, contextFolder, context
492
517
  const separator = existing.length > 0 && !existing.endsWith("\n") ? "\n\n" : existing.length > 0 ? "\n" : "";
493
518
  content = existing + separator + referenceBlock + "\n";
494
519
  }
495
- await writeFile2(fullPath, content, "utf-8");
520
+ await writeFile3(fullPath, content, "utf-8");
496
521
  return { created };
497
522
  }
498
523
  async function scanLocalContextFiles(repoRoot, contextFolder) {
499
- const folderPath = join2(repoRoot, contextFolder);
524
+ const folderPath = join3(repoRoot, contextFolder);
500
525
  try {
501
526
  const entries = await readdir(folderPath, { withFileTypes: true });
502
527
  return entries.filter((e) => e.isFile() && e.name.endsWith(".md")).map((e) => ({
@@ -574,59 +599,34 @@ var init_ai_tools = __esm({
574
599
  }
575
600
  });
576
601
 
577
- // src/lib/config.ts
578
- import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
579
- import { homedir as homedir2 } from "os";
580
- import { join as join3 } from "path";
581
- async function getConfig() {
582
- try {
583
- const data = await readFile3(CONFIG_PATH, "utf-8");
584
- return JSON.parse(data);
585
- } catch {
586
- return {};
587
- }
588
- }
589
- async function saveConfig(config2) {
590
- await mkdir3(CONFIG_DIR2, { recursive: true });
591
- await writeFile3(CONFIG_PATH, JSON.stringify(config2, null, 2));
592
- }
593
- var CONFIG_DIR2, CONFIG_PATH;
594
- var init_config = __esm({
595
- "src/lib/config.ts"() {
596
- "use strict";
597
- CONFIG_DIR2 = join3(homedir2(), ".repowise");
598
- CONFIG_PATH = join3(CONFIG_DIR2, "config.json");
599
- }
600
- });
601
-
602
602
  // src/lib/interview-handler.ts
603
- import chalk2 from "chalk";
603
+ import chalk3 from "chalk";
604
604
  import { input } from "@inquirer/prompts";
605
605
  async function handleInterview(syncId, questionId, questionText, questionContext, estimatedQuestions) {
606
606
  questionCounter++;
607
607
  if (questionCounter === 1) {
608
608
  console.log("");
609
- console.log(chalk2.cyan.bold(" \u2500\u2500 Interview \u2500\u2500"));
610
- console.log(chalk2.dim(" Help us understand your project better. Answer a few short"));
609
+ console.log(chalk3.cyan.bold(" \u2500\u2500 Interview \u2500\u2500"));
610
+ console.log(chalk3.dim(" Help us understand your project better. Answer a few short"));
611
611
  console.log(
612
- chalk2.dim(
612
+ chalk3.dim(
613
613
  ` questions so we can generate more relevant context files (up to ${MAX_QUESTIONS}).`
614
614
  )
615
615
  );
616
616
  }
617
617
  const total = Math.min(estimatedQuestions ?? MAX_QUESTIONS, MAX_QUESTIONS);
618
618
  console.log("");
619
- console.log(chalk2.cyan.bold(` Question ${questionCounter}/${total}`));
619
+ console.log(chalk3.cyan.bold(` Question ${questionCounter}/${total}`));
620
620
  if (questionContext) {
621
- console.log(chalk2.dim(` ${questionContext}`));
621
+ console.log(chalk3.dim(` ${questionContext}`));
622
622
  }
623
623
  console.log(` ${questionText}`);
624
- console.log(chalk2.dim(' (Enter to skip \xB7 "done" to finish early)'));
624
+ console.log(chalk3.dim(' (Enter to skip \xB7 "done" to finish early)'));
625
625
  let answer;
626
626
  try {
627
627
  answer = await Promise.race([
628
628
  input({
629
- message: chalk2.cyan(">"),
629
+ message: chalk3.cyan(">"),
630
630
  theme: { prefix: " " }
631
631
  }),
632
632
  new Promise(
@@ -635,7 +635,7 @@ async function handleInterview(syncId, questionId, questionText, questionContext
635
635
  ]);
636
636
  } catch (err) {
637
637
  if (err instanceof Error && err.message === "INTERVIEW_TIMEOUT") {
638
- console.log(chalk2.yellow(" Timed out \u2014 auto-skipping this question."));
638
+ console.log(chalk3.yellow(" Timed out \u2014 auto-skipping this question."));
639
639
  answer = "skip";
640
640
  } else {
641
641
  throw err;
@@ -654,7 +654,7 @@ async function handleInterview(syncId, questionId, questionText, questionContext
654
654
  }
655
655
  if (questionCounter >= MAX_QUESTIONS && action !== "done") {
656
656
  action = "done";
657
- console.log(chalk2.green(" Thanks for your answers! Wrapping up the interview."));
657
+ console.log(chalk3.green(" Thanks for your answers! Wrapping up the interview."));
658
658
  }
659
659
  try {
660
660
  await apiRequest(`/v1/sync/${syncId}/answer`, {
@@ -664,7 +664,7 @@ async function handleInterview(syncId, questionId, questionText, questionContext
664
664
  } catch (err) {
665
665
  const message = err instanceof Error ? err.message : String(err);
666
666
  if (message.includes("not awaiting input") || message.includes("expired")) {
667
- console.log(chalk2.dim(" Pipeline has already moved on \u2014 continuing."));
667
+ console.log(chalk3.dim(" Pipeline has already moved on \u2014 continuing."));
668
668
  return;
669
669
  }
670
670
  try {
@@ -674,16 +674,16 @@ async function handleInterview(syncId, questionId, questionText, questionContext
674
674
  body: JSON.stringify({ questionId, answerText, action })
675
675
  });
676
676
  } catch {
677
- console.log(chalk2.yellow(" Could not submit answer \u2014 pipeline will continue."));
677
+ console.log(chalk3.yellow(" Could not submit answer \u2014 pipeline will continue."));
678
678
  return;
679
679
  }
680
680
  }
681
681
  if (action === "done") {
682
- console.log(chalk2.dim(" Interview ended early."));
682
+ console.log(chalk3.dim(" Interview ended early."));
683
683
  } else if (action === "skip") {
684
- console.log(chalk2.dim(" Skipped."));
684
+ console.log(chalk3.dim(" Skipped."));
685
685
  } else {
686
- console.log(chalk2.dim(" Answer recorded."));
686
+ console.log(chalk3.dim(" Answer recorded."));
687
687
  }
688
688
  console.log("");
689
689
  }
@@ -699,7 +699,7 @@ var init_interview_handler = __esm({
699
699
  });
700
700
 
701
701
  // src/lib/progress-renderer.ts
702
- import chalk3 from "chalk";
702
+ import chalk4 from "chalk";
703
703
  var ProgressRenderer;
704
704
  var init_progress_renderer = __esm({
705
705
  "src/lib/progress-renderer.ts"() {
@@ -716,13 +716,13 @@ var init_progress_renderer = __esm({
716
716
  this.privacyShieldShown = true;
717
717
  spinner.stop();
718
718
  console.log("");
719
- console.log(chalk3.cyan.bold(" \u2500\u2500 Privacy Shield \u2500\u2500"));
719
+ console.log(chalk4.cyan.bold(" \u2500\u2500 Privacy Shield \u2500\u2500"));
720
720
  if (enabled) {
721
- console.log(` ${chalk3.green("\u2713")} Privacy Shield active`);
722
- console.log(` ${chalk3.green("\u2713")} Private connection established`);
721
+ console.log(` ${chalk4.green("\u2713")} Privacy Shield active`);
722
+ console.log(` ${chalk4.green("\u2713")} Private connection established`);
723
723
  } else {
724
- console.log(` ${chalk3.yellow("\u2139")} Privacy Shield not in current plan`);
725
- console.log(chalk3.dim(" Shield your data from the open internet."));
724
+ console.log(` ${chalk4.yellow("\u2139")} Privacy Shield not in current plan`);
725
+ console.log(chalk4.dim(" Shield your data from the open internet."));
726
726
  }
727
727
  console.log("");
728
728
  spinner.start();
@@ -732,21 +732,21 @@ var init_progress_renderer = __esm({
732
732
  this.discoveryShown = true;
733
733
  spinner.stop();
734
734
  console.log("");
735
- console.log(chalk3.cyan.bold(" \u2500\u2500 Repository Discovery \u2500\u2500"));
735
+ console.log(chalk4.cyan.bold(" \u2500\u2500 Repository Discovery \u2500\u2500"));
736
736
  if (result.languages.length > 0) {
737
737
  const langs = result.languages.slice(0, 5).map((l) => `${l.name} (${Math.round(l.percentage)}%)`).join(", ");
738
- console.log(` ${chalk3.dim("Languages:")} ${langs}`);
738
+ console.log(` ${chalk4.dim("Languages:")} ${langs}`);
739
739
  }
740
740
  if (result.frameworks.length > 0) {
741
741
  console.log(
742
- ` ${chalk3.dim("Frameworks:")} ${result.frameworks.map((f) => f.name).join(", ")}`
742
+ ` ${chalk4.dim("Frameworks:")} ${result.frameworks.map((f) => f.name).join(", ")}`
743
743
  );
744
744
  }
745
745
  console.log(
746
- ` ${chalk3.dim("Structure:")} ${result.structureType} ${chalk3.dim(`(${result.fileCount} files)`)}`
746
+ ` ${chalk4.dim("Structure:")} ${result.structureType} ${chalk4.dim(`(${result.fileCount} files)`)}`
747
747
  );
748
748
  if (result.existingDocs.length > 0) {
749
- console.log(` ${chalk3.dim("Existing docs:")} ${result.existingDocs.join(", ")}`);
749
+ console.log(` ${chalk4.dim("Existing docs:")} ${result.existingDocs.join(", ")}`);
750
750
  }
751
751
  if (result.fileTree && result.fileTree.length > 0) {
752
752
  this.renderTree(result.fileTree);
@@ -756,7 +756,7 @@ var init_progress_renderer = __esm({
756
756
  }
757
757
  renderTree(entries) {
758
758
  console.log("");
759
- console.log(chalk3.cyan.bold(" \u2500\u2500 Project Structure \u2500\u2500"));
759
+ console.log(chalk4.cyan.bold(" \u2500\u2500 Project Structure \u2500\u2500"));
760
760
  const root = { name: "", type: "tree", children: /* @__PURE__ */ new Map() };
761
761
  for (const entry of entries) {
762
762
  const parts = entry.path.split("/");
@@ -776,7 +776,7 @@ var init_progress_renderer = __esm({
776
776
  }
777
777
  const printNode = (node, prefix, isLast) => {
778
778
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
779
- const display = node.type === "tree" ? chalk3.bold.dim(`${node.name}/`) : node.name;
779
+ const display = node.type === "tree" ? chalk4.bold.dim(`${node.name}/`) : node.name;
780
780
  console.log(` ${prefix}${connector}${display}`);
781
781
  const sorted = [...node.children.values()].sort((a, b) => {
782
782
  if (a.type === "tree" && b.type !== "tree") return -1;
@@ -802,7 +802,7 @@ var init_progress_renderer = __esm({
802
802
  this.scanSummaryShown = true;
803
803
  spinner.stop();
804
804
  console.log(
805
- chalk3.dim(
805
+ chalk4.dim(
806
806
  ` Scan complete: ${summary.totalFiles} files, ${summary.totalFunctions} functions, ${summary.totalClasses} classes, ${summary.totalEndpoints} endpoints`
807
807
  )
808
808
  );
@@ -813,15 +813,15 @@ var init_progress_renderer = __esm({
813
813
  if (progress.status === "complete" && !this.validationShown) {
814
814
  this.validationShown = true;
815
815
  spinner.stop();
816
- console.log(chalk3.cyan.bold(" \u2500\u2500 Validation Results \u2500\u2500"));
816
+ console.log(chalk4.cyan.bold(" \u2500\u2500 Validation Results \u2500\u2500"));
817
817
  for (const result of progress.personaResults) {
818
- const scoreColor = result.score === "PASS" ? chalk3.green : result.score === "PARTIAL" ? chalk3.yellow : chalk3.red;
818
+ const scoreColor = result.score === "PASS" ? chalk4.green : result.score === "PARTIAL" ? chalk4.yellow : chalk4.red;
819
819
  console.log(` ${result.persona}: ${scoreColor(result.score)}`);
820
820
  }
821
821
  const passCount = progress.personaResults.filter((r) => r.score === "PASS").length;
822
822
  const total = progress.personaResults.length;
823
823
  const roundInfo = progress.round > 1 ? ` (${progress.round} rounds)` : "";
824
- console.log(chalk3.dim(` ${passCount}/${total} PASS${roundInfo}`));
824
+ console.log(chalk4.dim(` ${passCount}/${total} PASS${roundInfo}`));
825
825
  console.log("");
826
826
  spinner.start();
827
827
  return;
@@ -853,7 +853,7 @@ var init_progress_renderer = __esm({
853
853
  progressText = `Validation round ${vp.round}/${vp.maxRounds}`;
854
854
  }
855
855
  }
856
- return `${progressText}... ${chalk3.dim(`(${pct}%)`)}`;
856
+ return `${progressText}... ${chalk4.dim(`(${pct}%)`)}`;
857
857
  }
858
858
  update(syncResult, spinner) {
859
859
  if (syncResult.privacyShieldEnabled !== void 0) {
@@ -1234,7 +1234,7 @@ __export(create_exports, {
1234
1234
  create: () => create
1235
1235
  });
1236
1236
  import { execSync } from "child_process";
1237
- import chalk4 from "chalk";
1237
+ import chalk5 from "chalk";
1238
1238
  import ora from "ora";
1239
1239
  function detectRepoRoot() {
1240
1240
  return execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim();
@@ -1264,10 +1264,10 @@ async function create() {
1264
1264
  try {
1265
1265
  let credentials = await getValidCredentials();
1266
1266
  if (!credentials) {
1267
- spinner.info(chalk4.yellow("Not logged in. Opening browser to authenticate..."));
1267
+ spinner.info(chalk5.yellow("Not logged in. Opening browser to authenticate..."));
1268
1268
  credentials = await performLogin();
1269
1269
  const { email } = decodeIdToken(credentials.idToken);
1270
- spinner.succeed(chalk4.green(`Authenticated as ${chalk4.bold(email)}`));
1270
+ spinner.succeed(chalk5.green(`Authenticated as ${chalk5.bold(email)}`));
1271
1271
  } else {
1272
1272
  spinner.succeed("Authenticated");
1273
1273
  }
@@ -1280,7 +1280,7 @@ async function create() {
1280
1280
  if (pending?.repoId) {
1281
1281
  repoId = pending.repoId;
1282
1282
  repoName = pending.repoName;
1283
- spinner.succeed(`Found pending repository: ${chalk4.bold(repoName)}`);
1283
+ spinner.succeed(`Found pending repository: ${chalk5.bold(repoName)}`);
1284
1284
  apiRequest("/v1/onboarding/pending", { method: "DELETE" }).catch(() => {
1285
1285
  });
1286
1286
  }
@@ -1291,10 +1291,10 @@ async function create() {
1291
1291
  try {
1292
1292
  repoRoot = detectRepoRoot();
1293
1293
  repoName = detectRepoName(repoRoot);
1294
- spinner.succeed(`Repository: ${chalk4.bold(repoName)}`);
1294
+ spinner.succeed(`Repository: ${chalk5.bold(repoName)}`);
1295
1295
  } catch {
1296
1296
  spinner.fail(
1297
- chalk4.red(
1297
+ chalk5.red(
1298
1298
  "Not in a git repository. Run this command from your repo directory, or select a repo on the dashboard first."
1299
1299
  )
1300
1300
  );
@@ -1317,7 +1317,7 @@ async function create() {
1317
1317
  }
1318
1318
  if (!repoId) {
1319
1319
  spinner.fail(
1320
- chalk4.red(
1320
+ chalk5.red(
1321
1321
  "Could not find this repository in your RepoWise account. Connect it on the dashboard first."
1322
1322
  )
1323
1323
  );
@@ -1327,14 +1327,14 @@ async function create() {
1327
1327
  const { tools, hasOther } = await selectAiTools();
1328
1328
  if (hasOther) {
1329
1329
  console.log(
1330
- chalk4.cyan(
1330
+ chalk5.cyan(
1331
1331
  "\nFor AI tools not listed, context files still work with any tool that reads the filesystem.\nRequest support for your tool at: https://dashboard.repowise.ai/support/ai-tools"
1332
1332
  )
1333
1333
  );
1334
1334
  }
1335
1335
  if (tools.length === 0 && !hasOther) {
1336
1336
  console.log(
1337
- chalk4.yellow(
1337
+ chalk5.yellow(
1338
1338
  "\nNo AI tools selected. You can configure them later with `repowise config`."
1339
1339
  )
1340
1340
  );
@@ -1363,14 +1363,14 @@ async function create() {
1363
1363
  throw new Error("Could not find active sync to resume. Please try again.");
1364
1364
  }
1365
1365
  syncId = active.syncId;
1366
- spinner.info(chalk4.cyan("Resuming existing pipeline..."));
1366
+ spinner.info(chalk5.cyan("Resuming existing pipeline..."));
1367
1367
  spinner.start();
1368
1368
  }
1369
1369
  let pollAttempts = 0;
1370
1370
  const progressRenderer = new ProgressRenderer();
1371
1371
  while (true) {
1372
1372
  if (++pollAttempts > MAX_POLL_ATTEMPTS) {
1373
- spinner.fail(chalk4.red("Pipeline timed out. Check dashboard for status."));
1373
+ spinner.fail(chalk5.red("Pipeline timed out. Check dashboard for status."));
1374
1374
  process.exitCode = 1;
1375
1375
  return;
1376
1376
  }
@@ -1394,7 +1394,7 @@ async function create() {
1394
1394
  break;
1395
1395
  }
1396
1396
  if (syncResult.status === "failed") {
1397
- spinner.fail(chalk4.red(`Pipeline failed: ${syncResult.error ?? "Unknown error"}`));
1397
+ spinner.fail(chalk5.red(`Pipeline failed: ${syncResult.error ?? "Unknown error"}`));
1398
1398
  process.exitCode = 1;
1399
1399
  return;
1400
1400
  }
@@ -1413,7 +1413,7 @@ async function create() {
1413
1413
  const stderr = err instanceof Error && "stderr" in err ? String(err.stderr).trim() : "";
1414
1414
  const reason = stderr || (err instanceof Error ? err.message : "Unknown error");
1415
1415
  spinner.warn(
1416
- chalk4.yellow(
1416
+ chalk5.yellow(
1417
1417
  `Could not pull latest changes: ${reason}
1418
1418
  You may need to run \`git pull\` manually.`
1419
1419
  )
@@ -1441,7 +1441,7 @@ You may need to run \`git pull\` manually.`
1441
1441
  results.push(` ${action} ${config2.filePath}`);
1442
1442
  }
1443
1443
  spinner.succeed("AI tools configured");
1444
- console.log(chalk4.dim(results.join("\n")));
1444
+ console.log(chalk5.dim(results.join("\n")));
1445
1445
  }
1446
1446
  const existingConfig = await getConfig();
1447
1447
  await saveConfig({
@@ -1458,37 +1458,37 @@ You may need to run \`git pull\` manually.`
1458
1458
  listenerRunning = true;
1459
1459
  } catch {
1460
1460
  console.log(
1461
- chalk4.yellow(
1461
+ chalk5.yellow(
1462
1462
  "Warning: Could not start listener automatically. Run the following to enable it:"
1463
1463
  )
1464
1464
  );
1465
- console.log(chalk4.yellow(` $ repowise listen --install`));
1465
+ console.log(chalk5.yellow(` $ repowise listen --install`));
1466
1466
  }
1467
1467
  const elapsed = formatElapsed(Date.now() - startTime);
1468
1468
  console.log("");
1469
- console.log(chalk4.green.bold(" All done! Setup complete!"));
1469
+ console.log(chalk5.green.bold(" All done! Setup complete!"));
1470
1470
  console.log(
1471
- chalk4.green(
1472
- ` Your AI tools now have access to project context for ${chalk4.bold(repoName)}.`
1471
+ chalk5.green(
1472
+ ` Your AI tools now have access to project context for ${chalk5.bold(repoName)}.`
1473
1473
  )
1474
1474
  );
1475
1475
  if (listenerRunning) {
1476
1476
  console.log("");
1477
- console.log(chalk4.cyan(" The RepoWise listener is running in the background \u2014"));
1478
- console.log(chalk4.cyan(" your context will stay in sync automatically."));
1479
- console.log(chalk4.cyan(" Go back to coding, we've got it from here!"));
1477
+ console.log(chalk5.cyan(" The RepoWise listener is running in the background \u2014"));
1478
+ console.log(chalk5.cyan(" your context will stay in sync automatically."));
1479
+ console.log(chalk5.cyan(" Go back to coding, we've got it from here!"));
1480
1480
  }
1481
1481
  console.log("");
1482
1482
  console.log(
1483
- chalk4.cyan(
1483
+ chalk5.cyan(
1484
1484
  ' Head back to the dashboard and click "Complete Onboarding" to explore your RepoWise dashboard!'
1485
1485
  )
1486
1486
  );
1487
- console.log(chalk4.dim(`
1487
+ console.log(chalk5.dim(`
1488
1488
  Total time: ${elapsed}`));
1489
1489
  } catch (err) {
1490
1490
  const message = err instanceof Error ? err.message : "Create failed";
1491
- spinner.fail(chalk4.red(message));
1491
+ spinner.fail(chalk5.red(message));
1492
1492
  process.exitCode = 1;
1493
1493
  }
1494
1494
  }
@@ -1514,7 +1514,7 @@ var login_exports = {};
1514
1514
  __export(login_exports, {
1515
1515
  login: () => login
1516
1516
  });
1517
- import chalk5 from "chalk";
1517
+ import chalk6 from "chalk";
1518
1518
  import ora2 from "ora";
1519
1519
  async function login(options = {}) {
1520
1520
  const spinner = ora2("Preparing login...").start();
@@ -1529,7 +1529,7 @@ async function login(options = {}) {
1529
1529
  console.log(`
1530
1530
  Open this URL in your browser to authenticate:
1531
1531
  `);
1532
- console.log(chalk5.cyan(authorizeUrl));
1532
+ console.log(chalk6.cyan(authorizeUrl));
1533
1533
  console.log(`
1534
1534
  Waiting for authentication...`);
1535
1535
  } else {
@@ -1543,7 +1543,7 @@ Waiting for authentication...`);
1543
1543
  console.log(`
1544
1544
  Could not open browser automatically. Open this URL:
1545
1545
  `);
1546
- console.log(chalk5.cyan(authorizeUrl));
1546
+ console.log(chalk6.cyan(authorizeUrl));
1547
1547
  console.log(`
1548
1548
  Waiting for authentication...`);
1549
1549
  }
@@ -1556,10 +1556,10 @@ Waiting for authentication...`);
1556
1556
  const credentials = await exchangeCodeForTokens(code, codeVerifier);
1557
1557
  await storeCredentials(credentials);
1558
1558
  const { email } = decodeIdToken(credentials.idToken);
1559
- spinner.succeed(chalk5.green(`Logged in as ${chalk5.bold(email)}`));
1559
+ spinner.succeed(chalk6.green(`Logged in as ${chalk6.bold(email)}`));
1560
1560
  } catch (err) {
1561
1561
  const message = err instanceof Error ? err.message : "Login failed";
1562
- spinner.fail(chalk5.red(message));
1562
+ spinner.fail(chalk6.red(message));
1563
1563
  process.exitCode = 1;
1564
1564
  }
1565
1565
  }
@@ -1575,15 +1575,15 @@ var logout_exports = {};
1575
1575
  __export(logout_exports, {
1576
1576
  logout: () => logout
1577
1577
  });
1578
- import chalk6 from "chalk";
1578
+ import chalk7 from "chalk";
1579
1579
  async function logout() {
1580
1580
  const creds = await getStoredCredentials();
1581
1581
  if (!creds) {
1582
- console.log(chalk6.yellow("Not logged in."));
1582
+ console.log(chalk7.yellow("Not logged in."));
1583
1583
  return;
1584
1584
  }
1585
1585
  await clearCredentials();
1586
- console.log(chalk6.green("Logged out successfully."));
1586
+ console.log(chalk7.green("Logged out successfully."));
1587
1587
  }
1588
1588
  var init_logout = __esm({
1589
1589
  "src/commands/logout.ts"() {
@@ -2320,11 +2320,58 @@ var init_config3 = __esm({
2320
2320
  // bin/repowise.ts
2321
2321
  init_env();
2322
2322
  import { Command } from "commander";
2323
+ import { readFileSync } from "fs";
2324
+ import { fileURLToPath as fileURLToPath3 } from "url";
2325
+ import { dirname as dirname2, join as join12 } from "path";
2326
+
2327
+ // src/lib/welcome.ts
2328
+ init_config();
2329
+ import chalk from "chalk";
2330
+ async function showWelcome(currentVersion) {
2331
+ try {
2332
+ const config2 = await getConfig();
2333
+ if (config2.lastSeenVersion === currentVersion) return;
2334
+ const isUpgrade = !!config2.lastSeenVersion;
2335
+ console.log("");
2336
+ console.log(chalk.cyan(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
2337
+ console.log(chalk.cyan(" \u2502 \u2502"));
2338
+ if (isUpgrade) {
2339
+ console.log(
2340
+ chalk.cyan(" \u2502 ") + chalk.bold(`RepoWise v${currentVersion}`) + chalk.green(" \u2713 updated") + chalk.cyan(" \u2502")
2341
+ );
2342
+ } else {
2343
+ console.log(
2344
+ chalk.cyan(" \u2502 ") + chalk.bold(`RepoWise v${currentVersion}`) + chalk.green(" \u2713 installed") + chalk.cyan(" \u2502")
2345
+ );
2346
+ }
2347
+ console.log(chalk.cyan(" \u2502 \u2502"));
2348
+ console.log(chalk.cyan(" \u2502 ") + chalk.dim("Get started:") + chalk.cyan(" \u2502"));
2349
+ console.log(
2350
+ chalk.cyan(" \u2502 $ ") + chalk.bold("repowise create") + chalk.cyan(" \u2502")
2351
+ );
2352
+ console.log(chalk.cyan(" \u2502 \u2502"));
2353
+ console.log(
2354
+ chalk.cyan(" \u2502 ") + chalk.dim("Thank you for using RepoWise!") + chalk.cyan(" \u2502")
2355
+ );
2356
+ console.log(chalk.cyan(" \u2502 ") + chalk.dim("https://repowise.ai") + chalk.cyan(" \u2502"));
2357
+ console.log(chalk.cyan(" \u2502 \u2502"));
2358
+ console.log(chalk.cyan(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
2359
+ console.log("");
2360
+ await saveConfig({ ...config2, lastSeenVersion: currentVersion });
2361
+ } catch {
2362
+ }
2363
+ }
2364
+
2365
+ // bin/repowise.ts
2366
+ var __filename = fileURLToPath3(import.meta.url);
2367
+ var __dirname = dirname2(__filename);
2368
+ var pkg = JSON.parse(readFileSync(join12(__dirname, "..", "package.json"), "utf-8"));
2323
2369
  var program = new Command();
2324
- program.name("repowise").description("AI-optimized codebase context generator").version("0.1.0").option("--staging", "Use the staging environment").hook("preAction", () => {
2370
+ program.name("repowise").description("AI-optimized codebase context generator").version(pkg.version).option("--staging", "Use the staging environment").hook("preAction", async () => {
2325
2371
  if (program.opts()["staging"]) {
2326
2372
  setStagingMode(true);
2327
2373
  }
2374
+ await showWelcome(pkg.version);
2328
2375
  });
2329
2376
  program.command("create").description("Create context for a repository").action(async () => {
2330
2377
  const { create: create2 } = await Promise.resolve().then(() => (init_create(), create_exports));
package/package.json CHANGED
@@ -1,22 +1,20 @@
1
1
  {
2
2
  "name": "repowise",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "description": "AI-optimized codebase context generator",
6
6
  "bin": {
7
7
  "repowise": "dist/bin/repowise.js"
8
8
  },
9
9
  "files": [
10
- "dist",
11
- "scripts/postinstall.js"
10
+ "dist"
12
11
  ],
13
12
  "scripts": {
14
13
  "build": "tsc",
15
14
  "build:bundle": "tsup",
16
15
  "lint": "eslint src/ bin/",
17
16
  "test": "vitest run",
18
- "type-check": "tsc --noEmit",
19
- "postinstall": "node scripts/postinstall.js"
17
+ "type-check": "tsc --noEmit"
20
18
  },
21
19
  "dependencies": {
22
20
  "chalk": "^5.4.0",
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // Lightweight postinstall banner — no dependencies, plain ANSI codes
4
- const version = process.env.npm_package_version || '';
5
-
6
- const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
7
- const bold = (s) => `\x1b[1m${s}\x1b[0m`;
8
- const dim = (s) => `\x1b[2m${s}\x1b[0m`;
9
- const green = (s) => `\x1b[32m${s}\x1b[0m`;
10
-
11
- const v = version ? ` v${version}` : '';
12
-
13
- try {
14
- console.log('');
15
- console.log(cyan(' ╭─────────────────────────────────────────╮'));
16
- console.log(cyan(' │ │'));
17
- console.log(cyan(' │ ') + bold(`RepoWise${v} installed`) + green(' ✓') + cyan(' │'));
18
- console.log(cyan(' │ │'));
19
- console.log(cyan(' │ ') + dim('Get started:') + cyan(' │'));
20
- console.log(cyan(' │ $ ') + bold('repowise create') + cyan(' │'));
21
- console.log(cyan(' │ │'));
22
- console.log(cyan(' │ ') + dim('Thank you for using RepoWise!') + cyan(' │'));
23
- console.log(cyan(' │ ') + dim('https://repowise.ai') + cyan(' │'));
24
- console.log(cyan(' │ │'));
25
- console.log(cyan(' ╰─────────────────────────────────────────╯'));
26
- console.log('');
27
- } catch {
28
- // Never fail installation on a cosmetic banner
29
- }