klio 1.4.9 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/cli/cli.js CHANGED
@@ -1,13 +1,11 @@
1
1
  const { Command } = require('commander');
2
2
  const { planets, signs } = require('../astrology/astrologyConstants');
3
3
  const { showRetrogradePlanets } = require('../astrology/retrogradeService');
4
- const { getCurrentTimeInTimezone, showAspectFigures, analyzeElementDistribution, getTimezoneOffset, calculateJulianDayUTC, calculateHouses, getAstrologicalData, getPlanetHouse, showPlanetAspects, calculatePlanetAspects, getAllActiveAspects, showAllActiveAspects, getBirthDataFromConfig, getPersonDataFromConfig, detectAspectFigures, calculatePersonalTransits, showPersonalTransitAspects, showCombinedAnalysis, calculatePersonalTransitAspects, determineAspectPhase, findExactAspectTime, findLastExactAspectTime, getAspectAngle, getFutureAspects, getPastAspects, analyzeCSVWithDatetime, analyzeHouseDistributionSignificance, analyzeAspectDistributionSignificance, analyzeSignDistributionSignificance, calculateAspectStatistics, calculatePlanetComboAspects, showPlanetComboAspects, getCriticalPlanets, getHouseSystemCode, calculateNextPlanetIngress, calculateAstrologicalAngles, longitudeToSignDegree, calculateTransitFrequency } = require('../astrology/astrologyService');
4
+ const { getCurrentTimeInTimezone, showAspectFigures, analyzeElementDistribution, getTimezoneOffset, calculateJulianDayUTC, calculateHouses, getAstrologicalData, getPlanetHouse, showPlanetAspects, calculatePlanetAspects, getAllActiveAspects, showAllActiveAspects, getBirthDataFromConfig, getPersonDataFromConfig, detectAspectFigures, calculatePersonalTransits, showPersonalTransitAspects, showCombinedAnalysis, calculatePersonalTransitAspects, determineAspectPhase, getAspectAngle, getFutureAspects, getPastAspects, analyzeCSVWithDatetime, analyzeHouseDistributionSignificance, analyzeAspectDistributionSignificance, analyzeSignDistributionSignificance, calculateAspectStatistics, calculatePlanetComboAspects, showPlanetComboAspects, getCriticalPlanets, getHouseSystemCode, calculateNextPlanetIngress, calculateAstrologicalAngles, longitudeToSignDegree, calculateTransitFrequency } = require('../astrology/astrologyService');
5
5
  const { performSetup, showConfigStatus, loadConfig, setAIModel, askAIModel, setPerson1, setPerson2, setPerson, getPersonData, listPeople, deletePerson } = require('../config/configService');
6
6
  const { parseAppleHealthXML } = require('../health/healthService');
7
7
  const { analyzeStepsByPlanetSign, analyzeStressByPlanetAspects, analyzePlanetAspectsForSleep, analyzeLateNightAspects, analyzeAllNighterAspects } = require('../health/healthAnalysis');
8
- const { analyzeHouseDistribution, filterFilesByHouse } = require('../health/fileAnalysis');
9
8
  const { getFileCreationDate, parseDateToComponents } = require('../utils/fileUtils');
10
- const swisseph = require('swisseph');
11
9
  const path = require('path');
12
10
  const fs = require('fs');
13
11
 
@@ -43,7 +41,7 @@ const program = new Command();
43
41
 
44
42
  // Helper function to check if person data should be used (including new options)
45
43
  const shouldUsePersonData = (options) => {
46
- return options.ich || options.i || options.p1 || options.p2 || options.withPerson || options.wp || options.up;
44
+ return options.i || options.p1 || options.p2 || options.withPerson || options.wp || options.up;
47
45
  };
48
46
 
49
47
  // Universal AI handler function that works with any command
@@ -150,7 +148,7 @@ const getPersonDataToUse = (options) => {
150
148
  return { source: 'p5', data: getPersonDataFromConfig('p5') };
151
149
  } else if (options.p6) {
152
150
  return { source: 'p6', data: getPersonDataFromConfig('p6') };
153
- } else if (options.ich || options.i) {
151
+ } else if (options.i) {
154
152
  return { source: 'birth', data: getPersonDataFromConfig('birth') };
155
153
  }
