@orchestra-mcp/editor 0.2.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.
@@ -0,0 +1,145 @@
1
+ // src/CodeEditor/lsp-bridge.ts
2
+ var _requestId = 1;
3
+ async function connectLanguageServer(monaco, editor, languageId, wsUrl) {
4
+ const ws = new WebSocket(wsUrl);
5
+ const pending = /* @__PURE__ */ new Map();
6
+ const disposables = [];
7
+ function send(msg) {
8
+ if (ws.readyState === WebSocket.OPEN) {
9
+ ws.send(JSON.stringify(msg));
10
+ }
11
+ }
12
+ function request(method, params) {
13
+ const id = _requestId++;
14
+ send({ jsonrpc: "2.0", id, method, params });
15
+ return new Promise((resolve, reject) => {
16
+ pending.set(id, { resolve, reject });
17
+ });
18
+ }
19
+ function notify(method, params) {
20
+ send({ jsonrpc: "2.0", method, params });
21
+ }
22
+ return new Promise((resolve, reject) => {
23
+ const timeout = setTimeout(() => {
24
+ ws.close();
25
+ reject(new Error(`LSP server not reachable at ${wsUrl}`));
26
+ }, 5e3);
27
+ ws.onerror = () => {
28
+ clearTimeout(timeout);
29
+ reject(new Error(`LSP WebSocket error for ${languageId}`));
30
+ };
31
+ ws.onmessage = (event) => {
32
+ try {
33
+ const msg = JSON.parse(event.data);
34
+ if (msg.id !== void 0 && pending.has(msg.id)) {
35
+ const p = pending.get(msg.id);
36
+ pending.delete(msg.id);
37
+ if (msg.error) p.reject(msg.error);
38
+ else p.resolve(msg.result);
39
+ } else if (msg.method === "textDocument/publishDiagnostics") {
40
+ const params = msg.params;
41
+ if (params) handleDiagnostics(monaco, params.uri, params.diagnostics);
42
+ }
43
+ } catch {
44
+ }
45
+ };
46
+ ws.onopen = async () => {
47
+ clearTimeout(timeout);
48
+ await request("initialize", {
49
+ processId: null,
50
+ clientInfo: { name: "orchestra-mcp", version: "1.0" },
51
+ capabilities: {
52
+ textDocument: {
53
+ hover: { contentFormat: ["markdown", "plaintext"] },
54
+ completion: { completionItem: { snippetSupport: true } },
55
+ publishDiagnostics: {}
56
+ }
57
+ },
58
+ rootUri: null
59
+ });
60
+ notify("initialized", {});
61
+ const model = editor.getModel();
62
+ if (model) {
63
+ notify("textDocument/didOpen", {
64
+ textDocument: {
65
+ uri: model.uri.toString(),
66
+ languageId,
67
+ version: model.getVersionId(),
68
+ text: model.getValue()
69
+ }
70
+ });
71
+ const changeDisposable = model.onDidChangeContent((e) => {
72
+ notify("textDocument/didChange", {
73
+ textDocument: { uri: model.uri.toString(), version: model.getVersionId() },
74
+ contentChanges: e.changes.map((c) => ({
75
+ range: c.range,
76
+ rangeLength: c.rangeLength,
77
+ text: c.text
78
+ }))
79
+ });
80
+ });
81
+ disposables.push(changeDisposable);
82
+ const hoverDisposable = monaco.languages.registerHoverProvider(languageId, {
83
+ provideHover: async (_m, position) => {
84
+ try {
85
+ const result = await request("textDocument/hover", {
86
+ textDocument: { uri: model.uri.toString() },
87
+ position: { line: position.lineNumber - 1, character: position.column - 1 }
88
+ });
89
+ if (!result?.contents) return null;
90
+ const contents = Array.isArray(result.contents) ? result.contents.map((c) => typeof c === "string" ? { value: c } : c) : [typeof result.contents === "string" ? { value: result.contents } : result.contents];
91
+ return { contents };
92
+ } catch {
93
+ return null;
94
+ }
95
+ }
96
+ });
97
+ disposables.push(hoverDisposable);
98
+ const completionDisposable = monaco.languages.registerCompletionItemProvider(languageId, {
99
+ provideCompletionItems: async (_m, position) => {
100
+ try {
101
+ const result = await request("textDocument/completion", {
102
+ textDocument: { uri: model.uri.toString() },
103
+ position: { line: position.lineNumber - 1, character: position.column - 1 }
104
+ });
105
+ const items = Array.isArray(result) ? result : result?.items ?? [];
106
+ return { suggestions: items };
107
+ } catch {
108
+ return { suggestions: [] };
109
+ }
110
+ }
111
+ });
112
+ disposables.push(completionDisposable);
113
+ }
114
+ resolve({
115
+ dispose: () => {
116
+ const model2 = editor.getModel();
117
+ if (model2) {
118
+ notify("textDocument/didClose", {
119
+ textDocument: { uri: model2.uri.toString() }
120
+ });
121
+ }
122
+ disposables.forEach((d) => d.dispose());
123
+ ws.close();
124
+ }
125
+ });
126
+ };
127
+ });
128
+ }
129
+ function handleDiagnostics(monaco, uri, diagnostics) {
130
+ const model = monaco.editor.getModels().find((m) => m.uri.toString() === uri);
131
+ if (!model) return;
132
+ const markers = diagnostics.map((d) => ({
133
+ startLineNumber: d.range.start.line + 1,
134
+ startColumn: d.range.start.character + 1,
135
+ endLineNumber: d.range.end.line + 1,
136
+ endColumn: d.range.end.character + 1,
137
+ severity: d.severity === 1 ? monaco.MarkerSeverity.Error : d.severity === 2 ? monaco.MarkerSeverity.Warning : monaco.MarkerSeverity.Info,
138
+ message: d.message,
139
+ source: d.source
140
+ }));
141
+ monaco.editor.setModelMarkers(model, "lsp", markers);
142
+ }
143
+ export {
144
+ connectLanguageServer
145
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@orchestra-mcp/editor",
3
+ "version": "0.2.0",
4
+ "description": "Code and Markdown editor components for Orchestra MCP",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": ["dist"],
17
+ "publishConfig": { "access": "public" },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/orchestra-mcp/editor"
21
+ },
22
+ "funding": "https://github.com/sponsors/fadymondy",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "@orchestra-mcp/theme": "^0.2.0", "@orchestra-mcp/ui": "^0.2.0", "@orchestra-mcp/widgets": "^0.2.0",
26
+ "@monaco-editor/react": "^4.7.0",
27
+ "monaco-editor": "^0.52.2",
28
+ "html-to-image": "^1.11.13"
29
+ },
30
+ "peerDependencies": {
31
+ "react": ">=18.0.0",
32
+ "react-dom": ">=18.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/react": "^19.0.0",
36
+ "@types/react-dom": "^19.0.0",
37
+ "tsup": "^8.3.5",
38
+ "typescript": "^5.7.2"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
42
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
43
+ "prepublishOnly": "pnpm build"
44
+ },
45
+ "keywords": ["orchestra", "mcp", "react", "components", "editor"]
46
+ }