@likec4/language-server 1.50.0 → 1.52.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.
Files changed (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -25
  3. package/bin/likec4-language-server.mjs +2 -3
  4. package/dist/_chunks/LikeC4FileSystem.mjs +2 -2
  5. package/dist/_chunks/{WithMCPServer.mjs → mcp.mjs} +5 -5
  6. package/dist/_chunks/module.d.mts +124 -30
  7. package/dist/_chunks/module.mjs +19 -19
  8. package/dist/_chunks/utils.mjs +1 -1
  9. package/dist/_chunks/workspace.mjs +1 -1
  10. package/dist/browser/index.d.mts +2 -2
  11. package/dist/browser/index.mjs +1 -1
  12. package/dist/browser/worker.mjs +1 -1
  13. package/dist/filesystem/index.d.mts +1 -1
  14. package/dist/filesystem/index.mjs +1 -1
  15. package/dist/index.d.mts +2 -2
  16. package/dist/index.mjs +1 -1
  17. package/dist/mcp/index.d.mts +1 -1
  18. package/dist/mcp/index.mjs +1 -1
  19. package/dist/module.d.mts +2 -2
  20. package/dist/module.mjs +1 -1
  21. package/package.json +23 -35
  22. package/bundled/package.json +0 -4
  23. package/dist/THIRD-PARTY-LICENSES.md +0 -178
  24. package/dist/_chunks/ConfigurableLayouter.mjs +0 -1
  25. package/dist/_chunks/libs/@msgpack/msgpack.mjs +0 -1
  26. package/dist/_chunks/libs/eventemitter3.mjs +0 -1
  27. package/dist/_chunks/libs/fast-equals.mjs +0 -1
  28. package/dist/_chunks/libs/p-queue.mjs +0 -1
  29. package/dist/_chunks/libs/parse-ms.mjs +0 -1
  30. package/dist/_chunks/libs/picomatch.mjs +0 -1
  31. package/dist/_chunks/libs/pretty-ms.mjs +0 -1
  32. package/dist/_chunks/libs/remeda.mjs +0 -2
  33. package/dist/_chunks/libs/strip-indent.mjs +0 -1
  34. package/dist/_chunks/libs/ufo.mjs +0 -1
  35. package/dist/_chunks/rolldown-runtime.mjs +0 -1
  36. package/dist/bundled.d.mts +0 -27
  37. package/dist/bundled.mjs +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023-2026 Denis Davydkov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,31 +1,11 @@
1
1
  # `@likec4/language-server`
2
2
 
3
- [docs](https://likec4.dev/) | [playground](https://playground.likec4.dev/) | [demo](https://template.likec4.dev/view/index/)
3
+ LikeC4 Language Server Protocol (LSP) based on [langium](https://github.com/langium/langium) library.
4
4
 
5
- Language Server Protocol (LSP) based on [langium](https://github.com/langium/langium) library.
6
-
7
- ## Usage
8
-
9
- ```bash
10
- npm install -g @likec4/language-server
11
- likec4-language-server --stdio
12
- ```
13
-
14
- Valid arguments:
15
-
16
- - `--node-ipc`
17
- - `--stdio`
18
- - `--socket={number}`
19
-
20
- ### Usage in code
21
-
22
- ```js
23
- import { startLanguageServer } from '@likec4/language-server/bundled'
24
- startLanguageServer().catch((e) => {
25
- console.error(e)
26
- process.exit(1)
27
- })
28
- ```
5
+ > [!WARNING]
6
+ > **This package is intended for internal use within other LikeC4 packages.**
7
+ >
8
+ > Please use the main [`likec4`](https://www.npmjs.com/package/likec4) package instead.
29
9
 
30
10
  ## Getting help
31
11
 
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { startLanguageServer } from '../dist/bundled.mjs'
4
-
5
- startLanguageServer()
3
+ console.error('This package is not available as a standalone LSP server. Use `likec4 lsp` instead.')
4
+ process.exit(1)
@@ -1,3 +1,3 @@
1
- import{a as e,r as t}from"./likec4lib.mjs";import{n}from"./noop.mjs";import{Er as r,n as i,r as a,t as o}from"./utils.mjs";import{t as s}from"./libs/p-queue.mjs";import{D as c,o as l}from"./libs/remeda.mjs";import{isLikeC4Config as u,loadConfig as d}from"@likec4/config/node";import{fdir as f}from"fdir";import{SimpleCache as p,URI as m,UriUtils as h}from"langium";import{NodeFileSystemProvider as g}from"langium/node";import{mkdirSync as _,statSync as v}from"node:fs";import{unlink as y,writeFile as b}from"node:fs/promises";import{basename as x,dirname as S}from"node:path";import{objectHash as C,onNextTick as w}from"@likec4/core/utils";import T from"chokidar";import E from"json5";import{Position as D,Range as O}from"vscode-languageserver-types";const k=r.getChild(`manual-layouts`),isManualLayoutFile=e=>e.endsWith(`.likec4.snap`);function fileName(e){return`${e}.likec4.snap`}function getManualLayoutsOutDir(e){return h.resolvePath(e.folderUri,e.config.manualLayouts?.outDir??`.likec4`)}const A={manualLayouts:e=>new DefaultLikeC4ManualLayouts(e)},j=`file://./`;var DefaultLikeC4ManualLayouts=class{cache;constructor(e){this.services=e,this.cache=new p,w(()=>{e.workspace.ProjectsManager.onProjectsUpdate(()=>{this.clearCaches()})})}async read(e){return await this.cache.get(e.id,async()=>{let t=k.getChild(e.id),n=this.services.workspace.FileSystemProvider,r=getManualLayoutsOutDir(e),i=[];try{let a=await n.scanDirectory(r,isManualLayoutFile);if(a.length===0)return null;for(let r of a)try{let t=await n.readFile(r.uri),a=E.parse(t),o=this.resolveIconPathsAfterRead(a,e.folderUri);i.push({...o,_layout:`manual`})}catch(e){t.warn(`Failed to read view snapshot ${r.uri.fsPath}`,{err:e})}i.length&&t.debug`read manual layouts for ${e.id}, found ${i.length}`}catch(n){t.warn(`Failed to read manual layouts for ${e.folderUri.fsPath}`,{err:n})}if(i.length===0)return null;let a=c(i,l(`id`));return{hash:C(a),views:a}})}async write(e,t){let n=k.getChild(e.id),r=getManualLayoutsOutDir(e),i=h.joinPath(r,fileName(t.id));if(`manualLayout`in t){let{manualLayout:e,...n}=t;t=n}let a=E.stringify(this.normalizeIconPathsForWrite(t,e.folderUri),{space:2,quote:`'`}),o={uri:i.toString(),range:O.create(D.create(0,0),D.create(a.split(`
1
+ import{a as e,r as t}from"./likec4lib.mjs";import{n}from"./noop.mjs";import{Tr as r,n as i,r as a,t as o}from"./utils.mjs";import{isLikeC4Config as s,loadConfig as c}from"@likec4/config/node";import{fdir as l}from"fdir";import{SimpleCache as u,URI as d,UriUtils as f}from"langium";import{NodeFileSystemProvider as p}from"langium/node";import{mkdirSync as m,statSync as h}from"node:fs";import{unlink as g,writeFile as _}from"node:fs/promises";import{basename as v,dirname as y}from"node:path";import{objectHash as b,onNextTick as x}from"@likec4/core/utils";import S from"chokidar";import C from"p-queue";import w from"json5";import{indexBy as T,prop as E}from"remeda";import{Position as D,Range as O}from"vscode-languageserver-types";const k=r.getChild(`manual-layouts`),isManualLayoutFile=e=>e.endsWith(`.likec4.snap`);function fileName(e){return`${e}.likec4.snap`}function getManualLayoutsOutDir(e){return f.resolvePath(e.folderUri,e.config.manualLayouts?.outDir??`.likec4`)}const A={manualLayouts:e=>new DefaultLikeC4ManualLayouts(e)},j=`file://./`;var DefaultLikeC4ManualLayouts=class{cache;constructor(e){this.services=e,this.cache=new u,x(()=>{e.workspace.ProjectsManager.onProjectsUpdate(()=>{this.clearCaches()})})}async read(e){return await this.cache.get(e.id,async()=>{let t=k.getChild(e.id),n=this.services.workspace.FileSystemProvider,r=getManualLayoutsOutDir(e),i=[];try{let a=await n.scanDirectory(r,isManualLayoutFile);if(a.length===0)return null;for(let r of a)try{let t=await n.readFile(r.uri),a=w.parse(t),o=this.resolveIconPathsAfterRead(a,e.folderUri);i.push({...o,_layout:`manual`})}catch(e){t.warn(`Failed to read view snapshot ${r.uri.fsPath}`,{err:e})}i.length&&t.debug`read manual layouts for ${e.id}, found ${i.length}`}catch(n){t.warn(`Failed to read manual layouts for ${e.folderUri.fsPath}`,{err:n})}if(i.length===0)return null;let a=T(i,E(`id`));return{hash:b(a),views:a}})}async write(e,t){this.cache.delete(e.id);let n=k.getChild(e.id),r=getManualLayoutsOutDir(e),i=f.joinPath(r,fileName(t.id));if(`manualLayout`in t){let{manualLayout:e,...n}=t;t=n}let a=w.stringify(this.normalizeIconPathsForWrite(t,e.folderUri),{space:2,quote:`'`}),o={uri:i.toString(),range:O.create(D.create(0,0),D.create(a.split(`
2
2
  `).length-1,1))};n.debug`write snapshot of ${t.id} in project ${e.id} to ${i.fsPath}`;let s=this.services.workspace.FileSystemProvider;try{await s.writeFile(i,a+`
3
- `)}catch(e){n.warn(`Failed to write snapshot ${t.id} to ${i.fsPath}`,{err:e})}return this.cache.delete(e.id),o}async remove(e,t){let n=k.getChild(e.id),r=getManualLayoutsOutDir(e),i=h.joinPath(r,fileName(t));n.debug`delete snapshot of ${t} in project ${e.id}. File: ${i.fsPath}`;let a={uri:i.toString(),range:O.create(0,0,0,0)};this.cache.delete(e.id);try{if(!await this.services.workspace.FileSystemProvider.deleteFile(i))return n.warn`Snapshot ${t} did not exist at ${i.fsPath}`,null}catch(e){n.warn(`Failed to delete snapshot ${t} from ${i.fsPath}`,{err:e})}return a}clearCaches(){k.trace`clear caches`,this.cache.clear()}normalizeIconPathsForWrite(e,t){let n=e.nodes.map(e=>{if(!e.icon||typeof e.icon!=`string`)return e;if(e.icon.startsWith(`file://`)){let n=m.parse(e.icon),r=h.relative(t,n);return r.startsWith(`..`)?e:{...e,icon:`${j}${r}`}}return e});return{...e,nodes:n}}resolveIconPathsAfterRead(e,t){let n=e.nodes.map(e=>{if(!e.icon||typeof e.icon!=`string`)return e;if(e.icon.startsWith(j)){let n=e.icon.substring(9),r=h.joinPath(t,n);return{...e,icon:r.toString()}}return e});return{...e,nodes:n}}};const M=r.getChild(`chokidar`),N={fileSystemWatcher:e=>new ChokidarFileSystemWatcher(e)},isAnyLikeC4File=e=>{let t=x(e);return a(t)||u(t)||isManualLayoutFile(t)};var ChokidarFileSystemWatcher=class{watcher;queue=new s({concurrency:1,timeout:5e3});constructor(e){this.services=e}watch(e){if(this.watcher){M.debug`add watching folder: ${e}`,this.watcher.add(e);return}this.watcher=this.createWatcher(e)}async dispose(){if(this.watcher){let e=this.watcher;this.watcher=void 0,await e.close()}}createWatcher(e){M.debug`create watcher for folder: ${e}`;let t=T.watch(e,{ignored:[e=>e.includes(`node_modules`)||e.includes(`.git`),(e,t)=>!!t?.isFile()&&!isAnyLikeC4File(e)],followSymlinks:!0,ignoreInitial:!0}),onAddOrChange=(e,t)=>{t?.isDirectory()||this.enqueueFileOp(`addOrChange: `+e,async()=>{await this.onAddOrChange(e)})};return t.on(`add`,onAddOrChange).on(`change`,onAddOrChange).on(`unlink`,(e,t)=>{t?.isDirectory()||this.enqueueFileOp(`remove: `+e,async()=>{await this.onRemove(e)})}).on(`unlinkDir`,e=>{this.enqueueFileOp(`removeDir: `+e,async()=>{await this.onRemoveDir(e)})}),t}enqueueFileOp(e,t){this.queue.add(async()=>{try{await t()}catch(t){M.warn(`Failed on {fileop}`,{fileop:e,error:t})}}).catch(t=>{M.error(`Error on {fileop}`,{fileop:e,error:t})})}async onAddOrChange(e){let t=this.services.workspace,n=x(e),r=m.file(e);switch(!0){case u(n):M.debug`project file changed: ${e}`,t.ManualLayouts.clearCaches(),await t.ProjectsManager.registerConfigFile(r);break;case a(n):M.debug`file changed: ${e}`,await t.DocumentBuilder.update([r],[]);break;case isManualLayoutFile(n):{M.debug`manual layout file changed: ${e}`,t.ManualLayouts.clearCaches();let n=t.ProjectsManager.ownerProjectId(r);await t.ProjectsManager.rebuildProject(n);break}default:M.warn`Unknown file change: ${e}`}}async onRemove(e){let t=this.services.workspace,n=x(e),r=m.file(e);switch(!0){case u(n):M.debug`project file removed: ${e}`,t.ManualLayouts.clearCaches(),await t.ProjectsManager.reloadProjects();break;case a(n):M.debug`file removed: ${e}`,await t.DocumentBuilder.update([],[r]);break;case isManualLayoutFile(n):{M.debug`manual layout file removed: ${e}`;let n=t.ProjectsManager.ownerProjectId(r);t.ManualLayouts.clearCaches(),await t.ProjectsManager.rebuildProject(n);break}default:M.warn`Unknown file removal: ${e}`}}async onRemoveDir(e){M.debug`directory removed: ${e}`;let t=this.services.workspace;t.ProjectsManager.findOverlaped(e).length>0&&(t.ManualLayouts.clearCaches(),await t.ProjectsManager.reloadProjects())}};const P=r.getChild(`filesystem`);function isLikeC4ConfigFile(e,t=!1){return!t&&u(x(e))}function isLikeC4File(e,t=!1){return!t&&a(x(e))}const WithFileSystem=(e=!0)=>({fileSystemProvider:()=>new SymLinkTraversingFileSystemProvider,...e?N:n});var SymLinkTraversingFileSystemProvider=class extends g{async readFile(n){if(t(n))return Promise.resolve(e);try{return await super.readFile(n)}catch(e){return P.warn(`Failed to read file ${n.fsPath}`,{error:e}),``}}async readDirectory(e,t){let n=t?.recursive??!0,r=t?.maxDepth??1/0,a=[];try{let t=new f().withSymlinks({resolvePaths:!1}).exclude(i).withFullPaths().filter(isLikeC4File);n?r!==1/0&&(t=t.withMaxDepth(r)):t=t.withMaxDepth(1);let o=await t.crawl(e.fsPath).withPromise();for(let e of o)a.push({isFile:!0,isDirectory:!1,uri:m.file(e)})}catch(t){P.warn(`Failed to read directory ${e.fsPath}`,{error:t})}return a.sort(o)}async scanProjectFiles(e){return await this.scanDirectory(e,isLikeC4ConfigFile)}async scanDirectory(e,t){let n=[];try{let r=await new f().withSymlinks({resolvePaths:!1}).exclude(i).withFullPaths().filter(t).crawl(e.fsPath).withPromise();for(let e of r)n.push({isFile:!0,isDirectory:!1,uri:m.file(e)})}catch(t){P.warn(`Failed to scan directory {path}`,{path:e.fsPath,error:t})}return n}async loadProjectConfig(e){return await d(e)}async writeFile(e,t){let n=S(e.fsPath),r=v(n,{throwIfNoEntry:!1});if(r?.isFile())throw Error(`Cannot create directory ${n} because a file with the same name exists.`);return r||(P.debug(`creating directory {path}`,{path:n}),_(n,{recursive:!0})),P.debug(`writing file {path}`,{path:e.fsPath}),await b(e.fsPath,t,{encoding:`utf-8`})}async deleteFile(e){try{let t=e.fsPath,n=v(t,{throwIfNoEntry:!1});return n?.isFile()||n?.isSymbolicLink()?(await y(t),P.debug(`deleted file {path}`,{path:t}),!0):(P.warn(`deleteFile failed: {path} does not exist, or is not a file`,{path:t}),!1)}catch(t){P.warn(`Failed to delete file ${e.fsPath}`,{error:t})}return!1}};export{N as n,A as r,WithFileSystem as t};
3
+ `)}catch(e){n.warn(`Failed to write snapshot ${t.id} to ${i.fsPath}`,{err:e})}return o}async remove(e,t){this.cache.delete(e.id);let n=k.getChild(e.id),r=getManualLayoutsOutDir(e),i=f.joinPath(r,fileName(t));n.debug`delete snapshot of ${t} in project ${e.id}. File: ${i.fsPath}`;let a={uri:i.toString(),range:O.create(0,0,0,0)};try{if(!await this.services.workspace.FileSystemProvider.deleteFile(i))return n.warn`Snapshot ${t} did not exist at ${i.fsPath}`,null}catch(e){n.warn(`Failed to delete snapshot ${t} from ${i.fsPath}`,{err:e})}return a}clearCaches(){k.trace`clear caches`,this.cache.clear()}normalizeIconPathsForWrite(e,t){let n=e.nodes.map(e=>{if(!e.icon||typeof e.icon!=`string`)return e;if(e.icon.startsWith(`file://`)){let n=d.parse(e.icon),r=f.relative(t,n);return r.startsWith(`..`)?e:{...e,icon:`${j}${r}`}}return e});return{...e,nodes:n}}resolveIconPathsAfterRead(e,t){let n=e.nodes.map(e=>{if(!e.icon||typeof e.icon!=`string`)return e;if(e.icon.startsWith(j)){let n=e.icon.substring(9),r=f.joinPath(t,n);return{...e,icon:r.toString()}}return e});return{...e,nodes:n}}};const M=r.getChild(`chokidar`),N={fileSystemWatcher:e=>new ChokidarFileSystemWatcher(e)},isAnyLikeC4File=e=>{let t=v(e);return a(t)||s(t)||isManualLayoutFile(t)};var ChokidarFileSystemWatcher=class{watcher;queue=new C({concurrency:1,timeout:5e3});constructor(e){this.services=e}watch(e){if(this.watcher){M.debug`add watching folder: ${e}`,this.watcher.add(e);return}this.watcher=this.createWatcher(e)}async dispose(){if(this.watcher){let e=this.watcher;this.watcher=void 0,await e.close()}}createWatcher(e){M.debug`create watcher for folder: ${e}`;let t=S.watch(e,{ignored:[e=>e.includes(`node_modules`)||e.includes(`.git`),(e,t)=>!!t?.isFile()&&!isAnyLikeC4File(e)],followSymlinks:!0,ignoreInitial:!0}),onAddOrChange=(e,t)=>{t?.isDirectory()||this.enqueueFileOp(`addOrChange: `+e,async()=>{await this.onAddOrChange(e)})};return t.on(`add`,onAddOrChange).on(`change`,onAddOrChange).on(`unlink`,(e,t)=>{t?.isDirectory()||this.enqueueFileOp(`remove: `+e,async()=>{await this.onRemove(e)})}).on(`unlinkDir`,e=>{this.enqueueFileOp(`removeDir: `+e,async()=>{await this.onRemoveDir(e)})}),t}enqueueFileOp(e,t){this.queue.add(async()=>{try{await t()}catch(t){M.warn(`Failed on {fileop}`,{fileop:e,error:t})}}).catch(t=>{M.error(`Error on {fileop}`,{fileop:e,error:t})})}async onAddOrChange(e){let t=this.services.workspace,n=v(e),r=d.file(e);switch(!0){case s(n):M.debug`project file changed: ${e}`,t.ManualLayouts.clearCaches(),await t.ProjectsManager.registerConfigFile(r);break;case a(n):M.debug`file changed: ${e}`,await t.DocumentBuilder.update([r],[]);break;case isManualLayoutFile(n):{M.debug`manual layout file changed: ${e}`,t.ManualLayouts.clearCaches();let n=t.ProjectsManager.ownerProjectId(r);await t.ProjectsManager.rebuildProject(n);break}default:M.warn`Unknown file change: ${e}`}}async onRemove(e){let t=this.services.workspace,n=v(e),r=d.file(e);switch(!0){case s(n):M.debug`project file removed: ${e}`,t.ManualLayouts.clearCaches(),await t.ProjectsManager.reloadProjects();break;case a(n):M.debug`file removed: ${e}`,await t.DocumentBuilder.update([],[r]);break;case isManualLayoutFile(n):{M.debug`manual layout file removed: ${e}`;let n=t.ProjectsManager.ownerProjectId(r);t.ManualLayouts.clearCaches(),await t.ProjectsManager.rebuildProject(n);break}default:M.warn`Unknown file removal: ${e}`}}async onRemoveDir(e){M.debug`directory removed: ${e}`;let t=this.services.workspace;t.ProjectsManager.findOverlaped(e).length>0&&(t.ManualLayouts.clearCaches(),await t.ProjectsManager.reloadProjects())}};const P=r.getChild(`filesystem`);function isLikeC4ConfigFile(e,t=!1){return!t&&s(v(e))}function isLikeC4File(e,t=!1){return!t&&a(v(e))}const WithFileSystem=(e=!0)=>({fileSystemProvider:()=>new SymLinkTraversingFileSystemProvider,...e?N:n});var SymLinkTraversingFileSystemProvider=class extends p{async readFile(n){if(t(n))return Promise.resolve(e);try{return await super.readFile(n)}catch(e){return P.warn(`Failed to read file ${n.fsPath}`,{error:e}),``}}async readDirectory(e,t){let n=t?.recursive??!0,r=t?.maxDepth??1/0,a=[];try{let t=new l().withSymlinks({resolvePaths:!1}).exclude(i).withFullPaths().filter(isLikeC4File);n?r!==1/0&&(t=t.withMaxDepth(r)):t=t.withMaxDepth(1);let o=await t.crawl(e.fsPath).withPromise();for(let e of o)a.push({isFile:!0,isDirectory:!1,uri:d.file(e)})}catch(t){P.warn(`Failed to read directory ${e.fsPath}`,{error:t})}return a.sort(o)}async scanProjectFiles(e){return await this.scanDirectory(e,isLikeC4ConfigFile)}async scanDirectory(e,t){let n=[];try{let r=await new l().withSymlinks({resolvePaths:!1}).exclude(i).withFullPaths().filter(t).crawl(e.fsPath).withPromise();for(let e of r)n.push({isFile:!0,isDirectory:!1,uri:d.file(e)})}catch(t){P.warn(`Failed to scan directory {path}`,{path:e.fsPath,error:t})}return n}async loadProjectConfig(e){return await c(e)}async writeFile(e,t){let n=y(e.fsPath),r=h(n,{throwIfNoEntry:!1});if(r?.isFile())throw Error(`Cannot create directory ${n} because a file with the same name exists.`);return r||(P.debug(`creating directory {path}`,{path:n}),m(n,{recursive:!0})),P.debug(`writing file {path}`,{path:e.fsPath}),await _(e.fsPath,t,{encoding:`utf-8`})}async deleteFile(e){try{let t=e.fsPath,n=h(t,{throwIfNoEntry:!1});return n?.isFile()||n?.isSymbolicLink()?(await g(t),P.debug(`deleted file {path}`,{path:t}),!0):(P.warn(`deleteFile failed: {path} does not exist, or is not a file`,{path:t}),!1)}catch(t){P.warn(`Failed to delete file ${e.fsPath}`,{error:t})}return!1}};export{N as n,A as r,WithFileSystem as t};
@@ -1,4 +1,4 @@
1
- import{Er as e}from"./utils.mjs";import{h as t}from"./libs/remeda.mjs";import{n}from"./workspace.mjs";import{ifilter as r,invariant as i,isSameHierarchy as a}from"@likec4/core/utils";import{loggable as o}from"@likec4/log";import{invariant as s}from"@likec4/core";import{isDeploymentNodeModel as c,modelConnection as l}from"@likec4/core/model";import{URI as u}from"vscode-uri";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=e.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:o(t)}],isError:!0}}})}var b=`1.50.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){s(e.findElement(t),`Element "${t}" not found`);let o=new Set,c={},l=0,u=!1,d=[{elementId:t,depth:0}];for(;d.length>0;){let{elementId:t,depth:s}=d.shift();if(s>i||o.has(t))continue;if(o.size>=a){u=!0;break}let f=e.findElement(t);if(!f)continue;o.add(t),l=Math.max(l,s);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:s};for(let e of p)o.has(e.elementId)||d.push({elementId:e.elementId,depth:s+1})}for(let e of Object.values(c))e.neighbors=e.neighbors.filter(e=>e.elementId in c);return{target:t,totalNodes:o.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(n.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:u.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:`
1
+ import{Tr as e}from"./utils.mjs";import{n as t}from"./workspace.mjs";import{ifilter as n,invariant as r,isSameHierarchy as i}from"@likec4/core/utils";import{loggable as a}from"@likec4/log";import{keys as o}from"remeda";import{invariant as s}from"@likec4/core";import{isDeploymentNodeModel as c,modelConnection as l}from"@likec4/core/model";import{URI as u}from"vscode-uri";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=e.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.52.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){s(e.findElement(t),`Element "${t}" not found`);let o=new Set,c={},l=0,u=!1,d=[{elementId:t,depth:0}];for(;d.length>0;){let{elementId:t,depth:s}=d.shift();if(s>i||o.has(t))continue;if(o.size>=a){u=!0;break}let f=e.findElement(t);if(!f)continue;o.add(t),l=Math.max(l,s);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:s};for(let e of p)o.has(e.elementId)||d.push({elementId:e.elementId,depth:s+1})}for(let e of Object.values(c))e.neighbors=e.neighbors.filter(e=>e.elementId in c);return{target:t,totalNodes:o.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(t.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:u.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
 
@@ -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(a(t.element1,t.element2))throw Error(`No relationships possible between parent-child`);let r=[],o=await e.computedModel(n),s=o.findElement(t.element1);i(s,`Element "${t.element1}" not found in project "${n}"`);let c=o.findElement(t.element2);i(c,`Element "${t.element2}" not found in project "${n}"`);let u=mkLocate(e,n),d=l.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;r.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:u({relation:e.id})})}return{found:r}}),F=likec4Tool({name:`list-projects`,description:`
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 u=mkLocate(e,n),d=l.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:u({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:
@@ -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,n)=>{let r=e.projectsManager.ensureProjectId(n.project),i=e.project(r),a=await e.computedModel(r);return{title:i.title,folder:i.folder.fsPath,sources:i.documents?.map(e=>e.fsPath)??[],config:serializeConfig(i.config),specification:{elementKinds:t(a.specification.elements),relationshipKinds:t(a.specification.relationships),deploymentKinds:t(a.specification.deployments),tags:[...a.tags],metadataKeys:a.specification.metadataKeys??[]},elements:[...a.elements()].filter(e=>!e.imported).map(e=>({id:e.id,kind:e.kind,title:e.title,tags:[...e.tags]})),deployments:[...a.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:[...a.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:`
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:o(i.specification.elements),relationshipKinds:o(i.specification.relationships),deploymentKinds:o(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:
@@ -1051,7 +1051,7 @@ Example response:
1051
1051
  }
1052
1052
  ]
1053
1053
  }
