@mrclrchtr/supi-code-runtime 1.9.0 → 1.10.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.
@@ -1,4 +1,10 @@
1
- ![SuPi](assets/logo.png)
1
+ <div align="center">
2
+ <a href="https://github.com/mrclrchtr/supi/tree/main/packages/supi-core">
3
+ <picture>
4
+ <img src="https://raw.githubusercontent.com/mrclrchtr/supi/main/packages/supi-core/assets/logo.png" alt="SuPi" width="50%">
5
+ </picture>
6
+ </a>
7
+ </div>
2
8
 
3
9
  # @mrclrchtr/supi-core
4
10
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-core",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
5
5
  "license": "MIT",
6
6
  "repository": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-code-runtime",
3
- "version": "1.9.0",
3
+ "version": "1.10.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": {
@@ -19,7 +19,7 @@
19
19
  "!__tests__"
20
20
  ],
21
21
  "dependencies": {
22
- "@mrclrchtr/supi-core": "1.9.0"
22
+ "@mrclrchtr/supi-core": "1.10.0"
23
23
  },
24
24
  "peerDependencies": {
25
25
  "@earendil-works/pi-coding-agent": "*"
package/src/api.ts CHANGED
@@ -21,11 +21,15 @@ export type {
21
21
  CodeResult,
22
22
  CodeSymbol,
23
23
  ConfidenceMode,
24
+ DisambiguationCandidate,
24
25
  ExportData,
26
+ FileEdit,
25
27
  ImportData,
26
28
  NodeAtData,
27
29
  OutlineData,
30
+ RefactorResult,
28
31
  SourceRange,
32
+ WorkspaceEdit,
29
33
  } from "./types.ts";
30
34
  export type { WorkspaceContext } from "./workspace/context.ts";
31
35
  // Workspace context
@@ -14,6 +14,7 @@ import type {
14
14
  ImportData,
15
15
  NodeAtData,
16
16
  OutlineData,
17
+ RefactorResult,
17
18
  } from "../types.ts";
18
19
 
19
20
  // ── Availability state ─────────────────────────────────────────────────
@@ -47,6 +48,18 @@ export interface SemanticProvider {
47
48
  implementation(filePath: string, position: CodePosition): Promise<CodeLocation[] | null>;
48
49
  documentSymbols(filePath: string): Promise<CodeSymbol[] | null>;
49
50
  workspaceSymbols(query: string): Promise<CodeSymbol[] | null>;
51
+
52
+ /**
53
+ * Optional rename capability. When present, the provider supports
54
+ * precise semantic rename operations.
55
+ */
56
+ rename?(file: string, position: CodePosition, newName: string): Promise<RefactorResult>;
57
+
58
+ /**
59
+ * Optional code actions capability. When present, the provider
60
+ * supports code-action-based refactors.
61
+ */
62
+ codeActions?(file: string, position: CodePosition): Promise<RefactorResult[]>;
50
63
  }
51
64
 
52
65
  /**
package/src/types.ts CHANGED
@@ -104,6 +104,51 @@ export interface NodeAtData {
104
104
  }>;
105
105
  }
106
106
 
107
+ // ── Refactor types ───────────────────────────────────────────────────
108
+
109
+ /**
110
+ * A single file edit within a workspace edit.
111
+ */
112
+ export interface FileEdit {
113
+ /** Absolute file path */
114
+ file: string;
115
+ /** The source range to replace */
116
+ range: SourceRange;
117
+ /** The new text to insert */
118
+ newText: string;
119
+ }
120
+
121
+ /**
122
+ * A precise workspace edit — one or more file edits to apply atomically.
123
+ */
124
+ export interface WorkspaceEdit {
125
+ edits: FileEdit[];
126
+ }
127
+
128
+ /**
129
+ * A disambiguation candidate when a refactor target is ambiguous.
130
+ */
131
+ export interface DisambiguationCandidate {
132
+ description: string;
133
+ file?: string;
134
+ line?: number;
135
+ character?: number;
136
+ }
137
+
138
+ /**
139
+ * Result of a refactor operation.
140
+ *
141
+ * - `precise`: exact edits available for safe direct apply
142
+ * - `ambiguous`: multiple candidates, caller must disambiguate
143
+ * - `unavailable`: refactoring not possible
144
+ */
145
+ export type RefactorResult =
146
+ | { kind: "precise"; edits: WorkspaceEdit }
147
+ | { kind: "ambiguous"; candidates: DisambiguationCandidate[] }
148
+ | { kind: "unavailable"; reason: string };
149
+
150
+ // ── Structural data shapes (value types, range-flattened) ──────────────
151
+
107
152
  export interface CalleesData {
108
153
  enclosingScope: { name: string; startLine: number; endLine: number };
109
154
  callees: Array<{ name: string; startLine: number }>;
@@ -19,7 +19,11 @@ export interface WorkspaceContext {
19
19
  /** The working directory this context is scoped to. */
20
20
  cwd: string;
21
21
  /** Semantic analysis capability state and provider. */
22
- semantic: { state: CapabilityState; provider: SemanticProvider | null };
22
+ semantic: {
23
+ state: CapabilityState;
24
+ provider: SemanticProvider | null;
25
+ refactorAvailable: boolean;
26
+ };
23
27
  /** Structural analysis capability state and provider. */
24
28
  structural: { state: CapabilityState; provider: StructuralProvider | null };
25
29
  }
@@ -20,7 +20,12 @@ import type { CapabilityState, SemanticProvider, StructuralProvider } from "../c
20
20
  * provider instance (null when not ready).
21
21
  */
22
22
  export interface WorkspaceCapabilities {
23
- semantic: { state: CapabilityState; provider: SemanticProvider | null };
23
+ semantic: {
24
+ state: CapabilityState;
25
+ provider: SemanticProvider | null;
26
+ /** Whether the semantic provider supports precise refactoring operations */
27
+ refactorAvailable: boolean;
28
+ };
24
29
  structural: { state: CapabilityState; provider: StructuralProvider | null };
25
30
  }
26
31
 
@@ -33,6 +38,7 @@ function createDefaultCapabilities(): WorkspaceCapabilities {
33
38
  semantic: {
34
39
  state: { kind: "unavailable", reason: DEFAULT_UNAVAILABLE_REASON },
35
40
  provider: null,
41
+ refactorAvailable: false,
36
42
  },
37
43
  structural: {
38
44
  state: { kind: "unavailable", reason: DEFAULT_UNAVAILABLE_REASON },
@@ -41,6 +47,10 @@ function createDefaultCapabilities(): WorkspaceCapabilities {
41
47
  };
42
48
  }
43
49
 
50
+ function hasRefactorCapability(provider: SemanticProvider | null): boolean {
51
+ return !!(provider && (provider.rename !== undefined || provider.codeActions !== undefined));
52
+ }
53
+
44
54
  // ── Runtime ────────────────────────────────────────────────────────────
45
55
 
46
56
  /**
@@ -73,12 +83,13 @@ export class WorkspaceRuntime {
73
83
  * without affecting the structural provider.
74
84
  */
75
85
  registerSemantic(cwd: string, provider: SemanticProvider): void {
86
+ const refactorAvailable = hasRefactorCapability(provider);
76
87
  const existing = this.#workspaces.get(cwd);
77
88
  if (existing) {
78
- existing.semantic = { state: { kind: "ready" }, provider };
89
+ existing.semantic = { state: { kind: "ready" }, provider, refactorAvailable };
79
90
  } else {
80
91
  this.#workspaces.set(cwd, {
81
- semantic: { state: { kind: "ready" }, provider },
92
+ semantic: { state: { kind: "ready" }, provider, refactorAvailable },
82
93
  structural: createDefaultCapabilities().structural,
83
94
  });
84
95
  }