156
154
  return { source: null, data: null };
@@ -158,7 +156,7 @@ const getPersonDataToUse = (options) => {
158
156
 
159
157
  // Helper function to check if birth data should be used (for backward compatibility only)
160
158
  const shouldUseBirthData = (options) => {
161
- return options.ich || options.i;
159
+ return options.i;
162
160
  };
163
161
 
164
162
  // Function to calculate the Julian Day in UTC
@@ -224,19 +222,6 @@ program
224
222
  .option('--a', 'Shows all aspects of the planet')
225
223
  .option('--k', 'Shows aspects between any planet combinations')
226
224
  .option('--s', 'Shows all planet positions in a table with signs, degrees and houses')
227
- .option('--folder <path>', 'Analyzes house distribution of all files in the folder')
228
- .option('--h1', 'Filters files with planet in house 1')
229
- .option('--h2', 'Filters files with planet in house 2')
230
- .option('--h3', 'Filters files with planet in house 3')
231
- .option('--h4', 'Filters files with planet in house 4')
232
- .option('--h5', 'Filters files with planet in house 5')
233
- .option('--h6', 'Filters files with planet in house 6')
234
- .option('--h7', 'Filters files with planet in house 7')
235
- .option('--h8', 'Filters files with planet in house 8')
236
- .option('--h9', 'Filters files with planet in house 9')
237
- .option('--h10', 'Filters files with planet in house 10')
238
- .option('--h11', 'Filters files with planet in house 11')
239
- .option('--h12', 'Filters files with planet in house 12')
240
225
  .option('--apple <filepath>', 'Analyzes Apple Health Export XML file')
241
226
  .option('--hypothesis <type>', 'Specifies the hypothesis to test (e.g. "sleep-moon", "steps-moon", "stress-moon")')
242
227
  .option('--sleep', 'Analyzes sleep patterns with moon aspects')
@@ -250,7 +235,6 @@ program
250
235
  .option('--rx', 'Shows all retrograde or stationary planets')
251
236
  .option('--c', 'Shows all planets on critical degrees')
252
237
  .option('--status', 'Shows the stored configuration data')
253
- .option('--ich', 'Uses the birth data from setup for calculations')
254
238
  .option('--i', 'Uses the birth data from setup for calculations (short form)')
255
239
  .option('--p1', 'Uses the data from person 1 for calculations')
256
240
  .option('--p2', 'Uses the data from person 2 for calculations')
@@ -270,7 +254,6 @@ program
270
254
  .option('--el', 'Shows the element distribution of planets in a horizontal chart')
271
255
  .option('--af', 'Shows active aspect figures like T-squares, Grand Trines, etc.')
272
256
  .option('--tra', 'Shows personal transits based on birth data')
273
- .option('--transit-aspekte', 'Shows personal transit aspects (Transit → Radix)')
274
257
  .option('--tr', 'Shows personal transit aspects (Transit → Radix) (short form)')
275
258
  .option('--v <count>', 'Shows past aspects between two planets (Format: --v <count> planet1 aspectType planet2)')
276
259
  .option('--z <count>', 'Shows future aspects between two planets (Format: --z <count> planet1 aspectType planet2)')
@@ -281,6 +264,7 @@ program
281
264
  .option('--wiki <occupation>', 'Fetches people from Wikidata by occupation and checks for specific aspects (Format: planet1 aspectType planet2 --wiki <occupation> [limit])')
282
265
  .option('--gui', 'Launches the web interface for command history (port 37421)')
283
266
  .option('--gui-port <port>', 'Specify custom port for GUI server')
267
+ .option('--gui-verbose', 'Enable verbose logging for GUI server')
284
268
  .option('--o', 'Shows how often this transit occurs in the sky (frequency calculation)')
285
269
  .description('Shows astrological data for a planet')
286
270
  .action(async (planetArg, planet2Arg, options) => {
@@ -292,19 +276,18 @@ program
292
276
  if (options.gui) {
293
277
  if (!guiServer) {
294
278
  console.error('❌ GUI server is not available. Please install required dependencies.');
295
- console.error('💡 Run: npm install express sqlite3');
296
279
  process.exit(1);
297
280
  }
298
281
 
299
282
  try {
283
+ // Set verbose logging based on --gui-verbose flag
284
+ guiServer.enableVerboseLogging(!!options.guiVerbose);
285
+
300
286
  await guiServer.initialize();
301
287
  const port = options.guiPort ? parseInt(options.guiPort) : 37421;
302
288
  await guiServer.start(port);
303
289
 
304
- console.log(`\n🌐 GUI Server started successfully!`);
305
- console.log(`📊 Open your browser and navigate to: http://localhost:${guiServer.getPort()}`);
306
- console.log(`💡 Press Ctrl+C to stop the server and return to CLI`);
307
-
290
+ // Server start messages are now handled by the server itself
308
291
  // Keep the process running
309
292
  await new Promise(() => {});
310
293
  return;
@@ -316,7 +299,7 @@ program
316
299
 
317
300
  // Show critical planets if --c option is specified (no planet required)
318
301
  if (actualOptions.c) {
319
- // Use person data if --p1, --p2 or --ich option is specified
302
+ // Use person data if --p1, --p2 or --i option is specified
320
303
  let customDate = null;
321
304
  let personSource = null;
322
305
  const personDataToUse = getPersonDataToUse(options);
@@ -341,6 +324,54 @@ program
341
324
  }
342
325
  }
343
326
 
327
+ // Use custom date if specified (overrides person data)
328
+ if (options.d) {
329
+ // Try to parse the date as DD.MM.YYYY or DD.MM.YYYY HH:MM
330
+ const dateRegex = /^(\d{1,2})\.(\d{1,2})\.(\d{4})(?:\s+(\d{1,2}):(\d{2}))?$/;
331
+ const match = options.d.match(dateRegex);
332
+
333
+ if (match) {
334
+ const day = parseInt(match[1], 10);
335
+ const month = parseInt(match[2], 10);
336
+ const year = parseInt(match[3], 10);
337
+ const hour = match[4] ? parseInt(match[4], 10) : 12; // Default: 12 o'clock
338
+ const minute = match[5] ? parseInt(match[5], 10) : 0; // Default: 0 minutes
339
+
340
+ // Check if the date is valid
341
+ const date = new Date(year, month - 1, day, hour, minute);
342
+ if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) {
343
+ customDate = {
344
+ day: day,
345
+ month: month,
346
+ year: year,
347
+ hour: hour,
348
+ minute: minute
349
+ };
350
+ console.log(`Using custom date: ${day}.${month}.${year} ${hour}:${minute.toString().padStart(2, '0')}`);
351
+ } else {
352
+ console.error('Invalid date:', options.d);
353
+ console.error('💡 Please use the format: DD.MM.YYYY or "DD.MM.YYYY HH:MM" (with quotes for date with time)');
354
+ process.exit(1);
355
+ }
356
+ } else {
357
+ console.error('Invalid date:', options.d);
358
+ console.error('💡 Please use the format: DD.MM.YYYY or "DD.MM.YYYY HH:MM" (with quotes for date with time)');
359
+ process.exit(1);
360
+ }
361
+ }
362
+
363
+ // If no custom date is specified, use current date
364
+ if (!customDate) {
365
+ const currentTime = getCurrentTimeInTimezone();
366
+ customDate = {
367
+ day: currentTime.day,
368
+ month: currentTime.month,
369
+ year: currentTime.year,
370
+ hour: currentTime.hour,
371
+ minute: currentTime.minute
372
+ };
373
+ }
374
+
344
375
  const criticalPlanets = getCriticalPlanets(customDate);
345
376
 
346
377
  if (criticalPlanets.length === 0) {
@@ -348,18 +379,20 @@ program
348
379
  return;
349
380
  }
350
381
 
351
- console.log('========================================================');
352
- console.log('| Planet | Sign | Degree | Type |');
353
- console.log('========================================================');
382
+ console.log('================================================================================================================');
383
+ console.log('| Planet | Sign | Degree | Type | Interpretation |');
384
+ console.log('================================================================================================================');
354
385
 
355
386
  criticalPlanets.forEach(planet => {
356
387
  const planetName = planet.name.charAt(0).toUpperCase() + planet.name.slice(1);
357
388
  const sign = planet.sign.padEnd(10, ' ');
358
389
  const degree = planet.degree.padEnd(5, ' ');
359
- console.log(`| ${planetName.padEnd(8)} | ${sign} | ${degree} | ${planet.criticalType} |`);
390
+ const criticalType = planet.criticalType.padEnd(20, ' ');
391
+ const interpretation = planet.interpretation.padEnd(46, ' ');
392
+ console.log(`| ${planetName.padEnd(8)} | ${sign} | ${degree} | ${criticalType} | ${interpretation} |`);
360
393
  });
361
394
 
362
- console.log('========================================================');
395
+ console.log('================================================================================================================');
363
396
  if (shouldUseBirthData(options)) {
364
397
  console.log('\nThis analysis is based on your birth chart.');
365
398
  } else {
@@ -426,7 +459,7 @@ program
426
459
 
427
460
  // Show element distribution if --el option is specified (no planet required)
428
461
  if (options.el) {
429
- // Use person data if --p1, --p2 or --ich option is specified
462
+ // Use person data if --p1, --p2 or --i option is specified
430
463
  let customDate = null;
431
464
  let useBirthData = false;
432
465
  let personSource = null;
@@ -452,7 +485,7 @@ program
452
485
  console.log(`Location: ${customDate.location.name}, ${customDate.location.country}`);
453
486
  }
454
487
  }
455
- // Use custom date if specified (overrides --p1, --p2 and --ich options)
488
+ // Use custom date if specified (overrides --p1, --p2 and --i options)
456
489
  if (options.d) {
457
490
  // Try to parse the date as DD.MM.YYYY or DD.MM.YYYY HH:MM
458
491
  const dateRegex = /^(\d{1,2})\.(\d{1,2})\.(\d{4})(?:\s+(\d{1,2}):(\d{2}))?$/;
@@ -500,7 +533,7 @@ program
500
533
  };
501
534
  }
502
535
 
503
- // Check if we should use natal positions (when --i or --ich is used without custom date)
536
+ // Check if we should use natal positions (when --i is used without custom date)
504
537
  if (shouldUseBirthData(options) && !options.d) {
505
538
  useNatalPositions = true;
506
539
  // customDate is already set to birth data from personDataToUse
@@ -639,9 +672,9 @@ program
639
672
  return;
640
673
  }
641
674
 
642
- // Show combined analysis ONLY when --tr/--transit-aspekte is used together with --hs
675
+ // Show combined analysis ONLY when --tr is used together with --hs
643
676
  // This ensures that `--tr` without `--hs` shows only personal transit aspects
644
- if ((options.transitAspekte || options.tr) && options.hs) {
677
+ if (options.tr && options.hs) {
645
678
 
646
679
  // Person data is required
647
680
  const personDataToUse = getPersonDataToUse(options);
@@ -699,7 +732,7 @@ program
699
732
  // If no planet is specified, show ONLY the transit aspects table
700
733
  console.log('Transit aspects (Transit → Radix):');
701
734
  console.log('================================================================================');
702
- console.log('| Transit | Aspect | With Planet | Orb | Transit Pos | Transit House | Birth House | Phase | Exact Date/Time |');
735
+ console.log('| Transit | Aspect | With Planet | Orb | Transit Pos | Transit House | Birth House | Phase |');
703
736
  console.log('================================================================================');
704
737
 
705
738
  // Calculate houses once for all planets
@@ -729,18 +762,8 @@ program
729
762
  const targetAngle = aspectAngles[aspect.type];
730
763
  const phase = determineAspectPhase(planetName, aspect.birthPlanet, transitDateDisplay, aspect.type, targetAngle);
731
764
 
732
- // Calculate exact date and time for this aspect
733
- const exactDateTime = findExactAspectTime(planetName, aspect.birthPlanet, aspect.type, transitDateDisplay);
734
- let dateTimeStr = '-';
735
- if (exactDateTime) {
736
- dateTimeStr = `${String(exactDateTime.day).padStart(2, '0')}.${String(exactDateTime.month).padStart(2, '0')}.${exactDateTime.year} ${String(exactDateTime.hour).padStart(2, '0')}:${String(exactDateTime.minute).padStart(2, '0')}`;
737
- } else if (phase === 'separativ') {
738
- // For separative phases: find the last exact date in the past
739
- const lastExactDateTime = findLastExactAspectTime(planetName, aspect.birthPlanet, aspect.type, transitDateDisplay);
740
- if (lastExactDateTime) {
741
- dateTimeStr = `${String(lastExactDateTime.day).padStart(2, '0')}.${String(lastExactDateTime.month).padStart(2, '0')}.${lastExactDateTime.year} ${String(lastExactDateTime.hour).padStart(2, '0')}:${String(lastExactDateTime.minute).padStart(2, '0')} (e)`;
742
- }
743
- }
765
+ // Exact time calculation removed
766
+ const dateTimeStr = '-';
744
767
 
745
768
  const transitPlanetFormatted = planetName.charAt(0).toUpperCase() + planetName.slice(1);
746
769
  const aspectTypeFormatted = aspect.type.padEnd(11);
@@ -752,7 +775,7 @@ program
752
775
  const phaseFormatted = phase === 'separativ' ? 'separativ'.padEnd(11) : phase.padEnd(11);
753
776
  const dateTimeFormatted = dateTimeStr.padEnd(22);
754
777
 
755
- console.log(`| ${transitPlanetFormatted.padEnd(10)} | ${aspectTypeFormatted} | ${aspectPlanetFormatted.padEnd(10)} | ${orbFormatted}° | ${transitPosFormatted.padEnd(16)} | ${transitHouseFormatted} | ${birthHouseFormatted} | ${phaseFormatted} | ${dateTimeFormatted} |`);
778
+ console.log(`| ${transitPlanetFormatted.padEnd(10)} | ${aspectTypeFormatted} | ${aspectPlanetFormatted.padEnd(10)} | ${orbFormatted}° | ${transitPosFormatted.padEnd(16)} | ${transitHouseFormatted} | ${birthHouseFormatted} | ${phaseFormatted} |`);
756
779
  });
757
780
  }
758
781
  }
