@mrclrchtr/supi-code-intelligence 4.2.0 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/package.json +3 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +2 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +3 -3
- package/package.json +5 -5
- package/src/extension.ts +5 -1
- package/src/substrate/lsp/lifecycle.ts +55 -3
- package/src/substrate/lsp/state.ts +6 -0
- package/src/ui/footer.ts +33 -8
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-code-runtime",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "SuPi code-runtime — shared workspace context, capability contracts, and canonical types for the code-understanding stack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"!__tests__"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@mrclrchtr/supi-core": "4.
|
|
32
|
+
"@mrclrchtr/supi-core": "4.4.0"
|
|
33
33
|
},
|
|
34
34
|
"bundledDependencies": [
|
|
35
35
|
"@mrclrchtr/supi-core"
|
package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-code-runtime",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "SuPi code-runtime — shared workspace context, capability contracts, and canonical types for the code-understanding stack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"!__tests__"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@mrclrchtr/supi-core": "4.
|
|
32
|
+
"@mrclrchtr/supi-core": "4.4.0"
|
|
33
33
|
},
|
|
34
34
|
"bundledDependencies": [
|
|
35
35
|
"@mrclrchtr/supi-core"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-lsp",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "SuPi LSP runtime — Language Server Protocol integration library for pi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"vscode-jsonrpc": "^9.0.0",
|
|
38
38
|
"vscode-languageserver-protocol": "^3.17.5",
|
|
39
39
|
"vscode-languageserver-types": "^3.17.5",
|
|
40
|
-
"@mrclrchtr/supi-
|
|
41
|
-
"@mrclrchtr/supi-
|
|
40
|
+
"@mrclrchtr/supi-code-runtime": "4.4.0",
|
|
41
|
+
"@mrclrchtr/supi-core": "4.4.0"
|
|
42
42
|
},
|
|
43
43
|
"bundledDependencies": [
|
|
44
44
|
"@mrclrchtr/supi-code-runtime",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-code-runtime",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "SuPi code-runtime — shared workspace context, capability contracts, and canonical types for the code-understanding stack",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"!__tests__"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@mrclrchtr/supi-core": "4.
|
|
32
|
+
"@mrclrchtr/supi-core": "4.4.0"
|
|
33
33
|
},
|
|
34
34
|
"bundledDependencies": [
|
|
35
35
|
"@mrclrchtr/supi-core"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-tree-sitter",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "SuPi Tree-sitter library — structural AST analysis for pi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"web-tree-sitter": "^0.26.8",
|
|
37
|
-
"@mrclrchtr/supi-code-runtime": "4.
|
|
38
|
-
"@mrclrchtr/supi-core": "4.
|
|
37
|
+
"@mrclrchtr/supi-code-runtime": "4.4.0",
|
|
38
|
+
"@mrclrchtr/supi-core": "4.4.0"
|
|
39
39
|
},
|
|
40
40
|
"bundledDependencies": [
|
|
41
41
|
"@mrclrchtr/supi-code-runtime",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-code-intelligence",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"description": "SuPi Code Intelligence extension — workspace orientation, target resolution and inspection, relationship analysis, code-aware search, live health, and semantic refactoring for pi",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"yaml": "^2.9.0",
|
|
37
|
-
"@mrclrchtr/supi-code-runtime": "4.
|
|
38
|
-
"@mrclrchtr/supi-
|
|
39
|
-
"@mrclrchtr/supi-tree-sitter": "4.
|
|
40
|
-
"@mrclrchtr/supi-
|
|
37
|
+
"@mrclrchtr/supi-code-runtime": "4.4.0",
|
|
38
|
+
"@mrclrchtr/supi-core": "4.4.0",
|
|
39
|
+
"@mrclrchtr/supi-tree-sitter": "4.4.0",
|
|
40
|
+
"@mrclrchtr/supi-lsp": "4.4.0"
|
|
41
41
|
},
|
|
42
42
|
"bundledDependencies": [
|
|
43
43
|
"@mrclrchtr/supi-code-runtime",
|
package/src/extension.ts
CHANGED
|
@@ -43,7 +43,11 @@ export default function codeIntelligenceExtension(
|
|
|
43
43
|
);
|
|
44
44
|
|
|
45
45
|
registerCiStatusCommand(pi);
|
|
46
|
-
registerLspFooterContribution(lspState);
|
|
46
|
+
const lspFooter = registerLspFooterContribution(pi, lspState);
|
|
47
|
+
|
|
48
|
+
pi.on("session_shutdown", () => {
|
|
49
|
+
lspFooter.dispose();
|
|
50
|
+
});
|
|
47
51
|
|
|
48
52
|
pi.on("before_agent_start", (event, ctx) => {
|
|
49
53
|
const session = app.getSession(ctx.cwd) ?? app.createSession(ctx.cwd);
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
// LSP lifecycle backed by the process-shared Workspace provider host.
|
|
2
2
|
|
|
3
3
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
4
|
-
import { unregisterLspFooterContribution } from "../../ui/footer.ts";
|
|
5
4
|
import { acquireWorkspaceProviderHost } from "../workspace-provider-host.ts";
|
|
6
|
-
import type
|
|
5
|
+
import { LSP_STATE_CHANGE_EVENT, type LspAdapterState } from "./state.ts";
|
|
6
|
+
|
|
7
|
+
const STATE_CHANGE_EVENT = new Event(LSP_STATE_CHANGE_EVENT);
|
|
8
|
+
|
|
9
|
+
/** Poll interval (ms) for detecting server readiness transitions in the footer. */
|
|
10
|
+
const READINESS_POLL_MS = 2_000;
|
|
7
11
|
|
|
8
12
|
/** Acquire providers once per workspace and release them after the final Pi session ends. */
|
|
9
13
|
export function registerLspSessionLifecycle(
|
|
@@ -11,12 +15,55 @@ export function registerLspSessionLifecycle(
|
|
|
11
15
|
state: LspAdapterState,
|
|
12
16
|
onStarted?: (ctx: ExtensionContext) => void | Promise<void>,
|
|
13
17
|
): void {
|
|
18
|
+
let readinessTimer: ReturnType<typeof setInterval> | null = null;
|
|
19
|
+
let lastFingerprint = "";
|
|
20
|
+
|
|
21
|
+
function fingerprint(): string {
|
|
22
|
+
const servers = state.controller?.workspaceRuntime?.getProjectServers();
|
|
23
|
+
if (!servers) return "";
|
|
24
|
+
let ready = 0;
|
|
25
|
+
let starting = 0;
|
|
26
|
+
let error = 0;
|
|
27
|
+
let unavailable = 0;
|
|
28
|
+
let openFiles = 0;
|
|
29
|
+
for (const s of servers) {
|
|
30
|
+
openFiles += s.openFiles.length;
|
|
31
|
+
if (s.status === "running" && s.ready) ready++;
|
|
32
|
+
else if (s.status === "running") starting++;
|
|
33
|
+
else if (s.status === "error") error++;
|
|
34
|
+
else unavailable++;
|
|
35
|
+
}
|
|
36
|
+
return `${ready}:${starting}:${error}:${unavailable}:${openFiles}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function startReadinessPolling(): void {
|
|
40
|
+
stopReadinessPolling();
|
|
41
|
+
lastFingerprint = fingerprint();
|
|
42
|
+
readinessTimer = setInterval(() => {
|
|
43
|
+
if (state.controller?.kind !== "ready") return;
|
|
44
|
+
const current = fingerprint();
|
|
45
|
+
if (current === lastFingerprint) return;
|
|
46
|
+
lastFingerprint = current;
|
|
47
|
+
state.stateChanges.dispatchEvent(STATE_CHANGE_EVENT);
|
|
48
|
+
}, READINESS_POLL_MS);
|
|
49
|
+
readinessTimer.unref?.();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function stopReadinessPolling(): void {
|
|
53
|
+
if (readinessTimer) {
|
|
54
|
+
clearInterval(readinessTimer);
|
|
55
|
+
readinessTimer = null;
|
|
56
|
+
}
|
|
57
|
+
lastFingerprint = "";
|
|
58
|
+
}
|
|
59
|
+
|
|
14
60
|
pi.on("session_start", async (_event, ctx: ExtensionContext) => {
|
|
15
61
|
await state.providerLease?.release();
|
|
16
62
|
state.providerLease = null;
|
|
17
63
|
state.controller = null;
|
|
18
64
|
state.lspActive = false;
|
|
19
65
|
state.sentinelSnapshot = new Map();
|
|
66
|
+
stopReadinessPolling();
|
|
20
67
|
|
|
21
68
|
const lease = await acquireWorkspaceProviderHost(ctx.cwd, {
|
|
22
69
|
projectTrusted: ctx.isProjectTrusted(),
|
|
@@ -26,14 +73,19 @@ export function registerLspSessionLifecycle(
|
|
|
26
73
|
state.lspActive = lease.lspController?.kind === "ready";
|
|
27
74
|
state.sentinelSnapshot = lease.sentinelSnapshot;
|
|
28
75
|
await onStarted?.(ctx);
|
|
76
|
+
|
|
77
|
+
// Dispatch initial server list so the footer shows starting servers immediately.
|
|
78
|
+
state.stateChanges.dispatchEvent(STATE_CHANGE_EVENT);
|
|
79
|
+
// Poll for readiness transitions (running → ready, errors, etc.).
|
|
80
|
+
startReadinessPolling();
|
|
29
81
|
});
|
|
30
82
|
|
|
31
83
|
pi.on("session_shutdown", async () => {
|
|
84
|
+
stopReadinessPolling();
|
|
32
85
|
await state.providerLease?.release();
|
|
33
86
|
state.providerLease = null;
|
|
34
87
|
state.controller = null;
|
|
35
88
|
state.lspActive = false;
|
|
36
89
|
state.sentinelSnapshot = new Map();
|
|
37
|
-
unregisterLspFooterContribution();
|
|
38
90
|
});
|
|
39
91
|
}
|
|
@@ -25,6 +25,8 @@ export interface LspAdapterState {
|
|
|
25
25
|
lspActive: boolean;
|
|
26
26
|
/** Snapshot of workspace sentinel files (package.json, tsconfig, lockfiles) for change detection. */
|
|
27
27
|
sentinelSnapshot: Map<string, number>;
|
|
28
|
+
/** Fired when server statuses or readiness change — footer listens for re-renders. */
|
|
29
|
+
stateChanges: EventTarget;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export function createLspAdapterState(): LspAdapterState {
|
|
@@ -34,5 +36,9 @@ export function createLspAdapterState(): LspAdapterState {
|
|
|
34
36
|
inspector: { handle: null, close: null },
|
|
35
37
|
lspActive: false,
|
|
36
38
|
sentinelSnapshot: new Map(),
|
|
39
|
+
stateChanges: new EventTarget(),
|
|
37
40
|
};
|
|
38
41
|
}
|
|
42
|
+
|
|
43
|
+
/** Event type dispatched on {@link LspAdapterState.stateChanges} when server statuses change. */
|
|
44
|
+
export const LSP_STATE_CHANGE_EVENT = "server-status-changed" as const;
|
package/src/ui/footer.ts
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LSP footer stats-end contribution for code-intelligence.
|
|
3
3
|
*
|
|
4
|
-
* Provides the persistent "| λ lsp • N
|
|
4
|
+
* Provides the persistent "| λ lsp • N ✓ • M open files" suffix on the
|
|
5
5
|
* footer stats line, after cost and context info. This was removed during the
|
|
6
6
|
* supi-lsp → supi-code-intelligence migration.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
9
10
|
import { footerContributions } from "@mrclrchtr/supi-core/footer-registry";
|
|
10
|
-
import type
|
|
11
|
+
import { LSP_STATE_CHANGE_EVENT, type LspAdapterState } from "../substrate/lsp/state.ts";
|
|
11
12
|
|
|
12
|
-
/** Build the LSP status text: "λ lsp •
|
|
13
|
+
/** Build the LSP status text: "λ lsp • 3 ✓ • 1 ⟳ • 1 ✗ • 2 open files" */
|
|
13
14
|
export function buildLspStatusText(lspState: LspAdapterState): string | undefined {
|
|
14
15
|
const controller = lspState.controller;
|
|
15
16
|
const runtime = controller?.workspaceRuntime;
|
|
16
17
|
if (!runtime) return undefined;
|
|
17
18
|
|
|
18
19
|
const servers = runtime.getProjectServers();
|
|
19
|
-
const runningServers = servers.filter((s) => s.status === "running").length;
|
|
20
20
|
const openFiles = servers.reduce((sum, s) => sum + s.openFiles.length, 0);
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
// Aggregate server states
|
|
23
|
+
const ready = servers.filter((s) => s.status === "running" && s.ready).length;
|
|
24
|
+
const starting = servers.filter((s) => s.status === "running" && !s.ready).length;
|
|
25
|
+
const error = servers.filter((s) => s.status === "error").length;
|
|
26
|
+
const unavailable = servers.filter((s) => s.status === "unavailable").length;
|
|
27
|
+
|
|
28
|
+
const hasServers = ready + starting + error + unavailable > 0;
|
|
29
|
+
if (!hasServers && openFiles === 0) return undefined;
|
|
23
30
|
|
|
24
31
|
const parts = ["λ lsp"];
|
|
25
|
-
if (
|
|
26
|
-
|
|
32
|
+
if (ready > 0) parts.push(`${ready} ✓`);
|
|
33
|
+
if (starting > 0) parts.push(`${starting} ⟳`);
|
|
34
|
+
if (error > 0) parts.push(`${error} ✗`);
|
|
35
|
+
if (unavailable > 0) parts.push(`${unavailable} ⊘`);
|
|
27
36
|
if (openFiles > 0) parts.push(`${openFiles} ${openFiles === 1 ? "open file" : "open files"}`);
|
|
28
37
|
return parts.join(" • ");
|
|
29
38
|
}
|
|
@@ -33,7 +42,12 @@ export function buildLspStatusText(lspState: LspAdapterState): string | undefine
|
|
|
33
42
|
const FOOTER_KEY = "lsp-status";
|
|
34
43
|
|
|
35
44
|
/** Register the LSP stats-end footer contribution for the given adapter state. */
|
|
36
|
-
export function registerLspFooterContribution(
|
|
45
|
+
export function registerLspFooterContribution(
|
|
46
|
+
pi: ExtensionAPI,
|
|
47
|
+
lspState: LspAdapterState,
|
|
48
|
+
): {
|
|
49
|
+
dispose: () => void;
|
|
50
|
+
} {
|
|
37
51
|
footerContributions.register({
|
|
38
52
|
key: FOOTER_KEY,
|
|
39
53
|
placement: "stats-end",
|
|
@@ -44,6 +58,17 @@ export function registerLspFooterContribution(lspState: LspAdapterState): void {
|
|
|
44
58
|
return `| ${text}`;
|
|
45
59
|
},
|
|
46
60
|
});
|
|
61
|
+
|
|
62
|
+
// Trigger TUI re-render when server states change.
|
|
63
|
+
const handler = () => pi.events.emit("supi:lsp:invalidate", {});
|
|
64
|
+
lspState.stateChanges.addEventListener(LSP_STATE_CHANGE_EVENT, handler);
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
dispose() {
|
|
68
|
+
lspState.stateChanges.removeEventListener(LSP_STATE_CHANGE_EVENT, handler);
|
|
69
|
+
unregisterLspFooterContribution();
|
|
70
|
+
},
|
|
71
|
+
};
|
|
47
72
|
}
|
|
48
73
|
|
|
49
74
|
/** Remove the LSP stats footer contribution. */
|