liferewind 0.1.0

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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -0
  3. package/dist/api/client.d.ts +31 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +115 -0
  6. package/dist/cli/commands/collect.d.ts +3 -0
  7. package/dist/cli/commands/collect.d.ts.map +1 -0
  8. package/dist/cli/commands/collect.js +62 -0
  9. package/dist/cli/commands/config.d.ts +3 -0
  10. package/dist/cli/commands/config.d.ts.map +1 -0
  11. package/dist/cli/commands/config.js +112 -0
  12. package/dist/cli/commands/doctor.d.ts +3 -0
  13. package/dist/cli/commands/doctor.d.ts.map +1 -0
  14. package/dist/cli/commands/doctor.js +150 -0
  15. package/dist/cli/commands/init.d.ts +3 -0
  16. package/dist/cli/commands/init.d.ts.map +1 -0
  17. package/dist/cli/commands/init.js +244 -0
  18. package/dist/cli/commands/start.d.ts +3 -0
  19. package/dist/cli/commands/start.d.ts.map +1 -0
  20. package/dist/cli/commands/start.js +59 -0
  21. package/dist/cli/commands/status.d.ts +3 -0
  22. package/dist/cli/commands/status.d.ts.map +1 -0
  23. package/dist/cli/commands/status.js +49 -0
  24. package/dist/cli/detect/browsers.d.ts +3 -0
  25. package/dist/cli/detect/browsers.d.ts.map +1 -0
  26. package/dist/cli/detect/browsers.js +19 -0
  27. package/dist/cli/detect/chatbot.d.ts +3 -0
  28. package/dist/cli/detect/chatbot.d.ts.map +1 -0
  29. package/dist/cli/detect/chatbot.js +15 -0
  30. package/dist/cli/detect/git.d.ts +2 -0
  31. package/dist/cli/detect/git.d.ts.map +1 -0
  32. package/dist/cli/detect/git.js +10 -0
  33. package/dist/cli/detect/index.d.ts +4 -0
  34. package/dist/cli/detect/index.d.ts.map +1 -0
  35. package/dist/cli/detect/index.js +3 -0
  36. package/dist/cli/index.d.ts +3 -0
  37. package/dist/cli/index.d.ts.map +1 -0
  38. package/dist/cli/index.js +30 -0
  39. package/dist/cli/utils/output.d.ts +8 -0
  40. package/dist/cli/utils/output.d.ts.map +1 -0
  41. package/dist/cli/utils/output.js +28 -0
  42. package/dist/cli/utils/path.d.ts +9 -0
  43. package/dist/cli/utils/path.d.ts.map +1 -0
  44. package/dist/cli/utils/path.js +23 -0
  45. package/dist/config/loader.d.ts +7 -0
  46. package/dist/config/loader.d.ts.map +1 -0
  47. package/dist/config/loader.js +64 -0
  48. package/dist/config/paths.d.ts +8 -0
  49. package/dist/config/paths.d.ts.map +1 -0
  50. package/dist/config/paths.js +21 -0
  51. package/dist/config/schema.d.ts +95 -0
  52. package/dist/config/schema.d.ts.map +1 -0
  53. package/dist/config/schema.js +110 -0
  54. package/dist/config/writer.d.ts +3 -0
  55. package/dist/config/writer.d.ts.map +1 -0
  56. package/dist/config/writer.js +19 -0
  57. package/dist/core/collector.d.ts +19 -0
  58. package/dist/core/collector.d.ts.map +1 -0
  59. package/dist/core/collector.js +83 -0
  60. package/dist/core/scheduler.d.ts +12 -0
  61. package/dist/core/scheduler.d.ts.map +1 -0
  62. package/dist/core/scheduler.js +48 -0
  63. package/dist/core/types.d.ts +29 -0
  64. package/dist/core/types.d.ts.map +1 -0
  65. package/dist/core/types.js +2 -0
  66. package/dist/index.d.ts +9 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +7 -0
  69. package/dist/sources/base.d.ts +27 -0
  70. package/dist/sources/base.d.ts.map +1 -0
  71. package/dist/sources/base.js +23 -0
  72. package/dist/sources/browser/index.d.ts +14 -0
  73. package/dist/sources/browser/index.d.ts.map +1 -0
  74. package/dist/sources/browser/index.js +116 -0
  75. package/dist/sources/browser/readers/base.d.ts +28 -0
  76. package/dist/sources/browser/readers/base.d.ts.map +1 -0
  77. package/dist/sources/browser/readers/base.js +110 -0
  78. package/dist/sources/browser/readers/chromium.d.ts +13 -0
  79. package/dist/sources/browser/readers/chromium.d.ts.map +1 -0
  80. package/dist/sources/browser/readers/chromium.js +64 -0
  81. package/dist/sources/browser/readers/safari.d.ts +9 -0
  82. package/dist/sources/browser/readers/safari.d.ts.map +1 -0
  83. package/dist/sources/browser/readers/safari.js +34 -0
  84. package/dist/sources/browser/types.d.ts +35 -0
  85. package/dist/sources/browser/types.d.ts.map +1 -0
  86. package/dist/sources/browser/types.js +1 -0
  87. package/dist/sources/chatbot/index.d.ts +12 -0
  88. package/dist/sources/chatbot/index.d.ts.map +1 -0
  89. package/dist/sources/chatbot/index.js +67 -0
  90. package/dist/sources/chatbot/readers/base.d.ts +25 -0
  91. package/dist/sources/chatbot/readers/base.d.ts.map +1 -0
  92. package/dist/sources/chatbot/readers/base.js +109 -0
  93. package/dist/sources/chatbot/readers/chatwise.d.ts +14 -0
  94. package/dist/sources/chatbot/readers/chatwise.d.ts.map +1 -0
  95. package/dist/sources/chatbot/readers/chatwise.js +117 -0
  96. package/dist/sources/chatbot/types.d.ts +33 -0
  97. package/dist/sources/chatbot/types.d.ts.map +1 -0
  98. package/dist/sources/chatbot/types.js +1 -0
  99. package/dist/sources/filesystem/index.d.ts +10 -0
  100. package/dist/sources/filesystem/index.d.ts.map +1 -0
  101. package/dist/sources/filesystem/index.js +58 -0
  102. package/dist/sources/filesystem/scanner.d.ts +24 -0
  103. package/dist/sources/filesystem/scanner.d.ts.map +1 -0
  104. package/dist/sources/filesystem/scanner.js +264 -0
  105. package/dist/sources/filesystem/types.d.ts +39 -0
  106. package/dist/sources/filesystem/types.d.ts.map +1 -0
  107. package/dist/sources/filesystem/types.js +1 -0
  108. package/dist/sources/git/index.d.ts +16 -0
  109. package/dist/sources/git/index.d.ts.map +1 -0
  110. package/dist/sources/git/index.js +169 -0
  111. package/dist/sources/git/types.d.ts +25 -0
  112. package/dist/sources/git/types.d.ts.map +1 -0
  113. package/dist/sources/git/types.js +1 -0
  114. package/dist/sources/index.d.ts +7 -0
  115. package/dist/sources/index.d.ts.map +1 -0
  116. package/dist/sources/index.js +16 -0
  117. package/dist/sources/registry.d.ts +13 -0
  118. package/dist/sources/registry.d.ts.map +1 -0
  119. package/dist/sources/registry.js +19 -0
  120. package/dist/utils/logger.d.ts +12 -0
  121. package/dist/utils/logger.d.ts.map +1 -0
  122. package/dist/utils/logger.js +34 -0
  123. package/dist/utils/path.d.ts +9 -0
  124. package/dist/utils/path.d.ts.map +1 -0
  125. package/dist/utils/path.js +22 -0
  126. package/dist/utils/retry.d.ts +8 -0
  127. package/dist/utils/retry.d.ts.map +1 -0
  128. package/dist/utils/retry.js +22 -0
  129. package/package.json +81 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/output.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,IAAI,IAAI,CASlC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAGhD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAElD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE9C"}