@@ -766,8 +789,8 @@ program
766
789
  return;
767
790
  }
768
791
 
769
- // Show personal transit aspects if --transit-aspekte or --tr option is specified
770
- if (options.transitAspekte || options.tr) {
792
+ // Show personal transit aspects if --tr option is specified
793
+ if (options.tr) {
771
794
  // Person data is required for transit aspects
772
795
  const personDataToUse = getPersonDataToUse(options);
773
796
  if (!personDataToUse.data) {
@@ -845,7 +868,7 @@ program
845
868
 
846
869
  // Show aspect figures if --af option is specified (no planet required)
847
870
  if (options.af) {
848
- // Use person data if --p1, --p2 or --ich option is specified
871
+ // Use person data if --p1, --p2 or --i option is specified
849
872
  let customDate = null;
850
873
  let useBirthData = false;
851
874
  let personSource = null;
@@ -871,7 +894,7 @@ program
871
894
  console.log(`Location: ${customDate.location.name}, ${customDate.location.country}`);
872
895
  }
873
896
  }
874
- // Use custom date if specified (overrides --p1, --p2 and --ich options)
897
+ // Use custom date if specified (overrides --p1, --p2 and --i options)
875
898
  if (options.d) {
876
899
  // Try to parse the date as DD.MM.YYYY or DD.MM.YYYY HH:MM
877
900
  const dateRegex = /^(\d{1,2})\.(\d{1,2})\.(\d{4})(?:\s+(\d{1,2}):(\d{2}))?$/;
@@ -1248,7 +1271,7 @@ program
1248
1271
 
1249
1272
  // Show table view of all planet positions if --s option is specified
1250
1273
  if (options.s) {
1251
- // Use person data for house calculation if --p1, --p2 or --ich option is specified
1274
+ // Use person data for house calculation if --p1, --p2 or --i option is specified
1252
1275
  let customDate = null;
1253
1276
  let birthData = null;
1254
1277
  let houseSystem = options.hs ? options.hs.toLowerCase() : 'koch';
@@ -1327,7 +1350,7 @@ program
1327
1350
  };
1328
1351
  }
1329
1352
 
1330
- // Check if we should use natal positions (when --i or --ich is used without custom date)
1353
+ // Check if we should use natal positions (when --i is used without custom date)
1331
1354
  if (shouldUseBirthData(options) && !options.d) {
1332
1355
  useNatalPositions = true;
1333
1356
  customDate = birthData; // Use birth data for planet positions
@@ -1694,7 +1717,7 @@ program
1694
1717
  const planet = planetArg ? planetArg.toLowerCase() : null;
1695
1718
 
1696
1719
  if (options.a) {
1697
- // Use person data if --p1, --p2 or --ich option is specified
1720
+ // Use person data if --p1, --p2 or --i option is specified
1698
1721
  let customDate = null;
1699
1722
  let useBirthData = false;
1700
1723
  let personSource = null;
@@ -1720,7 +1743,7 @@ program
1720
1743
  console.log(`Location: ${customDate.location.name}, ${customDate.location.country}`);
1721
1744
  }
1722
1745
  }
1723
- // Use custom date if specified (overrides --p1, --p2 and --ich options)
1746
+ // Use custom date if specified (overrides --p1, --p2 and --i options)
1724
1747
  if (options.d) {
1725
1748
  // Try to parse the date as DD.MM.YYYY or DD.MM.YYYY HH:MM
1726
1749
  const dateRegex = /^(\d{1,2})\.(\d{1,2})\.(\d{4})(?:\s+(\d{1,2}):(\d{2}))?$/;
@@ -1828,7 +1851,7 @@ program
1828
1851
  process.exit(1);
1829
1852
  }
1830
1853
 
1831
- // Use person data if --p1, --p2 or --ich option is specified
1854
+ // Use person data if --p1, --p2 or --i option is specified
1832
1855
  let customDate = null;
1833
1856
  let useBirthData = false;
1834
1857
  let personSource = null;
@@ -1854,7 +1877,7 @@ program
1854
1877
  console.log(`Location: ${customDate.location.name}, ${customDate.location.country}`);
1855
1878
  }
1856
1879
  }
