ahok-skill 1.3.1

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 (141) hide show
  1. package/.prettierrc +8 -0
  2. package/Dockerfile +59 -0
  3. package/RAW_SKILL.md +219 -0
  4. package/README.md +277 -0
  5. package/SKILL.md +58 -0
  6. package/bin/opm.js +268 -0
  7. package/data/openmemory.sqlite +0 -0
  8. package/data/openmemory.sqlite-shm +0 -0
  9. package/data/openmemory.sqlite-wal +0 -0
  10. package/dist/ai/graph.js +293 -0
  11. package/dist/ai/mcp.js +397 -0
  12. package/dist/cli.js +78 -0
  13. package/dist/core/cfg.js +87 -0
  14. package/dist/core/db.js +636 -0
  15. package/dist/core/memory.js +116 -0
  16. package/dist/core/migrate.js +227 -0
  17. package/dist/core/models.js +105 -0
  18. package/dist/core/telemetry.js +57 -0
  19. package/dist/core/types.js +2 -0
  20. package/dist/core/vector/postgres.js +52 -0
  21. package/dist/core/vector/valkey.js +246 -0
  22. package/dist/core/vector_store.js +2 -0
  23. package/dist/index.js +44 -0
  24. package/dist/memory/decay.js +301 -0
  25. package/dist/memory/embed.js +675 -0
  26. package/dist/memory/hsg.js +959 -0
  27. package/dist/memory/reflect.js +131 -0
  28. package/dist/memory/user_summary.js +99 -0
  29. package/dist/migrate.js +9 -0
  30. package/dist/ops/compress.js +255 -0
  31. package/dist/ops/dynamics.js +189 -0
  32. package/dist/ops/extract.js +333 -0
  33. package/dist/ops/ingest.js +214 -0
  34. package/dist/server/index.js +109 -0
  35. package/dist/server/middleware/auth.js +137 -0
  36. package/dist/server/routes/auth.js +186 -0
  37. package/dist/server/routes/compression.js +108 -0
  38. package/dist/server/routes/dashboard.js +399 -0
  39. package/dist/server/routes/docs.js +241 -0
  40. package/dist/server/routes/dynamics.js +312 -0
  41. package/dist/server/routes/ide.js +280 -0
  42. package/dist/server/routes/index.js +33 -0
  43. package/dist/server/routes/keys.js +132 -0
  44. package/dist/server/routes/langgraph.js +61 -0
  45. package/dist/server/routes/memory.js +213 -0
  46. package/dist/server/routes/sources.js +140 -0
  47. package/dist/server/routes/system.js +63 -0
  48. package/dist/server/routes/temporal.js +293 -0
  49. package/dist/server/routes/users.js +101 -0
  50. package/dist/server/routes/vercel.js +57 -0
  51. package/dist/server/server.js +211 -0
  52. package/dist/server.js +3 -0
  53. package/dist/sources/base.js +223 -0
  54. package/dist/sources/github.js +171 -0
  55. package/dist/sources/google_drive.js +166 -0
  56. package/dist/sources/google_sheets.js +112 -0
  57. package/dist/sources/google_slides.js +139 -0
  58. package/dist/sources/index.js +34 -0
  59. package/dist/sources/notion.js +165 -0
  60. package/dist/sources/onedrive.js +143 -0
  61. package/dist/sources/web_crawler.js +166 -0
  62. package/dist/temporal_graph/index.js +20 -0
  63. package/dist/temporal_graph/query.js +240 -0
  64. package/dist/temporal_graph/store.js +116 -0
  65. package/dist/temporal_graph/timeline.js +241 -0
  66. package/dist/temporal_graph/types.js +2 -0
  67. package/dist/utils/chunking.js +60 -0
  68. package/dist/utils/index.js +31 -0
  69. package/dist/utils/keyword.js +94 -0
  70. package/dist/utils/text.js +120 -0
  71. package/nodemon.json +7 -0
  72. package/package.json +50 -0
  73. package/references/api_reference.md +66 -0
  74. package/references/examples.md +45 -0
  75. package/src/ai/graph.ts +363 -0
  76. package/src/ai/mcp.ts +494 -0
  77. package/src/cli.ts +94 -0
  78. package/src/core/cfg.ts +110 -0
  79. package/src/core/db.ts +1052 -0
  80. package/src/core/memory.ts +99 -0
  81. package/src/core/migrate.ts +302 -0
  82. package/src/core/models.ts +107 -0
  83. package/src/core/telemetry.ts +47 -0
  84. package/src/core/types.ts +130 -0
  85. package/src/core/vector/postgres.ts +61 -0
  86. package/src/core/vector/valkey.ts +261 -0
  87. package/src/core/vector_store.ts +9 -0
  88. package/src/index.ts +5 -0
  89. package/src/memory/decay.ts +427 -0
  90. package/src/memory/embed.ts +707 -0
  91. package/src/memory/hsg.ts +1245 -0
  92. package/src/memory/reflect.ts +158 -0
  93. package/src/memory/user_summary.ts +110 -0
  94. package/src/migrate.ts +8 -0
  95. package/src/ops/compress.ts +296 -0
  96. package/src/ops/dynamics.ts +272 -0
  97. package/src/ops/extract.ts +360 -0
  98. package/src/ops/ingest.ts +286 -0
  99. package/src/server/index.ts +159 -0
  100. package/src/server/middleware/auth.ts +156 -0
  101. package/src/server/routes/auth.ts +223 -0
  102. package/src/server/routes/compression.ts +106 -0
  103. package/src/server/routes/dashboard.ts +420 -0
  104. package/src/server/routes/docs.ts +380 -0
  105. package/src/server/routes/dynamics.ts +516 -0
  106. package/src/server/routes/ide.ts +283 -0
  107. package/src/server/routes/index.ts +32 -0
  108. package/src/server/routes/keys.ts +131 -0
  109. package/src/server/routes/langgraph.ts +71 -0
  110. package/src/server/routes/memory.ts +440 -0
  111. package/src/server/routes/sources.ts +111 -0
  112. package/src/server/routes/system.ts +68 -0
  113. package/src/server/routes/temporal.ts +335 -0
  114. package/src/server/routes/users.ts +111 -0
  115. package/src/server/routes/vercel.ts +55 -0
  116. package/src/server/server.js +215 -0
  117. package/src/server.ts +1 -0
  118. package/src/sources/base.ts +257 -0
  119. package/src/sources/github.ts +156 -0
  120. package/src/sources/google_drive.ts +144 -0
  121. package/src/sources/google_sheets.ts +85 -0
  122. package/src/sources/google_slides.ts +115 -0
  123. package/src/sources/index.ts +19 -0
  124. package/src/sources/notion.ts +148 -0
  125. package/src/sources/onedrive.ts +131 -0
  126. package/src/sources/web_crawler.ts +161 -0
  127. package/src/temporal_graph/index.ts +4 -0
  128. package/src/temporal_graph/query.ts +299 -0
  129. package/src/temporal_graph/store.ts +156 -0
  130. package/src/temporal_graph/timeline.ts +319 -0
  131. package/src/temporal_graph/types.ts +41 -0
  132. package/src/utils/chunking.ts +66 -0
  133. package/src/utils/index.ts +25 -0
  134. package/src/utils/keyword.ts +137 -0
  135. package/src/utils/text.ts +115 -0
  136. package/tests/test_api_workspace_management.ts +413 -0
  137. package/tests/test_bulk_delete.ts +267 -0
  138. package/tests/test_omnibus.ts +166 -0
  139. package/tests/test_workspace_management.ts +278 -0
  140. package/tests/verify.ts +104 -0
  141. package/tsconfig.json +15 -0
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ /**
3
+ * base source class for openmemory data sources - production grade
4
+ *
5
+ * features:
6
+ * - custom exception hierarchy
7
+ * - logging
8
+ * - retry logic with exponential backoff
9
+ * - rate limiting
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.base_source = exports.rate_limiter = exports.source_fetch_error = exports.source_rate_limit_error = exports.source_config_error = exports.source_auth_error = exports.source_error = void 0;
46
+ exports.with_retry = with_retry;
47
+ // -- exceptions --
48
+ class source_error extends Error {
49
+ source;
50
+ cause;
51
+ constructor(msg, source, cause) {
52
+ super(source ? `[${source}] ${msg}` : msg);
53
+ this.name = 'source_error';
54
+ this.source = source;
55
+ this.cause = cause;
56
+ }
57
+ }
58
+ exports.source_error = source_error;
59
+ class source_auth_error extends source_error {
60
+ constructor(msg, source, cause) {
61
+ super(msg, source, cause);
62
+ this.name = 'source_auth_error';
63
+ }
64
+ }
65
+ exports.source_auth_error = source_auth_error;
66
+ class source_config_error extends source_error {
67
+ constructor(msg, source, cause) {
68
+ super(msg, source, cause);
69
+ this.name = 'source_config_error';
70
+ }
71
+ }
72
+ exports.source_config_error = source_config_error;
73
+ class source_rate_limit_error extends source_error {
74
+ retry_after;
75
+ constructor(msg, retry_after, source) {
76
+ super(msg, source);
77
+ this.name = 'source_rate_limit_error';
78
+ this.retry_after = retry_after;
79
+ }
80
+ }
81
+ exports.source_rate_limit_error = source_rate_limit_error;
82
+ class source_fetch_error extends source_error {
83
+ constructor(msg, source, cause) {
84
+ super(msg, source, cause);
85
+ this.name = 'source_fetch_error';
86
+ }
87
+ }
88
+ exports.source_fetch_error = source_fetch_error;
89
+ // -- rate limiter --
90
+ class rate_limiter {
91
+ rps;
92
+ tokens;
93
+ last_update;
94
+ constructor(requests_per_second = 10) {
95
+ this.rps = requests_per_second;
96
+ this.tokens = requests_per_second;
97
+ this.last_update = Date.now();
98
+ }
99
+ async acquire() {
100
+ const now = Date.now();
101
+ const elapsed = (now - this.last_update) / 1000;
102
+ this.tokens = Math.min(this.rps, this.tokens + elapsed * this.rps);
103
+ this.last_update = now;
104
+ if (this.tokens < 1) {
105
+ const wait_time = ((1 - this.tokens) / this.rps) * 1000;
106
+ await new Promise(r => setTimeout(r, wait_time));
107
+ this.tokens = 0;
108
+ }
109
+ else {
110
+ this.tokens -= 1;
111
+ }
112
+ }
113
+ }
114
+ exports.rate_limiter = rate_limiter;
115
+ // -- retry helper --
116
+ async function with_retry(fn, max_attempts = 3, base_delay = 1000, max_delay = 60000) {
117
+ let last_err = null;
118
+ for (let attempt = 0; attempt < max_attempts; attempt++) {
119
+ try {
120
+ return await fn();
121
+ }
122
+ catch (e) {
123
+ last_err = e;
124
+ if (e instanceof source_auth_error) {
125
+ throw e; // don't retry auth errors
126
+ }
127
+ if (attempt < max_attempts - 1) {
128
+ const delay = e instanceof source_rate_limit_error && e.retry_after
129
+ ? e.retry_after * 1000
130
+ : Math.min(base_delay * Math.pow(2, attempt), max_delay);
131
+ console.warn(`[retry] attempt ${attempt + 1}/${max_attempts} failed: ${e.message}, retrying in ${delay}ms`);
132
+ await new Promise(r => setTimeout(r, delay));
133
+ }
134
+ }
135
+ }
136
+ throw last_err;
137
+ }
138
+ // -- base source --
139
+ class base_source {
140
+ name = 'base';
141
+ user_id;
142
+ _connected = false;
143
+ _max_retries;
144
+ _rate_limiter;
145
+ constructor(user_id, config) {
146
+ this.user_id = user_id || 'anonymous';
147
+ this._max_retries = config?.max_retries || 3;
148
+ this._rate_limiter = new rate_limiter(config?.requests_per_second || 10);
149
+ }
150
+ get connected() {
151
+ return this._connected;
152
+ }
153
+ async connect(creds) {
154
+ console.log(`[${this.name}] connecting...`);
155
+ try {
156
+ const result = await this._connect(creds || {});
157
+ this._connected = result;
158
+ if (result) {
159
+ console.log(`[${this.name}] connected`);
160
+ }
161
+ return result;
162
+ }
163
+ catch (e) {
164
+ console.error(`[${this.name}] connection failed: ${e.message}`);
165
+ throw new source_auth_error(e.message, this.name, e);
166
+ }
167
+ }
168
+ async disconnect() {
169
+ this._connected = false;
170
+ console.log(`[${this.name}] disconnected`);
171
+ }
172
+ async list_items(filters) {
173
+ if (!this._connected) {
174
+ await this.connect();
175
+ }
176
+ await this._rate_limiter.acquire();
177
+ try {
178
+ const items = await with_retry(() => this._list_items(filters || {}), this._max_retries);
179
+ console.log(`[${this.name}] found ${items.length} items`);
180
+ return items;
181
+ }
182
+ catch (e) {
183
+ throw new source_fetch_error(e.message, this.name, e);
184
+ }
185
+ }
186
+ async fetch_item(item_id) {
187
+ if (!this._connected) {
188
+ await this.connect();
189
+ }
190
+ await this._rate_limiter.acquire();
191
+ try {
192
+ return await with_retry(() => this._fetch_item(item_id), this._max_retries);
193
+ }
194
+ catch (e) {
195
+ throw new source_fetch_error(e.message, this.name, e);
196
+ }
197
+ }
198
+ async ingest_all(filters) {
199
+ const { ingestDocument } = await Promise.resolve().then(() => __importStar(require('../ops/ingest')));
200
+ const items = await this.list_items(filters);
201
+ const ids = [];
202
+ const errors = [];
203
+ console.log(`[${this.name}] ingesting ${items.length} items...`);
204
+ for (let i = 0; i < items.length; i++) {
205
+ const item = items[i];
206
+ try {
207
+ const content = await this.fetch_item(item.id);
208
+ const result = await ingestDocument(content.type || 'text', content.data || content.text || '', { source: this.name, ...content.meta }, undefined, this.user_id);
209
+ ids.push(result.root_memory_id);
210
+ }
211
+ catch (e) {
212
+ console.warn(`[${this.name}] failed to ingest ${item.id}: ${e.message}`);
213
+ errors.push({ id: item.id, error: e.message });
214
+ }
215
+ }
216
+ console.log(`[${this.name}] ingested ${ids.length} items, ${errors.length} errors`);
217
+ return ids;
218
+ }
219
+ _get_env(key, default_val) {
220
+ return process.env[key] || default_val;
221
+ }
222
+ }
223
+ exports.base_source = base_source;
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ /**
3
+ * github source for openmemory - production grade
4
+ * requires: @octokit/rest
5
+ * env vars: GITHUB_TOKEN
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.github_source = void 0;
42
+ const base_1 = require("./base");
43
+ class github_source extends base_1.base_source {
44
+ name = 'github';
45
+ octokit = null;
46
+ async _connect(creds) {
47
+ let Octokit;
48
+ try {
49
+ Octokit = await Promise.resolve().then(() => __importStar(require('@octokit/rest'))).then(m => m.Octokit);
50
+ }
51
+ catch {
52
+ throw new base_1.source_config_error('missing deps: npm install @octokit/rest', this.name);
53
+ }
54
+ const token = creds.token || process.env.GITHUB_TOKEN;
55
+ if (!token) {
56
+ throw new base_1.source_config_error('no credentials: set GITHUB_TOKEN', this.name);
57
+ }
58
+ this.octokit = new Octokit({ auth: token });
59
+ return true;
60
+ }
61
+ async _list_items(filters) {
62
+ if (!filters.repo) {
63
+ throw new base_1.source_config_error('repo is required (format: owner/repo)', this.name);
64
+ }
65
+ const [owner, repo] = filters.repo.split('/');
66
+ const path = filters.path?.replace(/^\//, '') || '';
67
+ const include_issues = filters.include_issues || false;
68
+ const results = [];
69
+ // list files
70
+ try {
71
+ const resp = await this.octokit.repos.getContent({ owner, repo, path });
72
+ const contents = Array.isArray(resp.data) ? resp.data : [resp.data];
73
+ for (const content of contents) {
74
+ results.push({
75
+ id: `${filters.repo}:${content.path}`,
76
+ name: content.name,
77
+ type: content.type === 'dir' ? 'dir' : content.encoding || 'file',
78
+ path: content.path,
79
+ size: content.size || 0,
80
+ sha: content.sha
81
+ });
82
+ }
83
+ }
84
+ catch (e) {
85
+ console.warn(`[github] failed to list ${path}: ${e.message}`);
86
+ }
87
+ // list issues if requested
88
+ if (include_issues) {
89
+ try {
90
+ const resp = await this.octokit.issues.listForRepo({ owner, repo, state: 'all', per_page: 50 });
91
+ for (const issue of resp.data) {
92
+ results.push({
93
+ id: `${filters.repo}:issue:${issue.number}`,
94
+ name: issue.title,
95
+ type: 'issue',
96
+ number: issue.number,
97
+ state: issue.state,
98
+ labels: issue.labels.map((l) => l.name)
99
+ });
100
+ }
101
+ }
102
+ catch (e) {
103
+ console.warn(`[github] failed to list issues: ${e.message}`);
104
+ }
105
+ }
106
+ return results;
107
+ }
108
+ async _fetch_item(item_id) {
109
+ const parts = item_id.split(':');
110
+ const repo_full = parts[0];
111
+ const [owner, repo] = repo_full.split('/');
112
+ // issue
113
+ if (parts.length >= 3 && parts[1] === 'issue') {
114
+ const issue_num = parseInt(parts[2]);
115
+ const issue = await this.octokit.issues.get({ owner, repo, issue_number: issue_num });
116
+ const comments = await this.octokit.issues.listComments({ owner, repo, issue_number: issue_num });
117
+ const text_parts = [
118
+ `# ${issue.data.title}`,
119
+ `**State:** ${issue.data.state}`,
120
+ `**Labels:** ${issue.data.labels.map((l) => l.name).join(', ')}`,
121
+ '',
122
+ issue.data.body || ''
123
+ ];
124
+ for (const comment of comments.data) {
125
+ text_parts.push(`\n---\n**${comment.user?.login}:** ${comment.body}`);
126
+ }
127
+ const text = text_parts.join('\n');
128
+ return {
129
+ id: item_id,
130
+ name: issue.data.title,
131
+ type: 'issue',
132
+ text,
133
+ data: text,
134
+ meta: { source: 'github', repo: repo_full, issue_number: issue_num, state: issue.data.state }
135
+ };
136
+ }
137
+ // file
138
+ const path = parts.slice(1).join(':');
139
+ const resp = await this.octokit.repos.getContent({ owner, repo, path });
140
+ if (Array.isArray(resp.data)) {
141
+ const text = resp.data.map((c) => `- ${c.path}`).join('\n');
142
+ return {
143
+ id: item_id,
144
+ name: path || repo_full,
145
+ type: 'directory',
146
+ text,
147
+ data: text,
148
+ meta: { source: 'github', repo: repo_full, path }
149
+ };
150
+ }
151
+ const content = resp.data;
152
+ let text = '';
153
+ let data = '';
154
+ if (content.content) {
155
+ data = Buffer.from(content.content, 'base64');
156
+ try {
157
+ text = data.toString('utf-8');
158
+ }
159
+ catch { }
160
+ }
161
+ return {
162
+ id: item_id,
163
+ name: content.name,
164
+ type: content.encoding || 'file',
165
+ text,
166
+ data,
167
+ meta: { source: 'github', repo: repo_full, path: content.path, sha: content.sha, size: content.size }
168
+ };
169
+ }
170
+ }
171
+ exports.github_source = github_source;
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ /**
3
+ * google drive source for openmemory - production grade
4
+ * requires: googleapis
5
+ * env vars: GOOGLE_SERVICE_ACCOUNT_FILE or GOOGLE_CREDENTIALS_JSON
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.google_drive_source = void 0;
42
+ const base_1 = require("./base");
43
+ class google_drive_source extends base_1.base_source {
44
+ name = 'google_drive';
45
+ service = null;
46
+ auth = null;
47
+ async _connect(creds) {
48
+ let google;
49
+ try {
50
+ google = await Promise.resolve().then(() => __importStar(require('googleapis'))).then(m => m.google);
51
+ }
52
+ catch {
53
+ throw new base_1.source_config_error('missing deps: npm install googleapis', this.name);
54
+ }
55
+ const scopes = ['https://www.googleapis.com/auth/drive.readonly'];
56
+ if (creds.credentials_json) {
57
+ this.auth = new google.auth.GoogleAuth({
58
+ credentials: creds.credentials_json,
59
+ scopes
60
+ });
61
+ }
62
+ else if (creds.service_account_file) {
63
+ this.auth = new google.auth.GoogleAuth({
64
+ keyFile: creds.service_account_file,
65
+ scopes
66
+ });
67
+ }
68
+ else if (process.env.GOOGLE_CREDENTIALS_JSON) {
69
+ this.auth = new google.auth.GoogleAuth({
70
+ credentials: JSON.parse(process.env.GOOGLE_CREDENTIALS_JSON),
71
+ scopes
72
+ });
73
+ }
74
+ else if (process.env.GOOGLE_SERVICE_ACCOUNT_FILE) {
75
+ this.auth = new google.auth.GoogleAuth({
76
+ keyFile: process.env.GOOGLE_SERVICE_ACCOUNT_FILE,
77
+ scopes
78
+ });
79
+ }
80
+ else {
81
+ throw new base_1.source_config_error('no credentials: set GOOGLE_SERVICE_ACCOUNT_FILE or GOOGLE_CREDENTIALS_JSON', this.name);
82
+ }
83
+ this.service = google.drive({ version: 'v3', auth: this.auth });
84
+ return true;
85
+ }
86
+ async _list_items(filters) {
87
+ const q_parts = ['trashed=false'];
88
+ if (filters.folder_id) {
89
+ q_parts.push(`'${filters.folder_id}' in parents`);
90
+ }
91
+ if (filters.mime_types?.length) {
92
+ const mime_q = filters.mime_types.map((m) => `mimeType='${m}'`).join(' or ');
93
+ q_parts.push(`(${mime_q})`);
94
+ }
95
+ const query = q_parts.join(' and ');
96
+ const results = [];
97
+ let page_token;
98
+ do {
99
+ const resp = await this.service.files.list({
100
+ q: query,
101
+ spaces: 'drive',
102
+ fields: 'nextPageToken, files(id, name, mimeType, modifiedTime, size)',
103
+ pageToken: page_token,
104
+ pageSize: 100
105
+ });
106
+ for (const f of resp.data.files || []) {
107
+ results.push({
108
+ id: f.id,
109
+ name: f.name,
110
+ type: f.mimeType,
111
+ modified: f.modifiedTime,
112
+ size: f.size
113
+ });
114
+ }
115
+ page_token = resp.data.nextPageToken;
116
+ } while (page_token);
117
+ return results;
118
+ }
119
+ async _fetch_item(item_id) {
120
+ const meta = await this.service.files.get({
121
+ fileId: item_id,
122
+ fields: 'id,name,mimeType'
123
+ });
124
+ const mime = meta.data.mimeType;
125
+ let text = '';
126
+ let data = '';
127
+ // google docs -> export as text
128
+ if (mime === 'application/vnd.google-apps.document') {
129
+ const resp = await this.service.files.export({ fileId: item_id, mimeType: 'text/plain' });
130
+ text = resp.data;
131
+ data = text;
132
+ }
133
+ // google sheets -> export as csv
134
+ else if (mime === 'application/vnd.google-apps.spreadsheet') {
135
+ const resp = await this.service.files.export({ fileId: item_id, mimeType: 'text/csv' });
136
+ text = resp.data;
137
+ data = text;
138
+ }
139
+ // google slides -> export as plain text
140
+ else if (mime === 'application/vnd.google-apps.presentation') {
141
+ const resp = await this.service.files.export({ fileId: item_id, mimeType: 'text/plain' });
142
+ text = resp.data;
143
+ data = text;
144
+ }
145
+ // other files -> download raw
146
+ else {
147
+ const resp = await this.service.files.get({ fileId: item_id, alt: 'media' }, { responseType: 'arraybuffer' });
148
+ data = Buffer.from(resp.data);
149
+ try {
150
+ text = data.toString('utf-8');
151
+ }
152
+ catch {
153
+ text = '';
154
+ }
155
+ }
156
+ return {
157
+ id: item_id,
158
+ name: meta.data.name,
159
+ type: mime,
160
+ text,
161
+ data,
162
+ meta: { source: 'google_drive', file_id: item_id, mime_type: mime }
163
+ };
164
+ }
165
+ }
166
+ exports.google_drive_source = google_drive_source;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /**
3
+ * google sheets source for openmemory - production grade
4
+ * requires: googleapis
5
+ * env vars: GOOGLE_SERVICE_ACCOUNT_FILE or GOOGLE_CREDENTIALS_JSON
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.google_sheets_source = void 0;
42
+ const base_1 = require("./base");
43
+ class google_sheets_source extends base_1.base_source {
44
+ name = 'google_sheets';
45
+ service = null;
46
+ auth = null;
47
+ async _connect(creds) {
48
+ let google;
49
+ try {
50
+ google = await Promise.resolve().then(() => __importStar(require('googleapis'))).then(m => m.google);
51
+ }
52
+ catch {
53
+ throw new base_1.source_config_error('missing deps: npm install googleapis', this.name);
54
+ }
55
+ const scopes = ['https://www.googleapis.com/auth/spreadsheets.readonly'];
56
+ if (creds.credentials_json) {
57
+ this.auth = new google.auth.GoogleAuth({ credentials: creds.credentials_json, scopes });
58
+ }
59
+ else if (creds.service_account_file) {
60
+ this.auth = new google.auth.GoogleAuth({ keyFile: creds.service_account_file, scopes });
61
+ }
62
+ else if (process.env.GOOGLE_CREDENTIALS_JSON) {
63
+ this.auth = new google.auth.GoogleAuth({ credentials: JSON.parse(process.env.GOOGLE_CREDENTIALS_JSON), scopes });
64
+ }
65
+ else if (process.env.GOOGLE_SERVICE_ACCOUNT_FILE) {
66
+ this.auth = new google.auth.GoogleAuth({ keyFile: process.env.GOOGLE_SERVICE_ACCOUNT_FILE, scopes });
67
+ }
68
+ else {
69
+ throw new base_1.source_config_error('no credentials: set GOOGLE_SERVICE_ACCOUNT_FILE or GOOGLE_CREDENTIALS_JSON', this.name);
70
+ }
71
+ this.service = google.sheets({ version: 'v4', auth: this.auth });
72
+ return true;
73
+ }
74
+ async _list_items(filters) {
75
+ if (!filters.spreadsheet_id) {
76
+ throw new base_1.source_config_error('spreadsheet_id is required', this.name);
77
+ }
78
+ const meta = await this.service.spreadsheets.get({ spreadsheetId: filters.spreadsheet_id });
79
+ return (meta.data.sheets || []).map((sheet, i) => ({
80
+ id: `${filters.spreadsheet_id}!${sheet.properties?.title || 'Sheet1'}`,
81
+ name: sheet.properties?.title || 'Sheet1',
82
+ type: 'sheet',
83
+ index: i,
84
+ spreadsheet_id: filters.spreadsheet_id
85
+ }));
86
+ }
87
+ async _fetch_item(item_id) {
88
+ const [spreadsheet_id, sheet_range] = item_id.includes('!')
89
+ ? item_id.split('!', 2)
90
+ : [item_id, 'A:ZZ'];
91
+ const result = await this.service.spreadsheets.values.get({
92
+ spreadsheetId: spreadsheet_id,
93
+ range: sheet_range
94
+ });
95
+ const values = result.data.values || [];
96
+ // convert to markdown table
97
+ const lines = values.map((row, i) => {
98
+ const line = row.map(String).join(' | ');
99
+ return i === 0 ? `${line}\n${row.map(() => '---').join(' | ')}` : line;
100
+ });
101
+ const text = lines.join('\n');
102
+ return {
103
+ id: item_id,
104
+ name: sheet_range,
105
+ type: 'spreadsheet',
106
+ text,
107
+ data: text,
108
+ meta: { source: 'google_sheets', spreadsheet_id, range: sheet_range, row_count: values.length }
109
+ };
110
+ }
111
+ }
112
+ exports.google_sheets_source = google_sheets_source;