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.
Files changed (156) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +84 -0
  3. package/dist/adapters/claude.d.ts +2 -0
  4. package/dist/adapters/claude.js +50 -0
  5. package/dist/adapters/claude.js.map +1 -0
  6. package/dist/adapters/codex.d.ts +2 -0
  7. package/dist/adapters/codex.js +52 -0
  8. package/dist/adapters/codex.js.map +1 -0
  9. package/dist/adapters/content.d.ts +6 -0
  10. package/dist/adapters/content.js +68 -0
  11. package/dist/adapters/content.js.map +1 -0
  12. package/dist/adapters/grok.d.ts +2 -0
  13. package/dist/adapters/grok.js +44 -0
  14. package/dist/adapters/grok.js.map +1 -0
  15. package/dist/adapters/index.d.ts +31 -0
  16. package/dist/adapters/index.js +111 -0
  17. package/dist/adapters/index.js.map +1 -0
  18. package/dist/adapters/jsonl.d.ts +6 -0
  19. package/dist/adapters/jsonl.js +26 -0
  20. package/dist/adapters/jsonl.js.map +1 -0
  21. package/dist/adapters/types.d.ts +10 -0
  22. package/dist/adapters/types.js +2 -0
  23. package/dist/adapters/types.js.map +1 -0
  24. package/dist/auth/account-status.d.ts +50 -0
  25. package/dist/auth/account-status.js +59 -0
  26. package/dist/auth/account-status.js.map +1 -0
  27. package/dist/auth/google-account.d.ts +21 -0
  28. package/dist/auth/google-account.js +45 -0
  29. package/dist/auth/google-account.js.map +1 -0
  30. package/dist/auth/google-oauth.d.ts +35 -0
  31. package/dist/auth/google-oauth.js +191 -0
  32. package/dist/auth/google-oauth.js.map +1 -0
  33. package/dist/auth/oauth-loopback.d.ts +10 -0
  34. package/dist/auth/oauth-loopback.js +81 -0
  35. package/dist/auth/oauth-loopback.js.map +1 -0
  36. package/dist/auth/official-oauth-client.d.ts +5 -0
  37. package/dist/auth/official-oauth-client.js +6 -0
  38. package/dist/auth/official-oauth-client.js.map +1 -0
  39. package/dist/auth/platform-secrets.d.ts +14 -0
  40. package/dist/auth/platform-secrets.js +81 -0
  41. package/dist/auth/platform-secrets.js.map +1 -0
  42. package/dist/auth/secret-store-factory.d.ts +11 -0
  43. package/dist/auth/secret-store-factory.js +37 -0
  44. package/dist/auth/secret-store-factory.js.map +1 -0
  45. package/dist/auth/secret-store.d.ts +13 -0
  46. package/dist/auth/secret-store.js +40 -0
  47. package/dist/auth/secret-store.js.map +1 -0
  48. package/dist/capture/images.d.ts +11 -0
  49. package/dist/capture/images.js +27 -0
  50. package/dist/capture/images.js.map +1 -0
  51. package/dist/capture/normalize.d.ts +11 -0
  52. package/dist/capture/normalize.js +43 -0
  53. package/dist/capture/normalize.js.map +1 -0
  54. package/dist/capture/redact.d.ts +10 -0
  55. package/dist/capture/redact.js +60 -0
  56. package/dist/capture/redact.js.map +1 -0
  57. package/dist/cli/index.d.ts +20 -0
  58. package/dist/cli/index.js +781 -0
  59. package/dist/cli/index.js.map +1 -0
  60. package/dist/clients/registry.d.ts +24 -0
  61. package/dist/clients/registry.js +105 -0
  62. package/dist/clients/registry.js.map +1 -0
  63. package/dist/domain/config-io.d.ts +15 -0
  64. package/dist/domain/config-io.js +168 -0
  65. package/dist/domain/config-io.js.map +1 -0
  66. package/dist/domain/config.d.ts +74 -0
  67. package/dist/domain/config.js +130 -0
  68. package/dist/domain/config.js.map +1 -0
  69. package/dist/domain/errors.d.ts +6 -0
  70. package/dist/domain/errors.js +11 -0
  71. package/dist/domain/errors.js.map +1 -0
  72. package/dist/domain/session.d.ts +62 -0
  73. package/dist/domain/session.js +47 -0
  74. package/dist/domain/session.js.map +1 -0
  75. package/dist/drive/drive-port.d.ts +51 -0
  76. package/dist/drive/drive-port.js +2 -0
  77. package/dist/drive/drive-port.js.map +1 -0
  78. package/dist/drive/google-drive.d.ts +28 -0
  79. package/dist/drive/google-drive.js +501 -0
  80. package/dist/drive/google-drive.js.map +1 -0
  81. package/dist/drive/memory-drive.d.ts +19 -0
  82. package/dist/drive/memory-drive.js +148 -0
  83. package/dist/drive/memory-drive.js.map +1 -0
  84. package/dist/drive/scoped-drive.d.ts +17 -0
  85. package/dist/drive/scoped-drive.js +115 -0
  86. package/dist/drive/scoped-drive.js.map +1 -0
  87. package/dist/mcp/server.d.ts +55 -0
  88. package/dist/mcp/server.js +133 -0
  89. package/dist/mcp/server.js.map +1 -0
  90. package/dist/portrait/obsidian.d.ts +7 -0
  91. package/dist/portrait/obsidian.js +16 -0
  92. package/dist/portrait/obsidian.js.map +1 -0
  93. package/dist/portrait/portrait-service.d.ts +12 -0
  94. package/dist/portrait/portrait-service.js +18 -0
  95. package/dist/portrait/portrait-service.js.map +1 -0
  96. package/dist/portrait/portrait-sync-service.d.ts +21 -0
  97. package/dist/portrait/portrait-sync-service.js +43 -0
  98. package/dist/portrait/portrait-sync-service.js.map +1 -0
  99. package/dist/runtime/command.d.ts +4 -0
  100. package/dist/runtime/command.js +2 -0
  101. package/dist/runtime/command.js.map +1 -0
  102. package/dist/runtime/container.d.ts +72 -0
  103. package/dist/runtime/container.js +361 -0
  104. package/dist/runtime/container.js.map +1 -0
  105. package/dist/scheduler/jobs.d.ts +2 -0
  106. package/dist/scheduler/jobs.js +7 -0
  107. package/dist/scheduler/jobs.js.map +1 -0
  108. package/dist/scheduler/launchd.d.ts +7 -0
  109. package/dist/scheduler/launchd.js +40 -0
  110. package/dist/scheduler/launchd.js.map +1 -0
  111. package/dist/scheduler/manager.d.ts +26 -0
  112. package/dist/scheduler/manager.js +113 -0
  113. package/dist/scheduler/manager.js.map +1 -0
  114. package/dist/search/chunk-text.d.ts +11 -0
  115. package/dist/search/chunk-text.js +40 -0
  116. package/dist/search/chunk-text.js.map +1 -0
  117. package/dist/search/e5-embedder.d.ts +19 -0
  118. package/dist/search/e5-embedder.js +71 -0
  119. package/dist/search/e5-embedder.js.map +1 -0
  120. package/dist/search/embedder.d.ts +8 -0
  121. package/dist/search/embedder.js +5 -0
  122. package/dist/search/embedder.js.map +1 -0
  123. package/dist/search/model-cache.d.ts +7 -0
  124. package/dist/search/model-cache.js +38 -0
  125. package/dist/search/model-cache.js.map +1 -0
  126. package/dist/search/search-service.d.ts +46 -0
  127. package/dist/search/search-service.js +319 -0
  128. package/dist/search/search-service.js.map +1 -0
  129. package/dist/setup/backfill-service.d.ts +33 -0
  130. package/dist/setup/backfill-service.js +47 -0
  131. package/dist/setup/backfill-service.js.map +1 -0
  132. package/dist/setup/setup-service.d.ts +65 -0
  133. package/dist/setup/setup-service.js +90 -0
  134. package/dist/setup/setup-service.js.map +1 -0
  135. package/dist/setup/uninstall-service.d.ts +34 -0
  136. package/dist/setup/uninstall-service.js +91 -0
  137. package/dist/setup/uninstall-service.js.map +1 -0
  138. package/dist/state/sqlite-store.d.ts +19 -0
  139. package/dist/state/sqlite-store.js +299 -0
  140. package/dist/state/sqlite-store.js.map +1 -0
  141. package/dist/state/store.d.ts +52 -0
  142. package/dist/state/store.js +2 -0
  143. package/dist/state/store.js.map +1 -0
  144. package/dist/status/status-service.d.ts +38 -0
  145. package/dist/status/status-service.js +93 -0
  146. package/dist/status/status-service.js.map +1 -0
  147. package/dist/update/update-check-service.d.ts +38 -0
  148. package/dist/update/update-check-service.js +105 -0
  149. package/dist/update/update-check-service.js.map +1 -0
  150. package/dist/upload/lock.d.ts +7 -0
  151. package/dist/upload/lock.js +68 -0
  152. package/dist/upload/lock.js.map +1 -0
  153. package/dist/upload/upload-service.d.ts +36 -0
  154. package/dist/upload/upload-service.js +360 -0
  155. package/dist/upload/upload-service.js.map +1 -0
  156. 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":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,MAAM,EAAiB,MAAM,YAAY,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,WAAW,EAA0B,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EACL,uBAAuB,GAExB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAsB,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EACL,yBAAyB,EACzB,eAAe,GAChB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAqB,MAAM,6BAA6B,CAAC;AAC/E,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,mCAAmC,CAAC;AAE3C,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CACpD,oBAAoB,CAGrB,CAAC;AAEF,MAAM,kBAAkB;IACtB,iBAAiB,CAAC,IAAY;QAC5B,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;IACvE,CAAC;IACD,WAAW;QACT,OAAO,IAAI,CAAC;IACd,CAAC;IACD,UAAU,KAAU,CAAC;IACrB,YAAY,KAAU,CAAC;IACvB,UAAU;QACR,OAAO,IAAI,CAAC;IACd,CAAC;IACD,WAAW;QACT,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,qBAAqB;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,qBAAqB,KAAU,CAAC;CACjC;AAED,MAAM,gBAAgB,GAAuD;IAC3E,aAAa,EAAE,QAAQ;IACvB,KAAK,EAAE,OAAO;IACd,YAAY,EAAE,MAAM;CACrB,CAAC;AAEF,KAAK,UAAU,aAAa,CAAC,IAAY;IACvC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,CAAC;QACH,KAAK,MAAM,KAAK,IAAI,MAAM,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACjE,MAAM,KAAK,GAAG,GAAG,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACtC,KAAK,IAAI,KAAK,CAAC,WAAW,EAAE;gBAC1B,CAAC,CAAC,MAAM,aAAa,CAAC,KAAK,CAAC;gBAC5B,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/B,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,KAAK,CAAC;IACtE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,OAAO,eAAe;IACjB,MAAM,CAAiB;IACvB,KAAK,CAAgB;IACrB,OAAO,CAAS;IAChB,QAAQ,CAAkB;IAC1B,UAAU,CAAS;IACnB,UAAU,CAAS;IACnB,cAAc,CAAW;IAClC,WAAW,GAA4B,IAAI,CAAC;IAC5C,UAAU,GAAqB,IAAI,CAAC;IACpC,YAAY,GAAqB,IAAI,CAAC;IACtC,kBAAkB,GAA0B,IAAI,CAAC;IACxC,mBAAmB,CAA2B;IAC9C,aAAa,CAA8C;IAEpE,YAAY,OAUX;QACC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;QACnD,IAAI,CAAC,mBAAmB;YACtB,OAAO,CAAC,kBAAkB,IAAI,uBAAuB,CAAC;QACxD,IAAI,CAAC,aAAa;YAChB,OAAO,CAAC,YAAY,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,WAAW,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE;YAC9D,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe;gBAC5B,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE;gBAC5C,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,WAAW,GAAG,KAAK;QAC7B,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;YACpC,MAAM,IAAI,aAAa,CACrB,qBAAqB,EACrB,gCAAgC,CACjC,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB,CAAC;YACvC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI;SACvC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAI,WAAW,CAChC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,EACjC,OAAO,CACR,CAAC,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,kBAAkB,GAAG,MAAM,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,IAAI,WAAW,CAAC;YAChC,MAAM;YACN,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY;SAC7C,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC;QAChD,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC7B,MAAM,IAAI,aAAa,CACrB,qBAAqB,EACrB,wCAAwC,CACzC,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC3E,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAKd;QACC,OAAO,gBAAgB,CAAC;YACtB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,QAAQ,EAAE;YAC7C,gBAAgB,EACd,KAAK,CAAC,gBAAgB,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB;YAChE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,CAAC,aAAa,EAAE,OAAO,EAAE,YAAY,CAAC;YAChE,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW;gBACvC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU;gBACrC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS;aACpC;YACD,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtE,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpE,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAKpB;QACC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC;QACrC,MAAM,KAAK,GAAe,MAAM,CAAC,CAAC,CAAC,IAAI,kBAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5E,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,aAAa,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;QACxE,MAAM,aAAa,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC;QACzC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC;YACpC,GAAG,KAAK;YACR,OAAO;YACP,GAAG,CAAC,CAAC,QAAQ;gBACX,CAAC,CAAC;oBACE,aAAa,EAAE,MAAM,CAAC,WAAW,CAC/B,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;wBACtB,MAAM;wBACN,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,aAAa;qBACrD,CAAC,CACuC;oBAC3C,YAAY,EAAE,KAAK;yBAChB,WAAW,CAAC,MAAM,CAAC;yBACnB,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;yBACrD,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;iBACxC;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM;YACnB,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;YAClD,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnE,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC;YAChC,KAAK;YACL,KAAK;YACL,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW;YAC3C,SAAS,EAAE;gBACT,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe;gBACpD,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa;aACjD;SACF,CAAC,CAAC;QACH,IAAI,MAAoB,CAAC;QACzB,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,EAAE;gBACxD,MAAM,EAAE,IAAI;aACb,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,cAAc,CAAC,CAAC;YACnE,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,EAAE;oBACxD,MAAM,EAAE,KAAK;iBACd,CAAC,CAAC;YACL,CAAC;oBAAS,CAAC;gBACT,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC5D,KAAK,CAAC,qBAAqB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,CAAC,gBAAgB,GAAG,SAAS,CAAC,gBAAgB,CAAC;QACrD,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC;QACvC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC5C,OAAO;YACL,GAAG,MAAM;YACT,QAAQ,EAAE,SAAS,CAAC,MAAM;YAC1B,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM;SACvD,CAAC;IACJ,CAAC;IAED,aAAa,CAAC,KAAgB;QAC5B,OAAO,IAAI,aAAa,CAAC;YACvB,KAAK;YACL,QAAQ,EAAE,IAAI,UAAU,CAAC;gBACvB,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK;gBAC/B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa;gBAC1C,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;gBACzC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU;aAChC,CAAC;YACF,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe;YACrC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW;YAC3C,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY;SAC9C,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAMpB;QACC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;YACtC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,IAAI,CAAC,GAAG,CACb,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAC9C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAC5B;YACD,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,KAGhB;QAMC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC;YAC/B,MAAM,EAAE,QAAQ;YAChB,WAAW,EAAE;gBACX,GAAG,EAAE,aAAa;gBAClB,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC;aAC3D;SACF,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,OAAO;aAClB,MAAM,CACL,CAAC,SAAS,EAAE,EAAE,CACZ,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YACnC,SAAS,CAAC,QAAQ,KAAK,eAAe;YACtC,SAAS,CAAC,aAAa,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;YAC/C,SAAS,CAAC,aAAa,CAAC,cAAc,KAAK,KAAK,CAAC,cAAc,CAClE;aACA,IAAI,CACH,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACd,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,aAAa,CACjE,IAAI,CAAC,aAAa,CAAC,SAAS,IAAI,IAAI,CAAC,YAAY,CAClD,IAAI,KAAK,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CACvC,CAAC,CAAC,CAAC,CAAC;QACP,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,aAAa,CACrB,mBAAmB,EACnB,iBAAiB,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,cAAc,mBAAmB,CACzE,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,OAAO;YACL,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtC,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,SAAS,IAAI,KAAK,CAAC,YAAY;SAC/D,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,OAAO,IAAI,eAAe,CAAC;YACzB,KAAK,EAAE,MAAM,IAAI,CAAC,QAAQ,EAAE;YAC5B,IAAI,EAAE,yBAAyB;SAChC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,OAAO,IAAI,mBAAmB,CAAC;YAC7B,cAAc,EAAE;gBACd,KAAK,EAAE,MAAM,IAAI,CAAC,QAAQ,EAAE;gBAC5B,IAAI,EAAE,yBAAyB;aAChC;YACD,OAAO,EAAE;gBACP,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY;gBAC9C,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe;oBAC7B,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE;oBAChD,CAAC,CAAC,EAAE,CAAC;aACR;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO,CAAC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,CAAC;IACD,KAAK,CAAC,YAAY;QAChB,OAAO,CAAC,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,SAAS,GAAG,IAAI,gBAAgB,CAAC;YACrC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,UAAU;YACxB,IAAI,EAAE,IAAI,CAAC,cAAc;SAC1B,CAAC,CAAC;QACH,OAAO,IAAI,aAAa,CAAC;YACvB,OAAO,EAAE;gBACP,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC;gBACzD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY;oBAChC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE;oBAC3C,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB;oBACtC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE;oBACvD,CAAC,CAAC,EAAE,CAAC;aACR;YACD,IAAI,EAAE;gBACJ,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC;gBACnD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc;gBACtC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY;oBAChC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE;oBACxC,CAAC,CAAC,EAAE,CAAC;aACR;YACD,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;YAC9B,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM;YACpD,KAAK,EAAE,KAAK,IAAI,EAAE;gBAChB,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACzD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;oBACtD,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK;oBAC/B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa;oBAC1C,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;iBAC1C,CAAC,CAAC;gBACH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YAC5D,CAAC;YACD,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE;YACvE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE;YACjC,QAAQ,EAAE,KAAK,IAAI,EAAE;gBACnB,MAAM,QAAQ,GAAG,MAAM,CACrB,MAAM,IAAI,CAAC,QAAQ,EAAE,CACtB,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;gBACtC,OAAO,QAAQ;oBACb,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,YAAY,EAAE;oBACxD,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YAC3B,CAAC;YACD,QAAQ,EAAE,KAAK,IAAI,EAAE;gBACnB,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC;oBAC1C,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY;oBAC9C,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe;wBAC7B,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE;wBAChD,CAAC,CAAC,EAAE,CAAC;iBACR,CAAC,CAAC;gBACH,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;YACnE,CAAC;YACD,MAAM,EAAE,GAAG,EAAE,CACX,IAAI,kBAAkB,CAAC;gBACrB,cAAc,EAAE,eAAe,CAAC,OAAO;gBACvC,KAAK,EAAE,IAAI,eAAe,CACxB,IAAI,CACF,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAC/C,mBAAmB,CACpB,CACF;gBACD,WAAW,EAAE,qBAAqB;aACnC,CAAC,CAAC,KAAK,EAAE;SACb,CAAC,CAAC,SAAS,EAAE,CAAC;IACjB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export declare const dailyUploadArguments: readonly ["upload", "--sources", "claude-code,codex,grok-build"];
2
+ export declare const portraitSyncArguments: readonly ["portrait", "sync"];
@@ -0,0 +1,7 @@
1
+ export const dailyUploadArguments = [
2
+ "upload",
3
+ "--sources",
4
+ "claude-code,codex,grok-build",
5
+ ];
6
+ export const portraitSyncArguments = ["portrait", "sync"];
7
+ //# sourceMappingURL=jobs.js.map
@@ -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,7 @@
1
+ export declare function renderLaunchAgent(options: {
2
+ command: string;
3
+ args: string[];
4
+ at: string;
5
+ logDirectory: string;
6
+ job?: "upload" | "portrait-sync";
7
+ }): string;
@@ -0,0 +1,40 @@
1
+ import { dailyUploadArguments, portraitSyncArguments } from "./jobs.js";
2
+ function xml(value) {
3
+ return value
4
+ .replaceAll("&", "&amp;")
5
+ .replaceAll("<", "&lt;")
6
+ .replaceAll(">", "&gt;")
7
+ .replaceAll('"', "&quot;")
8
+ .replaceAll("'", "&apos;");
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