@opticlm/connector 2.2.0 → 2.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.
- package/README.md +2 -2
- package/dist/index.d.ts +65 -40
- package/dist/index.js +1 -6
- package/dist/{interfaces-wSmWeYxt.d.ts → interfaces-B9NK_71f.d.ts} +1 -1
- package/dist/lsp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts +3 -54
- package/dist/pipe/index.d.ts +43 -0
- package/dist/pipe/index.js +6 -0
- package/dist/schemas.d.ts +54 -0
- package/dist/schemas.js +2 -0
- package/package.json +9 -1
- package/dist/resolver-CSuvobsJ.d.ts +0 -69
package/README.md
CHANGED
|
@@ -343,7 +343,7 @@ When the MCP server runs in a separate process from the IDE plugin (e.g., spawne
|
|
|
343
343
|
**IDE plugin side** — expose providers:
|
|
344
344
|
|
|
345
345
|
```typescript
|
|
346
|
-
import { servePipe } from '@opticlm/connector'
|
|
346
|
+
import { servePipe } from '@opticlm/connector/pipe'
|
|
347
347
|
|
|
348
348
|
const server = await servePipe({
|
|
349
349
|
pipeName: 'my-ide-lsp',
|
|
@@ -361,7 +361,7 @@ const server = await servePipe({
|
|
|
361
361
|
|
|
362
362
|
```typescript
|
|
363
363
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
|
|
364
|
-
import { connectPipe } from '@opticlm/connector'
|
|
364
|
+
import { connectPipe } from '@opticlm/connector/pipe'
|
|
365
365
|
import { install } from '@opticlm/connector/mcp'
|
|
366
366
|
|
|
367
367
|
const conn = await connectPipe({
|
package/dist/index.d.ts
CHANGED
|
@@ -1,45 +1,70 @@
|
|
|
1
|
-
import { F as FileAccessProvider,
|
|
2
|
-
export { C as CodeSnippet,
|
|
3
|
-
export { R as ResolverConfig, S as SymbolResolutionError, a as SymbolResolver } from './resolver-CSuvobsJ.js';
|
|
1
|
+
import { F as FileAccessProvider, U as UnifiedUri, l as FuzzyPosition, j as ExactPosition } from './interfaces-B9NK_71f.js';
|
|
2
|
+
export { C as CodeSnippet, D as DefinitionProvider, h as Diagnostic, g as DiagnosticSeverity, a as DiagnosticsProvider, k as DiskRange, i as DocumentSymbol, m as EditFailureReason, E as EditProvider, d as EditResult, n as Frontmatter, e as FrontmatterMatch, c as FrontmatterProvider, o as FrontmatterValue, f as GlobalFindMatch, p as GlobalFindOptions, G as GlobalFindProvider, b as GraphProvider, H as HierarchyProvider, L as Link, q as OnDiagnosticsChangedCallback, O as OutlineProvider, P as PendingEditOperation, R as ReferencesProvider, S as SymbolKind, T as TextEdit } from './interfaces-B9NK_71f.js';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
readonly edit?: EditProvider;
|
|
12
|
-
readonly definition?: DefinitionProvider;
|
|
13
|
-
readonly references?: ReferencesProvider;
|
|
14
|
-
readonly hierarchy?: HierarchyProvider;
|
|
15
|
-
readonly diagnostics?: DiagnosticsProvider;
|
|
16
|
-
readonly outline?: OutlineProvider;
|
|
17
|
-
readonly globalFind?: GlobalFindProvider;
|
|
18
|
-
readonly graph?: GraphProvider;
|
|
19
|
-
readonly frontmatter?: FrontmatterProvider;
|
|
20
|
-
readonly availableMethods: string[];
|
|
21
|
-
disconnect(): void;
|
|
22
|
-
}
|
|
23
|
-
declare function connectPipe(options: connectPipeOptions): Promise<LspPipeConnection>;
|
|
4
|
+
/**
|
|
5
|
+
* Smart Resolver Logic for MCP LSP Driver SDK
|
|
6
|
+
*
|
|
7
|
+
* This is the internal engine of the SDK. It translates the LLM's imprecise
|
|
8
|
+
* instructions into precise coordinates.
|
|
9
|
+
*/
|
|
24
10
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Configuration options for the SymbolResolver.
|
|
13
|
+
*/
|
|
14
|
+
interface ResolverConfig {
|
|
15
|
+
/**
|
|
16
|
+
* Number of lines to scan above and below the lineHint if the symbol
|
|
17
|
+
* is not found at the exact line. Defaults to 2.
|
|
18
|
+
*/
|
|
19
|
+
lineSearchRadius?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Error thrown when a symbol cannot be resolved.
|
|
23
|
+
*/
|
|
24
|
+
declare class SymbolResolutionError extends Error {
|
|
25
|
+
readonly symbolName: string;
|
|
26
|
+
readonly lineHint: number;
|
|
27
|
+
readonly reason: string;
|
|
28
|
+
constructor(symbolName: string, lineHint: number, reason: string);
|
|
37
29
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
/**
|
|
31
|
+
* The SymbolResolver translates fuzzy positions (as provided by an LLM)
|
|
32
|
+
* into exact positions that can be used by the IDE.
|
|
33
|
+
*
|
|
34
|
+
* Algorithm:
|
|
35
|
+
* 1. Read file content via FileAccessProvider.
|
|
36
|
+
* 2. Split content into lines.
|
|
37
|
+
* 3. Target the lineHint (converting 1-based to 0-based).
|
|
38
|
+
* 4. Search for symbolName in that line.
|
|
39
|
+
* - If orderHint is 0, find first occurrence.
|
|
40
|
+
* - If orderHint is N, find Nth occurrence.
|
|
41
|
+
* 5. Robustness Fallback:
|
|
42
|
+
* - If the line is empty or symbol not found at lineHint,
|
|
43
|
+
* scan +/- lineSearchRadius lines to handle minor line shifts.
|
|
44
|
+
* 6. Return ExactPosition (line, character start index).
|
|
45
|
+
*/
|
|
46
|
+
declare class SymbolResolver {
|
|
47
|
+
private readonly fs;
|
|
48
|
+
private readonly lineSearchRadius;
|
|
49
|
+
constructor(fs: FileAccessProvider, config?: ResolverConfig);
|
|
50
|
+
/**
|
|
51
|
+
* Resolves a fuzzy position to an exact position.
|
|
52
|
+
*
|
|
53
|
+
* @param uri - The URI of the file
|
|
54
|
+
* @param fuzzy - The fuzzy position provided by the LLM
|
|
55
|
+
* @returns The exact position in the file
|
|
56
|
+
* @throws SymbolResolutionError if the symbol cannot be found
|
|
57
|
+
*/
|
|
58
|
+
resolvePosition(uri: UnifiedUri, fuzzy: FuzzyPosition): Promise<ExactPosition>;
|
|
59
|
+
/**
|
|
60
|
+
* Finds the Nth occurrence of a symbol in a line.
|
|
61
|
+
*
|
|
62
|
+
* @param line - The line to search in (may be undefined if out of bounds)
|
|
63
|
+
* @param symbolName - The symbol to find
|
|
64
|
+
* @param orderHint - Which occurrence to find (0-based)
|
|
65
|
+
* @returns The character offset of the symbol, or null if not found
|
|
66
|
+
*/
|
|
67
|
+
private findSymbolInLine;
|
|
42
68
|
}
|
|
43
|
-
declare function servePipe(options: servePipeOptions): Promise<LspPipeServer>;
|
|
44
69
|
|
|
45
|
-
export {
|
|
70
|
+
export { ExactPosition, FileAccessProvider, FuzzyPosition, type ResolverConfig, SymbolResolutionError, SymbolResolver, UnifiedUri };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
|
|
2
|
-
`);})}sendNotification(r,e){if(this.destroyed)return;let i={type:"notification",method:r,params:e};this.socket.write(`${JSON.stringify(i)}
|
|
3
|
-
`);}destroy(){this.destroyed||(this.destroyed=true,this.rejectAll(new Error("Transport destroyed")),this.socket.destroy());}handleData(r){this.buffer+=r.toString();let e=this.buffer.split(`
|
|
4
|
-
`);this.buffer=e.pop()??"";for(let i of e){let o=i.replace(/\r$/,"");if(o)try{let n=JSON.parse(o);this.dispatch(n);}catch{}}}dispatch(r){switch(r.type){case "response":{let e=this.pending.get(r.id);e&&(this.pending.delete(r.id),r.error?e.reject(new Error(r.error.message)):e.resolve(r.result));break}case "request":{this.requestHandler&&this.requestHandler(r.method,r.params).then(e=>{if(this.destroyed)return;let i={type:"response",id:r.id,result:e};this.socket.write(`${JSON.stringify(i)}
|
|
5
|
-
`);}).catch(e=>{if(this.destroyed)return;let i={type:"response",id:r.id,error:{message:e instanceof Error?e.message:String(e)}};this.socket.write(`${JSON.stringify(i)}
|
|
6
|
-
`);});break}case "notification":{this.notificationHandler?.(r.method,r.params);break}}}rejectAll(r){for(let[,e]of this.pending)e.reject(r);this.pending.clear();}};function w(l){return process.platform==="win32"?`\\\\.\\pipe\\${l}`:`/tmp/${l}.sock`}var b=[{providerKey:"fileAccess",methods:["readFile","readDirectory"]},{providerKey:"edit",methods:["applyEdits","previewAndApplyEdits"]},{providerKey:"definition",methods:["provideDefinition"]},{providerKey:"references",methods:["provideReferences"]},{providerKey:"hierarchy",methods:["provideCallHierarchy"]},{providerKey:"diagnostics",methods:["provideDiagnostics","getWorkspaceDiagnostics"]},{providerKey:"outline",methods:["provideDocumentSymbols"]},{providerKey:"globalFind",methods:["globalFind"]},{providerKey:"graph",methods:["getLinkStructure","resolveOutlinks","resolveBacklinks","addLink"]},{providerKey:"frontmatter",methods:["getFrontmatterStructure","getFrontmatter","setFrontmatter"]}];function C(l){let{pipeName:r,connectTimeout:e=5e3}=l,i=w(r);return new Promise((o,n)=>{let a=connect(i),t=false,d=setTimeout(()=>{t||(t=true,a.destroy(),n(new Error(`Connection timeout after ${e}ms`)));},e);a.on("error",s=>{t||(t=true,clearTimeout(d),n(s));}),a.on("connect",()=>{if(clearTimeout(d),t)return;let s,p,c=new v(a,{onNotification:(u,m)=>{u==="onDiagnosticsChanged"&&s&&s(m[0]),u==="onFileChanged"&&p&&p(m[0]);}});c.sendRequest("_handshake",[]).then(u=>{if(t)return;let g=u.methods,f={};for(let{providerKey:P,methods:D}of b){let R=D.filter(h=>g.includes(`${P}.${h}`));if(R.length===0)continue;let y={};for(let h of R)y[h]=(...E)=>c.sendRequest(`${P}.${h}`,E);P==="diagnostics"&&g.includes("onDiagnosticsChanged")&&(y.onDiagnosticsChanged=h=>{s=h;}),P==="fileAccess"&&g.includes("onFileChanged")&&(y.onFileChanged=h=>{p=h;}),f[P]=y;}t=true,o({fileAccess:f.fileAccess,edit:f.edit,definition:f.definition,references:f.references,hierarchy:f.hierarchy,diagnostics:f.diagnostics,outline:f.outline,globalFind:f.globalFind,graph:f.graph,frontmatter:f.frontmatter,availableMethods:g,disconnect(){c.destroy();}});}).catch(u=>{t||(t=true,c.destroy(),n(u instanceof Error?u:new Error(String(u))));});});})}function A(l){let{pipeName:r}=l,e=w(r),i=new Map;for(let{providerKey:t,methods:d}of b){let s=l[t];if(s)for(let p of d){let c=s[p];if(typeof c=="function"){let u=`${t}.${p}`;i.set(u,(...m)=>c.apply(s,m));}}}let o=[...i.keys()];l.diagnostics?.onDiagnosticsChanged&&o.push("onDiagnosticsChanged"),l.fileAccess.onFileChanged&&o.push("onFileChanged");let n=new Set,a=createServer(t=>{let d=new v(t,{onRequest:async(s,p)=>{if(s==="_handshake")return {methods:o};let c=i.get(s);if(!c)throw new Error(`Unknown method: ${s}`);return c(...p)}});n.add(d),t.on("close",()=>n.delete(d));});return l.diagnostics?.onDiagnosticsChanged&&l.diagnostics.onDiagnosticsChanged(t=>{for(let d of n)d.sendNotification("onDiagnosticsChanged",[t]);}),l.fileAccess.onFileChanged&&l.fileAccess.onFileChanged(t=>{for(let d of n)d.sendNotification("onFileChanged",[t]);}),new Promise((t,d)=>{if(process.platform!=="win32")try{unlinkSync(e);}catch{}a.on("error",d),a.listen(e,()=>{a.removeListener("error",d),t({get pipePath(){return e},get connectionCount(){return n.size},async close(){for(let s of n)s.destroy();if(n.clear(),await new Promise((s,p)=>{a.close(c=>{c?p(c):s();});}),process.platform!=="win32")try{unlinkSync(e);}catch{}}});});})}var k=class extends Error{constructor(e,i,o){super(`Could not find symbol '${e}' at or near line ${i}. ${o}`);this.symbolName=e;this.lineHint=i;this.reason=o;this.name="SymbolResolutionError";}},F=class{constructor(r,e){this.fs=r;this.lineSearchRadius=e?.lineSearchRadius??2;}lineSearchRadius;async resolvePosition(r,e){let o=(await this.fs.readFile(r)).split(/\r?\n/),n=e.lineHint-1,a=e.orderHint??0,t=this.findSymbolInLine(o[n],e.symbolName,a);if(t!==null)return {line:n,character:t};for(let d=1;d<=this.lineSearchRadius;d++){let s=n-d;if(s>=0){let c=this.findSymbolInLine(o[s],e.symbolName,a);if(c!==null)return {line:s,character:c}}let p=n+d;if(p<o.length){let c=this.findSymbolInLine(o[p],e.symbolName,a);if(c!==null)return {line:p,character:c}}}throw new k(e.symbolName,e.lineHint,`Please verify the file content and try again. Searched lines ${Math.max(1,e.lineHint-this.lineSearchRadius)} to ${Math.min(o.length,e.lineHint+this.lineSearchRadius)}.`)}findSymbolInLine(r,e,i){if(r===void 0||r.length===0)return null;let o=0,n=0;for(;o<r.length;){let a=r.indexOf(e,o);if(a===-1)break;if(n===i)return a;n++,o=a+1;}return null}};export{k as SymbolResolutionError,F as SymbolResolver,C as connectPipe,A as servePipe};
|
|
1
|
+
var a=class extends Error{constructor(e,s,i){super(`Could not find symbol '${e}' at or near line ${s}. ${i}`);this.symbolName=e;this.lineHint=s;this.reason=i;this.name="SymbolResolutionError";}},u=class{constructor(n,e){this.fs=n;this.lineSearchRadius=e?.lineSearchRadius??2;}lineSearchRadius;async resolvePosition(n,e){let i=(await this.fs.readFile(n)).split(/\r?\n/),r=e.lineHint-1,t=e.orderHint??0,m=this.findSymbolInLine(i[r],e.symbolName,t);if(m!==null)return {line:r,character:m};for(let l=1;l<=this.lineSearchRadius;l++){let c=r-l;if(c>=0){let o=this.findSymbolInLine(i[c],e.symbolName,t);if(o!==null)return {line:c,character:o}}let d=r+l;if(d<i.length){let o=this.findSymbolInLine(i[d],e.symbolName,t);if(o!==null)return {line:d,character:o}}}throw new a(e.symbolName,e.lineHint,`Please verify the file content and try again. Searched lines ${Math.max(1,e.lineHint-this.lineSearchRadius)} to ${Math.min(i.length,e.lineHint+this.lineSearchRadius)}.`)}findSymbolInLine(n,e,s){if(n===void 0||n.length===0)return null;let i=0,r=0;for(;i<n.length;){let t=n.indexOf(e,i);if(t===-1)break;if(r===s)return t;r++,i=t+1;}return null}};export{a as SymbolResolutionError,u as SymbolResolver};
|
|
@@ -442,4 +442,4 @@ interface EditProvider {
|
|
|
442
442
|
previewAndApplyEdits?(operation: PendingEditOperation): Promise<boolean>;
|
|
443
443
|
}
|
|
444
444
|
|
|
445
|
-
export type { CodeSnippet as C, DefinitionProvider as D, EditProvider as E, FileAccessProvider as F, GlobalFindProvider as G, HierarchyProvider as H, Link as L, OutlineProvider as O, PendingEditOperation as P, ReferencesProvider as R, SymbolKind as S, TextEdit as T, UnifiedUri as U, DiagnosticsProvider as a, GraphProvider as b, FrontmatterProvider as c,
|
|
445
|
+
export type { CodeSnippet as C, DefinitionProvider as D, EditProvider as E, FileAccessProvider as F, GlobalFindProvider as G, HierarchyProvider as H, Link as L, OutlineProvider as O, PendingEditOperation as P, ReferencesProvider as R, SymbolKind as S, TextEdit as T, UnifiedUri as U, DiagnosticsProvider as a, GraphProvider as b, FrontmatterProvider as c, EditResult as d, FrontmatterMatch as e, GlobalFindMatch as f, DiagnosticSeverity as g, Diagnostic as h, DocumentSymbol as i, ExactPosition as j, DiskRange as k, FuzzyPosition as l, EditFailureReason as m, Frontmatter as n, FrontmatterValue as o, GlobalFindOptions as p, OnDiagnosticsChangedCallback as q };
|
package/dist/lsp/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChildProcess } from 'node:child_process';
|
|
2
2
|
import { ProtocolConnection } from 'vscode-languageserver-protocol/node.js';
|
|
3
|
-
import { D as DefinitionProvider, R as ReferencesProvider, H as HierarchyProvider, O as OutlineProvider, a as DiagnosticsProvider, F as FileAccessProvider,
|
|
3
|
+
import { D as DefinitionProvider, R as ReferencesProvider, H as HierarchyProvider, O as OutlineProvider, a as DiagnosticsProvider, F as FileAccessProvider, g as DiagnosticSeverity, C as CodeSnippet, h as Diagnostic$1, i as DocumentSymbol$1, j as ExactPosition, k as DiskRange, S as SymbolKind } from '../interfaces-B9NK_71f.js';
|
|
4
4
|
import { Location, LocationLink, Diagnostic, DocumentSymbol, SymbolInformation } from 'vscode-languageserver-protocol';
|
|
5
5
|
|
|
6
6
|
interface LspClientOptions {
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -1,59 +1,8 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { F as FileAccessProvider, E as EditProvider, D as DefinitionProvider, R as ReferencesProvider, H as HierarchyProvider, a as DiagnosticsProvider, O as OutlineProvider, G as GlobalFindProvider, b as GraphProvider, c as FrontmatterProvider,
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Zod schemas for MCP tool inputs and outputs.
|
|
8
|
-
* @internal
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
declare const FuzzyPositionSchema: z.ZodObject<{
|
|
12
|
-
uri: z.ZodString;
|
|
13
|
-
symbol_name: z.ZodString;
|
|
14
|
-
line_hint: z.ZodNumber;
|
|
15
|
-
order_hint: z.ZodDefault<z.ZodNumber>;
|
|
16
|
-
}, z.core.$strip>;
|
|
17
|
-
declare const ApplyEditSchema: z.ZodObject<{
|
|
18
|
-
uri: z.ZodString;
|
|
19
|
-
start_hash: z.ZodString;
|
|
20
|
-
end_hash: z.ZodOptional<z.ZodString>;
|
|
21
|
-
replace_text: z.ZodString;
|
|
22
|
-
description: z.ZodString;
|
|
23
|
-
}, z.core.$strip>;
|
|
24
|
-
declare const CallHierarchySchema: z.ZodObject<{
|
|
25
|
-
uri: z.ZodString;
|
|
26
|
-
symbol_name: z.ZodString;
|
|
27
|
-
line_hint: z.ZodNumber;
|
|
28
|
-
order_hint: z.ZodDefault<z.ZodNumber>;
|
|
29
|
-
direction: z.ZodEnum<{
|
|
30
|
-
incoming: "incoming";
|
|
31
|
-
outgoing: "outgoing";
|
|
32
|
-
}>;
|
|
33
|
-
}, z.core.$strip>;
|
|
34
|
-
declare const GlobalFindSchema: z.ZodObject<{
|
|
35
|
-
query: z.ZodString;
|
|
36
|
-
case_sensitive: z.ZodDefault<z.ZodBoolean>;
|
|
37
|
-
exact_match: z.ZodDefault<z.ZodBoolean>;
|
|
38
|
-
regex_mode: z.ZodDefault<z.ZodBoolean>;
|
|
39
|
-
}, z.core.$strip>;
|
|
40
|
-
declare const AddLinkSchema: z.ZodObject<{
|
|
41
|
-
path: z.ZodString;
|
|
42
|
-
pattern: z.ZodString;
|
|
43
|
-
link_to: z.ZodString;
|
|
44
|
-
}, z.core.$strip>;
|
|
45
|
-
declare const FileReferencesSchema: z.ZodObject<{
|
|
46
|
-
uri: z.ZodString;
|
|
47
|
-
}, z.core.$strip>;
|
|
48
|
-
declare const GetFrontmatterStructureSchema: z.ZodObject<{
|
|
49
|
-
property: z.ZodString;
|
|
50
|
-
path: z.ZodOptional<z.ZodString>;
|
|
51
|
-
}, z.core.$strip>;
|
|
52
|
-
declare const SetFrontmatterSchema: z.ZodObject<{
|
|
53
|
-
path: z.ZodString;
|
|
54
|
-
property: z.ZodString;
|
|
55
|
-
value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodNumber, z.ZodArray<z.ZodNumber>, z.ZodBoolean, z.ZodArray<z.ZodBoolean>, z.ZodNull]>;
|
|
56
|
-
}, z.core.$strip>;
|
|
3
|
+
import { F as FileAccessProvider, E as EditProvider, D as DefinitionProvider, R as ReferencesProvider, H as HierarchyProvider, a as DiagnosticsProvider, O as OutlineProvider, G as GlobalFindProvider, b as GraphProvider, c as FrontmatterProvider, d as EditResult, e as FrontmatterMatch, f as GlobalFindMatch, L as Link } from '../interfaces-B9NK_71f.js';
|
|
4
|
+
import { ResolverConfig } from '../index.js';
|
|
5
|
+
import { FuzzyPositionSchema, ApplyEditSchema, GetFrontmatterStructureSchema, SetFrontmatterSchema, GlobalFindSchema, AddLinkSchema, CallHierarchySchema, FileReferencesSchema } from '../schemas.js';
|
|
57
6
|
|
|
58
7
|
/**
|
|
59
8
|
* MCP entry point for installing individual providers onto an MCP server.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { F as FileAccessProvider, E as EditProvider, D as DefinitionProvider, R as ReferencesProvider, H as HierarchyProvider, a as DiagnosticsProvider, O as OutlineProvider, G as GlobalFindProvider, b as GraphProvider, c as FrontmatterProvider } from '../interfaces-B9NK_71f.js';
|
|
2
|
+
|
|
3
|
+
interface connectPipeOptions {
|
|
4
|
+
pipeName: string;
|
|
5
|
+
connectTimeout?: number;
|
|
6
|
+
}
|
|
7
|
+
interface PipeConnection {
|
|
8
|
+
readonly fileAccess?: FileAccessProvider;
|
|
9
|
+
readonly edit?: EditProvider;
|
|
10
|
+
readonly definition?: DefinitionProvider;
|
|
11
|
+
readonly references?: ReferencesProvider;
|
|
12
|
+
readonly hierarchy?: HierarchyProvider;
|
|
13
|
+
readonly diagnostics?: DiagnosticsProvider;
|
|
14
|
+
readonly outline?: OutlineProvider;
|
|
15
|
+
readonly globalFind?: GlobalFindProvider;
|
|
16
|
+
readonly graph?: GraphProvider;
|
|
17
|
+
readonly frontmatter?: FrontmatterProvider;
|
|
18
|
+
readonly availableMethods: string[];
|
|
19
|
+
disconnect(): void;
|
|
20
|
+
}
|
|
21
|
+
declare function connectPipe(options: connectPipeOptions): Promise<PipeConnection>;
|
|
22
|
+
|
|
23
|
+
interface servePipeOptions {
|
|
24
|
+
pipeName: string;
|
|
25
|
+
fileAccess: FileAccessProvider;
|
|
26
|
+
edit?: EditProvider;
|
|
27
|
+
definition?: DefinitionProvider;
|
|
28
|
+
references?: ReferencesProvider;
|
|
29
|
+
hierarchy?: HierarchyProvider;
|
|
30
|
+
diagnostics?: DiagnosticsProvider;
|
|
31
|
+
outline?: OutlineProvider;
|
|
32
|
+
globalFind?: GlobalFindProvider;
|
|
33
|
+
graph?: GraphProvider;
|
|
34
|
+
frontmatter?: FrontmatterProvider;
|
|
35
|
+
}
|
|
36
|
+
interface PipeServer {
|
|
37
|
+
readonly pipePath: string;
|
|
38
|
+
readonly connectionCount: number;
|
|
39
|
+
close(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
declare function servePipe(options: servePipeOptions): Promise<PipeServer>;
|
|
42
|
+
|
|
43
|
+
export { type PipeConnection, type PipeServer, connectPipe, type connectPipeOptions, servePipe, type servePipeOptions };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import {connect,createServer}from'net';import {unlinkSync}from'fs';var v=class{socket;requestHandler;notificationHandler;nextId=1;pending=new Map;buffer="";destroyed=false;constructor(e,r){this.socket=e,this.requestHandler=r?.onRequest,this.notificationHandler=r?.onNotification,e.on("data",n=>this.handleData(n)),e.on("close",()=>this.rejectAll(new Error("Connection closed"))),e.on("error",n=>this.rejectAll(n));}sendRequest(e,r){return this.destroyed?Promise.reject(new Error("Transport destroyed")):new Promise((n,f)=>{let o=this.nextId++;this.pending.set(o,{resolve:n,reject:f});let c={type:"request",id:o,method:e,params:r};this.socket.write(`${JSON.stringify(c)}
|
|
2
|
+
`);})}sendNotification(e,r){if(this.destroyed)return;let n={type:"notification",method:e,params:r};this.socket.write(`${JSON.stringify(n)}
|
|
3
|
+
`);}destroy(){this.destroyed||(this.destroyed=true,this.rejectAll(new Error("Transport destroyed")),this.socket.destroy());}handleData(e){this.buffer+=e.toString();let r=this.buffer.split(`
|
|
4
|
+
`);this.buffer=r.pop()??"";for(let n of r){let f=n.replace(/\r$/,"");if(f)try{let o=JSON.parse(f);this.dispatch(o);}catch{}}}dispatch(e){switch(e.type){case "response":{let r=this.pending.get(e.id);r&&(this.pending.delete(e.id),e.error?r.reject(new Error(e.error.message)):r.resolve(e.result));break}case "request":{this.requestHandler&&this.requestHandler(e.method,e.params).then(r=>{if(this.destroyed)return;let n={type:"response",id:e.id,result:r};this.socket.write(`${JSON.stringify(n)}
|
|
5
|
+
`);}).catch(r=>{if(this.destroyed)return;let n={type:"response",id:e.id,error:{message:r instanceof Error?r.message:String(r)}};this.socket.write(`${JSON.stringify(n)}
|
|
6
|
+
`);});break}case "notification":{this.notificationHandler?.(e.method,e.params);break}}}rejectAll(e){for(let[,r]of this.pending)r.reject(e);this.pending.clear();}};function w(s){return process.platform==="win32"?`\\\\.\\pipe\\${s}`:`/tmp/${s}.sock`}var k=[{providerKey:"fileAccess",methods:["readFile","readDirectory"]},{providerKey:"edit",methods:["applyEdits","previewAndApplyEdits"]},{providerKey:"definition",methods:["provideDefinition"]},{providerKey:"references",methods:["provideReferences"]},{providerKey:"hierarchy",methods:["provideCallHierarchy"]},{providerKey:"diagnostics",methods:["provideDiagnostics","getWorkspaceDiagnostics"]},{providerKey:"outline",methods:["provideDocumentSymbols"]},{providerKey:"globalFind",methods:["globalFind"]},{providerKey:"graph",methods:["getLinkStructure","resolveOutlinks","resolveBacklinks","addLink"]},{providerKey:"frontmatter",methods:["getFrontmatterStructure","getFrontmatter","setFrontmatter"]}];function E(s){let{pipeName:e,connectTimeout:r=5e3}=s,n=w(e);return new Promise((f,o)=>{let c=connect(n),i=false,d=setTimeout(()=>{i||(i=true,c.destroy(),o(new Error(`Connection timeout after ${r}ms`)));},r);c.on("error",t=>{i||(i=true,clearTimeout(d),o(t));}),c.on("connect",()=>{if(clearTimeout(d),i)return;let t,l,a=new v(c,{onNotification:(h,P)=>{h==="onDiagnosticsChanged"&&t&&t(P[0]),h==="onFileChanged"&&l&&l(P[0]);}});a.sendRequest("_handshake",[]).then(h=>{if(i)return;let m=h.methods,p={};for(let{providerKey:g,methods:R}of k){let F=R.filter(u=>m.includes(`${g}.${u}`));if(F.length===0)continue;let y={};for(let u of F)y[u]=(...D)=>a.sendRequest(`${g}.${u}`,D);g==="diagnostics"&&m.includes("onDiagnosticsChanged")&&(y.onDiagnosticsChanged=u=>{t=u;}),g==="fileAccess"&&m.includes("onFileChanged")&&(y.onFileChanged=u=>{l=u;}),p[g]=y;}i=true,f({fileAccess:p.fileAccess,edit:p.edit,definition:p.definition,references:p.references,hierarchy:p.hierarchy,diagnostics:p.diagnostics,outline:p.outline,globalFind:p.globalFind,graph:p.graph,frontmatter:p.frontmatter,availableMethods:m,disconnect(){a.destroy();}});}).catch(h=>{i||(i=true,a.destroy(),o(h instanceof Error?h:new Error(String(h))));});});})}function S(s){let{pipeName:e}=s,r=w(e),n=new Map;for(let{providerKey:i,methods:d}of k){let t=s[i];if(t)for(let l of d){let a=t[l];if(typeof a=="function"){let h=`${i}.${l}`;n.set(h,(...P)=>a.apply(t,P));}}}let f=[...n.keys()];s.diagnostics?.onDiagnosticsChanged&&f.push("onDiagnosticsChanged"),s.fileAccess.onFileChanged&&f.push("onFileChanged");let o=new Set,c=createServer(i=>{let d=new v(i,{onRequest:async(t,l)=>{if(t==="_handshake")return {methods:f};let a=n.get(t);if(!a)throw new Error(`Unknown method: ${t}`);return a(...l)}});o.add(d),i.on("close",()=>o.delete(d));});return s.diagnostics?.onDiagnosticsChanged&&s.diagnostics.onDiagnosticsChanged(i=>{for(let d of o)d.sendNotification("onDiagnosticsChanged",[i]);}),s.fileAccess.onFileChanged&&s.fileAccess.onFileChanged(i=>{for(let d of o)d.sendNotification("onFileChanged",[i]);}),new Promise((i,d)=>{if(process.platform!=="win32")try{unlinkSync(r);}catch{}c.on("error",d),c.listen(r,()=>{c.removeListener("error",d),i({get pipePath(){return r},get connectionCount(){return o.size},async close(){for(let t of o)t.destroy();if(o.clear(),await new Promise((t,l)=>{c.close(a=>{a?l(a):t();});}),process.platform!=="win32")try{unlinkSync(r);}catch{}}});});})}export{E as connectPipe,S as servePipe};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Zod schemas for MCP tool inputs and outputs.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
declare const FuzzyPositionSchema: z.ZodObject<{
|
|
8
|
+
uri: z.ZodString;
|
|
9
|
+
symbol_name: z.ZodString;
|
|
10
|
+
line_hint: z.ZodNumber;
|
|
11
|
+
order_hint: z.ZodDefault<z.ZodNumber>;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
declare const ApplyEditSchema: z.ZodObject<{
|
|
14
|
+
uri: z.ZodString;
|
|
15
|
+
start_hash: z.ZodString;
|
|
16
|
+
end_hash: z.ZodOptional<z.ZodString>;
|
|
17
|
+
replace_text: z.ZodString;
|
|
18
|
+
description: z.ZodString;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
declare const CallHierarchySchema: z.ZodObject<{
|
|
21
|
+
uri: z.ZodString;
|
|
22
|
+
symbol_name: z.ZodString;
|
|
23
|
+
line_hint: z.ZodNumber;
|
|
24
|
+
order_hint: z.ZodDefault<z.ZodNumber>;
|
|
25
|
+
direction: z.ZodEnum<{
|
|
26
|
+
incoming: "incoming";
|
|
27
|
+
outgoing: "outgoing";
|
|
28
|
+
}>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
declare const GlobalFindSchema: z.ZodObject<{
|
|
31
|
+
query: z.ZodString;
|
|
32
|
+
case_sensitive: z.ZodDefault<z.ZodBoolean>;
|
|
33
|
+
exact_match: z.ZodDefault<z.ZodBoolean>;
|
|
34
|
+
regex_mode: z.ZodDefault<z.ZodBoolean>;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
declare const AddLinkSchema: z.ZodObject<{
|
|
37
|
+
path: z.ZodString;
|
|
38
|
+
pattern: z.ZodString;
|
|
39
|
+
link_to: z.ZodString;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
declare const FileReferencesSchema: z.ZodObject<{
|
|
42
|
+
uri: z.ZodString;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
declare const GetFrontmatterStructureSchema: z.ZodObject<{
|
|
45
|
+
property: z.ZodString;
|
|
46
|
+
path: z.ZodOptional<z.ZodString>;
|
|
47
|
+
}, z.core.$strip>;
|
|
48
|
+
declare const SetFrontmatterSchema: z.ZodObject<{
|
|
49
|
+
path: z.ZodString;
|
|
50
|
+
property: z.ZodString;
|
|
51
|
+
value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodNumber, z.ZodArray<z.ZodNumber>, z.ZodBoolean, z.ZodArray<z.ZodBoolean>, z.ZodNull]>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
|
|
54
|
+
export { AddLinkSchema, ApplyEditSchema, CallHierarchySchema, FileReferencesSchema, FuzzyPositionSchema, GetFrontmatterStructureSchema, GlobalFindSchema, SetFrontmatterSchema };
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {z}from'zod';var t=z.string().describe("The relative file path"),r=z.string().describe("The text of the symbol to find"),o=z.number().int().positive().describe("Approximate 1-based line number where the symbol is expected"),i=z.number().int().min(0).default(0).describe("0-based index of which occurrence to target if symbol appears multiple times"),l=z.object({uri:t,symbol_name:r,line_hint:o,order_hint:i}),d=z.object({uri:t,start_hash:z.string().describe('Start line reference from hashline output, format "<line>:<hash>" (e.g., "3:a1"). Copy this exactly from the files:// resource output.'),end_hash:z.string().optional().describe('End line reference for multi-line edits (e.g., "5:0e"). The range is inclusive. Omit for single-line edits (defaults to start_hash).'),replace_text:z.string().describe("The new text to replace the entire line range with"),description:z.string().describe("Rationale for the edit")}),p=z.object({uri:z.string().describe("The file URI or path"),symbol_name:r,line_hint:o,order_hint:i,direction:z.enum(["incoming","outgoing"]).describe("Direction of the call hierarchy")}),n=z.string().describe("The search query"),s=z.boolean().default(false).describe("Whether the search is case-sensitive"),a=z.boolean().default(false).describe("Whether to match exact words only"),c=z.boolean().default(false).describe("Whether the query is a regular expression"),b=z.object({query:n,case_sensitive:s,exact_match:a,regex_mode:c}),m=z.object({path:z.string().describe("The path to the document to modify"),pattern:z.string().describe("The text pattern to find and replace with a link"),link_to:z.string().describe("The target URI the link should point to")}),u=z.object({uri:t}),f=z.object({property:z.string().describe("The frontmatter property name to search for"),path:z.string().optional().describe("Optional path to limit the search to a specific document. If not provided, searches all documents.")}),g=z.object({path:z.string().describe("The path to the document to modify"),property:z.string().describe("The frontmatter property name to set"),value:z.union([z.string(),z.array(z.string()),z.number(),z.array(z.number()),z.boolean(),z.array(z.boolean()),z.null()]).describe("The value to set. Can be a string, number, boolean, array of these types, or null to remove.")});
|
|
2
|
+
export{m as AddLinkSchema,d as ApplyEditSchema,p as CallHierarchySchema,u as FileReferencesSchema,l as FuzzyPositionSchema,f as GetFrontmatterStructureSchema,b as GlobalFindSchema,g as SetFrontmatterSchema};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opticlm/connector",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "Provides an abstract interface that allows LLMs to connect to fact sources such as LSPs, code diagnostics, symbol definitions/references, links, and frontmatter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
"./mcp": {
|
|
17
17
|
"types": "./dist/mcp/index.d.ts",
|
|
18
18
|
"default": "./dist/mcp/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./pipe": {
|
|
21
|
+
"types": "./dist/pipe/index.d.ts",
|
|
22
|
+
"default": "./dist/pipe/index.js"
|
|
23
|
+
},
|
|
24
|
+
"./schemas": {
|
|
25
|
+
"types": "./dist/schemas.d.ts",
|
|
26
|
+
"default": "./dist/schemas.js"
|
|
19
27
|
}
|
|
20
28
|
},
|
|
21
29
|
"files": [
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { F as FileAccessProvider, U as UnifiedUri, n as FuzzyPosition, j as ExactPosition } from './interfaces-wSmWeYxt.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Smart Resolver Logic for MCP LSP Driver SDK
|
|
5
|
-
*
|
|
6
|
-
* This is the internal engine of the SDK. It translates the LLM's imprecise
|
|
7
|
-
* instructions into precise coordinates.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Configuration options for the SymbolResolver.
|
|
12
|
-
*/
|
|
13
|
-
interface ResolverConfig {
|
|
14
|
-
/**
|
|
15
|
-
* Number of lines to scan above and below the lineHint if the symbol
|
|
16
|
-
* is not found at the exact line. Defaults to 2.
|
|
17
|
-
*/
|
|
18
|
-
lineSearchRadius?: number;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Error thrown when a symbol cannot be resolved.
|
|
22
|
-
*/
|
|
23
|
-
declare class SymbolResolutionError extends Error {
|
|
24
|
-
readonly symbolName: string;
|
|
25
|
-
readonly lineHint: number;
|
|
26
|
-
readonly reason: string;
|
|
27
|
-
constructor(symbolName: string, lineHint: number, reason: string);
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* The SymbolResolver translates fuzzy positions (as provided by an LLM)
|
|
31
|
-
* into exact positions that can be used by the IDE.
|
|
32
|
-
*
|
|
33
|
-
* Algorithm:
|
|
34
|
-
* 1. Read file content via FileAccessProvider.
|
|
35
|
-
* 2. Split content into lines.
|
|
36
|
-
* 3. Target the lineHint (converting 1-based to 0-based).
|
|
37
|
-
* 4. Search for symbolName in that line.
|
|
38
|
-
* - If orderHint is 0, find first occurrence.
|
|
39
|
-
* - If orderHint is N, find Nth occurrence.
|
|
40
|
-
* 5. Robustness Fallback:
|
|
41
|
-
* - If the line is empty or symbol not found at lineHint,
|
|
42
|
-
* scan +/- lineSearchRadius lines to handle minor line shifts.
|
|
43
|
-
* 6. Return ExactPosition (line, character start index).
|
|
44
|
-
*/
|
|
45
|
-
declare class SymbolResolver {
|
|
46
|
-
private readonly fs;
|
|
47
|
-
private readonly lineSearchRadius;
|
|
48
|
-
constructor(fs: FileAccessProvider, config?: ResolverConfig);
|
|
49
|
-
/**
|
|
50
|
-
* Resolves a fuzzy position to an exact position.
|
|
51
|
-
*
|
|
52
|
-
* @param uri - The URI of the file
|
|
53
|
-
* @param fuzzy - The fuzzy position provided by the LLM
|
|
54
|
-
* @returns The exact position in the file
|
|
55
|
-
* @throws SymbolResolutionError if the symbol cannot be found
|
|
56
|
-
*/
|
|
57
|
-
resolvePosition(uri: UnifiedUri, fuzzy: FuzzyPosition): Promise<ExactPosition>;
|
|
58
|
-
/**
|
|
59
|
-
* Finds the Nth occurrence of a symbol in a line.
|
|
60
|
-
*
|
|
61
|
-
* @param line - The line to search in (may be undefined if out of bounds)
|
|
62
|
-
* @param symbolName - The symbol to find
|
|
63
|
-
* @param orderHint - Which occurrence to find (0-based)
|
|
64
|
-
* @returns The character offset of the symbol, or null if not found
|
|
65
|
-
*/
|
|
66
|
-
private findSymbolInLine;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export { type ResolverConfig as R, SymbolResolutionError as S, SymbolResolver as a };
|