1054
- `,inputSchema:{search:f.string().min(2,`Search must be at least 2 characters long`)},outputSchema:{total:f.number(),found:Q}},async(e,t)=>{let n=e.projects(),i=[],a=t.search.toLowerCase(),predicate;a.startsWith(`kind:`)?(a=a.slice(5),y.debug(`search by kind: {search}`,{search:a}),predicate=e=>e.kind.toLowerCase()===a):a.startsWith(`shape:`)?(a=a.slice(6),y.debug(`search by shape: {search}`,{search:a}),predicate=e=>e.shape.toLowerCase()===a):a.startsWith(`meta:`)?(a=a.slice(5),y.debug(`search by metadata: {search}`,{search:a}),predicate=e=>!!e.getMetadata(a)):a.startsWith(`#`)?(a=a.slice(1),y.debug(`search by tag: {search}`,{search:a}),predicate=e=>e.tags.some(e=>e.toLowerCase().includes(a))):(y.debug(`search by id/title: {search}`,{search:a}),predicate=e=>e.id.toLowerCase().includes(a)||e.title.toLowerCase().includes(a));for(let t of n)try{let n=await e.computedModel(t.id);for(let e of r(n.elements(),e=>!e.imported&&predicate(e)))i.push({type:`element`,project:t.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:includedInViews(e.views())});for(let e of r(n.deployment.nodes(),predicate))i.push({type:`deployment-node`,project:t.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:includedInViews(e.views())})}catch(e){y.error(`Error searching in project ${t.id}:`,{error:e})}return{total:i.length,found:i.slice(0,20)}}),ee=f.object({id:f.string().describe(`Element id (FQN)`),name:f.string().describe(`Element name`),kind:f.string().describe(`Element kind`),title:f.string().describe(`Human-readable title`),depth:f.number().describe(`Depth relative to the root element (1 = direct child)`),tags:f.array(f.string()).describe(`Assigned tags`),metadata:f.record(f.union([f.string(),f.array(f.string())])).describe(`Element metadata`),childCount:f.number().describe(`Number of direct children`),incomingCount:f.number().describe(`Number of incoming relationships`),outgoingCount:f.number().describe(`Number of outgoing relationships`)}),te=likec4Tool({name:`subgraph-summary`,description:`
1054
+ `,inputSchema:{search:f.string().min(2,`Search must be at least 2 characters long`)},outputSchema:{total:f.number(),found:Q}},async(e,t)=>{let r=e.projects(),i=[],a=t.search.toLowerCase(),predicate;a.startsWith(`kind:`)?(a=a.slice(5),y.debug(`search by kind: {search}`,{search:a}),predicate=e=>e.kind.toLowerCase()===a):a.startsWith(`shape:`)?(a=a.slice(6),y.debug(`search by shape: {search}`,{search:a}),predicate=e=>e.shape.toLowerCase()===a):a.startsWith(`meta:`)?(a=a.slice(5),y.debug(`search by metadata: {search}`,{search:a}),predicate=e=>!!e.getMetadata(a)):a.startsWith(`#`)?(a=a.slice(1),y.debug(`search by tag: {search}`,{search:a}),predicate=e=>e.tags.some(e=>e.toLowerCase().includes(a))):(y.debug(`search by id/title: {search}`,{search:a}),predicate=e=>e.id.toLowerCase().includes(a)||e.title.toLowerCase().includes(a));for(let t of r)try{let r=await e.computedModel(t.id);for(let e of n(r.elements(),e=>!e.imported&&predicate(e)))i.push({type:`element`,project:t.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:includedInViews(e.views())});for(let e of n(r.deployment.nodes(),predicate))i.push({type:`deployment-node`,project:t.id,id:e.id,name:e.name,kind:e.kind,title:e.title,technology:e.technology,shape:e.shape,tags:[...e.tags],metadata:e.getMetadata(),includedInViews:includedInViews(e.views())})}catch(e){y.error(`Error searching in project ${t.id}:`,{error:e})}return{total:i.length,found:i.slice(0,20)}}),ee=f.object({id:f.string().describe(`Element id (FQN)`),name:f.string().describe(`Element name`),kind:f.string().describe(`Element kind`),title:f.string().describe(`Human-readable title`),depth:f.number().describe(`Depth relative to the root element (1 = direct child)`),tags:f.array(f.string()).describe(`Assigned tags`),metadata:f.record(f.union([f.string(),f.array(f.string())])).describe(`Element metadata`),childCount:f.number().describe(`Number of direct children`),incomingCount:f.number().describe(`Number of incoming relationships`),outgoingCount:f.number().describe(`Number of outgoing relationships`)}),te=likec4Tool({name:`subgraph-summary`,description:`
1055
1055
  Get a compact, table-friendly summary of all descendants of a parent element.
