repowise 0.1.4 → 0.1.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.
Files changed (66) hide show
  1. package/dist/bin/repowise.js +116 -14
  2. package/dist/src/commands/create.d.ts +1 -1
  3. package/dist/src/commands/create.d.ts.map +1 -1
  4. package/dist/src/commands/create.js +237 -2
  5. package/dist/src/commands/create.js.map +1 -1
  6. package/dist/src/commands/listen.d.ts +3 -2
  7. package/dist/src/commands/listen.d.ts.map +1 -1
  8. package/dist/src/commands/listen.js +45 -3
  9. package/dist/src/commands/listen.js.map +1 -1
  10. package/dist/src/commands/login.d.ts +4 -1
  11. package/dist/src/commands/login.d.ts.map +1 -1
  12. package/dist/src/commands/login.js +56 -2
  13. package/dist/src/commands/login.js.map +1 -1
  14. package/dist/src/commands/logout.d.ts +1 -1
  15. package/dist/src/commands/logout.d.ts.map +1 -1
  16. package/dist/src/commands/logout.js +10 -2
  17. package/dist/src/commands/logout.js.map +1 -1
  18. package/dist/src/commands/start.d.ts +2 -0
  19. package/dist/src/commands/start.d.ts.map +1 -0
  20. package/dist/src/commands/start.js +17 -0
  21. package/dist/src/commands/start.js.map +1 -0
  22. package/dist/src/commands/status.d.ts +1 -1
  23. package/dist/src/commands/status.d.ts.map +1 -1
  24. package/dist/src/commands/status.js +61 -2
  25. package/dist/src/commands/status.js.map +1 -1
  26. package/dist/src/commands/stop.d.ts +2 -0
  27. package/dist/src/commands/stop.d.ts.map +1 -0
  28. package/dist/src/commands/stop.js +17 -0
  29. package/dist/src/commands/stop.js.map +1 -0
  30. package/dist/src/lib/ai-tools.d.ts +23 -0
  31. package/dist/src/lib/ai-tools.d.ts.map +1 -0
  32. package/dist/src/lib/ai-tools.js +193 -0
  33. package/dist/src/lib/ai-tools.js.map +1 -0
  34. package/dist/src/lib/api.d.ts.map +1 -1
  35. package/dist/src/lib/api.js +25 -4
  36. package/dist/src/lib/api.js.map +1 -1
  37. package/dist/src/lib/auth.d.ts +18 -0
  38. package/dist/src/lib/auth.d.ts.map +1 -1
  39. package/dist/src/lib/auth.js +251 -7
  40. package/dist/src/lib/auth.js.map +1 -1
  41. package/dist/src/lib/config.d.ts +2 -0
  42. package/dist/src/lib/config.d.ts.map +1 -1
  43. package/dist/src/lib/config.js.map +1 -1
  44. package/dist/src/lib/env.d.ts +10 -0
  45. package/dist/src/lib/env.d.ts.map +1 -0
  46. package/dist/src/lib/env.js +26 -0
  47. package/dist/src/lib/env.js.map +1 -0
  48. package/dist/src/lib/interview-handler.d.ts +2 -0
  49. package/dist/src/lib/interview-handler.d.ts.map +1 -0
  50. package/dist/src/lib/interview-handler.js +96 -0
  51. package/dist/src/lib/interview-handler.js.map +1 -0
  52. package/dist/src/lib/progress-renderer.d.ts +69 -0
  53. package/dist/src/lib/progress-renderer.d.ts.map +1 -0
  54. package/dist/src/lib/progress-renderer.js +186 -0
  55. package/dist/src/lib/progress-renderer.js.map +1 -0
  56. package/dist/src/lib/prompts.d.ts +6 -1
  57. package/dist/src/lib/prompts.d.ts.map +1 -1
  58. package/dist/src/lib/prompts.js +21 -3
  59. package/dist/src/lib/prompts.js.map +1 -1
  60. package/dist/src/types/index.d.ts +1 -0
  61. package/dist/src/types/index.d.ts.map +1 -1
  62. package/dist/tsup.config.d.ts +3 -0
  63. package/dist/tsup.config.d.ts.map +1 -0
  64. package/dist/tsup.config.js +18 -0
  65. package/dist/tsup.config.js.map +1 -0
  66. package/package.json +1 -1
