@pellux/goodvibes-sdk 0.25.21 → 0.26.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/dist/_internal/contracts/artifacts/operator-contract.json +5000 -149
- package/dist/_internal/contracts/generated/foundation-client-types.d.ts +83 -15
- package/dist/_internal/contracts/generated/foundation-client-types.d.ts.map +1 -1
- package/dist/_internal/contracts/generated/foundation-metadata.d.ts +2 -2
- package/dist/_internal/contracts/generated/foundation-metadata.js +2 -2
- package/dist/_internal/contracts/generated/operator-contract.d.ts.map +1 -1
- package/dist/_internal/contracts/generated/operator-contract.js +5000 -149
- package/dist/_internal/contracts/generated/operator-method-ids.d.ts +1 -1
- package/dist/_internal/contracts/generated/operator-method-ids.d.ts.map +1 -1
- package/dist/_internal/contracts/generated/operator-method-ids.js +18 -0
- package/dist/_internal/daemon/context.d.ts +1 -0
- package/dist/_internal/daemon/context.d.ts.map +1 -1
- package/dist/_internal/daemon/knowledge-route-types.d.ts +1 -0
- package/dist/_internal/daemon/knowledge-route-types.d.ts.map +1 -1
- package/dist/_internal/daemon/knowledge-routes.d.ts +1 -1
- package/dist/_internal/daemon/knowledge-routes.d.ts.map +1 -1
- package/dist/_internal/daemon/knowledge-routes.js +30 -0
- package/dist/_internal/daemon/operator.d.ts +1 -1
- package/dist/_internal/daemon/operator.d.ts.map +1 -1
- package/dist/_internal/daemon/operator.js +2 -0
- package/dist/_internal/platform/control-plane/method-catalog-control-automation.js +7 -7
- package/dist/_internal/platform/control-plane/method-catalog-control-core.d.ts.map +1 -1
- package/dist/_internal/platform/control-plane/method-catalog-control-core.js +4 -9
- package/dist/_internal/platform/control-plane/method-catalog-homegraph.d.ts +3 -0
- package/dist/_internal/platform/control-plane/method-catalog-homegraph.d.ts.map +1 -0
- package/dist/_internal/platform/control-plane/method-catalog-homegraph.js +223 -0
- package/dist/_internal/platform/control-plane/method-catalog-knowledge.d.ts.map +1 -1
- package/dist/_internal/platform/control-plane/method-catalog-knowledge.js +23 -1
- package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.d.ts +15 -1
- package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.d.ts.map +1 -1
- package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.js +118 -0
- package/dist/_internal/platform/daemon/facade-composition.d.ts.map +1 -1
- package/dist/_internal/platform/daemon/facade-composition.js +2 -0
- package/dist/_internal/platform/daemon/facade-types.d.ts +2 -1
- package/dist/_internal/platform/daemon/facade-types.d.ts.map +1 -1
- package/dist/_internal/platform/daemon/http/home-graph-routes.d.ts +18 -0
- package/dist/_internal/platform/daemon/http/home-graph-routes.d.ts.map +1 -0
- package/dist/_internal/platform/daemon/http/home-graph-routes.js +108 -0
- package/dist/_internal/platform/daemon/http/router-route-contexts.d.ts.map +1 -1
- package/dist/_internal/platform/daemon/http/router-route-contexts.js +1 -0
- package/dist/_internal/platform/daemon/http/router.d.ts +4 -1
- package/dist/_internal/platform/daemon/http/router.d.ts.map +1 -1
- package/dist/_internal/platform/daemon/http/router.js +16 -0
- package/dist/_internal/platform/daemon/types.d.ts +2 -1
- package/dist/_internal/platform/daemon/types.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/browser-history/discover.d.ts +3 -0
- package/dist/_internal/platform/knowledge/browser-history/discover.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/browser-history/discover.js +88 -0
- package/dist/_internal/platform/knowledge/browser-history/index.d.ts +7 -0
- package/dist/_internal/platform/knowledge/browser-history/index.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/browser-history/index.js +4 -0
- package/dist/_internal/platform/knowledge/browser-history/ingest.d.ts +12 -0
- package/dist/_internal/platform/knowledge/browser-history/ingest.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/browser-history/ingest.js +275 -0
- package/dist/_internal/platform/knowledge/browser-history/locked-db.d.ts +7 -0
- package/dist/_internal/platform/knowledge/browser-history/locked-db.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/browser-history/locked-db.js +38 -0
- package/dist/_internal/platform/knowledge/browser-history/paths.d.ts +15 -0
- package/dist/_internal/platform/knowledge/browser-history/paths.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/browser-history/paths.js +125 -0
- package/dist/_internal/platform/knowledge/browser-history/readers.d.ts +8 -0
- package/dist/_internal/platform/knowledge/browser-history/readers.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/browser-history/readers.js +374 -0
- package/dist/_internal/platform/knowledge/browser-history/types.d.ts +50 -0
- package/dist/_internal/platform/knowledge/browser-history/types.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/browser-history/types.js +1 -0
- package/dist/_internal/platform/knowledge/consolidation.js +2 -0
- package/dist/_internal/platform/knowledge/extractors.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/extractors.js +31 -0
- package/dist/_internal/platform/knowledge/graphql-schema.d.ts +1 -1
- package/dist/_internal/platform/knowledge/graphql-schema.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/graphql-schema.js +5 -5
- package/dist/_internal/platform/knowledge/graphql.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/graphql.js +16 -5
- package/dist/_internal/platform/knowledge/home-graph/helpers.d.ts +46 -0
- package/dist/_internal/platform/knowledge/home-graph/helpers.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/helpers.js +230 -0
- package/dist/_internal/platform/knowledge/home-graph/index.d.ts +4 -0
- package/dist/_internal/platform/knowledge/home-graph/index.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/index.js +2 -0
- package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts +25 -0
- package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/rendering.js +139 -0
- package/dist/_internal/platform/knowledge/home-graph/service.d.ts +82 -0
- package/dist/_internal/platform/knowledge/home-graph/service.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/service.js +654 -0
- package/dist/_internal/platform/knowledge/home-graph/state.d.ts +24 -0
- package/dist/_internal/platform/knowledge/home-graph/state.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/state.js +96 -0
- package/dist/_internal/platform/knowledge/home-graph/types.d.ts +206 -0
- package/dist/_internal/platform/knowledge/home-graph/types.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/home-graph/types.js +33 -0
- package/dist/_internal/platform/knowledge/html-readability.d.ts +13 -0
- package/dist/_internal/platform/knowledge/html-readability.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/html-readability.js +66 -0
- package/dist/_internal/platform/knowledge/index.d.ts +6 -0
- package/dist/_internal/platform/knowledge/index.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/index.js +3 -0
- package/dist/_internal/platform/knowledge/internal.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/internal.js +1 -0
- package/dist/_internal/platform/knowledge/knowledge-api.d.ts +2 -0
- package/dist/_internal/platform/knowledge/knowledge-api.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/knowledge-api.js +1 -0
- package/dist/_internal/platform/knowledge/lint.js +1 -0
- package/dist/_internal/platform/knowledge/scheduling.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/scheduling.js +1 -0
- package/dist/_internal/platform/knowledge/service.d.ts +4 -0
- package/dist/_internal/platform/knowledge/service.d.ts.map +1 -1
- package/dist/_internal/platform/knowledge/service.js +15 -0
- package/dist/_internal/platform/knowledge/spaces.d.ts +19 -0
- package/dist/_internal/platform/knowledge/spaces.d.ts.map +1 -0
- package/dist/_internal/platform/knowledge/spaces.js +54 -0
- package/dist/_internal/platform/knowledge/types.d.ts +3 -3
- package/dist/_internal/platform/knowledge/types.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/services.d.ts +2 -1
- package/dist/_internal/platform/runtime/services.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/services.js +3 -1
- package/dist/_internal/platform/version.js +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { emitKnowledgeIngestCompleted, emitKnowledgeIngestFailed, emitKnowledgeIngestStarted, } from '../../runtime/emitters/index.js';
|
|
3
|
+
import { summarizeError } from '../../utils/error-display.js';
|
|
4
|
+
import { compileKnowledgeSource } from '../ingest-compile.js';
|
|
5
|
+
import { canonicalizeUri, estimateTokens, isHttpUri, mergeTags, slugify } from '../internal.js';
|
|
6
|
+
import { discoverBrowserKnowledgeProfiles } from './discover.js';
|
|
7
|
+
import { readBrowserKnowledgeProfile } from './readers.js';
|
|
8
|
+
function timestampForEntry(entry) {
|
|
9
|
+
return entry.sourceKind === 'history' ? entry.visitedAtMs : entry.addedAtMs;
|
|
10
|
+
}
|
|
11
|
+
function hashAggregate(aggregate) {
|
|
12
|
+
return createHash('sha256')
|
|
13
|
+
.update(JSON.stringify(aggregate.entries.map((entry) => ({
|
|
14
|
+
sourceKind: entry.sourceKind,
|
|
15
|
+
url: entry.url,
|
|
16
|
+
browser: entry.browser,
|
|
17
|
+
profilePath: entry.profilePath,
|
|
18
|
+
rawId: entry.rawId,
|
|
19
|
+
recordedAt: timestampForEntry(entry),
|
|
20
|
+
}))))
|
|
21
|
+
.digest('hex');
|
|
22
|
+
}
|
|
23
|
+
function sourceTypeForAggregate(aggregate) {
|
|
24
|
+
return aggregate.sourceKinds.includes('bookmark') ? 'bookmark' : 'history';
|
|
25
|
+
}
|
|
26
|
+
function titleForAggregate(aggregate) {
|
|
27
|
+
return aggregate.entries.find((entry) => entry.title)?.title
|
|
28
|
+
?? aggregate.entries[0]?.url
|
|
29
|
+
?? aggregate.canonicalUri;
|
|
30
|
+
}
|
|
31
|
+
function folderForAggregate(aggregate) {
|
|
32
|
+
return aggregate.folders[0] ?? `/browser/${aggregate.browsers[0] ?? 'local'}`;
|
|
33
|
+
}
|
|
34
|
+
function tagsForAggregate(aggregate) {
|
|
35
|
+
return mergeTags([
|
|
36
|
+
'browser',
|
|
37
|
+
...aggregate.browsers,
|
|
38
|
+
...aggregate.sourceKinds.map((kind) => kind === 'history' ? 'browser-history' : 'browser-bookmark'),
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
function metadataForAggregate(aggregate) {
|
|
42
|
+
return {
|
|
43
|
+
browserKnowledge: true,
|
|
44
|
+
browserSourceKinds: [...aggregate.sourceKinds],
|
|
45
|
+
browserKinds: [...aggregate.browsers],
|
|
46
|
+
browserProfiles: [...aggregate.profileKeys],
|
|
47
|
+
browserFolders: [...aggregate.folders],
|
|
48
|
+
browserObservationCount: aggregate.entries.length,
|
|
49
|
+
browserVisitCount: aggregate.visitCount,
|
|
50
|
+
...(typeof aggregate.firstRecordedAt === 'number' ? { browserFirstRecordedAt: aggregate.firstRecordedAt } : {}),
|
|
51
|
+
...(typeof aggregate.lastRecordedAt === 'number' ? { browserLastRecordedAt: aggregate.lastRecordedAt } : {}),
|
|
52
|
+
browserObservations: aggregate.entries.slice(0, 32).map((entry) => ({
|
|
53
|
+
sourceKind: entry.sourceKind,
|
|
54
|
+
browser: entry.browser,
|
|
55
|
+
browserFamily: entry.family,
|
|
56
|
+
profileName: entry.profileName,
|
|
57
|
+
profilePath: entry.profilePath,
|
|
58
|
+
title: entry.title,
|
|
59
|
+
rawId: entry.rawId,
|
|
60
|
+
recordedAt: timestampForEntry(entry),
|
|
61
|
+
...(entry.sourceKind === 'history' ? {
|
|
62
|
+
visitCount: entry.visitCount,
|
|
63
|
+
transition: entry.transition,
|
|
64
|
+
} : {
|
|
65
|
+
folderPath: entry.folderPath,
|
|
66
|
+
}),
|
|
67
|
+
})),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function describeAggregate(aggregate) {
|
|
71
|
+
const parts = [
|
|
72
|
+
aggregate.sourceKinds.includes('bookmark') && aggregate.sourceKinds.includes('history')
|
|
73
|
+
? 'Browser-local page observed in bookmarks and history.'
|
|
74
|
+
: aggregate.sourceKinds.includes('bookmark')
|
|
75
|
+
? 'Browser-local page observed in bookmarks.'
|
|
76
|
+
: 'Browser-local page observed in browsing history.',
|
|
77
|
+
`Browsers: ${aggregate.browsers.join(', ')}.`,
|
|
78
|
+
`Profiles: ${aggregate.profileKeys.join(', ')}.`,
|
|
79
|
+
aggregate.visitCount > 0 ? `Visit count: ${aggregate.visitCount}.` : '',
|
|
80
|
+
typeof aggregate.lastRecordedAt === 'number' ? `Last recorded: ${new Date(aggregate.lastRecordedAt).toISOString()}.` : '',
|
|
81
|
+
aggregate.folders.length ? `Folders: ${aggregate.folders.slice(0, 4).join(', ')}.` : '',
|
|
82
|
+
`URL: ${aggregate.canonicalUri}`,
|
|
83
|
+
].filter(Boolean);
|
|
84
|
+
return parts.join(' ');
|
|
85
|
+
}
|
|
86
|
+
function extractionForAggregate(aggregate, source) {
|
|
87
|
+
const summary = describeAggregate(aggregate);
|
|
88
|
+
return {
|
|
89
|
+
extractorId: 'browser-history',
|
|
90
|
+
format: 'text',
|
|
91
|
+
title: titleForAggregate(aggregate),
|
|
92
|
+
summary,
|
|
93
|
+
excerpt: summary,
|
|
94
|
+
sections: mergeTags([
|
|
95
|
+
...aggregate.sourceKinds.map((kind) => `browser ${kind}`),
|
|
96
|
+
...aggregate.browsers,
|
|
97
|
+
...aggregate.folders,
|
|
98
|
+
]).slice(0, 24),
|
|
99
|
+
links: [aggregate.canonicalUri],
|
|
100
|
+
estimatedTokens: estimateTokens(summary, aggregate.canonicalUri, titleForAggregate(aggregate)),
|
|
101
|
+
structure: {
|
|
102
|
+
sourceKinds: [...aggregate.sourceKinds],
|
|
103
|
+
browsers: [...aggregate.browsers],
|
|
104
|
+
profiles: [...aggregate.profileKeys],
|
|
105
|
+
canonicalUri: source.canonicalUri,
|
|
106
|
+
},
|
|
107
|
+
metadata: metadataForAggregate(aggregate),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function aggregateBrowserEntries(entries) {
|
|
111
|
+
const buckets = new Map();
|
|
112
|
+
for (const entry of entries) {
|
|
113
|
+
if (!isHttpUri(entry.url))
|
|
114
|
+
continue;
|
|
115
|
+
const canonicalUri = canonicalizeUri(entry.url) ?? entry.url;
|
|
116
|
+
const bucket = buckets.get(canonicalUri) ?? [];
|
|
117
|
+
bucket.push(entry);
|
|
118
|
+
buckets.set(canonicalUri, bucket);
|
|
119
|
+
}
|
|
120
|
+
return [...buckets.entries()].map(([canonicalUri, bucket]) => {
|
|
121
|
+
const sorted = [...bucket].sort((a, b) => (timestampForEntry(b) ?? 0) - (timestampForEntry(a) ?? 0));
|
|
122
|
+
const timestamps = sorted.map(timestampForEntry).filter((value) => typeof value === 'number');
|
|
123
|
+
const kinds = new Set(sorted.map((entry) => entry.sourceKind));
|
|
124
|
+
const sourceKinds = ['history', 'bookmark'].filter((kind) => kinds.has(kind));
|
|
125
|
+
const browsers = mergeTags(sorted.map((entry) => entry.browser));
|
|
126
|
+
const profileKeys = mergeTags(sorted.map((entry) => `${entry.browser}:${entry.profileName}`));
|
|
127
|
+
const folders = mergeTags(sorted.flatMap((entry) => entry.sourceKind === 'bookmark' && entry.folderPath ? [entry.folderPath] : []));
|
|
128
|
+
const visitCount = sorted.reduce((sum, entry) => (entry.sourceKind === 'history' ? sum + Math.max(1, entry.visitCount ?? 1) : sum), 0);
|
|
129
|
+
return {
|
|
130
|
+
canonicalUri,
|
|
131
|
+
entries: sorted,
|
|
132
|
+
sourceKinds,
|
|
133
|
+
browsers,
|
|
134
|
+
profileKeys,
|
|
135
|
+
folders,
|
|
136
|
+
...(timestamps.length ? { firstRecordedAt: Math.min(...timestamps), lastRecordedAt: Math.max(...timestamps) } : {}),
|
|
137
|
+
visitCount,
|
|
138
|
+
};
|
|
139
|
+
}).sort((a, b) => (b.lastRecordedAt ?? 0) - (a.lastRecordedAt ?? 0));
|
|
140
|
+
}
|
|
141
|
+
async function upsertAggregate(context, aggregate, options = {}) {
|
|
142
|
+
const existing = context.store.getSourceByCanonicalUri(aggregate.canonicalUri);
|
|
143
|
+
const sourceType = existing?.sourceType ?? sourceTypeForAggregate(aggregate);
|
|
144
|
+
const connectorId = existing?.connectorId ?? options.connectorId ?? 'browser-local';
|
|
145
|
+
const summary = describeAggregate(aggregate);
|
|
146
|
+
const source = await context.store.upsertSource({
|
|
147
|
+
...(existing ? { id: existing.id } : {}),
|
|
148
|
+
connectorId,
|
|
149
|
+
sourceType,
|
|
150
|
+
title: existing?.title ?? titleForAggregate(aggregate),
|
|
151
|
+
sourceUri: existing?.sourceUri ?? aggregate.canonicalUri,
|
|
152
|
+
canonicalUri: aggregate.canonicalUri,
|
|
153
|
+
summary: existing?.summary ?? summary,
|
|
154
|
+
description: existing?.description ?? summary,
|
|
155
|
+
tags: mergeTags(existing?.tags, tagsForAggregate(aggregate)),
|
|
156
|
+
folderPath: existing?.folderPath ?? folderForAggregate(aggregate),
|
|
157
|
+
status: 'indexed',
|
|
158
|
+
artifactId: existing?.artifactId,
|
|
159
|
+
contentHash: existing?.contentHash ?? hashAggregate(aggregate),
|
|
160
|
+
lastCrawledAt: existing?.lastCrawledAt ?? Date.now(),
|
|
161
|
+
sessionId: options.sessionId ?? existing?.sessionId,
|
|
162
|
+
metadata: {
|
|
163
|
+
...(existing?.metadata ?? {}),
|
|
164
|
+
...metadataForAggregate(aggregate),
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
const existingExtraction = context.store.getExtractionBySourceId(source.id);
|
|
168
|
+
const extraction = existingExtraction ?? await context.store.upsertExtraction({
|
|
169
|
+
sourceId: source.id,
|
|
170
|
+
...extractionForAggregate(aggregate, source),
|
|
171
|
+
});
|
|
172
|
+
for (const entry of aggregate.entries) {
|
|
173
|
+
const browserNode = await context.store.upsertNode({
|
|
174
|
+
kind: 'source_group',
|
|
175
|
+
slug: slugify(`browser-${entry.browser}-${entry.profileName}`),
|
|
176
|
+
title: `${entry.browser} ${entry.profileName}`,
|
|
177
|
+
summary: `Local ${entry.browser} browser profile imported from ${entry.profilePath}.`,
|
|
178
|
+
aliases: [entry.browser, entry.profileName],
|
|
179
|
+
status: 'active',
|
|
180
|
+
confidence: 85,
|
|
181
|
+
metadata: {
|
|
182
|
+
browser: entry.browser,
|
|
183
|
+
browserFamily: entry.family,
|
|
184
|
+
browserProfilePath: entry.profilePath,
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
await context.store.upsertEdge({
|
|
188
|
+
fromKind: 'source',
|
|
189
|
+
fromId: source.id,
|
|
190
|
+
toKind: 'node',
|
|
191
|
+
toId: browserNode.id,
|
|
192
|
+
relation: entry.sourceKind === 'history' ? 'visited_in_browser_profile' : 'bookmarked_in_browser_profile',
|
|
193
|
+
weight: timestampForEntry(entry) ? 1.2 : 1,
|
|
194
|
+
metadata: {
|
|
195
|
+
sourceKind: entry.sourceKind,
|
|
196
|
+
recordedAt: timestampForEntry(entry),
|
|
197
|
+
browser: entry.browser,
|
|
198
|
+
profileName: entry.profileName,
|
|
199
|
+
...(entry.sourceKind === 'bookmark' && entry.folderPath ? { folderPath: entry.folderPath } : {}),
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
await compileKnowledgeSource(context, source, extraction);
|
|
204
|
+
return source;
|
|
205
|
+
}
|
|
206
|
+
export async function collectBrowserKnowledge(filter = {}) {
|
|
207
|
+
const profiles = await discoverBrowserKnowledgeProfiles(filter);
|
|
208
|
+
const entries = [];
|
|
209
|
+
const errors = [];
|
|
210
|
+
const perProfileLimit = Math.max(1, Math.ceil((filter.limit ?? 1000) / Math.max(1, profiles.length)));
|
|
211
|
+
const sourceKinds = filter.sourceKinds ?? ['history', 'bookmark'];
|
|
212
|
+
for (const profile of profiles) {
|
|
213
|
+
try {
|
|
214
|
+
const found = await readBrowserKnowledgeProfile(profile, {
|
|
215
|
+
limit: perProfileLimit,
|
|
216
|
+
sinceMs: filter.sinceMs,
|
|
217
|
+
sourceKinds,
|
|
218
|
+
});
|
|
219
|
+
entries.push(...found);
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
errors.push(`${profile.browser}/${profile.profileName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
entries.sort((a, b) => (timestampForEntry(b) ?? 0) - (timestampForEntry(a) ?? 0));
|
|
226
|
+
return {
|
|
227
|
+
profiles,
|
|
228
|
+
entries: entries.slice(0, filter.limit ?? entries.length),
|
|
229
|
+
errors,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
export async function ingestBrowserKnowledge(context, options = {}) {
|
|
233
|
+
await context.store.init();
|
|
234
|
+
const collected = await collectBrowserKnowledge(options);
|
|
235
|
+
const aggregates = aggregateBrowserEntries(collected.entries);
|
|
236
|
+
const sources = [];
|
|
237
|
+
const errors = [...collected.errors];
|
|
238
|
+
let imported = 0;
|
|
239
|
+
let failed = 0;
|
|
240
|
+
for (const aggregate of aggregates) {
|
|
241
|
+
try {
|
|
242
|
+
context.emitIfReady((bus, ctx) => emitKnowledgeIngestStarted(bus, ctx, {
|
|
243
|
+
sourceId: aggregate.canonicalUri,
|
|
244
|
+
connectorId: options.connectorId ?? 'browser-local',
|
|
245
|
+
sourceType: sourceTypeForAggregate(aggregate),
|
|
246
|
+
uri: aggregate.canonicalUri,
|
|
247
|
+
}), options.sessionId);
|
|
248
|
+
const source = await upsertAggregate(context, aggregate, options);
|
|
249
|
+
sources.push(source);
|
|
250
|
+
imported += 1;
|
|
251
|
+
context.emitIfReady((bus, ctx) => emitKnowledgeIngestCompleted(bus, ctx, {
|
|
252
|
+
sourceId: source.id,
|
|
253
|
+
status: source.status,
|
|
254
|
+
title: source.title,
|
|
255
|
+
}), source.sessionId);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
failed += 1;
|
|
259
|
+
errors.push(`${aggregate.canonicalUri}: ${summarizeError(error)}`);
|
|
260
|
+
context.emitIfReady((bus, ctx) => emitKnowledgeIngestFailed(bus, ctx, {
|
|
261
|
+
sourceId: aggregate.canonicalUri,
|
|
262
|
+
error: summarizeError(error),
|
|
263
|
+
}), options.sessionId);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
await context.syncReviewedMemory();
|
|
267
|
+
await context.lint();
|
|
268
|
+
return {
|
|
269
|
+
imported,
|
|
270
|
+
failed,
|
|
271
|
+
sources,
|
|
272
|
+
errors,
|
|
273
|
+
profiles: collected.profiles,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface LockedBrowserDbCopy {
|
|
2
|
+
readonly copiedDbPath: string;
|
|
3
|
+
readonly tempDir: string;
|
|
4
|
+
cleanup(): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export declare function copyLockedBrowserSqlite(sourcePath: string): Promise<LockedBrowserDbCopy>;
|
|
7
|
+
//# sourceMappingURL=locked-db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locked-db.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/browser-history/locked-db.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAWD,wBAAsB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA0B9F"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { access, copyFile, mkdtemp, rm } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { basename, join } from 'node:path';
|
|
4
|
+
async function exists(path) {
|
|
5
|
+
try {
|
|
6
|
+
await access(path);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export async function copyLockedBrowserSqlite(sourcePath) {
|
|
14
|
+
if (!(await exists(sourcePath))) {
|
|
15
|
+
throw new Error(`Browser SQLite file does not exist: ${sourcePath}`);
|
|
16
|
+
}
|
|
17
|
+
const tempDir = await mkdtemp(join(tmpdir(), 'goodvibes-browser-db-'));
|
|
18
|
+
const baseName = basename(sourcePath);
|
|
19
|
+
const copiedDbPath = join(tempDir, baseName);
|
|
20
|
+
await copyFile(sourcePath, copiedDbPath);
|
|
21
|
+
for (const suffix of ['-wal', '-shm']) {
|
|
22
|
+
const source = `${sourcePath}${suffix}`;
|
|
23
|
+
if (await exists(source)) {
|
|
24
|
+
await copyFile(source, join(tempDir, `${baseName}${suffix}`));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
let cleaned = false;
|
|
28
|
+
return {
|
|
29
|
+
copiedDbPath,
|
|
30
|
+
tempDir,
|
|
31
|
+
async cleanup() {
|
|
32
|
+
if (cleaned)
|
|
33
|
+
return;
|
|
34
|
+
cleaned = true;
|
|
35
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BrowserKnowledgeFamily, BrowserKnowledgeKind } from './types.js';
|
|
2
|
+
interface BrowserPathEntry {
|
|
3
|
+
readonly family: BrowserKnowledgeFamily;
|
|
4
|
+
readonly paths: Partial<Record<'linux' | 'darwin', readonly string[]>>;
|
|
5
|
+
readonly profileGlob: string;
|
|
6
|
+
readonly historyFile: string;
|
|
7
|
+
readonly bookmarksFile: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const BROWSER_PATHS: Record<BrowserKnowledgeKind, BrowserPathEntry>;
|
|
10
|
+
export declare function listBrowserKinds(): BrowserKnowledgeKind[];
|
|
11
|
+
export declare function getBrowserPathEntry(kind: BrowserKnowledgeKind): BrowserPathEntry;
|
|
12
|
+
export declare function expandBrowserRoots(kind: BrowserKnowledgeKind, homeOverride?: string): string[];
|
|
13
|
+
export declare function profileGlobToRegex(kind: BrowserKnowledgeKind): RegExp;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/browser-history/paths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAE/E,UAAU,gBAAgB;IACxB,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IACvE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAKD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,oBAAoB,EAAE,gBAAgB,CA0GxE,CAAC;AAEF,wBAAgB,gBAAgB,IAAI,oBAAoB,EAAE,CAEzD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAEhF;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,oBAAoB,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAI9F;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { normalize } from 'node:path';
|
|
3
|
+
const CHROMIUM_PROFILES = '(Default|Profile .+|Guest Profile)';
|
|
4
|
+
const GECKO_PROFILES = '(.+\\.default|.+\\.default-release|.+\\.dev-edition-default|[a-z0-9]+\\..+)';
|
|
5
|
+
export const BROWSER_PATHS = {
|
|
6
|
+
chrome: {
|
|
7
|
+
family: 'chromium',
|
|
8
|
+
paths: { linux: ['~/.config/google-chrome', '~/.config/google-chrome-beta'], darwin: ['~/Library/Application Support/Google/Chrome'] },
|
|
9
|
+
profileGlob: CHROMIUM_PROFILES,
|
|
10
|
+
historyFile: 'History',
|
|
11
|
+
bookmarksFile: 'Bookmarks',
|
|
12
|
+
},
|
|
13
|
+
chromium: {
|
|
14
|
+
family: 'chromium',
|
|
15
|
+
paths: { linux: ['~/.config/chromium'], darwin: ['~/Library/Application Support/Chromium'] },
|
|
16
|
+
profileGlob: CHROMIUM_PROFILES,
|
|
17
|
+
historyFile: 'History',
|
|
18
|
+
bookmarksFile: 'Bookmarks',
|
|
19
|
+
},
|
|
20
|
+
brave: {
|
|
21
|
+
family: 'chromium',
|
|
22
|
+
paths: { linux: ['~/.config/BraveSoftware/Brave-Browser'], darwin: ['~/Library/Application Support/BraveSoftware/Brave-Browser'] },
|
|
23
|
+
profileGlob: CHROMIUM_PROFILES,
|
|
24
|
+
historyFile: 'History',
|
|
25
|
+
bookmarksFile: 'Bookmarks',
|
|
26
|
+
},
|
|
27
|
+
edge: {
|
|
28
|
+
family: 'chromium',
|
|
29
|
+
paths: { linux: ['~/.config/microsoft-edge', '~/.config/microsoft-edge-dev'], darwin: ['~/Library/Application Support/Microsoft Edge'] },
|
|
30
|
+
profileGlob: CHROMIUM_PROFILES,
|
|
31
|
+
historyFile: 'History',
|
|
32
|
+
bookmarksFile: 'Bookmarks',
|
|
33
|
+
},
|
|
34
|
+
vivaldi: {
|
|
35
|
+
family: 'chromium',
|
|
36
|
+
paths: { linux: ['~/.config/vivaldi'], darwin: ['~/Library/Application Support/Vivaldi'] },
|
|
37
|
+
profileGlob: CHROMIUM_PROFILES,
|
|
38
|
+
historyFile: 'History',
|
|
39
|
+
bookmarksFile: 'Bookmarks',
|
|
40
|
+
},
|
|
41
|
+
arc: {
|
|
42
|
+
family: 'chromium',
|
|
43
|
+
paths: { darwin: ['~/Library/Application Support/Arc/User Data'] },
|
|
44
|
+
profileGlob: CHROMIUM_PROFILES,
|
|
45
|
+
historyFile: 'History',
|
|
46
|
+
bookmarksFile: 'Bookmarks',
|
|
47
|
+
},
|
|
48
|
+
opera: {
|
|
49
|
+
family: 'chromium',
|
|
50
|
+
paths: { linux: ['~/.config/opera'], darwin: ['~/Library/Application Support/com.operasoftware.Opera'] },
|
|
51
|
+
profileGlob: CHROMIUM_PROFILES,
|
|
52
|
+
historyFile: 'History',
|
|
53
|
+
bookmarksFile: 'Bookmarks',
|
|
54
|
+
},
|
|
55
|
+
firefox: {
|
|
56
|
+
family: 'gecko',
|
|
57
|
+
paths: { linux: ['~/.mozilla/firefox', '~/snap/firefox/common/.mozilla/firefox', '~/.var/app/org.mozilla.firefox/.mozilla/firefox'], darwin: ['~/Library/Application Support/Firefox/Profiles'] },
|
|
58
|
+
profileGlob: GECKO_PROFILES,
|
|
59
|
+
historyFile: 'places.sqlite',
|
|
60
|
+
bookmarksFile: 'places.sqlite',
|
|
61
|
+
},
|
|
62
|
+
zen: {
|
|
63
|
+
family: 'gecko',
|
|
64
|
+
paths: { linux: ['~/.zen'], darwin: ['~/Library/Application Support/zen/Profiles'] },
|
|
65
|
+
profileGlob: '(.+\\.default|.+\\.default-release|[a-z0-9]+\\..+)',
|
|
66
|
+
historyFile: 'places.sqlite',
|
|
67
|
+
bookmarksFile: 'places.sqlite',
|
|
68
|
+
},
|
|
69
|
+
librewolf: {
|
|
70
|
+
family: 'gecko',
|
|
71
|
+
paths: { linux: ['~/.librewolf'], darwin: ['~/Library/Application Support/LibreWolf/Profiles'] },
|
|
72
|
+
profileGlob: '(.+\\.default|.+\\.default-release|[a-z0-9]+\\..+)',
|
|
73
|
+
historyFile: 'places.sqlite',
|
|
74
|
+
bookmarksFile: 'places.sqlite',
|
|
75
|
+
},
|
|
76
|
+
waterfox: {
|
|
77
|
+
family: 'gecko',
|
|
78
|
+
paths: { linux: ['~/.waterfox'], darwin: ['~/Library/Application Support/Waterfox/Profiles'] },
|
|
79
|
+
profileGlob: '(.+\\.default|.+\\.default-release|[a-z0-9]+\\..+)',
|
|
80
|
+
historyFile: 'places.sqlite',
|
|
81
|
+
bookmarksFile: 'places.sqlite',
|
|
82
|
+
},
|
|
83
|
+
floorp: {
|
|
84
|
+
family: 'gecko',
|
|
85
|
+
paths: { linux: ['~/.floorp'], darwin: ['~/Library/Application Support/Floorp/Profiles'] },
|
|
86
|
+
profileGlob: '(.+\\.default|.+\\.default-release|[a-z0-9]+\\..+)',
|
|
87
|
+
historyFile: 'places.sqlite',
|
|
88
|
+
bookmarksFile: 'places.sqlite',
|
|
89
|
+
},
|
|
90
|
+
safari: {
|
|
91
|
+
family: 'webkit',
|
|
92
|
+
paths: { darwin: ['~/Library/Safari'] },
|
|
93
|
+
profileGlob: '(Default)',
|
|
94
|
+
historyFile: 'History.db',
|
|
95
|
+
bookmarksFile: 'Bookmarks.plist',
|
|
96
|
+
},
|
|
97
|
+
orion: {
|
|
98
|
+
family: 'webkit',
|
|
99
|
+
paths: { darwin: ['~/Library/Application Support/Orion'] },
|
|
100
|
+
profileGlob: '(Default|Profile .+)',
|
|
101
|
+
historyFile: 'History.db',
|
|
102
|
+
bookmarksFile: 'Bookmarks.plist',
|
|
103
|
+
},
|
|
104
|
+
epiphany: {
|
|
105
|
+
family: 'webkit',
|
|
106
|
+
paths: { linux: ['~/.local/share/epiphany', '~/.var/app/org.gnome.Epiphany/data/epiphany'] },
|
|
107
|
+
profileGlob: '(Default)',
|
|
108
|
+
historyFile: 'ephy-history.db',
|
|
109
|
+
bookmarksFile: 'bookmarks.gvdb',
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
export function listBrowserKinds() {
|
|
113
|
+
return Object.keys(BROWSER_PATHS);
|
|
114
|
+
}
|
|
115
|
+
export function getBrowserPathEntry(kind) {
|
|
116
|
+
return BROWSER_PATHS[kind];
|
|
117
|
+
}
|
|
118
|
+
export function expandBrowserRoots(kind, homeOverride) {
|
|
119
|
+
const platform = process.platform === 'darwin' ? 'darwin' : 'linux';
|
|
120
|
+
const home = homeOverride ?? homedir();
|
|
121
|
+
return (BROWSER_PATHS[kind].paths[platform] ?? []).map((entry) => normalize(entry.replace(/^~/, home)));
|
|
122
|
+
}
|
|
123
|
+
export function profileGlobToRegex(kind) {
|
|
124
|
+
return new RegExp(`^(?:${BROWSER_PATHS[kind].profileGlob})$`);
|
|
125
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BrowserKnowledgeEntry, BrowserKnowledgeProfile } from './types.js';
|
|
2
|
+
export interface BrowserKnowledgeReadOptions {
|
|
3
|
+
readonly limit?: number;
|
|
4
|
+
readonly sinceMs?: number;
|
|
5
|
+
readonly sourceKinds?: readonly ('history' | 'bookmark')[];
|
|
6
|
+
}
|
|
7
|
+
export declare function readBrowserKnowledgeProfile(profile: BrowserKnowledgeProfile, options?: BrowserKnowledgeReadOptions): Promise<BrowserKnowledgeEntry[]>;
|
|
8
|
+
//# sourceMappingURL=readers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readers.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/browser-history/readers.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC,SAAS,GAAG,UAAU,CAAC,EAAE,CAAC;CAC5D;AA8YD,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,uBAAuB,EAChC,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAclC"}
|