@@ -0,0 +1,28 @@
1
+ import pc from 'picocolors';
2
+ export function printBanner() {
3
+ console.log(pc.cyan(`
4
+ LifeRewind Collector Setup
5
+
6
+ This wizard will help you configure the collector.
7
+ Press Enter to accept default values.
8
+ `));
9
+ }
10
+ export function printSection(title) {
11
+ console.log(`\n${pc.bold(pc.blue(title))}`);
12
+ console.log(pc.dim('─'.repeat(45)));
13
+ }
14
+ export function printSuccess(message) {
15
+ console.log(`${pc.green('✓')} ${message}`);
16
+ }
17
+ export function printError(message) {
18
+ console.error(`${pc.red('✗')} ${message}`);
19
+ }
20
+ export function printInfo(message) {
21
+ console.log(`${pc.blue('ℹ')} ${message}`);
22
+ }
23
+ export function printWarning(message) {
24
+ console.log(`${pc.yellow('⚠')} ${message}`);
25
+ }
26
+ export function printDim(message) {
27
+ console.log(pc.dim(message));
28
+ }
@@ -0,0 +1,9 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/path.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ/C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAKlD"}
@@ -0,0 +1,23 @@
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
+ }
@@ -0,0 +1,7 @@
1
+ import { type CollectorConfig } from './schema.js';
2
+ export declare function loadConfig(customPath?: string): CollectorConfig;
3
+ /**
4
+ * Find and return the path of the first existing config file
5
+ */
6
+ export declare function findConfigPath(customPath?: string): string | null;
7
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAGjE,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,CAmD/D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQjE"}
@@ -0,0 +1,64 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { ZodError } from 'zod';
3
+ import { configSchema } from './schema.js';
4
+ import { getAllConfigPaths } from './paths.js';
5
+ export function loadConfig(customPath) {
6
+ // Build search paths: custom path first, then standard paths
7
+ const paths = customPath ? [customPath, ...getAllConfigPaths()] : getAllConfigPaths();
8
+ for (const configPath of paths) {
9
+ if (existsSync(configPath)) {
10
+ try {
11
+ const raw = readFileSync(configPath, 'utf-8');
12
+ const parsed = JSON.parse(raw);
13
+ return configSchema.parse(parsed);
14
+ }
15
+ catch (error) {
16
+ if (error instanceof SyntaxError) {
17
+ throw new Error(`Invalid JSON in config file ${configPath}: ${error.message}`);
18
+ }
19
+ if (error instanceof ZodError) {
20
+ const issues = error.issues
21
+ .map((i) => ` - ${i.path.join('.')}: ${i.message}`)
22
+ .join('\n');
23
+ throw new Error(`Config validation failed in ${configPath}:\n${issues}`);
24
+ }
25
+ throw error;
26
+ }
27
+ }
28
+ }
29
+ // Check environment variables for API config
30
+ const envApiUrl = process.env['LIFEREWIND_API_URL'];
31
+ const envApiKey = process.env['LIFEREWIND_API_KEY'];
32
+ if (envApiUrl && envApiKey) {
33
+ try {
34
+ return configSchema.parse({
35
+ api: {
36
+ baseUrl: envApiUrl,
37
+ apiKey: envApiKey,
38
+ },
39
+ });
40
+ }
41
+ catch (error) {
42
+ if (error instanceof ZodError) {
43
+ const issues = error.issues
44
+ .map((i) => ` - ${i.path.join('.')}: ${i.message}`)
45
+ .join('\n');
46
+ throw new Error(`Environment variable config validation failed:\n${issues}`);
47
+ }
48
+ throw error;
49
+ }
50
+ }
51
+ throw new Error('No configuration found. Run `liferewind init` to create one, or set LIFEREWIND_API_URL and LIFEREWIND_API_KEY environment variables.');
52
+ }
53
+ /**
54
+ * Find and return the path of the first existing config file
55
+ */
56
+ export function findConfigPath(customPath) {
57
+ const paths = customPath ? [customPath, ...getAllConfigPaths()] : getAllConfigPaths();
58
+ for (const configPath of paths) {
59
+ if (existsSync(configPath)) {
60
+ return configPath;
61
+ }
62
+ }
63
+ return null;
64
+ }
@@ -0,0 +1,8 @@
1
+ export declare const USER_CONFIG_DIR: string;
2
+ export declare const USER_CONFIG_PATH: string;
3
+ export declare const LEGACY_CONFIG_PATHS: string[];
4
+ export declare const PROJECT_CONFIG_PATH = "./collector.config.json";
5
+ export declare function getUserConfigPath(): string;
6
+ export declare function getUserConfigDir(): string;
7
+ export declare function getAllConfigPaths(): string[];
8
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/config/paths.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,eAAe,QAAoC,CAAC;AACjE,eAAO,MAAM,gBAAgB,QAA0C,CAAC;AAGxE,eAAO,MAAM,mBAAmB,UAG/B,CAAC;AAGF,eAAO,MAAM,mBAAmB,4BAA4B,CAAC;AAE7D,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C"}
@@ -0,0 +1,21 @@
1
+ import { homedir } from 'node:os';
2
+ import { resolve } from 'node:path';
3
+ // Primary user config path
4
+ export const USER_CONFIG_DIR = resolve(homedir(), '.liferewind');
5
+ export const USER_CONFIG_PATH = resolve(USER_CONFIG_DIR, 'config.json');
6
+ // Legacy config paths (for backward compatibility)
7
+ export const LEGACY_CONFIG_PATHS = [
8
+ resolve(homedir(), '.config/liferewind/collector.json'),
9
+ resolve(homedir(), '.liferewind-collector.json'),
10
+ ];
11
+ // Project-level config
12
+ export const PROJECT_CONFIG_PATH = './collector.config.json';
13
+ export function getUserConfigPath() {
14
+ return USER_CONFIG_PATH;
15
+ }
16
+ export function getUserConfigDir() {
17
+ return USER_CONFIG_DIR;
18
+ }
19
+ export function getAllConfigPaths() {
20
+ return [USER_CONFIG_PATH, ...LEGACY_CONFIG_PATHS, PROJECT_CONFIG_PATH];
21
+ }
@@ -0,0 +1,95 @@
1
+ import { z } from 'zod';
2
+ export declare const configSchema: z.ZodObject<{
3
+ api: z.ZodObject<{
4
+ baseUrl: z.ZodURL;
5
+ apiKey: z.ZodString;
6
+ timeout: z.ZodDefault<z.ZodNumber>;
7
+ retryAttempts: z.ZodDefault<z.ZodNumber>;
8
+ }, z.core.$strip>;
9
+ sources: z.ZodDefault<z.ZodObject<{
10
+ git: z.ZodObject<{
11
+ enabled: z.ZodBoolean;
12
+ schedule: z.ZodEnum<{
13
+ hourly: "hourly";
14
+ daily: "daily";
15
+ weekly: "weekly";
16
+ monthly: "monthly";
17
+ manual: "manual";
18
+ }>;
19
+ options: z.ZodObject<{
20
+ scanPaths: z.ZodArray<z.ZodString>;
21
+ excludeRepositories: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
+ authors: z.ZodOptional<z.ZodArray<z.ZodString>>;
23
+ sinceDays: z.ZodNumber;
24
+ }, z.core.$strip>;
25
+ }, z.core.$strip>;
26
+ browser: z.ZodObject<{
27
+ enabled: z.ZodBoolean;
28
+ schedule: z.ZodEnum<{
29
+ hourly: "hourly";
30
+ daily: "daily";
31
+ weekly: "weekly";
32
+ monthly: "monthly";
33
+ manual: "manual";
34
+ }>;
35
+ options: z.ZodObject<{
36
+ browsers: z.ZodArray<z.ZodEnum<{
37
+ chrome: "chrome";
38
+ safari: "safari";
39
+ arc: "arc";
40
+ dia: "dia";
41
+ comet: "comet";
42
+ }>>;
43
+ excludeDomains: z.ZodArray<z.ZodString>;
44
+ sinceDays: z.ZodNumber;
45
+ }, z.core.$strip>;
46
+ }, z.core.$strip>;
47
+ filesystem: z.ZodObject<{
48
+ enabled: z.ZodBoolean;
49
+ schedule: z.ZodEnum<{
50
+ hourly: "hourly";
51
+ daily: "daily";
52
+ weekly: "weekly";
53
+ monthly: "monthly";
54
+ manual: "manual";
55
+ }>;
56
+ options: z.ZodObject<{
57
+ watchPaths: z.ZodArray<z.ZodString>;
58
+ excludePatterns: z.ZodArray<z.ZodString>;
59
+ fileTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
60
+ sinceDays: z.ZodDefault<z.ZodNumber>;
61
+ maxFileSize: z.ZodOptional<z.ZodNumber>;
62
+ includeContent: z.ZodDefault<z.ZodBoolean>;
63
+ }, z.core.$strip>;
64
+ }, z.core.$strip>;
65
+ chatbot: z.ZodObject<{
66
+ enabled: z.ZodBoolean;
67
+ schedule: z.ZodEnum<{
68
+ hourly: "hourly";
69
+ daily: "daily";
70
+ weekly: "weekly";
71
+ monthly: "monthly";
72
+ manual: "manual";
73
+ }>;
74
+ options: z.ZodObject<{
75
+ clients: z.ZodArray<z.ZodEnum<{
76
+ chatwise: "chatwise";
77
+ }>>;
78
+ sinceDays: z.ZodDefault<z.ZodNumber>;
79
+ includeContent: z.ZodDefault<z.ZodBoolean>;
80
+ maxMessagesPerChat: z.ZodOptional<z.ZodNumber>;
81
+ excludeModels: z.ZodOptional<z.ZodArray<z.ZodString>>;
82
+ }, z.core.$strip>;
83
+ }, z.core.$strip>;
84
+ }, z.core.$strip>>;
85
+ logging: z.ZodDefault<z.ZodObject<{
86
+ level: z.ZodEnum<{
87
+ debug: "debug";
88
+ info: "info";
89
+ warn: "warn";
90
+ error: "error";
91
+ }>;
92
+ }, z.core.$strip>>;
93
+ }, z.core.$strip>;
94
+ export type CollectorConfig = z.infer<typeof configSchema>;
95
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAkHxB,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASvB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC"}
@@ -0,0 +1,110 @@
1
+ import { z } from 'zod';
2
+ const scheduleFrequencySchema = z.enum(['hourly', 'daily', 'weekly', 'monthly', 'manual']);
3
+ // Git source
4
+ const gitOptionsSchema = z.object({
5
+ scanPaths: z.array(z.string()),
6
+ excludeRepositories: z.array(z.string()).optional(),
7
+ authors: z.array(z.string()).optional(),
8
+ sinceDays: z.number(),
9
+ });
10
+ const gitSourceConfigSchema = z.object({
11
+ enabled: z.boolean(),
12
+ schedule: scheduleFrequencySchema,
13
+ options: gitOptionsSchema,
14
+ });
15
+ // Browser source
16
+ const browserOptionsSchema = z.object({
17
+ browsers: z.array(z.enum(['chrome', 'safari', 'arc', 'dia', 'comet'])),
18
+ excludeDomains: z.array(z.string()),
19
+ sinceDays: z.number(),
20
+ });
21
+ const browserSourceConfigSchema = z.object({
22
+ enabled: z.boolean(),
23
+ schedule: scheduleFrequencySchema,
24
+ options: browserOptionsSchema,
25
+ });
26
+ // Filesystem source
27
+ const filesystemOptionsSchema = z.object({
28
+ watchPaths: z.array(z.string()),
29
+ excludePatterns: z.array(z.string()),
30
+ fileTypes: z.array(z.string()).optional(),
31
+ sinceDays: z.number().default(7),
32
+ maxFileSize: z.number().optional(),
33
+ includeContent: z.boolean().default(true),
34
+ });
35
+ const filesystemSourceConfigSchema = z.object({
36
+ enabled: z.boolean(),
37
+ schedule: scheduleFrequencySchema,
38
+ options: filesystemOptionsSchema,
39
+ });
40
+ // Chatbot source
41
+ const chatbotOptionsSchema = z.object({
42
+ clients: z.array(z.enum(['chatwise'])),
43
+ sinceDays: z.number().default(30),
44
+ includeContent: z.boolean().default(true),
45
+ maxMessagesPerChat: z.number().optional(),
46
+ excludeModels: z.array(z.string()).optional(),
47
+ });
48
+ const chatbotSourceConfigSchema = z.object({
49
+ enabled: z.boolean(),
50
+ schedule: scheduleFrequencySchema,
51
+ options: chatbotOptionsSchema,
52
+ });
53
+ // Sources config with defaults
54
+ const sourcesSchema = z.object({
55
+ git: gitSourceConfigSchema,
56
+ browser: browserSourceConfigSchema,
57
+ filesystem: filesystemSourceConfigSchema,
58
+ chatbot: chatbotSourceConfigSchema,
59
+ });
60
+ // Default values defined once
61
+ const DEFAULT_SOURCES = {
62
+ git: {
63
+ enabled: true,
64
+ schedule: 'daily',
65
+ options: { scanPaths: [], excludeRepositories: [], sinceDays: 30 },
66
+ },
67
+ browser: {
68
+ enabled: true,
69
+ schedule: 'daily',
70
+ options: { browsers: ['chrome'], excludeDomains: [], sinceDays: 7 },
71
+ },
72
+ filesystem: {
73
+ enabled: true,
74
+ schedule: 'daily',
75
+ options: {
76
+ watchPaths: [],
77
+ excludePatterns: ['**/node_modules/**', '**/.git/**', '**/Library/**', '**/AppData/**'],
78
+ fileTypes: ['.md', '.txt', '.docx', '.doc', '.pptx', '.ppt', '.xlsx', '.xls', '.pdf', '.pages', '.numbers', '.key'],
79
+ sinceDays: 7,
80
+ includeContent: true,
81
+ },
82
+ },
83
+ chatbot: {
84
+ enabled: true,
85
+ schedule: 'daily',
86
+ options: {
87
+ clients: ['chatwise'],
88
+ sinceDays: 30,
89
+ includeContent: true,
90
+ },
91
+ },
92
+ };
93
+ // Logging config
94
+ const loggingSchema = z.object({
95
+ level: z.enum(['debug', 'info', 'warn', 'error']),
96
+ });
97
+ const DEFAULT_LOGGING = {
98
+ level: 'info',
99
+ };
100
+ // Main config schema
101
+ export const configSchema = z.object({
102
+ api: z.object({
103
+ baseUrl: z.url(),
104
+ apiKey: z.string().min(1),
105
+ timeout: z.number().default(30000),
106
+ retryAttempts: z.number().default(3),
107
+ }),
108
+ sources: sourcesSchema.default(DEFAULT_SOURCES),
109
+ logging: loggingSchema.default(DEFAULT_LOGGING),
110
+ });
@@ -0,0 +1,3 @@
1
+ import { type CollectorConfig } from './schema.js';
2
+ export declare function writeConfig(config: CollectorConfig, path?: string): void;
3
+ //# sourceMappingURL=writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/config/writer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAEjE,wBAAgB,WAAW,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAiBxE"}
@@ -0,0 +1,19 @@
1
+ import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ import { getUserConfigPath } from './paths.js';
4
+ import { configSchema } from './schema.js';
5
+ export function writeConfig(config, path) {
6
+ // Validate config before writing
7
+ const validated = configSchema.parse(config);
8
+ const targetPath = path || getUserConfigPath();
9
+ const dir = dirname(targetPath);
10
+ // Ensure directory exists with secure permissions
11
+ if (!existsSync(dir)) {
12
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
13
+ }
14
+ // Write formatted JSON with secure permissions (owner read/write only)
15
+ writeFileSync(targetPath, JSON.stringify(validated, null, 2), {
16
+ encoding: 'utf-8',
17
+ mode: 0o600,
18
+ });
19
+ }
@@ -0,0 +1,19 @@
1
+ import type { CollectorConfig } from '../config/schema.js';
2
+ import type { SourceType } from './types.js';
3
+ import type { Logger } from '../utils/logger.js';
4
+ export declare class Collector {
5
+ private config;
6
+ private logger;
7
+ private scheduler;
8
+ private apiClient;
9
+ private sources;
10
+ constructor(config: CollectorConfig, logger: Logger);
11
+ validateSources(): Promise<void>;
12
+ start(): Promise<void>;
13
+ stop(): Promise<void>;
14
+ collectAndPush(sourceType: SourceType): Promise<void>;
15
+ collectAll(): Promise<void>;
16
+ triggerCollection(sourceType: SourceType): Promise<void>;
17
+ getEnabledSources(): SourceType[];
18
+ }
19
+ //# sourceMappingURL=collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/core/collector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,OAAO,CAA0C;gBAE7C,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM;IAO7C,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBhC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BrD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAM3B,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9D,iBAAiB,IAAI,UAAU,EAAE;CAGlC"}
@@ -0,0 +1,83 @@
1
+ import { Scheduler } from './scheduler.js';
2
+ import { ApiClient } from '../api/client.js';
3
+ import { sourceRegistry } from '../sources/registry.js';
4
+ export class Collector {
5
+ config;
6
+ logger;
7
+ scheduler;
8
+ apiClient;
9
+ sources = new Map();
10
+ constructor(config, logger) {
11
+ this.config = config;
12
+ this.logger = logger;
13
+ this.scheduler = new Scheduler(logger);
14
+ this.apiClient = new ApiClient(config.api, logger);
15
+ }
16
+ async validateSources() {
17
+ const context = { logger: this.logger };
18
+ for (const [sourceType, sourceConfig] of Object.entries(this.config.sources)) {
19
+ if (!sourceConfig.enabled) {
20
+ this.logger.debug(`Source ${sourceType} is disabled, skipping`);
21
+ continue;
22
+ }
23
+ const source = sourceRegistry.create(sourceType, sourceConfig, context);
24
+ const isValid = await source.validate();
25
+ if (!isValid) {
26
+ this.logger.warn(`Source ${sourceType} validation failed, disabling`);
27
+ continue;
28
+ }
29
+ this.sources.set(sourceType, source);
30
+ this.logger.info(`Source ${sourceType} validated and ready`);
31
+ }
32
+ }
33
+ async start() {
34
+ const apiHealthy = await this.apiClient.healthCheck();
35
+ if (!apiHealthy) {
36
+ this.logger.warn('API health check failed, will retry on first push');
37
+ }
38
+ for (const [sourceType, source] of this.sources) {
39
+ this.scheduler.schedule(sourceType, source.getSchedule(), () => this.collectAndPush(sourceType));
40
+ }
41
+ this.scheduler.startAll();
42
+ if (process.env['COLLECTOR_RUN_ON_START'] === 'true') {
43
+ this.logger.info('Running initial collection...');
44
+ await this.collectAll();
45
+ }
46
+ }
47
+ async stop() {
48
+ this.scheduler.stopAll();
49
+ this.logger.info('Collector stopped');
50
+ }
51
+ async collectAndPush(sourceType) {
52
+ const source = this.sources.get(sourceType);
53
+ try {
54
+ this.logger.info(`Collecting from ${sourceType}...`);
55
+ const result = await source.collect();
56
+ if (!result.success) {
57
+ this.logger.error(`Collection failed for ${sourceType}`, result.error);
58
+ return;
59
+ }
60
+ if (result.itemsCollected === 0) {
61
+ this.logger.info(`No new items from ${sourceType}`);
62
+ return;
63
+ }
64
+ this.logger.info(`Collected ${result.itemsCollected} items from ${sourceType}`);
65
+ const response = await this.apiClient.pushData(result);
66
+ this.logger.info(`Pushed to API: ${response.data.itemsReceived} received, ${response.data.itemsInserted} inserted`);
67
+ }
68
+ catch (error) {
69
+ this.logger.error(`Error in collect/push cycle for ${sourceType}`, error);
70
+ }
71
+ }
72
+ async collectAll() {
73
+ for (const sourceType of this.sources.keys()) {
74
+ await this.collectAndPush(sourceType);
75
+ }
76
+ }
77
+ async triggerCollection(sourceType) {
78
+ await this.collectAndPush(sourceType);
79
+ }
80
+ getEnabledSources() {
81
+ return Array.from(this.sources.keys());
82
+ }
83
+ }
@@ -0,0 +1,12 @@
1
+ import type { ScheduleFrequency, SourceType } from './types.js';
2
+ import type { Logger } from '../utils/logger.js';
3
+ export declare class Scheduler {
4
+ private tasks;
5
+ private logger;
6
+ constructor(logger: Logger);
7
+ schedule(sourceType: SourceType, frequency: ScheduleFrequency, handler: () => Promise<void>): void;
8
+ unschedule(sourceType: SourceType): void;
9
+ startAll(): void;
10
+ stopAll(): void;
11
+ }
12
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/core/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAgBjD,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAwC;IACrD,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAI1B,QAAQ,CACN,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAC3B,IAAI;IAoBP,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAQxC,QAAQ,IAAI,IAAI;IAMhB,OAAO,IAAI,IAAI;CAKhB"}
@@ -0,0 +1,48 @@
1
+ import cron from 'node-cron';
2
+ const CRON_EXPRESSIONS = {
3
+ hourly: '0 * * * *',
4
+ daily: '0 9 * * *',
5
+ weekly: '0 9 * * 1',
6
+ monthly: '0 9 1 * *',
7
+ manual: null,
8
+ };
9
+ export class Scheduler {
10
+ tasks = new Map();
11
+ logger;
12
+ constructor(logger) {
13
+ this.logger = logger;
14
+ }
15
+ schedule(sourceType, frequency, handler) {
16
+ this.unschedule(sourceType);
17
+ const cronExpression = CRON_EXPRESSIONS[frequency];
18
+ if (!cronExpression) {
19
+ this.logger.info(`Source ${sourceType} set to manual - no schedule created`);
20
+ return;
21
+ }
22
+ const cronJob = cron.schedule(cronExpression, () => {
23
+ this.logger.info(`Running scheduled collection for ${sourceType}`);
24
+ handler().catch((error) => {
25
+ this.logger.error(`Scheduled collection failed for ${sourceType}`, error);
26
+ });
27
+ });
28
+ this.tasks.set(sourceType, { sourceType, cronJob, frequency });
29
+ this.logger.info(`Scheduled ${sourceType} with frequency: ${frequency}`);
30
+ }
31
+ unschedule(sourceType) {
32
+ const task = this.tasks.get(sourceType);
33
+ if (task) {
34
+ task.cronJob.stop();
35
+ this.tasks.delete(sourceType);
36
+ }
37
+ }
38
+ startAll() {
39
+ for (const task of this.tasks.values()) {
40
+ task.cronJob.start();
41
+ }
42
+ }
43
+ stopAll() {
44
+ for (const task of this.tasks.values()) {
45
+ task.cronJob.stop();
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,29 @@
1
+ /** Unique identifier for each data source type */
2
+ export type SourceType = 'git' | 'browser' | 'filesystem' | 'chatbot';
3
+ /** List of all valid source types */
4
+ export declare const SOURCE_TYPES: readonly SourceType[];
5
+ /** Schedule frequency for data collection */
6
+ export type ScheduleFrequency = 'hourly' | 'daily' | 'weekly' | 'monthly' | 'manual';
7
+ /** Base structure for all collected data items */
8
+ export interface CollectedItem {
9
+ sourceType: SourceType;
10
+ timestamp: Date;
11
+ data: unknown;
12
+ }
13
+ /** Result from a collection operation */
14
+ export interface CollectionResult {
15
+ sourceType: SourceType;
16
+ success: boolean;
17
+ itemsCollected: number;
18
+ items: CollectedItem[];
19
+ error?: Error;
20
+ collectedAt: Date;
21
+ }
22
+ /** Configuration for a specific data source */
23
+ export interface SourceConfig {
24
+ enabled: boolean;
25
+ schedule: ScheduleFrequency;
26
+ /** Source-specific options, type checked at runtime by Zod schema */
27
+ options: unknown;
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;AAEtE,qCAAqC;AACrC,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAAyD,CAAC;AAExG,6CAA6C;AAC7C,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAErF,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,yCAAyC;AACzC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,WAAW,EAAE,IAAI,CAAC;CACnB;AAED,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAC;CAClB"}
@@ -0,0 +1,2 @@
1
+ /** List of all valid source types */
2
+ export const SOURCE_TYPES = ['git', 'browser', 'filesystem', 'chatbot'];
@@ -0,0 +1,9 @@
1
+ export { Collector } from './core/collector.js';
2
+ export { loadConfig, findConfigPath } from './config/loader.js';
3
+ export { writeConfig } from './config/writer.js';
4
+ export { getUserConfigPath, getUserConfigDir, getAllConfigPaths } from './config/paths.js';
5
+ export { createLogger } from './utils/logger.js';
6
+ export { registerBuiltinSources, sourceRegistry } from './sources/index.js';
7
+ export type { CollectorConfig } from './config/schema.js';
8
+ export type { SourceType, CollectedItem } from './core/types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ // Library exports for programmatic usage
2
+ export { Collector } from './core/collector.js';
3
+ export { loadConfig, findConfigPath } from './config/loader.js';
4
+ export { writeConfig } from './config/writer.js';
5
+ export { getUserConfigPath, getUserConfigDir, getAllConfigPaths } from './config/paths.js';
6
+ export { createLogger } from './utils/logger.js';
7
+ export { registerBuiltinSources, sourceRegistry } from './sources/index.js';