@elaraai/east-diagnostics 1.0.70 → 1.0.72

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.
@@ -9,8 +9,12 @@ export { createDiagnosticsService } from "./service.js";
9
9
  export type { DiagnosticsService, DiagnosticsServiceOptions } from "./service.js";
10
10
  export { runEastLsp } from "./lsp.js";
11
11
  export type { EastLspOptions } from "./lsp.js";
12
- export { findEastPy, runEastPyLint, renderPythonReview, PYTHON_EAST_IMPORT } from "./python-lint.js";
12
+ export { findEastPy, findEastPyProject, runEastPyLint, runEastPyCheck, renderPythonReview, PYTHON_EAST_IMPORT } from "./python-lint.js";
13
13
  export type { PythonDiagnostic } from "./python-lint.js";
14
+ export { PythonLspProxy } from "./python-lsp-proxy.js";
15
+ export type { PythonLspProxyOptions } from "./python-lsp-proxy.js";
16
+ export { runEastPyLsp } from "./python-lsp-server.js";
17
+ export type { EastPyLspOptions } from "./python-lsp-server.js";
14
18
  export { getEastModule } from "./east-module.js";
15
19
  export type { EastModule } from "./east-module.js";
16
20
  export { reifyEastType } from "./type-reify.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,mBAAmB,YAAY,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACrG,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAClE,YAAY,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,mBAAmB,YAAY,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACxI,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAClE,YAAY,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/src/index.js CHANGED
@@ -2,7 +2,9 @@ export * from "./rules/index.js";
2
2
  export { runEastRules } from "./run.js";
3
3
  export { createDiagnosticsService } from "./service.js";
4
4
  export { runEastLsp } from "./lsp.js";
5
- export { findEastPy, runEastPyLint, renderPythonReview, PYTHON_EAST_IMPORT } from "./python-lint.js";
5
+ export { findEastPy, findEastPyProject, runEastPyLint, runEastPyCheck, renderPythonReview, PYTHON_EAST_IMPORT } from "./python-lint.js";
6
+ export { PythonLspProxy } from "./python-lsp-proxy.js";
7
+ export { runEastPyLsp } from "./python-lsp-server.js";
6
8
  export { getEastModule } from "./east-module.js";
7
9
  export { reifyEastType } from "./type-reify.js";
8
10
  export { rewriteEastAssignability, ASSIGNABILITY_CODES } from "./type-diff-rewrite.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAErG,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAExI,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACvF,OAAO,EAAE,IAAI,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ export interface JsonRpcMessage {
6
+ jsonrpc: "2.0";
7
+ id?: number | string | null;
8
+ method?: string;
9
+ params?: any;
10
+ result?: unknown;
11
+ error?: {
12
+ code: number;
13
+ message: string;
14
+ };
15
+ }
16
+ /** Encode one message as a framed chunk. */
17
+ export declare function frame(message: object): string;
18
+ /**
19
+ * A reader that reassembles framed messages from arbitrary chunks. A
20
+ * malformed frame is skipped, not fatal — a session survives a bad message.
21
+ */
22
+ export declare class FrameReader {
23
+ private readonly onMessage;
24
+ private buffer;
25
+ constructor(onMessage: (message: JsonRpcMessage) => void);
26
+ push(chunk: Buffer): void;
27
+ reset(): void;
28
+ }
29
+ //# sourceMappingURL=jsonrpc-stdio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonrpc-stdio.d.ts","sourceRoot":"","sources":["../../src/jsonrpc-stdio.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,4CAA4C;AAC5C,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED;;;GAGG;AACH,qBAAa,WAAW;IAGV,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,MAAM,CAAmB;gBAEJ,SAAS,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI;IAEzE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IA0BzB,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ /** Encode one message as a framed chunk. */
6
+ export function frame(message) {
7
+ const body = JSON.stringify({ jsonrpc: "2.0", ...message });
8
+ return `Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n${body}`;
9
+ }
10
+ /**
11
+ * A reader that reassembles framed messages from arbitrary chunks. A
12
+ * malformed frame is skipped, not fatal — a session survives a bad message.
13
+ */
14
+ export class FrameReader {
15
+ onMessage;
16
+ buffer = Buffer.alloc(0);
17
+ constructor(onMessage) {
18
+ this.onMessage = onMessage;
19
+ }
20
+ push(chunk) {
21
+ this.buffer = Buffer.concat([this.buffer, chunk]);
22
+ for (;;) {
23
+ const headerEnd = this.buffer.indexOf("\r\n\r\n");
24
+ if (headerEnd < 0)
25
+ return;
26
+ const header = this.buffer.subarray(0, headerEnd).toString("utf8");
27
+ const match = /Content-Length:\s*(\d+)/i.exec(header);
28
+ if (match === null) {
29
+ this.buffer = this.buffer.subarray(headerEnd + 4);
30
+ continue;
31
+ }
32
+ const length = Number(match[1]);
33
+ const bodyStart = headerEnd + 4;
34
+ if (this.buffer.length < bodyStart + length)
35
+ return;
36
+ const body = this.buffer.subarray(bodyStart, bodyStart + length).toString("utf8");
37
+ this.buffer = this.buffer.subarray(bodyStart + length);
38
+ let message;
39
+ try {
40
+ message = JSON.parse(body);
41
+ }
42
+ catch {
43
+ continue;
44
+ }
45
+ this.onMessage(message);
46
+ }
47
+ }
48
+ reset() {
49
+ this.buffer = Buffer.alloc(0);
50
+ }
51
+ }
52
+ //# sourceMappingURL=jsonrpc-stdio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonrpc-stdio.js","sourceRoot":"","sources":["../../src/jsonrpc-stdio.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAeH,4CAA4C;AAC5C,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC5D,OAAO,mBAAmB,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;AAC7E,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,WAAW;IAGO;IAFrB,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEjC,YAA6B,SAA4C;QAA5C,cAAS,GAAT,SAAS,CAAmC;IAAG,CAAC;IAE7E,IAAI,CAAC,KAAa;QAChB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAClD,SAAS,CAAC;YACR,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,SAAS,GAAG,CAAC;gBAAE,OAAO;YAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnE,MAAM,KAAK,GAAG,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;gBAClD,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,MAAM,SAAS,GAAG,SAAS,GAAG,CAAC,CAAC;YAChC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,GAAG,MAAM;gBAAE,OAAO;YACpD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAClF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;YACvD,IAAI,OAAuB,CAAC;YAC5B,IAAI,CAAC;gBACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../../src/lsp.ts"],"names":[],"mappings":"AAMA,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAyDjF,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,oDAAoD;IACpD,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,OAAO,GAAE,cAAmB,GAAG,IAAI,CA4M7D"}
1
+ {"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../../src/lsp.ts"],"names":[],"mappings":"AAMA,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAoDjF,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,oDAAoD;IACpD,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAED,4DAA4D;AAC5D,wBAAgB,UAAU,CAAC,OAAO,GAAE,cAAmB,GAAG,IAAI,CA6K7D"}
package/dist/src/lsp.js CHANGED
@@ -5,7 +5,15 @@
5
5
  import { readFileSync } from "node:fs";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { createDiagnosticsService } from "./service.js";
