@opticlm/connector 2.3.0 → 2.4.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/README.md +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/{interfaces-B9NK_71f.d.ts → interfaces-DaNlFJZG.d.ts} +18 -35
- package/dist/lsp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +8 -7
- package/dist/pipe/index.d.ts +6 -6
- package/dist/pipe/index.js +3 -3
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -54,8 +54,8 @@ const fileAccess = {
|
|
|
54
54
|
// 3. Implement Edit Provider
|
|
55
55
|
const edit = {
|
|
56
56
|
// Show diff in your IDE and get user approval
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
applyEdits: async (operation) => {
|
|
58
|
+
// ...
|
|
59
59
|
},
|
|
60
60
|
}
|
|
61
61
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { F as FileAccessProvider, U as UnifiedUri, l as FuzzyPosition, j as ExactPosition } from './interfaces-
|
|
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
|
|
1
|
+
import { F as FileAccessProvider, U as UnifiedUri, l as FuzzyPosition, j as ExactPosition } from './interfaces-DaNlFJZG.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 } from './interfaces-DaNlFJZG.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Smart Resolver Logic
|
|
5
|
+
* Smart Resolver Logic
|
|
6
6
|
*
|
|
7
7
|
* This is the internal engine of the SDK. It translates the LLM's imprecise
|
|
8
8
|
* instructions into precise coordinates.
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Core Data Models
|
|
2
|
+
* Core Data Models
|
|
3
3
|
*
|
|
4
|
-
* These types define how the LLM communicates intent versus
|
|
5
|
-
* how the IDE executes commands.
|
|
4
|
+
* These types define how the LLM communicates intent versus how the IDE executes commands.
|
|
6
5
|
*/
|
|
7
6
|
/**
|
|
8
7
|
* A Unified Resource Identifier.
|
|
@@ -57,25 +56,18 @@ interface CodeSnippet {
|
|
|
57
56
|
/** The actual text read from disk */
|
|
58
57
|
content: string;
|
|
59
58
|
}
|
|
60
|
-
/**
|
|
61
|
-
* Represents a proposed change to a file.
|
|
62
|
-
*/
|
|
63
|
-
interface TextEdit {
|
|
64
|
-
/** The range to replace */
|
|
65
|
-
range: DiskRange;
|
|
66
|
-
/** The new text to insert */
|
|
67
|
-
newText: string;
|
|
68
|
-
}
|
|
69
59
|
/**
|
|
70
60
|
* Represents a pending edit operation that awaits user approval.
|
|
61
|
+
* The SDK resolves edits against the current file content and provides
|
|
62
|
+
* the fully updated file text, so plugins only need to write the result.
|
|
71
63
|
*/
|
|
72
64
|
interface PendingEditOperation {
|
|
73
65
|
/** Unique identifier for this operation */
|
|
74
66
|
id: string;
|
|
75
67
|
/** The URI of the file to edit */
|
|
76
68
|
uri: UnifiedUri;
|
|
77
|
-
/** The
|
|
78
|
-
|
|
69
|
+
/** The full updated content of the file after applying the edit */
|
|
70
|
+
updated: string;
|
|
79
71
|
/** Optional description of the edit (e.g., "Refactor logic to handle null cases") */
|
|
80
72
|
description?: string;
|
|
81
73
|
}
|
|
@@ -84,11 +76,15 @@ interface PendingEditOperation {
|
|
|
84
76
|
*/
|
|
85
77
|
type EditFailureReason = 'UserRejected' | 'IOError' | 'ValidationFailed';
|
|
86
78
|
/**
|
|
87
|
-
* The result of
|
|
79
|
+
* The result of editing a file.
|
|
80
|
+
* The edit may be automatically approved, or it may require user approval;
|
|
81
|
+
* the user may reject it, approve it, or make changes based on the existing edit.
|
|
88
82
|
*/
|
|
89
83
|
type EditResult = {
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
type: EditFailureReason;
|
|
85
|
+
} | {
|
|
86
|
+
type: 'Approved';
|
|
87
|
+
updated: string;
|
|
92
88
|
};
|
|
93
89
|
/**
|
|
94
90
|
* Severity level for diagnostics.
|
|
@@ -172,7 +168,7 @@ interface Link {
|
|
|
172
168
|
}
|
|
173
169
|
|
|
174
170
|
/**
|
|
175
|
-
* Capability Providers
|
|
171
|
+
* Capability Providers
|
|
176
172
|
*
|
|
177
173
|
* Each provider interface corresponds to one LSP capability.
|
|
178
174
|
* Note: All inputs use ExactPosition. The SDK handles Fuzzy -> Exact conversion.
|
|
@@ -383,10 +379,7 @@ interface FrontmatterProvider {
|
|
|
383
379
|
type OnDiagnosticsChangedCallback = (uri: UnifiedUri) => void;
|
|
384
380
|
|
|
385
381
|
/**
|
|
386
|
-
* Infrastructure Interfaces
|
|
387
|
-
*
|
|
388
|
-
* The SDK consumer (Plugin Developer) must implement these interfaces
|
|
389
|
-
* to bridge the SDK to the specific IDE.
|
|
382
|
+
* Infrastructure Interfaces
|
|
390
383
|
*/
|
|
391
384
|
|
|
392
385
|
/**
|
|
@@ -421,25 +414,15 @@ interface FileAccessProvider {
|
|
|
421
414
|
}
|
|
422
415
|
/**
|
|
423
416
|
* Provides edit capabilities for applying changes to files.
|
|
424
|
-
* At least one of the methods must be implemented.
|
|
425
417
|
*/
|
|
426
418
|
interface EditProvider {
|
|
427
419
|
/**
|
|
428
|
-
* Applies edits
|
|
429
|
-
* Use this when user approval is handled elsewhere or not needed.
|
|
420
|
+
* Applies edits.
|
|
430
421
|
*
|
|
431
422
|
* @param operation - The pending edit operation to apply
|
|
432
423
|
* @returns true if applied successfully, false if failed
|
|
433
424
|
*/
|
|
434
|
-
applyEdits
|
|
435
|
-
/**
|
|
436
|
-
* Displays a diff view or a confirmation dialog in the IDE.
|
|
437
|
-
* The user decides whether to apply the edits or discard them.
|
|
438
|
-
*
|
|
439
|
-
* @param operation - The pending edit operation to preview
|
|
440
|
-
* @returns true if applied, false if rejected/cancelled
|
|
441
|
-
*/
|
|
442
|
-
previewAndApplyEdits?(operation: PendingEditOperation): Promise<boolean>;
|
|
425
|
+
applyEdits(operation: PendingEditOperation): Promise<EditResult>;
|
|
443
426
|
}
|
|
444
427
|
|
|
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,
|
|
428
|
+
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, 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, 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-
|
|
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-DaNlFJZG.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,6 +1,6 @@
|
|
|
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, d as EditResult, e as FrontmatterMatch, f as GlobalFindMatch, L as Link } from '../interfaces-
|
|
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-DaNlFJZG.js';
|
|
4
4
|
import { ResolverConfig } from '../index.js';
|
|
5
5
|
import { FuzzyPositionSchema, ApplyEditSchema, GetFrontmatterStructureSchema, SetFrontmatterSchema, GlobalFindSchema, AddLinkSchema, CallHierarchySchema, FileReferencesSchema } from '../schemas.js';
|
|
6
6
|
|
package/dist/mcp/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {ResourceTemplate}from'@modelcontextprotocol/sdk/server/mcp.js';import {z as z$1}from'zod';var g=class extends Error{constructor(
|
|
2
|
-
`)}function
|
|
3
|
-
${
|
|
4
|
-
`)}var H=new Uint16Array(256);for(let a=0;a<256;a++){let
|
|
5
|
-
`)}function
|
|
6
|
-
${
|
|
1
|
+
import {ResourceTemplate}from'@modelcontextprotocol/sdk/server/mcp.js';import {z as z$1}from'zod';var g=class extends Error{constructor(n,r,t){super(`Could not find symbol '${n}' at or near line ${r}. ${t}`);this.symbolName=n;this.lineHint=r;this.reason=t;this.name="SymbolResolutionError";}},k=class{constructor(i,n){this.fs=i;this.lineSearchRadius=n?.lineSearchRadius??2;}lineSearchRadius;async resolvePosition(i,n){let t=(await this.fs.readFile(i)).split(/\r?\n/),e=n.lineHint-1,o=n.orderHint??0,s=this.findSymbolInLine(t[e],n.symbolName,o);if(s!==null)return {line:e,character:s};for(let c=1;c<=this.lineSearchRadius;c++){let l=e-c;if(l>=0){let h=this.findSymbolInLine(t[l],n.symbolName,o);if(h!==null)return {line:l,character:h}}let d=e+c;if(d<t.length){let h=this.findSymbolInLine(t[d],n.symbolName,o);if(h!==null)return {line:d,character:h}}}throw new g(n.symbolName,n.lineHint,`Please verify the file content and try again. Searched lines ${Math.max(1,n.lineHint-this.lineSearchRadius)} to ${Math.min(t.length,n.lineHint+this.lineSearchRadius)}.`)}findSymbolInLine(i,n,r){if(i===void 0||i.length===0)return null;let t=0,e=0;for(;t<i.length;){let o=i.indexOf(n,t);if(o===-1)break;if(e===r)return o;e++,t=o+1;}return null}};var f=a=>({content:[{type:"text",text:JSON.stringify(a??"")}],structuredContent:a});function m(a){if(a.includes(".."))throw new Error('URI could not include ".." operator');return a.replace(/\\/g,"/")}function C(){return `edit-${Date.now()}`}function $(a){return a.length===0?"No diagnostics found.":a.map(i=>{let n=i.range.start.line+1,r=i.severity.toUpperCase(),t=i.source?` [${i.source}]`:"",e=i.code!==void 0?` (${i.code})`:"";return `- **${r}**${t}${e} at line ${n}: ${i.message}`}).join(`
|
|
2
|
+
`)}function A(a,i=0){if(a.length===0&&i===0)return "No symbols found.";let n=" ".repeat(i);return a.map(r=>{let t=r.range.start.line+1,e=r.range.end.line+1,o=t===e?`line ${t}`:`lines ${t}-${e}`,s=r.detail?` - ${r.detail}`:"",c=`${n}- **${r.kind}** \`${r.name}\`${s} (${o})`;return r.children&&r.children.length>0?`${c}
|
|
3
|
+
${A(r.children,i+1)}`:c}).join(`
|
|
4
|
+
`)}var H=new Uint16Array(256);for(let a=0;a<256;a++){let i=a<<8;for(let n=0;n<8;n++)i=i<<1^(i&32768?4129:0);H[a]=i&65535;}function R(a){let i=65535;for(let n=0;n<a.length;n++)i=i<<8&65535^H[(i>>8^a.charCodeAt(n))&255];return (i&255).toString(16).padStart(2,"0")}function M(a){return a.split(/\r?\n/).map((i,n)=>({num:n+1,text:i}))}function j(a){return a.map(i=>`${i.num}:${R(i.text)}|${i.text}`).join(`
|
|
5
|
+
`)}function _(a){let i=a.match(/^(\d+):([0-9a-f]{2})$/);if(!i||!i[1]||!i[2])throw new Error(`Invalid hashline reference "${a}". Expected format: "<line>:<hash>" (e.g., "3:a1")`);return {line:parseInt(i[1],10),hash:i[2]}}var z=z$1.string().describe("The relative file path"),N=z$1.string().describe("The text of the symbol to find"),U=z$1.number().int().positive().describe("Approximate 1-based line number where the symbol is expected"),W=z$1.number().int().min(0).default(0).describe("0-based index of which occurrence to target if symbol appears multiple times"),I=z$1.object({uri:z,symbol_name:N,line_hint:U,order_hint:W}),y=z$1.object({uri:z,start_hash:z$1.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$1.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$1.string().describe("The new text to replace the entire line range with"),description:z$1.string().describe("Rationale for the edit")}),J=z$1.object({uri:z$1.string().describe("The file URI or path"),symbol_name:N,line_hint:U,order_hint:W,direction:z$1.enum(["incoming","outgoing"]).describe("Direction of the call hierarchy")}),he=z$1.string().describe("The search query"),ge=z$1.boolean().default(false).describe("Whether the search is case-sensitive"),ye=z$1.boolean().default(false).describe("Whether to match exact words only"),ve=z$1.boolean().default(false).describe("Whether the query is a regular expression"),q=z$1.object({query:he,case_sensitive:ge,exact_match:ye,regex_mode:ve}),B=z$1.object({path:z$1.string().describe("The path to the document to modify"),pattern:z$1.string().describe("The text pattern to find and replace with a link"),link_to:z$1.string().describe("The target URI the link should point to")}),Q=z$1.object({uri:z}),K=z$1.object({property:z$1.string().describe("The frontmatter property name to search for"),path:z$1.string().optional().describe("Optional path to limit the search to a specific document. If not provided, searches all documents.")}),V=z$1.object({path:z$1.string().describe("The path to the document to modify"),property:z$1.string().describe("The frontmatter property name to set"),value:z$1.union([z$1.string(),z$1.array(z$1.string()),z$1.number(),z$1.array(z$1.number()),z$1.boolean(),z$1.array(z$1.boolean()),z$1.null()]).describe("The value to set. Can be a string, number, boolean, array of these types, or null to remove.")});function Se(a){if(!a)return null;let i=a.match(/^L(\d+)(?:-L(\d+))?$/);if(!i||!i[1])return null;let n=parseInt(i[1],10),r=i[2]?parseInt(i[2],10):n;return n<1||r<n?null:{start:n,end:r}}function X(a){let i=a.indexOf("?");return i===-1?{path:a,params:new URLSearchParams}:{path:a.slice(0,i),params:new URLSearchParams(a.slice(i+1))}}function G(a){return async i=>{let n=i.lastIndexOf("/"),r=n>=0?i.slice(0,n):"",t=n>=0?i.slice(n+1):i;try{let e=await a(r||"."),o=t.toLowerCase();return e.filter(s=>s.toLowerCase().startsWith(o)).map(s=>r?`${r}/${s}`:s)}catch{return []}}}function Y(a,i,n,r){a.registerTool("goto_definition",{description:"Navigate to the definition of a symbol.",inputSchema:I,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async t=>{r?.onInput?.(t);try{let e=m(t.uri),o={symbolName:t.symbol_name,lineHint:t.line_hint,orderHint:t.order_hint},s=await n.resolvePosition(e,o),c=(await i.provideDefinition(e,s)).map(l=>({uri:l.uri,startLine:l.range.start.line+1,endLine:l.range.end.line+1,content:l.content}));return r?.onOutput?.({snippets:c}),f({snippets:c})}catch(e){let o=e instanceof g?e.message:`Error: ${e instanceof Error?e.message:String(e)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function Z(a,i,n,r){let t=i.provideTypeDefinition;t&&a.registerTool("goto_type_definition",{description:"Navigate to the type definition of a symbol.",inputSchema:I,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async e=>{r?.onInput?.(e);try{let o=m(e.uri),s={symbolName:e.symbol_name,lineHint:e.line_hint,orderHint:e.order_hint},c=await n.resolvePosition(o,s),l=(await t(o,c)).map(d=>({uri:d.uri,startLine:d.range.start.line+1,endLine:d.range.end.line+1,content:d.content}));return r?.onOutput?.({snippets:l}),f({snippets:l})}catch(o){let s=o instanceof g?o.message:`Error: ${o instanceof Error?o.message:String(o)}`;return {content:[{type:"text",text:s}],structuredContent:{error:s},isError:true}}});}function ee(a,i,n,r){a.registerTool("find_references",{description:"Find all references to a symbol. Returns a list of locations where the symbol is used.",inputSchema:I,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async t=>{r?.onInput?.(t);try{let e=m(t.uri),o={symbolName:t.symbol_name,lineHint:t.line_hint,orderHint:t.order_hint},s=await n.resolvePosition(e,o),c=(await i.provideReferences(e,s)).map(l=>({uri:l.uri,startLine:l.range.start.line+1,endLine:l.range.end.line+1,content:l.content}));return r?.onOutput?.({snippets:c}),f({snippets:c})}catch(e){let o=e instanceof g?e.message:`Error: ${e instanceof Error?e.message:String(e)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function te(a,i,n,r){a.registerTool("call_hierarchy",{description:"Get call hierarchy for a function or method. Shows incoming or outgoing calls.",inputSchema:J,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async t=>{r?.onInput?.(t);try{let e=m(t.uri),o={symbolName:t.symbol_name,lineHint:t.line_hint,orderHint:t.order_hint},s=await n.resolvePosition(e,o),c=(await i.provideCallHierarchy(e,s,t.direction)).map(l=>({uri:l.uri,startLine:l.range.start.line+1,endLine:l.range.end.line+1,content:l.content}));return r?.onOutput?.({snippets:c}),f({snippets:c})}catch(e){let o=e instanceof g?e.message:`Error: ${e instanceof Error?e.message:String(e)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function re(a,i,n){let r=i.provideFileReferences;r&&a.registerTool("find_file_references",{description:"Find all references to a file across the workspace. Returns locations that import or link to the given file.",inputSchema:Q,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async t=>{n?.onInput?.(t);try{let e=m(t.uri),o=(await r(e)).map(s=>({uri:s.uri,startLine:s.range.start.line+1,endLine:s.range.end.line+1,content:s.content}));return n?.onOutput?.({snippets:o}),f({snippets:o})}catch(e){let o=`Error: ${e instanceof Error?e.message:String(e)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function ne(a,i,n){let r=new ResourceTemplate("diagnostics://{+path}",{list:void 0,complete:n?{path:n}:void 0});if(a.registerResource("diagnostics",r,{description:"Diagnostics (errors, warnings, hints) for a specific file. Use the file path after diagnostics://",mimeType:"text/markdown"},async(t,e)=>{try{let o=e.path,s=m(o),c=await i.provideDiagnostics(s),l=$(c);return {contents:[{uri:`diagnostics://${o}`,mimeType:"text/markdown",text:l}]}}catch(o){let s=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`diagnostics://${e.path}`,mimeType:"text/markdown",text:s}]}}}),i.getWorkspaceDiagnostics){let t=i.getWorkspaceDiagnostics.bind(i);a.registerResource("workspace-diagnostics","diagnostics://workspace",{description:"All diagnostics (errors, warnings, hints) across the entire workspace",mimeType:"text/markdown"},async()=>{try{let e=await t(),o=new Map;for(let c of e){let l=o.get(c.uri)??[];l.push(c),o.set(c.uri,l);}if(o.size===0)return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:"No diagnostics found in workspace."}]};let s=[];for(let[c,l]of o)s.push(`## ${c}
|
|
6
|
+
${$(l)}`);return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:s.join(`
|
|
7
7
|
|
|
8
|
-
`)}]}}catch(e){return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:`Error: ${e instanceof Error?e.message:String(e)}`}]}}});}n.onDiagnosticsChanged&&n.onDiagnosticsChanged(t=>{let e=d(t);a.server.sendResourceUpdated({uri:`diagnostics://${e}`}),n.getWorkspaceDiagnostics&&a.server.sendResourceUpdated({uri:"diagnostics://workspace"});});}function ie(a,n,i){let r=new ResourceTemplate("outline://{+path}",{list:void 0,complete:i?{path:i}:void 0});a.registerResource("outline",r,{description:"Document outline (symbols like classes, functions, variables) for a specific file. Use the file path after outline://",mimeType:"text/markdown"},async(t,e)=>{try{let o=e.path,s=d(o),c=await n.provideDocumentSymbols(s),l=$(c);return {contents:[{uri:`outline://${o}`,mimeType:"text/markdown",text:l}]}}catch(o){let s=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`outline://${e.path}`,mimeType:"text/markdown",text:s}]}}});}function oe(a,n,i,r){let t=n.previewAndApplyEdits?.bind(n)??n.applyEdits?.bind(n);t&&a.registerTool("apply_edit",{description:'Apply a text edit to a file. WORKFLOW: First read the file via the files:// resource to get hashline-formatted content (e.g., "3:a1| return x"). Then reference lines by their "line:hash" to specify the edit range. The hash verifies the file has not changed since your read \u2014 if it has, the edit is rejected and you must re-read the file. For single-line edits, only start_hash is needed. For multi-line edits, provide both start_hash and end_hash. The edit replaces the entire line range (inclusive) with replace_text. The edit must be approved by the user before being applied.',inputSchema:{uri:v.shape.uri,start_hash:v.shape.start_hash,end_hash:v.shape.end_hash,replace_text:v.shape.replace_text,description:v.shape.description},outputSchema:{success:z$1.boolean(),message:z$1.string()}},async e=>{r?.onInput?.(e);try{let o=d(e.uri),s=A(e.start_hash),c=e.end_hash?A(e.end_hash):s,m=(await i(o)).split(/\r?\n/);if(s.line<1||s.line>m.length)throw new Error(`Start line ${s.line} is out of range (file has ${m.length} lines)`);if(c.line<s.line||c.line>m.length)throw new Error(`End line ${c.line} is out of range (file has ${m.length} lines)`);let h=m[s.line-1],b=k(h);if(b!==s.hash)throw new Error(`Hash mismatch at line ${s.line}: expected "${s.hash}", got "${b}". File has changed since last read.`);let P=m[c.line-1],F=k(P);if(F!==c.hash)throw new Error(`Hash mismatch at line ${c.line}: expected "${c.hash}", got "${F}". File has changed since last read.`);let E={start:{line:s.line-1,character:0},end:{line:c.line-1,character:P.length}},I={id:C(),uri:o,edits:[{range:E,newText:e.replace_text}],description:e.description},y=await t(I)?{success:!0,message:"Edit successfully applied and saved."}:{success:!1,message:"Edit rejected by user."};return r?.onOutput?.(y),f(y)}catch(o){let s=`Error: ${o instanceof Error?o.message:String(o)}`;return {content:[{type:"text",text:s}],structuredContent:{success:false,message:s},isError:true}}});}function se(a,n){let{readFile:i,readDirectory:r}=n,t=new ResourceTemplate("files://{+path}",{list:void 0,complete:{path:z(r)}});a.registerResource("filesystem",t,{description:'Access filesystem resources. For directories: returns children as JSON (git-ignored files excluded). For files: returns content in hashline format where each line is prefixed with "<lineNumber>:<hash>|" (e.g., "1:a3|function hello() {"). The hash is a 2-char hex CRC16 digest of the line content. Use these line:hash references with the apply_edit tool to make edits. Supports line ranges with #L23 or #L23-L30 fragment. Supports regex filtering with ?pattern=<regex> query parameter (matches raw line text, not the hash prefix). Line numbers in the output are always the original file line numbers, even when filtering.'},async(e,o)=>{let s=e.toString();try{let c=o.path,l,m=c,h=c.indexOf("#");h!==-1&&(l=c.slice(h+1),m=c.slice(0,h));let{path:b,params:P}=X(m),{path:F,params:E}=X(l??"");l=l?F:void 0;let I=new URLSearchParams([...P.entries(),...E.entries()]),T=d(b),y=Se(l),G=I.get("pattern");try{let D=await i(T),x=M(D);if(y&&(x=x.filter(w=>w.num>=y.start&&w.num<=y.end)),G){let w=new RegExp(G);x=x.filter(fe=>w.test(fe.text));}return {contents:[{uri:s,mimeType:"text/plain",text:j(x)}]}}catch{let D=await r(T);return {contents:[{uri:s,mimeType:"application/json",text:JSON.stringify(D)}]}}}catch(c){let l=`Error: ${c instanceof Error?c.message:String(c)}`;return {contents:[{uri:s,mimeType:"text/plain",text:l}]}}}),n.onFileChanged&&n.onFileChanged(e=>{let o=d(e);a.server.sendResourceUpdated({uri:`files://${o}`});});}function ae(a,n,i){a.registerTool("global_find",{description:"Search for text across the entire workspace.",inputSchema:q,outputSchema:{matches:z$1.array(z$1.object({uri:z$1.string(),line:z$1.number(),column:z$1.number(),matchText:z$1.string(),context:z$1.string()})),count:z$1.number()}},async r=>{i?.onInput?.(r);try{let t=r.case_sensitive??!1,e=r.exact_match??!1,o=r.regex_mode??!1,s=await n.globalFind(r.query,{caseSensitive:t,exactMatch:e,regexMode:o});return i?.onOutput?.({count:s.length,matches:s}),f({count:s.length,matches:s})}catch(t){let e=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:e}],structuredContent:{error:e},isError:true}}});}function ce(a,n,i){let r=new ResourceTemplate("outlinks://{+path}",{list:void 0,complete:i?{path:i}:void 0});a.registerResource("outlinks",r,{description:"Outgoing links from a specific file. Use the file path after outlinks://",mimeType:"application/json"},async(e,o)=>{try{let s=o.path,c=d(s),l=await n.resolveOutlinks(c);return {contents:[{uri:`outlinks://${s}`,mimeType:"application/json",text:JSON.stringify(l,null,2)}]}}catch(s){let c=`Error: ${s instanceof Error?s.message:String(s)}`;return {contents:[{uri:`outlinks://${o.path}`,mimeType:"application/json",text:JSON.stringify({error:c})}]}}});let t=new ResourceTemplate("backlinks://{+path}",{list:void 0,complete:i?{path:i}:void 0});a.registerResource("backlinks",t,{description:"Incoming links (backlinks) to a specific file. Use the file path after backlinks://",mimeType:"application/json"},async(e,o)=>{try{let s=o.path,c=d(s),l=await n.resolveBacklinks(c);return {contents:[{uri:`backlinks://${s}`,mimeType:"application/json",text:JSON.stringify(l,null,2)}]}}catch(s){let c=`Error: ${s instanceof Error?s.message:String(s)}`;return {contents:[{uri:`backlinks://${o.path}`,mimeType:"application/json",text:JSON.stringify({error:c})}]}}});}function ue(a,n,i){a.registerTool("get_link_structure",{description:"Get all links in the workspace, showing relationships between documents.",inputSchema:{},outputSchema:{links:z$1.array(z$1.object({sourceUri:z$1.string(),targetUri:z$1.string(),subpath:z$1.string().optional(),displayText:z$1.string().optional(),resolved:z$1.boolean(),line:z$1.number(),column:z$1.number()}))}},async()=>{try{let r=await n.getLinkStructure();return i?.onOutput?.({links:r}),f({links:r})}catch(r){let t=`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:t}],structuredContent:{error:t},isError:true}}});}function le(a,n,i){a.registerTool("add_link",{description:"Add a link to a document by finding a text pattern and replacing it with a link to the target.",inputSchema:B,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async r=>{i?.onInput?.(r);try{let t=d(r.path),e=d(r.link_to);await n.addLink(t,r.pattern,e);let o={success:!0,message:"Link added successfully."};return i?.onOutput?.(o),f(o)}catch(t){let e=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:e}],structuredContent:{success:false,message:e},isError:true}}});}function pe(a,n,i){a.registerTool("get_frontmatter_structure",{description:"Get frontmatter property values across documents. If path is provided, searches only that document. Otherwise, searches all documents.",inputSchema:K,outputSchema:{matches:z$1.array(z$1.object({path:z$1.string(),value:z$1.unknown()}))}},async r=>{i?.onInput?.(r);try{let t=r.path?d(r.path):void 0,e=await n.getFrontmatterStructure(r.property,t);return i?.onOutput?.({matches:e}),f({matches:e})}catch(t){let e=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:e}],structuredContent:{error:e},isError:true}}});}function de(a,n,i){a.registerTool("set_frontmatter",{description:"Set a frontmatter property on a document. Use null to remove the property.",inputSchema:V,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async r=>{i?.onInput?.(r);try{let t=d(r.path),e=r.value===null?void 0:r.value;await n.setFrontmatter(t,r.property,e);let o={success:!0,message:"Frontmatter updated successfully."};return i?.onOutput?.(o),f(o)}catch(t){let e=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:e}],structuredContent:{success:false,message:e},isError:true}}});}function me(a,n,i){let r=new ResourceTemplate("frontmatter://{+path}",{list:void 0,complete:i?{path:i}:void 0});a.registerResource("frontmatter",r,{description:"Frontmatter metadata for a specific file. Use the file path after frontmatter://",mimeType:"application/json"},async(t,e)=>{try{let o=e.path,s=d(o),c=await n.getFrontmatter(s);return {contents:[{uri:`frontmatter://${o}`,mimeType:"application/json",text:JSON.stringify(c,null,2)}]}}catch(o){let s=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`frontmatter://${e.path}`,mimeType:"application/json",text:JSON.stringify({error:s})}]}}});}function xe(a){if(a.length<=0)throw new Error("providers array must not be empty");if(a.length===1&&a[0])return a[0];let n=a[0];if(!n)throw new Error("The first item of providers array must be defined");if("readFile"in n&&"readDirectory"in n){let i=a,r={readFile:t=>n.readFile(t),readDirectory:t=>n.readDirectory(t)};return i.some(t=>t.onFileChanged)&&(r.onFileChanged=t=>{for(let e of i)e.onFileChanged?.(t);}),r}if("applyEdits"in n||"previewAndApplyEdits"in n)return n;if("provideDefinition"in n){let i=a,r={async provideDefinition(t,e){return (await Promise.all(i.map(s=>s.provideDefinition(t,e)))).flat()}};return i.some(t=>t.provideTypeDefinition)&&(r.provideTypeDefinition=async(t,e)=>{let o=i.filter(c=>c.provideTypeDefinition);return (await Promise.all(o.map(c=>c.provideTypeDefinition(t,e)))).flat()}),r}if("provideReferences"in n){let i=a,r={async provideReferences(t,e){return (await Promise.all(i.map(s=>s.provideReferences(t,e)))).flat()}};return i.some(t=>t.provideFileReferences)&&(r.provideFileReferences=async t=>{let e=i.filter(s=>s.provideFileReferences);return (await Promise.all(e.map(s=>s.provideFileReferences(t)))).flat()}),r}if("provideCallHierarchy"in n){let i=a;return {async provideCallHierarchy(r,t,e){return (await Promise.all(i.map(s=>s.provideCallHierarchy(r,t,e)))).flat()}}}if("provideDiagnostics"in n){let i=a,r={async provideDiagnostics(t){return (await Promise.all(i.map(o=>o.provideDiagnostics(t)))).flat()}};return i.some(t=>t.getWorkspaceDiagnostics)&&(r.getWorkspaceDiagnostics=async()=>{let t=i.filter(o=>o.getWorkspaceDiagnostics);return (await Promise.all(t.map(o=>o.getWorkspaceDiagnostics()))).flat()}),i.some(t=>t.onDiagnosticsChanged)&&(r.onDiagnosticsChanged=t=>{for(let e of i)e.onDiagnosticsChanged?.(t);}),r}if("provideDocumentSymbols"in n){let i=a;return {async provideDocumentSymbols(r){return (await Promise.all(i.map(e=>e.provideDocumentSymbols(r)))).flat()}}}if("globalFind"in n){let i=a;return {async globalFind(r,t){return (await Promise.all(i.map(o=>o.globalFind(r,t)))).flat()}}}if("getLinkStructure"in n){let i=a;return {async getLinkStructure(){return (await Promise.all(i.map(t=>t.getLinkStructure()))).flat()},async resolveOutlinks(r){return (await Promise.all(i.map(e=>e.resolveOutlinks(r)))).flat()},async resolveBacklinks(r){return (await Promise.all(i.map(e=>e.resolveBacklinks(r)))).flat()},async addLink(r,t,e){await Promise.all(i.map(o=>o.addLink(r,t,e)));}}}if("getFrontmatterStructure"in n){let i=a;return {async getFrontmatterStructure(r,t){return (await Promise.all(i.map(o=>o.getFrontmatterStructure(r,t)))).flat()},async getFrontmatter(r){let t=await Promise.all(i.map(e=>e.getFrontmatter(r)));return Object.assign({},...t)},async setFrontmatter(r,t,e){await Promise.all(i.map(o=>o.setFrontmatter(r,t,e)));}}}return n}function _e(a,n,i){let r=Array.isArray(n)?xe(n):n,t=i?.fileAccess,e=t?z(t.readDirectory):void 0,o=()=>{if(!t)throw new Error("fileAccess is required in options for providers that need symbol resolution");return new O(t,i?.resolverConfig)};if("readFile"in r&&"readDirectory"in r){se(a,r);return}if("applyEdits"in r||"previewAndApplyEdits"in r){if(!t)throw new Error("fileAccess is required in options when installing an EditProvider");let s=i;oe(a,r,t.readFile,{onInput:s?.onEditInput,onOutput:s?.onEditOutput});return}if("provideDefinition"in r){let s=r,c=i,l=o();Y(a,s,l,{onInput:c?.onDefinitionInput,onOutput:c?.onDefinitionOutput}),s.provideTypeDefinition&&Z(a,s,l,{onInput:c?.onTypeDefinitionInput,onOutput:c?.onTypeDefinitionOutput});return}if("provideReferences"in r){let s=r,c=i;ee(a,s,o(),{onInput:c?.onReferencesInput,onOutput:c?.onReferencesOutput}),re(a,s,{onInput:c?.onFileReferencesInput,onOutput:c?.onFileReferencesOutput});return}if("provideCallHierarchy"in r){let s=i;te(a,r,o(),{onInput:s?.onCallHierarchyInput,onOutput:s?.onCallHierarchyOutput});return}if("provideDiagnostics"in r){ne(a,r,e);return}if("provideDocumentSymbols"in r){ie(a,r,e);return}if("globalFind"in r){let s=i;ae(a,r,{onInput:s?.onGlobalFindInput,onOutput:s?.onGlobalFindOutput});return}if("getLinkStructure"in r){let s=r,c=i;ue(a,s,{onOutput:c?.onLinkStructureOutput}),le(a,s,{onInput:c?.onAddLinkInput,onOutput:c?.onAddLinkOutput}),ce(a,s,e);return}if("getFrontmatterStructure"in r){let s=r,c=i;pe(a,s,{onInput:c?.onFrontmatterStructureInput,onOutput:c?.onFrontmatterStructureOutput}),de(a,s,{onInput:c?.onSetFrontmatterInput,onOutput:c?.onSetFrontmatterOutput}),me(a,s,e);return}}
|
|
8
|
+
`)}]}}catch(e){return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:`Error: ${e instanceof Error?e.message:String(e)}`}]}}});}i.onDiagnosticsChanged&&i.onDiagnosticsChanged(t=>{let e=m(t);a.server.sendResourceUpdated({uri:`diagnostics://${e}`}),i.getWorkspaceDiagnostics&&a.server.sendResourceUpdated({uri:"diagnostics://workspace"});});}function ie(a,i,n){let r=new ResourceTemplate("outline://{+path}",{list:void 0,complete:n?{path:n}:void 0});a.registerResource("outline",r,{description:"Document outline (symbols like classes, functions, variables) for a specific file. Use the file path after outline://",mimeType:"text/markdown"},async(t,e)=>{try{let o=e.path,s=m(o),c=await i.provideDocumentSymbols(s),l=A(c);return {contents:[{uri:`outline://${o}`,mimeType:"text/markdown",text:l}]}}catch(o){let s=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`outline://${e.path}`,mimeType:"text/markdown",text:s}]}}});}function oe(a,i,n,r){let t=i.applyEdits.bind(i);a.registerTool("apply_edit",{description:'Apply a text edit to a file. WORKFLOW: First read the file via the files:// resource to get hashline-formatted content (e.g., "3:a1| return x"). Then reference lines by their "line:hash" to specify the edit range. The hash verifies the file has not changed since your read \u2014 if it has, the edit is rejected and you must re-read the file. For single-line edits, only start_hash is needed. For multi-line edits, provide both start_hash and end_hash. The edit replaces the entire line range (inclusive) with replace_text. The edit must be approved by the user before being applied.',inputSchema:{uri:y.shape.uri,start_hash:y.shape.start_hash,end_hash:y.shape.end_hash,replace_text:y.shape.replace_text,description:y.shape.description}},async e=>{r?.onInput?.(e);try{let o=m(e.uri),s=_(e.start_hash),c=e.end_hash?_(e.end_hash):s,d=(await n(o)).split(/\r?\n/);if(s.line<1||s.line>d.length)throw new Error(`Start line ${s.line} is out of range (file has ${d.length} lines)`);if(c.line<s.line||c.line>d.length)throw new Error(`End line ${c.line} is out of range (file has ${d.length} lines)`);let h=d[s.line-1],P=R(h);if(P!==s.hash)throw new Error(`Hash mismatch at line ${s.line}: expected "${s.hash}", got "${P}". File has changed since last read.`);let T=d[c.line-1],F=R(T);if(F!==c.hash)throw new Error(`Hash mismatch at line ${c.line}: expected "${c.hash}", got "${F}". File has changed since last read.`);let E=d.slice(0,s.line-1),D=d.slice(c.line),w=[...E,e.replace_text,...D].join(`
|
|
9
|
+
`),S={id:C(),uri:o,updated:w,description:e.description},x=await t(S);return r?.onOutput?.(x),f(x)}catch(o){let s=`Error: ${o instanceof Error?o.message:String(o)}`;return {content:[{type:"text",text:s}],structuredContent:{success:false,message:s},isError:true}}});}function se(a,i){let{readFile:n,readDirectory:r}=i,t=new ResourceTemplate("files://{+path}",{list:void 0,complete:{path:G(r)}});a.registerResource("filesystem",t,{description:'Access filesystem resources. For directories: returns children as JSON (git-ignored files excluded). For files: returns content in hashline format where each line is prefixed with "<lineNumber>:<hash>|" (e.g., "1:a3|function hello() {"). The hash is a 2-char hex CRC16 digest of the line content. Use these line:hash references with the apply_edit tool to make edits. Supports line ranges with #L23 or #L23-L30 fragment. Supports regex filtering with ?pattern=<regex> query parameter (matches raw line text, not the hash prefix). Line numbers in the output are always the original file line numbers, even when filtering.'},async(e,o)=>{let s=e.toString();try{let c=o.path,l,d=c,h=c.indexOf("#");h!==-1&&(l=c.slice(h+1),d=c.slice(0,h));let{path:P,params:T}=X(d),{path:F,params:E}=X(l??"");l=l?F:void 0;let D=new URLSearchParams([...T.entries(),...E.entries()]),w=m(P),S=Se(l),x=D.get("pattern");try{let L=await n(w),b=M(L);if(S&&(b=b.filter(O=>O.num>=S.start&&O.num<=S.end)),x){let O=new RegExp(x);b=b.filter(fe=>O.test(fe.text));}return {contents:[{uri:s,mimeType:"text/plain",text:j(b)}]}}catch{let L=await r(w);return {contents:[{uri:s,mimeType:"application/json",text:JSON.stringify(L)}]}}}catch(c){let l=`Error: ${c instanceof Error?c.message:String(c)}`;return {contents:[{uri:s,mimeType:"text/plain",text:l}]}}}),i.onFileChanged&&i.onFileChanged(e=>{let o=m(e);a.server.sendResourceUpdated({uri:`files://${o}`});});}function ae(a,i,n){a.registerTool("global_find",{description:"Search for text across the entire workspace.",inputSchema:q,outputSchema:{matches:z$1.array(z$1.object({uri:z$1.string(),line:z$1.number(),column:z$1.number(),matchText:z$1.string(),context:z$1.string()})),count:z$1.number()}},async r=>{n?.onInput?.(r);try{let t=r.case_sensitive??!1,e=r.exact_match??!1,o=r.regex_mode??!1,s=await i.globalFind(r.query,{caseSensitive:t,exactMatch:e,regexMode:o});return n?.onOutput?.({count:s.length,matches:s}),f({count:s.length,matches:s})}catch(t){let e=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:e}],structuredContent:{error:e},isError:true}}});}function ce(a,i,n){let r=new ResourceTemplate("outlinks://{+path}",{list:void 0,complete:n?{path:n}:void 0});a.registerResource("outlinks",r,{description:"Outgoing links from a specific file. Use the file path after outlinks://",mimeType:"application/json"},async(e,o)=>{try{let s=o.path,c=m(s),l=await i.resolveOutlinks(c);return {contents:[{uri:`outlinks://${s}`,mimeType:"application/json",text:JSON.stringify(l,null,2)}]}}catch(s){let c=`Error: ${s instanceof Error?s.message:String(s)}`;return {contents:[{uri:`outlinks://${o.path}`,mimeType:"application/json",text:JSON.stringify({error:c})}]}}});let t=new ResourceTemplate("backlinks://{+path}",{list:void 0,complete:n?{path:n}:void 0});a.registerResource("backlinks",t,{description:"Incoming links (backlinks) to a specific file. Use the file path after backlinks://",mimeType:"application/json"},async(e,o)=>{try{let s=o.path,c=m(s),l=await i.resolveBacklinks(c);return {contents:[{uri:`backlinks://${s}`,mimeType:"application/json",text:JSON.stringify(l,null,2)}]}}catch(s){let c=`Error: ${s instanceof Error?s.message:String(s)}`;return {contents:[{uri:`backlinks://${o.path}`,mimeType:"application/json",text:JSON.stringify({error:c})}]}}});}function ue(a,i,n){a.registerTool("get_link_structure",{description:"Get all links in the workspace, showing relationships between documents.",inputSchema:{},outputSchema:{links:z$1.array(z$1.object({sourceUri:z$1.string(),targetUri:z$1.string(),subpath:z$1.string().optional(),displayText:z$1.string().optional(),resolved:z$1.boolean(),line:z$1.number(),column:z$1.number()}))}},async()=>{try{let r=await i.getLinkStructure();return n?.onOutput?.({links:r}),f({links:r})}catch(r){let t=`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:t}],structuredContent:{error:t},isError:true}}});}function le(a,i,n){a.registerTool("add_link",{description:"Add a link to a document by finding a text pattern and replacing it with a link to the target.",inputSchema:B,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async r=>{n?.onInput?.(r);try{let t=m(r.path),e=m(r.link_to);await i.addLink(t,r.pattern,e);let o={success:!0,message:"Link added successfully."};return n?.onOutput?.(o),f(o)}catch(t){let e=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:e}],structuredContent:{success:false,message:e},isError:true}}});}function pe(a,i,n){a.registerTool("get_frontmatter_structure",{description:"Get frontmatter property values across documents. If path is provided, searches only that document. Otherwise, searches all documents.",inputSchema:K,outputSchema:{matches:z$1.array(z$1.object({path:z$1.string(),value:z$1.unknown()}))}},async r=>{n?.onInput?.(r);try{let t=r.path?m(r.path):void 0,e=await i.getFrontmatterStructure(r.property,t);return n?.onOutput?.({matches:e}),f({matches:e})}catch(t){let e=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:e}],structuredContent:{error:e},isError:true}}});}function de(a,i,n){a.registerTool("set_frontmatter",{description:"Set a frontmatter property on a document. Use null to remove the property.",inputSchema:V,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async r=>{n?.onInput?.(r);try{let t=m(r.path),e=r.value===null?void 0:r.value;await i.setFrontmatter(t,r.property,e);let o={success:!0,message:"Frontmatter updated successfully."};return n?.onOutput?.(o),f(o)}catch(t){let e=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:e}],structuredContent:{success:false,message:e},isError:true}}});}function me(a,i,n){let r=new ResourceTemplate("frontmatter://{+path}",{list:void 0,complete:n?{path:n}:void 0});a.registerResource("frontmatter",r,{description:"Frontmatter metadata for a specific file. Use the file path after frontmatter://",mimeType:"application/json"},async(t,e)=>{try{let o=e.path,s=m(o),c=await i.getFrontmatter(s);return {contents:[{uri:`frontmatter://${o}`,mimeType:"application/json",text:JSON.stringify(c,null,2)}]}}catch(o){let s=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`frontmatter://${e.path}`,mimeType:"application/json",text:JSON.stringify({error:s})}]}}});}function xe(a){if(a.length<=0)throw new Error("providers array must not be empty");if(a.length===1&&a[0])return a[0];let i=a[0];if(!i)throw new Error("The first item of providers array must be defined");if("readFile"in i&&"readDirectory"in i){let n=a,r={readFile:t=>i.readFile(t),readDirectory:t=>i.readDirectory(t)};return n.some(t=>t.onFileChanged)&&(r.onFileChanged=t=>{for(let e of n)e.onFileChanged?.(t);}),r}if("applyEdits"in i)return i;if("provideDefinition"in i){let n=a,r={async provideDefinition(t,e){return (await Promise.all(n.map(s=>s.provideDefinition(t,e)))).flat()}};return n.some(t=>t.provideTypeDefinition)&&(r.provideTypeDefinition=async(t,e)=>{let o=n.filter(c=>c.provideTypeDefinition);return (await Promise.all(o.map(c=>c.provideTypeDefinition(t,e)))).flat()}),r}if("provideReferences"in i){let n=a,r={async provideReferences(t,e){return (await Promise.all(n.map(s=>s.provideReferences(t,e)))).flat()}};return n.some(t=>t.provideFileReferences)&&(r.provideFileReferences=async t=>{let e=n.filter(s=>s.provideFileReferences);return (await Promise.all(e.map(s=>s.provideFileReferences(t)))).flat()}),r}if("provideCallHierarchy"in i){let n=a;return {async provideCallHierarchy(r,t,e){return (await Promise.all(n.map(s=>s.provideCallHierarchy(r,t,e)))).flat()}}}if("provideDiagnostics"in i){let n=a,r={async provideDiagnostics(t){return (await Promise.all(n.map(o=>o.provideDiagnostics(t)))).flat()}};return n.some(t=>t.getWorkspaceDiagnostics)&&(r.getWorkspaceDiagnostics=async()=>{let t=n.filter(o=>o.getWorkspaceDiagnostics);return (await Promise.all(t.map(o=>o.getWorkspaceDiagnostics()))).flat()}),n.some(t=>t.onDiagnosticsChanged)&&(r.onDiagnosticsChanged=t=>{for(let e of n)e.onDiagnosticsChanged?.(t);}),r}if("provideDocumentSymbols"in i){let n=a;return {async provideDocumentSymbols(r){return (await Promise.all(n.map(e=>e.provideDocumentSymbols(r)))).flat()}}}if("globalFind"in i){let n=a;return {async globalFind(r,t){return (await Promise.all(n.map(o=>o.globalFind(r,t)))).flat()}}}if("getLinkStructure"in i){let n=a;return {async getLinkStructure(){return (await Promise.all(n.map(t=>t.getLinkStructure()))).flat()},async resolveOutlinks(r){return (await Promise.all(n.map(e=>e.resolveOutlinks(r)))).flat()},async resolveBacklinks(r){return (await Promise.all(n.map(e=>e.resolveBacklinks(r)))).flat()},async addLink(r,t,e){await Promise.all(n.map(o=>o.addLink(r,t,e)));}}}if("getFrontmatterStructure"in i){let n=a;return {async getFrontmatterStructure(r,t){return (await Promise.all(n.map(o=>o.getFrontmatterStructure(r,t)))).flat()},async getFrontmatter(r){let t=await Promise.all(n.map(e=>e.getFrontmatter(r)));return Object.assign({},...t)},async setFrontmatter(r,t,e){await Promise.all(n.map(o=>o.setFrontmatter(r,t,e)));}}}return i}function _e(a,i,n){let r=Array.isArray(i)?xe(i):i,t=n?.fileAccess,e=t?G(t.readDirectory):void 0,o=()=>{if(!t)throw new Error("fileAccess is required in options for providers that need symbol resolution");return new k(t,n?.resolverConfig)};if("readFile"in r&&"readDirectory"in r){se(a,r);return}if("applyEdits"in r){if(!t)throw new Error("fileAccess is required in options when installing an EditProvider");let s=n;oe(a,r,t.readFile,{onInput:s?.onEditInput,onOutput:s?.onEditOutput});return}if("provideDefinition"in r){let s=r,c=n,l=o();Y(a,s,l,{onInput:c?.onDefinitionInput,onOutput:c?.onDefinitionOutput}),s.provideTypeDefinition&&Z(a,s,l,{onInput:c?.onTypeDefinitionInput,onOutput:c?.onTypeDefinitionOutput});return}if("provideReferences"in r){let s=r,c=n;ee(a,s,o(),{onInput:c?.onReferencesInput,onOutput:c?.onReferencesOutput}),re(a,s,{onInput:c?.onFileReferencesInput,onOutput:c?.onFileReferencesOutput});return}if("provideCallHierarchy"in r){let s=n;te(a,r,o(),{onInput:s?.onCallHierarchyInput,onOutput:s?.onCallHierarchyOutput});return}if("provideDiagnostics"in r){ne(a,r,e);return}if("provideDocumentSymbols"in r){ie(a,r,e);return}if("globalFind"in r){let s=n;ae(a,r,{onInput:s?.onGlobalFindInput,onOutput:s?.onGlobalFindOutput});return}if("getLinkStructure"in r){let s=r,c=n;ue(a,s,{onOutput:c?.onLinkStructureOutput}),le(a,s,{onInput:c?.onAddLinkInput,onOutput:c?.onAddLinkOutput}),ce(a,s,e);return}if("getFrontmatterStructure"in r){let s=r,c=n;pe(a,s,{onInput:c?.onFrontmatterStructureInput,onOutput:c?.onFrontmatterStructureOutput}),de(a,s,{onInput:c?.onSetFrontmatterInput,onOutput:c?.onSetFrontmatterOutput}),me(a,s,e);return}}
|
|
9
10
|
export{_e as install};
|
package/dist/pipe/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
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-
|
|
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-DaNlFJZG.js';
|
|
2
2
|
|
|
3
3
|
interface connectPipeOptions {
|
|
4
4
|
pipeName: string;
|
|
5
5
|
connectTimeout?: number;
|
|
6
6
|
}
|
|
7
|
-
interface
|
|
7
|
+
interface PipeConnection {
|
|
8
8
|
readonly fileAccess?: FileAccessProvider;
|
|
9
9
|
readonly edit?: EditProvider;
|
|
10
10
|
readonly definition?: DefinitionProvider;
|
|
@@ -18,7 +18,7 @@ interface LspPipeConnection {
|
|
|
18
18
|
readonly availableMethods: string[];
|
|
19
19
|
disconnect(): void;
|
|
20
20
|
}
|
|
21
|
-
declare function connectPipe(options: connectPipeOptions): Promise<
|
|
21
|
+
declare function connectPipe(options: connectPipeOptions): Promise<PipeConnection>;
|
|
22
22
|
|
|
23
23
|
interface servePipeOptions {
|
|
24
24
|
pipeName: string;
|
|
@@ -33,11 +33,11 @@ interface servePipeOptions {
|
|
|
33
33
|
graph?: GraphProvider;
|
|
34
34
|
frontmatter?: FrontmatterProvider;
|
|
35
35
|
}
|
|
36
|
-
interface
|
|
36
|
+
interface PipeServer {
|
|
37
37
|
readonly pipePath: string;
|
|
38
38
|
readonly connectionCount: number;
|
|
39
39
|
close(): Promise<void>;
|
|
40
40
|
}
|
|
41
|
-
declare function servePipe(options: servePipeOptions): Promise<
|
|
41
|
+
declare function servePipe(options: servePipeOptions): Promise<PipeServer>;
|
|
42
42
|
|
|
43
|
-
export { type
|
|
43
|
+
export { type PipeConnection, type PipeServer, connectPipe, type connectPipeOptions, servePipe, type servePipeOptions };
|
package/dist/pipe/index.js
CHANGED
|
@@ -1,6 +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
|
|
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 t=this.nextId++;this.pending.set(t,{resolve:n,reject:f});let c={type:"request",id:t,method:e,params:r};this.socket.write(`${JSON.stringify(c)}
|
|
2
2
|
`);})}sendNotification(e,r){if(this.destroyed)return;let n={type:"notification",method:e,params:r};this.socket.write(`${JSON.stringify(n)}
|
|
3
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
|
|
4
|
+
`);this.buffer=r.pop()??"";for(let n of r){let f=n.replace(/\r$/,"");if(f)try{let t=JSON.parse(f);this.dispatch(t);}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
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"
|
|
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"]},{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,t)=>{let c=connect(n),i=false,d=setTimeout(()=>{i||(i=true,c.destroy(),t(new Error(`Connection timeout after ${r}ms`)));},r);c.on("error",o=>{i||(i=true,clearTimeout(d),t(o));}),c.on("connect",()=>{if(clearTimeout(d),i)return;let o,l,a=new v(c,{onNotification:(h,P)=>{h==="onDiagnosticsChanged"&&o&&o(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=>{o=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(),t(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 o=s[i];if(o)for(let l of d){let a=o[l];if(typeof a=="function"){let h=`${i}.${l}`;n.set(h,(...P)=>a.apply(o,P));}}}let f=[...n.keys()];s.diagnostics?.onDiagnosticsChanged&&f.push("onDiagnosticsChanged"),s.fileAccess.onFileChanged&&f.push("onFileChanged");let t=new Set,c=createServer(i=>{let d=new v(i,{onRequest:async(o,l)=>{if(o==="_handshake")return {methods:f};let a=n.get(o);if(!a)throw new Error(`Unknown method: ${o}`);return a(...l)}});t.add(d),i.on("close",()=>t.delete(d));});return s.diagnostics?.onDiagnosticsChanged&&s.diagnostics.onDiagnosticsChanged(i=>{for(let d of t)d.sendNotification("onDiagnosticsChanged",[i]);}),s.fileAccess.onFileChanged&&s.fileAccess.onFileChanged(i=>{for(let d of t)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 t.size},async close(){for(let o of t)o.destroy();if(t.clear(),await new Promise((o,l)=>{c.close(a=>{a?l(a):o();});}),process.platform!=="win32")try{unlinkSync(r);}catch{}}});});})}export{E as connectPipe,S as servePipe};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opticlm/connector",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
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",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"types": "./dist/mcp/index.d.ts",
|
|
18
18
|
"default": "./dist/mcp/index.js"
|
|
19
19
|
},
|
|
20
|
+
"./pipe": {
|
|
21
|
+
"types": "./dist/pipe/index.d.ts",
|
|
22
|
+
"default": "./dist/pipe/index.js"
|
|
23
|
+
},
|
|
20
24
|
"./schemas": {
|
|
21
25
|
"types": "./dist/schemas.d.ts",
|
|
22
26
|
"default": "./dist/schemas.js"
|