1056
1056
  Returns each descendant with its depth, metadata, tags, and relationship counts in a single call.
1057
1057
  Much more efficient than calling read-element for each descendant individually.
@@ -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,...t,capabilities:{tools:{},logging:{},...t?.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=t=>{e.error(o(t))},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(o(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:a=!1,port:s=t}=e.configuration.mcp;if(!a){n.stop();return}Promise.resolve().then(()=>n.start(s)).then(()=>{i?.telemetry?.logEvent({eventName:`mcp-server-started`,mcpPort:s})}).catch(e=>{let t=o(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};
1154
+ `,enforceStrictCapabilities:!0,...t,capabilities:{tools:{},logging:{},...t?.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=t=>{e.error(a(t))},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,9 +2,9 @@ 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 { CompletionItemKind, Diagnostic, DocumentSymbol, FormattingOptions, Hover, Location, Range, SemanticTokens, SemanticTokensDelta, SymbolKind, TextEdit } from "vscode-languageserver-types";
5
+ import { CompletionItemKind, Diagnostic, DocumentSymbol, FormattingOptions, Hover, Location, Range, SymbolKind, TextEdit } from "vscode-languageserver-types";
6
6
  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
- import { GraphvizLayouter, QueueGraphvizLayoter } from "@likec4/layouts";
7
+ import { GraphvizLayouter, GraphvizPort, QueueGraphvizLayoter } from "@likec4/layouts";
8
8
  import * as c4 from "@likec4/core";
9
9
  import { ComputedView, DiagramView, LayoutType, LayoutedView, NonEmptyArray, NonEmptyReadonlyArray, ProjectId, Tag, UnknownComputed, UnknownLayouted, UnknownParsed, ViewChange, ViewId } from "@likec4/core";
10
10
  import { AdhocViewPredicate, LayoutedProjectsView as LayoutedProjectsView$1 } from "@likec4/core/compute-view";
@@ -13,9 +13,9 @@ import { IncludeConfig, LikeC4ProjectConfig, LikeC4ProjectConfigInput } from "@l
13
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
- import { CancellationToken as CancellationToken$1, CodeAction, CodeActionParams, Command, SemanticTokensDeltaParams, SemanticTokensParams, SemanticTokensRangeParams } from "vscode-languageserver-protocol";
16
+ import { CodeAction, CodeActionParams, Command } from "vscode-languageserver-protocol";
17
17
  import { Fqn as Fqn$1, GuardedBy, LayoutedView as LayoutedView$1, ProjectId as ProjectId$1, ViewId as ViewId$1 } from "@likec4/core/types";
18
- import { CancellationToken as CancellationToken$2 } from "vscode-jsonrpc";
18
+ import { CancellationToken as CancellationToken$1 } from "vscode-jsonrpc";
19
19
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
20
20
  import * as type_fest0 from "type-fest";
21
21
  import { ConditionalPick, MergeExclusive, Simplify, Tagged, ValueOf, Writable } from "type-fest";
@@ -45,8 +45,8 @@ declare class LikeC4DocumentationProvider extends JSDocDocumentationProvider {
45
45
  //#region src/workspace/ProjectsManager.d.ts
46
46
  type DocOrUri = LangiumDocument | string | URI;
47
47
  /**
48
- * A tagged string that represents a project folder URI
49
- * Always has trailing slash.
48
+ * A tagged string that represents a project folder URI (with trailing slash).
49
+ * Used in `startsWith` checks to determine if a document belongs to a project.
50
50
  */
51
51
  type ProjectFolder = Tagged<string, 'ProjectFolder'>;
52
52
  declare function ProjectFolder(folder: URI | string): ProjectFolder;
@@ -167,6 +167,7 @@ declare class ProjectsManager {
167
167
  private getWorkspaceFolder;
168
168
  private notifyListeners;
169
169
  private updateIncludesExcludes;
170
+ private warnIfConfigOverride;
170
171
  }
171
172
  //#endregion
172
173
  //#region src/filesystem/types.d.ts
@@ -324,7 +325,7 @@ interface LikeC4MCPServerModuleContext {
324
325
  }
325
326
  //#endregion
326
327
  //#region src/generated/ast.d.ts
327
- type AnyProperty = DynamicViewProperty | ElementProperty | RelationProperty | StringProperty | ViewProperty;
328
+ type AnyProperty = DynamicViewProperty | ElementProperty | NavigateToProperty | NotationProperty | NotesProperty | RelationProperty | RelationshipStyleProperty | StringProperty | StyleProperty | ViewProperty;
328
329
  declare const AnyProperty = "AnyProperty";
329
330
  type ArrowType = 'crow' | 'diamond' | 'dot' | 'none' | 'normal' | 'odiamond' | 'odot' | 'onormal' | 'open' | 'vee';
330
331
  type BorderStyleValue = 'none' | LineOptions;
@@ -1699,7 +1700,6 @@ interface ParsedAstElementView {
1699
1700
  tags: c4.NonEmptyArray<c4.Tag> | null;
1700
1701
  links: c4.NonEmptyArray<c4.Link> | null;
1701
1702
  rules: c4.ElementViewRule[];
1702
- manualLayout?: c4.ViewManualLayout;
1703
1703
  }
1704
1704
  interface ParsedAstDynamicView {
1705
1705
  id: c4.ViewId;
@@ -1711,7 +1711,6 @@ interface ParsedAstDynamicView {
1711
1711
  steps: c4.DynamicViewStep[];
1712
1712
  rules: Array<c4.DynamicViewRule>;
1713
1713
  variant: c4.DynamicViewDisplayVariant | undefined;
1714
- manualLayout?: c4.ViewManualLayout;
1715
1714
  }
1716
1715
  interface ParsedAstDeploymentView {
1717
1716
  id: c4.ViewId;
@@ -1721,7 +1720,6 @@ interface ParsedAstDeploymentView {
1721
1720
  tags: c4.NonEmptyArray<c4.Tag> | null;
1722
1721
  links: c4.NonEmptyArray<c4.Link> | null;
1723
1722
  rules: Array<c4.DeploymentViewRule>;
1724
- manualLayout?: c4.ViewManualLayout;
1725
1723
  }
1726
1724
  type ParsedAstView = ParsedAstElementView | ParsedAstDynamicView | ParsedAstDeploymentView;
1727
1725
  interface AstNodeDescriptionWithFqn extends AstNodeDescription {
@@ -2075,9 +2073,9 @@ declare class LastSeenArtifacts {
2075
2073
  //#region src/model/model-builder.d.ts
2076
2074
  type ModelParsedListener = (docs: URI[]) => void;
2077
2075
  interface LikeC4ModelBuilder extends Disposable {
2078
- parseModel(projectId?: ProjectId | undefined, cancelToken?: CancellationToken$2): Promise<LikeC4Model<UnknownParsed> | null>;
2076
+ parseModel(projectId?: ProjectId | undefined, cancelToken?: CancellationToken$1): Promise<LikeC4Model<UnknownParsed> | null>;
2079
2077
  unsafeSyncComputeModel(projectId: ProjectId): LikeC4Model<UnknownComputed>;
2080
- computeModel(projectId?: ProjectId | undefined, cancelToken?: CancellationToken$2): Promise<LikeC4Model<UnknownComputed>>;
2078
+ computeModel(projectId?: ProjectId | undefined, cancelToken?: CancellationToken$1): Promise<LikeC4Model<UnknownComputed>>;
2081
2079
  onModelParsed(callback: ModelParsedListener): Disposable;
2082
2080
  clearCache(): void;
2083
2081
  }
@@ -2231,8 +2229,56 @@ interface LikeC4Views {
2231
2229
  adhocView(predicates: AdhocViewPredicate[], projectId?: ProjectId | undefined): Promise<LayoutedView>;
2232
2230
  }
2233
2231
  //#endregion
2232
+ //#region src/views/index.d.ts
2233
+ interface LikeC4ViewsModuleContext {
2234
+ graphviz: (services: LikeC4Services) => GraphvizPort;
2235
+ }
2236
+ declare const WithWasmGraphviz: LikeC4ViewsModuleContext;
2237
+ declare function WithGraphviz(graphviz: GraphvizPort): LikeC4ViewsModuleContext;
2238
+ //#endregion
2239
+ //#region src/configureLogger.d.ts
2240
+ type ConfigureLanguageServerLoggerOptions = {
2241
+ /**
2242
+ * The LSP connection if available
2243
+ * (used by Telemetry)
2244
+ */
2245
+ lspConnection?: Connection | undefined;
2246
+ /**
2247
+ * Whether to use stderr for logging instead of stdout.
2248
+ * @default false
2249
+ */
2250
+ useStdErr?: boolean;
2251
+ /**
2252
+ * The log level to use.
2253
+ * @default 'warning'
2254
+ */
2255
+ logLevel?: 'trace' | 'debug' | 'info' | 'warning' | 'error' | undefined;
2256
+ /**
2257
+ * @default true
2258
+ */
2259
+ enableTelemetry?: boolean;
2260
+ /**
2261
+ * Enable non-blocking logging (async).
2262
+ * @default false
2263
+ */
2264
+ nonBlocking?: boolean;
2265
+ /**
2266
+ * Whether to use colors in logging.
2267
+ * @default false
2268
+ */
2269
+ colors?: boolean;
2270
+ };
2271
+ declare function configureLanguageServerLogger({
2272
+ lspConnection: connection,
2273
+ enableTelemetry,
2274
+ useStdErr,
2275
+ logLevel: lowestLevel,
2276
+ nonBlocking,
2277
+ colors
2278
+ }?: ConfigureLanguageServerLoggerOptions): void;
2279
+ //#endregion
2234
2280
  //#region src/index.d.ts
2235
- type StartLanguageServerOptions = {
2281
+ interface StartLanguageServerOptions {
2236
2282
  /**
2237
2283
  * The Language Server Protocol connection to use.
2238
2284
  */
@@ -2242,10 +2288,6 @@ type StartLanguageServerOptions = {
2242
2288
  * @default true
2243
2289
  */
2244
2290
  enableWatcher?: boolean;
2245
- /**
2246
- * @default true
2247
- */
2248
- enableTelemetry?: boolean;
2249
2291
  /**
2250
2292
  * Whether to enable the MCP server.
2251
2293
  * @default 'sse'
@@ -2258,7 +2300,25 @@ type StartLanguageServerOptions = {
2258
2300
  * @default true
2259
2301
  */
2260
2302
  enableManualLayouts?: boolean;
2261
- };
2303
+ /**
2304
+ * Whether to use the `dot` binary for layouting or the WebAssembly version.
2305
+ * If {@link connection} is set, {@link ConfigurableLayouter} is started
2306
+ * and this option controls the default layouter implementation used by it.
2307
+ *
2308
+ * @default 'wasm'
2309
+ */
2310
+ graphviz?: 'wasm' | 'binary';
2311
+ /**
2312
+ * Whether to configure the logger.
2313
+ *
2314
+ * - `false` - don't configure the logger
2315
+ * - `'console'` - configure the logger with console sink
2316
+ * - `'stderr'` - configure the logger with stderr sink
2317
+ *
2318
+ * @default false
2319
+ */
2320
+ configureLogger?: false | 'console' | 'stderr';
2321
+ }
2262
2322
  declare function startLanguageServer$1(options?: StartLanguageServerOptions): {
2263
2323
  shared: LikeC4SharedServices;
2264
2324
  likec4: LikeC4Services;
@@ -3035,28 +3095,28 @@ interface LikeC4LanguageServices {
3035
3095
  * Computes and layouts projects overview - a special diagram
3036
3096
  * that shows all projects and their relationships
3037
3097
  */
3038
- projectsOverview(cancelToken?: CancellationToken$2): Promise<LayoutedProjectsView$1>;
3098
+ projectsOverview(cancelToken?: CancellationToken$1): Promise<LayoutedProjectsView$1>;
3039
3099
  /**
3040
3100
  * Returns {@link LikeC4Model} of the specified project, with computed views {@link ComputedView}
3041
3101
  * Not ready for rendering, but enough to traverse model. Much faster than {@link layoutedModel}
3042
3102
  *
3043
3103
  * If no {@link project} is specified, returns for default project
3044
3104
  */
3045
- computedModel(project?: ProjectId | undefined, cancelToken?: CancellationToken$2): Promise<LikeC4Model<UnknownComputed>>;
3105
+ computedModel(project?: ProjectId | undefined, cancelToken?: CancellationToken$1): Promise<LikeC4Model<UnknownComputed>>;
3046
3106
  /**
3047
3107
  * Returns {@link LikeC4Model} of the specified project, with layouted views {@link LayoutedView}
3048
3108
  * Ready for rendering. Applies manual layouts if available.
3049
3109
  *
3050
3110
  * If no {@link project} is specified, returns for default project
3051
3111
  */
3052
- layoutedModel(project?: ProjectId | undefined, cancelToken?: CancellationToken$2): Promise<LikeC4Model<UnknownLayouted>>;
3112
+ layoutedModel(project?: ProjectId | undefined, cancelToken?: CancellationToken$1): Promise<LikeC4Model<UnknownLayouted>>;
3053
3113
  /**
3054
3114
  * Returns diagrams (i.e. layouted views {@link LayoutedView}) for the specified project
3055
3115
  * Applies manual layouts if available.
3056
3116
  *
3057
3117
  * If no {@link project} is specified, returns diagrams for default project
3058
3118
  */
3059
- diagrams(project?: ProjectId | undefined, cancelToken?: CancellationToken$2): Promise<LayoutedView[]>;
3119
+ diagrams(project?: ProjectId | undefined, cancelToken?: CancellationToken$1): Promise<LayoutedView[]>;
3060
3120
  getErrors(): Array<{
3061
3121
  message: string;
3062
3122
  line: number;
@@ -3067,8 +3127,43 @@ interface LikeC4LanguageServices {
3067
3127
  * Returns the location of the specified element, relation, view or deployment element
3068
3128
  */
3069
3129
  locate(params: Locate.Params): Locate.Res;
3130
+ /**
3131
+ * Formats documents and returns a map of document URI → formatted source text.
3132
+ *
3133
+ * Target selection uses union semantics:
3134
+ * - No options: formats all documents across all projects
3135
+ * - `projectIds`: includes all documents from those projects
3136
+ * - `documentUris`: includes specific documents
3137
+ * - Both: formats the union (deduplicated)
3138
+ */
3139
+ format(options?: FormatOptions): Promise<Map<string, string>>;
3070
3140
  dispose(): Promise<void>;
3071
3141
  }
3142
+ /**
3143
+ * Options for {@link LikeC4LanguageServices.format}.
3144
+ *
3145
+ * Target selection uses union semantics:
3146
+ * - Omit both `projectIds` and `documentUris` to format **all** documents.
3147
+ * - Provide `projectIds` to include all documents from those projects.
3148
+ * - Provide `documentUris` to include specific documents.
3149
+ * - Provide both to format the **union** of project documents and specified documents.
3150
+ */
3151
+ interface FormatOptions {
3152
+ /** Include all documents from these projects. */
3153
+ projectIds?: ReadonlyArray<ProjectId>;
3154
+ /** Include these specific documents (by URI string). */
3155
+ documentUris?: ReadonlyArray<string>;
3156
+ /** Size of a tab in spaces (default: 2). */
3157
+ tabSize?: number;
3158
+ /** Prefer spaces over tabs (default: true). */
3159
+ insertSpaces?: boolean;
3160
+ /** Trim trailing whitespace on a line. */
3161
+ trimTrailingWhitespace?: boolean;
3162
+ /** Insert a newline character at the end of the file if one does not exist. */
3163
+ insertFinalNewline?: boolean;
3164
+ /** Trim all newlines after the final newline at the end of the file. */
3165
+ trimFinalNewlines?: boolean;
3166
+ }
3072
3167
  //#endregion
3073
3168
  //#region src/lsp/CodeLensProvider.d.ts
3074
3169
  declare class LikeC4CodeLensProvider implements CodeLensProvider {
@@ -3181,7 +3276,7 @@ declare class LikeC4CodeActionProvider implements CodeActionProvider {
3181
3276
  * @throws `OperationCancelled` if cancellation is detected during execution
3182
3277
  * @throws `ResponseError` if an error is detected that should be sent as response to the client
3183
3278
  */
3184
- getCodeActions(document: LangiumDocument, params: CodeActionParams): CommandOrCodeAction[] | undefined;
3279
+ getCodeActions(_document: LangiumDocument, _params: CodeActionParams): CommandOrCodeAction[] | undefined;
3185
3280
  }
3186
3281
  //#endregion
3187
3282
  //#region src/lsp/SemanticTokenProvider.d.ts
@@ -3190,10 +3285,6 @@ declare class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider
3190
3285
  private rules;
3191
3286
  constructor(services: LikeC4Services);
3192
3287
  protected initRules(): void;
3193
- semanticHighlight(document: LangiumDocument, params: SemanticTokensParams, cancelToken?: CancellationToken$1): Promise<SemanticTokens>;
3194
- semanticHighlightRange(document: LangiumDocument, params: SemanticTokensRangeParams, cancelToken?: CancellationToken$1): Promise<SemanticTokens>;
3195
- semanticHighlightDelta(document: LangiumDocument, params: SemanticTokensDeltaParams, cancelToken?: CancellationToken$1): Promise<SemanticTokens | SemanticTokensDelta>;
3196
- protected ensureState(document: LangiumDocument, cancelToken: CancellationToken$1): Promise<void>;
3197
3288
  protected highlightElement(node: AstNode, acceptor: SemanticTokenAcceptor): void | undefined | 'prune';
3198
3289
  private highlightNameAndKind;
3199
3290
  private highlightView;
@@ -3226,7 +3317,6 @@ declare class NodeKindProvider$1 implements NodeKindProvider {
3226
3317
  declare class WorkspaceSymbolProvider extends DefaultWorkspaceSymbolProvider {}
3227
3318
  //#endregion
3228
3319
  //#region src/module.d.ts
3229
- type LanguageServicesContext = Omit<DefaultSharedModuleContext, 'fileSystemProvider'> & FileSystemModuleContext & LikeC4MCPServerModuleContext & LikeC4ManualLayoutsModuleContext;
3230
3320
  interface LikeC4AddedSharedServices {
3231
3321
  lsp: {
3232
3322
  NodeKindProvider: NodeKindProvider$1;
@@ -3244,6 +3334,7 @@ interface LikeC4AddedSharedServices {
3244
3334
  };
3245
3335
  }
3246
3336
  type LikeC4SharedServices = LangiumSharedServices & LikeC4AddedSharedServices;
3337
+ type LikeC4SharedModuleContext = Omit<DefaultSharedModuleContext, 'fileSystemProvider'> & FileSystemModuleContext & LikeC4ManualLayoutsModuleContext;
3247
3338
  /**
3248
3339
  * Declaration of custom services - add your own service classes here.
3249
3340
  */
@@ -3262,6 +3353,7 @@ interface LikeC4AddedServices {
3262
3353
  likec4: {
3263
3354
  LanguageServices: LikeC4LanguageServices;
3264
3355
  Views: LikeC4Views;
3356
+ Graphviz: GraphvizPort;
3265
3357
  Layouter: QueueGraphvizLayoter;
3266
3358
  DeploymentsIndex: DeploymentsIndex;
3267
3359
  FqnIndex: FqnIndex;
@@ -3293,12 +3385,14 @@ interface LikeC4AddedServices {
3293
3385
  };
3294
3386
  }
3295
3387
  type LikeC4Services = LangiumServices & LikeC4AddedServices;
3388
+ type LikeC4ServicesContext = LikeC4MCPServerModuleContext & LikeC4ViewsModuleContext;
3296
3389
  /**
3297
3390
  * Most probably you don't need to use this function directly.
3298
3391
  * Use {@link createLanguageServices} instead.
3299
3392
  * @internal
3300
3393
  */
3301
- declare function createLikeC4Module(context: LikeC4MCPServerModuleContext): Module<LikeC4Services, PartialLangiumServices & LikeC4AddedServices>;
3394
+ declare function createLikeC4Module(context: LikeC4ServicesContext): Module<LikeC4Services, PartialLangiumServices & LikeC4AddedServices>;
3395
+ type LanguageServicesContext = LikeC4SharedModuleContext & LikeC4ServicesContext;
3302
3396
  /**
3303
3397
  * Create and initialize likec4 language services with the given context
3304
3398
  * @example
@@ -3344,4 +3438,4 @@ declare function createLanguageServices<I1, I2, I3, I extends I1 & I2 & I3 & Lik
3344
3438
  */
3345
3439
  declare function createSharedServices(context?: Partial<LanguageServicesContext>): LikeC4SharedServices;
3346
3440
  //#endregion
3347
- export { FileNode as A, ProjectsManager as B, LikeC4MCPServerModuleContext as C, NoFileSystem as D, WithFileSystem as E, LikeC4ManualLayouts as F, LikeC4ManualLayoutsModuleContext as I, ManualLayoutsSnapshot as L, FileSystemProvider$1 as M, FileSystemWatcher as N, NoFileSystemWatcher as O, FileSystemWatcherModuleContext as P, Project as R, LikeC4MCPServerFactory as S, WithChokidarWatcher as T, LikeC4ModelBuilder as _, createLanguageServices as a, LangiumDocuments as b, LikeC4LanguageServices as c, startLanguageServer$1 as d, LikeC4Views as f, ViewLocateResult as g, LikeC4ModelLocator as h, LikeC4SharedServices as i, FileSystemModuleContext as j, NoLikeC4ManualLayouts as k, DocumentParser as l, NoMCPServer as m, LikeC4AddedServices as n, createLikeC4Module as o, WithMCPServer as p, LikeC4Services as r, createSharedServices as s, LanguageServicesContext as t, LikeC4ModelParser as u, FqnIndex as v, WithLikeC4ManualLayouts as w, LikeC4MCPServer as x, LikeC4WorkspaceManager as y, ProjectData as z };
3441
+ export { LikeC4MCPServerFactory as A, FileSystemProvider$1 as B, LikeC4ModelLocator as C, LikeC4WorkspaceManager as D, FqnIndex as E, NoFileSystem as F, ManualLayoutsSnapshot as G, FileSystemWatcherModuleContext as H, NoFileSystemWatcher as I, ProjectsManager as J, Project as K, NoLikeC4ManualLayouts as L, WithLikeC4ManualLayouts as M, WithChokidarWatcher as N, LangiumDocuments as O, WithFileSystem as P, FileNode as R, NoMCPServer as S, LikeC4ModelBuilder as T, LikeC4ManualLayouts as U, FileSystemWatcher as V, LikeC4ManualLayoutsModuleContext as W, LikeC4ViewsModuleContext as _, LikeC4SharedModuleContext as a, LikeC4Views as b, createLikeC4Module as c, LikeC4LanguageServices as d, DocumentParser as f, configureLanguageServerLogger as g, ConfigureLanguageServerLoggerOptions as h, LikeC4ServicesContext as i, LikeC4MCPServerModuleContext as j, LikeC4MCPServer as k, createSharedServices as l, startLanguageServer$1 as m, LikeC4AddedServices as n, LikeC4SharedServices as o, LikeC4ModelParser as p, ProjectData as q, LikeC4Services as r, createLanguageServices as s, LanguageServicesContext as t, FormatOptions as u, WithGraphviz as v, ViewLocateResult as w, WithMCPServer as x, WithWasmGraphviz as y, FileSystemModuleContext as z };