8
- import { PYTHON_EAST_IMPORT, runEastPyLint } from "./python-lint.js";
8
+ import { frame, FrameReader } from "./jsonrpc-stdio.js";
9
+ // Minimal LSP server over stdio for TypeScript: full-document sync in,
10
+ // publishDiagnostics out, everything backed by the shared DiagnosticsService.
11
+ // Hand-rolled JSON-RPC framing keeps the package dependency-free.
12
+ //
13
+ // Python is NOT this server's: `runEastPyLsp` (python-lsp-server.ts) is its
14
+ // own server with its own lifecycle, registered for `.py` beside this one. A
15
+ // `.py` document that still reaches here — an old manifest — gets an empty
16
+ // publish, never a verdict.
9
17
  const EAST_IMPORT_PATTERN = /@elaraai\//;
10
18
  // Vendored / built / generated trees: never diagnose code the user doesn't own.
11
19
  const SKIP_PATH = /[/\\](node_modules|dist|build|\.venv|\.git)[/\\]/;
@@ -56,30 +64,7 @@ export function runEastLsp(options = {}) {
56
64
  const pending = new Map();
57
65
  let shuttingDown = false;
58
66
  function send(message) {
59
- const body = JSON.stringify({ jsonrpc: "2.0", ...message });
60
- output.write(`Content-Length: ${Buffer.byteLength(body, "utf8")}\r\n\r\n${body}`);
61
- }
62
- /** A python document: the east-py rules, run out of process; published when they answer. */
63
- function publishPython(path, content) {
64
- if (content === undefined || SKIP_PATH.test(path) || !PYTHON_EAST_IMPORT.test(content)) {
65
- send({ method: "textDocument/publishDiagnostics", params: { uri: `file://${path}`, diagnostics: [] } });
66
- return;
67
- }
68
- void runEastPyLint(path, open.has(path) ? content : undefined).then((records) => {
69
- if (records === null)
70
- return; // no east-py answered: say nothing rather than "clean"
71
- const diagnostics = records.map((r) => ({
72
- range: {
73
- start: { line: r.line - 1, character: r.column - 1 },
74
- end: { line: (r.end_line ?? r.line) - 1, character: (r.end_column ?? r.column + 1) - 1 },
75
- },
76
- severity: SEVERITY[r.category] ?? 2,
77
- code: r.rule,
78
- source: "east-py",
79
- message: r.message,
80
- }));
81
- send({ method: "textDocument/publishDiagnostics", params: { uri: `file://${path}`, diagnostics } });
82
- });
67
+ output.write(frame(message));
83
68
  }
84
69
  function publish(path) {
85
70
  const content = open.get(path) ?? (() => {
@@ -90,10 +75,6 @@ export function runEastLsp(options = {}) {
90
75
  return undefined;
91
76
  }
92
77
  })();
93
- if (path.endsWith(".py")) {
94
- publishPython(path, content);
95
- return;
96
- }
97
78
  let diagnostics = [];
98
79
  if (content !== undefined && !SKIP_PATH.test(path) && EAST_IMPORT_PATTERN.test(content)) {
99
80
  const starts = lineStarts(content);
@@ -124,6 +105,13 @@ export function runEastLsp(options = {}) {
124
105
  }
125
106
  }, DEBOUNCE_MS));
126
107
  }
