liferewind 0.1.1 → 0.1.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/collect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,eAAO,MAAM,cAAc,SA6DvB,CAAC"}
1
+ {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/collect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,eAAO,MAAM,cAAc,SAyDvB,CAAC"}
@@ -20,7 +20,6 @@ export const collectCommand = new Command('collect')
20
20
  .action(async (source, _options, cmd) => {
21
21
  const globalOpts = cmd.optsWithGlobals();
22
22
  const verbose = !!globalOpts.verbose;
23
- // Validate source argument
24
23
  if (source && !SOURCE_TYPES.includes(source)) {
25
24
  printError(`Invalid source: ${source}`);
26
25
  console.log(`Valid sources: ${SOURCE_TYPES.join(', ')}`);
@@ -28,7 +27,6 @@ export const collectCommand = new Command('collect')
28
27
  }
29
28
  try {
30
29
  const config = loadConfig(globalOpts.config);
31
- // Apply global log level overrides
32
30
  let logLevel = config.logging.level;
33
31
  if (globalOpts.verbose)
34
32
  logLevel = 'debug';
@@ -45,7 +43,6 @@ export const collectCommand = new Command('collect')
45
43
  }
46
44
  const spinner = ora();
47
45
  if (source) {
48
- // Collect specific source
49
46
  if (!enabledSources.includes(source)) {
50
47
  printError(`Source '${source}' is not enabled or not validated.`);
51
48
  process.exit(1);
@@ -56,7 +53,6 @@ export const collectCommand = new Command('collect')
56
53
  showSkippedInfo(result, verbose);
57
54
  }
58
55
  else {
59
- // Collect all enabled sources
60
56
  for (const src of enabledSources) {
61
57
  spinner.start(`Collecting from ${src}...`);
62
58
  const result = await collector.triggerCollection(src);
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,eAAO,MAAM,aAAa,SAA4D,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,eAAO,MAAM,aAAa,SAA4D,CAAC"}
@@ -1,15 +1,14 @@
1
1
  import { Command } from 'commander';
2
2
  import { existsSync } from 'node:fs';
3
- import { homedir } from 'node:os';
4
3
  import pc from 'picocolors';
5
- import { input, confirm, select, checkbox } from '@inquirer/prompts';
4
+ import { confirm, select, checkbox, Separator } from '@inquirer/prompts';
6
5
  import { loadConfig, findConfigPath } from '../../config/loader.js';
7
6
  import { writeConfig } from '../../config/writer.js';
8
7
  import { getUserConfigPath, getAllConfigPaths } from '../../config/paths.js';
9
8
  import { printError, printSuccess, printInfo, printDim } from '../utils/output.js';
10
9
  import { detectInstalledBrowsers, detectGitInstalled, detectChatbotClients } from '../detect/index.js';
11
- import { parsePaths } from '../utils/path.js';
12
- import { maskApiKey, warnMissingPaths, showMaskedKey, SCHEDULE_CHOICES } from '../utils/prompts.js';
10
+ import { maskApiKey, SCHEDULE_CHOICES, GIT_PATH_PRESETS, FILESYSTEM_PATH_PRESETS, selectPaths, } from '../utils/prompts.js';
11
+ import { inputApiUrl, inputApiKey } from '../utils/api.js';
13
12
  export const configCommand = new Command('config').description('Manage configuration');
14
13
  function printConfigSummary(config, revealSecrets = false) {
15
14
  console.log(pc.bold('\nAPI Configuration'));
@@ -90,10 +89,10 @@ configCommand
90
89
  process.exit(1);
91
90
  }
92
91
  let hasChanges = false;
93
- // Main menu loop
94
92
  while (true) {
95
93
  const choice = await select({
96
94
  message: 'What would you like to configure?',
95
+ loop: false,
97
96
  choices: [
98
97
  { name: `API Settings ${pc.dim(`(${config.api.baseUrl})`)}`, value: 'api' },
99
98
  {
@@ -110,7 +109,7 @@ configCommand
110
109
  value: 'chatbot',
111
110
  },
112
111
  { name: `Logging ${pc.dim(`(${config.logging.level})`)}`, value: 'logging' },
113
- { name: pc.dim('─────────────'), value: 'separator', disabled: true },
112
+ new Separator(),
114
113
  { name: hasChanges ? pc.green('Save and Exit') : 'Exit', value: 'exit' },
115
114
  ],
116
115
  });
@@ -127,29 +126,12 @@ configCommand
127
126
  }
128
127
  break;
129
128
  }
130
- // Handle each section
131
129
  if (choice === 'api') {
132
- const newUrl = await input({
133
- message: 'API Base URL:',
134
- default: config.api.baseUrl,
135
- validate: (value) => {
136
- try {
137
- new URL(value);
138
- return true;
139
- }
140
- catch {
141
- return 'Please enter a valid URL';
142
- }
143
- },
144
- });
130
+ const newUrl = await inputApiUrl(config.api.baseUrl);
145
131
  const changeKey = await confirm({ message: 'Change API Key?', default: false });
146
132
  let newKey = config.api.apiKey;
147
133
  if (changeKey) {
148
- newKey = await input({
149
- message: 'New API Key:',
150
- validate: (value) => (value.length > 0 ? true : 'API Key is required'),
151
- });
152
- showMaskedKey(newKey);
134
+ newKey = await inputApiKey();
153
135
  }
154
136
  if (newUrl !== config.api.baseUrl || newKey !== config.api.apiKey) {
155
137
  config.api.baseUrl = newUrl;
@@ -170,6 +152,7 @@ configCommand
170
152
  const currentBrowsers = config.sources.browser.options.browsers || [];
171
153
  const selectedBrowsers = await checkbox({
172
154
  message: 'Select browsers:',
155
+ loop: false,
173
156
  choices: ['chrome', 'safari', 'arc', 'dia', 'comet'].map((b) => ({
174
157
  name: b.charAt(0).toUpperCase() + b.slice(1),
175
158
  value: b,
@@ -179,6 +162,7 @@ configCommand
179
162
  const schedule = await select({
180
163
  message: 'Collection schedule:',
181
164
  choices: SCHEDULE_CHOICES,
165
+ loop: false,
182
166
  default: config.sources.browser.schedule,
183
167
  });
184
168
  config.sources.browser = {
@@ -201,15 +185,11 @@ configCommand
201
185
  });
202
186
  if (enabled) {
203
187
  const currentPaths = config.sources.git.options.scanPaths || [];
204
- const pathsInput = await input({
205
- message: 'Paths to scan (comma-separated):',
206
- default: currentPaths.join(',') || `${homedir()}/Projects`,
207
- });
208
- const scanPaths = parsePaths(pathsInput);
209
- warnMissingPaths(scanPaths);
188
+ const scanPaths = await selectPaths('Select paths to scan for git repositories:', GIT_PATH_PRESETS, currentPaths);
210
189
  const schedule = await select({
211
190
  message: 'Collection schedule:',
212
191
  choices: SCHEDULE_CHOICES,
192
+ loop: false,
213
193
  default: config.sources.git.schedule,
214
194
  });
215
195
  config.sources.git = {
@@ -230,15 +210,11 @@ configCommand
230
210
  });
231
211
  if (enabled) {
232
212
  const currentPaths = config.sources.filesystem.options.watchPaths || [];
233
- const pathsInput = await input({
234
- message: 'Paths to monitor (comma-separated):',
235
- default: currentPaths.join(',') || `${homedir()}/Documents`,
236
- });
237
- const watchPaths = parsePaths(pathsInput);
238
- warnMissingPaths(watchPaths);
213
+ const watchPaths = await selectPaths('Select paths to monitor:', FILESYSTEM_PATH_PRESETS, currentPaths);
239
214
  const schedule = await select({
240
215
  message: 'Collection schedule:',
241
216
  choices: SCHEDULE_CHOICES,
217
+ loop: false,
242
218
  default: config.sources.filesystem.schedule,
243
219
  });
244
220
  config.sources.filesystem = {
@@ -265,6 +241,7 @@ configCommand
265
241
  const schedule = await select({
266
242
  message: 'Collection schedule:',
267
243
  choices: SCHEDULE_CHOICES,
244
+ loop: false,
268
245
  default: config.sources.chatbot.schedule,
269
246
  });
270
247
  config.sources.chatbot = {
@@ -284,6 +261,7 @@ configCommand
284
261
  if (choice === 'logging') {
285
262
  const level = await select({
286
263
  message: 'Log level:',
264
+ loop: false,
287
265
  choices: [
288
266
  { name: 'Debug (verbose)', value: 'debug' },
289
267
  { name: 'Info (default)', value: 'info' },
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoHpC,eAAO,MAAM,aAAa,SAiDtB,CAAC"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoHpC,eAAO,MAAM,aAAa,SA+CtB,CAAC"}
@@ -107,7 +107,6 @@ export const doctorCommand = new Command('doctor')
107
107
  const globalOpts = cmd.optsWithGlobals();
108
108
  const customPath = globalOpts.config;
109
109
  console.log('Running diagnostics...\n');
110
- // Synchronous checks
111
110
  const syncChecks = [
112
111
  { name: 'Node.js version', result: checkNodeVersion() },
113
112
  { name: 'Configuration file', result: checkConfigExists(customPath) },
@@ -128,7 +127,6 @@ export const doctorCommand = new Command('doctor')
128
127
  hasIssues = true;
129
128
  }
130
129
  }
131
- // Async check for API
132
130
  const apiResult = await checkApiConnection(customPath);
133
131
  if (apiResult.ok) {
134
132
  printSuccess(`API connectivity: ${apiResult.message}`);
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,eAAO,MAAM,WAAW,SA+OpB,CAAC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,eAAO,MAAM,WAAW,SAqNpB,CAAC"}
@@ -1,20 +1,18 @@
1
1
  import { Command } from 'commander';
2
2
  import { existsSync } from 'node:fs';
3
- import { homedir } from 'node:os';
4
- import { input, confirm, select, checkbox } from '@inquirer/prompts';
3
+ import { confirm, select, checkbox } from '@inquirer/prompts';
5
4
  import { detectInstalledBrowsers, detectGitInstalled, detectChatbotClients } from '../detect/index.js';
6
5
  import { writeConfig } from '../../config/writer.js';
7
6
  import { getUserConfigPath } from '../../config/paths.js';
8
7
  import { printBanner, printSection, printSuccess, printInfo, printDim, printWarning } from '../utils/output.js';
9
- import { parsePaths } from '../utils/path.js';
10
- import { warnMissingPaths, showMaskedKey, SCHEDULE_CHOICES_WITH_HINT } from '../utils/prompts.js';
8
+ import { SCHEDULE_CHOICES_WITH_HINT, GIT_PATH_PRESETS, FILESYSTEM_PATH_PRESETS, selectPaths, } from '../utils/prompts.js';
9
+ import { inputApiUrl, inputApiKey } from '../utils/api.js';
11
10
  export const initCommand = new Command('init')
12
11
  .description('Initialize configuration with interactive wizard')
13
12
  .option('--force', 'overwrite existing configuration')
14
13
  .action(async (options, cmd) => {
15
14
  const globalOpts = cmd.optsWithGlobals();
16
15
  const configPath = globalOpts.config || getUserConfigPath();
17
- // Check if config already exists
18
16
  if (existsSync(configPath) && !options.force) {
19
17
  printInfo(`Configuration already exists at ${configPath}`);
20
18
  const overwrite = await confirm({
@@ -48,24 +46,8 @@ export const initCommand = new Command('init')
48
46
  };
49
47
  // Step 1: API Configuration
50
48
  printSection('Step 1/5: API Configuration');
51
- config.api.baseUrl = await input({
52
- message: 'API Base URL:',
53
- default: 'http://localhost:3000',
54
- validate: (value) => {
55
- try {
56
- new URL(value);
57
- return true;
58
- }
59
- catch {
60
- return 'Please enter a valid URL';
61
- }
62
- },
63
- });
64
- config.api.apiKey = await input({
65
- message: 'API Key:',
66
- validate: (value) => (value.length > 0 ? true : 'API Key is required'),
67
- });
68
- showMaskedKey(config.api.apiKey);
49
+ config.api.baseUrl = await inputApiUrl();
50
+ config.api.apiKey = await inputApiKey();
69
51
  // Step 2: Browser History
70
52
  printSection('Step 2/5: Browser History');
71
53
  const detectedBrowsers = detectInstalledBrowsers();
@@ -82,6 +64,7 @@ export const initCommand = new Command('init')
82
64
  if (enableBrowser) {
83
65
  const selectedBrowsers = await checkbox({
84
66
  message: 'Select browsers to collect:',
67
+ loop: false,
85
68
  choices: [
86
69
  { name: 'Chrome', value: 'chrome', checked: detectedBrowsers.includes('chrome') },
87
70
  { name: 'Safari', value: 'safari', checked: detectedBrowsers.includes('safari') },
@@ -90,7 +73,6 @@ export const initCommand = new Command('init')
90
73
  { name: 'Comet', value: 'comet', checked: detectedBrowsers.includes('comet') },
91
74
  ],
92
75
  });
93
- // If no browsers selected, disable the source
94
76
  if (selectedBrowsers.length === 0) {
95
77
  printWarning('No browsers selected, browser collection will be disabled.');
96
78
  }
@@ -98,6 +80,7 @@ export const initCommand = new Command('init')
98
80
  const browserSchedule = await select({
99
81
  message: 'Collection schedule:',
100
82
  choices: SCHEDULE_CHOICES_WITH_HINT,
83
+ loop: false,
101
84
  default: 'daily',
102
85
  });
103
86
  config.sources.browser = {
@@ -120,20 +103,15 @@ export const initCommand = new Command('init')
120
103
  default: true,
121
104
  });
122
105
  if (enableGit) {
123
- const defaultPaths = [`${homedir()}/Projects`, `${homedir()}/Documents`].filter(existsSync);
124
- const scanPathsInput = await input({
125
- message: 'Paths to scan for git repositories (comma-separated):',
126
- default: defaultPaths.join(',') || `${homedir()}/Projects`,
127
- });
128
- const scanPaths = parsePaths(scanPathsInput);
106
+ const scanPaths = await selectPaths('Select paths to scan for git repositories:', GIT_PATH_PRESETS);
129
107
  if (scanPaths.length === 0) {
130
- printWarning('No paths specified, git collection will be disabled.');
108
+ printWarning('No paths selected, git collection will be disabled.');
131
109
  }
132
110
  else {
133
- warnMissingPaths(scanPaths);
134
111
  const gitSchedule = await select({
135
112
  message: 'Collection schedule:',
136
113
  choices: SCHEDULE_CHOICES_WITH_HINT,
114
+ loop: false,
137
115
  default: 'daily',
138
116
  });
139
117
  config.sources.git = {
@@ -146,26 +124,27 @@ export const initCommand = new Command('init')
146
124
  };
147
125
  }
148
126
  }
149
- // Step 4: Filesystem (Optional)
127
+ // Step 4: Filesystem
150
128
  printSection('Step 4/5: Filesystem Changes');
151
129
  const enableFilesystem = await confirm({
152
130
  message: 'Enable filesystem monitoring?',
153
131
  default: true,
154
132
  });
155
133
  if (enableFilesystem) {
156
- const watchPathsInput = await input({
157
- message: 'Paths to monitor (comma-separated):',
158
- default: `${homedir()}/Documents,${homedir()}/Desktop`,
159
- });
160
- const watchPaths = parsePaths(watchPathsInput);
134
+ const watchPaths = await selectPaths('Select paths to monitor:', FILESYSTEM_PATH_PRESETS);
161
135
  if (watchPaths.length === 0) {
162
- printWarning('No paths specified, filesystem monitoring will be disabled.');
136
+ printWarning('No paths selected, filesystem monitoring will be disabled.');
163
137
  }
164
138
  else {
165
- warnMissingPaths(watchPaths);
139
+ const fsSchedule = await select({
140
+ message: 'Collection schedule:',
141
+ choices: SCHEDULE_CHOICES_WITH_HINT,
142
+ loop: false,
143
+ default: 'daily',
144
+ });
166
145
  config.sources.filesystem = {
167
146
  enabled: true,
168
- schedule: 'daily',
147
+ schedule: fsSchedule,
169
148
  options: {
170
149
  watchPaths,
171
150
  excludePatterns: ['**/node_modules/**', '**/.git/**', '**/Library/**'],
@@ -175,7 +154,7 @@ export const initCommand = new Command('init')
175
154
  };
176
155
  }
177
156
  }
178
- // Step 5: Chatbot (Optional)
157
+ // Step 5: Chatbot
179
158
  printSection('Step 5/5: Chatbot History');
180
159
  const detectedChatbots = detectChatbotClients();
181
160
  if (detectedChatbots.length > 0) {
@@ -199,7 +178,6 @@ export const initCommand = new Command('init')
199
178
  },
200
179
  };
201
180
  }
202
- // Summary
203
181
  printSection('Configuration Summary');
204
182
  console.log(` API: ${config.api.baseUrl}`);
205
183
  console.log(' Sources enabled:');
@@ -207,7 +185,6 @@ export const initCommand = new Command('init')
207
185
  console.log(` ${config.sources.git.enabled ? '✓' : '✗'} Git`);
208
186
  console.log(` ${config.sources.filesystem.enabled ? '✓' : '✗'} Filesystem`);
209
187
  console.log(` ${config.sources.chatbot.enabled ? '✓' : '✗'} Chatbot`);
210
- // Save
211
188
  const shouldSave = await confirm({
212
189
  message: `Save configuration to ${configPath}?`,
213
190
  default: true,
@@ -1 +1 @@
1
- {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,YAAY,SA8DrB,CAAC"}
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,YAAY,SA6DrB,CAAC"}
@@ -12,7 +12,6 @@ export const startCommand = new Command('start')
12
12
  const globalOpts = cmd.optsWithGlobals();
13
13
  try {
14
14
  const config = loadConfig(globalOpts.config);
15
- // Apply global log level overrides
16
15
  let logLevel = config.logging.level;
17
16
  if (globalOpts.verbose)
18
17
  logLevel = 'debug';
package/dist/cli/index.js CHANGED
@@ -9,7 +9,6 @@ import { collectCommand } from './commands/collect.js';
9
9
  import { configCommand } from './commands/config.js';
10
10
  import { statusCommand } from './commands/status.js';
11
11
  import { doctorCommand } from './commands/doctor.js';
12
- // Read version from package.json
13
12
  const __dirname = dirname(fileURLToPath(import.meta.url));
14
13
  const packagePath = join(__dirname, '../../package.json');
15
14
  const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Input API URL with validation
3
+ */
4
+ export declare function inputApiUrl(defaultUrl?: string): Promise<string>;
5
+ /**
6
+ * Input API Key with masked confirmation
7
+ */
8
+ export declare function inputApiKey(): Promise<string>;
9
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/api.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,WAAW,CAAC,UAAU,SAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAavF;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAOnD"}
@@ -0,0 +1,31 @@
1
+ import { input } from '@inquirer/prompts';
2
+ import { showMaskedKey } from './prompts.js';
3
+ /**
4
+ * Input API URL with validation
5
+ */
6
+ export async function inputApiUrl(defaultUrl = 'http://localhost:3000') {
7
+ return input({
8
+ message: 'API Base URL:',
9
+ default: defaultUrl,
10
+ validate: (value) => {
11
+ try {
12
+ new URL(value);
13
+ return true;
14
+ }
15
+ catch {
16
+ return 'Please enter a valid URL';
17
+ }
18
+ },
19
+ });
20
+ }
21
+ /**
22
+ * Input API Key with masked confirmation
23
+ */
24
+ export async function inputApiKey() {
25
+ const apiKey = await input({
26
+ message: 'API Key:',
27
+ validate: (value) => (value.length > 0 ? true : 'API Key is required'),
28
+ });
29
+ showMaskedKey(apiKey);
30
+ return apiKey;
31
+ }
@@ -2,10 +2,6 @@
2
2
  * Mask an API key for display (show first 8 and last 4 chars)
3
3
  */
4
4
  export declare function maskApiKey(key: string): string;
5
- /**
6
- * Warn about paths that don't exist
7
- */
8
- export declare function warnMissingPaths(paths: string[]): void;
9
5
  /**
10
6
  * Show masked API key confirmation
11
7
  */
@@ -45,4 +41,23 @@ export declare const SCHEDULE_CHOICES_WITH_HINT: ({
45
41
  name: string;
46
42
  value: "manual";
47
43
  })[];
44
+ /** Preset paths for Git repository scanning */
45
+ export declare const GIT_PATH_PRESETS: {
46
+ path: string;
47
+ defaultChecked: boolean;
48
+ }[];
49
+ /** Preset paths for Filesystem monitoring */
50
+ export declare const FILESYSTEM_PATH_PRESETS: {
51
+ path: string;
52
+ defaultChecked: boolean;
53
+ }[];
54
+ interface PathPreset {
55
+ path: string;
56
+ defaultChecked: boolean;
57
+ }
58
+ /**
59
+ * Interactive path selector with presets and custom path support
60
+ */
61
+ export declare function selectPaths(message: string, presets: PathPreset[], currentPaths?: string[]): Promise<string[]>;
62
+ export {};
48
63
  //# sourceMappingURL=prompts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prompts.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAMtD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;IAM5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;IAKtC,CAAC"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/prompts.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;IAM5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;IAKtC,CAAC;AAIF,+CAA+C;AAC/C,eAAO,MAAM,gBAAgB;;;GAI5B,CAAC;AAEF,6CAA6C;AAC7C,eAAO,MAAM,uBAAuB;;;GAInC,CAAC;AAIF,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,UAAU,EAAE,EACrB,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,OAAO,CAAC,MAAM,EAAE,CAAC,CAyCnB"}
@@ -1,22 +1,14 @@
1
1
  import { existsSync } from 'node:fs';
2
- import { printWarning, printDim } from './output.js';
3
- import { expandPath } from './path.js';
2
+ import { homedir } from 'node:os';
3
+ import { checkbox, input } from '@inquirer/prompts';
4
+ import { printDim } from './output.js';
5
+ import { expandPath } from '../../utils/path.js';
4
6
  /**
5
7
  * Mask an API key for display (show first 8 and last 4 chars)
6
8
  */
7
9
  export function maskApiKey(key) {
8
10
  return key.length > 12 ? key.slice(0, 8) + '***...' + key.slice(-4) : '***';
9
11
  }
10
- /**
11
- * Warn about paths that don't exist
12
- */
13
- export function warnMissingPaths(paths) {
14
- for (const p of paths) {
15
- if (!existsSync(expandPath(p))) {
16
- printWarning(`Path does not exist: ${p}`);
17
- }
18
- }
19
- }
20
12
  /**
21
13
  * Show masked API key confirmation
22
14
  */
@@ -42,3 +34,58 @@ export const SCHEDULE_CHOICES_WITH_HINT = [
42
34
  { name: 'Weekly', value: 'weekly' },
43
35
  { name: 'Manual only', value: 'manual' },
44
36
  ];
37
+ const home = homedir();
38
+ /** Preset paths for Git repository scanning */
39
+ export const GIT_PATH_PRESETS = [
40
+ { path: `${home}/Documents`, defaultChecked: true },
41
+ { path: `${home}/Desktop`, defaultChecked: false },
42
+ { path: `${home}/Developer`, defaultChecked: false },
43
+ ];
44
+ /** Preset paths for Filesystem monitoring */
45
+ export const FILESYSTEM_PATH_PRESETS = [
46
+ { path: `${home}/Documents`, defaultChecked: true },
47
+ { path: `${home}/Desktop`, defaultChecked: true },
48
+ { path: `${home}/Downloads`, defaultChecked: true },
49
+ ];
50
+ const ADD_CUSTOM_PATH = '__add_custom__';
51
+ /**
52
+ * Interactive path selector with presets and custom path support
53
+ */
54
+ export async function selectPaths(message, presets, currentPaths) {
55
+ const existingPresets = presets.filter((p) => existsSync(p.path));
56
+ const choices = existingPresets.map((preset) => {
57
+ const isChecked = currentPaths ? currentPaths.includes(preset.path) : preset.defaultChecked;
58
+ return {
59
+ name: preset.path.replace(home, '~'),
60
+ value: preset.path,
61
+ checked: isChecked,
62
+ };
63
+ });
64
+ choices.push({
65
+ name: '── Add custom path...',
66
+ value: ADD_CUSTOM_PATH,
67
+ checked: false,
68
+ });
69
+ const selected = await checkbox({
70
+ message,
71
+ choices,
72
+ loop: false,
73
+ });
74
+ if (selected.includes(ADD_CUSTOM_PATH)) {
75
+ const filtered = selected.filter((p) => p !== ADD_CUSTOM_PATH);
76
+ const customPath = await input({
77
+ message: 'Enter custom path:',
78
+ validate: (value) => {
79
+ if (!value.trim())
80
+ return 'Path cannot be empty';
81
+ const expanded = expandPath(value.trim());
82
+ if (!existsSync(expanded)) {
83
+ return `Path does not exist: ${value}`;
84
+ }
85
+ return true;
86
+ },
87
+ });
88
+ return [...filtered, expandPath(customPath.trim())];
89
+ }
90
+ return selected;
91
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "liferewind",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "AI-powered personal life review tool - collect your digital footprints from git, browser history, documents, and AI chatbots",
5
5
  "keywords": [
6
6
  "cli",
@@ -1,9 +0,0 @@
1
- /**
2
- * Expand a path that may start with ~ or ~/ to an absolute path.
3
- */
4
- export declare function expandPath(path: string): string;
5
- /**
6
- * Parse comma-separated paths and trim whitespace
7
- */
8
- export declare function parsePaths(input: string): string[];
9
- //# sourceMappingURL=path.d.ts.map
@@ -1,23 +0,0 @@
1
- import { homedir } from 'node:os';
2
- import { resolve } from 'node:path';
3
- /**
4
- * Expand a path that may start with ~ or ~/ to an absolute path.
5
- */
6
- export function expandPath(path) {
7
- if (path === '~') {
8
- return homedir();
9
- }
10
- if (path.startsWith('~/')) {
11
- return resolve(homedir(), path.slice(2));
12
- }
13
- return resolve(path);
14
- }
15
- /**
16
- * Parse comma-separated paths and trim whitespace
17
- */
18
- export function parsePaths(input) {
19
- return input
20
- .split(',')
21
- .map((p) => p.trim())
22
- .filter(Boolean);
23
- }