@@ -102,20 +102,38 @@ function startCallbackServer() {
102
102
  const error = url.searchParams.get("error");
103
103
  if (error) {
104
104
  res.writeHead(200, { "Content-Type": "text/html" });
105
- res.end(callbackPage("Authentication Failed", "Something went wrong. Please close this tab and try again.", true));
105
+ res.end(
106
+ callbackPage(
107
+ "Authentication Failed",
108
+ "Something went wrong. Please close this tab and try again.",
109
+ true
110
+ )
111
+ );
106
112
  server.close();
107
113
  reject(new Error(`Authentication error: ${error}`));
108
114
  return;
109
115
  }
110
116
  if (!code || !state) {
111
117
  res.writeHead(400, { "Content-Type": "text/html" });
112
- res.end(callbackPage("Missing Parameters", "The callback was missing required data. Please close this tab and try again.", true));
118
+ res.end(
119
+ callbackPage(
120
+ "Missing Parameters",
121
+ "The callback was missing required data. Please close this tab and try again.",
122
+ true
123
+ )
124
+ );
113
125
  server.close();
114
126
  reject(new Error("Missing code or state in callback"));
115
127
  return;
116
128
  }
117
129
  res.writeHead(200, { "Content-Type": "text/html" });
118
- res.end(callbackPage("Authentication Successful", "You can close this tab and return to the terminal.", false));
130
+ res.end(
131
+ callbackPage(
132
+ "Authentication Successful",
133
+ "You can close this tab and return to the terminal.",
134
+ false
135
+ )
136
+ );
119
137
  server.close();
120
138
  resolve({ code, state });
121
139
  });