108
+ /** A python document is another server's: clear it, never judge it. */
109
+ function notOurs(path) {
110
+ if (!path.endsWith(".py"))
111
+ return false;
112
+ send({ method: "textDocument/publishDiagnostics", params: { uri: `file://${path}`, diagnostics: [] } });
113
+ return true;
114
+ }
127
115
  function handle(message) {
128
116
  const { method, id, params } = message;
129
117
  if (method === undefined)
@@ -171,16 +159,17 @@ export function runEastLsp(options = {}) {
171
159
  send({ id, result: null });
172
160
  return;
173
161
  case "exit":
174
- exit(shuttingDown ? 0 : 1);
162
+ shutdown(shuttingDown ? 0 : 1);
175
163
  return;
176
164
  case "textDocument/didOpen": {
177
165
  const path = uriToPath(params?.textDocument?.uri ?? "");
178
166
  const text = params?.textDocument?.text;
179
167
  if (path === undefined || typeof text !== "string")
180
168
  return;
169
+ if (notOurs(path))
170
+ return;
181
171
  open.set(path, text);
182
- if (!path.endsWith(".py"))
183
- service.setOverlay(path, text);
172
+ service.setOverlay(path, text);
184
173
  schedule(path);
185
174
  return;
186
175
  }
@@ -189,9 +178,10 @@ export function runEastLsp(options = {}) {
189
178
  const text = params?.contentChanges?.at?.(-1)?.text;
190
179
  if (path === undefined || typeof text !== "string")
191
180
  return;
181
+ if (notOurs(path))
182
+ return;
192
183
  open.set(path, text);
193
- if (!path.endsWith(".py"))
194
- service.setOverlay(path, text);
184
+ service.setOverlay(path, text);
195
185
  schedule(path);
196
186
  return;
197
187
  }
@@ -199,16 +189,16 @@ export function runEastLsp(options = {}) {
199
189
  const path = uriToPath(params?.textDocument?.uri ?? "");
200
190
  if (path === undefined)
201
191
  return;
192
+ if (notOurs(path))
193
+ return;
202
194
  const text = params?.text;
203
195
  if (typeof text === "string") {
204
196
  open.set(path, text);
205
- if (!path.endsWith(".py"))
206
- service.setOverlay(path, text);
197
+ service.setOverlay(path, text);
207
198
  }
208
199
  else {
209
200
  open.delete(path);
210
- if (!path.endsWith(".py"))
211
- service.clearOverlay(path);
201
+ service.clearOverlay(path);
212
202
  }
213
203
  schedule(path);
214
204
  return;
@@ -234,35 +224,19 @@ export function runEastLsp(options = {}) {
234
224
  return;
235
225
  }
236
226
  }
237
- // Content-Length framed reader.
238
- let buffer = Buffer.alloc(0);
239
- input.on("data", (chunk) => {
240
- buffer = Buffer.concat([buffer, chunk]);
241
- for (;;) {
242
- const headerEnd = buffer.indexOf("\r\n\r\n");
243
- if (headerEnd < 0)
244
- return;
245
- const header = buffer.subarray(0, headerEnd).toString("utf8");
246
- const match = /Content-Length:\s*(\d+)/i.exec(header);
247
- if (match === null) {
248
- buffer = buffer.subarray(headerEnd + 4);
249
- continue;
250
- }
251
- const length = Number(match[1]);
252
- const bodyStart = headerEnd + 4;
253
- if (buffer.length < bodyStart + length)
254
- return;
255
- const body = buffer.subarray(bodyStart, bodyStart + length).toString("utf8");
256
- buffer = buffer.subarray(bodyStart + length);
257
- try {
258
- handle(JSON.parse(body));
259
- }
260
- catch {
261
- // Malformed frame — skip it rather than dying mid-session.
262
- }
227
+ const reader = new FrameReader((message) => {
228
+ try {
229
+ handle(message);
230
+ }
231
+ catch {
232
+ // Never let one message kill the server.
263
233
  }
264
234
  });
265
- input.on("close", () => exit(0));
266
- input.on("end", () => exit(0));
235
+ input.on("data", (chunk) => reader.push(chunk));
236
+ // The client going away ends the session: a disconnecting client may never
237
+ // send the `exit` message.
238
+ const shutdown = (code) => exit(code);
239
+ input.on("close", () => shutdown(0));
240
+ input.on("end", () => shutdown(0));
267
241
  }
268
242
  //# sourceMappingURL=lsp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lsp.js","sourceRoot":"","sources":["../../src/lsp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lsp.js","sourceRoot":"","sources":["../../src/lsp.ts"],"names":[],"mappings":"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"}
@@ -15,13 +15,32 @@ export declare const PYTHON_EAST_IMPORT: RegExp;
15
15
  /** The `east-py` command for a file: `EAST_PY_LINT` when set, else the
16
16
  * nearest `.venv` above `fromDir`, else `east-py` on PATH. */
17
17
  export declare function findEastPy(fromDir: string): string;
18
+ /**
19
+ * The directory of the nearest `pyproject.toml` at or above `fromDir` that
20
+ * depends on east-py — what makes a directory an east-py PROJECT, as opposed
21
+ * to a python file that happens to import `east`. A uv workspace root that
22
+ * declares it counts for every member below it, so the walk continues past a
23
+ * member's own pyproject that says nothing. `undefined` when nothing above
24
+ * declares it.
25
+ */
26
+ export declare function findEastPyProject(fromDir: string): string | undefined;
18
27
  /**
19
28
  * The east-py findings for a python file — `""`-free: `[]` when clean,
20
29
  * `null` when no east-py answered (absent, failed, or over `budgetMs`), so
21
30
  * callers can stay silent. `content` (an unsaved buffer) is linted from a
22
31
  * temporary copy under the file's own name; the file itself otherwise.
32
+ * `command` is the `east-py` to run; by default the one `findEastPy` resolves
33
+ * for the file.
34
+ */
35
+ export declare function runEastPyLint(file: string, content?: string, budgetMs?: number, command?: string): Promise<PythonDiagnostic[] | null>;
36
+ /**
37
+ * The BUILD's findings for a python file — `east-py check --format json
38
+ * --only-if-enabled`, the records `runEastPyLint` returns plus the `build` /
39
+ * `import` rules — `[]` when clean or when the project has not opted into the
40
+ * build tier (`[tool.east-py] check = true`), `null` when no east-py answered.
41
+ * A cold subprocess, the right shape for a hook that runs once per file.
23
42
  */
24
- export declare function runEastPyLint(file: string, content?: string, budgetMs?: number): Promise<PythonDiagnostic[] | null>;
43
+ export declare function runEastPyCheck(file: string, budgetMs?: number, command?: string): Promise<PythonDiagnostic[] | null>;
25
44
  /** The findings as the `<east-code-review>` block the plugin injects — `""` when there are none. */
26
45
  export declare function renderPythonReview(records: PythonDiagnostic[]): string;
27
46
  //# sourceMappingURL=python-lint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"python-lint.d.ts","sourceRoot":"","sources":["../../src/python-lint.ts"],"names":[],"mappings":"AAeA,8DAA8D;AAC9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,QAAiE,CAAC;AAEjG;8DAC8D;AAC9D,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYlD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,SAAO,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAiCjH;AAED,oGAAoG;AACpG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAItE"}
1
+ {"version":3,"file":"python-lint.d.ts","sourceRoot":"","sources":["../../src/python-lint.ts"],"names":[],"mappings":"AAeA,8DAA8D;AAC9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,YAAY,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oGAAoG;AACpG,eAAO,MAAM,kBAAkB,QAAiE,CAAC;AAEjG;8DAC8D;AAC9D,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYlD;AAKD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAerE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,SAAO,EAAE,OAAO,SAA4B,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAgCtJ;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAO,EAAE,OAAO,SAA4B,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,CAsBrI;AAED,oGAAoG;AACpG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAItE"}
@@ -3,7 +3,7 @@
3
3
  * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
4
  */
5
5
  import { execFile } from "node:child_process";
6
- import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
6
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
7
7
  import { tmpdir } from "node:os";
8
8
  import { basename, dirname, join } from "node:path";
9
9
  /** A python file that imports east: `import east`, `from east import …`, `from east.x import …`. */
@@ -26,14 +26,44 @@ export function findEastPy(fromDir) {
26
26
  dir = parent;
27
27
  }
28
28
  }
29
+ /** A `pyproject.toml` that declares an east-py distribution as a dependency. */
30
+ const EAST_PY_DEPENDENCY = /elaraai-east-py(?![\w-])|elaraai-east-py-(?:std|io|datascience|cli)(?![\w-])/;
31
+ /**
32
+ * The directory of the nearest `pyproject.toml` at or above `fromDir` that
33
+ * depends on east-py — what makes a directory an east-py PROJECT, as opposed
34
+ * to a python file that happens to import `east`. A uv workspace root that
35
+ * declares it counts for every member below it, so the walk continues past a
36
+ * member's own pyproject that says nothing. `undefined` when nothing above
37
+ * declares it.
38
+ */
39
+ export function findEastPyProject(fromDir) {
40
+ let dir = fromDir;
41
+ for (;;) {
42
+ const candidate = join(dir, "pyproject.toml");
43
+ if (existsSync(candidate)) {
44
+ try {
45
+ if (EAST_PY_DEPENDENCY.test(readFileSync(candidate, "utf-8")))
46
+ return dir;
47
+ }
48
+ catch {
49
+ /* unreadable: keep walking */
50
+ }
51
+ }
52
+ const parent = dirname(dir);
53
+ if (parent === dir)
54
+ return undefined;
55
+ dir = parent;
56
+ }
57
+ }
29
58
  /**
30
59
  * The east-py findings for a python file — `""`-free: `[]` when clean,
31
60
  * `null` when no east-py answered (absent, failed, or over `budgetMs`), so
32
61
  * callers can stay silent. `content` (an unsaved buffer) is linted from a
33
62
  * temporary copy under the file's own name; the file itself otherwise.
63
+ * `command` is the `east-py` to run; by default the one `findEastPy` resolves
64
+ * for the file.
34
65
  */
35
- export function runEastPyLint(file, content, budgetMs = 4000) {
36
- const command = findEastPy(dirname(file));
66
+ export function runEastPyLint(file, content, budgetMs = 4000, command = findEastPy(dirname(file))) {
37
67
  let target = file;
38
68
  let scratch = null;
39
69
  if (content !== undefined) {
@@ -64,6 +94,32 @@ export function runEastPyLint(file, content, budgetMs = 4000) {
64
94
  });
65
95
  });
66
96
  }
97
+ /**
98
+ * The BUILD's findings for a python file — `east-py check --format json
99
+ * --only-if-enabled`, the records `runEastPyLint` returns plus the `build` /
100
+ * `import` rules — `[]` when clean or when the project has not opted into the
101
+ * build tier (`[tool.east-py] check = true`), `null` when no east-py answered.
102
+ * A cold subprocess, the right shape for a hook that runs once per file.
103
+ */
104
+ export function runEastPyCheck(file, budgetMs = 8000, command = findEastPy(dirname(file))) {
105
+ return new Promise((resolveFindings) => {
106
+ execFile(command, ["check", "--format", "json", "--only-if-enabled", file], { timeout: budgetMs, encoding: "utf-8", maxBuffer: 4 * 1024 * 1024, env: { ...process.env, PYTHONIOENCODING: "utf-8" } }, (error, stdout) => {
107
+ if (error !== null && error.code !== 1) {
108
+ resolveFindings(null);
109
+ return;
110
+ }
111
+ let records;
112
+ try {
113
+ records = JSON.parse(stdout);
114
+ }
115
+ catch {
116
+ resolveFindings(null);
117
+ return;
118
+ }
119
+ resolveFindings(Array.isArray(records) ? records : null);
120
+ });
121
+ });
122
+ }
67
123
  /** The findings as the `<east-code-review>` block the plugin injects — `""` when there are none. */
68
124
  export function renderPythonReview(records) {
69
125
  if (records.length === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"python-lint.js","sourceRoot":"","sources":["../../src/python-lint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"python-lint.js","sourceRoot":"","sources":["../../src/python-lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ import { type ChildProcessWithoutNullStreams } from "node:child_process";
6
+ export interface PythonDiagnostic {
7
+ range: {
8
+ start: {
9
+ line: number;
10
+ character: number;
11
+ };
12
+ end: {
13
+ line: number;
14
+ character: number;
15
+ };
16
+ };
17
+ severity?: number;
18
+ code?: string | number;
19
+ source?: string;
20
+ message: string;
21
+ }
22
+ export interface PythonLspProxyOptions {
23
+ /** Called when the child publishes diagnostics for a document. */
24
+ onDiagnostics: (uri: string, diagnostics: PythonDiagnostic[]) => void;
25
+ /** Called when a start fails, with the reason — the owner's cue to fall back. */
26
+ onUnavailable?: (reason: string) => void;
27
+ /** Called with each line the child writes to stderr; defaults to this process's stderr. */
28
+ onStderr?: (line: string) => void;
29
+ /** Resolve the `east-py` command for a file's directory; defaults to `findEastPy`. */
30
+ resolveCommand?: (fromDir: string) => string;
31
+ /** Spawn override, for tests. */
32
+ spawnChild?: (command: string, args: string[]) => ChildProcessWithoutNullStreams;
33
+ /** How long to wait for `initialize`; defaults to 15 s. */
34
+ initializeTimeoutMs?: number;
35
+ /** How long to wait after a crash before respawning; defaults to 5 s. */
36
+ restartBackoffMs?: number;
37
+ }
38
+ /**
39
+ * Owns one long-lived `east-py lsp` process and forwards `.py` documents to it.
40
+ */
41
+ export declare class PythonLspProxy {
42
+ private readonly options;
43
+ private child;
44
+ private readonly reader;
45
+ private nextId;
46
+ private ready;
47
+ private starting;
48
+ private lastExitAt;
49
+ private lastStderr;
50
+ private disposed;
51
+ /** Documents open on the proxy — what a (re)start replays to the child. */
52
+ private readonly open;
53
+ /** path -> the document version the CURRENT child has been sent, by didOpen or didChange. */
54
+ private readonly seenByChild;
55
+ /** id -> settle(answered): true when the child replied, false when it went away. */
56
+ private readonly pending;
57
+ constructor(options: PythonLspProxyOptions);
58
+ /** Whether a child is up and initialized. */
59
+ get available(): boolean;
60
+ private resolveCommand;
61
+ private unavailable;
62
+ /** Start the child if it is not running. Resolves false when it cannot start. */
63
+ private ensure;
64
+ private start;
65
+ private handleExit;
66
+ private write;
67
+ private handle;
68
+ /**
69
+ * Bring the child up to `doc`: a didOpen when this child has not seen the
70
+ * document, a didChange when it has an older version, nothing when a start
71
+ * just replayed exactly this version.
72
+ */
73
+ private deliver;
74
+ /** Forward an opened document, starting the child if needed. */
75
+ didOpen(path: string, uri: string, text: string): Promise<void>;
76
+ /** Forward a change. */
77
+ didChange(path: string, uri: string, text: string): Promise<void>;
78
+ /** Forward a save — the moment the build tier runs without waiting. */
79
+ didSave(path: string, uri: string, text: string): Promise<void>;
80
+ /** Forward a close. */
81
+ didClose(path: string, uri: string): void;
82
+ /** Stop the child. */
83
+ dispose(): void;
84
+ }
85
+ //# sourceMappingURL=python-lsp-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-lsp-proxy.d.ts","sourceRoot":"","sources":["../../src/python-lsp-proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,304 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ import { spawn } from "node:child_process";
6
+ import { dirname } from "node:path";
7
+ import { findEastPy } from "./python-lint.js";
8
+ import { frame, FrameReader } from "./jsonrpc-stdio.js";
9
+ // One persistent `east-py lsp` child, proxied (#681).
10
+ //
11
+ // The build check (#653) imports the module, and a process per check pays that
12
+ // import every time: measured here, 0.12s for a module whose dependencies
13
+ // import lazily and 0.81s for one importing torch at module scope, against
14
+ // 0.0003s to re-check in a process that already holds them. So the python
15
+ // server stays warm, and this class owns it: started lazily by the first
16
+ // document, verified by its `initialize` reply, restarted after a crash once
17
+ // the backoff has elapsed with every open document replayed, and killed when
18
+ // its owner goes away — on the handshake timeout too, so a child that will not
19
+ // answer is never left running.
20
+ //
21
+ // Every method is safe to call when no child is running: the proxy stays
22
+ // silent rather than erroring. A START that fails — no command, no reply, a
23
+ // child that dies during the handshake — is reported through `onUnavailable`
24
+ // with the reason, so the owner can fall back (the python launcher drops to a
25
+ // cold `east-py lint` per change) instead of hiding the cause.
26
+ /** How long to wait for the child's `initialize` reply before giving up. */
27
+ const INITIALIZE_TIMEOUT_MS = 15_000;
28
+ /** Backoff after a crash, so a child that dies on startup is not respawned hot. */
29
+ const RESTART_BACKOFF_MS = 5_000;
30
+ /**
31
+ * Owns one long-lived `east-py lsp` process and forwards `.py` documents to it.
32
+ */
33
+ export class PythonLspProxy {
34
+ options;
35
+ child;
36
+ reader = new FrameReader((message) => this.handle(message));
37
+ nextId = 1;
38
+ ready = false;
39
+ starting;
40
+ lastExitAt = 0;
41
+ lastStderr = "";
42
+ disposed = false;
43
+ /** Documents open on the proxy — what a (re)start replays to the child. */
44
+ open = new Map();
45
+ /** path -> the document version the CURRENT child has been sent, by didOpen or didChange. */
46
+ seenByChild = new Map();
47
+ /** id -> settle(answered): true when the child replied, false when it went away. */
48
+ pending = new Map();
49
+ constructor(options) {
50
+ this.options = options;
51
+ }
52
+ /** Whether a child is up and initialized. */
53
+ get available() {
54
+ return this.ready && this.child !== undefined;
55
+ }
56
+ resolveCommand(fromDir) {
57
+ return (this.options.resolveCommand ?? findEastPy)(fromDir);
58
+ }
59
+ unavailable(reason) {
60
+ this.options.onUnavailable?.(reason);
61
+ }
62
+ /** Start the child if it is not running. Resolves false when it cannot start. */
63
+ async ensure(fromDir) {
64
+ if (this.disposed)
65
+ return false;
66
+ if (this.available)
67
+ return true;
68
+ if (this.starting !== undefined)
69
+ return this.starting;
70
+ if (Date.now() - this.lastExitAt < (this.options.restartBackoffMs ?? RESTART_BACKOFF_MS))
71
+ return false;
72
+ this.starting = this.start(fromDir).finally(() => {
73
+ this.starting = undefined;
74
+ });
75
+ return this.starting;
76
+ }
77
+ async start(fromDir) {
78
+ const command = this.resolveCommand(fromDir);
79
+ let child;
80
+ try {
81
+ const spawnChild = this.options.spawnChild ?? ((c, a) => spawn(c, a, { stdio: "pipe" }));
82
+ child = spawnChild(command, ["lsp"]);
83
+ }
84
+ catch (error) {
85
+ this.lastExitAt = Date.now();
86
+ this.unavailable(`could not spawn \`${command} lsp\`: ${error.message}`);
87
+ return false;
88
+ }
89
+ this.child = child;
90
+ this.reader.reset();
91
+ this.seenByChild.clear();
92
+ this.lastStderr = "";
93
+ child.on("error", (error) => {
94
+ // A spawn failure surfaces here, asynchronously — ENOENT for a command
95
+ // that is not there. The handshake below is what reports it.
96
+ this.lastStderr = error.message;
97
+ this.handleExit(child);
98
+ });
99
+ // `close` follows `exit` once the stdio pipes have drained, so the child's
100
+ // last words on stderr (why it could not start) are read before the
101
+ // bookkeeping is cleared; `exit` alone would race them. The grace timer is
102
+ // for a child whose pipes never close.
103
+ child.on("exit", () => {
104
+ const grace = setTimeout(() => this.handleExit(child), 250);
105
+ grace.unref?.();
106
+ });
107
+ child.on("close", () => this.handleExit(child));
108
+ child.stdout.on("data", (chunk) => {
109
+ if (child === this.child)
110
+ this.reader.push(chunk);
111
+ });
112
+ // The child's stderr is where it says WHY it cannot start (a missing pygls
113
+ // says so there): keep the last line for the failure report and pass every
114
+ // line on, so a log of this process shows the cause.
115
+ let stderrRest = "";
116
+ child.stderr.on("data", (chunk) => {
117
+ stderrRest += chunk.toString("utf8");
118
+ const lines = stderrRest.split(/\r?\n/);
119
+ stderrRest = lines.pop() ?? "";
120
+ for (const line of lines) {
121
+ if (line.trim() === "")
122
+ continue;
123
+ this.lastStderr = line;
124
+ (this.options.onStderr ?? ((l) => process.stderr.write(`[east-py lsp] ${l}\n`)))(line);
125
+ }
126
+ });
127
+ // A pipe reports a failed write as an `error` EVENT, never a throw — so a
128
+ // child that has exited before `initialize` reaches it (a real `east-py`
129
+ // that dies on import; the test stand-in under a loaded runner, v1.0.71's
130
+ // run on main) fails that write with EPIPE, the try/catch in `write` never
131
+ // sees it, and with no listener the event is an uncaught exception that
132
+ // takes the owner down. Nothing to do here: `exit` and `close` report the
133
+ // death, once stderr has said why, and the destroyed pipe refuses further
134
+ // writes in `write`.
135
+ for (const stream of [child.stdin, child.stdout, child.stderr]) {
136
+ stream.on("error", () => undefined);
137
+ }
138
+ // A stray child must be physically unable to hold this process open. The
139
+ // process handle AND its three stdio pipes are separate libuv handles, and
140
+ // the `data` reader above keeps the loop alive on its own — unref every
141
+ // one. (The pipes are Sockets at runtime, which have `unref`; the Readable
142
+ // and Writable types they are declared as do not, hence the guarded call.
143
+ // A test's spawn override may hand back a stand-in with none of them.)
144
+ for (const handle of [child, child.stdout, child.stderr, child.stdin]) {
145
+ const unref = handle.unref;
146
+ if (typeof unref === "function")
147
+ unref.call(handle);
148
+ }
149
+ const id = this.nextId++;
150
+ // The resolver takes the OUTCOME: `handleExit` settles every pending entry
151
+ // as failure so a dying child never hangs the caller and never leaves
152
+ // `ready` true with no child attached.
153
+ const initialized = new Promise((resolve) => {
154
+ const timer = setTimeout(() => resolve(false), this.options.initializeTimeoutMs ?? INITIALIZE_TIMEOUT_MS);
155
+ this.pending.set(id, (answered) => {
156
+ clearTimeout(timer);
157
+ resolve(answered);
158
+ });
159
+ });
160
+ this.write({ jsonrpc: "2.0", id, method: "initialize", params: { processId: process.pid, rootUri: null, capabilities: {} } });
161
+ const ok = await initialized;
162
+ if (!ok) {
163
+ const alive = child === this.child;
164
+ const why = this.lastStderr !== ""
165
+ ? this.lastStderr
166
+ : alive ? `no initialize reply within ${this.options.initializeTimeoutMs ?? INITIALIZE_TIMEOUT_MS} ms` : "exited during the handshake";
167
+ // A child that never answered is still running: kill it, or it lives on
168
+ // beside its replacement.
169
+ this.handleExit(child);
170
+ this.unavailable(`\`${command} lsp\` did not start: ${why}`);
171
+ return false;
172
+ }
173
+ this.write({ jsonrpc: "2.0", method: "initialized", params: {} });
174
+ this.ready = true;
175
+ // Every document open on the proxy is opened on THIS child — a first start
176
+ // and a restart alike, since the child has seen nothing either way. The
177
+ // caller that triggered the start finds its document already open and
178
+ // sends what it meant to send (a change, a save) rather than a second open.
179
+ for (const [path, doc] of this.open) {
180
+ this.write({ jsonrpc: "2.0", method: "textDocument/didOpen", params: { textDocument: { uri: doc.uri, languageId: "python", version: doc.version, text: doc.text } } });
181
+ this.seenByChild.set(path, doc.version);
182
+ }
183
+ return true;
184
+ }
185
+ handleExit(child) {
186
+ // Only the child we currently own: a late `exit` from one already replaced
187
+ // must not clear the fresh one's bookkeeping.
188
+ if (child !== this.child)
189
+ return;
190
+ this.child = undefined;
191
+ this.ready = false;
192
+ this.seenByChild.clear();
193
+ this.lastExitAt = Date.now();
194
+ child.removeAllListeners();
195
+ try {
196
+ child.kill();
197
+ }
198
+ catch {
199
+ /* already gone */
200
+ }
201
+ // Killing the process is not enough to let this one exit: its stdio pipes
202
+ // are their own libuv handles, and the `data` reader on stdout keeps the
203
+ // event loop alive after the child is gone. Destroy them explicitly.
204
+ for (const stream of [child.stdout, child.stderr, child.stdin]) {
205
+ try {
206
+ stream.destroy();
207
+ }
208
+ catch {
209
+ /* already closed */
210
+ }
211
+ }
212
+ for (const settle of this.pending.values())
213
+ settle(false);
214
+ this.pending.clear();
215
+ }
216
+ write(message) {
217
+ const child = this.child;
218
+ if (child === undefined || child.stdin.destroyed)
219
+ return;
220
+ try {
221
+ child.stdin.write(frame(message));
222
+ }
223
+ catch {
224
+ this.handleExit(child);
225
+ }
226
+ }
227
+ handle(message) {
228
+ if (message.id !== undefined && message.id !== null && message.method === undefined) {
229
+ const settle = this.pending.get(message.id);
230
+ if (settle !== undefined) {
231
+ this.pending.delete(message.id);
232
+ settle(true);
233
+ }
234
+ return;
235
+ }
236
+ if (message.method === "textDocument/publishDiagnostics") {
237
+ const uri = message.params?.uri;
238
+ if (typeof uri === "string") {
239
+ this.options.onDiagnostics(uri, (message.params?.diagnostics ?? []));
240
+ }
241
+ }
242
+ }
243
+ /**
244
+ * Bring the child up to `doc`: a didOpen when this child has not seen the
245
+ * document, a didChange when it has an older version, nothing when a start
246
+ * just replayed exactly this version.
247
+ */
248
+ deliver(path, doc) {
249
+ const delivered = this.seenByChild.get(path);
250
+ if (delivered === doc.version)
251
+ return;
252
+ if (delivered === undefined) {
253
+ this.write({ jsonrpc: "2.0", method: "textDocument/didOpen", params: { textDocument: { uri: doc.uri, languageId: "python", version: doc.version, text: doc.text } } });
254
+ }
255
+ else {
256
+ this.write({ jsonrpc: "2.0", method: "textDocument/didChange", params: { textDocument: { uri: doc.uri, version: doc.version }, contentChanges: [{ text: doc.text }] } });
257
+ }
258
+ this.seenByChild.set(path, doc.version);
259
+ }
260
+ /** Forward an opened document, starting the child if needed. */
261
+ async didOpen(path, uri, text) {
262
+ const doc = { uri, text, version: 1 };
263
+ this.open.set(path, doc);
264
+ if (!(await this.ensure(dirname(path))))
265
+ return;
266
+ this.deliver(path, doc);
267
+ }
268
+ /** Forward a change. */
269
+ async didChange(path, uri, text) {
270
+ const known = this.open.get(path);
271
+ const doc = { uri, text, version: (known?.version ?? 0) + 1 };
272
+ this.open.set(path, doc);
273
+ if (!(await this.ensure(dirname(path))))
274
+ return;
275
+ this.deliver(path, doc);
276
+ }
277
+ /** Forward a save — the moment the build tier runs without waiting. */
278
+ async didSave(path, uri, text) {
279
+ const known = this.open.get(path);
280
+ const doc = { uri, text, version: known?.version ?? 1 };
281
+ this.open.set(path, doc);
282
+ if (!(await this.ensure(dirname(path))))
283
+ return;
284
+ this.deliver(path, doc);
285
+ this.write({ jsonrpc: "2.0", method: "textDocument/didSave", params: { textDocument: { uri }, text } });
286
+ }
287
+ /** Forward a close. */
288
+ didClose(path, uri) {
289
+ this.open.delete(path);
290
+ if (!this.available || !this.seenByChild.has(path))
291
+ return;
292
+ this.seenByChild.delete(path);
293
+ this.write({ jsonrpc: "2.0", method: "textDocument/didClose", params: { textDocument: { uri } } });
294
+ }
295
+ /** Stop the child. */
296
+ dispose() {
297
+ this.disposed = true;
298
+ this.open.clear();
299
+ const child = this.child;
300
+ if (child !== undefined)
301
+ this.handleExit(child);
302
+ }
303
+ }
304
+ //# sourceMappingURL=python-lsp-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-lsp-proxy.js","sourceRoot":"","sources":["../../src/python-lsp-proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type PythonDiagnostic as LintRecord } from "./python-lint.js";
2
+ import type { ChildProcessWithoutNullStreams } from "node:child_process";
3
+ export interface EastPyLspOptions {
4
+ input?: NodeJS.ReadableStream;
5
+ output?: NodeJS.WritableStream;
6
+ /** Called on `exit`; defaults to `process.exit`. */
7
+ exit?: (code: number) => void;
8
+ /** Where the launcher explains itself; defaults to this process's stderr. */
9
+ log?: (line: string) => void;
10
+ /** Whether `fromDir` belongs to an east-py project; defaults to the pyproject / venv / override walk. */
11
+ eastPythonProject?: (fromDir: string) => boolean;
12
+ /** Resolve the `east-py` command for a directory; defaults to `findEastPy`. */
13
+ resolveCommand?: (fromDir: string) => string;
14
+ /** Spawn override for the child, for tests. */
15
+ spawnChild?: (command: string, args: string[]) => ChildProcessWithoutNullStreams;
16
+ /** The cold lint used when the child cannot start; defaults to `runEastPyLint`. */
17
+ lint?: (file: string, content: string | undefined) => Promise<LintRecord[] | null>;
18
+ initializeTimeoutMs?: number;
19
+ restartBackoffMs?: number;
20
+ }
21
+ /** Whether a directory belongs to a project that uses east-py — the default gate. */
22
+ export declare function isEastPythonProject(fromDir: string): boolean;
23
+ /** Run the python East language server until the client disconnects. */
24
+ export declare function runEastPyLsp(options?: EastPyLspOptions): void;
25
+ //# sourceMappingURL=python-lsp-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-lsp-server.d.ts","sourceRoot":"","sources":["../../src/python-lsp-server.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,gBAAgB,IAAI,UAAU,EACpC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AA2DzE,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,oDAAoD;IACpD,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,yGAAyG;IACzG,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IACjD,+EAA+E;IAC/E,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7C,+CAA+C;IAC/C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,8BAA8B,CAAC;IACjF,mFAAmF;IACnF,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;IACnF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAoLjE"}
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Copyright (c) 2025 Elara AI Pty Ltd
3
+ * Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
4
+ */
5
+ import { readFileSync } from "node:fs";
6
+ import { dirname } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import { frame, FrameReader } from "./jsonrpc-stdio.js";
9
+ import { findEastPy, findEastPyProject, PYTHON_EAST_IMPORT, runEastPyLint, } from "./python-lint.js";
10
+ import { PythonLspProxy } from "./python-lsp-proxy.js";
11
+ // The python language server the Claude Code plugin registers for `.py` files
12
+ // (#681): a launcher around the project's own `east-py lsp`.
13
+ //
14
+ // It is its own server, beside the TypeScript one, rather than a proxy hidden
15
+ // inside it, so each language has its own lifecycle: a python-only project
16
+ // never starts the TypeScript service, a TypeScript project never spawns
17
+ // python, and a crash in one is the other's business no more than a crash in
18
+ // pyright would be. It is a launcher rather than `east-py lsp` itself because
19
+ // a manifest can only name a command on PATH or under the plugin root, and the
20
+ // right `east-py` lives in the project's venv (`findEastPy`).
21
+ //
22
+ // What it does for a `.py` document, in order:
23
+ //
24
+ // 1. Nothing, unless the document imports east AND its directory belongs to an
25
+ // east-py PROJECT — a `pyproject.toml` above it declares an east-py
26
+ // distribution, or `EAST_PY_LINT` names the command outright, or a `.venv`
27
+ // above it has `east-py`. The manifest cannot be conditional, so this
28
+ // process starts for any `.py` file anywhere the plugin is enabled; the gate
29
+ // is what keeps it a silent null server everywhere else. It never claims a
30
+ // file is clean: an empty publish means "not mine".
31
+ // 2. Starts ONE `east-py lsp` child — the warm two-tier server — verified by its
32
+ // `initialize` reply, restarted after a crash with the open documents
33
+ // replayed, killed when the client goes away.
34
+ // 3. Falls back, when that child cannot START, to what the plugin did before
35
+ // the warm server existed: `east-py lint --format json` as a cold subprocess
36
+ // per debounced change. The rules never disappear because pygls is missing;
37
+ // only the build tier does, and stderr says why.
38
+ const LINT_DEBOUNCE_MS = 100;
39
+ const SEVERITY = { error: 1, warning: 2, suggestion: 3 };
40
+ function uriToPath(uri) {
41
+ if (!uri.startsWith("file://"))
42
+ return undefined;
43
+ try {
44
+ return fileURLToPath(uri);
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ }
50
+ /** A lint record in the shape `east-py lsp` publishes, so both paths look the same to the client. */
51
+ function toDiagnostic(record) {
52
+ const endLine = record.end_line ?? record.line;
53
+ const endColumn = record.end_column ?? record.column + 1;
54
+ return {
55
+ range: {
56
+ start: { line: record.line - 1, character: Math.max(record.column - 1, 0) },
57
+ end: { line: endLine - 1, character: Math.max(endColumn - 1, 0) },
58
+ },
59
+ severity: SEVERITY[record.category] ?? 1,
60
+ code: record.code,
61
+ source: "east-py",
62
+ message: `${record.message} [${record.rule}]`,
63
+ };
64
+ }
65
+ /** Whether a directory belongs to a project that uses east-py — the default gate. */
66
+ export function isEastPythonProject(fromDir) {
67
+ const override = process.env["EAST_PY_LINT"];
68
+ if (override !== undefined && override !== "")
69
+ return true;
70
+ if (findEastPyProject(fromDir) !== undefined)
71
+ return true;
72
+ // a resolvable venv east-py is evidence enough, pyproject or not
73
+ const command = findEastPy(fromDir);
74
+ return command !== "east-py";
75
+ }
76
+ /** Run the python East language server until the client disconnects. */
77
+ export function runEastPyLsp(options = {}) {
78
+ const input = options.input ?? process.stdin;
79
+ const output = options.output ?? process.stdout;
80
+ const exit = options.exit ?? ((code) => process.exit(code));
81
+ const log = options.log ?? ((line) => process.stderr.write(`[east-py] ${line}\n`));
82
+ const inProject = options.eastPythonProject ?? isEastPythonProject;
83
+ const resolveCommand = options.resolveCommand ?? findEastPy;
84
+ // The fallback runs the same `east-py` the child would have: one resolution
85
+ // for both paths, so "the server cannot start" never turns into "some other
86
+ // east-py on PATH answers instead".
87
+ const lint = options.lint ?? ((file, content) => runEastPyLint(file, content, 4000, resolveCommand(dirname(file))));
88
+ // path -> the client's uri and the current buffer
89
+ const open = new Map();
90
+ const pendingLint = new Map();
91
+ const gated = new Map();
92
+ let mode = "child";
93
+ let shuttingDown = false;
94
+ let disposed = false;
95
+ function send(message) {
96
+ output.write(frame(message));
97
+ }
98
+ function publish(uri, diagnostics) {
99
+ send({ method: "textDocument/publishDiagnostics", params: { uri, diagnostics } });
100
+ }
101
+ const python = new PythonLspProxy({
102
+ onDiagnostics: publish,
103
+ onStderr: (line) => log(`east-py lsp: ${line}`),
104
+ onUnavailable: (reason) => {
105
+ if (mode === "lint")
106
+ return;
107
+ mode = "lint";
108
+ log(`${reason} — falling back to \`east-py lint\` per change; the build tier is off until it starts (east-py lsp --probe says why)`);
109
+ for (const [path, doc] of open)
110
+ lintLater(path, doc.uri);
111
+ },
112
+ ...(options.resolveCommand !== undefined ? { resolveCommand: options.resolveCommand } : {}),
113
+ ...(options.spawnChild !== undefined ? { spawnChild: options.spawnChild } : {}),
114
+ ...(options.initializeTimeoutMs !== undefined ? { initializeTimeoutMs: options.initializeTimeoutMs } : {}),
115
+ ...(options.restartBackoffMs !== undefined ? { restartBackoffMs: options.restartBackoffMs } : {}),
116
+ });
117
+ function lintLater(path, uri) {
118
+ const existing = pendingLint.get(path);
119
+ if (existing !== undefined)
120
+ clearTimeout(existing);
121
+ pendingLint.set(path, setTimeout(() => {
122
+ pendingLint.delete(path);
123
+ const doc = open.get(path);
124
+ if (doc === undefined)
125
+ return;
126
+ void lint(path, doc.text).then((records) => {
127
+ // no east-py answered: say nothing rather than "clean"
128
+ if (records === null || open.get(path) !== doc)
129
+ return;
130
+ publish(uri, records.map(toDiagnostic));
131
+ });
132
+ }, LINT_DEBOUNCE_MS));
133
+ }
134
+ /** Whether this document is ours: a `.py` that imports east, in an east-py project. */
135
+ function ours(path, text) {
136
+ if (!path.endsWith(".py") || !PYTHON_EAST_IMPORT.test(text))
137
+ return false;
138
+ const dir = dirname(path);
139
+ let verdict = gated.get(dir);
140
+ if (verdict === undefined) {
141
+ verdict = inProject(dir);
142
+ gated.set(dir, verdict);
143
+ if (!verdict)
144
+ log(`${dir} is not an east-py project (no pyproject.toml above it depends on elaraai-east-py, no .venv east-py, no EAST_PY_LINT): python diagnostics stay idle there`);
145
+ }
146
+ return verdict;
147
+ }
148
+ function forward(kind, path, uri, text) {
149
+ if (!ours(path, text)) {
150
+ const was = open.get(path);
151
+ open.delete(path);
152
+ if (was !== undefined && mode === "child")
153
+ python.didClose(path, uri);
154
+ publish(uri, []);
155
+ return;
156
+ }
157
+ open.set(path, { uri, text });
158
+ if (mode === "lint") {
159
+ lintLater(path, uri);
160
+ return;
161
+ }
162
+ void (kind === "open" ? python.didOpen(path, uri, text)
163
+ : kind === "save" ? python.didSave(path, uri, text)
164
+ : python.didChange(path, uri, text));
165
+ }
166
+ function readSource(path) {
167
+ try {
168
+ return readFileSync(path, "utf-8");
169
+ }
170
+ catch {
171
+ return undefined;
172
+ }
173
+ }
174
+ function handle(message) {
175
+ const { method, id, params } = message;
176
+ if (method === undefined)
177
+ return; // a response — we send no requests to the client
178
+ switch (method) {
179
+ case "initialize":
180
+ send({
181
+ id,
182
+ result: {
183
+ capabilities: {
184
+ textDocumentSync: { openClose: true, change: 1, save: { includeText: true } },
185
+ },
186
+ serverInfo: { name: "east-py-diagnostics" },
187
+ },
188
+ });
189
+ return;
190
+ case "initialized":
191
+ return;
192
+ case "shutdown":
193
+ shuttingDown = true;
194
+ send({ id, result: null });
195
+ return;
196
+ case "exit":
197
+ shutdown(shuttingDown ? 0 : 1);
198
+ return;
199
+ case "textDocument/didOpen": {
200
+ const path = uriToPath(params?.textDocument?.uri ?? "");
201
+ const text = params?.textDocument?.text;
202
+ if (path === undefined || typeof text !== "string")
203
+ return;
204
+ forward("open", path, params.textDocument.uri, text);
205
+ return;
206
+ }
207
+ case "textDocument/didChange": {
208
+ const path = uriToPath(params?.textDocument?.uri ?? "");
209
+ const text = params?.contentChanges?.at?.(-1)?.text;
210
+ if (path === undefined || typeof text !== "string")
211
+ return;
212
+ forward("change", path, params.textDocument.uri, text);
213
+ return;
214
+ }
215
+ case "textDocument/didSave": {
216
+ const path = uriToPath(params?.textDocument?.uri ?? "");
217
+ if (path === undefined)
218
+ return;
219
+ const text = typeof params?.text === "string" ? params.text : (open.get(path)?.text ?? readSource(path));
220
+ if (text === undefined)
221
+ return;
222
+ forward("save", path, params.textDocument.uri, text);
223
+ return;
224
+ }
225
+ case "textDocument/didClose": {
226
+ const uri = params?.textDocument?.uri ?? "";
227
+ const path = uriToPath(uri);
228
+ if (path === undefined)
229
+ return;
230
+ const timer = pendingLint.get(path);
231
+ if (timer !== undefined)
232
+ clearTimeout(timer);
233
+ pendingLint.delete(path);
234
+ if (open.delete(path) && mode === "child")
235
+ python.didClose(path, uri);
236
+ publish(uri, []);
237
+ return;
238
+ }
239
+ default:
240
+ if (id !== undefined) {
241
+ send({ id, error: { code: -32601, message: `Method not found: ${method}` } });
242
+ }
243
+ return;
244
+ }
245
+ }
246
+ const reader = new FrameReader(handle);
247
+ input.on("data", (chunk) => reader.push(chunk));
248
+ // The client going away ends the session, and the python child must go with
249
+ // it. Wiring this only to the `exit` MESSAGE is not enough: a disconnecting
250
+ // client may never send one.
251
+ const shutdown = (code) => {
252
+ if (disposed)
253
+ return;
254
+ disposed = true;
255
+ for (const timer of pendingLint.values())
256
+ clearTimeout(timer);
257
+ pendingLint.clear();
258
+ python.dispose();
259
+ exit(code);
260
+ };
261
+ input.on("close", () => shutdown(0));
262
+ input.on("end", () => shutdown(0));
263
+ }
264
+ //# sourceMappingURL=python-lsp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-lsp-server.js","sourceRoot":"","sources":["../../src/python-lsp-server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elaraai/east-diagnostics",
3
- "version": "1.0.70",
3
+ "version": "1.0.72",
4
4
  "license": "AGPL-3.0-or-later",
5
5
  "type": "module",
6
6
  "description": "East-aware diagnostic rules over the TypeScript checker — one shared engine for the editor (tsserver plugin), the agent (headless daemon), and CI.",
@@ -44,8 +44,8 @@
44
44
  "devDependencies": {
45
45
  "@types/node": "^22.18.1",
46
46
  "typescript": "~5.9.2",
47
- "@elaraai/e3": "1.0.70",
48
- "@elaraai/east": "1.0.70"
47
+ "@elaraai/e3": "1.0.72",
48
+ "@elaraai/east": "1.0.72"
49
49
  },
50
50
  "scripts": {
51
51
  "build": "tsc",