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.
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/dist/api/client.d.ts +31 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +115 -0
- package/dist/cli/commands/collect.d.ts +3 -0
- package/dist/cli/commands/collect.d.ts.map +1 -0
- package/dist/cli/commands/collect.js +62 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +112 -0
- package/dist/cli/commands/doctor.d.ts +3 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +150 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +244 -0
- package/dist/cli/commands/start.d.ts +3 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +59 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +49 -0
- package/dist/cli/detect/browsers.d.ts +3 -0
- package/dist/cli/detect/browsers.d.ts.map +1 -0
- package/dist/cli/detect/browsers.js +19 -0
- package/dist/cli/detect/chatbot.d.ts +3 -0
- package/dist/cli/detect/chatbot.d.ts.map +1 -0
- package/dist/cli/detect/chatbot.js +15 -0
- package/dist/cli/detect/git.d.ts +2 -0
- package/dist/cli/detect/git.d.ts.map +1 -0
- package/dist/cli/detect/git.js +10 -0
- package/dist/cli/detect/index.d.ts +4 -0
- package/dist/cli/detect/index.d.ts.map +1 -0
- package/dist/cli/detect/index.js +3 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +30 -0
- package/dist/cli/utils/output.d.ts +8 -0
- package/dist/cli/utils/output.d.ts.map +1 -0
- package/dist/cli/utils/output.js +28 -0
- package/dist/cli/utils/path.d.ts +9 -0
- package/dist/cli/utils/path.d.ts.map +1 -0
- package/dist/cli/utils/path.js +23 -0
- package/dist/config/loader.d.ts +7 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +64 -0
- package/dist/config/paths.d.ts +8 -0
- package/dist/config/paths.d.ts.map +1 -0
- package/dist/config/paths.js +21 -0
- package/dist/config/schema.d.ts +95 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +110 -0
- package/dist/config/writer.d.ts +3 -0
- package/dist/config/writer.d.ts.map +1 -0
- package/dist/config/writer.js +19 -0
- package/dist/core/collector.d.ts +19 -0
- package/dist/core/collector.d.ts.map +1 -0
- package/dist/core/collector.js +83 -0
- package/dist/core/scheduler.d.ts +12 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +48 -0
- package/dist/core/types.d.ts +29 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/sources/base.d.ts +27 -0
- package/dist/sources/base.d.ts.map +1 -0
- package/dist/sources/base.js +23 -0
- package/dist/sources/browser/index.d.ts +14 -0
- package/dist/sources/browser/index.d.ts.map +1 -0
- package/dist/sources/browser/index.js +116 -0
- package/dist/sources/browser/readers/base.d.ts +28 -0
- package/dist/sources/browser/readers/base.d.ts.map +1 -0
- package/dist/sources/browser/readers/base.js +110 -0
- package/dist/sources/browser/readers/chromium.d.ts +13 -0
- package/dist/sources/browser/readers/chromium.d.ts.map +1 -0
- package/dist/sources/browser/readers/chromium.js +64 -0
- package/dist/sources/browser/readers/safari.d.ts +9 -0
- package/dist/sources/browser/readers/safari.d.ts.map +1 -0
- package/dist/sources/browser/readers/safari.js +34 -0
- package/dist/sources/browser/types.d.ts +35 -0
- package/dist/sources/browser/types.d.ts.map +1 -0
- package/dist/sources/browser/types.js +1 -0
- package/dist/sources/chatbot/index.d.ts +12 -0
- package/dist/sources/chatbot/index.d.ts.map +1 -0
- package/dist/sources/chatbot/index.js +67 -0
- package/dist/sources/chatbot/readers/base.d.ts +25 -0
- package/dist/sources/chatbot/readers/base.d.ts.map +1 -0
- package/dist/sources/chatbot/readers/base.js +109 -0
- package/dist/sources/chatbot/readers/chatwise.d.ts +14 -0
- package/dist/sources/chatbot/readers/chatwise.d.ts.map +1 -0
- package/dist/sources/chatbot/readers/chatwise.js +117 -0
- package/dist/sources/chatbot/types.d.ts +33 -0
- package/dist/sources/chatbot/types.d.ts.map +1 -0
- package/dist/sources/chatbot/types.js +1 -0
- package/dist/sources/filesystem/index.d.ts +10 -0
- package/dist/sources/filesystem/index.d.ts.map +1 -0
- package/dist/sources/filesystem/index.js +58 -0
- package/dist/sources/filesystem/scanner.d.ts +24 -0
- package/dist/sources/filesystem/scanner.d.ts.map +1 -0
- package/dist/sources/filesystem/scanner.js +264 -0
- package/dist/sources/filesystem/types.d.ts +39 -0
- package/dist/sources/filesystem/types.d.ts.map +1 -0
- package/dist/sources/filesystem/types.js +1 -0
- package/dist/sources/git/index.d.ts +16 -0
- package/dist/sources/git/index.d.ts.map +1 -0
- package/dist/sources/git/index.js +169 -0
- package/dist/sources/git/types.d.ts +25 -0
- package/dist/sources/git/types.d.ts.map +1 -0
- package/dist/sources/git/types.js +1 -0
- package/dist/sources/index.d.ts +7 -0
- package/dist/sources/index.d.ts.map +1 -0
- package/dist/sources/index.js +16 -0
- package/dist/sources/registry.d.ts +13 -0
- package/dist/sources/registry.d.ts.map +1 -0
- package/dist/sources/registry.js +19 -0
- package/dist/utils/logger.d.ts +12 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +34 -0
- package/dist/utils/path.d.ts +9 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +22 -0
- package/dist/utils/retry.d.ts +8 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +22 -0
- package/package.json +81 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CollectionResult, SourceConfig, SourceType } from '../core/types.js';
|
|
2
|
+
import type { Logger } from '../utils/logger.js';
|
|
3
|
+
export interface DataSourceContext {
|
|
4
|
+
logger: Logger;
|
|
5
|
+
lastCollectionTime?: Date;
|
|
6
|
+
}
|
|
7
|
+
export declare abstract class DataSource<TOptions = unknown> {
|
|
8
|
+
abstract readonly type: SourceType;
|
|
9
|
+
abstract readonly name: string;
|
|
10
|
+
protected config: SourceConfig;
|
|
11
|
+
protected context: DataSourceContext;
|
|
12
|
+
constructor(config: SourceConfig, context: DataSourceContext);
|
|
13
|
+
/**
|
|
14
|
+
* Source-specific options, cast to the concrete type.
|
|
15
|
+
* Type assertion is safe because options are validated by Zod schema in config loader.
|
|
16
|
+
*/
|
|
17
|
+
protected get options(): TOptions;
|
|
18
|
+
/** Validate that this source can run on the current system */
|
|
19
|
+
abstract validate(): Promise<boolean>;
|
|
20
|
+
/** Collect data from this source */
|
|
21
|
+
abstract collect(): Promise<CollectionResult>;
|
|
22
|
+
/** Get the schedule for this source */
|
|
23
|
+
getSchedule(): import("../core/types.js").ScheduleFrequency;
|
|
24
|
+
/** Check if this source is enabled */
|
|
25
|
+
isEnabled(): boolean;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/sources/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,IAAI,CAAC;CAC3B;AAED,8BAAsB,UAAU,CAAC,QAAQ,GAAG,OAAO;IACjD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAE/B,SAAS,CAAC,MAAM,EAAE,YAAY,CAAC;IAC/B,SAAS,CAAC,OAAO,EAAE,iBAAiB,CAAC;gBAEzB,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,iBAAiB;IAK5D;;;OAGG;IACH,SAAS,KAAK,OAAO,IAAI,QAAQ,CAEhC;IAED,8DAA8D;IAC9D,QAAQ,CAAC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAErC,oCAAoC;IACpC,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAE7C,uCAAuC;IACvC,WAAW;IAIX,sCAAsC;IACtC,SAAS;CAGV"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class DataSource {
|
|
2
|
+
config;
|
|
3
|
+
context;
|
|
4
|
+
constructor(config, context) {
|
|
5
|
+
this.config = config;
|
|
6
|
+
this.context = context;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Source-specific options, cast to the concrete type.
|
|
10
|
+
* Type assertion is safe because options are validated by Zod schema in config loader.
|
|
11
|
+
*/
|
|
12
|
+
get options() {
|
|
13
|
+
return this.config.options;
|
|
14
|
+
}
|
|
15
|
+
/** Get the schedule for this source */
|
|
16
|
+
getSchedule() {
|
|
17
|
+
return this.config.schedule;
|
|
18
|
+
}
|
|
19
|
+
/** Check if this source is enabled */
|
|
20
|
+
isEnabled() {
|
|
21
|
+
return this.config.enabled;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DataSource } from '../base.js';
|
|
2
|
+
import type { CollectionResult } from '../../core/types.js';
|
|
3
|
+
import type { BrowserSourceOptions } from './types.js';
|
|
4
|
+
export declare class BrowserSource extends DataSource<BrowserSourceOptions> {
|
|
5
|
+
readonly type: "browser";
|
|
6
|
+
readonly name = "Browser History";
|
|
7
|
+
private readers;
|
|
8
|
+
validate(): Promise<boolean>;
|
|
9
|
+
collect(): Promise<CollectionResult>;
|
|
10
|
+
/** Aggregate raw browser history items by URL + browser + date */
|
|
11
|
+
private aggregateByDay;
|
|
12
|
+
private createReader;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sources/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAEV,oBAAoB,EAGrB,MAAM,YAAY,CAAC;AAKpB,qBAAa,aAAc,SAAQ,UAAU,CAAC,oBAAoB,CAAC;IACjE,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAU;IACnC,QAAQ,CAAC,IAAI,qBAAqB;IAElC,OAAO,CAAC,OAAO,CAAuB;IAEhC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IA0B5B,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAqC1C,kEAAkE;IAClE,OAAO,CAAC,cAAc;IAmDtB,OAAO,CAAC,YAAY;CAcrB"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { DataSource } from '../base.js';
|
|
2
|
+
import { ChromiumReader } from './readers/chromium.js';
|
|
3
|
+
import { SafariReader } from './readers/safari.js';
|
|
4
|
+
export class BrowserSource extends DataSource {
|
|
5
|
+
type = 'browser';
|
|
6
|
+
name = 'Browser History';
|
|
7
|
+
readers = [];
|
|
8
|
+
async validate() {
|
|
9
|
+
const readerContext = {
|
|
10
|
+
logger: this.context.logger,
|
|
11
|
+
sinceDays: this.options.sinceDays,
|
|
12
|
+
excludeDomains: this.options.excludeDomains,
|
|
13
|
+
};
|
|
14
|
+
// Create readers for enabled browsers
|
|
15
|
+
for (const browser of this.options.browsers) {
|
|
16
|
+
const reader = this.createReader(browser, readerContext);
|
|
17
|
+
if (reader && reader.hasValidDatabases()) {
|
|
18
|
+
this.readers.push(reader);
|
|
19
|
+
this.context.logger.info(`Browser ${browser} validated and ready`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.context.logger.warn(`Browser ${browser} has no accessible history database`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (this.readers.length === 0) {
|
|
26
|
+
this.context.logger.error('No valid browser history databases found');
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
async collect() {
|
|
32
|
+
const allItems = [];
|
|
33
|
+
for (const reader of this.readers) {
|
|
34
|
+
try {
|
|
35
|
+
const items = reader.read();
|
|
36
|
+
allItems.push(...items);
|
|
37
|
+
this.context.logger.debug(`Collected ${items.length} items from ${reader.browserType}`);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
this.context.logger.error(`Failed to collect from ${reader.browserType}`, error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Aggregate by URL + browser + date
|
|
44
|
+
const aggregated = this.aggregateByDay(allItems);
|
|
45
|
+
this.context.logger.info(`Aggregated ${allItems.length} raw visits into ${aggregated.length} daily records`);
|
|
46
|
+
// Sort by last visit time descending
|
|
47
|
+
aggregated.sort((a, b) => new Date(b.lastVisitTime).getTime() - new Date(a.lastVisitTime).getTime());
|
|
48
|
+
return {
|
|
49
|
+
sourceType: this.type,
|
|
50
|
+
success: true,
|
|
51
|
+
itemsCollected: aggregated.length,
|
|
52
|
+
items: aggregated.map((item) => ({
|
|
53
|
+
sourceType: this.type,
|
|
54
|
+
timestamp: new Date(item.lastVisitTime),
|
|
55
|
+
data: item,
|
|
56
|
+
})),
|
|
57
|
+
collectedAt: new Date(),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Aggregate raw browser history items by URL + browser + date */
|
|
61
|
+
aggregateByDay(items) {
|
|
62
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
63
|
+
const grouped = new Map();
|
|
64
|
+
for (const item of items) {
|
|
65
|
+
// Get local date string in YYYY-MM-DD format
|
|
66
|
+
const date = new Date(item.visitTime).toLocaleDateString('en-CA', { timeZone: timezone });
|
|
67
|
+
const key = `${item.url}|${item.browser}|${date}`;
|
|
68
|
+
if (!grouped.has(key)) {
|
|
69
|
+
grouped.set(key, []);
|
|
70
|
+
}
|
|
71
|
+
grouped.get(key).push(item);
|
|
72
|
+
}
|
|
73
|
+
return Array.from(grouped.entries()).map(([key, visits]) => {
|
|
74
|
+
const parts = key.split('|');
|
|
75
|
+
// Key format is guaranteed: `${url}|${browser}|${date}`
|
|
76
|
+
if (parts.length < 3) {
|
|
77
|
+
throw new Error(`Invalid aggregation key format: ${key}`);
|
|
78
|
+
}
|
|
79
|
+
const url = parts[0];
|
|
80
|
+
const browser = parts[1];
|
|
81
|
+
const date = parts[2];
|
|
82
|
+
// Sort visits by time ascending to get first and last
|
|
83
|
+
const sorted = visits.sort((a, b) => new Date(a.visitTime).getTime() - new Date(b.visitTime).getTime());
|
|
84
|
+
// Collect unique profiles
|
|
85
|
+
const profiles = [...new Set(visits.map((v) => v.profile).filter((p) => !!p))];
|
|
86
|
+
// sorted is guaranteed non-empty since visits came from grouping
|
|
87
|
+
const firstVisit = sorted[0];
|
|
88
|
+
const lastVisit = sorted[sorted.length - 1];
|
|
89
|
+
return {
|
|
90
|
+
url,
|
|
91
|
+
title: lastVisit.title, // Use title from last visit
|
|
92
|
+
browser,
|
|
93
|
+
profiles,
|
|
94
|
+
date,
|
|
95
|
+
timezone,
|
|
96
|
+
dailyVisitCount: visits.length,
|
|
97
|
+
firstVisitTime: firstVisit.visitTime,
|
|
98
|
+
lastVisitTime: lastVisit.visitTime,
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
createReader(browser, context) {
|
|
103
|
+
switch (browser) {
|
|
104
|
+
case 'chrome':
|
|
105
|
+
case 'arc':
|
|
106
|
+
case 'dia':
|
|
107
|
+
case 'comet':
|
|
108
|
+
return new ChromiumReader(browser, context);
|
|
109
|
+
case 'safari':
|
|
110
|
+
return new SafariReader(context);
|
|
111
|
+
default:
|
|
112
|
+
this.context.logger.warn(`Unknown browser type: ${browser}`);
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { BrowserHistoryItem, BrowserType } from '../types.js';
|
|
2
|
+
import type { Logger } from '../../../utils/logger.js';
|
|
3
|
+
export interface ReaderContext {
|
|
4
|
+
logger: Logger;
|
|
5
|
+
sinceDays: number;
|
|
6
|
+
excludeDomains: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare abstract class BrowserReader {
|
|
9
|
+
abstract readonly browserType: BrowserType;
|
|
10
|
+
protected context: ReaderContext;
|
|
11
|
+
constructor(context: ReaderContext);
|
|
12
|
+
/** Get all database paths for this browser */
|
|
13
|
+
abstract getDbPaths(): string[];
|
|
14
|
+
/** Get the SQL query for this browser's history format */
|
|
15
|
+
abstract getQuery(): string;
|
|
16
|
+
/** Get profile name from database path (if applicable) */
|
|
17
|
+
abstract getProfileName(dbPath: string): string | undefined;
|
|
18
|
+
/** Read history from all available databases */
|
|
19
|
+
read(): BrowserHistoryItem[];
|
|
20
|
+
/** Check if any history databases exist */
|
|
21
|
+
hasValidDatabases(): boolean;
|
|
22
|
+
private readFromDb;
|
|
23
|
+
/** Type guard to validate raw SQL row structure */
|
|
24
|
+
private isValidRow;
|
|
25
|
+
private isValidUrl;
|
|
26
|
+
private isExcluded;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/sources/browser/readers/base.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAiB,MAAM,aAAa,CAAC;AAClF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,8BAAsB,aAAa;IACjC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAE3C,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC;gBAErB,OAAO,EAAE,aAAa;IAIlC,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,IAAI,MAAM,EAAE;IAE/B,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,IAAI,MAAM;IAE3B,0DAA0D;IAC1D,QAAQ,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAE3D,gDAAgD;IAChD,IAAI,IAAI,kBAAkB,EAAE;IAwB5B,2CAA2C;IAC3C,iBAAiB,IAAI,OAAO;IAI5B,OAAO,CAAC,UAAU;IAgDlB,mDAAmD;IACnD,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,UAAU;CAYnB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { copyFileSync, unlinkSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { randomUUID } from 'node:crypto';
|
|
5
|
+
import Database from 'better-sqlite3';
|
|
6
|
+
export class BrowserReader {
|
|
7
|
+
context;
|
|
8
|
+
constructor(context) {
|
|
9
|
+
this.context = context;
|
|
10
|
+
}
|
|
11
|
+
/** Read history from all available databases */
|
|
12
|
+
read() {
|
|
13
|
+
const items = [];
|
|
14
|
+
const dbPaths = this.getDbPaths();
|
|
15
|
+
if (dbPaths.length === 0) {
|
|
16
|
+
this.context.logger.debug(`No ${this.browserType} history databases found`);
|
|
17
|
+
return items;
|
|
18
|
+
}
|
|
19
|
+
for (const dbPath of dbPaths) {
|
|
20
|
+
try {
|
|
21
|
+
const profileItems = this.readFromDb(dbPath);
|
|
22
|
+
items.push(...profileItems);
|
|
23
|
+
this.context.logger.debug(`Read ${profileItems.length} items from ${this.browserType} (${this.getProfileName(dbPath) ?? 'default'})`);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
this.context.logger.warn(`Failed to read from ${dbPath}`, error);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return items;
|
|
30
|
+
}
|
|
31
|
+
/** Check if any history databases exist */
|
|
32
|
+
hasValidDatabases() {
|
|
33
|
+
return this.getDbPaths().length > 0;
|
|
34
|
+
}
|
|
35
|
+
readFromDb(dbPath) {
|
|
36
|
+
const tempPath = join(tmpdir(), `browser-history-${randomUUID()}.db`);
|
|
37
|
+
let db = null;
|
|
38
|
+
try {
|
|
39
|
+
// Copy database to avoid locking issues
|
|
40
|
+
copyFileSync(dbPath, tempPath);
|
|
41
|
+
db = new Database(tempPath, { readonly: true });
|
|
42
|
+
const sinceTimestamp = Math.floor(Date.now() / 1000) - this.context.sinceDays * 24 * 60 * 60;
|
|
43
|
+
const stmt = db.prepare(this.getQuery());
|
|
44
|
+
const rows = stmt.all(sinceTimestamp);
|
|
45
|
+
const profile = this.getProfileName(dbPath);
|
|
46
|
+
return rows
|
|
47
|
+
.filter((row) => this.isValidRow(row))
|
|
48
|
+
.filter((row) => this.isValidUrl(row.url))
|
|
49
|
+
.filter((row) => !this.isExcluded(row.url))
|
|
50
|
+
.map((row) => ({
|
|
51
|
+
url: row.url,
|
|
52
|
+
title: row.title ?? '',
|
|
53
|
+
visitTime: new Date(row.visit_unix * 1000).toISOString(),
|
|
54
|
+
visitCount: row.visit_count,
|
|
55
|
+
browser: this.browserType,
|
|
56
|
+
...(profile && { profile }),
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
// Close database connection
|
|
61
|
+
if (db) {
|
|
62
|
+
try {
|
|
63
|
+
db.close();
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
this.context.logger.debug('Failed to close database connection', error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Clean up temp file
|
|
70
|
+
if (existsSync(tempPath)) {
|
|
71
|
+
try {
|
|
72
|
+
unlinkSync(tempPath);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
this.context.logger.debug(`Failed to clean up temp file: ${tempPath}`, error);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Type guard to validate raw SQL row structure */
|
|
81
|
+
isValidRow(row) {
|
|
82
|
+
if (typeof row !== 'object' || row === null)
|
|
83
|
+
return false;
|
|
84
|
+
const record = row;
|
|
85
|
+
return (typeof record['url'] === 'string' &&
|
|
86
|
+
(typeof record['title'] === 'string' || record['title'] === null) &&
|
|
87
|
+
typeof record['visit_count'] === 'number' &&
|
|
88
|
+
typeof record['visit_unix'] === 'number');
|
|
89
|
+
}
|
|
90
|
+
isValidUrl(url) {
|
|
91
|
+
try {
|
|
92
|
+
const parsed = new URL(url);
|
|
93
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
isExcluded(url) {
|
|
100
|
+
if (this.context.excludeDomains.length === 0)
|
|
101
|
+
return false;
|
|
102
|
+
try {
|
|
103
|
+
const hostname = new URL(url).hostname;
|
|
104
|
+
return this.context.excludeDomains.some((domain) => hostname === domain || hostname.endsWith(`.${domain}`));
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BrowserReader, type ReaderContext } from './base.js';
|
|
2
|
+
import type { BrowserType } from '../types.js';
|
|
3
|
+
export type ChromiumBrowserType = 'chrome' | 'arc' | 'dia' | 'comet';
|
|
4
|
+
export declare class ChromiumReader extends BrowserReader {
|
|
5
|
+
readonly browserType: BrowserType;
|
|
6
|
+
private readonly browserPath;
|
|
7
|
+
constructor(browserType: ChromiumBrowserType, context: ReaderContext);
|
|
8
|
+
getDbPaths(): string[];
|
|
9
|
+
getQuery(): string;
|
|
10
|
+
getProfileName(dbPath: string): string | undefined;
|
|
11
|
+
private discoverProfiles;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=chromium.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chromium.d.ts","sourceRoot":"","sources":["../../../../src/sources/browser/readers/chromium.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AASrE,qBAAa,cAAe,SAAQ,aAAa;IAC/C,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,aAAa;IAMpE,UAAU,IAAI,MAAM,EAAE;IAUtB,QAAQ,IAAI,MAAM;IAclB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAUlD,OAAO,CAAC,gBAAgB;CAWzB"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { join, sep } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { BrowserReader } from './base.js';
|
|
5
|
+
// Chromium timestamp: microseconds since 1601-01-01
|
|
6
|
+
// Conversion: timestamp / 1000000 - 11644473600 = unix timestamp
|
|
7
|
+
const CHROMIUM_EPOCH_OFFSET = 11644473600;
|
|
8
|
+
const BROWSER_PATHS = {
|
|
9
|
+
chrome: join(homedir(), 'Library', 'Application Support', 'Google', 'Chrome'),
|
|
10
|
+
arc: join(homedir(), 'Library', 'Application Support', 'Arc', 'User Data'),
|
|
11
|
+
dia: join(homedir(), 'Library', 'Application Support', 'Dia', 'User Data'),
|
|
12
|
+
comet: join(homedir(), 'Library', 'Application Support', 'Comet'),
|
|
13
|
+
};
|
|
14
|
+
export class ChromiumReader extends BrowserReader {
|
|
15
|
+
browserType;
|
|
16
|
+
browserPath;
|
|
17
|
+
constructor(browserType, context) {
|
|
18
|
+
super(context);
|
|
19
|
+
this.browserType = browserType;
|
|
20
|
+
this.browserPath = BROWSER_PATHS[browserType];
|
|
21
|
+
}
|
|
22
|
+
getDbPaths() {
|
|
23
|
+
if (!existsSync(this.browserPath)) {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
return this.discoverProfiles()
|
|
27
|
+
.map((profile) => join(this.browserPath, profile, 'History'))
|
|
28
|
+
.filter((path) => existsSync(path));
|
|
29
|
+
}
|
|
30
|
+
getQuery() {
|
|
31
|
+
return `
|
|
32
|
+
SELECT
|
|
33
|
+
urls.url,
|
|
34
|
+
urls.title,
|
|
35
|
+
urls.visit_count,
|
|
36
|
+
CAST((visits.visit_time / 1000000 - ${CHROMIUM_EPOCH_OFFSET}) AS INTEGER) as visit_unix
|
|
37
|
+
FROM urls
|
|
38
|
+
JOIN visits ON urls.id = visits.url
|
|
39
|
+
WHERE visit_unix > ?
|
|
40
|
+
ORDER BY visits.visit_time DESC
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
getProfileName(dbPath) {
|
|
44
|
+
const parts = dbPath.split(sep);
|
|
45
|
+
const historyIndex = parts.findIndex((p) => p === 'History');
|
|
46
|
+
if (historyIndex > 0) {
|
|
47
|
+
const profile = parts[historyIndex - 1];
|
|
48
|
+
return profile === 'Default' ? undefined : profile;
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
discoverProfiles() {
|
|
53
|
+
try {
|
|
54
|
+
const entries = readdirSync(this.browserPath, { withFileTypes: true });
|
|
55
|
+
return entries
|
|
56
|
+
.filter((e) => e.isDirectory())
|
|
57
|
+
.filter((e) => e.name === 'Default' || e.name.startsWith('Profile '))
|
|
58
|
+
.map((e) => e.name);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BrowserReader } from './base.js';
|
|
2
|
+
import type { BrowserType } from '../types.js';
|
|
3
|
+
export declare class SafariReader extends BrowserReader {
|
|
4
|
+
readonly browserType: BrowserType;
|
|
5
|
+
getDbPaths(): string[];
|
|
6
|
+
getQuery(): string;
|
|
7
|
+
getProfileName(_dbPath: string): string | undefined;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=safari.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safari.d.ts","sourceRoot":"","sources":["../../../../src/sources/browser/readers/safari.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAQ/C,qBAAa,YAAa,SAAQ,aAAa;IAC7C,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAY;IAE7C,UAAU,IAAI,MAAM,EAAE;IAOtB,QAAQ,IAAI,MAAM;IAclB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;CAIpD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { BrowserReader } from './base.js';
|
|
5
|
+
// Safari timestamp: seconds since 2001-01-01 (Apple Cocoa epoch)
|
|
6
|
+
// Conversion: timestamp + 978307200 = unix timestamp
|
|
7
|
+
const SAFARI_EPOCH_OFFSET = 978307200;
|
|
8
|
+
const SAFARI_HISTORY_PATH = join(homedir(), 'Library', 'Safari', 'History.db');
|
|
9
|
+
export class SafariReader extends BrowserReader {
|
|
10
|
+
browserType = 'safari';
|
|
11
|
+
getDbPaths() {
|
|
12
|
+
if (existsSync(SAFARI_HISTORY_PATH)) {
|
|
13
|
+
return [SAFARI_HISTORY_PATH];
|
|
14
|
+
}
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
getQuery() {
|
|
18
|
+
return `
|
|
19
|
+
SELECT
|
|
20
|
+
i.url,
|
|
21
|
+
v.title,
|
|
22
|
+
i.visit_count,
|
|
23
|
+
CAST((v.visit_time + ${SAFARI_EPOCH_OFFSET}) AS INTEGER) as visit_unix
|
|
24
|
+
FROM history_items i
|
|
25
|
+
JOIN history_visits v ON i.id = v.history_item
|
|
26
|
+
WHERE visit_unix > ?
|
|
27
|
+
ORDER BY v.visit_time DESC
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
30
|
+
getProfileName(_dbPath) {
|
|
31
|
+
// Safari doesn't have profiles
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type BrowserType = 'chrome' | 'safari' | 'arc' | 'dia' | 'comet';
|
|
2
|
+
/** Raw browser history item from SQLite database */
|
|
3
|
+
export interface BrowserHistoryItem {
|
|
4
|
+
url: string;
|
|
5
|
+
title: string;
|
|
6
|
+
visitTime: string;
|
|
7
|
+
visitCount: number;
|
|
8
|
+
browser: BrowserType;
|
|
9
|
+
profile?: string;
|
|
10
|
+
}
|
|
11
|
+
/** Aggregated browser history item (grouped by URL + browser + date) */
|
|
12
|
+
export interface AggregatedBrowserHistoryItem {
|
|
13
|
+
url: string;
|
|
14
|
+
title: string;
|
|
15
|
+
browser: BrowserType;
|
|
16
|
+
profiles: string[];
|
|
17
|
+
date: string;
|
|
18
|
+
timezone: string;
|
|
19
|
+
dailyVisitCount: number;
|
|
20
|
+
firstVisitTime: string;
|
|
21
|
+
lastVisitTime: string;
|
|
22
|
+
}
|
|
23
|
+
export interface BrowserSourceOptions {
|
|
24
|
+
browsers: BrowserType[];
|
|
25
|
+
excludeDomains: string[];
|
|
26
|
+
sinceDays: number;
|
|
27
|
+
}
|
|
28
|
+
/** Internal representation of a raw history row from SQLite */
|
|
29
|
+
export interface RawHistoryRow {
|
|
30
|
+
url: string;
|
|
31
|
+
title: string | null;
|
|
32
|
+
visit_count: number;
|
|
33
|
+
visit_unix: number;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/sources/browser/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AAExE,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wEAAwE;AACxE,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DataSource } from '../base.js';
|
|
2
|
+
import type { CollectionResult } from '../../core/types.js';
|
|
3
|
+
import type { ChatbotSourceOptions } from './types.js';
|
|
4
|
+
export declare class ChatbotSource extends DataSource<ChatbotSourceOptions> {
|
|
5
|
+
readonly type: "chatbot";
|
|
6
|
+
readonly name = "Chatbot History";
|
|
7
|
+
private readers;
|
|
8
|
+
validate(): Promise<boolean>;
|
|
9
|
+
collect(): Promise<CollectionResult>;
|
|
10
|
+
private createReader;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sources/chatbot/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAgC,MAAM,YAAY,CAAC;AAIrF,qBAAa,aAAc,SAAQ,UAAU,CAAC,oBAAoB,CAAC;IACjE,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAU;IACnC,QAAQ,CAAC,IAAI,qBAAqB;IAElC,OAAO,CAAC,OAAO,CAAuB;IAEhC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IA4B5B,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC;IA+B1C,OAAO,CAAC,YAAY;CASrB"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { DataSource } from '../base.js';
|
|
2
|
+
import { ChatWiseReader } from './readers/chatwise.js';
|
|
3
|
+
export class ChatbotSource extends DataSource {
|
|
4
|
+
type = 'chatbot';
|
|
5
|
+
name = 'Chatbot History';
|
|
6
|
+
readers = [];
|
|
7
|
+
async validate() {
|
|
8
|
+
const readerContext = {
|
|
9
|
+
logger: this.context.logger,
|
|
10
|
+
sinceDays: this.options.sinceDays,
|
|
11
|
+
includeContent: this.options.includeContent,
|
|
12
|
+
maxMessagesPerChat: this.options.maxMessagesPerChat,
|
|
13
|
+
excludeModels: this.options.excludeModels,
|
|
14
|
+
};
|
|
15
|
+
// Create readers for enabled clients
|
|
16
|
+
for (const client of this.options.clients) {
|
|
17
|
+
const reader = this.createReader(client, readerContext);
|
|
18
|
+
if (reader && reader.hasValidDatabase()) {
|
|
19
|
+
this.readers.push(reader);
|
|
20
|
+
this.context.logger.info(`Chatbot client ${client} validated and ready`);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
this.context.logger.warn(`Chatbot client ${client} has no accessible database`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (this.readers.length === 0) {
|
|
27
|
+
this.context.logger.error('No valid chatbot databases found');
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
async collect() {
|
|
33
|
+
const allItems = [];
|
|
34
|
+
for (const reader of this.readers) {
|
|
35
|
+
try {
|
|
36
|
+
const items = reader.read();
|
|
37
|
+
allItems.push(...items);
|
|
38
|
+
this.context.logger.debug(`Collected ${items.length} chats from ${reader.clientType}`);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
this.context.logger.error(`Failed to collect from ${reader.clientType}`, error);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Sort by last reply time descending
|
|
45
|
+
allItems.sort((a, b) => new Date(b.session.lastReplyAt).getTime() - new Date(a.session.lastReplyAt).getTime());
|
|
46
|
+
return {
|
|
47
|
+
sourceType: this.type,
|
|
48
|
+
success: true,
|
|
49
|
+
itemsCollected: allItems.length,
|
|
50
|
+
items: allItems.map((item) => ({
|
|
51
|
+
sourceType: this.type,
|
|
52
|
+
timestamp: new Date(item.session.lastReplyAt),
|
|
53
|
+
data: item,
|
|
54
|
+
})),
|
|
55
|
+
collectedAt: new Date(),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
createReader(client, context) {
|
|
59
|
+
switch (client) {
|
|
60
|
+
case 'chatwise':
|
|
61
|
+
return new ChatWiseReader(context);
|
|
62
|
+
default:
|
|
63
|
+
this.context.logger.warn(`Unknown chatbot client: ${client}`);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ChatbotType, ChatSession, ChatMessage, ChatHistoryItem } from '../types.js';
|
|
2
|
+
import type { Logger } from '../../../utils/logger.js';
|
|
3
|
+
export interface ReaderContext {
|
|
4
|
+
logger: Logger;
|
|
5
|
+
sinceDays: number;
|
|
6
|
+
includeContent: boolean;
|
|
7
|
+
maxMessagesPerChat?: number;
|
|
8
|
+
excludeModels?: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare abstract class ChatbotReader {
|
|
11
|
+
abstract readonly clientType: ChatbotType;
|
|
12
|
+
protected context: ReaderContext;
|
|
13
|
+
constructor(context: ReaderContext);
|
|
14
|
+
abstract getDbPath(): string | null;
|
|
15
|
+
abstract getChatQuery(): string;
|
|
16
|
+
abstract getMessageQuery(): string;
|
|
17
|
+
abstract parseChatRow(row: unknown): ChatSession | null;
|
|
18
|
+
abstract parseMessageRow(row: unknown): ChatMessage | null;
|
|
19
|
+
read(): ChatHistoryItem[];
|
|
20
|
+
hasValidDatabase(): boolean;
|
|
21
|
+
private readFromDb;
|
|
22
|
+
private getMessagesForChat;
|
|
23
|
+
private isModelExcluded;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/sources/chatbot/readers/base.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,8BAAsB,aAAa;IACjC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;IAE1C,SAAS,CAAC,OAAO,EAAE,aAAa,CAAC;gBAErB,OAAO,EAAE,aAAa;IAIlC,QAAQ,CAAC,SAAS,IAAI,MAAM,GAAG,IAAI;IACnC,QAAQ,CAAC,YAAY,IAAI,MAAM;IAC/B,QAAQ,CAAC,eAAe,IAAI,MAAM;IAClC,QAAQ,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI;IACvD,QAAQ,CAAC,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI;IAE1D,IAAI,IAAI,eAAe,EAAE;IAUzB,gBAAgB,IAAI,OAAO;IAK3B,OAAO,CAAC,UAAU;IAiElB,OAAO,CAAC,kBAAkB;IAiC1B,OAAO,CAAC,eAAe;CAQxB"}
|