@@ -574,16 +592,32 @@ var init_config = __esm({
574
592
  // src/lib/interview-handler.ts
575
593
  import chalk2 from "chalk";
576
594
  import { input } from "@inquirer/prompts";
577
- async function handleInterview(syncId, questionId, questionText, questionContext) {
595
+ async function handleInterview(syncId, questionId, questionText, questionContext, estimatedQuestions) {
578
596
  questionCounter++;
597
+ if (questionCounter === 1) {
598
+ console.log("");
599
+ console.log(chalk2.cyan.bold(" \u2500\u2500 Interview \u2500\u2500"));
600
+ console.log(chalk2.dim(" Help us understand your project better. Answer a few short"));
601
+ console.log(chalk2.dim(" questions so we can generate more relevant context files."));
602
+ if (estimatedQuestions) {
603
+ console.log(
604
+ chalk2.dim(
605
+ ` The AI estimates ${chalk2.white(`~${estimatedQuestions}`)} questions based on your codebase.`
606
+ )
607
+ );
608
+ }
609
+ console.log(chalk2.dim(' Type "skip" to skip a question, "done" to finish early.'));
610
+ }
579
611
  console.log("");
580
- console.log(chalk2.cyan.bold(` \u2500\u2500 Interview Question ${questionCounter} \u2500\u2500`));
612
+ console.log(
613
+ chalk2.cyan.bold(
614
+ ` Question ${questionCounter}${estimatedQuestions ? `/${estimatedQuestions}` : ""}`
615
+ )
616
+ );
581
617
  if (questionContext) {
582
618
  console.log(chalk2.dim(` ${questionContext}`));
583
619
  }
584
620
  console.log(` ${questionText}`);
585
- console.log(chalk2.dim(' Type "skip" to skip, "done" to finish interview early.'));
586
- console.log(chalk2.dim(" (Auto-skips after 5 minutes of inactivity)"));
587
621
  let answer;
588
622
  try {
589
623
  answer = await Promise.race([
@@ -705,9 +739,55 @@ var init_progress_renderer = __esm({
705
739
  if (result.existingDocs.length > 0) {
706
740
  console.log(` ${chalk3.dim("Existing docs:")} ${result.existingDocs.join(", ")}`);
707
741
  }
742
+ if (result.fileTree && result.fileTree.length > 0) {
743
+ this.renderTree(result.fileTree);
744
+ }
708
745
  console.log("");
709
746
  spinner.start();
710
747
  }
748
+ renderTree(entries) {
749
+ console.log("");
750
+ console.log(chalk3.cyan.bold(" \u2500\u2500 Project Structure \u2500\u2500"));
751
+ const root = { name: "", type: "tree", children: /* @__PURE__ */ new Map() };
752
+ for (const entry of entries) {
753
+ const parts = entry.path.split("/");
754
+ let current = root;
755
+ for (let i = 0; i < parts.length; i++) {
756
+ const part = parts[i];
757
+ if (!current.children.has(part)) {
758
+ const isLast = i === parts.length - 1;
759
+ current.children.set(part, {
760
+ name: part,
761
+ type: isLast ? entry.type : "tree",
762
+ children: /* @__PURE__ */ new Map()
763
+ });
764
+ }
765
+ current = current.children.get(part);
766
+ }
767
+ }
768
+ const printNode = (node, prefix, isLast) => {
769
+ const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
770
+ const display = node.type === "tree" ? chalk3.bold.dim(`${node.name}/`) : node.name;
771
+ console.log(` ${prefix}${connector}${display}`);
772
+ const sorted = [...node.children.values()].sort((a, b) => {
773
+ if (a.type === "tree" && b.type !== "tree") return -1;
774
+ if (a.type !== "tree" && b.type === "tree") return 1;
775
+ return a.name.localeCompare(b.name);
776
+ });
777
+ const childPrefix = prefix + (isLast ? " " : "\u2502 ");
778
+ sorted.forEach((child, idx) => {
779
+ printNode(child, childPrefix, idx === sorted.length - 1);
780
+ });
781
+ };
782
+ const topLevel = [...root.children.values()].sort((a, b) => {
783
+ if (a.type === "tree" && b.type !== "tree") return -1;
784
+ if (a.type !== "tree" && b.type === "tree") return 1;
785
+ return a.name.localeCompare(b.name);
786
+ });
787
+ topLevel.forEach((child, idx) => {
788
+ printNode(child, "", idx === topLevel.length - 1);
789
+ });
790
+ }
711
791
  renderScanSummary(summary, spinner) {
712
792
  if (this.scanSummaryShown) return;
713
793
  this.scanSummaryShown = true;
@@ -1230,11 +1310,32 @@ async function create() {
1230
1310
  );
1231
1311
  }
1232
1312
  spinner.start("Starting context generation pipeline...");
1233
- const triggerResult = await apiRequest(`/v1/repos/${repoId}/sync`, {
1234
- method: "POST",
1235
- body: JSON.stringify({ scanType: "full" })
1236
- });
1237
- const syncId = triggerResult.syncId;
1313
+ let syncId;
1314
+ try {
1315
+ const triggerResult = await apiRequest(`/v1/repos/${repoId}/sync`, {
1316
+ method: "POST",
1317
+ body: JSON.stringify({ scanType: "full" })
1318
+ });
1319
+ syncId = triggerResult.syncId;
1320
+ } catch (triggerErr) {
1321
+ const msg = triggerErr instanceof Error ? triggerErr.message : "";
1322
+ if (!msg.toLowerCase().includes("already running")) {
1323
+ throw triggerErr;
1324
+ }
1325
+ spinner.text = "Resuming existing pipeline...";
1326
+ const syncs = await apiRequest(
1327
+ `/v1/repos/${repoId}/syncs?limit=1`
1328
+ );
1329
+ const active = syncs.items.find(
1330
+ (s) => s.status === "in_progress" || s.status === "awaiting_input"
1331
+ );
1332
+ if (!active) {
1333
+ throw new Error("Could not find active sync to resume. Please try again.");
1334
+ }
1335
+ syncId = active.syncId;
1336
+ spinner.info(chalk4.cyan("Resuming existing pipeline..."));
1337
+ spinner.start();
1338
+ }
1238
1339
  let pollAttempts = 0;
1239
1340
  const progressRenderer = new ProgressRenderer();
1240
1341
  while (true) {
@@ -1245,13 +1346,15 @@ async function create() {
1245
1346
  }
1246
1347
  await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
1247
1348
  const syncResult = await apiRequest(`/v1/sync/${syncId}/status`);
1349
+ progressRenderer.update(syncResult, spinner);
1248
1350
  if (syncResult.status === "awaiting_input" && syncResult.questionId && syncResult.questionText) {
1249
1351
  spinner.stop();
1250
1352
  await handleInterview(
1251
1353
  syncId,
1252
1354
  syncResult.questionId,
1253
1355
  syncResult.questionText,
1254
- syncResult.questionContext ?? void 0
1356
+ syncResult.questionContext ?? void 0,
1357
+ syncResult.discoveryResult?.estimatedInterviewQuestions
1255
1358
  );
1256
1359
  spinner.start("Resuming pipeline...");
1257
1360
  continue;
@@ -1265,7 +1368,6 @@ async function create() {
1265
1368
  process.exitCode = 1;
1266
1369
  return;
1267
1370
  }
1268
- progressRenderer.update(syncResult, spinner);
1269
1371
  }
1270
1372
  if (repoRoot) {
1271
1373
  spinner.start("Pulling latest changes...");
@@ -1,2 +1,2 @@
1
- export declare function create(): void;
1
+ export declare function create(): Promise<void>;
2
2
  //# sourceMappingURL=create.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,IAAI,IAAI,CAE7B"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"AAyGA,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAkQ5C"}
@@ -1,4 +1,239 @@
1
- export function create() {
2
- console.log('Create command - not yet implemented');
1
+ import { execSync } from 'node:child_process';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { getValidCredentials, performLogin, decodeIdToken } from '../lib/auth.js';
5
+ import { apiRequest } from '../lib/api.js';
6
+ import { selectAiTools } from '../lib/prompts.js';
7
+ import { updateToolConfig, scanLocalContextFiles, AI_TOOL_CONFIG } from '../lib/ai-tools.js';
8
+ import { getConfig, saveConfig } from '../lib/config.js';
9
+ import { handleInterview } from '../lib/interview-handler.js';
10
+ import { ProgressRenderer } from '../lib/progress-renderer.js';
11
+ function detectRepoRoot() {
12
+ return execSync('git rev-parse --show-toplevel', { encoding: 'utf-8' }).trim();
13
+ }
14
+ function detectRepoName(repoRoot) {
15
+ try {
16
+ const remoteUrl = execSync('git remote get-url origin', {
17
+ encoding: 'utf-8',
18
+ cwd: repoRoot,
19
+ }).trim();
20
+ // Extract repo name from URL (handles both HTTPS and SSH)
21
+ const match = remoteUrl.match(/\/([^/]+?)(?:\.git)?$/);
22
+ if (match?.[1])
23
+ return match[1];
24
+ }
25
+ catch {
26
+ // No remote configured — fall back to directory name
27
+ }
28
+ return repoRoot.split('/').pop() ?? 'unknown';
29
+ }
30
+ function formatElapsed(ms) {
31
+ const totalSeconds = Math.round(ms / 1000);
32
+ const minutes = Math.floor(totalSeconds / 60);
33
+ const seconds = totalSeconds % 60;
34
+ if (minutes === 0)
35
+ return `${seconds}s`;
36
+ return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
37
+ }
38
+ const POLL_INTERVAL_MS = 3000;
39
+ const MAX_POLL_ATTEMPTS = 200; // ~10 minutes at 3s interval
40
+ const DEFAULT_CONTEXT_FOLDER = 'repowise-context';
41
+ export async function create() {
42
+ const startTime = Date.now();
43
+ const spinner = ora('Checking authentication...').start();
44
+ try {
45
+ // Step 1: Auth check — auto-login if not authenticated (Story 2.1)
46
+ let credentials = await getValidCredentials();
47
+ if (!credentials) {
48
+ spinner.info(chalk.yellow('Not logged in. Opening browser to authenticate...'));
49
+ credentials = await performLogin();
50
+ const { email } = decodeIdToken(credentials.idToken);
51
+ spinner.succeed(chalk.green(`Authenticated as ${chalk.bold(email)}`));
52
+ }
53
+ else {
54
+ spinner.succeed('Authenticated');
55
+ }
56
+ // Step 2: Check for pending onboarding repo from dashboard (Story 2.2)
57
+ let repoId;
58
+ let repoName;
59
+ let repoRoot;
60
+ spinner.start('Checking for pending repository...');
61
+ try {
62
+ const pending = await apiRequest('/v1/onboarding/pending');
63
+ if (pending?.repoId) {
64
+ repoId = pending.repoId;
65
+ repoName = pending.repoName;
66
+ spinner.succeed(`Found pending repository: ${chalk.bold(repoName)}`);
67
+ // Clear pending onboarding after pickup
68
+ apiRequest('/v1/onboarding/pending', { method: 'DELETE' }).catch(() => { });
69
+ }
70
+ }
71
+ catch {
72
+ // No pending onboarding API available or failed — fall through to local detection
73
+ }
74
+ // Fall back to local git detection if no pending repo
75
+ if (!repoId) {
76
+ spinner.text = 'Detecting repository...';
77
+ try {
78
+ repoRoot = detectRepoRoot();
79
+ repoName = detectRepoName(repoRoot);
80
+ spinner.succeed(`Repository: ${chalk.bold(repoName)}`);
81
+ }
82
+ catch {
83
+ spinner.fail(chalk.red('Not in a git repository. Run this command from your repo directory, or select a repo on the dashboard first.'));
84
+ process.exitCode = 1;
85
+ return;
86
+ }
87
+ // Resolve repoId from API
88
+ try {
89
+ const repos = await apiRequest('/v1/repos');
90
+ const match = repos.find((r) => r.name === repoName || r.fullName.endsWith(`/${repoName}`));
91
+ if (match) {
92
+ repoId = match.repoId;
93
+ }
94
+ }
95
+ catch {
96
+ // Could not resolve — will fail at sync trigger
97
+ }
98
+ }
99
+ else {
100
+ // Try to detect local repo root even with pending repo (for git pull later)
101
+ try {
102
+ repoRoot = detectRepoRoot();
103
+ }
104
+ catch {
105
+ // Not in a git repo directory — that's ok with pending repo
106
+ }
107
+ }
108
+ if (!repoId) {
109
+ spinner.fail(chalk.red('Could not find this repository in your RepoWise account. Connect it on the dashboard first.'));
110
+ process.exitCode = 1;
111
+ return;
112
+ }
113
+ // Step 3: AI tool selection
114
+ const { tools, hasOther } = await selectAiTools();
115
+ if (hasOther) {
116
+ console.log(chalk.cyan('\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'));
117
+ }
118
+ if (tools.length === 0 && !hasOther) {
119
+ console.log(chalk.yellow('\nNo AI tools selected. You can configure them later with `repowise config`.'));
120
+ }
121
+ // Step 4: Trigger pipeline (or resume an existing active sync)
122
+ spinner.start('Starting context generation pipeline...');
123
+ let syncId;
124
+ try {
125
+ const triggerResult = await apiRequest(`/v1/repos/${repoId}/sync`, {
126
+ method: 'POST',
127
+ body: JSON.stringify({ scanType: 'full' }),
128
+ });
129
+ syncId = triggerResult.syncId;
130
+ }
131
+ catch (triggerErr) {
132
+ const msg = triggerErr instanceof Error ? triggerErr.message : '';
133
+ if (!msg.toLowerCase().includes('already running')) {
134
+ throw triggerErr;
135
+ }
136
+ // A sync is already in progress — find it and resume polling
137
+ spinner.text = 'Resuming existing pipeline...';
138
+ const syncs = await apiRequest(`/v1/repos/${repoId}/syncs?limit=1`);
139
+ const active = syncs.items.find((s) => s.status === 'in_progress' || s.status === 'awaiting_input');
140
+ if (!active) {
141
+ throw new Error('Could not find active sync to resume. Please try again.');
142
+ }
143
+ syncId = active.syncId;
144
+ spinner.info(chalk.cyan('Resuming existing pipeline...'));
145
+ spinner.start();
146
+ }
147
+ // Step 5: Poll for completion with enriched progress display
148
+ let pollAttempts = 0;
149
+ const progressRenderer = new ProgressRenderer();
150
+ while (true) {
151
+ if (++pollAttempts > MAX_POLL_ATTEMPTS) {
152
+ spinner.fail(chalk.red('Pipeline timed out. Check dashboard for status.'));
153
+ process.exitCode = 1;
154
+ return;
155
+ }
156
+ await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
157
+ const syncResult = await apiRequest(`/v1/sync/${syncId}/status`);
158
+ // Update progress display first so discovery/scan sections render
159
+ // even if the status already jumped to awaiting_input or completed
160
+ progressRenderer.update(syncResult, spinner);
161
+ // Handle interview questions (Story 3.2)
162
+ if (syncResult.status === 'awaiting_input' &&
163
+ syncResult.questionId &&
164
+ syncResult.questionText) {
165
+ spinner.stop();
166
+ await handleInterview(syncId, syncResult.questionId, syncResult.questionText, syncResult.questionContext ?? undefined, syncResult.discoveryResult?.estimatedInterviewQuestions);
167
+ spinner.start('Resuming pipeline...');
168
+ continue;
169
+ }
170
+ if (syncResult.status === 'completed') {
171
+ spinner.succeed('Context generation complete');
172
+ break;
173
+ }
174
+ if (syncResult.status === 'failed') {
175
+ spinner.fail(chalk.red(`Pipeline failed: ${syncResult.error ?? 'Unknown error'}`));
176
+ process.exitCode = 1;
177
+ return;
178
+ }
179
+ }
180
+ // Step 6: Git pull to get context files
181
+ if (repoRoot) {
182
+ spinner.start('Pulling latest changes...');
183
+ try {
184
+ execSync('git pull', { cwd: repoRoot, encoding: 'utf-8', stdio: 'pipe' });
185
+ spinner.succeed('Pulled latest changes');
186
+ }
187
+ catch {
188
+ spinner.warn(chalk.yellow('Could not pull latest changes. You may need to run `git pull` manually.'));
189
+ }
190
+ }
191
+ // Step 7: Collect context files
192
+ const contextFolder = DEFAULT_CONTEXT_FOLDER;
193
+ let contextFiles = [];
194
+ if (repoRoot) {
195
+ contextFiles = await scanLocalContextFiles(repoRoot, contextFolder);
196
+ }
197
+ // Step 8: Configure AI tools
198
+ if (tools.length > 0 && repoRoot) {
199
+ spinner.start('Configuring AI tools...');
200
+ const results = [];
201
+ for (const tool of tools) {
202
+ const { created: wasCreated } = await updateToolConfig(repoRoot, tool, repoName, contextFolder, contextFiles);
203
+ const config = AI_TOOL_CONFIG[tool];
204
+ const action = wasCreated ? 'Created' : 'Updated';
205
+ results.push(` ${action} ${config.filePath}`);
206
+ }
207
+ spinner.succeed('AI tools configured');
208
+ console.log(chalk.dim(results.join('\n')));
209
+ }
210
+ // Step 9: Save config
211
+ const existingConfig = await getConfig();
212
+ await saveConfig({
213
+ ...existingConfig,
214
+ aiTools: tools,
215
+ contextFolder,
216
+ });
217
+ // Step 10: Auto-start listener
218
+ try {
219
+ const { install } = await import('@repowise/listener/service-installer');
220
+ const { startBackground } = await import('@repowise/listener/process-manager');
221
+ await install();
222
+ await startBackground();
223
+ console.log(chalk.green('Listener started — your context will stay in sync automatically.'));
224
+ }
225
+ catch {
226
+ console.log(chalk.yellow('Warning: Could not start listener automatically. Run `repowise listen --install` to enable auto-start.'));
227
+ }
228
+ // Step 11: Completion summary with elapsed time (Story 2.3)
229
+ const elapsed = formatElapsed(Date.now() - startTime);
230
+ console.log(chalk.green(`\n${chalk.bold('Setup complete!')} Your AI tools now have access to project context for ${chalk.bold(repoName)}.`));
231
+ console.log(chalk.dim(`Total time: ${elapsed}`));
232
+ }
233
+ catch (err) {
234
+ const message = err instanceof Error ? err.message : 'Create failed';
235
+ spinner.fail(chalk.red(message));
236
+ process.exitCode = 1;
237
+ }
3
238
  }
4
239
  //# sourceMappingURL=create.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,MAAM;IACpB,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- export declare function listen(_options: {
1
+ export declare function listen(options: {
2
2
  install?: boolean;
3
- }): void;
3
+ uninstall?: boolean;
4
+ }): Promise<void>;
4
5
  //# sourceMappingURL=listen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"listen.d.ts","sourceRoot":"","sources":["../../../src/commands/listen.ts"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,CAAC,QAAQ,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAG5D"}
1
+ {"version":3,"file":"listen.d.ts","sourceRoot":"","sources":["../../../src/commands/listen.ts"],"names":[],"mappings":"AAEA,wBAAsB,MAAM,CAAC,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA6C/F"}
@@ -1,5 +1,47 @@
1
- export function listen(_options) {
2
- void _options;
3
- console.log('Listen command - not yet implemented');
1
+ import { getValidCredentials } from '../lib/auth.js';
2
+ export async function listen(options) {
3
+ if (options.install) {
4
+ try {
5
+ const { install } = await import('@repowise/listener/service-installer');
6
+ await install();
7
+ console.log('Auto-start service installed. The listener will start on boot.');
8
+ }
9
+ catch (err) {
10
+ const message = err instanceof Error ? err.message : 'Unknown error';
11
+ console.error(`Failed to install auto-start service: ${message}`);
12
+ console.error('You can still run the listener manually with `repowise listen`.');
13
+ process.exitCode = 1;
14
+ }
15
+ return;
16
+ }
17
+ if (options.uninstall) {
18
+ try {
19
+ const { uninstall } = await import('@repowise/listener/service-installer');
20
+ await uninstall();
21
+ console.log('Auto-start service removed.');
22
+ }
23
+ catch (err) {
24
+ const message = err instanceof Error ? err.message : 'Unknown error';
25
+ console.error(`Failed to uninstall auto-start service: ${message}`);
26
+ process.exitCode = 1;
27
+ }
28
+ return;
29
+ }
30
+ const credentials = await getValidCredentials();
31
+ if (!credentials) {
32
+ console.error('Not logged in. Run `repowise login` first.');
33
+ process.exitCode = 1;
34
+ return;
35
+ }
36
+ console.log('Starting RepoWise listener...');
37
+ // Dynamic import to avoid hard dependency on listener package
38
+ try {
39
+ const { startListener } = await import('@repowise/listener/main');
40
+ await startListener();
41
+ }
42
+ catch {
43
+ console.error('Failed to start listener. Ensure @repowise/listener is installed.');
44
+ process.exitCode = 1;
45
+ }
4
46
  }
5
47
  //# sourceMappingURL=listen.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"listen.js","sourceRoot":"","sources":["../../../src/commands/listen.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,MAAM,CAAC,QAA+B;IACpD,KAAK,QAAQ,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"listen.js","sourceRoot":"","sources":["../../../src/commands/listen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAmD;IAC9E,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,sCAAsC,CAAC,CAAC;YACzE,MAAM,OAAO,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,OAAO,CAAC,KAAK,CAAC,yCAAyC,OAAO,EAAE,CAAC,CAAC;YAClE,OAAO,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;YACjF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,sCAAsC,CAAC,CAAC;YAC3E,MAAM,SAAS,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,OAAO,CAAC,KAAK,CAAC,2CAA2C,OAAO,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAChD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAC5D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAE7C,8DAA8D;IAC9D,IAAI,CAAC;QACH,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QAClE,MAAM,aAAa,EAAE,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACnF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -1,2 +1,5 @@
1
- export declare function login(): void;
1
+ export interface LoginOptions {
2
+ browser?: boolean;
3
+ }
4
+ export declare function login(options?: LoginOptions): Promise<void>;
2
5
  //# sourceMappingURL=login.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/commands/login.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,IAAI,IAAI,CAE5B"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/commands/login.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6DrE"}
@@ -1,4 +1,58 @@
1
- export function login() {
2
- console.log('Login command - not yet implemented');
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { generateCodeVerifier, generateCodeChallenge, generateState, getAuthorizeUrl, startCallbackServer, exchangeCodeForTokens, storeCredentials, decodeIdToken, } from '../lib/auth.js';
4
+ export async function login(options = {}) {
5
+ const spinner = ora('Preparing login...').start();
6
+ try {
7
+ // Generate PKCE and state
8
+ const codeVerifier = generateCodeVerifier();
9
+ const codeChallenge = generateCodeChallenge(codeVerifier);
10
+ const state = generateState();
11
+ // Build authorize URL
12
+ const authorizeUrl = getAuthorizeUrl(codeChallenge, state);
13
+ // Start callback server first
14
+ const callbackPromise = startCallbackServer();
15
+ // Open browser or print URL
16
+ if (options.browser === false) {
17
+ spinner.stop();
18
+ console.log(`\nOpen this URL in your browser to authenticate:\n`);
19
+ console.log(chalk.cyan(authorizeUrl));
20
+ console.log(`\nWaiting for authentication...`);
21
+ }
22
+ else {
23
+ spinner.text = 'Opening browser for authentication...';
24
+ try {
25
+ const open = (await import('open')).default;
26
+ await open(authorizeUrl);
27
+ spinner.text = 'Waiting for authentication in browser...';
28
+ }
29
+ catch {
30
+ // Fall back to printing URL if open fails
31
+ spinner.stop();
32
+ console.log(`\nCould not open browser automatically. Open this URL:\n`);
33
+ console.log(chalk.cyan(authorizeUrl));
34
+ console.log(`\nWaiting for authentication...`);
35
+ }
36
+ }
37
+ // Wait for callback
38
+ const { code, state: returnedState } = await callbackPromise;
39
+ // Validate state
40
+ if (returnedState !== state) {
41
+ throw new Error('State mismatch — possible CSRF attack. Please try again.');
42
+ }
43
+ spinner.start('Exchanging authorization code...');
44
+ // Exchange code for tokens
45
+ const credentials = await exchangeCodeForTokens(code, codeVerifier);
46
+ // Store credentials
47
+ await storeCredentials(credentials);
48
+ // Decode ID token for display
49
+ const { email } = decodeIdToken(credentials.idToken);
50
+ spinner.succeed(chalk.green(`Logged in as ${chalk.bold(email)}`));
51
+ }
52
+ catch (err) {
53
+ const message = err instanceof Error ? err.message : 'Login failed';
54
+ spinner.fail(chalk.red(message));
55
+ process.exitCode = 1;
56
+ }
3
57
  }
4
58
  //# sourceMappingURL=login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/login.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,KAAK;IACnB,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export declare function logout(): void;
1
+ export declare function logout(): Promise<void>;
2
2
  //# sourceMappingURL=logout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,IAAI,IAAI,CAE7B"}
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../src/commands/logout.ts"],"names":[],"mappings":"AAGA,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAU5C"}
@@ -1,4 +1,12 @@
1
- export function logout() {
2
- console.log('Logout command - not yet implemented');
1
+ import chalk from 'chalk';
2
+ import { clearCredentials, getStoredCredentials } from '../lib/auth.js';
3
+ export async function logout() {
4
+ const creds = await getStoredCredentials();
5
+ if (!creds) {
6
+ console.log(chalk.yellow('Not logged in.'));
7
+ return;
8
+ }
9
+ await clearCredentials();
10
+ console.log(chalk.green('Logged out successfully.'));
3
11
  }
4
12
  //# sourceMappingURL=logout.js.map