@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 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, 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-wSmWeYxt.js';
2
- export { C as CodeSnippet, d as Diagnostic, e as DiagnosticSeverity, f as DiskRange, g as DocumentSymbol, h as EditFailureReason, i as EditResult, j as ExactPosition, k as Frontmatter, l as FrontmatterMatch, m as FrontmatterValue, n as FuzzyPosition, o as GlobalFindMatch, p as GlobalFindOptions, L as Link, q as OnDiagnosticsChangedCallback, P as PendingEditOperation, S as SymbolKind, T as TextEdit, U as UnifiedUri } from './interfaces-wSmWeYxt.js';
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
- interface connectPipeOptions {
6
- pipeName: string;
7
- connectTimeout?: number;
8
- }
9
- interface LspPipeConnection {
10
- readonly fileAccess?: FileAccessProvider;
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
- interface servePipeOptions {
26
- pipeName: string;
27
- fileAccess: FileAccessProvider;
28
- edit?: EditProvider;
29
- definition?: DefinitionProvider;
30
- references?: ReferencesProvider;
31
- hierarchy?: HierarchyProvider;
32
- diagnostics?: DiagnosticsProvider;
33
- outline?: OutlineProvider;
34
- globalFind?: GlobalFindProvider;
35
- graph?: GraphProvider;
36
- frontmatter?: FrontmatterProvider;
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
- interface LspPipeServer {
39
- readonly pipePath: string;
40
- readonly connectionCount: number;
41
- close(): Promise<void>;
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 { DefinitionProvider, DiagnosticsProvider, EditProvider, FileAccessProvider, FrontmatterProvider, GlobalFindProvider, GraphProvider, HierarchyProvider, type LspPipeConnection, type LspPipeServer, OutlineProvider, ReferencesProvider, connectPipe, type connectPipeOptions, servePipe, type servePipeOptions };
70
+ export { ExactPosition, FileAccessProvider, FuzzyPosition, type ResolverConfig, SymbolResolutionError, SymbolResolver, UnifiedUri };
package/dist/index.js CHANGED
@@ -1,6 +1 @@
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(r,e){this.socket=r,this.requestHandler=e?.onRequest,this.notificationHandler=e?.onNotification,r.on("data",i=>this.handleData(i)),r.on("close",()=>this.rejectAll(new Error("Connection closed"))),r.on("error",i=>this.rejectAll(i));}sendRequest(r,e){return this.destroyed?Promise.reject(new Error("Transport destroyed")):new Promise((i,o)=>{let n=this.nextId++;this.pending.set(n,{resolve:i,reject:o});let a={type:"request",id:n,method:r,params:e};this.socket.write(`${JSON.stringify(a)}
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, Diagnostic as d, DiagnosticSeverity as e, DiskRange as f, DocumentSymbol as g, EditFailureReason as h, EditResult as i, ExactPosition as j, Frontmatter as k, FrontmatterMatch as l, FrontmatterValue as m, FuzzyPosition as n, GlobalFindMatch as o, GlobalFindOptions as p, OnDiagnosticsChangedCallback as q };
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 };
@@ -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, e as DiagnosticSeverity, C as CodeSnippet, d as Diagnostic$1, g as DocumentSymbol$1, j as ExactPosition, f as DiskRange, S as SymbolKind } from '../interfaces-wSmWeYxt.js';
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 {
@@ -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, i as EditResult, l as FrontmatterMatch, o as GlobalFindMatch, L as Link } from '../interfaces-wSmWeYxt.js';
4
- import { R as ResolverConfig } from '../resolver-CSuvobsJ.js';
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 };
@@ -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.2.0",
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 };