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,81 @@
1
+ import { createServer } from "node:http";
2
+ import open from "open";
3
+ export async function startOAuthLoopback(state, options = {}) {
4
+ let resolveCode = () => undefined;
5
+ let rejectCode = () => undefined;
6
+ let settled = false;
7
+ const codePromise = new Promise((resolve, reject) => {
8
+ resolveCode = resolve;
9
+ rejectCode = reject;
10
+ });
11
+ const settleError = (error) => {
12
+ if (settled)
13
+ return;
14
+ settled = true;
15
+ rejectCode(error);
16
+ };
17
+ const server = createServer((request, response) => {
18
+ const url = new URL(request.url ?? "/", "http://127.0.0.1");
19
+ if (url.pathname !== "/oauth/callback" ||
20
+ url.searchParams.get("state") !== state) {
21
+ response.writeHead(400, { "content-type": "text/plain; charset=utf-8" });
22
+ response.end("BrainHub authorization failed. You can close this window.");
23
+ settleError(new Error("OAuth callback validation failed"));
24
+ return;
25
+ }
26
+ if (url.searchParams.has("error")) {
27
+ response.writeHead(400, { "content-type": "text/plain; charset=utf-8" });
28
+ response.end("BrainHub authorization was cancelled. You can close this window.");
29
+ settleError(new Error("OAuth authorization was cancelled"));
30
+ return;
31
+ }
32
+ const code = url.searchParams.get("code");
33
+ if (!code) {
34
+ response.writeHead(400, { "content-type": "text/plain; charset=utf-8" });
35
+ response.end("BrainHub authorization failed. You can close this window.");
36
+ settleError(new Error("OAuth callback validation failed"));
37
+ return;
38
+ }
39
+ response.writeHead(200, { "content-type": "text/plain; charset=utf-8" });
40
+ response.end("BrainHub authorization completed. You can close this window.");
41
+ if (!settled) {
42
+ settled = true;
43
+ resolveCode(code);
44
+ }
45
+ });
46
+ await new Promise((resolve, reject) => {
47
+ server.once("error", reject);
48
+ server.listen(0, "127.0.0.1", () => resolve());
49
+ });
50
+ const address = server.address();
51
+ if (!address || typeof address === "string") {
52
+ server.close();
53
+ throw new Error("Unable to open OAuth callback server");
54
+ }
55
+ const redirectUri = `http://127.0.0.1:${address.port}/oauth/callback`;
56
+ let timeout;
57
+ return {
58
+ redirectUri,
59
+ async authorize(authorizationUrl) {
60
+ await (options.openUrl ?? open)(authorizationUrl);
61
+ timeout = setTimeout(() => settleError(new Error("OAuth callback timed out")), options.timeoutMs ?? 5 * 60_000);
62
+ try {
63
+ return await codePromise;
64
+ }
65
+ finally {
66
+ clearTimeout(timeout);
67
+ timeout = undefined;
68
+ }
69
+ },
70
+ async close() {
71
+ if (timeout)
72
+ clearTimeout(timeout);
73
+ if (!server.listening)
74
+ return;
75
+ await new Promise((resolve, reject) => {
76
+ server.close((error) => (error ? reject(error) : resolve()));
77
+ });
78
+ },
79
+ };
80
+ }
81
+ //# sourceMappingURL=oauth-loopback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-loopback.js","sourceRoot":"","sources":["../../src/auth/oauth-loopback.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare const BUNDLED_GOOGLE_OAUTH_CLIENT: {
2
+ clientId: string;
3
+ clientSecret: string;
4
+ redirectUris: string[];
5
+ };
@@ -0,0 +1,6 @@
1
+ export const BUNDLED_GOOGLE_OAUTH_CLIENT = {
2
+ clientId: "149056240470-pklabt8ej6pn91vl80vuhjbv471sao44.apps.googleusercontent.com",
3
+ clientSecret: "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",
4
+ redirectUris: ["http://127.0.0.1"],
5
+ };
6
+ //# sourceMappingURL=official-oauth-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"official-oauth-client.js","sourceRoot":"","sources":["../../src/auth/official-oauth-client.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,QAAQ,EAAE,qCAAqC;IAC/C,YAAY,EAAE,yCAAyC;IACvD,YAAY,EAAE,CAAC,kBAAkB,CAAC;CACnC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { SecretStore } from "./secret-store.js";
2
+ export type CommandRunner = (command: string, args: string[], input?: string) => Promise<string>;
3
+ export declare class PlatformSecretStore implements SecretStore {
4
+ #private;
5
+ constructor(options: {
6
+ platform?: NodeJS.Platform;
7
+ service?: string;
8
+ account: string;
9
+ runner?: CommandRunner;
10
+ });
11
+ get(): Promise<string | null>;
12
+ set(value: string): Promise<void>;
13
+ delete(): Promise<void>;
14
+ }
@@ -0,0 +1,81 @@
1
+ import { spawn } from "node:child_process";
2
+ import { BrainHubError } from "../domain/errors.js";
3
+ const defaultRunner = async (command, args, input) => new Promise((resolve, reject) => {
4
+ const child = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"] });
5
+ const stdout = [];
6
+ const stderr = [];
7
+ child.stdout.on("data", (chunk) => stdout.push(chunk));
8
+ child.stderr.on("data", (chunk) => stderr.push(chunk));
9
+ child.on("error", reject);
10
+ child.on("close", (code) => {
11
+ if (code === 0)
12
+ resolve(Buffer.concat(stdout).toString("utf8"));
13
+ else {
14
+ const error = new Error(`${command} exited with ${code}: ${Buffer.concat(stderr).toString("utf8").trim()}`);
15
+ error.exitCode = code;
16
+ reject(error);
17
+ }
18
+ });
19
+ child.stdin.end(input);
20
+ });
21
+ export class PlatformSecretStore {
22
+ #platform;
23
+ #service;
24
+ #account;
25
+ #runner;
26
+ constructor(options) {
27
+ this.#platform = options.platform ?? process.platform;
28
+ this.#service = options.service ?? "brainhub-mcp-google-oauth";
29
+ this.#account = options.account;
30
+ this.#runner = options.runner ?? defaultRunner;
31
+ if (this.#platform !== "darwin") {
32
+ throw new BrainHubError("PLATFORM_UNSUPPORTED", "BrainHub MCP v1 supports macOS only");
33
+ }
34
+ }
35
+ async get() {
36
+ try {
37
+ const output = await this.#runner("security", [
38
+ "find-generic-password",
39
+ "-s",
40
+ this.#service,
41
+ "-a",
42
+ this.#account,
43
+ "-w",
44
+ ]);
45
+ return output.trim() || null;
46
+ }
47
+ catch {
48
+ return null;
49
+ }
50
+ }
51
+ async set(value) {
52
+ await this.#runner("security", [
53
+ "add-generic-password",
54
+ "-U",
55
+ "-s",
56
+ this.#service,
57
+ "-a",
58
+ this.#account,
59
+ "-w",
60
+ value,
61
+ ]);
62
+ }
63
+ async delete() {
64
+ try {
65
+ await this.#runner("security", [
66
+ "delete-generic-password",
67
+ "-s",
68
+ this.#service,
69
+ "-a",
70
+ this.#account,
71
+ ]);
72
+ }
73
+ catch (error) {
74
+ const exitCode = error.exitCode;
75
+ if (exitCode === 44)
76
+ return;
77
+ throw error;
78
+ }
79
+ }
80
+ }
81
+ //# sourceMappingURL=platform-secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-secrets.js","sourceRoot":"","sources":["../../src/auth/platform-secrets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type CommandRunner } from "./platform-secrets.js";
2
+ import { type SecretStore } from "./secret-store.js";
3
+ export interface ConfigSecretStoreOptions {
4
+ platform: NodeJS.Platform;
5
+ configFile: string;
6
+ legacyAccount: string;
7
+ runner?: CommandRunner;
8
+ }
9
+ export type ConfigSecretStoreFactory = (options: ConfigSecretStoreOptions) => SecretStore;
10
+ export declare function credentialStoreAccount(configFile: string): string;
11
+ export declare function createConfigSecretStore(options: ConfigSecretStoreOptions): SecretStore;
@@ -0,0 +1,37 @@
1
+ import { createHash } from "node:crypto";
2
+ import { resolve } from "node:path";
3
+ import { PlatformSecretStore } from "./platform-secrets.js";
4
+ import { MigratingSecretStore } from "./secret-store.js";
5
+ export function credentialStoreAccount(configFile) {
6
+ const digest = createHash("sha256")
7
+ .update(resolve(configFile))
8
+ .digest("hex")
9
+ .slice(0, 32);
10
+ return `config-${digest}`;
11
+ }
12
+ export function createConfigSecretStore(options) {
13
+ const common = {
14
+ platform: options.platform,
15
+ ...(options.runner ? { runner: options.runner } : {}),
16
+ };
17
+ const account = credentialStoreAccount(options.configFile);
18
+ const primary = new PlatformSecretStore({
19
+ ...common,
20
+ account,
21
+ });
22
+ const legacyAccount = new PlatformSecretStore({
23
+ ...common,
24
+ account: options.legacyAccount,
25
+ });
26
+ const renamedService = new MigratingSecretStore(new PlatformSecretStore({
27
+ ...common,
28
+ service: "brain-mcp-google-oauth",
29
+ account,
30
+ }), new PlatformSecretStore({
31
+ ...common,
32
+ service: "brain-mcp-google-oauth",
33
+ account: options.legacyAccount,
34
+ }));
35
+ return new MigratingSecretStore(primary, new MigratingSecretStore(legacyAccount, renamedService));
36
+ }
37
+ //# sourceMappingURL=secret-store-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-store-factory.js","sourceRoot":"","sources":["../../src/auth/secret-store-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,mBAAmB,EAAsB,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAoB,MAAM,mBAAmB,CAAC;AAa3E,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC;SAChC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;SAC3B,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,OAAO,UAAU,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,OAAiC;IAEjC,MAAM,MAAM,GAAG;QACb,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC;IACF,MAAM,OAAO,GAAG,sBAAsB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC;QACtC,GAAG,MAAM;QACT,OAAO;KACR,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,IAAI,mBAAmB,CAAC;QAC5C,GAAG,MAAM;QACT,OAAO,EAAE,OAAO,CAAC,aAAa;KAC/B,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,IAAI,oBAAoB,CAC7C,IAAI,mBAAmB,CAAC;QACtB,GAAG,MAAM;QACT,OAAO,EAAE,wBAAwB;QACjC,OAAO;KACR,CAAC,EACF,IAAI,mBAAmB,CAAC;QACtB,GAAG,MAAM;QACT,OAAO,EAAE,wBAAwB;QACjC,OAAO,EAAE,OAAO,CAAC,aAAa;KAC/B,CAAC,CACH,CAAC;IACF,OAAO,IAAI,oBAAoB,CAC7B,OAAO,EACP,IAAI,oBAAoB,CAAC,aAAa,EAAE,cAAc,CAAC,CACxD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface SecretStore {
2
+ get(): Promise<string | null>;
3
+ set(value: string): Promise<void>;
4
+ delete(): Promise<void>;
5
+ }
6
+ export declare class MigratingSecretStore implements SecretStore {
7
+ readonly primary: SecretStore;
8
+ readonly legacy: SecretStore;
9
+ constructor(primary: SecretStore, legacy: SecretStore);
10
+ get(): Promise<string | null>;
11
+ set(value: string): Promise<void>;
12
+ delete(): Promise<void>;
13
+ }
@@ -0,0 +1,40 @@
1
+ export class MigratingSecretStore {
2
+ primary;
3
+ legacy;
4
+ constructor(primary, legacy) {
5
+ this.primary = primary;
6
+ this.legacy = legacy;
7
+ }
8
+ async get() {
9
+ const current = await this.primary.get();
10
+ if (current)
11
+ return current;
12
+ const legacy = await this.legacy.get();
13
+ if (!legacy)
14
+ return null;
15
+ await this.primary.set(legacy);
16
+ await this.legacy.delete();
17
+ return legacy;
18
+ }
19
+ async set(value) {
20
+ await this.primary.set(value);
21
+ }
22
+ async delete() {
23
+ const previous = await this.primary.get();
24
+ await this.primary.delete();
25
+ try {
26
+ await this.legacy.delete();
27
+ }
28
+ catch (error) {
29
+ try {
30
+ if (previous !== null)
31
+ await this.primary.set(previous);
32
+ }
33
+ catch (restoreError) {
34
+ throw new AggregateError([error, restoreError], "Legacy credential deletion and primary credential restore both failed", { cause: restoreError });
35
+ }
36
+ throw error;
37
+ }
38
+ }
39
+ }
40
+ //# sourceMappingURL=secret-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-store.js","sourceRoot":"","sources":["../../src/auth/secret-store.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,oBAAoB;IAEpB;IACA;IAFX,YACW,OAAoB,EACpB,MAAmB;QADnB,YAAO,GAAP,OAAO,CAAa;QACpB,WAAM,GAAN,MAAM,CAAa;IAC3B,CAAC;IAEJ,KAAK,CAAC,GAAG;QACP,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACzC,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QACvC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAa;QACrB,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1C,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC;gBACH,IAAI,QAAQ,KAAK,IAAI;oBAAE,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,YAAY,EAAE,CAAC;gBACtB,MAAM,IAAI,cAAc,CACtB,CAAC,KAAK,EAAE,YAAY,CAAC,EACrB,uEAAuE,EACvE,EAAE,KAAK,EAAE,YAAY,EAAE,CACxB,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import type { NormalizedSession } from "../domain/session.js";
2
+ export interface ImageArtifact {
3
+ sha256: string;
4
+ drivePath: string;
5
+ bytes: Buffer;
6
+ }
7
+ export declare function embeddedImageKey(data: string): string;
8
+ export declare function processSessionImages(session: NormalizedSession): Promise<{
9
+ artifacts: ImageArtifact[];
10
+ references: Map<string, string>;
11
+ }>;
@@ -0,0 +1,27 @@
1
+ import { createHash } from "node:crypto";
2
+ import sharp from "sharp";
3
+ export function embeddedImageKey(data) {
4
+ return createHash("sha256").update(Buffer.from(data, "base64")).digest("hex");
5
+ }
6
+ export async function processSessionImages(session) {
7
+ const artifacts = [];
8
+ const references = new Map();
9
+ for (const turn of session.turns) {
10
+ for (const image of turn.images) {
11
+ if (image.kind !== "embedded")
12
+ continue;
13
+ const sha256 = embeddedImageKey(image.data);
14
+ if (references.has(sha256))
15
+ continue;
16
+ const drivePath = `inbox/_assets/sha256/${sha256.slice(0, 2)}/${sha256}.webp`;
17
+ const bytes = await sharp(Buffer.from(image.data, "base64"))
18
+ .rotate()
19
+ .webp({ quality: 80 })
20
+ .toBuffer();
21
+ references.set(sha256, drivePath);
22
+ artifacts.push({ sha256, drivePath, bytes });
23
+ }
24
+ }
25
+ return { artifacts, references };
26
+ }
27
+ //# sourceMappingURL=images.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"images.js","sourceRoot":"","sources":["../../src/capture/images.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAA0B;IAK1B,MAAM,SAAS,GAAoB,EAAE,CAAC;IACtC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;gBAAE,SAAS;YACxC,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YACrC,MAAM,SAAS,GAAG,wBAAwB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC;YAC9E,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;iBACzD,MAAM,EAAE;iBACR,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;iBACrB,QAAQ,EAAE,CAAC;YACd,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAClC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { NormalizedSession } from "../domain/session.js";
2
+ export interface RenderOptions {
3
+ redactionVersion: number;
4
+ redactionCount: number;
5
+ imageReferences: Map<string, string>;
6
+ }
7
+ export declare function sessionFilename(session: NormalizedSession): string;
8
+ export declare function renderSessionMarkdown(session: NormalizedSession, options: RenderOptions): {
9
+ markdown: string;
10
+ contentSha256: string;
11
+ };
@@ -0,0 +1,43 @@
1
+ import { createHash } from "node:crypto";
2
+ import { embeddedImageKey } from "./images.js";
3
+ function renderImage(image, references) {
4
+ if (image.kind === "remote")
5
+ return `![](${image.url})`;
6
+ const path = references.get(embeddedImageKey(image.data));
7
+ return path ? `![](${path})` : null;
8
+ }
9
+ export function sessionFilename(session) {
10
+ const date = session.startedAt.slice(0, 10).replaceAll("-", "");
11
+ const shortId = session.conversationId
12
+ .replace(/[^A-Za-z0-9]/gu, "")
13
+ .slice(0, 8);
14
+ return `${session.source}-${date}-${shortId}.md`;
15
+ }
16
+ export function renderSessionMarkdown(session, options) {
17
+ const body = session.turns
18
+ .map((turn) => {
19
+ const images = turn.images
20
+ .map((image) => renderImage(image, options.imageReferences))
21
+ .filter((value) => Boolean(value));
22
+ const content = [turn.text, ...images].filter(Boolean).join("\n\n");
23
+ return `## ${turn.role === "user" ? "User" : "Assistant"}\n${content}`;
24
+ })
25
+ .join("\n\n");
26
+ const canonical = [
27
+ `source: ${session.source}`,
28
+ `conversation_id: ${session.conversationId}`,
29
+ `device: ${session.device}`,
30
+ `started_at: ${session.startedAt}`,
31
+ `updated_at: ${session.updatedAt}`,
32
+ `turn_count: ${session.turns.length}`,
33
+ `redaction_version: ${options.redactionVersion}`,
34
+ `redaction_count: ${options.redactionCount}`,
35
+ "---",
36
+ body,
37
+ "",
38
+ ].join("\n");
39
+ const contentSha256 = createHash("sha256").update(canonical).digest("hex");
40
+ const markdown = `---\n${canonical.replace("---\n", `content_sha256: ${contentSha256}\n---\n`)}`;
41
+ return { markdown, contentSha256 };
42
+ }
43
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/capture/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQ/C,SAAS,WAAW,CAClB,KAAe,EACf,UAA+B;IAE/B,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,OAAO,KAAK,CAAC,GAAG,GAAG,CAAC;IACxD,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAA0B;IACxD,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc;SACnC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC7B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACf,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAA0B,EAC1B,OAAsB;IAEtB,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK;SACvB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;aACvB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;aAC3D,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpE,OAAO,MAAM,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,KAAK,OAAO,EAAE,CAAC;IACzE,CAAC,CAAC;SACD,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,MAAM,SAAS,GAAG;QAChB,WAAW,OAAO,CAAC,MAAM,EAAE;QAC3B,oBAAoB,OAAO,CAAC,cAAc,EAAE;QAC5C,WAAW,OAAO,CAAC,MAAM,EAAE;QAC3B,eAAe,OAAO,CAAC,SAAS,EAAE;QAClC,eAAe,OAAO,CAAC,SAAS,EAAE;QAClC,eAAe,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE;QACrC,sBAAsB,OAAO,CAAC,gBAAgB,EAAE;QAChD,oBAAoB,OAAO,CAAC,cAAc,EAAE;QAC5C,KAAK;QACL,IAAI;QACJ,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,aAAa,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,QAAQ,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,mBAAmB,aAAa,SAAS,CAAC,EAAE,CAAC;IACjG,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AACrC,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface RedactionOptions {
2
+ internalDomains?: string[];
3
+ internalCidrs?: string[];
4
+ }
5
+ export interface RedactionResult {
6
+ text: string;
7
+ count: number;
8
+ version: 1;
9
+ }
10
+ export declare function redactText(input: string, options?: RedactionOptions): RedactionResult;
@@ -0,0 +1,60 @@
1
+ const replacement = "[REDACTED]";
2
+ function escapeRegExp(value) {
3
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
4
+ }
5
+ function ipv4ToInteger(value) {
6
+ const parts = value.split(".").map(Number);
7
+ if (parts.length !== 4 ||
8
+ parts.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) {
9
+ return null;
10
+ }
11
+ return parts.reduce((result, part) => ((result << 8) | part) >>> 0, 0);
12
+ }
13
+ function isInCidr(ip, cidr) {
14
+ const [networkText, prefixText] = cidr.split("/");
15
+ const ipValue = ipv4ToInteger(ip);
16
+ const network = networkText ? ipv4ToInteger(networkText) : null;
17
+ const prefix = Number(prefixText);
18
+ if (ipValue === null ||
19
+ network === null ||
20
+ !Number.isInteger(prefix) ||
21
+ prefix < 0 ||
22
+ prefix > 32) {
23
+ return false;
24
+ }
25
+ const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;
26
+ return (ipValue & mask) === (network & mask);
27
+ }
28
+ export function redactText(input, options = {}) {
29
+ let text = input;
30
+ let count = 0;
31
+ const replace = (pattern, replacer) => {
32
+ text = text.replace(pattern, (...args) => {
33
+ count += 1;
34
+ if (typeof replacer === "string")
35
+ return replacer;
36
+ return replacer(args[0], ...args.slice(1, -2));
37
+ });
38
+ };
39
+ replace(/-----BEGIN (?:[A-Z0-9]+ )?PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z0-9]+ )?PRIVATE KEY-----/gu, replacement);
40
+ replace(/(authorization\s*:\s*bearer\s+)[^\s]+/giu, (_match, prefix) => `${prefix}${replacement}`);
41
+ replace(/((?:"(?:password|passwd|pwd)"|'(?:password|passwd|pwd)'|(?:password|passwd|pwd))\s*[=:]\s*)(["'])([\s\S]*?)\2/giu, (_match, prefix, quote) => `${prefix}${quote}${replacement}${quote}`);
42
+ replace(/((?:password|passwd|pwd)\s*[=:]\s*)[^\s&;]+/giu, (_match, prefix) => `${prefix}${replacement}`);
43
+ replace(/((?:access[_-]?token|api[_-]?key|x-amz-signature|x-goog-signature|signature|sig)\s*[=:]\s*)[^\s&;]+/giu, (_match, prefix) => `${prefix}${replacement}`);
44
+ replace(/(https?:\/\/)[^\s/@:]+:[^\s/@]+@/giu, (_match, scheme) => `${scheme}${replacement}@`);
45
+ replace(/\bsk-[A-Za-z0-9_-]{20,}\b/gu, replacement);
46
+ for (const domain of options.internalDomains ?? []) {
47
+ if (!domain.trim())
48
+ continue;
49
+ replace(new RegExp(`\\b(?:[a-z0-9-]+\\.)*${escapeRegExp(domain)}\\b`, "giu"), replacement);
50
+ }
51
+ const cidrs = options.internalCidrs ?? [];
52
+ if (cidrs.length > 0) {
53
+ replace(/\b(?:\d{1,3}\.){3}\d{1,3}\b/gu, (ip) => cidrs.some((cidr) => isInCidr(ip, cidr)) ? replacement : ip);
54
+ // The replacement callback is invoked for every IPv4 candidate; compensate public addresses.
55
+ const candidates = input.match(/\b(?:\d{1,3}\.){3}\d{1,3}\b/gu) ?? [];
56
+ count -= candidates.filter((ip) => !cidrs.some((cidr) => isInCidr(ip, cidr))).length;
57
+ }
58
+ return { text, count, version: 1 };
59
+ }
60
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/capture/redact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import { type drive_v3 } from "googleapis";
3
+ import { GoogleOAuth, type GoogleOAuthClient } from "../auth/google-oauth.js";
4
+ import { type ConfigSecretStoreFactory } from "../auth/secret-store-factory.js";
5
+ import type { SecretStore } from "../auth/secret-store.js";
6
+ import { writeConfig } from "../domain/config-io.js";
7
+ import { type BackfillResult } from "../setup/backfill-service.js";
8
+ export interface CliDependencies {
9
+ writeOutput?: (value: string) => void;
10
+ secretStoreFactory?: ConfigSecretStoreFactory;
11
+ oauthFactory?: (clientFile: string, secrets: SecretStore) => Pick<GoogleOAuth, "beginInteractiveAuthorization" | "getClient">;
12
+ driveFactory?: (auth: GoogleOAuthClient) => drive_v3.Drive;
13
+ writeConfig?: typeof writeConfig;
14
+ runBackfill?: (options: {
15
+ yes: boolean;
16
+ json: boolean;
17
+ }) => Promise<BackfillResult>;
18
+ }
19
+ export declare function isAffirmativeConfirmation(value: string): boolean;
20
+ export declare function runCli(argv?: string[], dependencies?: CliDependencies): Promise<void>;