@splicr/mcp-server 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.
- package/dist/auth.d.ts +18 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +115 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +80 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +34 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/auto-register.d.ts +7 -0
- package/dist/lib/auto-register.d.ts.map +1 -0
- package/dist/lib/auto-register.js +204 -0
- package/dist/lib/auto-register.js.map +1 -0
- package/dist/lib/project-detector.d.ts +12 -0
- package/dist/lib/project-detector.d.ts.map +1 -0
- package/dist/lib/project-detector.js +68 -0
- package/dist/lib/project-detector.js.map +1 -0
- package/dist/lib/supabase.d.ts +14 -0
- package/dist/lib/supabase.d.ts.map +1 -0
- package/dist/lib/supabase.js +50 -0
- package/dist/lib/supabase.js.map +1 -0
- package/dist/login-cli.d.ts +3 -0
- package/dist/login-cli.d.ts.map +1 -0
- package/dist/login-cli.js +7 -0
- package/dist/login-cli.js.map +1 -0
- package/dist/tools/get-project-context.d.ts +20 -0
- package/dist/tools/get-project-context.d.ts.map +1 -0
- package/dist/tools/get-project-context.js +59 -0
- package/dist/tools/get-project-context.js.map +1 -0
- package/dist/tools/get-recent-insights.d.ts +19 -0
- package/dist/tools/get-recent-insights.d.ts.map +1 -0
- package/dist/tools/get-recent-insights.js +55 -0
- package/dist/tools/get-recent-insights.js.map +1 -0
- package/dist/tools/retry-failed.d.ts +10 -0
- package/dist/tools/retry-failed.d.ts.map +1 -0
- package/dist/tools/retry-failed.js +53 -0
- package/dist/tools/retry-failed.js.map +1 -0
- package/dist/tools/save-from-agent.d.ts +31 -0
- package/dist/tools/save-from-agent.d.ts.map +1 -0
- package/dist/tools/save-from-agent.js +84 -0
- package/dist/tools/save-from-agent.js.map +1 -0
- package/dist/tools/search-knowledge.d.ts +24 -0
- package/dist/tools/search-knowledge.d.ts.map +1 -0
- package/dist/tools/search-knowledge.js +160 -0
- package/dist/tools/search-knowledge.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface DetectedProject {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
confidence: 'exact' | 'inferred';
|
|
5
|
+
}
|
|
6
|
+
/** Normalize path for consistent DB lookups across Windows/WSL/Mac */
|
|
7
|
+
export declare function normalizePath(p: string): string;
|
|
8
|
+
export declare function detectProject(cwd: string): Promise<DetectedProject | null>;
|
|
9
|
+
export declare function getGitRemoteUrl(cwd: string): string | null;
|
|
10
|
+
export declare function normalizeGitUrl(url: string): string;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=project-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-detector.d.ts","sourceRoot":"","sources":["../../src/lib/project-detector.ts"],"names":[],"mappings":"AAIA,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,GAAG,UAAU,CAAC;CAClC;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA2ChF;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO1D;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAInD"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { getSupabase } from './supabase.js';
|
|
3
|
+
import { autoRegisterProject } from './auto-register.js';
|
|
4
|
+
/** Normalize path for consistent DB lookups across Windows/WSL/Mac */
|
|
5
|
+
export function normalizePath(p) {
|
|
6
|
+
return p
|
|
7
|
+
.replace(/\\/g, '/') // backslash → forward slash
|
|
8
|
+
.replace(/\/+$/, '') // strip trailing slash
|
|
9
|
+
.replace(/^([A-Z]):/, (_, d) => `${d.toLowerCase()}:`); // C: → c:
|
|
10
|
+
}
|
|
11
|
+
export async function detectProject(cwd) {
|
|
12
|
+
const { supabase, userId } = await getSupabase();
|
|
13
|
+
const normalizedCwd = normalizePath(cwd);
|
|
14
|
+
// 1. Direct path match (try both raw and normalized)
|
|
15
|
+
const { data: byPath } = await supabase
|
|
16
|
+
.from('projects')
|
|
17
|
+
.select('id, name')
|
|
18
|
+
.eq('user_id', userId)
|
|
19
|
+
.eq('local_path', normalizedCwd)
|
|
20
|
+
.single();
|
|
21
|
+
if (byPath)
|
|
22
|
+
return { ...byPath, confidence: 'exact' };
|
|
23
|
+
// 2. Git remote match
|
|
24
|
+
const gitRemote = getGitRemoteUrl(cwd);
|
|
25
|
+
if (gitRemote) {
|
|
26
|
+
const normalized = normalizeGitUrl(gitRemote);
|
|
27
|
+
const { data: byRepo } = await supabase
|
|
28
|
+
.from('projects')
|
|
29
|
+
.select('id, name')
|
|
30
|
+
.eq('user_id', userId)
|
|
31
|
+
.eq('github_repo_url', normalized)
|
|
32
|
+
.single();
|
|
33
|
+
if (byRepo)
|
|
34
|
+
return { ...byRepo, confidence: 'exact' };
|
|
35
|
+
}
|
|
36
|
+
// 3. Fuzzy match by directory name
|
|
37
|
+
const dirName = normalizedCwd.split('/').pop()?.toLowerCase();
|
|
38
|
+
if (dirName) {
|
|
39
|
+
const { data: projects } = await supabase
|
|
40
|
+
.from('projects')
|
|
41
|
+
.select('id, name')
|
|
42
|
+
.eq('user_id', userId)
|
|
43
|
+
.eq('status', 'active');
|
|
44
|
+
const match = projects?.find(p => p.name.toLowerCase() === dirName);
|
|
45
|
+
if (match)
|
|
46
|
+
return { ...match, confidence: 'inferred' };
|
|
47
|
+
}
|
|
48
|
+
// 4. Auto-register from local files
|
|
49
|
+
const registered = await autoRegisterProject(cwd);
|
|
50
|
+
if (registered)
|
|
51
|
+
return { ...registered, confidence: 'inferred' };
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
export function getGitRemoteUrl(cwd) {
|
|
55
|
+
try {
|
|
56
|
+
const result = execSync('git config --get remote.origin.url', { cwd, encoding: 'utf-8' });
|
|
57
|
+
return result.trim();
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function normalizeGitUrl(url) {
|
|
64
|
+
return url
|
|
65
|
+
.replace(/^git@github\.com:/, 'https://github.com/')
|
|
66
|
+
.replace(/\.git$/, '');
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=project-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-detector.js","sourceRoot":"","sources":["../../src/lib/project-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
+
/**
|
|
3
|
+
* Get an authenticated Supabase client.
|
|
4
|
+
* - If auth.json exists: uses anon key + user JWT (RLS enforced)
|
|
5
|
+
* - Fallback: uses service role key + hardcoded userId (legacy, deprecated)
|
|
6
|
+
*/
|
|
7
|
+
export declare function getSupabase(): Promise<{
|
|
8
|
+
supabase: SupabaseClient;
|
|
9
|
+
userId: string;
|
|
10
|
+
}>;
|
|
11
|
+
export declare const geminiApiKey: string;
|
|
12
|
+
export declare const supabase: SupabaseClient<any, "public", "public", any, any>;
|
|
13
|
+
export declare const userId: string;
|
|
14
|
+
//# sourceMappingURL=supabase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/lib/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAYrE;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAgCzF;AAGD,eAAO,MAAM,YAAY,QAAsB,CAAC;AAIhD,eAAO,MAAM,QAAQ,mDAAkE,CAAC;AACxF,eAAO,MAAM,MAAM,QAAgB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createClient } from '@supabase/supabase-js';
|
|
2
|
+
import { loadConfig } from '../config.js';
|
|
3
|
+
import { loadAuth, hasAuth } from '../auth.js';
|
|
4
|
+
const config = loadConfig();
|
|
5
|
+
// Cached client and user
|
|
6
|
+
let _client = null;
|
|
7
|
+
let _userId = null;
|
|
8
|
+
let _mode = null;
|
|
9
|
+
let _lastToken = null;
|
|
10
|
+
/**
|
|
11
|
+
* Get an authenticated Supabase client.
|
|
12
|
+
* - If auth.json exists: uses anon key + user JWT (RLS enforced)
|
|
13
|
+
* - Fallback: uses service role key + hardcoded userId (legacy, deprecated)
|
|
14
|
+
*/
|
|
15
|
+
export async function getSupabase() {
|
|
16
|
+
if (hasAuth() && config.supabaseAnonKey) {
|
|
17
|
+
// JWT auth mode — RLS enforced
|
|
18
|
+
const auth = await loadAuth();
|
|
19
|
+
// Only recreate client if token actually changed
|
|
20
|
+
if (_mode !== 'jwt' || _userId !== auth.userId || _lastToken !== auth.accessToken) {
|
|
21
|
+
_client = createClient(config.supabaseUrl, config.supabaseAnonKey, {
|
|
22
|
+
global: {
|
|
23
|
+
headers: { Authorization: `Bearer ${auth.accessToken}` },
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
_userId = auth.userId;
|
|
27
|
+
_mode = 'jwt';
|
|
28
|
+
_lastToken = auth.accessToken;
|
|
29
|
+
}
|
|
30
|
+
return { supabase: _client, userId: auth.userId };
|
|
31
|
+
}
|
|
32
|
+
// Legacy fallback — service role key bypasses RLS
|
|
33
|
+
if (!_client || _mode !== 'legacy') {
|
|
34
|
+
if (!config.userId) {
|
|
35
|
+
throw new Error('Not authenticated. Run `splicr login` or set SPLICR_USER_ID env var.');
|
|
36
|
+
}
|
|
37
|
+
console.error('[Splicr MCP] WARNING: Using legacy service role key auth. Run `splicr login` to switch to user-scoped auth.');
|
|
38
|
+
_client = createClient(config.supabaseUrl, config.supabaseServiceRoleKey);
|
|
39
|
+
_userId = config.userId;
|
|
40
|
+
_mode = 'legacy';
|
|
41
|
+
}
|
|
42
|
+
return { supabase: _client, userId: _userId };
|
|
43
|
+
}
|
|
44
|
+
// Gemini API key (unchanged — not auth-related)
|
|
45
|
+
export const geminiApiKey = config.geminiApiKey;
|
|
46
|
+
// Legacy exports for backward compat during transition
|
|
47
|
+
// TODO: Remove after all tool files are migrated to getSupabase()
|
|
48
|
+
export const supabase = createClient(config.supabaseUrl, config.supabaseServiceRoleKey);
|
|
49
|
+
export const userId = config.userId;
|
|
50
|
+
//# sourceMappingURL=supabase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supabase.js","sourceRoot":"","sources":["../../src/lib/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAkB,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;AAE5B,yBAAyB;AACzB,IAAI,OAAO,GAA0B,IAAI,CAAC;AAC1C,IAAI,OAAO,GAAkB,IAAI,CAAC;AAClC,IAAI,KAAK,GAA4B,IAAI,CAAC;AAC1C,IAAI,UAAU,GAAkB,IAAI,CAAC;AAErC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,OAAO,EAAE,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QACxC,+BAA+B;QAC/B,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;QAE9B,iDAAiD;QACjD,IAAI,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI,UAAU,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YAClF,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,eAAe,EAAE;gBACjE,MAAM,EAAE;oBACN,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,WAAW,EAAE,EAAE;iBACzD;aACF,CAAC,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;YACtB,KAAK,GAAG,KAAK,CAAC;YACd,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC;QAChC,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,OAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IACrD,CAAC;IAED,kDAAkD;IAClD,IAAI,CAAC,OAAO,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;QAC1F,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,6GAA6G,CAAC,CAAC;QAC7H,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAC1E,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;QACxB,KAAK,GAAG,QAAQ,CAAC;IACnB,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,OAAQ,EAAE,MAAM,EAAE,OAAQ,EAAE,CAAC;AAClD,CAAC;AAED,gDAAgD;AAChD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;AAEhD,uDAAuD;AACvD,kEAAkE;AAClE,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAC;AACxF,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-cli.d.ts","sourceRoot":"","sources":["../src/login-cli.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-cli.js","sourceRoot":"","sources":["../src/login-cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IAClB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const getProjectContextSchema: {
|
|
2
|
+
name: "get_project_context";
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
project: {
|
|
8
|
+
type: "string";
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
limit: {
|
|
12
|
+
type: "number";
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
required: "project"[];
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export declare function handleGetProjectContext(args: Record<string, unknown>): Promise<string>;
|
|
20
|
+
//# sourceMappingURL=get-project-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-project-context.d.ts","sourceRoot":"","sources":["../../src/tools/get-project-context.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;CAanC,CAAC;AAEF,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CA6C5F"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getSupabase } from '../lib/supabase.js';
|
|
2
|
+
import { detectProject } from '../lib/project-detector.js';
|
|
3
|
+
export const getProjectContextSchema = {
|
|
4
|
+
name: 'get_project_context',
|
|
5
|
+
description: `Show what's new in a project's knowledge feed from Splicr. Only call this when the user explicitly asks to see new saves, recent context, or "what's new." Do NOT call this proactively at session start.
|
|
6
|
+
|
|
7
|
+
Uses a watermark system — only returns captures saved since the last time context was served for this project. Safe to call repeatedly; it will return empty if nothing is new.`,
|
|
8
|
+
inputSchema: {
|
|
9
|
+
type: 'object',
|
|
10
|
+
properties: {
|
|
11
|
+
project: { type: 'string', description: 'Project name or "auto" to detect from cwd' },
|
|
12
|
+
limit: { type: 'number', description: 'Max results (default: 10)' },
|
|
13
|
+
},
|
|
14
|
+
required: ['project'],
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
export async function handleGetProjectContext(args) {
|
|
18
|
+
const { supabase, userId } = await getSupabase();
|
|
19
|
+
const projectArg = args.project;
|
|
20
|
+
const limit = Math.min(Math.max(1, Number(args.limit) || 20), 100);
|
|
21
|
+
// Resolve project
|
|
22
|
+
let projectId;
|
|
23
|
+
let projectName;
|
|
24
|
+
if (projectArg === 'auto') {
|
|
25
|
+
const detected = await detectProject(process.cwd());
|
|
26
|
+
if (!detected)
|
|
27
|
+
return 'Could not auto-detect project from current directory. Specify a project name.';
|
|
28
|
+
projectId = detected.id;
|
|
29
|
+
projectName = detected.name;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const { data, error: lookupError } = await supabase
|
|
33
|
+
.from('projects')
|
|
34
|
+
.select('id, name')
|
|
35
|
+
.eq('user_id', userId)
|
|
36
|
+
.ilike('name', projectArg)
|
|
37
|
+
.limit(1);
|
|
38
|
+
if (lookupError || !data?.[0]?.id) {
|
|
39
|
+
return `Project "${projectArg}" not found.`;
|
|
40
|
+
}
|
|
41
|
+
projectId = data[0].id;
|
|
42
|
+
projectName = data[0].name;
|
|
43
|
+
}
|
|
44
|
+
// Call DB function (reads watermark, updates it, returns only new captures)
|
|
45
|
+
const { data, error } = await supabase.rpc('get_project_context', {
|
|
46
|
+
p_user_id: userId,
|
|
47
|
+
p_project_id: projectId,
|
|
48
|
+
p_limit: limit,
|
|
49
|
+
});
|
|
50
|
+
if (error)
|
|
51
|
+
return `Error: ${error.message}`;
|
|
52
|
+
if (!data || data.length === 0)
|
|
53
|
+
return `No new saves for ${projectName} since last check.`;
|
|
54
|
+
const items = data.map((r, i) => `${i + 1}. **${r.title || 'Untitled'}** · splicr [${r.relevance}]\n` +
|
|
55
|
+
` ${r.insight}\n` +
|
|
56
|
+
` Tags: ${r.tags?.join(', ') || 'none'}${r.source_url ? ` | ${r.source_url}` : ''}`).join('\n\n');
|
|
57
|
+
return `*From Splicr — ${data.length} new save(s) for ${projectName}:*\n\n${items}`;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=get-project-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-project-context.js","sourceRoot":"","sources":["../../src/tools/get-project-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const getRecentInsightsSchema: {
|
|
2
|
+
name: "get_recent_insights";
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
days: {
|
|
8
|
+
type: "number";
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
limit: {
|
|
12
|
+
type: "number";
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export declare function handleGetRecentInsights(args: Record<string, unknown>): Promise<string>;
|
|
19
|
+
//# sourceMappingURL=get-recent-insights.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-recent-insights.d.ts","sourceRoot":"","sources":["../../src/tools/get-recent-insights.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;CAUnC,CAAC;AAEF,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CA6C5F"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getSupabase } from '../lib/supabase.js';
|
|
2
|
+
export const getRecentInsightsSchema = {
|
|
3
|
+
name: 'get_recent_insights',
|
|
4
|
+
description: `Show everything the user saved recently across all projects in Splicr. Only call when the user explicitly asks to see their recent saves or wants a cross-project overview.`,
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
days: { type: 'number', description: 'Last N days (default: 3)' },
|
|
9
|
+
limit: { type: 'number', description: 'Max results (default: 15)' },
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
export async function handleGetRecentInsights(args) {
|
|
14
|
+
const { supabase, userId } = await getSupabase();
|
|
15
|
+
const days = Math.min(Math.max(1, Number(args.days) || 3), 365);
|
|
16
|
+
const limit = Math.min(Math.max(1, Number(args.limit) || 15), 100);
|
|
17
|
+
const since = new Date();
|
|
18
|
+
since.setDate(since.getDate() - days);
|
|
19
|
+
const { data, error } = await supabase
|
|
20
|
+
.from('captures')
|
|
21
|
+
.select(`
|
|
22
|
+
id, title, insight, source_url, source_type, content_category, tags, created_at,
|
|
23
|
+
project_captures ( project_id, relevance, projects:project_id ( name ) )
|
|
24
|
+
`)
|
|
25
|
+
.eq('user_id', userId)
|
|
26
|
+
.eq('status', 'complete')
|
|
27
|
+
.gte('created_at', since.toISOString())
|
|
28
|
+
.order('created_at', { ascending: false })
|
|
29
|
+
.limit(limit);
|
|
30
|
+
if (error)
|
|
31
|
+
return `Error: ${error.message}`;
|
|
32
|
+
if (!data || data.length === 0)
|
|
33
|
+
return `No saves in the last ${days} days.`;
|
|
34
|
+
const items = data.map((c, i) => {
|
|
35
|
+
const projects = c.project_captures
|
|
36
|
+
?.map((pc) => pc.projects?.name)
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
.join(', ') || 'General';
|
|
39
|
+
return `${i + 1}. **${c.title || 'Untitled'}** · splicr → ${projects}\n` +
|
|
40
|
+
` ${c.insight}\n` +
|
|
41
|
+
` ${c.content_category} | ${c.tags?.join(', ') || 'no tags'}`;
|
|
42
|
+
}).join('\n\n');
|
|
43
|
+
// Check for failed captures
|
|
44
|
+
const { count: failedCount } = await supabase
|
|
45
|
+
.from('captures')
|
|
46
|
+
.select('*', { count: 'exact', head: true })
|
|
47
|
+
.eq('user_id', userId)
|
|
48
|
+
.eq('status', 'failed');
|
|
49
|
+
let output = `*From Splicr — ${data.length} recent save(s):*\n\n${items}`;
|
|
50
|
+
if (failedCount && failedCount > 0) {
|
|
51
|
+
output += `\n\n_Note: ${failedCount} capture(s) failed processing. Use retry_failed to reprocess._`;
|
|
52
|
+
}
|
|
53
|
+
return output;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=get-recent-insights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-recent-insights.js","sourceRoot":"","sources":["../../src/tools/get-recent-insights.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE,qBAA8B;IACpC,WAAW,EAAE,6KAA6K;IAC1L,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,0BAA0B,EAAE;YAC1E,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,2BAA2B,EAAE;SAC7E;KACF;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,IAA6B;IACzE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,WAAW,EAAE,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAEnE,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;IACzB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IAEtC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ;SACnC,IAAI,CAAC,UAAU,CAAC;SAChB,MAAM,CAAC;;;KAGP,CAAC;SACD,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;SACrB,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;SACxB,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;SACtC,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;SACzC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEhB,IAAI,KAAK;QAAE,OAAO,UAAU,KAAK,CAAC,OAAO,EAAE,CAAC;IAC5C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,wBAAwB,IAAI,QAAQ,CAAC;IAE5E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,CAAS,EAAE,EAAE;QAC3C,MAAM,QAAQ,GAAG,CAAC,CAAC,gBAAgB;YACjC,EAAE,GAAG,CAAC,CAAC,EAAO,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC;aACpC,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;QAC3B,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,UAAU,iBAAiB,QAAQ,IAAI;YACtE,MAAM,CAAC,CAAC,OAAO,IAAI;YACnB,MAAM,CAAC,CAAC,gBAAgB,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,4BAA4B;IAC5B,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,QAAQ;SAC1C,IAAI,CAAC,UAAU,CAAC;SAChB,MAAM,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;SAC3C,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;SACrB,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAE1B,IAAI,MAAM,GAAG,kBAAkB,IAAI,CAAC,MAAM,wBAAwB,KAAK,EAAE,CAAC;IAC1E,IAAI,WAAW,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,cAAc,WAAW,gEAAgE,CAAC;IACtG,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const retryFailedSchema: {
|
|
2
|
+
name: "retry_failed";
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {};
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export declare function handleRetryFailed(_args: Record<string, unknown>): Promise<string>;
|
|
10
|
+
//# sourceMappingURL=retry-failed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-failed.d.ts","sourceRoot":"","sources":["../../src/tools/retry-failed.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB;;;;;;;CAO7B,CAAC;AAEF,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAuCvF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { loadAuth, hasAuth } from '../auth.js';
|
|
2
|
+
import { loadConfig } from '../config.js';
|
|
3
|
+
export const retryFailedSchema = {
|
|
4
|
+
name: 'retry_failed',
|
|
5
|
+
description: `Retry processing of failed captures in Splicr. Some captures may fail during AI processing (extraction, distillation, or routing). This tool requeues them for reprocessing. Returns the number of captures queued for retry.`,
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {},
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
export async function handleRetryFailed(_args) {
|
|
12
|
+
const config = loadConfig();
|
|
13
|
+
// Get auth token for API call
|
|
14
|
+
let token;
|
|
15
|
+
if (hasAuth()) {
|
|
16
|
+
const auth = await loadAuth();
|
|
17
|
+
token = auth.accessToken;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
return 'Not authenticated. Run `splicr login` first to enable retry.';
|
|
21
|
+
}
|
|
22
|
+
// Call API server's retry endpoint
|
|
23
|
+
const url = `${config.apiServerUrl}/captures/retry-failed`;
|
|
24
|
+
try {
|
|
25
|
+
const response = await fetch(url, {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
headers: {
|
|
28
|
+
'Authorization': `Bearer ${token}`,
|
|
29
|
+
'Content-Type': 'application/json',
|
|
30
|
+
},
|
|
31
|
+
signal: AbortSignal.timeout(15000),
|
|
32
|
+
});
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
let body = '';
|
|
35
|
+
try {
|
|
36
|
+
body = await response.text();
|
|
37
|
+
}
|
|
38
|
+
catch { }
|
|
39
|
+
return `Retry request failed (${response.status}): ${body}`;
|
|
40
|
+
}
|
|
41
|
+
const result = await response.json();
|
|
42
|
+
if (result.data.retried === 0) {
|
|
43
|
+
return 'No failed captures to retry.';
|
|
44
|
+
}
|
|
45
|
+
return `*Splicr:* ${result.data.message}`;
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
if (err.name === 'TimeoutError')
|
|
49
|
+
return 'Retry request timed out after 15s.';
|
|
50
|
+
return `Retry request failed: ${err.message}`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=retry-failed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-failed.js","sourceRoot":"","sources":["../../src/tools/retry-failed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,cAAuB;IAC7B,WAAW,EAAE,+NAA+N;IAC5O,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE,EAAE;KACf;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAA8B;IACpE,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,8BAA8B;IAC9B,IAAI,KAAa,CAAC;IAClB,IAAI,OAAO,EAAE,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC9B,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC;IAC3B,CAAC;SAAM,CAAC;QACN,OAAO,8DAA8D,CAAC;IACxE,CAAC;IAED,mCAAmC;IACnC,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,YAAY,wBAAwB,CAAC;IAC3D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,KAAK,EAAE;gBAClC,cAAc,EAAE,kBAAkB;aACnC;YACD,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;SACnC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,CAAC;gBAAC,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAC9C,OAAO,yBAAyB,QAAQ,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC;QAC9D,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAoD,CAAC;QACvF,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,8BAA8B,CAAC;QACxC,CAAC;QACD,OAAO,aAAa,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IAC5C,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc;YAAE,OAAO,oCAAoC,CAAC;QAC7E,OAAO,yBAAyB,GAAG,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare const saveFromAgentSchema: {
|
|
2
|
+
name: "save_from_agent";
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
content: {
|
|
8
|
+
type: "string";
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
title: {
|
|
12
|
+
type: "string";
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
project: {
|
|
16
|
+
type: "string";
|
|
17
|
+
description: string;
|
|
18
|
+
};
|
|
19
|
+
tags: {
|
|
20
|
+
type: "array";
|
|
21
|
+
items: {
|
|
22
|
+
type: "string";
|
|
23
|
+
};
|
|
24
|
+
description: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
required: ("title" | "content")[];
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export declare function handleSaveFromAgent(args: Record<string, unknown>): Promise<string>;
|
|
31
|
+
//# sourceMappingURL=save-from-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save-from-agent.d.ts","sourceRoot":"","sources":["../../src/tools/save-from-agent.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAa/B,CAAC;AAEF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAqExF"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import { getSupabase } from '../lib/supabase.js';
|
|
3
|
+
import { detectProject } from '../lib/project-detector.js';
|
|
4
|
+
export const saveFromAgentSchema = {
|
|
5
|
+
name: 'save_from_agent',
|
|
6
|
+
description: `Save knowledge to Splicr. ONLY call this when the user explicitly asks to save, remember, or store something in Splicr. Do NOT call this proactively — the user decides what goes into their knowledge base, not the agent.`,
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
content: { type: 'string', description: 'The knowledge to save' },
|
|
11
|
+
title: { type: 'string', description: 'Short title' },
|
|
12
|
+
project: { type: 'string', description: 'Project name, "auto", or "all"' },
|
|
13
|
+
tags: { type: 'array', items: { type: 'string' }, description: 'Tags' },
|
|
14
|
+
},
|
|
15
|
+
required: ['content', 'title'],
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
export async function handleSaveFromAgent(args) {
|
|
19
|
+
const { supabase, userId } = await getSupabase();
|
|
20
|
+
const content = args.content;
|
|
21
|
+
const title = args.title;
|
|
22
|
+
const projectArg = args.project;
|
|
23
|
+
const tags = args.tags || [];
|
|
24
|
+
// Content hash for dedup
|
|
25
|
+
const contentHash = createHash('sha256').update(content).digest('hex').substring(0, 16);
|
|
26
|
+
// Insert capture (agent saves are already distilled — skip AI pipeline)
|
|
27
|
+
const { data: capture, error } = await supabase
|
|
28
|
+
.from('captures')
|
|
29
|
+
.insert({
|
|
30
|
+
user_id: userId,
|
|
31
|
+
source_type: 'agent',
|
|
32
|
+
captured_from: 'ide_agent',
|
|
33
|
+
title,
|
|
34
|
+
raw_content: content,
|
|
35
|
+
insight: content,
|
|
36
|
+
content_category: 'technique',
|
|
37
|
+
tags,
|
|
38
|
+
content_hash: contentHash,
|
|
39
|
+
status: 'complete',
|
|
40
|
+
processed_at: new Date().toISOString(),
|
|
41
|
+
})
|
|
42
|
+
.select()
|
|
43
|
+
.single();
|
|
44
|
+
// Duplicate detected by DB constraint
|
|
45
|
+
if (error?.code === '23505' || error?.message?.includes('duplicate key')) {
|
|
46
|
+
return `*Already saved in Splicr:* "${title}"`;
|
|
47
|
+
}
|
|
48
|
+
if (error)
|
|
49
|
+
return `Error saving: ${error.message}`;
|
|
50
|
+
if (!capture)
|
|
51
|
+
return 'Error saving: no data returned from insert';
|
|
52
|
+
// Route to project if specified
|
|
53
|
+
if (projectArg && projectArg !== 'all') {
|
|
54
|
+
let projectId;
|
|
55
|
+
if (projectArg === 'auto') {
|
|
56
|
+
const detected = await detectProject(process.cwd());
|
|
57
|
+
projectId = detected?.id;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const { data, error: lookupError } = await supabase
|
|
61
|
+
.from('projects')
|
|
62
|
+
.select('id')
|
|
63
|
+
.eq('user_id', userId)
|
|
64
|
+
.ilike('name', projectArg)
|
|
65
|
+
.limit(1);
|
|
66
|
+
if (!lookupError) {
|
|
67
|
+
projectId = data?.[0]?.id;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (projectId) {
|
|
71
|
+
const { error: routeError } = await supabase.from('project_captures').insert({
|
|
72
|
+
project_id: projectId,
|
|
73
|
+
capture_id: capture.id,
|
|
74
|
+
relevance: 'high',
|
|
75
|
+
routed_by: 'agent',
|
|
76
|
+
});
|
|
77
|
+
if (routeError) {
|
|
78
|
+
return `*Saved to Splicr:* "${title}" (warning: routing to project failed)`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return `*Saved to Splicr:* "${title}"${projectArg ? ` → routed to ${projectArg}` : ''}`;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=save-from-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save-from-agent.js","sourceRoot":"","sources":["../../src/tools/save-from-agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,iBAA0B;IAChC,WAAW,EAAE,6NAA6N;IAC1O,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,uBAAuB,EAAE;YAC1E,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,aAAa,EAAE;YAC9D,OAAO,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,gCAAgC,EAAE;YACnF,IAAI,EAAE,EAAE,IAAI,EAAE,OAAgB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE;SAC1F;QACD,QAAQ,EAAE,CAAC,SAAkB,EAAE,OAAgB,CAAC;KACjD;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAA6B;IACrE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,WAAW,EAAE,CAAC;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAiB,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAe,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,OAA6B,CAAC;IACtD,MAAM,IAAI,GAAI,IAAI,CAAC,IAAiB,IAAI,EAAE,CAAC;IAE3C,yBAAyB;IACzB,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAExF,wEAAwE;IACxE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ;SAC5C,IAAI,CAAC,UAAU,CAAC;SAChB,MAAM,CAAC;QACN,OAAO,EAAE,MAAM;QACf,WAAW,EAAE,OAAO;QACpB,aAAa,EAAE,WAAW;QAC1B,KAAK;QACL,WAAW,EAAE,OAAO;QACpB,OAAO,EAAE,OAAO;QAChB,gBAAgB,EAAE,WAAW;QAC7B,IAAI;QACJ,YAAY,EAAE,WAAW;QACzB,MAAM,EAAE,UAAU;QAClB,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACvC,CAAC;SACD,MAAM,EAAE;SACR,MAAM,EAAE,CAAC;IAEZ,sCAAsC;IACtC,IAAI,KAAK,EAAE,IAAI,KAAK,OAAO,IAAI,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACzE,OAAO,+BAA+B,KAAK,GAAG,CAAC;IACjD,CAAC;IACD,IAAI,KAAK;QAAE,OAAO,iBAAiB,KAAK,CAAC,OAAO,EAAE,CAAC;IACnD,IAAI,CAAC,OAAO;QAAE,OAAO,4CAA4C,CAAC;IAElE,gCAAgC;IAChC,IAAI,UAAU,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACvC,IAAI,SAA6B,CAAC;QAElC,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YACpD,SAAS,GAAG,QAAQ,EAAE,EAAE,CAAC;QAC3B,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,QAAQ;iBAChD,IAAI,CAAC,UAAU,CAAC;iBAChB,MAAM,CAAC,IAAI,CAAC;iBACZ,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;iBACrB,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC;iBACzB,KAAK,CAAC,CAAC,CAAC,CAAC;YACZ,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,SAAS,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC;gBAC3E,UAAU,EAAE,SAAS;gBACrB,UAAU,EAAE,OAAO,CAAC,EAAE;gBACtB,SAAS,EAAE,MAAM;gBACjB,SAAS,EAAE,OAAO;aACnB,CAAC,CAAC;YACH,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,uBAAuB,KAAK,wCAAwC,CAAC;YAC9E,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,uBAAuB,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,gBAAgB,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC1F,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const searchKnowledgeSchema: {
|
|
2
|
+
name: "search_knowledge";
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: {
|
|
7
|
+
query: {
|
|
8
|
+
type: "string";
|
|
9
|
+
description: string;
|
|
10
|
+
};
|
|
11
|
+
project: {
|
|
12
|
+
type: "string";
|
|
13
|
+
description: string;
|
|
14
|
+
};
|
|
15
|
+
limit: {
|
|
16
|
+
type: "number";
|
|
17
|
+
description: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
required: "query"[];
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export declare function handleSearchKnowledge(args: Record<string, unknown>): Promise<string>;
|
|
24
|
+
//# sourceMappingURL=search-knowledge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-knowledge.d.ts","sourceRoot":"","sources":["../../src/tools/search-knowledge.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;CAsBjC,CAAC;AAyDF,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CA2E1F"}
|