stellar-memory 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +362 -0
- package/dist/api/routes/analytics.d.ts +15 -0
- package/dist/api/routes/analytics.js +131 -0
- package/dist/api/routes/analytics.js.map +1 -0
- package/dist/api/routes/conflicts.d.ts +12 -0
- package/dist/api/routes/conflicts.js +67 -0
- package/dist/api/routes/conflicts.js.map +1 -0
- package/dist/api/routes/consolidation.d.ts +11 -0
- package/dist/api/routes/consolidation.js +63 -0
- package/dist/api/routes/consolidation.js.map +1 -0
- package/dist/api/routes/constellation.d.ts +4 -0
- package/dist/api/routes/constellation.js +84 -0
- package/dist/api/routes/constellation.js.map +1 -0
- package/dist/api/routes/memories.d.ts +4 -0
- package/dist/api/routes/memories.js +219 -0
- package/dist/api/routes/memories.js.map +1 -0
- package/dist/api/routes/observations.d.ts +10 -0
- package/dist/api/routes/observations.js +42 -0
- package/dist/api/routes/observations.js.map +1 -0
- package/dist/api/routes/orbit.d.ts +4 -0
- package/dist/api/routes/orbit.js +71 -0
- package/dist/api/routes/orbit.js.map +1 -0
- package/dist/api/routes/projects.d.ts +15 -0
- package/dist/api/routes/projects.js +121 -0
- package/dist/api/routes/projects.js.map +1 -0
- package/dist/api/routes/scan.d.ts +4 -0
- package/dist/api/routes/scan.js +403 -0
- package/dist/api/routes/scan.js.map +1 -0
- package/dist/api/routes/sun.d.ts +4 -0
- package/dist/api/routes/sun.js +43 -0
- package/dist/api/routes/sun.js.map +1 -0
- package/dist/api/routes/system.d.ts +4 -0
- package/dist/api/routes/system.js +70 -0
- package/dist/api/routes/system.js.map +1 -0
- package/dist/api/routes/temporal.d.ts +13 -0
- package/dist/api/routes/temporal.js +82 -0
- package/dist/api/routes/temporal.js.map +1 -0
- package/dist/api/server.d.ts +2 -0
- package/dist/api/server.js +99 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/websocket.d.ts +53 -0
- package/dist/api/websocket.js +168 -0
- package/dist/api/websocket.js.map +1 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.js +35 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +10 -0
- package/dist/cli/init.js +163 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/engine/analytics.d.ts +93 -0
- package/dist/engine/analytics.js +437 -0
- package/dist/engine/analytics.js.map +1 -0
- package/dist/engine/conflict.d.ts +54 -0
- package/dist/engine/conflict.js +322 -0
- package/dist/engine/conflict.js.map +1 -0
- package/dist/engine/consolidation.d.ts +83 -0
- package/dist/engine/consolidation.js +368 -0
- package/dist/engine/consolidation.js.map +1 -0
- package/dist/engine/constellation.d.ts +66 -0
- package/dist/engine/constellation.js +382 -0
- package/dist/engine/constellation.js.map +1 -0
- package/dist/engine/corona.d.ts +53 -0
- package/dist/engine/corona.js +181 -0
- package/dist/engine/corona.js.map +1 -0
- package/dist/engine/embedding.d.ts +44 -0
- package/dist/engine/embedding.js +168 -0
- package/dist/engine/embedding.js.map +1 -0
- package/dist/engine/gravity.d.ts +63 -0
- package/dist/engine/gravity.js +121 -0
- package/dist/engine/gravity.js.map +1 -0
- package/dist/engine/multiproject.d.ts +75 -0
- package/dist/engine/multiproject.js +241 -0
- package/dist/engine/multiproject.js.map +1 -0
- package/dist/engine/observation.d.ts +82 -0
- package/dist/engine/observation.js +357 -0
- package/dist/engine/observation.js.map +1 -0
- package/dist/engine/orbit.d.ts +91 -0
- package/dist/engine/orbit.js +249 -0
- package/dist/engine/orbit.js.map +1 -0
- package/dist/engine/planet.d.ts +64 -0
- package/dist/engine/planet.js +432 -0
- package/dist/engine/planet.js.map +1 -0
- package/dist/engine/procedural.d.ts +71 -0
- package/dist/engine/procedural.js +259 -0
- package/dist/engine/procedural.js.map +1 -0
- package/dist/engine/quality.d.ts +48 -0
- package/dist/engine/quality.js +245 -0
- package/dist/engine/quality.js.map +1 -0
- package/dist/engine/repository.d.ts +79 -0
- package/dist/engine/repository.js +13 -0
- package/dist/engine/repository.js.map +1 -0
- package/dist/engine/sun.d.ts +61 -0
- package/dist/engine/sun.js +240 -0
- package/dist/engine/sun.js.map +1 -0
- package/dist/engine/temporal.d.ts +67 -0
- package/dist/engine/temporal.js +283 -0
- package/dist/engine/temporal.js.map +1 -0
- package/dist/engine/types.d.ts +179 -0
- package/dist/engine/types.js +27 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +60 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/connector-registry.d.ts +20 -0
- package/dist/mcp/connector-registry.js +35 -0
- package/dist/mcp/connector-registry.js.map +1 -0
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +242 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/daemon-tool.d.ts +16 -0
- package/dist/mcp/tools/daemon-tool.js +58 -0
- package/dist/mcp/tools/daemon-tool.js.map +1 -0
- package/dist/mcp/tools/ingestion-tools.d.ts +20 -0
- package/dist/mcp/tools/ingestion-tools.js +34 -0
- package/dist/mcp/tools/ingestion-tools.js.map +1 -0
- package/dist/mcp/tools/memory-tools.d.ts +122 -0
- package/dist/mcp/tools/memory-tools.js +1037 -0
- package/dist/mcp/tools/memory-tools.js.map +1 -0
- package/dist/scanner/cloud/github.d.ts +34 -0
- package/dist/scanner/cloud/github.js +260 -0
- package/dist/scanner/cloud/github.js.map +1 -0
- package/dist/scanner/cloud/google-drive.d.ts +30 -0
- package/dist/scanner/cloud/google-drive.js +289 -0
- package/dist/scanner/cloud/google-drive.js.map +1 -0
- package/dist/scanner/cloud/notion.d.ts +33 -0
- package/dist/scanner/cloud/notion.js +231 -0
- package/dist/scanner/cloud/notion.js.map +1 -0
- package/dist/scanner/cloud/slack.d.ts +38 -0
- package/dist/scanner/cloud/slack.js +282 -0
- package/dist/scanner/cloud/slack.js.map +1 -0
- package/dist/scanner/cloud/types.d.ts +73 -0
- package/dist/scanner/cloud/types.js +9 -0
- package/dist/scanner/cloud/types.js.map +1 -0
- package/dist/scanner/index.d.ts +35 -0
- package/dist/scanner/index.js +420 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/local/filesystem.d.ts +33 -0
- package/dist/scanner/local/filesystem.js +203 -0
- package/dist/scanner/local/filesystem.js.map +1 -0
- package/dist/scanner/local/git.d.ts +24 -0
- package/dist/scanner/local/git.js +161 -0
- package/dist/scanner/local/git.js.map +1 -0
- package/dist/scanner/local/parsers/code.d.ts +3 -0
- package/dist/scanner/local/parsers/code.js +127 -0
- package/dist/scanner/local/parsers/code.js.map +1 -0
- package/dist/scanner/local/parsers/index.d.ts +11 -0
- package/dist/scanner/local/parsers/index.js +24 -0
- package/dist/scanner/local/parsers/index.js.map +1 -0
- package/dist/scanner/local/parsers/json-parser.d.ts +3 -0
- package/dist/scanner/local/parsers/json-parser.js +117 -0
- package/dist/scanner/local/parsers/json-parser.js.map +1 -0
- package/dist/scanner/local/parsers/markdown.d.ts +3 -0
- package/dist/scanner/local/parsers/markdown.js +120 -0
- package/dist/scanner/local/parsers/markdown.js.map +1 -0
- package/dist/scanner/local/parsers/text.d.ts +3 -0
- package/dist/scanner/local/parsers/text.js +41 -0
- package/dist/scanner/local/parsers/text.js.map +1 -0
- package/dist/scanner/metadata-scanner.d.ts +67 -0
- package/dist/scanner/metadata-scanner.js +356 -0
- package/dist/scanner/metadata-scanner.js.map +1 -0
- package/dist/scanner/types.d.ts +47 -0
- package/dist/scanner/types.js +19 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/service/daemon.d.ts +23 -0
- package/dist/service/daemon.js +105 -0
- package/dist/service/daemon.js.map +1 -0
- package/dist/service/scheduler.d.ts +73 -0
- package/dist/service/scheduler.js +281 -0
- package/dist/service/scheduler.js.map +1 -0
- package/dist/storage/database.d.ts +10 -0
- package/dist/storage/database.js +265 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/queries.d.ts +85 -0
- package/dist/storage/queries.js +865 -0
- package/dist/storage/queries.js.map +1 -0
- package/dist/storage/sqlite-repository.d.ts +32 -0
- package/dist/storage/sqlite-repository.js +68 -0
- package/dist/storage/sqlite-repository.js.map +1 -0
- package/dist/storage/vec.d.ts +62 -0
- package/dist/storage/vec.js +111 -0
- package/dist/storage/vec.js.map +1 -0
- package/dist/utils/config.d.ts +5 -0
- package/dist/utils/config.js +60 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/logger.js +86 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/time.d.ts +21 -0
- package/dist/utils/time.js +42 -0
- package/dist/utils/time.js.map +1 -0
- package/dist/utils/tokenizer.d.ts +13 -0
- package/dist/utils/tokenizer.js +46 -0
- package/dist/utils/tokenizer.js.map +1 -0
- package/package.json +77 -0
- package/scripts/check-node.mjs +36 -0
- package/scripts/setup.mjs +157 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scanner/cloud/slack.ts — Slack connector.
|
|
3
|
+
*
|
|
4
|
+
* Collects: channel message history, thread conversations, pinned messages.
|
|
5
|
+
* Intentionally EXCLUDES: DMs and private channels (privacy by default).
|
|
6
|
+
* DMs can be included by setting credential `include_dms=true` explicitly.
|
|
7
|
+
*
|
|
8
|
+
* Authentication: Bot Token (xoxb-…) with scopes:
|
|
9
|
+
* channels:history, channels:read, groups:history, groups:read,
|
|
10
|
+
* pins:read, users:read (for display names)
|
|
11
|
+
* Credential key: `bot_token`
|
|
12
|
+
*
|
|
13
|
+
* Rate limits: Slack Tier 3 = 50 req/min. We add 60ms between requests.
|
|
14
|
+
* Exponential backoff on 429 honouring the Retry-After header.
|
|
15
|
+
*
|
|
16
|
+
* Incremental sync: channel history accepts `oldest` (Unix timestamp).
|
|
17
|
+
*/
|
|
18
|
+
import { createLogger } from '../../utils/logger.js';
|
|
19
|
+
const log = createLogger('slack');
|
|
20
|
+
const SLACK_API_BASE = 'https://slack.com/api';
|
|
21
|
+
const MAX_RETRIES = 4;
|
|
22
|
+
const REQUEST_GAP_MS = 60; // ≈50 req/min
|
|
23
|
+
const MAX_MESSAGES_PER_CHANNEL = 200;
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// SlackConnector
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
export class SlackConnector {
|
|
28
|
+
name = 'Slack';
|
|
29
|
+
type = 'slack';
|
|
30
|
+
token = null;
|
|
31
|
+
includeDMs = false;
|
|
32
|
+
lastRequestAt = 0;
|
|
33
|
+
userCache = new Map();
|
|
34
|
+
// -------------------------------------------------------------------------
|
|
35
|
+
// authenticate
|
|
36
|
+
// -------------------------------------------------------------------------
|
|
37
|
+
async authenticate(credentials) {
|
|
38
|
+
const token = credentials['bot_token'];
|
|
39
|
+
if (!token || !token.startsWith('xoxb-')) {
|
|
40
|
+
throw new Error('SlackConnector requires a "bot_token" credential starting with "xoxb-"');
|
|
41
|
+
}
|
|
42
|
+
// Verify by calling auth.test
|
|
43
|
+
const res = await this.call('auth.test', {}, token);
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
throw new Error(`Slack authentication failed: ${res.error ?? 'unknown error'}`);
|
|
46
|
+
}
|
|
47
|
+
this.token = token;
|
|
48
|
+
this.includeDMs = credentials['include_dms'] === 'true';
|
|
49
|
+
log.info('Slack authentication successful', {
|
|
50
|
+
team: res.team,
|
|
51
|
+
botUser: res.user,
|
|
52
|
+
includeDMs: this.includeDMs,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
isAuthenticated() {
|
|
56
|
+
return this.token !== null;
|
|
57
|
+
}
|
|
58
|
+
// -------------------------------------------------------------------------
|
|
59
|
+
// fetchDocuments
|
|
60
|
+
// -------------------------------------------------------------------------
|
|
61
|
+
async fetchDocuments(since) {
|
|
62
|
+
this.assertAuthenticated();
|
|
63
|
+
log.info('Fetching Slack documents', { since: since?.toISOString() });
|
|
64
|
+
const channels = await this.listChannels();
|
|
65
|
+
log.info('Found Slack channels', { count: channels.length });
|
|
66
|
+
const docs = [];
|
|
67
|
+
for (const channel of channels) {
|
|
68
|
+
// Fetch pinned messages (highest value; always include regardless of since)
|
|
69
|
+
try {
|
|
70
|
+
const pins = await this.fetchPinnedMessages(channel);
|
|
71
|
+
docs.push(...pins);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
log.warn('Failed to fetch pinned messages', { channel: channel.name });
|
|
75
|
+
log.error('Pins error', err instanceof Error ? err : new Error(String(err)));
|
|
76
|
+
}
|
|
77
|
+
// Fetch recent message history
|
|
78
|
+
try {
|
|
79
|
+
const history = await this.fetchChannelHistory(channel, since);
|
|
80
|
+
if (history)
|
|
81
|
+
docs.push(history);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
log.warn('Failed to fetch channel history', { channel: channel.name });
|
|
85
|
+
log.error('History error', err instanceof Error ? err : new Error(String(err)));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return docs;
|
|
89
|
+
}
|
|
90
|
+
// -------------------------------------------------------------------------
|
|
91
|
+
// toMemory
|
|
92
|
+
// -------------------------------------------------------------------------
|
|
93
|
+
toMemory(doc) {
|
|
94
|
+
const isPinned = doc.metadata['docType'] === 'pinned';
|
|
95
|
+
return {
|
|
96
|
+
content: doc.content,
|
|
97
|
+
summary: doc.title.slice(0, 120),
|
|
98
|
+
type: isPinned ? 'context' : 'observation',
|
|
99
|
+
tags: ['slack', 'cloud', String(doc.metadata['channelName'] ?? '')].filter(Boolean),
|
|
100
|
+
source: 'cloud',
|
|
101
|
+
source_path: doc.url,
|
|
102
|
+
metadata: {
|
|
103
|
+
...doc.metadata,
|
|
104
|
+
cloudService: 'slack',
|
|
105
|
+
lastModified: doc.lastModified.toISOString(),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// -------------------------------------------------------------------------
|
|
110
|
+
// Private helpers
|
|
111
|
+
// -------------------------------------------------------------------------
|
|
112
|
+
assertAuthenticated() {
|
|
113
|
+
if (!this.isAuthenticated()) {
|
|
114
|
+
throw new Error('SlackConnector: not authenticated. Call authenticate() first.');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async call(method, params, token) {
|
|
118
|
+
const now = Date.now();
|
|
119
|
+
const elapsed = now - this.lastRequestAt;
|
|
120
|
+
if (elapsed < REQUEST_GAP_MS) {
|
|
121
|
+
await sleep(REQUEST_GAP_MS - elapsed);
|
|
122
|
+
}
|
|
123
|
+
this.lastRequestAt = Date.now();
|
|
124
|
+
const searchParams = new URLSearchParams(Object.entries(params).map(([k, v]) => [k, String(v)]));
|
|
125
|
+
const res = await fetchWithBackoff(`${SLACK_API_BASE}/${method}?${searchParams}`, {
|
|
126
|
+
headers: { Authorization: `Bearer ${token ?? this.token}` },
|
|
127
|
+
});
|
|
128
|
+
if (!res.ok) {
|
|
129
|
+
throw new Error(`Slack API HTTP error: ${res.status}`);
|
|
130
|
+
}
|
|
131
|
+
return res.json();
|
|
132
|
+
}
|
|
133
|
+
async listChannels() {
|
|
134
|
+
const types = this.includeDMs
|
|
135
|
+
? 'public_channel,private_channel,im,mpim'
|
|
136
|
+
: 'public_channel,private_channel';
|
|
137
|
+
const data = await this.call('conversations.list', {
|
|
138
|
+
limit: 200,
|
|
139
|
+
exclude_archived: true,
|
|
140
|
+
types,
|
|
141
|
+
});
|
|
142
|
+
if (!data.ok) {
|
|
143
|
+
throw new Error(`conversations.list failed: ${data.error}`);
|
|
144
|
+
}
|
|
145
|
+
return data['channels'] ?? [];
|
|
146
|
+
}
|
|
147
|
+
async fetchPinnedMessages(channel) {
|
|
148
|
+
const data = await this.call('pins.list', { channel: channel.id });
|
|
149
|
+
if (!data.ok)
|
|
150
|
+
return [];
|
|
151
|
+
const pins = data['items'] ?? [];
|
|
152
|
+
const docs = [];
|
|
153
|
+
for (const pin of pins) {
|
|
154
|
+
if (!pin.message?.text)
|
|
155
|
+
continue;
|
|
156
|
+
const msg = pin.message;
|
|
157
|
+
const ts = parseSlackTs(msg.ts);
|
|
158
|
+
const userName = await this.resolveUser(msg.user);
|
|
159
|
+
const url = buildSlackUrl(channel.id, msg.ts);
|
|
160
|
+
docs.push({
|
|
161
|
+
id: `slack-pin-${channel.id}-${msg.ts}`,
|
|
162
|
+
title: `Pinned in #${channel.name}: ${msg.text.slice(0, 80)}`,
|
|
163
|
+
content: `**Pinned message in #${channel.name}**\n\n${msg.text}`,
|
|
164
|
+
url,
|
|
165
|
+
mimeType: 'text/markdown',
|
|
166
|
+
lastModified: ts,
|
|
167
|
+
author: userName,
|
|
168
|
+
metadata: {
|
|
169
|
+
channelId: channel.id,
|
|
170
|
+
channelName: channel.name,
|
|
171
|
+
docType: 'pinned',
|
|
172
|
+
ts: msg.ts,
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return docs;
|
|
177
|
+
}
|
|
178
|
+
async fetchChannelHistory(channel, since) {
|
|
179
|
+
const params = {
|
|
180
|
+
channel: channel.id,
|
|
181
|
+
limit: MAX_MESSAGES_PER_CHANNEL,
|
|
182
|
+
};
|
|
183
|
+
if (since) {
|
|
184
|
+
params['oldest'] = (since.getTime() / 1000).toFixed(6);
|
|
185
|
+
}
|
|
186
|
+
const data = await this.call('conversations.history', params);
|
|
187
|
+
if (!data.ok)
|
|
188
|
+
return null;
|
|
189
|
+
const messages = data['messages'] ?? [];
|
|
190
|
+
if (messages.length === 0)
|
|
191
|
+
return null;
|
|
192
|
+
// Collect threads for messages with replies
|
|
193
|
+
const lines = [`## #${channel.name} — recent messages\n`];
|
|
194
|
+
for (const msg of messages.slice().reverse()) {
|
|
195
|
+
const ts = parseSlackTs(msg.ts);
|
|
196
|
+
const userName = await this.resolveUser(msg.user);
|
|
197
|
+
const dateStr = ts.toISOString().slice(0, 16).replace('T', ' ');
|
|
198
|
+
lines.push(`**${userName}** (${dateStr}):\n${msg.text}\n`);
|
|
199
|
+
// Fetch thread replies if any
|
|
200
|
+
if (msg.thread_ts && msg.reply_count && msg.reply_count > 0) {
|
|
201
|
+
const thread = await this.fetchThread(channel.id, msg.thread_ts);
|
|
202
|
+
for (const reply of thread.slice(1)) { // skip first (= parent)
|
|
203
|
+
const rUser = await this.resolveUser(reply.user);
|
|
204
|
+
const rTs = parseSlackTs(reply.ts).toISOString().slice(0, 16).replace('T', ' ');
|
|
205
|
+
lines.push(` > **${rUser}** (${rTs}):\n > ${reply.text}\n`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const newestTs = messages[0]?.ts ?? String(Date.now() / 1000);
|
|
210
|
+
return {
|
|
211
|
+
id: `slack-history-${channel.id}`,
|
|
212
|
+
title: `#${channel.name} history`,
|
|
213
|
+
content: lines.join('\n'),
|
|
214
|
+
url: buildSlackUrl(channel.id),
|
|
215
|
+
mimeType: 'text/markdown',
|
|
216
|
+
lastModified: parseSlackTs(newestTs),
|
|
217
|
+
metadata: {
|
|
218
|
+
channelId: channel.id,
|
|
219
|
+
channelName: channel.name,
|
|
220
|
+
messageCount: messages.length,
|
|
221
|
+
docType: 'channel_history',
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
async fetchThread(channelId, threadTs) {
|
|
226
|
+
const data = await this.call('conversations.replies', {
|
|
227
|
+
channel: channelId,
|
|
228
|
+
ts: threadTs,
|
|
229
|
+
limit: 50,
|
|
230
|
+
});
|
|
231
|
+
if (!data.ok)
|
|
232
|
+
return [];
|
|
233
|
+
return data['messages'] ?? [];
|
|
234
|
+
}
|
|
235
|
+
async resolveUser(userId) {
|
|
236
|
+
if (!userId)
|
|
237
|
+
return 'Unknown';
|
|
238
|
+
const cached = this.userCache.get(userId);
|
|
239
|
+
if (cached)
|
|
240
|
+
return cached;
|
|
241
|
+
try {
|
|
242
|
+
const data = await this.call('users.info', { user: userId });
|
|
243
|
+
if (data.ok) {
|
|
244
|
+
const user = data['user'];
|
|
245
|
+
const name = user.real_name ?? user.name ?? userId;
|
|
246
|
+
this.userCache.set(userId, name);
|
|
247
|
+
return name;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
// Non-critical; fallback to userId
|
|
252
|
+
}
|
|
253
|
+
this.userCache.set(userId, userId);
|
|
254
|
+
return userId;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
// Utilities
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
function parseSlackTs(ts) {
|
|
261
|
+
const seconds = parseFloat(ts);
|
|
262
|
+
return new Date(seconds * 1000);
|
|
263
|
+
}
|
|
264
|
+
function buildSlackUrl(channelId, ts) {
|
|
265
|
+
const base = `https://app.slack.com/client/${channelId}`;
|
|
266
|
+
return ts ? `${base}/${channelId}-${ts.replace('.', '')}` : base;
|
|
267
|
+
}
|
|
268
|
+
async function fetchWithBackoff(url, init, attempt = 0) {
|
|
269
|
+
const res = await fetch(url, init);
|
|
270
|
+
if (res.status === 429 && attempt < MAX_RETRIES) {
|
|
271
|
+
const retryAfter = parseInt(res.headers.get('Retry-After') ?? '1', 10);
|
|
272
|
+
const delay = Math.max(retryAfter * 1000, Math.min(1000 * 2 ** attempt, 30_000));
|
|
273
|
+
log.debug('Slack rate limited, retrying', { delay, attempt });
|
|
274
|
+
await sleep(delay);
|
|
275
|
+
return fetchWithBackoff(url, init, attempt + 1);
|
|
276
|
+
}
|
|
277
|
+
return res;
|
|
278
|
+
}
|
|
279
|
+
function sleep(ms) {
|
|
280
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=slack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack.js","sourceRoot":"","sources":["../../../src/scanner/cloud/slack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scanner/cloud/types.ts — Common interfaces for cloud connectors.
|
|
3
|
+
*
|
|
4
|
+
* Each cloud connector (Google Drive, Notion, GitHub, Slack) implements
|
|
5
|
+
* CloudConnector. The CloudDocument is the neutral transport format;
|
|
6
|
+
* toMemory() maps it into the shape required by the storage layer.
|
|
7
|
+
*/
|
|
8
|
+
import type { MemoryType } from '../../engine/types.js';
|
|
9
|
+
export interface CloudDocument {
|
|
10
|
+
/** Service-specific unique identifier */
|
|
11
|
+
id: string;
|
|
12
|
+
/** Human-readable title / subject */
|
|
13
|
+
title: string;
|
|
14
|
+
/** Plain-text body content */
|
|
15
|
+
content: string;
|
|
16
|
+
/** Canonical URL to the document */
|
|
17
|
+
url: string;
|
|
18
|
+
/** MIME type (e.g., "text/plain", "text/markdown") */
|
|
19
|
+
mimeType: string;
|
|
20
|
+
/** Last modification timestamp on the cloud service */
|
|
21
|
+
lastModified: Date;
|
|
22
|
+
/** Optional display name of the document author */
|
|
23
|
+
author?: string;
|
|
24
|
+
/** Arbitrary service-specific metadata */
|
|
25
|
+
metadata: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
export interface MemoryCreateInput {
|
|
28
|
+
content: string;
|
|
29
|
+
summary: string;
|
|
30
|
+
type: MemoryType;
|
|
31
|
+
tags: string[];
|
|
32
|
+
source: 'cloud';
|
|
33
|
+
source_path: string;
|
|
34
|
+
metadata: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
export interface CloudConnector {
|
|
37
|
+
/** Human-readable service name */
|
|
38
|
+
readonly name: string;
|
|
39
|
+
/** Discriminated union key used for routing / logging */
|
|
40
|
+
readonly type: 'google-drive' | 'notion' | 'github' | 'slack';
|
|
41
|
+
/**
|
|
42
|
+
* Authenticate with the cloud service.
|
|
43
|
+
* Credentials are passed as a plain-object map so each connector can define
|
|
44
|
+
* its own required keys without leaking them into the interface.
|
|
45
|
+
* Credentials must come from environment variables or a local config file —
|
|
46
|
+
* never from user-supplied untrusted input directly.
|
|
47
|
+
*/
|
|
48
|
+
authenticate(credentials: Record<string, string>): Promise<void>;
|
|
49
|
+
/** Returns true if the connector holds valid authentication state */
|
|
50
|
+
isAuthenticated(): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Fetch documents modified since the given date.
|
|
53
|
+
* When `since` is omitted the connector performs a full initial scan.
|
|
54
|
+
* Implementors must honour rate limits and apply exponential backoff on 429s.
|
|
55
|
+
*/
|
|
56
|
+
fetchDocuments(since?: Date): Promise<CloudDocument[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Convert a fetched CloudDocument into the shape needed to create a memory.
|
|
59
|
+
* Implementors must populate source_path with the document URL so the
|
|
60
|
+
* deduplication index can find duplicates on re-sync.
|
|
61
|
+
*/
|
|
62
|
+
toMemory(doc: CloudDocument): MemoryCreateInput;
|
|
63
|
+
}
|
|
64
|
+
export type ConnectorType = CloudConnector['type'];
|
|
65
|
+
/** Represents the persisted authentication state for a connector */
|
|
66
|
+
export interface ConnectorAuthState {
|
|
67
|
+
type: ConnectorType;
|
|
68
|
+
authenticated: boolean;
|
|
69
|
+
authenticatedAt: Date | null;
|
|
70
|
+
/** Redacted credential summary — never store raw secrets here */
|
|
71
|
+
summary: string;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scanner/cloud/types.ts — Common interfaces for cloud connectors.
|
|
3
|
+
*
|
|
4
|
+
* Each cloud connector (Google Drive, Notion, GitHub, Slack) implements
|
|
5
|
+
* CloudConnector. The CloudDocument is the neutral transport format;
|
|
6
|
+
* toMemory() maps it into the shape required by the storage layer.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/scanner/cloud/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ScanConfig, ScanResult } from './types.js';
|
|
2
|
+
export type ScanProgressEvent = {
|
|
3
|
+
phase: 'collecting' | 'collected' | 'processing' | 'path_complete';
|
|
4
|
+
path: string;
|
|
5
|
+
currentFile?: string;
|
|
6
|
+
totalFiles?: number;
|
|
7
|
+
scannedFiles?: number;
|
|
8
|
+
createdMemories?: number;
|
|
9
|
+
skippedFiles?: number;
|
|
10
|
+
errorFiles?: number;
|
|
11
|
+
};
|
|
12
|
+
export declare const FULL_SCAN_EXTRA_EXCLUDES: string[];
|
|
13
|
+
export declare class StellarScanner {
|
|
14
|
+
private readonly config;
|
|
15
|
+
private stopWatchers;
|
|
16
|
+
constructor(config?: Partial<ScanConfig>);
|
|
17
|
+
scan(): Promise<ScanResult>;
|
|
18
|
+
scanPath(dirPath: string, opts?: {
|
|
19
|
+
recursive?: boolean;
|
|
20
|
+
includeGit?: boolean;
|
|
21
|
+
}): Promise<ScanResult>;
|
|
22
|
+
scanWithProgress(opts: {
|
|
23
|
+
paths?: string[];
|
|
24
|
+
includeGit?: boolean;
|
|
25
|
+
onProgress: (event: ScanProgressEvent) => void;
|
|
26
|
+
abortSignal?: AbortSignal;
|
|
27
|
+
}): Promise<ScanResult>;
|
|
28
|
+
watch(): void;
|
|
29
|
+
stop(): void;
|
|
30
|
+
private _processFile;
|
|
31
|
+
private _insertGitMemories;
|
|
32
|
+
private _ensureDataSource;
|
|
33
|
+
}
|
|
34
|
+
export declare function listDataSources(): import("./types.js").DataSource[];
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|