@likec4/language-server 1.52.0 → 1.54.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 +6 -0
- package/bin/likec4-language-server.mjs +1 -1
- package/dist/_chunks/LikeC4FileSystem.mjs +2 -2
- package/dist/_chunks/icons.d.mts +18 -0
- package/dist/_chunks/icons.mjs +2 -0
- package/dist/_chunks/mcp.mjs +15 -15
- package/dist/_chunks/module.d.mts +80 -9
- package/dist/_chunks/module.mjs +20 -20
- package/dist/_chunks/noop.mjs +1 -1
- package/dist/_chunks/noop2.mjs +1 -0
- package/dist/_chunks/protocol.d.mts +10 -3
- package/dist/_chunks/utils.mjs +1 -1
- package/dist/browser/index.mjs +1 -1
- package/dist/browser/worker.mjs +1 -1
- package/dist/filesystem/index.mjs +1 -1
- package/dist/icons.d.mts +2 -0
- package/dist/icons.mjs +1 -0
- package/dist/index.mjs +1 -1
- package/dist/likec4lib.d.mts +1 -3
- package/dist/likec4lib.mjs +1 -1
- package/dist/mcp/index.mjs +1 -1
- package/dist/module.mjs +1 -1
- package/icons/package.json +4 -0
- package/package.json +33 -23
- package/dist/_chunks/likec4lib.mjs +0 -2
- package/dist/_chunks/workspace.mjs +0 -1
package/dist/_chunks/mcp.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{l as e,oi as t}from"./utils.mjs";import{ifilter as n,invariant as r,isSameHierarchy as i}from"@likec4/core/utils";import{loggable as a}from"@likec4/log";import{invariant as o}from"@likec4/core";import{keys as s}from"remeda";import{URI as c}from"vscode-uri";import{isDeploymentNodeModel as l,modelConnection as u}from"@likec4/core/model";import{McpServer as d}from"@modelcontextprotocol/sdk/server/mcp.js";import*as f from"zod/v3";import{StdioServerTransport as p}from"@modelcontextprotocol/sdk/server/stdio.js";import{MemoryEventStore as m,StreamableHTTPTransport as h}from"@hono/mcp";import{serve as g}from"@hono/node-server";import{Hono as _}from"hono";import{cors as v}from"hono/cors";const y=t.getChild(`mcp`);function likec4Tool(e,t){let{name:n,description:r,...i}=e;return e=>[n,{description:r?.trim()??``,...i},mkcallTool(n,e,t)]}function mkcallTool(e,t,n){let r=n.bind(null,t);return(async function(t,n){y.debug(`Calling tool {name}, args: {args}`,{name:e,args:t});try{let e=await r.call(null,t,n);return typeof e==`string`?{content:[{type:`text`,text:e}]}:{content:[{type:`text`,text:JSON.stringify(e)}],structuredContent:e}}catch(t){return y.error(`Tool ${e} failed`,{err:t}),{content:[{type:`text`,text:a(t)}],isError:!0}}})}var b=`1.54.0`;const x=f.object({name:f.string().describe(`Project identifier`),title:f.string().optional().describe(`Human-readable project title`),contactPerson:f.string().optional().describe(`Maintainer contact information`),metadata:f.record(f.string(),f.unknown()).optional().describe(`Custom project metadata as key-value pairs`),extends:f.union([f.string(),f.array(f.string())]).optional().describe(`Style inheritance paths`),exclude:f.array(f.string()).optional().describe(`File exclusion patterns`),include:f.object({paths:f.array(f.string()).describe(`Include paths`),maxDepth:f.number().describe(`Maximum directory depth`),fileThreshold:f.number().describe(`File threshold`)}).optional().describe(`Include configuration`),manualLayouts:f.object({outDir:f.string().describe(`Output directory for manual layouts`)}).optional().describe(`Manual layouts configuration`),styles:f.object({hasTheme:f.boolean().describe(`Whether theme customization is defined`),hasDefaults:f.boolean().describe(`Whether default style values are defined`),hasCustomCss:f.boolean().describe(`Whether custom CSS is defined`)}).optional().describe(`Simplified styles configuration (boolean flags)`)});function serializeConfig(e){let t={name:e.name};return e.title!=null&&(t.title=e.title),e.contactPerson!=null&&(t.contactPerson=e.contactPerson),e.metadata&&(t.metadata=e.metadata),e.extends&&(t.extends=e.extends),e.exclude&&(t.exclude=e.exclude),e.include&&(t.include={paths:e.include.paths||[],maxDepth:e.include.maxDepth??3,fileThreshold:e.include.fileThreshold??30}),e.manualLayouts&&(t.manualLayouts={outDir:e.manualLayouts.outDir??`.likec4`}),e.styles&&(t.styles={hasTheme:!!e.styles.theme,hasDefaults:!!e.styles.defaults,hasCustomCss:!!e.styles.customCss}),t}const S=f.object({id:f.string().describe(`Element id (FQN)`),name:f.string().describe(`Element name`),kind:f.string().describe(`Element kind`),title:f.string(),tags:f.array(f.string()),metadata:f.record(f.union([f.string(),f.array(f.string())])),includedInViews:f.array(f.object({id:f.string().describe(`View id`),title:f.string().describe(`View title`),type:f.enum([`element`,`deployment`,`dynamic`]).describe(`View type`)})).describe(`Views that include this element`)});function serializeElement(e){return{id:e.id,name:e.name,kind:e.kind,title:e.title,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:includedInViews(e.views())}}function traverseGraph(e,t,n,r,i,a){o(e.findElement(t),`Element "${t}" not found`);let s=new Set,c={},l=0,u=!1,d=[{elementId:t,depth:0}];for(;d.length>0;){let{elementId:t,depth:o}=d.shift();if(o>i||s.has(t))continue;if(s.size>=a){u=!0;break}let f=e.findElement(t);if(!f)continue;s.add(t),l=Math.max(l,o);let p=(n===`incoming`?[...f.incoming(r)]:[...f.outgoing(r)]).map(e=>{let t={elementId:n===`incoming`?e.source.id:e.target.id};return e.title&&(t.relationshipLabel=e.title),e.technology&&(t.technology=e.technology),t});c[t]={...serializeElement(f),neighbors:p,depth:o};for(let e of p)s.has(e.elementId)||d.push({elementId:e.elementId,depth:o+1})}for(let e of Object.values(c))e.neighbors=e.neighbors.filter(e=>e.elementId in c);return{target:t,totalNodes:s.size,maxDepth:l,truncated:u,nodes:c}}const C=f.object({path:f.string().describe(`Path to the file`),range:f.object({start:f.object({line:f.number(),character:f.number()}),end:f.object({line:f.number(),character:f.number()})}).describe(`Range in the file`)}).nullable(),w=f.string().refine(e=>!0).optional().default(e.DefaultProjectId).describe(`Project id (optional, will use "default" if not specified)`),T=f.array(f.object({id:f.string().describe(`View id`),title:f.string().describe(`View title`),type:f.enum([`element`,`deployment`,`dynamic`]).describe(`View type`)})),includedInViews=e=>[...e].map(e=>({id:e.id,title:e.titleOrId,type:e.$view._type})),mkLocate=(e,t)=>n=>{try{let r=e.locate({projectId:t,...n});return r?{path:c.parse(r.uri).fsPath,range:r.range}:null}catch(e){return y.debug(`Failed to locate {params}`,{error:e,params:n}),null}},E=S.extend({description:f.string().nullable().describe(`Element description`),technology:f.string().nullable().describe(`Element technology`),shape:f.string().describe(`Rendered shape`),color:f.string().describe(`Rendered color`),children:f.array(f.string()).describe(`Direct child element ids`),incomingCount:f.number().describe(`Number of incoming relationships`),outgoingCount:f.number().describe(`Number of outgoing relationships`)}),D=likec4Tool({name:`batch-read-elements`,description:`
|
|
2
2
|
Read details of multiple elements in a single call, reducing round-trips.
|
|
3
3
|
Returns a compact summary for each element including metadata, description, technology, shape, children, and relationship counts.
|
|
4
4
|
|
|
@@ -60,7 +60,7 @@ Example response:
|
|
|
60
60
|
],
|
|
61
61
|
"notFound": []
|
|
62
62
|
}
|
|
63
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Batch read elements`},inputSchema:{ids:f.array(f.string()).min(1).max(50).describe(`Array of element ids (FQNs) to read (max 50)`),project:w},outputSchema:{elements:f.array(E),notFound:f.array(f.string()).describe(`Element ids that were not found`)}},async(e,t)=>{
|
|
63
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Batch read elements`},inputSchema:{ids:f.array(f.string()).min(1).max(50).describe(`Array of element ids (FQNs) to read (max 50)`),project:w},outputSchema:{elements:f.array(E),notFound:f.array(f.string()).describe(`Element ids that were not found`)}},async(e,t)=>{o(t.ids.length<=50,`Maximum 50 element ids per call`);let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=[],a=[];for(let e of t.ids){let t=r.findElement(e);if(!t){a.push(e);continue}i.push({...serializeElement(t),description:t.description.text,technology:t.technology,shape:t.shape,color:t.color,children:[...t.children()].map(e=>e.id),incomingCount:t.allIncoming.size,outgoingCount:t.allOutgoing.size})}return{elements:i,notFound:a}}),O=f.object({id:f.string(),kind:f.string(),title:f.string(),description:f.string().nullable(),technology:f.string().nullable(),shape:f.string(),color:f.string()}),k=f.object({element1:O,element2:O,propertyDiffs:f.array(f.object({property:f.string().describe(`Property name`),element1Value:f.string().nullable().describe(`Value in element1`),element2Value:f.string().nullable().describe(`Value in element2`)})).describe(`Properties that differ between the two elements`),tags:f.object({onlyInElement1:f.array(f.string()).describe(`Tags present only in element1`),onlyInElement2:f.array(f.string()).describe(`Tags present only in element2`),common:f.array(f.string()).describe(`Tags present in both elements`)}),metadata:f.object({onlyInElement1:f.record(f.union([f.string(),f.array(f.string())])).describe(`Metadata keys only in element1`),onlyInElement2:f.record(f.union([f.string(),f.array(f.string())])).describe(`Metadata keys only in element2`),different:f.array(f.object({key:f.string(),element1Value:f.union([f.string(),f.array(f.string())]),element2Value:f.union([f.string(),f.array(f.string())])})).describe(`Metadata keys present in both but with different values`),common:f.record(f.union([f.string(),f.array(f.string())])).describe(`Metadata keys with identical values in both`)}),relationships:f.object({incomingOnlyElement1:f.number().describe(`Count of unique source elements sending to element1 only`),incomingOnlyElement2:f.number().describe(`Count of unique source elements sending to element2 only`),incomingShared:f.number().describe(`Count of unique source elements sending to both`),outgoingOnlyElement1:f.number().describe(`Count of unique target elements receiving from element1 only`),outgoingOnlyElement2:f.number().describe(`Count of unique target elements receiving from element2 only`),outgoingShared:f.number().describe(`Count of unique target elements receiving from both`)})}),A=likec4Tool({name:`element-diff`,description:`
|
|
64
64
|
Compare two elements side-by-side, showing differences in properties, tags, metadata, and relationships.
|
|
65
65
|
|
|
66
66
|
Request:
|
|
@@ -120,7 +120,7 @@ Example response:
|
|
|
120
120
|
"outgoingShared": 2
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Compare two elements`},inputSchema:{element1Id:f.string().describe(`First element id (FQN)`),element2Id:f.string().describe(`Second element id (FQN)`),project:w},outputSchema:k.shape},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=r.findElement(t.element1Id);
|
|
123
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Compare two elements`},inputSchema:{element1Id:f.string().describe(`First element id (FQN)`),element2Id:f.string().describe(`Second element id (FQN)`),project:w},outputSchema:k.shape},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=r.findElement(t.element1Id);o(i,`Element "${t.element1Id}" not found in project "${n}"`);let a=r.findElement(t.element2Id);o(a,`Element "${t.element2Id}" not found in project "${n}"`);let s=[],c=[{name:`kind`,get:e=>e.kind},{name:`title`,get:e=>e.title},{name:`description`,get:e=>e.description.text},{name:`technology`,get:e=>e.technology},{name:`shape`,get:e=>e.shape},{name:`color`,get:e=>e.color}];for(let e of c){let t=e.get(i),n=e.get(a);t!==n&&s.push({property:e.name,element1Value:t,element2Value:n})}let l=new Set(i.tags),u=new Set(a.tags),d=[],f=[],p=[];for(let e of l)u.has(e)?d.push(e):f.push(e);for(let e of u)l.has(e)||p.push(e);let m=i.getMetadata(),h=a.getMetadata(),g=new Set([...Object.keys(m),...Object.keys(h)]),_={},v={},y=[],b={};for(let e of g){let t=m[e],n=h[e];t!==void 0&&n===void 0?_[e]=t:t===void 0&&n!==void 0?v[e]=n:t!==void 0&&n!==void 0&&(JSON.stringify(t)===JSON.stringify(n)?b[e]=t:y.push({key:e,element1Value:t,element2Value:n}))}let x=new Set([...i.incoming()].map(e=>e.source.id)),S=new Set([...a.incoming()].map(e=>e.source.id)),C=new Set([...i.outgoing()].map(e=>e.target.id)),w=new Set([...a.outgoing()].map(e=>e.target.id)),T=0,E=0,D=0;for(let e of x)S.has(e)?T++:E++;for(let e of S)x.has(e)||D++;let O=0,k=0,A=0;for(let e of C)w.has(e)?O++:k++;for(let e of w)C.has(e)||A++;return{element1:{id:i.id,kind:i.kind,title:i.title,description:i.description.text,technology:i.technology,shape:i.shape,color:i.color},element2:{id:a.id,kind:a.kind,title:a.title,description:a.description.text,technology:a.technology,shape:a.shape,color:a.color},propertyDiffs:s,tags:{onlyInElement1:f,onlyInElement2:p,common:d},metadata:{onlyInElement1:_,onlyInElement2:v,different:y,common:b},relationships:{incomingOnlyElement1:E,incomingOnlyElement2:D,incomingShared:T,outgoingOnlyElement1:k,outgoingOnlyElement2:A,outgoingShared:O}}}),j=likec4Tool({name:`find-relationship-paths`,description:`
|
|
124
124
|
Discover all paths (chains of relationships) between two elements, supporting multi-hop traversal.
|
|
125
125
|
|
|
126
126
|
Request:
|
|
@@ -209,7 +209,7 @@ Example response:
|
|
|
209
209
|
}
|
|
210
210
|
]
|
|
211
211
|
}
|
|
212
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Find relationship paths`},inputSchema:{sourceId:f.string().describe(`Source element FQN`),targetId:f.string().describe(`Target element FQN`),maxDepth:f.number().int().min(1).max(5).optional().default(3).describe(`Maximum path length (default: 3, max: 5)`),includeIndirect:f.boolean().optional().default(!1).describe(`Include indirect (implied) relationships through nested elements (default: false)`),project:w},outputSchema:{paths:f.array(f.object({length:f.number().describe(`Number of hops in the path`),steps:f.array(f.object({source:f.string().describe(`Source element FQN`),target:f.string().describe(`Target element FQN`),relationship:f.object({kind:f.string().nullable().describe(`Relationship kind`),title:f.string().nullable().describe(`Relationship title`),description:f.string().nullable().describe(`Relationship description`),technology:f.string().nullable().describe(`Relationship technology`),tags:f.array(f.string()).describe(`Relationship tags`)})})).describe(`Ordered sequence of relationships in the path`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=r.findElement(t.sourceId);
|
|
212
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Find relationship paths`},inputSchema:{sourceId:f.string().describe(`Source element FQN`),targetId:f.string().describe(`Target element FQN`),maxDepth:f.number().int().min(1).max(5).optional().default(3).describe(`Maximum path length (default: 3, max: 5)`),includeIndirect:f.boolean().optional().default(!1).describe(`Include indirect (implied) relationships through nested elements (default: false)`),project:w},outputSchema:{paths:f.array(f.object({length:f.number().describe(`Number of hops in the path`),steps:f.array(f.object({source:f.string().describe(`Source element FQN`),target:f.string().describe(`Target element FQN`),relationship:f.object({kind:f.string().nullable().describe(`Relationship kind`),title:f.string().nullable().describe(`Relationship title`),description:f.string().nullable().describe(`Relationship description`),technology:f.string().nullable().describe(`Relationship technology`),tags:f.array(f.string()).describe(`Relationship tags`)})})).describe(`Ordered sequence of relationships in the path`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=r.findElement(t.sourceId);o(i,`Source element "${t.sourceId}" not found in project "${n}"`);let a=r.findElement(t.targetId);o(a,`Target element "${t.targetId}" not found in project "${n}"`),o(i.id!==a.id,`Source and target must be different elements`);let s=t.maxDepth,c=t.includeIndirect?`all`:`direct`,l=[{elementId:i.id,path:[],visited:new Set([i.id])}],u=[];for(;l.length>0&&u.length<100;){let e=l.shift();if(e.path.length>=s)continue;let t=r.findElement(e.elementId);if(t)for(let n of t.outgoing(c)){let t=n.target.id;if(t===a.id){let t={source:n.source.id,target:n.target.id,relationship:{kind:n.kind,title:n.title,description:n.description.text,technology:n.technology,tags:[...n.tags]}};if(u.push({length:e.path.length+1,steps:[...e.path,t]}),u.length>=100)break;continue}if(e.visited.has(t))continue;let r={source:n.source.id,target:n.target.id,relationship:{kind:n.kind,title:n.title,description:n.description.text,technology:n.technology,tags:[...n.tags]}};l.push({elementId:t,path:[...e.path,r],visited:new Set([...e.visited,t])})}}return u.sort((e,t)=>e.length-t.length),{paths:u}}),M=f.object({id:f.string(),title:f.string(),kind:f.string()}),N=f.object({type:f.enum([`direct`,`indirect`]).describe(`Type of relationship, "direct" for direct relationships, "indirect" for relationships through nested elements`),source:M,target:M,kind:f.string().nullable().describe(`Relationship kind`),title:f.string().nullable().describe(`Relationship title`),description:f.string().nullable().describe(`Relationship description`),technology:f.string().nullable().describe(`Relationship technology`),tags:f.array(f.string()).describe(`Relationship tags`),includedInViews:T.describe(`Views that include this relationship`),sourceLocation:C}),P=likec4Tool({name:`find-relationships`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Find relationships between two elements`},description:`
|
|
213
213
|
Find relationships between two LikeC4 elements within a project.
|
|
214
214
|
|
|
215
215
|
What it does:
|
|
@@ -280,7 +280,7 @@ Response:
|
|
|
280
280
|
}
|
|
281
281
|
]
|
|
282
282
|
}
|
|
283
|
-
`,inputSchema:{element1:f.string().describe(`Element ID (FQN)`),element2:f.string().describe(`Element ID (FQN)`),project:w},outputSchema:{found:f.array(N)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project);if(i(t.element1,t.element2))throw Error(`No relationships possible between parent-child`);let a=[],o=await e.computedModel(n),s=o.findElement(t.element1);r(s,`Element "${t.element1}" not found in project "${n}"`);let c=o.findElement(t.element2);r(c,`Element "${t.element2}" not found in project "${n}"`);let
|
|
283
|
+
`,inputSchema:{element1:f.string().describe(`Element ID (FQN)`),element2:f.string().describe(`Element ID (FQN)`),project:w},outputSchema:{found:f.array(N)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project);if(i(t.element1,t.element2))throw Error(`No relationships possible between parent-child`);let a=[],o=await e.computedModel(n),s=o.findElement(t.element1);r(s,`Element "${t.element1}" not found in project "${n}"`);let c=o.findElement(t.element2);r(c,`Element "${t.element2}" not found in project "${n}"`);let l=mkLocate(e,n),d=u.findConnection(s,c,`both`).flatMap(e=>[...e.relations]);for(let e of d){let t=e.source===s&&e.target===c||e.source===c&&e.target===s;a.push({type:t?`direct`:`indirect`,source:{id:e.source.id,title:e.source.title,kind:e.source.kind},target:{id:e.target.id,title:e.target.title,kind:e.target.kind},kind:e.kind,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags],includedInViews:includedInViews(e.views()),sourceLocation:l({relation:e.id})})}return{found:a}}),F=likec4Tool({name:`list-projects`,description:`
|
|
284
284
|
List LikeC4 projects discoverable in the current workspace.
|
|
285
285
|
|
|
286
286
|
Request:
|
|
@@ -455,7 +455,7 @@ Example response:
|
|
|
455
455
|
"truncated": false,
|
|
456
456
|
"matchedTagValues": ["target_asil_qm", "target_asil_asil_b", "target_asil_qm__tbc"]
|
|
457
457
|
}
|
|
458
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by tag pattern`},inputSchema:{pattern:f.string().min(1).describe(`Tag pattern to match`),matchMode:f.enum([`prefix`,`contains`,`suffix`]).optional().default(`prefix`).describe(`Pattern matching mode (default: prefix)`),project:w},outputSchema:{results:f.array(S.extend({matchedTags:f.array(f.string()).describe(`Tags that matched the pattern`)})),truncated:f.boolean().describe(`True if results were truncated`),matchedTagValues:f.array(f.string()).describe(`All unique tag values matching the pattern across all elements`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=t.pattern.toLowerCase(),matchesTag=e=>{let n=e.toLowerCase();switch(t.matchMode){case`prefix`:return n.startsWith(i);case`contains`:return n.includes(i);case`suffix`:return n.endsWith(i)}},a=[],o=!1,s=new Set;for(let e of r.elements()){let t=[...e.tags].filter(matchesTag);if(t.length>0){if(t.forEach(e=>s.add(e)),a.length>=50){o=!0;continue}a.push({...serializeElement(e),matchedTags:t})}}for(let e of r.deployment.elements()){if(!
|
|
458
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by tag pattern`},inputSchema:{pattern:f.string().min(1).describe(`Tag pattern to match`),matchMode:f.enum([`prefix`,`contains`,`suffix`]).optional().default(`prefix`).describe(`Pattern matching mode (default: prefix)`),project:w},outputSchema:{results:f.array(S.extend({matchedTags:f.array(f.string()).describe(`Tags that matched the pattern`)})),truncated:f.boolean().describe(`True if results were truncated`),matchedTagValues:f.array(f.string()).describe(`All unique tag values matching the pattern across all elements`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=t.pattern.toLowerCase(),matchesTag=e=>{let n=e.toLowerCase();switch(t.matchMode){case`prefix`:return n.startsWith(i);case`contains`:return n.includes(i);case`suffix`:return n.endsWith(i)}},a=[],o=!1,s=new Set;for(let e of r.elements()){let t=[...e.tags].filter(matchesTag);if(t.length>0){if(t.forEach(e=>s.add(e)),a.length>=50){o=!0;continue}a.push({...serializeElement(e),matchedTags:t})}}for(let e of r.deployment.elements()){if(!l(e))continue;let t=[...e.tags].filter(matchesTag);if(t.length>0){if(t.forEach(e=>s.add(e)),a.length>=50){o=!0;continue}a.push({...serializeElement(e),matchedTags:t})}}return{results:a,truncated:o,matchedTagValues:[...s].sort((e,t)=>e.localeCompare(t))}}),B=likec4Tool({name:`query-by-tags`,description:`
|
|
459
459
|
Advanced tag filtering with boolean logic (AND, OR, NOT).
|
|
460
460
|
|
|
461
461
|
Request:
|
|
@@ -519,7 +519,7 @@ Example response:
|
|
|
519
519
|
}
|
|
520
520
|
]
|
|
521
521
|
}
|
|
522
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by tags`},inputSchema:{allOf:f.array(f.string()).optional().describe(`Element must have ALL these tags (AND)`),anyOf:f.array(f.string()).optional().describe(`Element must have ANY of these tags (OR)`),noneOf:f.array(f.string()).optional().describe(`Element must have NONE of these tags (NOT)`),project:w},outputSchema:{results:f.array(S),truncated:f.boolean().describe(`True if results were truncated due to exceeding the 50-result limit`)}},async(e,t)=>{
|
|
522
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query by tags`},inputSchema:{allOf:f.array(f.string()).optional().describe(`Element must have ALL these tags (AND)`),anyOf:f.array(f.string()).optional().describe(`Element must have ANY of these tags (OR)`),noneOf:f.array(f.string()).optional().describe(`Element must have NONE of these tags (NOT)`),project:w},outputSchema:{results:f.array(S),truncated:f.boolean().describe(`True if results were truncated due to exceeding the 50-result limit`)}},async(e,t)=>{o(t.allOf&&t.allOf.length>0||t.anyOf&&t.anyOf.length>0||t.noneOf&&t.noneOf.length>0,`At least one condition (allOf, anyOf, or noneOf) must be specified with at least one tag`);let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n),i=[],a=!1,matchesTags=e=>{let n=e instanceof Set?e:new Set(e);return!(t.allOf&&t.allOf.length>0&&!t.allOf.every(e=>n.has(e))||t.anyOf&&t.anyOf.length>0&&!t.anyOf.some(e=>n.has(e))||t.noneOf&&t.noneOf.length>0&&t.noneOf.some(e=>n.has(e)))};for(let e of r.elements()){if(i.length>=50){a=!0;break}matchesTags(e.tags)&&i.push(serializeElement(e))}if(!a)for(let e of r.deployment.elements()){if(i.length>=50){a=!0;break}l(e)&&matchesTags(e.tags)&&i.push(serializeElement(e))}return{results:i,truncated:a}}),V=f.enum([`ancestors`,`descendants`,`siblings`,`children`,`parent`,`incomers`,`outgoers`]),H=likec4Tool({name:`query-graph`,description:`
|
|
523
523
|
Query element hierarchy and relationships in the architecture graph.
|
|
524
524
|
|
|
525
525
|
Request:
|
|
@@ -591,7 +591,7 @@ Example response:
|
|
|
591
591
|
],
|
|
592
592
|
"truncated": false
|
|
593
593
|
}
|
|
594
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query element graph`},inputSchema:{elementId:f.string().describe(`Element id (FQN) to query`),queryType:V.describe(`Type of graph query`),includeIndirect:f.boolean().optional().default(!0).describe(`For incomers/outgoers: include indirect relationships (default: true)`),project:w},outputSchema:{results:f.array(S),truncated:f.boolean().describe(`True if results were truncated due to exceeding maximum limit`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.elementId);
|
|
594
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query element graph`},inputSchema:{elementId:f.string().describe(`Element id (FQN) to query`),queryType:V.describe(`Type of graph query`),includeIndirect:f.boolean().optional().default(!0).describe(`For incomers/outgoers: include indirect relationships (default: true)`),project:w},outputSchema:{results:f.array(S),truncated:f.boolean().describe(`True if results were truncated due to exceeding maximum limit`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.elementId);o(r,`Element "${t.elementId}" not found in project "${n}"`);let i=[],a=!1;switch(t.queryType){case`ancestors`:for(let e of r.ancestors()){if(i.length>=100){a=!0;break}i.push(serializeElement(e))}break;case`descendants`:for(let e of r.descendants()){if(i.length>=100){a=!0;break}i.push(serializeElement(e))}break;case`siblings`:for(let e of r.siblings()){if(i.length>=100){a=!0;break}i.push(serializeElement(e))}break;case`children`:for(let e of r.children()){if(i.length>=100){a=!0;break}i.push(serializeElement(e))}break;case`parent`:{let e=r.parent;e&&i.push(serializeElement(e));break}case`incomers`:{let e=t.includeIndirect?`all`:`direct`;for(let t of r.incomers(e)){if(i.length>=100){a=!0;break}i.push(serializeElement(t))}break}case`outgoers`:{let e=t.includeIndirect?`all`:`direct`;for(let t of r.outgoers(e)){if(i.length>=100){a=!0;break}i.push(serializeElement(t))}break}}return{results:i,truncated:a}}),U=f.object({elementId:f.string().describe(`ID of the incoming element`),relationshipLabel:f.string().optional().describe(`Label on the relationship`),technology:f.string().optional().describe(`Technology specified on the relationship`)}),W=likec4Tool({name:`query-incomers-graph`,description:`
|
|
595
595
|
Query the complete graph of all elements that provide input to the target element (recursive incomers/producers).
|
|
596
596
|
|
|
597
597
|
This tool performs a breadth-first traversal to discover all upstream dependencies - elements that directly or
|
|
@@ -648,7 +648,7 @@ Notes:
|
|
|
648
648
|
Example:
|
|
649
649
|
For a database element, this returns all services, APIs, and components that write to it,
|
|
650
650
|
plus all their dependencies, recursively up to maxDepth levels.
|
|
651
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query complete incomers graph`},inputSchema:{elementId:f.string().describe(`Target element id (FQN) to query incomers for`),includeIndirect:f.boolean().optional().default(!0).describe(`Include indirect relationships through nested elements (default: true)`),maxDepth:f.number().int().positive().max(50).optional().default(10).describe(`Maximum traversal depth (default: 10, max: 50)`),maxNodes:f.number().int().positive().max(2e3).optional().default(200).describe(`Maximum number of nodes to return (default: 200, max: 2000)`),project:w},outputSchema:{target:f.string().describe(`Target element id`),totalNodes:f.number().describe(`Total number of nodes in the graph`),maxDepth:f.number().describe(`Maximum depth reached`),truncated:f.boolean().describe(`True if result was truncated due to maxNodes limit`),nodes:f.record(S.extend({incomers:f.array(U).describe(`Incoming relationships with details`),depth:f.number().describe(`Distance from target element (0 = target)`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n);
|
|
651
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query complete incomers graph`},inputSchema:{elementId:f.string().describe(`Target element id (FQN) to query incomers for`),includeIndirect:f.boolean().optional().default(!0).describe(`Include indirect relationships through nested elements (default: true)`),maxDepth:f.number().int().positive().max(50).optional().default(10).describe(`Maximum traversal depth (default: 10, max: 50)`),maxNodes:f.number().int().positive().max(2e3).optional().default(200).describe(`Maximum number of nodes to return (default: 200, max: 2000)`),project:w},outputSchema:{target:f.string().describe(`Target element id`),totalNodes:f.number().describe(`Total number of nodes in the graph`),maxDepth:f.number().describe(`Maximum depth reached`),truncated:f.boolean().describe(`True if result was truncated due to maxNodes limit`),nodes:f.record(S.extend({incomers:f.array(U).describe(`Incoming relationships with details`),depth:f.number().describe(`Distance from target element (0 = target)`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n);o(r.findElement(t.elementId),`Element "${t.elementId}" not found in project "${n}"`);let i=t.includeIndirect?`all`:`direct`,a=traverseGraph(r,t.elementId,`incoming`,i,t.maxDepth,t.maxNodes),s={};for(let[e,t]of Object.entries(a.nodes)){let{neighbors:n,...r}=t;s[e]={...r,incomers:n}}return{target:a.target,totalNodes:a.totalNodes,maxDepth:a.maxDepth,truncated:a.truncated,nodes:s}}),G=f.object({elementId:f.string().describe(`ID of the outgoing element`),relationshipLabel:f.string().optional().describe(`Label on the relationship`),technology:f.string().optional().describe(`Technology specified on the relationship`)}),K=likec4Tool({name:`query-outgoers-graph`,description:`
|
|
652
652
|
Query the complete graph of all elements that receive output from the target element (recursive outgoers/consumers).
|
|
653
653
|
|
|
654
654
|
This tool performs a breadth-first traversal to discover all downstream dependencies - elements that directly or
|
|
@@ -705,7 +705,7 @@ Notes:
|
|
|
705
705
|
Example:
|
|
706
706
|
For an API service, this returns all clients, services, and systems that consume its output,
|
|
707
707
|
plus all their consumers, recursively up to maxDepth levels.
|
|
708
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query complete outgoers graph`},inputSchema:{elementId:f.string().describe(`Target element id (FQN) to query outgoers for`),includeIndirect:f.boolean().optional().default(!0).describe(`Include indirect relationships through nested elements (default: true)`),maxDepth:f.number().int().positive().max(50).optional().default(10).describe(`Maximum traversal depth (default: 10, max: 50)`),maxNodes:f.number().int().positive().max(2e3).optional().default(200).describe(`Maximum number of nodes to return (default: 200, max: 2000)`),project:w},outputSchema:{target:f.string().describe(`Target element id`),totalNodes:f.number().describe(`Total number of nodes in the graph`),maxDepth:f.number().describe(`Maximum depth reached`),truncated:f.boolean().describe(`True if result was truncated due to maxNodes limit`),nodes:f.record(S.extend({outgoers:f.array(G).describe(`Outgoing relationships with details`),depth:f.number().describe(`Distance from target element (0 = target)`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n);
|
|
708
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Query complete outgoers graph`},inputSchema:{elementId:f.string().describe(`Target element id (FQN) to query outgoers for`),includeIndirect:f.boolean().optional().default(!0).describe(`Include indirect relationships through nested elements (default: true)`),maxDepth:f.number().int().positive().max(50).optional().default(10).describe(`Maximum traversal depth (default: 10, max: 50)`),maxNodes:f.number().int().positive().max(2e3).optional().default(200).describe(`Maximum number of nodes to return (default: 200, max: 2000)`),project:w},outputSchema:{target:f.string().describe(`Target element id`),totalNodes:f.number().describe(`Total number of nodes in the graph`),maxDepth:f.number().describe(`Maximum depth reached`),truncated:f.boolean().describe(`True if result was truncated due to maxNodes limit`),nodes:f.record(S.extend({outgoers:f.array(G).describe(`Outgoing relationships with details`),depth:f.number().describe(`Distance from target element (0 = target)`)}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=await e.computedModel(n);o(r.findElement(t.elementId),`Element "${t.elementId}" not found in project "${n}"`);let i=t.includeIndirect?`all`:`direct`,a=traverseGraph(r,t.elementId,`outgoing`,i,t.maxDepth,t.maxNodes),s={};for(let[e,t]of Object.entries(a.nodes)){let{neighbors:n,...r}=t;s[e]={...r,outgoers:n}}return{target:a.target,totalNodes:a.totalNodes,maxDepth:a.maxDepth,truncated:a.truncated,nodes:s}}),q=likec4Tool({name:`read-deployment`,description:`
|
|
709
709
|
Read details about a deployment node or a deployed instance in a LikeC4 project.
|
|
710
710
|
|
|
711
711
|
What it does:
|
|
@@ -770,7 +770,7 @@ Example response (deployed instance):
|
|
|
770
770
|
"range": { "start": { "line": 10, "character": 0 }, "end": { "line": 25, "character": 0 } }
|
|
771
771
|
}
|
|
772
772
|
}
|
|
773
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read deployment entity`},inputSchema:{id:f.string().describe(`Deployment id (FQN)`),project:w},outputSchema:{type:f.enum([`deployment-node`,`deployed-instance`]),id:f.string().describe(`Deployment id (FQN)`),kind:f.string().describe(`Deployment node kind, or element kind for deployed instances`),name:f.string(),title:f.string(),description:f.string().nullable(),technology:f.string().nullable(),tags:f.array(f.string()),project:f.string(),metadata:f.record(f.union([f.string(),f.array(f.string())])),links:f.array(f.object({title:f.string().nullable().describe(`Optional link title`),url:f.string().describe(`Link URL`),relative:f.string().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this deployment entity`),shape:f.string(),color:f.string(),children:f.array(f.string()).describe(`Children of this deployment node (Array of Deployment ids)`),includedInViews:T.describe(`Views that include this deployment node`),instanceof:f.object({id:f.string().describe(`Element ID (FQN)`),title:f.string(),kind:f.string()}).nullable().describe(`If type is "deployed-instance", the referenced element`),sourceLocation:C}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).deployment.findElement(t.id);
|
|
773
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read deployment entity`},inputSchema:{id:f.string().describe(`Deployment id (FQN)`),project:w},outputSchema:{type:f.enum([`deployment-node`,`deployed-instance`]),id:f.string().describe(`Deployment id (FQN)`),kind:f.string().describe(`Deployment node kind, or element kind for deployed instances`),name:f.string(),title:f.string(),description:f.string().nullable(),technology:f.string().nullable(),tags:f.array(f.string()),project:f.string(),metadata:f.record(f.union([f.string(),f.array(f.string())])),links:f.array(f.object({title:f.string().nullable().describe(`Optional link title`),url:f.string().describe(`Link URL`),relative:f.string().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this deployment entity`),shape:f.string(),color:f.string(),children:f.array(f.string()).describe(`Children of this deployment node (Array of Deployment ids)`),includedInViews:T.describe(`Views that include this deployment node`),instanceof:f.object({id:f.string().describe(`Element ID (FQN)`),title:f.string(),kind:f.string()}).nullable().describe(`If type is "deployed-instance", the referenced element`),sourceLocation:C}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).deployment.findElement(t.id);o(r,`Deployment entity "${t.id}" not found in project "${n}"`);let i=mkLocate(e,n);return{type:r.isInstance()?`deployed-instance`:`deployment-node`,id:r.id,name:r.name,kind:r.kind,title:r.title,description:r.description.text,technology:r.technology,tags:[...r.tags],project:n,metadata:r.getMetadata(),links:(r.links??[]).map(e=>({title:e.title??null,url:e.url,relative:e.relative??null})),shape:r.shape,color:r.color,children:r.isInstance()?[]:[...r.children()].map(e=>e.id),includedInViews:includedInViews(r.views()),instanceof:r.isInstance()?{id:r.element.id,title:r.element.title,kind:r.element.kind}:null,sourceLocation:i({deployment:r.id})}}),J=likec4Tool({name:`read-element`,description:`
|
|
774
774
|
Read detailed information about a LikeC4 element.
|
|
775
775
|
|
|
776
776
|
Request:
|
|
@@ -857,7 +857,7 @@ Example response:
|
|
|
857
857
|
"range": { "start": { "line": 10, "character": 0 }, "end": { "line": 25, "character": 0 } }
|
|
858
858
|
}
|
|
859
859
|
}
|
|
860
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read element`},inputSchema:{id:f.string().describe(`Element id (FQN)`),project:w},outputSchema:{id:f.string().describe(`Element id (FQN)`),kind:f.string().describe(`Element kind`),name:f.string().describe(`Element name`),title:f.string(),description:f.string().nullable(),technology:f.string().nullable(),tags:f.array(f.string()),project:f.string(),metadata:f.record(f.union([f.string(),f.array(f.string())])),links:f.array(f.object({title:f.string().nullable().describe(`Optional link title`),url:f.string().describe(`Link URL`),relative:f.string().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this element`),shape:f.string(),color:f.string(),children:f.array(f.string()).describe(`Children of this element (Array of FQNs)`),defaultView:f.string().nullable().describe(`Name of the default view of this element`),includedInViews:T.describe(`Views that include this element`),relationships:f.object({incoming:f.array(f.object({source:f.object({id:f.string(),title:f.string(),kind:f.string()}).describe(`Source element of this relationship`),kind:f.string().nullable().describe(`Relationship kind`),target:f.string().describe(`Target element id (FQN), either this element or nested element, if relationship is indirect`),title:f.string().nullable().describe(`Relationship title`),description:f.string().nullable().describe(`Relationship description`),technology:f.string().nullable().describe(`Relationship technology`),tags:f.array(f.string()).describe(`Relationship tags`)})).describe(`Incoming relationships of this element (direct and indirect, incoming to nested elements)`),outgoing:f.array(f.object({source:f.string().describe(`Source element id (FQN), either this element or nested element, if relationship is indirect`),target:f.object({id:f.string(),title:f.string(),kind:f.string()}).describe(`Target element of this relationship`),kind:f.string().nullable().describe(`Relationship kind`),title:f.string().nullable().describe(`Relationship title`),description:f.string().nullable().describe(`Relationship description`),technology:f.string().nullable().describe(`Relationship technology`),tags:f.array(f.string()).describe(`Relationship tags`)})).describe(`Outgoing relationships of this element (direct and indirect, outgoing from nested elements)`)}).describe(`Relationships of this element`),deployedInstances:f.array(f.string()).describe(`Deployed instances of this element (Array of Deployment FQNs)`),sourceLocation:C}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.id);
|
|
860
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read element`},inputSchema:{id:f.string().describe(`Element id (FQN)`),project:w},outputSchema:{id:f.string().describe(`Element id (FQN)`),kind:f.string().describe(`Element kind`),name:f.string().describe(`Element name`),title:f.string(),description:f.string().nullable(),technology:f.string().nullable(),tags:f.array(f.string()),project:f.string(),metadata:f.record(f.union([f.string(),f.array(f.string())])),links:f.array(f.object({title:f.string().nullable().describe(`Optional link title`),url:f.string().describe(`Link URL`),relative:f.string().nullable().describe(`Relative path (if URL is relative to workspace root)`)})).describe(`External links associated with this element`),shape:f.string(),color:f.string(),children:f.array(f.string()).describe(`Children of this element (Array of FQNs)`),defaultView:f.string().nullable().describe(`Name of the default view of this element`),includedInViews:T.describe(`Views that include this element`),relationships:f.object({incoming:f.array(f.object({source:f.object({id:f.string(),title:f.string(),kind:f.string()}).describe(`Source element of this relationship`),kind:f.string().nullable().describe(`Relationship kind`),target:f.string().describe(`Target element id (FQN), either this element or nested element, if relationship is indirect`),title:f.string().nullable().describe(`Relationship title`),description:f.string().nullable().describe(`Relationship description`),technology:f.string().nullable().describe(`Relationship technology`),tags:f.array(f.string()).describe(`Relationship tags`)})).describe(`Incoming relationships of this element (direct and indirect, incoming to nested elements)`),outgoing:f.array(f.object({source:f.string().describe(`Source element id (FQN), either this element or nested element, if relationship is indirect`),target:f.object({id:f.string(),title:f.string(),kind:f.string()}).describe(`Target element of this relationship`),kind:f.string().nullable().describe(`Relationship kind`),title:f.string().nullable().describe(`Relationship title`),description:f.string().nullable().describe(`Relationship description`),technology:f.string().nullable().describe(`Relationship technology`),tags:f.array(f.string()).describe(`Relationship tags`)})).describe(`Outgoing relationships of this element (direct and indirect, outgoing from nested elements)`)}).describe(`Relationships of this element`),deployedInstances:f.array(f.string()).describe(`Deployed instances of this element (Array of Deployment FQNs)`),sourceLocation:C}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.id);o(r,`Element "${t.id}" not found in project "${n}"`);let i=mkLocate(e,n);return{id:r.id,name:r.name,kind:r.kind,title:r.title,description:r.description.text,technology:r.technology,tags:[...r.tags],project:n,metadata:r.getMetadata(),links:(r.links??[]).map(e=>({title:e.title??null,url:e.url,relative:e.relative??null})),shape:r.shape,color:r.color,children:[...r.children()].map(e=>e.id),defaultView:r.defaultView?.id||null,includedInViews:includedInViews(r.views()),relationships:{incoming:[...r.incoming()].map(e=>({source:{id:e.source.id,title:e.source.title,kind:e.source.kind},kind:e.kind,target:e.target.id,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags]})),outgoing:[...r.outgoing()].map(e=>({source:e.source.id,target:{id:e.target.id,title:e.target.title,kind:e.target.kind},kind:e.kind,title:e.title,description:e.description.text,technology:e.technology,tags:[...e.tags]}))},deployedInstances:[...r.deployments()].map(e=>e.id),sourceLocation:i({element:r.id})}}),Y=likec4Tool({name:`read-project-summary`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Read project summary`},description:`
|
|
861
861
|
Request:
|
|
862
862
|
- project: string (optional) — project id. Defaults to "default" if omitted.
|
|
863
863
|
|
|
@@ -948,7 +948,7 @@ Example response:
|
|
|
948
948
|
}
|
|
949
949
|
]
|
|
950
950
|
}
|
|
951
|
-
`,inputSchema:{project:w},outputSchema:{title:f.string(),folder:f.string(),sources:f.array(f.string()),config:x.describe(`Project configuration`),specification:f.object({elementKinds:f.array(f.string()),relationshipKinds:f.array(f.string()),deploymentKinds:f.array(f.string()),tags:f.array(f.string()),metadataKeys:f.array(f.string())}),elements:f.array(f.object({id:f.string(),kind:f.string(),title:f.string(),tags:f.array(f.string())})).describe(`List of elements in the project`),deployments:f.array(f.discriminatedUnion(`type`,[f.object({type:f.literal(`deployment-node`),id:f.string().describe(`Node ID`),kind:f.string().describe(`Deployment node kind`),title:f.string().describe(`Node title`),tags:f.array(f.string())}),f.object({type:f.literal(`deployed-instance`),id:f.string().describe(`Node ID`),title:f.string().describe(`Node title`),tags:f.array(f.string()),referencedElementId:f.string().describe(`Element ID (FQN)`)})])).describe(`List of deployment nodes and deployed instances in the project`),views:f.array(f.object({id:f.string(),title:f.string(),type:f.enum([`element`,`deployment`,`dynamic`])}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=e.project(n),i=await e.computedModel(n);return{title:r.title,folder:r.folder.fsPath,sources:r.documents?.map(e=>e.fsPath)??[],config:serializeConfig(r.config),specification:{elementKinds:
|
|
951
|
+
`,inputSchema:{project:w},outputSchema:{title:f.string(),folder:f.string(),sources:f.array(f.string()),config:x.describe(`Project configuration`),specification:f.object({elementKinds:f.array(f.string()),relationshipKinds:f.array(f.string()),deploymentKinds:f.array(f.string()),tags:f.array(f.string()),metadataKeys:f.array(f.string())}),elements:f.array(f.object({id:f.string(),kind:f.string(),title:f.string(),tags:f.array(f.string())})).describe(`List of elements in the project`),deployments:f.array(f.discriminatedUnion(`type`,[f.object({type:f.literal(`deployment-node`),id:f.string().describe(`Node ID`),kind:f.string().describe(`Deployment node kind`),title:f.string().describe(`Node title`),tags:f.array(f.string())}),f.object({type:f.literal(`deployed-instance`),id:f.string().describe(`Node ID`),title:f.string().describe(`Node title`),tags:f.array(f.string()),referencedElementId:f.string().describe(`Element ID (FQN)`)})])).describe(`List of deployment nodes and deployed instances in the project`),views:f.array(f.object({id:f.string(),title:f.string(),type:f.enum([`element`,`deployment`,`dynamic`])}))}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=e.project(n),i=await e.computedModel(n);return{title:r.title,folder:r.folder.fsPath,sources:r.documents?.map(e=>e.fsPath)??[],config:serializeConfig(r.config),specification:{elementKinds:s(i.specification.elements),relationshipKinds:s(i.specification.relationships),deploymentKinds:s(i.specification.deployments),tags:[...i.tags],metadataKeys:i.specification.metadataKeys??[]},elements:[...i.elements()].filter(e=>!e.imported).map(e=>({id:e.id,kind:e.kind,title:e.title,tags:[...e.tags]})),deployments:[...i.deployment.elements()].map(e=>e.isInstance()?{type:`deployed-instance`,id:e.id,title:e.title,tags:[...e.tags],referencedElementId:e.element.id}:{type:`deployment-node`,id:e.id,kind:e.kind,title:e.title,tags:[...e.tags]}),views:[...i.views()].map(e=>({id:e.id,title:e.titleOrId,type:e.$view._type}))}}),modelRef=e=>e.hasElement()?e.element.id:e.hasDeployment()?e.deployment.id:null,X=f.discriminatedUnion(`type`,[f.object({type:f.literal(`element`),id:f.string().describe(`Node ID`),elementId:f.string().describe(`Element ID (FQN)`),kind:f.string().describe(`Element kind`),title:f.string().describe(`Node title`),description:f.string().nullable(),technology:f.string().nullable(),children:f.array(f.string()).describe(`Children nodes, array of node IDs`),shape:f.string().describe(`Rendered shape`),color:f.string().describe(`Rendered color`),tags:f.array(f.string())}),f.object({type:f.literal(`deployment-node`),id:f.string().describe(`Node ID`),deploymentId:f.string().describe(`Deployment entity ID (FQN)`),kind:f.string().describe(`Deployment kind`),title:f.string().describe(`Node title`),description:f.string().nullable(),technology:f.string().nullable(),children:f.array(f.string()).describe(`Children nodes, array of node IDs`),shape:f.string().describe(`Rendered shape`),color:f.string().describe(`Rendered color`),tags:f.array(f.string())}),f.object({type:f.literal(`deployed-instance`),id:f.string().describe(`Node ID`),deploymentId:f.string().describe(`Deployment entity ID (FQN)`),title:f.string().describe(`Node title`),description:f.string().nullable(),technology:f.string().nullable(),referencedElement:f.object({id:f.string().describe(`Element ID (FQN)`),kind:f.string().describe(`Element kind`),title:f.string().describe(`Element title`)}),shape:f.string().describe(`Rendered shape`),color:f.string().describe(`Rendered color`),tags:f.array(f.string())})]),Z=likec4Tool({name:`read-view`,description:`
|
|
952
952
|
Read detailed information about a LikeC4 view.
|
|
953
953
|
|
|
954
954
|
Request:
|
|
@@ -1117,7 +1117,7 @@ Example response:
|
|
|
1117
1117
|
"truncated": false,
|
|
1118
1118
|
"truncatedByDepth": false
|
|
1119
1119
|
}
|
|
1120
|
-
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Subgraph summary`},inputSchema:{elementId:f.string().describe(`Parent element id (FQN) whose descendants to summarize`),maxDepth:f.number().int().min(1).max(20).optional().default(10).describe(`Maximum depth of descendants to include (default: 10, max: 20)`),metadataKeys:f.array(f.string()).optional().describe(`If provided, only include these metadata keys in the response`),project:w},outputSchema:{root:f.object({id:f.string(),kind:f.string(),title:f.string(),childCount:f.number()}),descendants:f.array(ee),totalDescendants:f.number().describe(`Total number of descendants found`),truncated:f.boolean().describe(`True if results were truncated due to exceeding the limit`),truncatedByDepth:f.boolean().describe(`True if deeper descendants exist beyond maxDepth`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.elementId);
|
|
1120
|
+
`,annotations:{readOnlyHint:!0,idempotentHint:!0,title:`Subgraph summary`},inputSchema:{elementId:f.string().describe(`Parent element id (FQN) whose descendants to summarize`),maxDepth:f.number().int().min(1).max(20).optional().default(10).describe(`Maximum depth of descendants to include (default: 10, max: 20)`),metadataKeys:f.array(f.string()).optional().describe(`If provided, only include these metadata keys in the response`),project:w},outputSchema:{root:f.object({id:f.string(),kind:f.string(),title:f.string(),childCount:f.number()}),descendants:f.array(ee),totalDescendants:f.number().describe(`Total number of descendants found`),truncated:f.boolean().describe(`True if results were truncated due to exceeding the limit`),truncatedByDepth:f.boolean().describe(`True if deeper descendants exist beyond maxDepth`)}},async(e,t)=>{let n=e.projectsManager.ensureProjectId(t.project),r=(await e.computedModel(n)).findElement(t.elementId);o(r,`Element "${t.elementId}" not found in project "${n}"`);let i=t.maxDepth,a=t.metadataKeys,s=[],c=0,l=!1,u=!1,d=[],f=[...r.children()];for(let e of f)d.push({element:e,depth:1});for(;d.length>0;){let{element:e,depth:t}=d.shift();if(t>i){u=!0;continue}c++;let n=[...e.children()];if(s.length<200){let r=e.getMetadata(),i=a?Object.fromEntries(a.filter(e=>e in r).map(e=>[e,r[e]])):r;s.push({id:e.id,name:e.name,kind:e.kind,title:e.title,depth:t,tags:[...e.tags],metadata:i,childCount:n.length,incomingCount:[...e.incoming()].length,outgoingCount:[...e.outgoing()].length})}else l=!0;for(let e of n)d.push({element:e,depth:t+1})}return{root:{id:r.id,kind:r.kind,title:r.title,childCount:f.length},descendants:s,totalDescendants:c,truncated:l,truncatedByDepth:u}});var MCPServerFactory=class{constructor(e){this.services=e}create(e){let n=this.services.shared.lsp.Connection!==void 0,r=new d({name:`LikeC4`,version:b},{instructions:`LikeC4 MCP – query and navigate LikeC4 models.
|
|
1121
1121
|
|
|
1122
1122
|
Conventions:
|
|
1123
1123
|
- All tools are read-only and idempotent.
|
|
@@ -1151,4 +1151,4 @@ Instructions:
|
|
|
1151
1151
|
- If response returns "sourceLocation", provide link to this location in the editor
|
|
1152
1152
|
|
|
1153
1153
|
Full documentation: https://likec4.dev/llms-full.txt
|
|
1154
|
-
`,enforceStrictCapabilities:!0,...
|
|
1154
|
+
`,enforceStrictCapabilities:!0,...e,capabilities:{tools:{},logging:{},...e?.capabilities}});return r.registerTool(...F(this.services.likec4.LanguageServices)),r.registerTool(...Y(this.services.likec4.LanguageServices)),r.registerTool(...J(this.services.likec4.LanguageServices)),r.registerTool(...q(this.services.likec4.LanguageServices)),r.registerTool(...Z(this.services.likec4.LanguageServices)),r.registerTool(...$(this.services.likec4.LanguageServices)),r.registerTool(...P(this.services.likec4.LanguageServices)),r.registerTool(...H(this.services.likec4.LanguageServices)),r.registerTool(...W(this.services.likec4.LanguageServices)),r.registerTool(...K(this.services.likec4.LanguageServices)),r.registerTool(...R(this.services.likec4.LanguageServices)),r.registerTool(...B(this.services.likec4.LanguageServices)),r.registerTool(...j(this.services.likec4.LanguageServices)),r.registerTool(...D(this.services.likec4.LanguageServices)),r.registerTool(...z(this.services.likec4.LanguageServices)),r.registerTool(...A(this.services.likec4.LanguageServices)),r.registerTool(...te(this.services.likec4.LanguageServices)),n&&r.registerTool(...I(this.services.likec4.LanguageServices)),r.server.onerror=e=>{t.error(a(e))},r}},StdioLikeC4MCPServer=class{transport=void 0;_mcp=void 0;constructor(e){this.services=e}get mcp(){if(!this._mcp)throw Error(`MCP server is not started`);return this._mcp}get isStarted(){return this.transport!==void 0}get port(){return NaN}async dispose(){await this.stop()}async start(){this.transport||(y.info(`Starting MCP stdio server`),this._mcp=this.services.mcp.ServerFactory.create(),this.transport=new p,await this._mcp.connect(this.transport),y.info(`LikeC4 MCP Server running on stdio`))}async stop(){if(this.transport)try{y.info(`Stopping MCP stdio server`),await this.transport.close(),this._mcp&&await this._mcp.close()}finally{this._mcp=void 0,this.transport=void 0}}};async function createHonoApp(e){let t=new _;t.use(`*`,v({origin:`*`,allowHeaders:[`Content-Type`,`mcp-session-id`,`Last-Event-ID`,`mcp-protocol-version`],exposeHeaders:[`mcp-session-id`,`mcp-protocol-version`]})),t.get(`/health`,e=>e.json({status:`ok`}));let n=e.create(),r=new h({eventStore:new m({})});return t.all(`/mcp`,async e=>(n.isConnected()||await n.connect(r),await r.handleRequest(e))),t.notFound(e=>(y.debug(`${e.req.method} ${e.req.url} not found`),e.json({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not found.`},id:null},{status:404}))),t.onError((e,t)=>(y.error(a(e)),t.json({jsonrpc:`2.0`,error:{code:-32603,message:`Internal server error`},id:null},{status:500}))),t}async function startServer(e){let{factory:t,port:n}=e,r=await createHonoApp(t);return new Promise((e,t)=>{let i=g({fetch:r.fetch,hostname:`0.0.0.0`,port:n}).prependOnceListener(`error`,t).prependOnceListener(`listening`,()=>{i.removeListener(`error`,t),e(i.unref())})})}var StreamableLikeC4MCPServer=class{server=void 0;constructor(e,t=33335){this.services=e,this._port=t}get mcp(){throw Error(`StreamableLikeC4MCPServer has access to McpServer only during the request`)}get isStarted(){return this.server?.listening===!0}get port(){return this._port}async dispose(){await this.stop()}async start(e=this._port){if(this.server){if(this.port===e)return;await this.stop()}y.info(`Starting MCP server on port {port}`,{port:e}),this._port=e,this.server=await startServer({factory:this.services.mcp.ServerFactory,port:e}),y.info(`MCP server ready at http://0.0.0.0:{port}/mcp`,{port:e})}stop(){let e=this.server;return e?(y.info(`Stopping MCP server`),this.server=void 0,new Promise(t=>{e.close(e=>{e?y.error(`Failed to stop MCP server`,{err:e}):y.info(`MCP server stopped`),t()})})):(y.info(`MCP server is not running, nothing to stop`),Promise.resolve())}};function streamableLikeC4MCPServer(e,t=33335){y.debug(`Creating StreamableLikeC4MCPServer`);let n=new StreamableLikeC4MCPServer(e,t),r=e.LanguageMetaData.languageId,i=e.shared.lsp.Connection;return e.shared.workspace.ConfigurationProvider.onConfigurationSectionUpdate(e=>{if(e.section!==r){y.warn(`Unexpected configuration update: {update}`,{update:e});return}let{enabled:o=!1,port:s=t}=e.configuration.mcp;if(!o){n.stop();return}Promise.resolve().then(()=>n.start(s)).then(()=>{i?.telemetry?.logEvent({eventName:`mcp-server-started`,mcpPort:s})}).catch(e=>{let t=a(e);i?.telemetry?.logEvent({eventName:`mcp-server-start-failed`,mcpPort:s,message:t}),y.warn(`Failed to start LikeC4 MCP Server: \n${t}`),i&&i.window.showErrorMessage(`LikeC4: Failed to start MCP Server\n\n${t}`)})}),n}function stdioLikeC4MCPServer(e){return new StdioLikeC4MCPServer(e)}function WithMCPServer(e=`sse`){return{mcpServer:t=>e===`stdio`?stdioLikeC4MCPServer(t):streamableLikeC4MCPServer(t,typeof e==`object`?e.port:33335),mcpServerFactory:e=>new MCPServerFactory(e)}}export{WithMCPServer as t};
|
|
@@ -2,15 +2,15 @@ import { h as Locate, n as ChangeView, o as DidRequestOpenViewNotification } fro
|
|
|
2
2
|
import * as langium from "langium";
|
|
3
3
|
import { AstNode, AstNodeDescription, AsyncDisposable, BuildOptions, Cancellation, CstNode, DefaultAstNodeDescriptionProvider, DefaultDocumentValidator, DefaultIndexManager, DefaultLangiumDocuments, DefaultNameProvider, DefaultScopeComputation, DefaultScopeProvider, DefaultValueConverter, DefaultWorkspaceManager, DiagnosticInfo, Disposable, FileSelector, FileSystemNode, FileSystemProvider, GrammarAST, JSDocDocumentationProvider, LangiumDocument, LangiumDocumentFactory, MaybePromise, Module, PrecomputedScopes, Reference, ReferenceDescription, ReferenceInfo, Scope, SimpleCache, Stream, URI, ValidationOptions, ValueType, WorkspaceCache } from "langium";
|
|
4
4
|
import { DefaultWeakMap, MultiMap as MultiMap$1 } from "@likec4/core/utils";
|
|
5
|
+
import * as c4 from "@likec4/core";
|
|
6
|
+
import { ComputedView, DiagramView, LayoutType, LayoutedView, NonEmptyArray, NonEmptyReadonlyArray, ProjectId, Tag, UnknownComputed, UnknownLayouted, UnknownParsed, ViewChange, ViewId } from "@likec4/core";
|
|
5
7
|
import { CompletionItemKind, Diagnostic, DocumentSymbol, FormattingOptions, Hover, Location, Range, SymbolKind, TextEdit } from "vscode-languageserver-types";
|
|
8
|
+
import { IncludeConfig, LikeC4ProjectConfig, LikeC4ProjectConfigInput } from "@likec4/config";
|
|
9
|
+
import { URI as URI$2 } from "vscode-uri";
|
|
6
10
|
import { AbstractFormatter, AbstractSemanticTokenProvider, AstNodeHoverProvider, CodeActionProvider, CodeLensProvider, CompletionAcceptor, CompletionContext, DefaultCompletionProvider, DefaultDocumentHighlightProvider, DefaultSharedModuleContext, DefaultWorkspaceSymbolProvider, DocumentLinkProvider, DocumentSymbolProvider, FormattingRegion, LangiumServices, LangiumSharedServices, NextFeature, NodeKindProvider, PartialLangiumServices, SemanticTokenAcceptor } from "langium/lsp";
|
|
7
11
|
import { GraphvizLayouter, GraphvizPort, QueueGraphvizLayoter } from "@likec4/layouts";
|
|
8
|
-
import * as c4 from "@likec4/core";
|
|
9
|
-
import { ComputedView, DiagramView, LayoutType, LayoutedView, NonEmptyArray, NonEmptyReadonlyArray, ProjectId, Tag, UnknownComputed, UnknownLayouted, UnknownParsed, ViewChange, ViewId } from "@likec4/core";
|
|
10
12
|
import { AdhocViewPredicate, LayoutedProjectsView as LayoutedProjectsView$1 } from "@likec4/core/compute-view";
|
|
11
13
|
import { ElementModel, LikeC4Model } from "@likec4/core/model";
|
|
12
|
-
import { IncludeConfig, LikeC4ProjectConfig, LikeC4ProjectConfigInput } from "@likec4/config";
|
|
13
|
-
import { URI as URI$2 } from "vscode-uri";
|
|
14
14
|
import { LikeC4Styles } from "@likec4/core/styles";
|
|
15
15
|
import { CancellationToken, CodeLens, CodeLensParams, Connection, DocumentHighlight, DocumentLink, DocumentLinkParams, DocumentSymbolParams, WorkspaceFolder } from "vscode-languageserver";
|
|
16
16
|
import { CodeAction, CodeActionParams, Command } from "vscode-languageserver-protocol";
|
|
@@ -231,11 +231,46 @@ type ManualLayoutsSnapshot = {
|
|
|
231
231
|
hash: string;
|
|
232
232
|
views: Record<ViewId$1, LayoutedView$1>;
|
|
233
233
|
};
|
|
234
|
+
type ManualLayoutUpdateEvent = {
|
|
235
|
+
updated: URI;
|
|
236
|
+
projectId: ProjectId$1;
|
|
237
|
+
viewId: ViewId$1;
|
|
238
|
+
} | {
|
|
239
|
+
removed: URI;
|
|
240
|
+
projectId: ProjectId$1;
|
|
241
|
+
/**
|
|
242
|
+
* Missing if triggered by FS event (file was deleted)
|
|
243
|
+
*/
|
|
244
|
+
viewId?: ViewId$1;
|
|
245
|
+
};
|
|
246
|
+
type ManualLayoutUpdateListener = (event: ManualLayoutUpdateEvent) => void;
|
|
234
247
|
interface LikeC4ManualLayouts {
|
|
248
|
+
/**
|
|
249
|
+
* Reads a single layouted view from the file system by its URI.
|
|
250
|
+
* Used by the language server to get the current layout state.
|
|
251
|
+
*/
|
|
252
|
+
readSnapshot(uri: URI): Promise<LayoutedView$1 | null>;
|
|
235
253
|
read(project: Project): Promise<ManualLayoutsSnapshot | null>;
|
|
236
254
|
write(project: Project, layouted: LayoutedView$1): Promise<Location>;
|
|
237
255
|
remove(project: Project, view: ViewId$1): Promise<Location | null>;
|
|
238
256
|
clearCaches(): void;
|
|
257
|
+
/**
|
|
258
|
+
* Registers a listener for manual layout updates.
|
|
259
|
+
* The listener will be called when a manual layout is created, updated, or deleted.
|
|
260
|
+
*/
|
|
261
|
+
onManualLayoutUpdate(listener: ManualLayoutUpdateListener): Disposable;
|
|
262
|
+
/**
|
|
263
|
+
* Handles file system updates for manual layouts.
|
|
264
|
+
* Used by the file system watcher to notify the manual layouts module of changes.
|
|
265
|
+
* @param event The file system event
|
|
266
|
+
*/
|
|
267
|
+
handleFileSystemUpdate(event: {
|
|
268
|
+
update: URI;
|
|
269
|
+
delete?: never;
|
|
270
|
+
} | {
|
|
271
|
+
delete: URI;
|
|
272
|
+
update?: never;
|
|
273
|
+
}): Promise<void>;
|
|
239
274
|
}
|
|
240
275
|
//#endregion
|
|
241
276
|
//#region src/filesystem/noop.d.ts
|
|
@@ -244,7 +279,7 @@ declare const NoFileSystem: FileSystemModuleContext;
|
|
|
244
279
|
declare const NoLikeC4ManualLayouts: LikeC4ManualLayoutsModuleContext;
|
|
245
280
|
//#endregion
|
|
246
281
|
//#region src/filesystem/LikeC4FileSystem.d.ts
|
|
247
|
-
declare const WithFileSystem: (
|
|
282
|
+
declare const WithFileSystem: (enableWatcher?: boolean) => FileSystemModuleContext;
|
|
248
283
|
//#endregion
|
|
249
284
|
//#region src/filesystem/ChokidarWatcher.d.ts
|
|
250
285
|
declare const WithChokidarWatcher: FileSystemWatcherModuleContext;
|
|
@@ -368,6 +403,7 @@ type Id = 'deployment' | 'element' | 'group' | 'instance' | 'model' | 'node' | A
|
|
|
368
403
|
type LikeC4View = DeploymentView | DynamicView | ElementView;
|
|
369
404
|
declare const LikeC4View = "LikeC4View";
|
|
370
405
|
type LineOptions = 'dashed' | 'dotted' | 'solid';
|
|
406
|
+
type MetadataFilterValue = boolean | string;
|
|
371
407
|
type MetadataProperty = MetadataBody;
|
|
372
408
|
declare const MetadataProperty = "MetadataProperty";
|
|
373
409
|
type MetadataValue = MarkdownOrString | MetadataArray;
|
|
@@ -404,7 +440,7 @@ type ViewRule = ViewRuleAutoLayout | ViewRuleGlobalPredicateRef | ViewRuleGroup
|
|
|
404
440
|
declare const ViewRule = "ViewRule";
|
|
405
441
|
type ViewRuleStyleOrGlobalRef = ViewRuleGlobalStyle | ViewRuleStyle;
|
|
406
442
|
declare const ViewRuleStyleOrGlobalRef = "ViewRuleStyleOrGlobalRef";
|
|
407
|
-
type WhereElement = WhereElementKind | WhereElementTag;
|
|
443
|
+
type WhereElement = WhereElementKind | WhereElementMetadata | WhereElementTag;
|
|
408
444
|
declare const WhereElement = "WhereElement";
|
|
409
445
|
type WhereElementExpression = WhereBinaryExpression | WhereElement | WhereElementNegation;
|
|
410
446
|
declare const WhereElementExpression = "WhereElementExpression";
|
|
@@ -412,7 +448,9 @@ type WhereExpression = WhereElementExpression | WhereRelationExpression;
|
|
|
412
448
|
declare const WhereExpression = "WhereExpression";
|
|
413
449
|
type WhereKindEqual = WhereElementKind | WhereRelationKind | WhereRelationParticipantKind;
|
|
414
450
|
declare const WhereKindEqual = "WhereKindEqual";
|
|
415
|
-
type
|
|
451
|
+
type WhereMetadataEqual = WhereElementMetadata | WhereRelationMetadata | WhereRelationParticipantMetadata;
|
|
452
|
+
declare const WhereMetadataEqual = "WhereMetadataEqual";
|
|
453
|
+
type WhereRelation = WhereRelationKind | WhereRelationMetadata | WhereRelationParticipantKind | WhereRelationParticipantMetadata | WhereRelationParticipantTag | WhereRelationTag;
|
|
416
454
|
declare const WhereRelation = "WhereRelation";
|
|
417
455
|
type WhereRelationExpression = WhereBinaryExpression | WhereRelation | WhereRelationNegation;
|
|
418
456
|
declare const WhereRelationExpression = "WhereRelationExpression";
|
|
@@ -943,8 +981,9 @@ declare const MetadataArray = "MetadataArray";
|
|
|
943
981
|
interface MetadataAttribute extends langium.AstNode {
|
|
944
982
|
readonly $container: MetadataBody;
|
|
945
983
|
readonly $type: 'MetadataAttribute';
|
|
984
|
+
boolValue: boolean;
|
|
946
985
|
key: string;
|
|
947
|
-
value
|
|
986
|
+
value?: MetadataValue;
|
|
948
987
|
}
|
|
949
988
|
declare const MetadataAttribute = "MetadataAttribute";
|
|
950
989
|
interface MetadataBody extends langium.AstNode {
|
|
@@ -1298,6 +1337,15 @@ interface WhereElementKind extends langium.AstNode {
|
|
|
1298
1337
|
value: langium.Reference<DeploymentNodeOrElementKind>;
|
|
1299
1338
|
}
|
|
1300
1339
|
declare const WhereElementKind = "WhereElementKind";
|
|
1340
|
+
interface WhereElementMetadata extends langium.AstNode {
|
|
1341
|
+
readonly $container: FqnExprWhere | WhereBinaryExpression | WhereElementNegation;
|
|
1342
|
+
readonly $type: 'WhereElementMetadata';
|
|
1343
|
+
key: Id;
|
|
1344
|
+
not: boolean;
|
|
1345
|
+
operator?: 'is' | string;
|
|
1346
|
+
value?: MetadataFilterValue;
|
|
1347
|
+
}
|
|
1348
|
+
declare const WhereElementMetadata = "WhereElementMetadata";
|
|
1301
1349
|
interface WhereElementNegation extends langium.AstNode {
|
|
1302
1350
|
readonly $container: FqnExprWhere | WhereBinaryExpression | WhereElementNegation;
|
|
1303
1351
|
readonly $type: 'WhereElementNegation';
|
|
@@ -1320,6 +1368,15 @@ interface WhereRelationKind extends langium.AstNode {
|
|
|
1320
1368
|
value: langium.Reference<RelationshipKind>;
|
|
1321
1369
|
}
|
|
1322
1370
|
declare const WhereRelationKind = "WhereRelationKind";
|
|
1371
|
+
interface WhereRelationMetadata extends langium.AstNode {
|
|
1372
|
+
readonly $container: RelationExprWhere | WhereBinaryExpression | WhereRelationNegation;
|
|
1373
|
+
readonly $type: 'WhereRelationMetadata';
|
|
1374
|
+
key: Id;
|
|
1375
|
+
not: boolean;
|
|
1376
|
+
operator?: 'is' | string;
|
|
1377
|
+
value?: MetadataFilterValue;
|
|
1378
|
+
}
|
|
1379
|
+
declare const WhereRelationMetadata = "WhereRelationMetadata";
|
|
1323
1380
|
interface WhereRelationNegation extends langium.AstNode {
|
|
1324
1381
|
readonly $container: RelationExprWhere | WhereBinaryExpression | WhereRelationNegation;
|
|
1325
1382
|
readonly $type: 'WhereRelationNegation';
|
|
@@ -1335,6 +1392,16 @@ interface WhereRelationParticipantKind extends langium.AstNode {
|
|
|
1335
1392
|
value: langium.Reference<DeploymentNodeOrElementKind>;
|
|
1336
1393
|
}
|
|
1337
1394
|
declare const WhereRelationParticipantKind = "WhereRelationParticipantKind";
|
|
1395
|
+
interface WhereRelationParticipantMetadata extends langium.AstNode {
|
|
1396
|
+
readonly $container: RelationExprWhere | WhereBinaryExpression | WhereRelationNegation;
|
|
1397
|
+
readonly $type: 'WhereRelationParticipantMetadata';
|
|
1398
|
+
key: Id;
|
|
1399
|
+
not: boolean;
|
|
1400
|
+
operator?: 'is' | string;
|
|
1401
|
+
participant: Participant;
|
|
1402
|
+
value?: MetadataFilterValue;
|
|
1403
|
+
}
|
|
1404
|
+
declare const WhereRelationParticipantMetadata = "WhereRelationParticipantMetadata";
|
|
1338
1405
|
interface WhereRelationParticipantTag extends langium.AstNode {
|
|
1339
1406
|
readonly $container: RelationExprWhere | WhereBinaryExpression | WhereRelationNegation;
|
|
1340
1407
|
readonly $type: 'WhereRelationParticipantTag';
|
|
@@ -1528,15 +1595,19 @@ type LikeC4AstType = {
|
|
|
1528
1595
|
WhereElement: WhereElement;
|
|
1529
1596
|
WhereElementExpression: WhereElementExpression;
|
|
1530
1597
|
WhereElementKind: WhereElementKind;
|
|
1598
|
+
WhereElementMetadata: WhereElementMetadata;
|
|
1531
1599
|
WhereElementNegation: WhereElementNegation;
|
|
1532
1600
|
WhereElementTag: WhereElementTag;
|
|
1533
1601
|
WhereExpression: WhereExpression;
|
|
1534
1602
|
WhereKindEqual: WhereKindEqual;
|
|
1603
|
+
WhereMetadataEqual: WhereMetadataEqual;
|
|
1535
1604
|
WhereRelation: WhereRelation;
|
|
1536
1605
|
WhereRelationExpression: WhereRelationExpression;
|
|
1537
1606
|
WhereRelationKind: WhereRelationKind;
|
|
1607
|
+
WhereRelationMetadata: WhereRelationMetadata;
|
|
1538
1608
|
WhereRelationNegation: WhereRelationNegation;
|
|
1539
1609
|
WhereRelationParticipantKind: WhereRelationParticipantKind;
|
|
1610
|
+
WhereRelationParticipantMetadata: WhereRelationParticipantMetadata;
|
|
1540
1611
|
WhereRelationParticipantTag: WhereRelationParticipantTag;
|
|
1541
1612
|
WhereRelationTag: WhereRelationTag;
|
|
1542
1613
|
WhereTagEqual: WhereTagEqual;
|
|
@@ -2071,7 +2142,7 @@ declare class LastSeenArtifacts {
|
|
|
2071
2142
|
}
|
|
2072
2143
|
//#endregion
|
|
2073
2144
|
//#region src/model/model-builder.d.ts
|
|
2074
|
-
type ModelParsedListener = (docs: URI[]) => void;
|
|
2145
|
+
type ModelParsedListener = (projectId: ProjectId, docs: URI[]) => void;
|
|
2075
2146
|
interface LikeC4ModelBuilder extends Disposable {
|
|
2076
2147
|
parseModel(projectId?: ProjectId | undefined, cancelToken?: CancellationToken$1): Promise<LikeC4Model<UnknownParsed> | null>;
|
|
2077
2148
|
unsafeSyncComputeModel(projectId: ProjectId): LikeC4Model<UnknownComputed>;
|