1857
- // Use custom date if specified (overrides --p1, --p2 and --ich options)
1880
+ // Use custom date if specified (overrides --p1, --p2 and --i options)
1858
1881
  if (options.d) {
1859
1882
  // Try to parse the date as DD.MM.YYYY or DD.MM.YYYY HH:MM
1860
1883
  const dateRegex = /^(\d{1,2})\.(\d{1,2})\.(\d{4})(?:\s+(\d{1,2}):(\d{2}))?$/;
@@ -2119,57 +2142,7 @@ program
2119
2142
  return;
2120
2143
  }
2121
2144
 
2122
- // Check for house filter options
2123
- const houseOptions = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9', 'h10', 'h11', 'h12'];
2124
- const selectedHouseOption = houseOptions.find(opt => options[opt]);
2125
-
2126
- if (selectedHouseOption && options.folder) {
2127
- const targetHouse = parseInt(selectedHouseOption.substring(1));
2128
- const houseSystem = options.hs ? options.hs.toLowerCase() : 'koch';
2129
- await filterFilesByHouse(planet, options.folder, targetHouse,
2130
- getHouseSystemCode(houseSystem));
2131
-
2132
- // Handle AI request for house filter
2133
- if (options.p) {
2134
- const folderData = {
2135
- planet: planet,
2136
- sign: 'Multiple',
2137
- degreeInSign: 'Multiple',
2138
- dignity: `Folder analysis: Files filtered by ${planet} in house ${targetHouse} (${houseSystem} system)`,
2139
- element: 'Multiple',
2140
- decan: 'Multiple',
2141
- analysisType: 'house-filter',
2142
- targetHouse: targetHouse,
2143
- houseSystem: houseSystem
2144
- };
2145
- await handleAIRequest(options, folderData);
2146
- }
2147
- return;
2148
- }
2149
-
2150
- // Perform folder analysis if --folder option is provided
2151
- if (options.folder) {
2152
- const houseSystem = options.hs ? options.hs.toLowerCase() : 'koch';
2153
- await analyzeHouseDistribution(planet, options.folder, getHouseSystemCode(houseSystem));
2154
-
2155
- // Handle AI request for folder analysis
2156
- if (options.p) {
2157
- const folderData = {
2158
- planet: planet,
2159
- sign: 'Multiple',
2160
- degreeInSign: 'Multiple',
2161
- dignity: `Folder analysis: House distribution for ${planet} (${houseSystem} system)`,
2162
- element: 'Multiple',
2163
- decan: 'Multiple',
2164
- analysisType: 'folder-analysis',
2165
- houseSystem: houseSystem
2166
- };
2167
- await handleAIRequest(options, folderData);
2168
- }
2169
- return;
2170
- }
2171
-
2172
- // Use person data if --p1, --p2, or --ich option is provided
2145
+ // Use person data if --p1, --p2, or --i option is provided
2173
2146
  let customDate = null;
