@siftd/connect-agent 0.2.37 → 0.2.38
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/dist/agent.js +173 -13
- package/dist/api.d.ts +2 -0
- package/dist/cli.js +4 -1
- package/dist/config.d.ts +7 -0
- package/dist/config.js +41 -0
- package/dist/core/assets.js +12 -1
- package/dist/core/context-graph.d.ts +94 -0
- package/dist/core/context-graph.js +247 -0
- package/dist/core/file-tracker.js +3 -1
- package/dist/core/hub.js +36 -1
- package/dist/core/memory-advanced.d.ts +5 -0
- package/dist/core/memory-advanced.js +27 -0
- package/dist/core/memory-postgres.d.ts +9 -0
- package/dist/core/memory-postgres.js +48 -0
- package/dist/core/preview-worker.js +3 -0
- package/dist/orchestrator.d.ts +46 -0
- package/dist/orchestrator.js +874 -26
- package/dist/tools/calendar.d.ts +50 -0
- package/dist/tools/calendar.js +233 -0
- package/dist/tools/worker.d.ts +6 -1
- package/dist/tools/worker.js +6 -0
- package/dist/workers/manager.d.ts +7 -0
- package/dist/workers/manager.js +35 -5
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { spawn, execSync } from 'child_process';
|
|
2
|
+
import { createWriteStream } from 'fs';
|
|
3
|
+
import { mkdir, stat } from 'fs/promises';
|
|
4
|
+
import { Readable } from 'stream';
|
|
5
|
+
import { pipeline } from 'stream/promises';
|
|
6
|
+
import { basename, join, parse } from 'path';
|
|
2
7
|
import { pollMessages, sendResponse } from './api.js';
|
|
3
|
-
import { getUserId, getAnthropicApiKey, isCloudMode, getDeploymentInfo } from './config.js';
|
|
8
|
+
import { getUserId, getOrgId, getAnthropicApiKey, isCloudMode, getDeploymentInfo, getInstanceMode, getUserOrgIds } from './config.js';
|
|
4
9
|
import { MasterOrchestrator } from './orchestrator.js';
|
|
5
10
|
import { AgentWebSocket } from './websocket.js';
|
|
6
11
|
import { startHeartbeat, stopHeartbeat, getHeartbeatState } from './heartbeat.js';
|
|
@@ -11,6 +16,97 @@ import { startPreviewWorker, stopPreviewWorker } from './core/preview-worker.js'
|
|
|
11
16
|
function stripAnsi(str) {
|
|
12
17
|
return str.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, '');
|
|
13
18
|
}
|
|
19
|
+
function parseAttachments(content) {
|
|
20
|
+
const marker = '📎 Attached files:';
|
|
21
|
+
const index = content.indexOf(marker);
|
|
22
|
+
if (index === -1)
|
|
23
|
+
return [];
|
|
24
|
+
const lines = content
|
|
25
|
+
.slice(index + marker.length)
|
|
26
|
+
.split('\n')
|
|
27
|
+
.map((line) => line.trim())
|
|
28
|
+
.filter(Boolean);
|
|
29
|
+
const attachments = [];
|
|
30
|
+
for (const line of lines) {
|
|
31
|
+
const match = line.match(/^(.+?):\s*(https?:\/\/\S+)$/);
|
|
32
|
+
if (!match)
|
|
33
|
+
continue;
|
|
34
|
+
attachments.push({ name: match[1].trim(), url: match[2].trim() });
|
|
35
|
+
}
|
|
36
|
+
return attachments;
|
|
37
|
+
}
|
|
38
|
+
function stripAttachmentBlock(content) {
|
|
39
|
+
const marker = '📎 Attached files:';
|
|
40
|
+
const index = content.indexOf(marker);
|
|
41
|
+
if (index === -1)
|
|
42
|
+
return content;
|
|
43
|
+
return content.slice(0, index).trim();
|
|
44
|
+
}
|
|
45
|
+
function isSaveIntent(text) {
|
|
46
|
+
const lower = text.toLowerCase();
|
|
47
|
+
if (!lower)
|
|
48
|
+
return true;
|
|
49
|
+
const analysis = /(analy|summarize|review|explain|inspect|diff|lint|test|build|run)/;
|
|
50
|
+
if (analysis.test(lower))
|
|
51
|
+
return false;
|
|
52
|
+
return /(save|store|archive|upload|attach|add|file|keep)/.test(lower);
|
|
53
|
+
}
|
|
54
|
+
async function fileExists(path) {
|
|
55
|
+
try {
|
|
56
|
+
await stat(path);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function getUniquePath(dir, filename) {
|
|
64
|
+
const safeName = basename(filename).replace(/[\\/:*?"<>|]/g, '_');
|
|
65
|
+
const parsed = parse(safeName);
|
|
66
|
+
let candidate = join(dir, safeName);
|
|
67
|
+
let counter = 1;
|
|
68
|
+
while (await fileExists(candidate)) {
|
|
69
|
+
candidate = join(dir, `${parsed.name}-${counter}${parsed.ext}`);
|
|
70
|
+
counter += 1;
|
|
71
|
+
}
|
|
72
|
+
return candidate;
|
|
73
|
+
}
|
|
74
|
+
function humanizePath(path) {
|
|
75
|
+
const home = process.env.HOME;
|
|
76
|
+
if (home && path.startsWith(home)) {
|
|
77
|
+
return `~${path.slice(home.length)}`;
|
|
78
|
+
}
|
|
79
|
+
return path;
|
|
80
|
+
}
|
|
81
|
+
async function saveAttachments(attachments, onProgress) {
|
|
82
|
+
const home = process.env.HOME || '/tmp';
|
|
83
|
+
const targetDir = join(home, 'Lia-Hub', 'shared', 'outputs', 'safe-files');
|
|
84
|
+
await mkdir(targetDir, { recursive: true });
|
|
85
|
+
const results = [];
|
|
86
|
+
for (const attachment of attachments) {
|
|
87
|
+
const targetPath = await getUniquePath(targetDir, attachment.name);
|
|
88
|
+
onProgress?.(`Saving ${attachment.name}...`);
|
|
89
|
+
try {
|
|
90
|
+
const response = await fetch(attachment.url);
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
93
|
+
}
|
|
94
|
+
if (!response.body) {
|
|
95
|
+
throw new Error('Empty response body');
|
|
96
|
+
}
|
|
97
|
+
const stream = Readable.fromWeb(response.body);
|
|
98
|
+
await pipeline(stream, createWriteStream(targetPath));
|
|
99
|
+
results.push({ name: attachment.name, path: targetPath });
|
|
100
|
+
onProgress?.(`Saved ${attachment.name} → ${humanizePath(targetPath)}`);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
104
|
+
results.push({ name: attachment.name, path: targetPath, error: message });
|
|
105
|
+
onProgress?.(`Failed ${attachment.name}: ${message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return results;
|
|
109
|
+
}
|
|
14
110
|
/**
|
|
15
111
|
* Self-update: npm install latest and auto-restart
|
|
16
112
|
* Called from webapp banner or update command
|
|
@@ -62,6 +158,9 @@ function initOrchestrator() {
|
|
|
62
158
|
// Check env first, then stored config
|
|
63
159
|
const apiKey = process.env.ANTHROPIC_API_KEY || getAnthropicApiKey();
|
|
64
160
|
const userId = getUserId();
|
|
161
|
+
const orgId = getOrgId();
|
|
162
|
+
const instanceMode = getInstanceMode();
|
|
163
|
+
const userOrgIds = getUserOrgIds();
|
|
65
164
|
if (!apiKey) {
|
|
66
165
|
console.log('[AGENT] No API key - using simple relay mode');
|
|
67
166
|
console.log('[AGENT] To enable orchestrator: pair with --api-key flag');
|
|
@@ -71,12 +170,21 @@ function initOrchestrator() {
|
|
|
71
170
|
console.log('[AGENT] No userId configured - using simple relay mode');
|
|
72
171
|
return null;
|
|
73
172
|
}
|
|
74
|
-
console.log(
|
|
173
|
+
console.log(`[AGENT] Initializing Master Orchestrator (mode: ${instanceMode})...`);
|
|
174
|
+
if (instanceMode === 'personal' && userOrgIds.length > 0) {
|
|
175
|
+
console.log(`[AGENT] Personal mode with access to ${userOrgIds.length} team(s): ${userOrgIds.join(', ')}`);
|
|
176
|
+
}
|
|
177
|
+
if (instanceMode === 'team' && orgId) {
|
|
178
|
+
console.log(`[AGENT] Team mode for org: ${orgId}`);
|
|
179
|
+
}
|
|
75
180
|
return new MasterOrchestrator({
|
|
76
181
|
apiKey,
|
|
77
182
|
userId,
|
|
183
|
+
orgId: orgId || undefined,
|
|
78
184
|
workspaceDir: process.env.HOME || '/tmp',
|
|
79
|
-
voyageApiKey: process.env.VOYAGE_API_KEY
|
|
185
|
+
voyageApiKey: process.env.VOYAGE_API_KEY,
|
|
186
|
+
instanceMode,
|
|
187
|
+
userOrgIds: instanceMode === 'personal' ? userOrgIds : undefined,
|
|
80
188
|
});
|
|
81
189
|
}
|
|
82
190
|
/**
|
|
@@ -137,6 +245,17 @@ async function sendToOrchestrator(input, orch, messageId, apiKey) {
|
|
|
137
245
|
if (wsClient?.connected()) {
|
|
138
246
|
wsClient.sendTyping(true);
|
|
139
247
|
}
|
|
248
|
+
const workerLogHandler = (workerId, line, stream) => {
|
|
249
|
+
if (!wsClient?.connected() || !messageId)
|
|
250
|
+
return;
|
|
251
|
+
const prefix = stream === 'stderr' ? `${workerId} stderr` : workerId;
|
|
252
|
+
const chunks = line.split(/\r?\n/).map(part => part.trim()).filter(Boolean);
|
|
253
|
+
for (const chunk of chunks) {
|
|
254
|
+
const trimmed = chunk.slice(0, 400);
|
|
255
|
+
wsClient.sendProgress(messageId, `[${prefix}] ${trimmed}`);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
orch.setWorkerLogCallback(workerLogHandler);
|
|
140
259
|
try {
|
|
141
260
|
const response = await orch.processMessage(input, conversationHistory, async (msg) => {
|
|
142
261
|
// Progress callback - log to console and send via WebSocket
|
|
@@ -172,6 +291,9 @@ async function sendToOrchestrator(input, orch, messageId, apiKey) {
|
|
|
172
291
|
}
|
|
173
292
|
return `Error: ${error instanceof Error ? error.message : 'Unknown error'}`;
|
|
174
293
|
}
|
|
294
|
+
finally {
|
|
295
|
+
orch.setWorkerLogCallback(null);
|
|
296
|
+
}
|
|
175
297
|
}
|
|
176
298
|
export async function processMessage(message) {
|
|
177
299
|
console.log(`\n[WEB] >>> ${message.content}`);
|
|
@@ -200,6 +322,42 @@ export async function processMessage(message) {
|
|
|
200
322
|
console.log('[AGENT] === SYSTEM UPDATE COMMAND ===');
|
|
201
323
|
return await performSelfUpdate();
|
|
202
324
|
}
|
|
325
|
+
const attachments = parseAttachments(message.content);
|
|
326
|
+
if (attachments.length > 0) {
|
|
327
|
+
const progress = (msgText) => {
|
|
328
|
+
if (wsClient?.connected() && message.id) {
|
|
329
|
+
wsClient.sendProgress(message.id, msgText);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
const results = await saveAttachments(attachments, progress);
|
|
333
|
+
const saved = results.filter((entry) => !entry.error);
|
|
334
|
+
const failed = results.filter((entry) => entry.error);
|
|
335
|
+
const savedLines = saved.map((entry) => `- ${humanizePath(entry.path)}`).join('\n');
|
|
336
|
+
const failedLines = failed
|
|
337
|
+
.map((entry) => `- ${entry.name}: ${entry.error}`)
|
|
338
|
+
.join('\n');
|
|
339
|
+
const baseText = stripAttachmentBlock(message.content);
|
|
340
|
+
if (isSaveIntent(baseText)) {
|
|
341
|
+
const responseLines = [
|
|
342
|
+
saved.length > 0 ? `Saved ${saved.length} file${saved.length === 1 ? '' : 's'}:` : 'No files saved.',
|
|
343
|
+
savedLines,
|
|
344
|
+
failed.length > 0 ? `\nFailed ${failed.length} file${failed.length === 1 ? '' : 's'}:\n${failedLines}` : ''
|
|
345
|
+
].filter(Boolean);
|
|
346
|
+
const response = responseLines.join('\n');
|
|
347
|
+
conversationHistory.push({ role: 'user', content: message.content });
|
|
348
|
+
conversationHistory.push({ role: 'assistant', content: response });
|
|
349
|
+
return response;
|
|
350
|
+
}
|
|
351
|
+
const savedNote = [
|
|
352
|
+
'Saved attachments locally:',
|
|
353
|
+
savedLines || '- (none)',
|
|
354
|
+
failed.length > 0 ? `Failed downloads:\n${failedLines}` : ''
|
|
355
|
+
].filter(Boolean).join('\n');
|
|
356
|
+
message = {
|
|
357
|
+
...message,
|
|
358
|
+
content: `${message.content}\n\n${savedNote}`
|
|
359
|
+
};
|
|
360
|
+
}
|
|
203
361
|
try {
|
|
204
362
|
if (orchestrator) {
|
|
205
363
|
return await sendToOrchestrator(message.content, orchestrator, message.id, message.apiKey);
|
|
@@ -339,19 +497,21 @@ export async function runAgent(pollInterval = 2000) {
|
|
|
339
497
|
});
|
|
340
498
|
// Keep process alive - WebSocket handles messages
|
|
341
499
|
console.log('[AGENT] Listening for WebSocket messages...\n');
|
|
342
|
-
//
|
|
500
|
+
// Poll only if WebSocket is not connected (WS input is preferred for latency).
|
|
343
501
|
while (true) {
|
|
344
502
|
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
503
|
+
if (!wsClient?.connected()) {
|
|
504
|
+
try {
|
|
505
|
+
const { messages } = await pollMessages();
|
|
506
|
+
for (const msg of messages) {
|
|
507
|
+
const response = await processMessage(msg);
|
|
508
|
+
await sendResponse(msg.id, response);
|
|
509
|
+
console.log(`[AGENT] Response sent (${response.length} chars)`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
catch (error) {
|
|
513
|
+
console.error('[AGENT] Poll error:', error.message);
|
|
351
514
|
}
|
|
352
|
-
}
|
|
353
|
-
catch (error) {
|
|
354
|
-
console.error('[AGENT] Poll error:', error.message);
|
|
355
515
|
}
|
|
356
516
|
}
|
|
357
517
|
}
|
package/dist/api.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { program } from 'commander';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
-
import { getServerUrl, setServerUrl, setAgentToken, setUserId, setAnthropicApiKey, getAnthropicApiKey, isConfigured, clearConfig, getConfigPath, } from './config.js';
|
|
4
|
+
import { getServerUrl, setServerUrl, setAgentToken, setUserId, setOrgId, setAnthropicApiKey, getAnthropicApiKey, isConfigured, clearConfig, getConfigPath, } from './config.js';
|
|
5
5
|
import { connectWithPairingCode, checkConnection } from './api.js';
|
|
6
6
|
import { runAgent } from './agent.js';
|
|
7
7
|
import { ensureLiaHub, getLiaHubPaths } from './core/hub.js';
|
|
@@ -29,6 +29,9 @@ program
|
|
|
29
29
|
}
|
|
30
30
|
setAgentToken(result.agentToken);
|
|
31
31
|
setUserId(result.userId);
|
|
32
|
+
if (result.orgId) {
|
|
33
|
+
setOrgId(result.orgId);
|
|
34
|
+
}
|
|
32
35
|
// Store API key if provided
|
|
33
36
|
if (options.apiKey) {
|
|
34
37
|
setAnthropicApiKey(options.apiKey);
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export type InstanceMode = 'personal' | 'team';
|
|
1
2
|
/**
|
|
2
3
|
* Check if running in cloud mode (environment variables take precedence)
|
|
3
4
|
*/
|
|
@@ -8,6 +9,12 @@ export declare function getAgentToken(): string | null;
|
|
|
8
9
|
export declare function setAgentToken(token: string | null): void;
|
|
9
10
|
export declare function getUserId(): string | null;
|
|
10
11
|
export declare function setUserId(id: string | null): void;
|
|
12
|
+
export declare function getOrgId(): string | null;
|
|
13
|
+
export declare function setOrgId(id: string | null): void;
|
|
14
|
+
export declare function getInstanceMode(): InstanceMode;
|
|
15
|
+
export declare function setInstanceMode(mode: InstanceMode | null): void;
|
|
16
|
+
export declare function getUserOrgIds(): string[];
|
|
17
|
+
export declare function setUserOrgIds(ids: string[] | null): void;
|
|
11
18
|
export declare function getAnthropicApiKey(): string | null;
|
|
12
19
|
export declare function setAnthropicApiKey(key: string | null): void;
|
|
13
20
|
export declare function isConfigured(): boolean;
|
package/dist/config.js
CHANGED
|
@@ -42,6 +42,46 @@ export function setUserId(id) {
|
|
|
42
42
|
config.set('userId', id);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
+
export function getOrgId() {
|
|
46
|
+
return process.env.CONNECT_ORG_ID || config.get('orgId') || null;
|
|
47
|
+
}
|
|
48
|
+
export function setOrgId(id) {
|
|
49
|
+
if (id === null) {
|
|
50
|
+
config.delete('orgId');
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
config.set('orgId', id);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function getInstanceMode() {
|
|
57
|
+
const mode = process.env.CONNECT_INSTANCE_MODE || config.get('instanceMode');
|
|
58
|
+
return mode === 'team' ? 'team' : 'personal';
|
|
59
|
+
}
|
|
60
|
+
export function setInstanceMode(mode) {
|
|
61
|
+
if (mode === null) {
|
|
62
|
+
config.delete('instanceMode');
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
config.set('instanceMode', mode);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function getUserOrgIds() {
|
|
69
|
+
// From env: comma-separated list
|
|
70
|
+
const envOrgIds = process.env.CONNECT_USER_ORG_IDS;
|
|
71
|
+
if (envOrgIds) {
|
|
72
|
+
return envOrgIds.split(',').map(id => id.trim()).filter(Boolean);
|
|
73
|
+
}
|
|
74
|
+
// From config
|
|
75
|
+
return config.get('userOrgIds') || [];
|
|
76
|
+
}
|
|
77
|
+
export function setUserOrgIds(ids) {
|
|
78
|
+
if (ids === null || ids.length === 0) {
|
|
79
|
+
config.delete('userOrgIds');
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
config.set('userOrgIds', ids);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
45
85
|
export function getAnthropicApiKey() {
|
|
46
86
|
// Environment variable takes precedence (cloud mode)
|
|
47
87
|
// Note: ANTHROPIC_API_KEY is also checked in orchestrator.ts
|
|
@@ -61,6 +101,7 @@ export function isConfigured() {
|
|
|
61
101
|
export function clearConfig() {
|
|
62
102
|
config.delete('agentToken');
|
|
63
103
|
config.delete('userId');
|
|
104
|
+
config.delete('orgId');
|
|
64
105
|
config.delete('anthropicApiKey');
|
|
65
106
|
}
|
|
66
107
|
export function getConfigPath() {
|
package/dist/core/assets.js
CHANGED
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
import { createHash } from 'crypto';
|
|
8
8
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, realpathSync } from 'fs';
|
|
9
9
|
import { basename, extname, join, relative, sep } from 'path';
|
|
10
|
+
const ASSET_MANIFEST_SUFFIX = '.asset.json';
|
|
11
|
+
const ASSET_PREVIEW_SUFFIX = '.preview.json';
|
|
12
|
+
function isAssetMetadataFile(filePath) {
|
|
13
|
+
return filePath.includes(ASSET_MANIFEST_SUFFIX) || filePath.includes(ASSET_PREVIEW_SUFFIX);
|
|
14
|
+
}
|
|
10
15
|
/**
|
|
11
16
|
* Convert internal manifest to client-safe version (strips path)
|
|
12
17
|
*/
|
|
@@ -123,6 +128,8 @@ export function createAssetManifest(filePath, options = {}) {
|
|
|
123
128
|
* Write asset manifest alongside the file
|
|
124
129
|
*/
|
|
125
130
|
export function writeAssetManifest(manifest) {
|
|
131
|
+
if (isAssetMetadataFile(manifest.path))
|
|
132
|
+
return;
|
|
126
133
|
const manifestPath = manifest.path + '.asset.json';
|
|
127
134
|
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
128
135
|
}
|
|
@@ -130,7 +137,11 @@ export function writeAssetManifest(manifest) {
|
|
|
130
137
|
* Read asset manifest for a file
|
|
131
138
|
*/
|
|
132
139
|
export function readAssetManifest(filePath) {
|
|
133
|
-
|
|
140
|
+
if (filePath.includes(ASSET_PREVIEW_SUFFIX))
|
|
141
|
+
return null;
|
|
142
|
+
const manifestPath = filePath.includes(ASSET_MANIFEST_SUFFIX)
|
|
143
|
+
? filePath
|
|
144
|
+
: filePath + '.asset.json';
|
|
134
145
|
if (!existsSync(manifestPath))
|
|
135
146
|
return null;
|
|
136
147
|
try {
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
type MemoryType = 'episodic' | 'semantic' | 'procedural' | 'working';
|
|
2
|
+
type MemoryRecord = {
|
|
3
|
+
id: string;
|
|
4
|
+
content: string;
|
|
5
|
+
timestamp: string;
|
|
6
|
+
source: string;
|
|
7
|
+
tags: string[];
|
|
8
|
+
};
|
|
9
|
+
type MemoryStore = {
|
|
10
|
+
remember: (content: string, options?: {
|
|
11
|
+
type?: MemoryType;
|
|
12
|
+
source?: string;
|
|
13
|
+
importance?: number;
|
|
14
|
+
tags?: string[];
|
|
15
|
+
}) => Promise<string>;
|
|
16
|
+
search: (query: string, options?: {
|
|
17
|
+
limit?: number;
|
|
18
|
+
type?: MemoryType;
|
|
19
|
+
minImportance?: number;
|
|
20
|
+
}) => Promise<MemoryRecord[]>;
|
|
21
|
+
findByTags?: (tags: string[], options?: {
|
|
22
|
+
limit?: number;
|
|
23
|
+
type?: MemoryType;
|
|
24
|
+
minImportance?: number;
|
|
25
|
+
}) => Promise<MemoryRecord[]>;
|
|
26
|
+
};
|
|
27
|
+
export type ContextEntityKind = 'person' | 'team' | 'project' | 'org' | 'role' | 'tool' | 'document' | 'task' | 'system' | 'topic';
|
|
28
|
+
export type ContextRelationKind = 'member_of' | 'leads' | 'works_on' | 'owns' | 'depends_on' | 'blocked_by' | 'related_to' | 'uses' | 'reports_to' | 'supports' | 'delivers_to' | 'requested_by' | 'scheduled_for';
|
|
29
|
+
export type ContextEntity = {
|
|
30
|
+
key: string;
|
|
31
|
+
kind: ContextEntityKind;
|
|
32
|
+
name: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
attributes?: Record<string, string>;
|
|
35
|
+
source?: string;
|
|
36
|
+
updatedAt: string;
|
|
37
|
+
};
|
|
38
|
+
export type ContextRelation = {
|
|
39
|
+
from: string;
|
|
40
|
+
to: string;
|
|
41
|
+
type: ContextRelationKind;
|
|
42
|
+
description?: string;
|
|
43
|
+
source?: string;
|
|
44
|
+
updatedAt: string;
|
|
45
|
+
};
|
|
46
|
+
type EntityInput = {
|
|
47
|
+
key?: string;
|
|
48
|
+
kind: ContextEntityKind;
|
|
49
|
+
name: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
attributes?: Record<string, string>;
|
|
52
|
+
tags?: string[];
|
|
53
|
+
source?: string;
|
|
54
|
+
importance?: number;
|
|
55
|
+
};
|
|
56
|
+
type RelationInput = {
|
|
57
|
+
from: string;
|
|
58
|
+
to: string;
|
|
59
|
+
type: ContextRelationKind;
|
|
60
|
+
description?: string;
|
|
61
|
+
source?: string;
|
|
62
|
+
fromKind?: ContextEntityKind;
|
|
63
|
+
toKind?: ContextEntityKind;
|
|
64
|
+
};
|
|
65
|
+
export declare class ContextGraph {
|
|
66
|
+
private memory;
|
|
67
|
+
private scope;
|
|
68
|
+
constructor(memory: MemoryStore, options?: {
|
|
69
|
+
scope?: string;
|
|
70
|
+
});
|
|
71
|
+
upsertEntity(input: EntityInput): Promise<ContextEntity>;
|
|
72
|
+
linkEntities(input: RelationInput): Promise<ContextRelation>;
|
|
73
|
+
searchEntities(query: string, options?: {
|
|
74
|
+
limit?: number;
|
|
75
|
+
kind?: ContextEntityKind;
|
|
76
|
+
}): Promise<ContextEntity[]>;
|
|
77
|
+
getRelationsForEntity(key: string, options?: {
|
|
78
|
+
limit?: number;
|
|
79
|
+
}): Promise<ContextRelation[]>;
|
|
80
|
+
getContextSummary(query: string, options?: {
|
|
81
|
+
limit?: number;
|
|
82
|
+
}): Promise<string | null>;
|
|
83
|
+
private normalizeKey;
|
|
84
|
+
private resolveEntity;
|
|
85
|
+
private inferKind;
|
|
86
|
+
private findEntityByKey;
|
|
87
|
+
private findByTags;
|
|
88
|
+
private pickMostRecent;
|
|
89
|
+
}
|
|
90
|
+
export declare const ContextGraphKinds: {
|
|
91
|
+
entities: ContextEntityKind[];
|
|
92
|
+
relations: ContextRelationKind[];
|
|
93
|
+
};
|
|
94
|
+
export {};
|