brainhub-mcp 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 +201 -0
- package/README.md +84 -0
- package/dist/adapters/claude.d.ts +2 -0
- package/dist/adapters/claude.js +50 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex.d.ts +2 -0
- package/dist/adapters/codex.js +52 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/content.d.ts +6 -0
- package/dist/adapters/content.js +68 -0
- package/dist/adapters/content.js.map +1 -0
- package/dist/adapters/grok.d.ts +2 -0
- package/dist/adapters/grok.js +44 -0
- package/dist/adapters/grok.js.map +1 -0
- package/dist/adapters/index.d.ts +31 -0
- package/dist/adapters/index.js +111 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/jsonl.d.ts +6 -0
- package/dist/adapters/jsonl.js +26 -0
- package/dist/adapters/jsonl.js.map +1 -0
- package/dist/adapters/types.d.ts +10 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/auth/account-status.d.ts +50 -0
- package/dist/auth/account-status.js +59 -0
- package/dist/auth/account-status.js.map +1 -0
- package/dist/auth/google-account.d.ts +21 -0
- package/dist/auth/google-account.js +45 -0
- package/dist/auth/google-account.js.map +1 -0
- package/dist/auth/google-oauth.d.ts +35 -0
- package/dist/auth/google-oauth.js +191 -0
- package/dist/auth/google-oauth.js.map +1 -0
- package/dist/auth/oauth-loopback.d.ts +10 -0
- package/dist/auth/oauth-loopback.js +81 -0
- package/dist/auth/oauth-loopback.js.map +1 -0
- package/dist/auth/official-oauth-client.d.ts +5 -0
- package/dist/auth/official-oauth-client.js +6 -0
- package/dist/auth/official-oauth-client.js.map +1 -0
- package/dist/auth/platform-secrets.d.ts +14 -0
- package/dist/auth/platform-secrets.js +81 -0
- package/dist/auth/platform-secrets.js.map +1 -0
- package/dist/auth/secret-store-factory.d.ts +11 -0
- package/dist/auth/secret-store-factory.js +37 -0
- package/dist/auth/secret-store-factory.js.map +1 -0
- package/dist/auth/secret-store.d.ts +13 -0
- package/dist/auth/secret-store.js +40 -0
- package/dist/auth/secret-store.js.map +1 -0
- package/dist/capture/images.d.ts +11 -0
- package/dist/capture/images.js +27 -0
- package/dist/capture/images.js.map +1 -0
- package/dist/capture/normalize.d.ts +11 -0
- package/dist/capture/normalize.js +43 -0
- package/dist/capture/normalize.js.map +1 -0
- package/dist/capture/redact.d.ts +10 -0
- package/dist/capture/redact.js +60 -0
- package/dist/capture/redact.js.map +1 -0
- package/dist/cli/index.d.ts +20 -0
- package/dist/cli/index.js +781 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/clients/registry.d.ts +24 -0
- package/dist/clients/registry.js +105 -0
- package/dist/clients/registry.js.map +1 -0
- package/dist/domain/config-io.d.ts +15 -0
- package/dist/domain/config-io.js +168 -0
- package/dist/domain/config-io.js.map +1 -0
- package/dist/domain/config.d.ts +74 -0
- package/dist/domain/config.js +130 -0
- package/dist/domain/config.js.map +1 -0
- package/dist/domain/errors.d.ts +6 -0
- package/dist/domain/errors.js +11 -0
- package/dist/domain/errors.js.map +1 -0
- package/dist/domain/session.d.ts +62 -0
- package/dist/domain/session.js +47 -0
- package/dist/domain/session.js.map +1 -0
- package/dist/drive/drive-port.d.ts +51 -0
- package/dist/drive/drive-port.js +2 -0
- package/dist/drive/drive-port.js.map +1 -0
- package/dist/drive/google-drive.d.ts +28 -0
- package/dist/drive/google-drive.js +501 -0
- package/dist/drive/google-drive.js.map +1 -0
- package/dist/drive/memory-drive.d.ts +19 -0
- package/dist/drive/memory-drive.js +148 -0
- package/dist/drive/memory-drive.js.map +1 -0
- package/dist/drive/scoped-drive.d.ts +17 -0
- package/dist/drive/scoped-drive.js +115 -0
- package/dist/drive/scoped-drive.js.map +1 -0
- package/dist/mcp/server.d.ts +55 -0
- package/dist/mcp/server.js +133 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/portrait/obsidian.d.ts +7 -0
- package/dist/portrait/obsidian.js +16 -0
- package/dist/portrait/obsidian.js.map +1 -0
- package/dist/portrait/portrait-service.d.ts +12 -0
- package/dist/portrait/portrait-service.js +18 -0
- package/dist/portrait/portrait-service.js.map +1 -0
- package/dist/portrait/portrait-sync-service.d.ts +21 -0
- package/dist/portrait/portrait-sync-service.js +43 -0
- package/dist/portrait/portrait-sync-service.js.map +1 -0
- package/dist/runtime/command.d.ts +4 -0
- package/dist/runtime/command.js +2 -0
- package/dist/runtime/command.js.map +1 -0
- package/dist/runtime/container.d.ts +72 -0
- package/dist/runtime/container.js +361 -0
- package/dist/runtime/container.js.map +1 -0
- package/dist/scheduler/jobs.d.ts +2 -0
- package/dist/scheduler/jobs.js +7 -0
- package/dist/scheduler/jobs.js.map +1 -0
- package/dist/scheduler/launchd.d.ts +7 -0
- package/dist/scheduler/launchd.js +40 -0
- package/dist/scheduler/launchd.js.map +1 -0
- package/dist/scheduler/manager.d.ts +26 -0
- package/dist/scheduler/manager.js +113 -0
- package/dist/scheduler/manager.js.map +1 -0
- package/dist/search/chunk-text.d.ts +11 -0
- package/dist/search/chunk-text.js +40 -0
- package/dist/search/chunk-text.js.map +1 -0
- package/dist/search/e5-embedder.d.ts +19 -0
- package/dist/search/e5-embedder.js +71 -0
- package/dist/search/e5-embedder.js.map +1 -0
- package/dist/search/embedder.d.ts +8 -0
- package/dist/search/embedder.js +5 -0
- package/dist/search/embedder.js.map +1 -0
- package/dist/search/model-cache.d.ts +7 -0
- package/dist/search/model-cache.js +38 -0
- package/dist/search/model-cache.js.map +1 -0
- package/dist/search/search-service.d.ts +46 -0
- package/dist/search/search-service.js +319 -0
- package/dist/search/search-service.js.map +1 -0
- package/dist/setup/backfill-service.d.ts +33 -0
- package/dist/setup/backfill-service.js +47 -0
- package/dist/setup/backfill-service.js.map +1 -0
- package/dist/setup/setup-service.d.ts +65 -0
- package/dist/setup/setup-service.js +90 -0
- package/dist/setup/setup-service.js.map +1 -0
- package/dist/setup/uninstall-service.d.ts +34 -0
- package/dist/setup/uninstall-service.js +91 -0
- package/dist/setup/uninstall-service.js.map +1 -0
- package/dist/state/sqlite-store.d.ts +19 -0
- package/dist/state/sqlite-store.js +299 -0
- package/dist/state/sqlite-store.js.map +1 -0
- package/dist/state/store.d.ts +52 -0
- package/dist/state/store.js +2 -0
- package/dist/state/store.js.map +1 -0
- package/dist/status/status-service.d.ts +38 -0
- package/dist/status/status-service.js +93 -0
- package/dist/status/status-service.js.map +1 -0
- package/dist/update/update-check-service.d.ts +38 -0
- package/dist/update/update-check-service.js +105 -0
- package/dist/update/update-check-service.js.map +1 -0
- package/dist/upload/lock.d.ts +7 -0
- package/dist/upload/lock.js +68 -0
- package/dist/upload/lock.js.map +1 -0
- package/dist/upload/upload-service.d.ts +36 -0
- package/dist/upload/upload-service.js +360 -0
- package/dist/upload/upload-service.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { type drive_v3 } from "googleapis";
|
|
2
|
+
import { type GoogleOAuthClient } from "../auth/google-oauth.js";
|
|
3
|
+
import { type ConfigSecretStoreFactory } from "../auth/secret-store-factory.js";
|
|
4
|
+
import type { BrainHubConfig, PlatformPaths } from "../domain/config.js";
|
|
5
|
+
import { type SessionSource } from "../domain/session.js";
|
|
6
|
+
import type { DrivePort } from "../drive/drive-port.js";
|
|
7
|
+
import { PortraitService } from "../portrait/portrait-service.js";
|
|
8
|
+
import { PortraitSyncService } from "../portrait/portrait-sync-service.js";
|
|
9
|
+
import { SearchService } from "../search/search-service.js";
|
|
10
|
+
import { type UploadOutput } from "../upload/upload-service.js";
|
|
11
|
+
export declare class BrainHubRuntime {
|
|
12
|
+
#private;
|
|
13
|
+
readonly config: BrainHubConfig;
|
|
14
|
+
readonly paths: PlatformPaths;
|
|
15
|
+
readonly homeDir: string;
|
|
16
|
+
readonly platform: NodeJS.Platform;
|
|
17
|
+
readonly configFile: string;
|
|
18
|
+
readonly executable: string;
|
|
19
|
+
readonly executableArgs: string[];
|
|
20
|
+
constructor(options: {
|
|
21
|
+
config: BrainHubConfig;
|
|
22
|
+
paths: PlatformPaths;
|
|
23
|
+
configFile: string;
|
|
24
|
+
homeDir: string;
|
|
25
|
+
platform: NodeJS.Platform;
|
|
26
|
+
executable: string;
|
|
27
|
+
executableArgs?: string[];
|
|
28
|
+
secretStoreFactory?: ConfigSecretStoreFactory;
|
|
29
|
+
driveFactory?: (auth: GoogleOAuthClient) => drive_v3.Drive;
|
|
30
|
+
});
|
|
31
|
+
drive(interactive?: boolean): Promise<DrivePort>;
|
|
32
|
+
discover(input: {
|
|
33
|
+
sources?: SessionSource[];
|
|
34
|
+
includeSubagents?: boolean;
|
|
35
|
+
modifiedAfter?: Partial<Record<SessionSource, string>>;
|
|
36
|
+
includePaths?: string[];
|
|
37
|
+
}): Promise<import("../adapters/index.js").DiscoveryResult>;
|
|
38
|
+
uploadSessions(input: {
|
|
39
|
+
sources?: SessionSource[];
|
|
40
|
+
includeSubagents?: boolean;
|
|
41
|
+
dryRun?: boolean;
|
|
42
|
+
backfill?: boolean;
|
|
43
|
+
}): Promise<UploadOutput & {
|
|
44
|
+
adapters: object;
|
|
45
|
+
pending: number;
|
|
46
|
+
}>;
|
|
47
|
+
searchService(drive: DrivePort): SearchService;
|
|
48
|
+
searchSessions(input: {
|
|
49
|
+
query: string;
|
|
50
|
+
from?: string;
|
|
51
|
+
to?: string;
|
|
52
|
+
sources?: string[];
|
|
53
|
+
limit?: number;
|
|
54
|
+
}): Promise<import("../search/search-service.js").SearchOutput>;
|
|
55
|
+
getSession(input: {
|
|
56
|
+
source: SessionSource;
|
|
57
|
+
conversationId: string;
|
|
58
|
+
}): Promise<{
|
|
59
|
+
source: SessionSource;
|
|
60
|
+
conversationId: string;
|
|
61
|
+
content: string;
|
|
62
|
+
updatedAt: string;
|
|
63
|
+
}>;
|
|
64
|
+
portraitService(): Promise<PortraitService>;
|
|
65
|
+
portraitSyncService(): Promise<PortraitSyncService>;
|
|
66
|
+
getPortrait(): Promise<{
|
|
67
|
+
portrait: string;
|
|
68
|
+
}>;
|
|
69
|
+
syncPortrait(): Promise<import("../portrait/portrait-sync-service.js").PortraitSyncOutput>;
|
|
70
|
+
hubStatus(): Promise<import("../status/status-service.js").StatusOutput>;
|
|
71
|
+
close(): void;
|
|
72
|
+
}
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { hostname } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { mkdir, readdir, stat } from "node:fs/promises";
|
|
5
|
+
import { google } from "googleapis";
|
|
6
|
+
import { discoverSessions } from "../adapters/index.js";
|
|
7
|
+
import { GoogleOAuth } from "../auth/google-oauth.js";
|
|
8
|
+
import { createConfigSecretStore, } from "../auth/secret-store-factory.js";
|
|
9
|
+
import { BrainHubError } from "../domain/errors.js";
|
|
10
|
+
import { conversationKey } from "../domain/session.js";
|
|
11
|
+
import { GoogleDrive } from "../drive/google-drive.js";
|
|
12
|
+
import { MemoryDrive } from "../drive/memory-drive.js";
|
|
13
|
+
import { DIGITAL_TWIN_PROFILE_PATH, PortraitService, } from "../portrait/portrait-service.js";
|
|
14
|
+
import { PortraitSyncService } from "../portrait/portrait-sync-service.js";
|
|
15
|
+
import { SchedulerManager } from "../scheduler/manager.js";
|
|
16
|
+
import { E5Embedder } from "../search/e5-embedder.js";
|
|
17
|
+
import { isModelReady } from "../search/model-cache.js";
|
|
18
|
+
import { SearchService } from "../search/search-service.js";
|
|
19
|
+
import { SqliteStateStore } from "../state/sqlite-store.js";
|
|
20
|
+
import { StatusService } from "../status/status-service.js";
|
|
21
|
+
import { discoverPublishDirectory } from "../portrait/obsidian.js";
|
|
22
|
+
import { UploadLock } from "../upload/lock.js";
|
|
23
|
+
import { UploadService } from "../upload/upload-service.js";
|
|
24
|
+
import { FileUpdateCache, UpdateCheckService, fetchNpmLatestVersion, } from "../update/update-check-service.js";
|
|
25
|
+
const packageMetadata = createRequire(import.meta.url)("../../package.json");
|
|
26
|
+
class VolatileStateStore {
|
|
27
|
+
getOrCreateDevice(name) {
|
|
28
|
+
return { id: "dry-run", name, createdAt: new Date(0).toISOString() };
|
|
29
|
+
}
|
|
30
|
+
markPending() {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
markFailed() { }
|
|
34
|
+
markUploaded() { }
|
|
35
|
+
getSession() {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
listPending() {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
getDiscoveryWatermark() {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
setDiscoveryWatermark() { }
|
|
45
|
+
}
|
|
46
|
+
const adapterStatusKey = {
|
|
47
|
+
"claude-code": "claude",
|
|
48
|
+
codex: "codex",
|
|
49
|
+
"grok-build": "grok",
|
|
50
|
+
};
|
|
51
|
+
async function directorySize(path) {
|
|
52
|
+
let total = 0;
|
|
53
|
+
try {
|
|
54
|
+
for (const entry of await readdir(path, { withFileTypes: true })) {
|
|
55
|
+
const child = `${path}/${entry.name}`;
|
|
56
|
+
total += entry.isDirectory()
|
|
57
|
+
? await directorySize(child)
|
|
58
|
+
: (await stat(child)).size;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error.code !== "ENOENT")
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
return total;
|
|
66
|
+
}
|
|
67
|
+
export class BrainHubRuntime {
|
|
68
|
+
config;
|
|
69
|
+
paths;
|
|
70
|
+
homeDir;
|
|
71
|
+
platform;
|
|
72
|
+
configFile;
|
|
73
|
+
executable;
|
|
74
|
+
executableArgs;
|
|
75
|
+
#stateStore = null;
|
|
76
|
+
#drivePort = null;
|
|
77
|
+
#myDrivePort = null;
|
|
78
|
+
#googleDriveClient = null;
|
|
79
|
+
#secretStoreFactory;
|
|
80
|
+
#driveFactory;
|
|
81
|
+
constructor(options) {
|
|
82
|
+
this.config = options.config;
|
|
83
|
+
this.paths = options.paths;
|
|
84
|
+
this.homeDir = options.homeDir;
|
|
85
|
+
this.platform = options.platform;
|
|
86
|
+
this.configFile = options.configFile;
|
|
87
|
+
this.executable = options.executable;
|
|
88
|
+
this.executableArgs = options.executableArgs ?? [];
|
|
89
|
+
this.#secretStoreFactory =
|
|
90
|
+
options.secretStoreFactory ?? createConfigSecretStore;
|
|
91
|
+
this.#driveFactory =
|
|
92
|
+
options.driveFactory ?? ((auth) => google.drive({ version: "v3", auth }));
|
|
93
|
+
}
|
|
94
|
+
#state() {
|
|
95
|
+
this.#stateStore ??= new SqliteStateStore(this.paths.stateFile, {
|
|
96
|
+
...(this.paths.legacyStateFile
|
|
97
|
+
? { legacyPath: this.paths.legacyStateFile }
|
|
98
|
+
: {}),
|
|
99
|
+
});
|
|
100
|
+
return this.#stateStore;
|
|
101
|
+
}
|
|
102
|
+
async drive(interactive = false) {
|
|
103
|
+
if (this.#drivePort)
|
|
104
|
+
return this.#drivePort;
|
|
105
|
+
if (!this.config.drive.rootFolderId) {
|
|
106
|
+
throw new BrainHubError("DRIVE_ROOT_REQUIRED", "Run `brainhub-mcp setup` first");
|
|
107
|
+
}
|
|
108
|
+
const secrets = this.#secretStoreFactory({
|
|
109
|
+
platform: this.platform,
|
|
110
|
+
configFile: this.configFile,
|
|
111
|
+
legacyAccount: this.config.device.name,
|
|
112
|
+
});
|
|
113
|
+
const auth = await new GoogleOAuth(this.config.drive.oauthClientFile, secrets).getClient({ interactive });
|
|
114
|
+
const client = this.#driveFactory(auth);
|
|
115
|
+
this.#googleDriveClient = client;
|
|
116
|
+
this.#drivePort = new GoogleDrive({
|
|
117
|
+
client,
|
|
118
|
+
rootFolderId: this.config.drive.rootFolderId,
|
|
119
|
+
});
|
|
120
|
+
return this.#drivePort;
|
|
121
|
+
}
|
|
122
|
+
async #myDrive() {
|
|
123
|
+
if (this.#myDrivePort)
|
|
124
|
+
return this.#myDrivePort;
|
|
125
|
+
await this.drive(false);
|
|
126
|
+
if (!this.#googleDriveClient) {
|
|
127
|
+
throw new BrainHubError("DRIVE_ROOT_REQUIRED", "Google Drive client is not initialized");
|
|
128
|
+
}
|
|
129
|
+
this.#myDrivePort = await GoogleDrive.openMyDrive(this.#googleDriveClient);
|
|
130
|
+
return this.#myDrivePort;
|
|
131
|
+
}
|
|
132
|
+
async discover(input) {
|
|
133
|
+
return discoverSessions({
|
|
134
|
+
device: this.config.device.name || hostname(),
|
|
135
|
+
includeSubagents: input.includeSubagents ?? this.config.capture.includeSubagents,
|
|
136
|
+
sources: input.sources ?? ["claude-code", "codex", "grok-build"],
|
|
137
|
+
paths: {
|
|
138
|
+
claude: this.config.capture.claudePaths,
|
|
139
|
+
codex: this.config.capture.codexPaths,
|
|
140
|
+
grok: this.config.capture.grokPaths,
|
|
141
|
+
},
|
|
142
|
+
...(input.modifiedAfter ? { modifiedAfter: input.modifiedAfter } : {}),
|
|
143
|
+
...(input.includePaths ? { includePaths: input.includePaths } : {}),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
async uploadSessions(input) {
|
|
147
|
+
const dryRun = input.dryRun ?? false;
|
|
148
|
+
const state = dryRun ? new VolatileStateStore() : this.#state();
|
|
149
|
+
const sources = input.sources ?? ["claude-code", "codex", "grok-build"];
|
|
150
|
+
const scanStartedAt = new Date().toISOString();
|
|
151
|
+
const backfill = input.backfill ?? false;
|
|
152
|
+
const discovery = await this.discover({
|
|
153
|
+
...input,
|
|
154
|
+
sources,
|
|
155
|
+
...(!backfill
|
|
156
|
+
? {
|
|
157
|
+
modifiedAfter: Object.fromEntries(sources.map((source) => [
|
|
158
|
+
source,
|
|
159
|
+
state.getDiscoveryWatermark(source) ?? scanStartedAt,
|
|
160
|
+
])),
|
|
161
|
+
includePaths: state
|
|
162
|
+
.listPending(10_000)
|
|
163
|
+
.filter((session) => sources.includes(session.source))
|
|
164
|
+
.map((session) => session.sourcePath),
|
|
165
|
+
}
|
|
166
|
+
: {}),
|
|
167
|
+
});
|
|
168
|
+
const device = dryRun
|
|
169
|
+
? state.getOrCreateDevice(this.config.device.name)
|
|
170
|
+
: state.getOrCreateDevice(this.config.device.name);
|
|
171
|
+
const drive = dryRun ? new MemoryDrive() : await this.drive(false);
|
|
172
|
+
const service = new UploadService({
|
|
173
|
+
drive,
|
|
174
|
+
state,
|
|
175
|
+
deviceId: device.id,
|
|
176
|
+
concurrency: this.config.upload.concurrency,
|
|
177
|
+
redaction: {
|
|
178
|
+
internalDomains: this.config.capture.internalDomains,
|
|
179
|
+
internalCidrs: this.config.capture.internalCidrs,
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
let output;
|
|
183
|
+
if (dryRun) {
|
|
184
|
+
output = await service.uploadSessions(discovery.sessions, {
|
|
185
|
+
dryRun: true,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
await mkdir(dirname(this.paths.stateFile), { recursive: true });
|
|
190
|
+
const lock = new UploadLock(`${this.paths.stateFile}.upload.lock`);
|
|
191
|
+
await lock.acquire();
|
|
192
|
+
try {
|
|
193
|
+
output = await service.uploadSessions(discovery.sessions, {
|
|
194
|
+
dryRun: false,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
await lock.release();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (!dryRun) {
|
|
202
|
+
for (const source of sources) {
|
|
203
|
+
if (discovery.status[adapterStatusKey[source]].errors === 0) {
|
|
204
|
+
state.setDiscoveryWatermark(source, scanStartedAt);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
output.skippedSubagents = discovery.skippedSubagents;
|
|
209
|
+
output.malformed = discovery.malformed;
|
|
210
|
+
output.warnings.push(...discovery.warnings);
|
|
211
|
+
return {
|
|
212
|
+
...output,
|
|
213
|
+
adapters: discovery.status,
|
|
214
|
+
pending: dryRun ? 0 : state.listPending(10_000).length,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
searchService(drive) {
|
|
218
|
+
return new SearchService({
|
|
219
|
+
drive,
|
|
220
|
+
embedder: new E5Embedder({
|
|
221
|
+
model: this.config.search.model,
|
|
222
|
+
revision: this.config.search.modelRevision,
|
|
223
|
+
dimensions: this.config.search.dimensions,
|
|
224
|
+
cacheDir: this.paths.modelCache,
|
|
225
|
+
}),
|
|
226
|
+
indexPath: this.paths.searchIndexFile,
|
|
227
|
+
chunkTokens: this.config.search.chunkTokens,
|
|
228
|
+
chunkOverlap: this.config.search.chunkOverlap,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
async searchSessions(input) {
|
|
232
|
+
const drive = await this.drive(false);
|
|
233
|
+
return this.searchService(drive).search({
|
|
234
|
+
query: input.query,
|
|
235
|
+
limit: Math.min(input.limit ?? this.config.search.defaultLimit, this.config.search.maxLimit),
|
|
236
|
+
...(input.sources ? { sources: input.sources } : {}),
|
|
237
|
+
...(input.from ? { since: input.from } : {}),
|
|
238
|
+
...(input.to ? { until: input.to } : {}),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
async getSession(input) {
|
|
242
|
+
const drive = await this.drive(false);
|
|
243
|
+
const entries = await drive.list({
|
|
244
|
+
prefix: "inbox/",
|
|
245
|
+
appProperty: {
|
|
246
|
+
key: "brainhubKey",
|
|
247
|
+
value: conversationKey(input.source, input.conversationId),
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
const entry = entries
|
|
251
|
+
.filter((candidate) => candidate.path.startsWith("inbox/") &&
|
|
252
|
+
candidate.mimeType === "text/markdown" &&
|
|
253
|
+
candidate.appProperties.source === input.source &&
|
|
254
|
+
candidate.appProperties.conversationId === input.conversationId)
|
|
255
|
+
.sort((left, right) => (right.appProperties.updatedAt ?? right.modifiedTime).localeCompare(left.appProperties.updatedAt ?? left.modifiedTime) || right.id.localeCompare(left.id))[0];
|
|
256
|
+
if (!entry) {
|
|
257
|
+
throw new BrainHubError("SESSION_NOT_FOUND", `Inbox session ${input.source}/${input.conversationId} is not available`);
|
|
258
|
+
}
|
|
259
|
+
const object = await drive.read(entry.id);
|
|
260
|
+
return {
|
|
261
|
+
source: input.source,
|
|
262
|
+
conversationId: input.conversationId,
|
|
263
|
+
content: object.bytes.toString("utf8"),
|
|
264
|
+
updatedAt: entry.appProperties.updatedAt ?? entry.modifiedTime,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
async portraitService() {
|
|
268
|
+
return new PortraitService({
|
|
269
|
+
drive: await this.#myDrive(),
|
|
270
|
+
path: DIGITAL_TWIN_PROFILE_PATH,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
async portraitSyncService() {
|
|
274
|
+
return new PortraitSyncService({
|
|
275
|
+
portraitSource: {
|
|
276
|
+
drive: await this.#myDrive(),
|
|
277
|
+
path: DIGITAL_TWIN_PROFILE_PATH,
|
|
278
|
+
},
|
|
279
|
+
publish: {
|
|
280
|
+
platform: this.platform,
|
|
281
|
+
homeDir: this.homeDir,
|
|
282
|
+
fallbackPath: this.config.publish.fallbackPath,
|
|
283
|
+
...(process.env.XDG_CONFIG_HOME
|
|
284
|
+
? { xdgConfigHome: process.env.XDG_CONFIG_HOME }
|
|
285
|
+
: {}),
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
async getPortrait() {
|
|
290
|
+
return (await this.portraitService()).getPortrait();
|
|
291
|
+
}
|
|
292
|
+
async syncPortrait() {
|
|
293
|
+
return (await this.portraitSyncService()).sync();
|
|
294
|
+
}
|
|
295
|
+
async hubStatus() {
|
|
296
|
+
const scheduler = new SchedulerManager({
|
|
297
|
+
platform: this.platform,
|
|
298
|
+
homeDir: this.homeDir,
|
|
299
|
+
command: this.executable,
|
|
300
|
+
args: this.executableArgs,
|
|
301
|
+
});
|
|
302
|
+
return new StatusService({
|
|
303
|
+
account: {
|
|
304
|
+
connected: Boolean(this.config.drive.accountPermissionId),
|
|
305
|
+
...(this.config.drive.accountEmail
|
|
306
|
+
? { email: this.config.drive.accountEmail }
|
|
307
|
+
: {}),
|
|
308
|
+
...(this.config.drive.accountDisplayName
|
|
309
|
+
? { displayName: this.config.drive.accountDisplayName }
|
|
310
|
+
: {}),
|
|
311
|
+
},
|
|
312
|
+
root: {
|
|
313
|
+
configured: Boolean(this.config.drive.rootFolderId),
|
|
314
|
+
name: this.config.drive.rootFolderName,
|
|
315
|
+
...(this.config.drive.rootFolderId
|
|
316
|
+
? { id: this.config.drive.rootFolderId }
|
|
317
|
+
: {}),
|
|
318
|
+
},
|
|
319
|
+
drive: () => this.drive(false),
|
|
320
|
+
upload: async () => (await this.discover({})).status,
|
|
321
|
+
model: async () => {
|
|
322
|
+
const bytes = await directorySize(this.paths.modelCache);
|
|
323
|
+
const ready = await isModelReady(this.paths.modelCache, {
|
|
324
|
+
model: this.config.search.model,
|
|
325
|
+
revision: this.config.search.modelRevision,
|
|
326
|
+
dimensions: this.config.search.dimensions,
|
|
327
|
+
});
|
|
328
|
+
return { ready, bytes, cachePath: this.paths.modelCache };
|
|
329
|
+
},
|
|
330
|
+
index: async () => this.searchService(await this.drive(false)).status(),
|
|
331
|
+
launchd: () => scheduler.status(),
|
|
332
|
+
portrait: async () => {
|
|
333
|
+
const portrait = await (await this.#myDrive()).readPath(DIGITAL_TWIN_PROFILE_PATH);
|
|
334
|
+
return portrait
|
|
335
|
+
? { available: true, modifiedAt: portrait.modifiedTime }
|
|
336
|
+
: { available: false };
|
|
337
|
+
},
|
|
338
|
+
obsidian: async () => {
|
|
339
|
+
const path = await discoverPublishDirectory({
|
|
340
|
+
platform: this.platform,
|
|
341
|
+
homeDir: this.homeDir,
|
|
342
|
+
fallbackPath: this.config.publish.fallbackPath,
|
|
343
|
+
...(process.env.XDG_CONFIG_HOME
|
|
344
|
+
? { xdgConfigHome: process.env.XDG_CONFIG_HOME }
|
|
345
|
+
: {}),
|
|
346
|
+
});
|
|
347
|
+
return path ? { configured: true, path } : { configured: false };
|
|
348
|
+
},
|
|
349
|
+
update: () => new UpdateCheckService({
|
|
350
|
+
currentVersion: packageMetadata.version,
|
|
351
|
+
cache: new FileUpdateCache(join(dirname(dirname(dirname(this.paths.stateFile))), "update-check.json")),
|
|
352
|
+
fetchLatest: fetchNpmLatestVersion,
|
|
353
|
+
}).check(),
|
|
354
|
+
}).getStatus();
|
|
355
|
+
}
|
|
356
|
+
close() {
|
|
357
|
+
this.#stateStore?.close();
|
|
358
|
+
this.#stateStore = null;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=container.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/runtime/container.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/scheduler/jobs.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,QAAQ;IACR,WAAW;IACX,8BAA8B;CACtB,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,UAAU,EAAE,MAAM,CAAU,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { dailyUploadArguments, portraitSyncArguments } from "./jobs.js";
|
|
2
|
+
function xml(value) {
|
|
3
|
+
return value
|
|
4
|
+
.replaceAll("&", "&")
|
|
5
|
+
.replaceAll("<", "<")
|
|
6
|
+
.replaceAll(">", ">")
|
|
7
|
+
.replaceAll('"', """)
|
|
8
|
+
.replaceAll("'", "'");
|
|
9
|
+
}
|
|
10
|
+
export function renderLaunchAgent(options) {
|
|
11
|
+
const [hour, minute] = options.at.split(":").map(Number);
|
|
12
|
+
if (!Number.isInteger(hour) || !Number.isInteger(minute))
|
|
13
|
+
throw new Error("Invalid schedule time");
|
|
14
|
+
const sync = options.job === "portrait-sync";
|
|
15
|
+
const label = sync ? "com.brainhub.sync" : "com.brainhub.upload";
|
|
16
|
+
const commandArguments = sync ? portraitSyncArguments : dailyUploadArguments;
|
|
17
|
+
const logName = sync ? "sync" : "upload";
|
|
18
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
19
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
20
|
+
<plist version="1.0">
|
|
21
|
+
<dict>
|
|
22
|
+
<key>Label</key><string>${label}</string>
|
|
23
|
+
<key>ProgramArguments</key>
|
|
24
|
+
<array>
|
|
25
|
+
<string>${xml(options.command)}</string>
|
|
26
|
+
${options.args.map((argument) => ` <string>${xml(argument)}</string>`).join("\n")}
|
|
27
|
+
${commandArguments.map((argument) => ` <string>${argument}</string>`).join("\n")}
|
|
28
|
+
<string>--json</string>
|
|
29
|
+
</array>
|
|
30
|
+
<key>RunAtLoad</key>
|
|
31
|
+
<true/>
|
|
32
|
+
<key>StartCalendarInterval</key>
|
|
33
|
+
<dict><key>Hour</key><integer>${hour}</integer><key>Minute</key><integer>${minute}</integer></dict>
|
|
34
|
+
<key>StandardOutPath</key><string>${xml(`${options.logDirectory}/${logName}.log`)}</string>
|
|
35
|
+
<key>StandardErrorPath</key><string>${xml(`${options.logDirectory}/${logName}-error.log`)}</string>
|
|
36
|
+
</dict>
|
|
37
|
+
</plist>
|
|
38
|
+
`;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=launchd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launchd.js","sourceRoot":"","sources":["../../src/scheduler/launchd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAExE,SAAS,GAAG,CAAC,KAAa;IACxB,OAAO,KAAK;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAMjC;IACC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,KAAK,eAAe,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,qBAAqB,CAAC;IACjE,MAAM,gBAAgB,GAAG,IAAI,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,oBAAoB,CAAC;IAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzC,OAAO;;;;4BAImB,KAAK;;;cAGnB,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;EAChC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;EAClF,gBAAgB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAe,QAAQ,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;kCAMjD,IAAI,uCAAuC,MAAM;sCAC7C,GAAG,CAAC,GAAG,OAAO,CAAC,YAAY,IAAI,OAAO,MAAM,CAAC;wCAC3C,GAAG,CAAC,GAAG,OAAO,CAAC,YAAY,IAAI,OAAO,YAAY,CAAC;;;CAG1F,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type Runner = (command: string, args: string[]) => Promise<void>;
|
|
2
|
+
export declare class SchedulerManager {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(options: {
|
|
5
|
+
platform?: NodeJS.Platform;
|
|
6
|
+
homeDir: string;
|
|
7
|
+
command: string;
|
|
8
|
+
args: string[];
|
|
9
|
+
runner?: Runner;
|
|
10
|
+
});
|
|
11
|
+
install(at: string, syncAt: string, options?: {
|
|
12
|
+
portrait?: boolean;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
uninstall(): Promise<void>;
|
|
15
|
+
status(): Promise<{
|
|
16
|
+
installed: boolean;
|
|
17
|
+
upload: {
|
|
18
|
+
installed: boolean;
|
|
19
|
+
};
|
|
20
|
+
sync: {
|
|
21
|
+
installed: boolean;
|
|
22
|
+
};
|
|
23
|
+
platform: string;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { access, mkdir, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { BrainHubError } from "../domain/errors.js";
|
|
5
|
+
import { renderLaunchAgent } from "./launchd.js";
|
|
6
|
+
const runner = async (command, args) => new Promise((resolve, reject) => {
|
|
7
|
+
const child = spawn(command, args, { stdio: "ignore" });
|
|
8
|
+
child.on("error", reject);
|
|
9
|
+
child.on("close", (code) => code === 0
|
|
10
|
+
? resolve()
|
|
11
|
+
: reject(new Error(`${command} exited with ${code}`)));
|
|
12
|
+
});
|
|
13
|
+
export class SchedulerManager {
|
|
14
|
+
#platform;
|
|
15
|
+
#homeDir;
|
|
16
|
+
#command;
|
|
17
|
+
#args;
|
|
18
|
+
#run;
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.#platform = options.platform ?? process.platform;
|
|
21
|
+
this.#homeDir = options.homeDir;
|
|
22
|
+
this.#command = options.command;
|
|
23
|
+
this.#args = options.args;
|
|
24
|
+
this.#run = options.runner ?? runner;
|
|
25
|
+
}
|
|
26
|
+
async install(at, syncAt, options = {}) {
|
|
27
|
+
if (this.#platform !== "darwin") {
|
|
28
|
+
throw new BrainHubError("PLATFORM_UNSUPPORTED", "BrainHub MCP v1 supports macOS only");
|
|
29
|
+
}
|
|
30
|
+
const directory = join(this.#homeDir, "Library", "LaunchAgents");
|
|
31
|
+
const logs = join(this.#homeDir, "Library", "Logs", "BrainHub");
|
|
32
|
+
const jobs = [
|
|
33
|
+
{
|
|
34
|
+
path: join(directory, "com.brainhub.upload.plist"),
|
|
35
|
+
at,
|
|
36
|
+
job: "upload",
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
const syncPath = join(directory, "com.brainhub.sync.plist");
|
|
40
|
+
if (options.portrait !== false) {
|
|
41
|
+
jobs.push({
|
|
42
|
+
path: syncPath,
|
|
43
|
+
at: syncAt,
|
|
44
|
+
job: "portrait-sync",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
await Promise.all([
|
|
48
|
+
mkdir(directory, { recursive: true }),
|
|
49
|
+
mkdir(logs, { recursive: true }),
|
|
50
|
+
]);
|
|
51
|
+
await Promise.all(jobs.map(({ path, ...jobOptions }) => writeFile(path, renderLaunchAgent({
|
|
52
|
+
command: this.#command,
|
|
53
|
+
args: this.#args,
|
|
54
|
+
logDirectory: logs,
|
|
55
|
+
...jobOptions,
|
|
56
|
+
}))));
|
|
57
|
+
const domain = `gui/${process.getuid?.() ?? 0}`;
|
|
58
|
+
if (options.portrait === false) {
|
|
59
|
+
await this.#run("launchctl", ["bootout", domain, syncPath]).catch(() => undefined);
|
|
60
|
+
await rm(syncPath, { force: true });
|
|
61
|
+
}
|
|
62
|
+
for (const { path } of jobs) {
|
|
63
|
+
await this.#run("launchctl", ["bootout", domain, path]).catch(() => undefined);
|
|
64
|
+
await this.#run("launchctl", ["bootstrap", domain, path]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async uninstall() {
|
|
68
|
+
if (this.#platform !== "darwin") {
|
|
69
|
+
throw new BrainHubError("PLATFORM_UNSUPPORTED", "BrainHub MCP v1 supports macOS only");
|
|
70
|
+
}
|
|
71
|
+
const directory = join(this.#homeDir, "Library", "LaunchAgents");
|
|
72
|
+
const paths = [
|
|
73
|
+
join(directory, "com.brainhub.upload.plist"),
|
|
74
|
+
join(directory, "com.brainhub.sync.plist"),
|
|
75
|
+
];
|
|
76
|
+
for (const path of paths) {
|
|
77
|
+
await this.#run("launchctl", [
|
|
78
|
+
"bootout",
|
|
79
|
+
`gui/${process.getuid?.() ?? 0}`,
|
|
80
|
+
path,
|
|
81
|
+
]).catch(() => undefined);
|
|
82
|
+
await rm(path, { force: true });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async status() {
|
|
86
|
+
if (this.#platform !== "darwin") {
|
|
87
|
+
return {
|
|
88
|
+
installed: false,
|
|
89
|
+
upload: { installed: false },
|
|
90
|
+
sync: { installed: false },
|
|
91
|
+
platform: this.#platform,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const directory = join(this.#homeDir, "Library", "LaunchAgents");
|
|
95
|
+
const uploadPath = join(directory, "com.brainhub.upload.plist");
|
|
96
|
+
const syncPath = join(directory, "com.brainhub.sync.plist");
|
|
97
|
+
const [uploadInstalled, syncInstalled] = await Promise.all([
|
|
98
|
+
access(uploadPath)
|
|
99
|
+
.then(() => true)
|
|
100
|
+
.catch(() => false),
|
|
101
|
+
access(syncPath)
|
|
102
|
+
.then(() => true)
|
|
103
|
+
.catch(() => false),
|
|
104
|
+
]);
|
|
105
|
+
return {
|
|
106
|
+
installed: uploadInstalled,
|
|
107
|
+
upload: { installed: uploadInstalled },
|
|
108
|
+
sync: { installed: syncInstalled },
|
|
109
|
+
platform: this.#platform,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=manager.js.map
|