2174
2147
  const personDataToUse = getPersonDataToUse(options);
2175
2148
  if (personDataToUse.data) {
@@ -2193,7 +2166,7 @@ program
2193
2166
  console.log(`Location: ${customDate.location.name}, ${customDate.location.country}`);
2194
2167
  }
2195
2168
  }
2196
- // Use custom date if provided (overrides --p1, --p2, and --ich options)
2169
+ // Use custom date if provided (overrides --p1, --p2, and --i options)
2197
2170
  if (options.d) {
2198
2171
  // Try to parse the date as DD.MM.YYYY or DD.MM.YYYY HH:MM
2199
2172
  const dateRegex = /^(\d{1,2})\.(\d{1,2})\.(\d{4})(?:\s+(\d{1,2}):(\d{2}))?$/;
@@ -2269,7 +2242,7 @@ program
2269
2242
  // Show only house table (without planet info)
2270
2243
  if (options.hl) {
2271
2244
  const julianDay = getJulianDay(null, shouldUsePersonData(options));
2272
- const useBirthLocation = shouldUsePersonData(options); // Use birth location if --p1, --p2 or --ich option is specified
2245
+ const useBirthLocation = shouldUsePersonData(options); // Use birth location if --p1, --p2 or --i option is specified
2273
2246
 
2274
2247
  try {
2275
2248
  let houses;
@@ -2331,33 +2304,45 @@ program
2331
2304
  // Example: "saturn k neptun" for Saturn conjunction Neptune
2332
2305
 
2333
2306
  // Parse planet and aspect information
2334
- const args = process.argv.slice(2); // Skip 'node' and 'script.js'
2307
+ let planet1, aspectType, planet2, count;
2308
+
2309
+ // Check if arguments are already parsed (from CLI service executeCommand)
2310
+ if (options.vPlanet1 && options.vAspectType && options.vPlanet2) {
2311
+ // Arguments already parsed by CLI service
2312
+ planet1 = options.vPlanet1.toLowerCase();
2313
+ aspectType = options.vAspectType.toLowerCase();
2314
+ planet2 = options.vPlanet2.toLowerCase();
2315
+ count = parseInt(options.v);
2316
+ } else {
2317
+ // Parse from process.argv (direct CLI execution)
2318
+ const args = process.argv.slice(2); // Skip 'node' and 'script.js'
2335
2319
 
2336
- // Find position of --v option
2337
- const vIndex = args.findIndex(arg => arg === '--v');
2338
- if (vIndex === -1) {
2339
- console.error('Error: --v option not found');
2340
- process.exit(1);
2341
- }
2320
+ // Find position of --v option
2321
+ const vIndex = args.findIndex(arg => arg === '--v');
2322
+ if (vIndex === -1) {
2323
+ console.error('Error: --v option not found');
2324
+ process.exit(1);
2325
+ }
2342
2326
 
2343
- // The next arguments after --v should be count, planet1, aspectType, planet2
2344
- const count = parseInt(options.v);
2327
+ // The next arguments after --v should be count, planet1, aspectType, planet2
2328
+ count = parseInt(options.v);
2329
+
2330
+ // We need three additional arguments: planet1, aspectType, planet2
2331
+ // The arguments are the next three arguments after --v
2332
+ // Check if we have enough arguments
2333
+ if (args.length < vIndex + 5) {
2334
+ console.error('Error: Past aspects require two planets and an aspect type.');
2335
+ console.error('Format: --v <count> planet1 aspectType planet2');
2336
+ console.error('Example: --v 3 saturn k neptun');
2337
+ console.error('Aspect types: k=conjunction, o=opposition, q=square, t=trine, s=sextile');
2338
+ process.exit(1);
2339
+ }
2345
2340
 
2346
- // We need three additional arguments: planet1, aspectType, planet2
2347
- // The arguments are the next three arguments after --v
2348
- // Check if we have enough arguments
2349
- if (args.length < vIndex + 5) {
2350
- console.error('Error: Past aspects require two planets and an aspect type.');
2351
- console.error('Format: --v <count> planet1 aspectType planet2');
2352
- console.error('Example: --v 3 saturn k neptun');
2353
- console.error('Aspect types: k=conjunction, o=opposition, q=square, t=trine, s=sextile');
2354
- process.exit(1);
2341
+ planet1 = args[vIndex + 2].toLowerCase();
2342
+ aspectType = args[vIndex + 3].toLowerCase();
2343
+ planet2 = args[vIndex + 4].toLowerCase();
2355
2344
  }
2356
2345
 
2357
- const planet1 = args[vIndex + 2].toLowerCase();
2358
- const aspectType = args[vIndex + 3].toLowerCase();
2359
- const planet2 = args[vIndex + 4].toLowerCase();
2360
-
2361
2346
  // Check if planets are valid
2362
2347
  if (!planets[planet1] || !planets[planet2]) {
2363
2348
  console.error('Error: Invalid planets.');
@@ -2420,23 +2405,35 @@ program
2420
2405
  // Example: "saturn k neptun" for Saturn conjunction Neptune
2421
2406
 
2422
2407
  // Parse planet and aspect information
2423
- const args = process.argv.slice(2); // Skip 'node' and 'script.js'
2408
+ let planet1, aspectType, planet2, count;
2409
+
2410
+ // Check if arguments are already parsed (from CLI service executeCommand)
2411
+ if (options.zPlanet1 && options.zAspectType && options.zPlanet2) {
2412
+ // Arguments already parsed by CLI service
2413
+ planet1 = options.zPlanet1.toLowerCase();
2414
+ aspectType = options.zAspectType.toLowerCase();
2415
+ planet2 = options.zPlanet2.toLowerCase();
2416
+ count = parseInt(options.z);
2417
+ } else {
2418
+ // Parse from process.argv (direct CLI execution)
2419
+ const args = process.argv.slice(2); // Skip 'node' and 'script.js'
2424
2420
 
2425
- // Find position of --z option
2426
- const zIndex = args.findIndex(arg => arg === '--z');
2427
- if (zIndex === -1) {
2428
- console.error('Error: --z option not found');
2429
- process.exit(1);
2430
- }
2421
+ // Find position of --z option
2422
+ const zIndex = args.findIndex(arg => arg === '--z');
2423
+ if (zIndex === -1) {
2424
+ console.error('Error: --z option not found');
2425
+ process.exit(1);
2426
+ }
2431
2427
 
2432
- // The next arguments after --z should be count, planet1, aspectType, planet2
2433
- const count = parseInt(options.z);
2428
+ // The next arguments after --z should be count, planet1, aspectType, planet2
2429
+ count = parseInt(options.z);
2434
2430
 
2435
- // We need three additional arguments: planet1, aspectType, planet2
2436
- // The arguments are the next three arguments after --z
2437
- const planet1 = args[zIndex + 2].toLowerCase();
2438
- const aspectType = args[zIndex + 3].toLowerCase();
2439
- const planet2 = args[zIndex + 4].toLowerCase();
2431
+ // We need three additional arguments: planet1, aspectType, planet2
2432
+ // The arguments are the next three arguments after --z
2433
+ planet1 = args[zIndex + 2].toLowerCase();
2434
+ aspectType = args[zIndex + 3].toLowerCase();
2435
+ planet2 = args[zIndex + 4].toLowerCase();
2436
+ }
2440
2437
 
2441
2438
  if (!planet1 || !aspectType || !planet2) {
2442
2439
  console.error('Error: Future aspects require two planets and an aspect type.');
@@ -2715,7 +2712,7 @@ program
2715
2712
 
2716
2713
  // House calculation with planet position
2717
2714
  if (options.hs) {
2718
- // Use person data if --p1, --p2 or --ich option is specified
2715
+ // Use person data if --p1, --p2 or --i option is specified
2719
2716
  let customDate = null;
2720
2717
  let useBirthData = false;
2721
2718
  let personSource = null;
@@ -2801,4 +2798,3 @@ function getAspectTypeFullName(aspectType) {
2801
2798
 
2802
2799
  return aspectNames[aspectType.toLowerCase()] || aspectType;
2803
2800
  }
2804
-