@mrclrchtr/supi-code-intelligence 6.3.0 → 7.0.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 (136) hide show
  1. package/README.md +164 -82
  2. package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  3. package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +8 -1
  4. package/node_modules/@mrclrchtr/supi-core/README.md +8 -0
  5. package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  6. package/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +10 -3
  7. package/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
  8. package/node_modules/@mrclrchtr/supi-core/src/llm.ts +141 -16
  9. package/node_modules/@mrclrchtr/supi-lsp/README.md +35 -13
  10. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  11. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +8 -1
  12. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +8 -0
  13. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  14. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +10 -3
  15. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
  16. package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/llm.ts +141 -16
  17. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/index.js +3 -1
  18. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/legacy.js +3 -1
  19. package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/package.json +1 -1
  20. package/node_modules/@mrclrchtr/supi-lsp/package.json +3 -3
  21. package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +16 -0
  22. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +43 -35
  23. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +83 -17
  24. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +108 -92
  25. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +44 -82
  26. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +3 -4
  27. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-publication.ts +9 -68
  28. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +45 -58
  29. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +230 -331
  30. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +201 -1
  31. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +129 -70
  32. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-typescript.ts +395 -0
  33. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +8 -12
  34. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +685 -183
  35. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +2 -2
  36. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +60 -60
  37. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-request-enrollment.ts +75 -0
  38. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-semantic-input-barrier.ts +443 -0
  39. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-semantic-input-errors.ts +30 -0
  40. package/node_modules/@mrclrchtr/supi-lsp/src/client/client-semantic-input-file.ts +15 -0
  41. package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +290 -37
  42. package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +72 -16
  43. package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +1 -0
  44. package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +30 -4
  45. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +1 -1
  46. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sentinels.ts +4 -32
  47. package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sources.ts +108 -0
  48. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +10 -4
  49. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-process-crash-report.ts +50 -1
  50. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +11 -7
  51. package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +770 -56
  52. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +3 -1
  53. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +37 -4
  54. package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +48 -12
  55. package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +50 -4
  56. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  57. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +8 -1
  58. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +8 -0
  59. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  60. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/footer-registry.ts +10 -3
  61. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +2 -0
  62. package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/llm.ts +141 -16
  63. package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +3 -3
  64. package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +2 -0
  65. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callee-display-name.ts +165 -0
  66. package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +67 -9
  67. package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +2 -0
  68. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +19 -18
  69. package/node_modules/yaml/browser/dist/nodes/Alias.js +25 -23
  70. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +19 -18
  71. package/node_modules/yaml/dist/nodes/Alias.js +25 -23
  72. package/node_modules/yaml/package.json +1 -1
  73. package/package.json +5 -5
  74. package/src/analysis/health/diagnostics.ts +1 -2
  75. package/src/analysis/health/file-scope.ts +4 -1
  76. package/src/analysis/health/server-status.ts +1 -1
  77. package/src/analysis/relations/callees.ts +17 -8
  78. package/src/analysis/relations/implementations.ts +1 -2
  79. package/src/analysis/relations/references.ts +8 -4
  80. package/src/analysis/relations/types.ts +6 -30
  81. package/src/analysis/target/anchored.ts +9 -1
  82. package/src/analysis/target/symbol.ts +29 -11
  83. package/src/analysis/target/types.ts +14 -6
  84. package/src/api.ts +2 -0
  85. package/src/session/graph/collect.ts +18 -3
  86. package/src/session/health-refresh.ts +27 -11
  87. package/src/session/health-types.ts +21 -4
  88. package/src/session/health-workflow.ts +28 -22
  89. package/src/session/orientation-types.ts +5 -6
  90. package/src/session/orientation-workflow.ts +10 -2
  91. package/src/session/session.ts +12 -5
  92. package/src/session/target-workflow.ts +9 -6
  93. package/src/substrate/lsp/maintenance.ts +53 -47
  94. package/src/substrate/lsp/source-tracking.ts +252 -0
  95. package/src/tool/code_find/guidance.ts +3 -3
  96. package/src/tool/code_find/spec.ts +5 -4
  97. package/src/tool/code_find/tui.ts +7 -1
  98. package/src/tool/code_graph/details.ts +32 -0
  99. package/src/tool/code_graph/display.ts +54 -0
  100. package/src/tool/code_graph/format.ts +60 -0
  101. package/src/tool/code_graph/guidance.ts +2 -2
  102. package/src/tool/code_graph/markdown.ts +76 -198
  103. package/src/tool/code_graph/read-next.ts +65 -0
  104. package/src/tool/code_graph/result.ts +118 -83
  105. package/src/tool/code_graph/tui.ts +216 -54
  106. package/src/tool/code_health/guidance.ts +3 -5
  107. package/src/tool/code_health/markdown.ts +90 -57
  108. package/src/tool/code_health/refresh-outcome.ts +51 -0
  109. package/src/tool/code_health/refresh-status.ts +130 -43
  110. package/src/tool/code_health/scope.ts +78 -0
  111. package/src/tool/code_health/spec.ts +1 -1
  112. package/src/tool/code_health/tui.ts +29 -38
  113. package/src/tool/code_inspect/guidance.ts +5 -3
  114. package/src/tool/code_inspect/tui.ts +7 -1
  115. package/src/tool/code_orientation/guidance.ts +3 -4
  116. package/src/tool/code_orientation/result.ts +31 -8
  117. package/src/tool/code_orientation/tui.ts +26 -5
  118. package/src/tool/code_refactor_apply/guidance.ts +1 -1
  119. package/src/tool/code_refactor_apply/tui.ts +7 -3
  120. package/src/tool/code_refactor_plan/guidance.ts +3 -5
  121. package/src/tool/code_refactor_plan/tui.ts +7 -1
  122. package/src/tool/code_resolve/guidance.ts +3 -5
  123. package/src/tool/code_resolve/result.ts +13 -10
  124. package/src/tool/code_resolve/tui.ts +18 -1
  125. package/src/tool/guidance.ts +11 -9
  126. package/src/tool/infra/truncate.ts +39 -13
  127. package/src/tool/result/candidate-row.ts +27 -0
  128. package/src/tool/result/errors.ts +21 -6
  129. package/src/tool/result/types.ts +7 -3
  130. package/src/tool/schemas.ts +5 -0
  131. package/src/types/execution.ts +2 -0
  132. package/src/types/index.ts +2 -0
  133. package/src/ui/tui/candidate-legacy-body.ts +69 -0
  134. package/src/ui/tui/candidate-selection.ts +366 -0
  135. package/src/ui/tui/common.ts +26 -31
  136. package/src/ui/tui/execution-error.ts +92 -0
package/README.md CHANGED
@@ -4,134 +4,216 @@
4
4
  </a>
5
5
  </div>
6
6
 
7
- # @mrclrchtr/supi-code-intelligence — LSP and Tree-sitter AST Code Intelligence for Pi
7
+ # @mrclrchtr/supi-code-intelligence
8
8
 
9
9
  [![GitHub stars](https://img.shields.io/github/stars/mrclrchtr/supi)](https://github.com/mrclrchtr/supi/stargazers) [![npm downloads](https://img.shields.io/npm/dm/@mrclrchtr/supi-code-intelligence)](https://www.npmjs.com/package/@mrclrchtr/supi-code-intelligence)
10
10
 
11
- Gives the [Pi coding agent](https://github.com/earendil-works/pi) direct, model-callable LSP semantic navigation and Tree-sitter AST structural code analysis.
11
+ A [Pi coding agent](https://github.com/earendil-works/pi) extension to navigate symbols, search code structure, check diagnostics, and preview and apply semantic refactors.
12
12
 
13
- ## LSP + AST, directly available to the agent
13
+ ## Install
14
14
 
15
- Instead of relying on file reads and text search alone, Pi can call focused `code_*` tools backed by:
15
+ ```bash
16
+ pi install npm:@mrclrchtr/supi-code-intelligence
17
+ ```
16
18
 
17
- - **Language servers (LSP)** for types, definitions, references, implementations, diagnostics, workspace symbols, and semantic refactoring.
18
- - **Tree-sitter ASTs** for syntax, outlines, source structure, structural search, and outgoing calls.
19
+ Add `-l` for a project-local install. To try the package for one run:
19
20
 
20
- The two sources complement each other without silently pretending one is the other. Results say which capability supplied the evidence and when semantic or structural analysis is unavailable.
21
+ ```bash
22
+ pi -e npm:@mrclrchtr/supi-code-intelligence
23
+ ```
21
24
 
22
- ## What your agent gets
25
+ For local development, run `pi install ./packages/supi-code-intelligence` from the SuPi repository root. Run `/reload` after changes.
23
26
 
24
- After installation, keep asking Pi normal coding questions. The agent can:
27
+ This package is included in the SuPi release installer. SuPi remains pre-release. The package bundles its LSP and Tree-sitter runtime dependencies, but not language-server binaries.
25
28
 
26
- - **Map an unfamiliar repository** — understand workspaces, packages, entry points, dependencies, and local `CLAUDE.md` or `AGENTS.md` instructions before editing.
27
- - **Navigate precisely with LSP** — identify the exact symbol at a source location and inspect its type, definition, enclosing declaration, and nearby diagnostics.
28
- - **Follow relationships across LSP and AST evidence** — find references, implementations, and outgoing calls without guessing from matching text.
29
- - **Search parsed code structure** — query AST definitions, types, interfaces, classes, methods, enums, imports, exports, and call sites. One owned Structural Worker keeps Pi responsive. Tool cancellation and the shared AST deadline propagate through an atomic cancellation flag into Worker reads, parser progress, and query progress.
30
- - **Correlate diagnostics** — each public `code_*` call gets one session-local opaque Debug Operation ID. Directly owned workflow, LSP, AST Scan, and Structural Worker events share it without changing normal Tool results.
31
- - **Check live project health** — inspect language-server status and current errors or warnings, with an option to refresh stale diagnostics.
32
- - **Refactor safely** — preview language-aware renames and extractions before applying them. Plans are rejected if the files changed in the meantime.
33
- - **See uncertainty clearly** — results distinguish “nothing found” from incomplete or unavailable analysis and disclose omitted matches.
29
+ ## What it adds
34
30
 
35
- When Pi recognizes a workspace, the agent also receives a compact architecture overview near the start of the session, so it can orient before spending turns opening files. The overview contains manifest facts (module names, one-line descriptions, declared topology, declared entrypoints, and detected languages), is labeled as untrusted repository evidence, and is controlled by the `code-intelligence.overviewEnabled` setting in `/supi-settings`.
31
+ - **Language Server Protocol (LSP) tools** for types, definitions, references, implementations, diagnostics, workspace symbols, and semantic refactoring.
32
+ - **Tree-sitter tools** for syntax, declarations, structural search, and calls as written in source code. These calls are not a semantic call graph.
33
+ - **Workspace orientation** from files, manifests, and declared package relationships. Directory orientation can also show local instruction files.
34
+ - **Visible evidence limits** that distinguish no matches from incomplete or unavailable analysis. Search modes do not silently switch to each other or to text search.
35
+ - **An optional first-turn overview** with discovered modules, manifest descriptions, declared entrypoints, dependencies, and detected languages. It is enabled by default and labeled as untrusted repository evidence, not instructions.
36
36
 
37
- ## Example requests
37
+ The overview is a hidden Pi message, not a live architecture graph. It is not repeated when the active session branch already contains it. All discovered modules are included: 1,000 estimated tokens is a warning threshold, not a size cap.
38
38
 
39
- You do not need to learn the tool-call syntax. Try asking Pi:
39
+ ## Usage
40
40
 
41
- - “Map this repository and explain where authentication lives.”
42
- - “Find every use and implementation of `PaymentProvider`.”
43
- - “What does `executeAskUser` call, and where is it referenced?”
44
- - “Find all exported interfaces under `packages/api`.”
45
- - “Check this project for current language-server diagnostics.”
46
- - “Rename `oldName` to `newName`, but show me the refactor plan before applying it.”
41
+ Ask Pi normal coding questions. For example:
47
42
 
48
- ## See it in action
43
+ - “Map this repository and find the authentication package.”
44
+ - “Find references and implementations of `PaymentProvider`.”
45
+ - “Show the calls written inside `executeAskUser`.”
46
+ - “Find interface declarations under `packages/api`.”
47
+ - “Refresh the language-server diagnostics for this file.”
48
+ - “Preview a rename from `oldName` to `newName`. Do not apply it yet.”
49
49
 
50
- Select any screenshot to open it at full resolution.
50
+ ### Agent tools
51
51
 
52
- ### Understand the workspace
52
+ The full extension registers all eight tools at startup; it does not load them on demand.
53
53
 
54
- [![Workspace orientation showing package files, manifest details, and relationships][workspace-orientation]][workspace-orientation]
54
+ | Tool | Purpose |
55
+ |---|---|
56
+ | `code_orientation` | Show workspace facts, or focus on a path, module, or symbol target |
57
+ | `code_resolve` | Resolve a real symbol anchor or semantic query to target handles, or list a file's declarations |
58
+ | `code_inspect` | Inspect syntax, the enclosing declaration, hover information, definitions, and nearby diagnostics at one point |
59
+ | `code_graph` | Find semantic references and implementations, or structural calls from the enclosing scope |
60
+ | `code_find` | Search with an explicit `ast` or `semantic` mode |
61
+ | `code_health` | Report diagnostic observations and language-server health |
62
+ | `code_refactor_plan` | Store a semantic refactor preview without changing files |
63
+ | `code_refactor_apply` | Apply a fresh stored plan after file and edit checks |
64
+
65
+ Use Pi's `grep` for literal or regular-expression search. Source points use 1-based lines and 1-based UTF-16 columns. A target or focus selector must contain exactly one choice.
66
+
67
+ Example tool calls:
68
+
69
+ ```javascript
70
+ code_orientation({ focus: { path: "packages/api" } })
71
+ code_find({ query: "PaymentProvider", mode: "semantic", scope: ["packages/api"] })
72
+ code_health({ scope: "packages/api/src/index.ts", refresh: true })
73
+ ```
55
74
 
56
- ### Inspect an exact symbol
75
+ Important tool rules:
57
76
 
58
- [![Symbol inspection showing syntax, hover information, definition, and diagnostics][symbol-inspection]][symbol-inspection]
77
+ - **Resolve:** new target handles require semantic readiness. A comment or whitespace point is not a symbol; use `code_inspect` there. Handles are session-local and become stale when file contents change. Resolve the symbol again rather than reuse a stale handle.
78
+ - **Graph:** relations are `references` (default), `callees`, and `implements`. Use `["all"]` for all three. Callee depth is `direct` by default; `deep` includes nested scopes, not transitive calls. Callees match source shape, not symbol identity. Counts include each distinct call site; repeated expressions share one agent-output row with all shown line/column coordinates. Each relation reports its counts and limits once. Provider-limited results have unknown totals; invalid locations are disclosed separately. Callee previews shorten receiver argument lists from syntax without changing grouping by the full expression. Matching previews get local expression numbers so distinct source expressions remain clear. Unavailable references retain the provider reason, including an exhausted enrollment retry. Unavailable callees retain the provider reason and a source-inspection next step. Ambiguous targets ask for candidate selection, not input correction. Candidate limits retain exact totals, or unknown totals when the provider returns partial data. Agent output and both transcript views disclose omissions. Only shown candidates receive target handles. The human transcript shows the resolved target and per-relation evidence types and status. The expanded view groups up to 20 sites per relation by file, without a duplicate Markdown body. If this display limit hides returned sites, the transcript links to a temporary file with all returned evidence. This file does not include evidence beyond `maxResults`, and its path does not add text to an otherwise complete agent result. Merged read ranges use neutral guidance.
79
+ - **Find:** AST mode requires `kind`: `definition`, `import`, `export`, `call`, `type`, `interface`, `class`, `method`, or `enum`. Semantic mode does not accept `kind`. A supplied `scope` is a non-empty array.
80
+ - **Health:** `include` accepts `diagnostics` and `servers` (both by default); `level` is `summary` (default) or `detailed`. Server inventory and route counts remain workspace-wide, even with a diagnostic scope. A diagnostic snapshot does not prove that the whole workspace is clean. Tsconfig and jsconfig coverage applies only to TypeScript and JavaScript-family files; other-language files have no `Tsconfig` label.
59
81
 
60
- ### Follow references and calls
82
+ `code_health({ refresh: true })` retries failed startup and exhausted process-crash routes in scope, with at most one attempt per route per call. It collects fresh diagnostic evidence and reports recovery separately from diagnostic confirmation. A broad maintenance attempt can include active tracked files outside a requested directory, but the diagnostic result keeps the requested directory and tracked-file boundary. The report labels maintenance evidence separately from result coverage. A later refresh can retry a failed route. Reports show up to 16 route entries per recovery list and disclose omitted entries. Use an exact file scope when a route reports `use-exact-file`.
61
83
 
62
- [![Relationship graph showing references and direct calls][relationship-graph]][relationship-graph]
84
+ ### Transcript failures
63
85
 
64
- ### Check live health
86
+ All Code Intelligence tools show PI execution failures with the tool name and the available reason. Structured failure text takes priority; a failure without details uses PI's plain error text. The transcript removes terminal controls and keeps up to 4096 characters. Collapsed output keeps two wrapped rows; expanded output keeps 20. A notice discloses further display limits. These limits do not change agent output or saved results.
65
87
 
66
- [![Code health showing diagnostics and running language servers][code-health]][code-health]
88
+ Candidate selection for Graph, Resolve, and Orientation uses one structured transcript view. The collapsed view shows `Choose a target` and one count summary. The expanded view shows one candidate section and selection guidance; it does not repeat raw Markdown when candidate rows are available. Older results use structured evidence when available. When candidate rows are unavailable, or structured reason or guidance is missing, the renderer uses a bounded raw detail view with up to 4096 source characters and 40 wrapped body rows. It shows a truncation notice and keeps any existing full-output link.
67
89
 
68
- ### Preview a safe refactor
90
+ ### Refactor checks
69
91
 
70
- [![Refactor plan previewing a semantic rename without changing files][refactor-plan]][refactor-plan]
92
+ The planner accepts one target handle or anchor and one operation: `rename_symbol`, `extract_function`, `extract_variable`, `update_imports`, or `delete_dead_code`. Availability depends on the language server. Unsupported operations do not fall back to text edits.
71
93
 
72
- ## Agent tools
94
+ Plans are held in memory for the current session. Apply accepts only the returned `planId`; it does not create or regenerate a plan. It checks SHA-256 file fingerprints, provider-authorized roots, document versions when available, edit ranges, and overlaps before writing. Changed files require a new plan. A successful apply removes the plan.
73
95
 
74
- The package adds eight tools that Pi selects as needed:
96
+ Refactors can change several files. If a later write fails, the tool attempts to restore earlier files and reports restoration failures. It does not create a Git commit. The plan/apply split is not a user confirmation dialog: the agent can call apply. Review the diff and run tests.
75
97
 
76
- | Tool | What it lets the agent do |
77
- |---|---|
78
- | `code_orientation` | Understand a workspace, package, directory, file, or symbol before reading broadly |
79
- | `code_resolve` | Resolve an exact symbol, disambiguate matches, or list declarations in a file |
80
- | `code_inspect` | Combine AST syntax with LSP type, definition, symbol, and diagnostic facts at one source location |
81
- | `code_graph` | Follow LSP references and implementations plus AST calls made by a symbol |
82
- | `code_find` | Search LSP workspace symbols or parsed AST source structure rather than raw text |
83
- | `code_health` | Check live diagnostics, language servers, and code-intelligence availability |
84
- | `code_refactor_plan` | Preview a precise rename, extraction, import cleanup, or dead-code deletion without changing files |
85
- | `code_refactor_apply` | Apply a fresh refactor plan after safety checks |
98
+ ## Language support
86
99
 
87
- Pi's built-in `grep` remains the right tool for literal or regular-expression searches; these tools add symbol and source-structure awareness.
100
+ Install the required language servers yourself. The extension detects project languages and starts available configured commands on `PATH` in trusted projects. It does not download or install servers. Individual semantic features depend on server support and readiness.
88
101
 
89
- `code_health({ refresh: true })` reports process-crash recovery as route-level data. It shows exact recovered, skipped, failed, and exhausted counts. It shows up to 16 server and workspace-relative root entries, plus the exact number of omitted entries. A skipped route gives the `use-exact-file` action. A failed or exhausted route gives the `reload-workspace` action. Markdown and expanded TUI output show route entries and bounded failure details. Compact TUI output shows the counts. Current and retained refresh results use the same outcome format.
102
+ Tree-sitter grammars are bundled and parse locally. Grammar selection uses the file extension, not a shebang.
90
103
 
91
- ## Install
104
+ | Language | Default LSP binary | Tree-sitter file extensions |
105
+ |---|---|---|
106
+ | TypeScript / JavaScript | `typescript-language-server` | `.ts`, `.mts`, `.cts`, `.tsx`, `.js`, `.jsx`, `.mjs`, `.cjs` |
107
+ | Python | `pyright-langserver` | `.py`, `.pyi` |
108
+ | Rust | `rust-analyzer` | `.rs` |
109
+ | Go | `gopls` | `.go` |
110
+ | C / C++ | `clangd` | `.c`, `.h`, `.cpp`, `.hpp`, `.cc`, `.cxx`, `.hxx`, `.c++`, `.h++` |
111
+ | Bash | `bash-language-server` | `.sh`, `.bash`, `.zsh`, `.ksh` (Bash grammar) |
112
+ | HTML | `vscode-html-language-server` | `.html`, `.htm`, `.xhtml` |
113
+ | SQL | `sql-language-server` | `.sql` |
114
+ | Ruby | `ruby-lsp` | `.rb`, `.gemspec` |
115
+ | Java | `jdtls` | `.java` |
116
+ | Kotlin | `kotlin-lsp` | `.kt`, `.kts` |
117
+ | R | `R` with the `languageserver` package | `.r` |
92
118
 
93
- ```bash
94
- pi install npm:@mrclrchtr/supi-code-intelligence
119
+ Operation support is narrower than grammar support. AST import and export search supports only JavaScript, TypeScript, and TSX. Other AST operations depend on the grammar's extractors. A missing LSP server does not prevent available workspace or structural queries, but it prevents new semantic targets and related operations.
120
+
121
+ ### Search and output limits
122
+
123
+ - An AST search has a 5,000 eligible-file limit and a 10-second deadline shared by file enumeration and analysis. These are not tool-call settings.
124
+ - Below directory roots, AST search excludes hidden entries, dependency/build/cache directories, symlinks, non-regular files, and files unsupported by the requested operation. It does **not** read `.gitignore`. Explicit roots are resolved and honored, including symlink roots. See the [scan policy](src/analysis/search/ast-scan.ts) for the exact directory list.
125
+ - An exact file that does not support the requested AST operation is invalid. Results disclose policy exclusions, interrupted scans, provider limits, and omitted matches. No matches do not mean that unsupported files were searched.
126
+ - Tool text is truncated at Pi's default 2,000 lines or 50 KB. When this occurs, the full text is written to a temporary file and its path is returned. Result-list limits still apply to that full text.
127
+
128
+ ## Status and settings
129
+
130
+ In interactive Pi, open the status overlay:
131
+
132
+ ```text
133
+ /supi-ci-status
95
134
  ```
96
135
 
97
- To try it for one run without installing:
136
+ It shows server routes and roots, missing or running servers, diagnostics, and capability warnings. The terminal must be at least 60 columns wide. Use Up/Down to select a diagnostic file, Enter or Space to expand it, `r` to reload the displayed snapshot, `a` to collapse it, and Escape to close. The extension also adds LSP status to the footer. Use `code_health` for health reports outside the interactive terminal.
98
137
 
99
- ```bash
100
- pi -e npm:@mrclrchtr/supi-code-intelligence
138
+ The package registers **Code Intelligence** and **LSP** settings. If `@mrclrchtr/supi-settings` is installed, use `/supi-settings` to edit them. A standalone Code Intelligence install does not include that settings UI.
139
+
140
+ Configuration files:
141
+
142
+ - Global: `~/.pi/agent/supi/config.json`
143
+ - Project: `.pi/supi/config.json`
144
+
145
+ Project values override global values, which override defaults. Project configuration and instruction discovery require project trust. For an untrusted project, the overview setting uses global values and defaults only; no LSP controller is started for that session.
146
+
147
+ | Setting | Default | Effect |
148
+ |---|---|---|
149
+ | `code-intelligence.overviewEnabled` | `true` | Add the hidden overview; the choice is fixed for the session |
150
+ | `code-intelligence.instructionFileNames` | `["CLAUDE.md", "AGENTS.md"]` | Ordered plain filenames for directory instruction discovery |
151
+ | `lsp.exclude` | `[]` | Gitignore-style patterns for automatic LSP work, not exact-file requests |
152
+ | `lsp.servers.<language>.enabled` | Enabled unless `false` | Disable a language server |
153
+
154
+ Example `.pi/supi/config.json`:
155
+
156
+ ```json
157
+ {
158
+ "code-intelligence": {
159
+ "overviewEnabled": false,
160
+ "instructionFileNames": ["AGENTS.md", "CLAUDE.md"]
161
+ },
162
+ "lsp": {
163
+ "exclude": ["generated/**"],
164
+ "servers": {
165
+ "python": { "enabled": false }
166
+ }
167
+ }
168
+ }
101
169
  ```
102
170
 
103
- ## Language support
171
+ Use `typescript`, `python`, `rust`, `go`, `c`, `ruby`, `java`, `kotlin`, `bash`, `html`, `sql`, or `r` for built-in server keys (`cpp` aliases `c`). Server command and routing overrides are defined in the [LSP configuration reference](../supi-lsp/README.md#custom-server-configuration). `.pi-lsp.json` is not read. Restart Pi after server configuration changes. Only the boolean `true` enables the overview; non-boolean values do not enable it.
172
+
173
+ Directory orientation checks the path from the workspace root to the focused directory. It selects the first valid configured instruction file per directory, skips files already loaded by Pi or shown on the active branch, and shows at most 200 lines per file. Resolved instruction paths must stay inside the workspace. These snippets are tool output, not additions to Pi's system prompt.
174
+
175
+ ## Privacy and security
104
176
 
105
- Structural code search is bundled with the package. Full symbol navigation, references, diagnostics, and semantic refactoring require the matching language server on `PATH`.
177
+ Pi extensions run with your system permissions; this package is not a sandbox. Language servers run as local processes and receive source files. Review server commands and project configuration before trusting a project. `lsp.exclude` and AST scan exclusions are not access controls.
106
178
 
107
- The extension detects project languages and starts installed servers automatically:
179
+ Tool results and the hidden overview enter Pi's model context and can be saved in session history. They can contain source text, paths, manifest data, diagnostics, and instruction-file contents. Truncated tool results and graph display overflow also leave full returned text in local temporary files. These files are not durable session storage and can be removed by system cleanup. “Hidden” means not displayed in the transcript, not hidden from the model.
108
180
 
109
- | Language | Required binary |
181
+ ## Public entrypoints
182
+
183
+ | Export | Surface |
110
184
  |---|---|
111
- | TypeScript / JavaScript | `typescript-language-server` |
112
- | Python | `pyright-langserver` |
113
- | Rust | `rust-analyzer` |
114
- | Go | `gopls` |
115
- | C / C++ | `clangd` |
116
- | Bash | `bash-language-server` |
117
- | HTML | `vscode-html-language-server` |
118
- | SQL | `sql-language-server` |
119
- | Ruby | `ruby-lsp` |
120
- | Java | `jdtls` |
121
- | Kotlin | `kotlin-lsp` |
122
- | R | `R` with the `languageserver` package |
123
-
124
- If a server is missing, the agent can still use available workspace and structural evidence. Semantic features report that they are unavailable rather than silently guessing.
185
+ | `@mrclrchtr/supi-code-intelligence/api` | Type-only provider contracts, architecture models, targets, health observations, and tool results; no runtime functions |
186
+ | `@mrclrchtr/supi-code-intelligence/extension` | Default full Pi extension factory |
187
+ | `@mrclrchtr/supi-code-intelligence/headless` | Default inspection-only extension factory and `HEADLESS_INSPECTION_TOOL_NAMES` |
188
+ | `@mrclrchtr/supi-code-intelligence/package.json` | Package manifest |
125
189
 
126
- ## Status and settings
190
+ The package-root export also re-exports types; prefer `/api`. See [the type exports](src/api.ts) for the complete list.
127
191
 
128
- Open the status view to see each LSP route with its workspace-relative root, running or missing servers, typed route issue counts, and capability warnings:
192
+ The headless factory registers only `code_resolve`, `code_inspect`, `code_orientation`, `code_graph`, `code_find`, and `code_health` for managed child sessions. It adds no refactor tools, settings, commands, UI, or overview. It is a tool profile, not a filesystem sandbox.
129
193
 
130
- ```text
131
- /supi-ci-status
132
- ```
194
+ ## See it in action
195
+
196
+ Select any screenshot to open it at full resolution.
133
197
 
134
- Use `/supi-settings` to disable language servers you do not need, change the instruction filenames surfaced during directory orientation (defaults `CLAUDE.md` and `AGENTS.md`), or disable the first-turn architecture overview with `overviewEnabled`.
198
+ ### Understand the workspace
199
+
200
+ [![Workspace orientation showing package files, manifest details, and relationships][workspace-orientation]][workspace-orientation]
201
+
202
+ ### Inspect an exact symbol
203
+
204
+ [![Symbol inspection showing syntax, hover information, definition, and diagnostics][symbol-inspection]][symbol-inspection]
205
+
206
+ ### Follow references and calls
207
+
208
+ [![Relationship graph showing references and direct calls][relationship-graph]][relationship-graph]
209
+
210
+ ### Check live health
211
+
212
+ [![Code health showing diagnostics and running language servers][code-health]][code-health]
213
+
214
+ ### Preview a refactor
215
+
216
+ [![Refactor plan previewing a semantic rename without changing files][refactor-plan]][refactor-plan]
135
217
 
136
218
  [workspace-orientation]: https://raw.githubusercontent.com/mrclrchtr/supi/main/packages/supi-code-intelligence/assets/workspace-orientation.png
137
219
  [symbol-inspection]: https://raw.githubusercontent.com/mrclrchtr/supi/main/packages/supi-code-intelligence/assets/symbol-inspection.png
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-code-runtime",
3
- "version": "6.3.0",
3
+ "version": "7.0.0",
4
4
  "description": "Shared workspace context and capability contracts for code intelligence",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -234,7 +234,14 @@ export type CalleeDepth = "direct" | "deep";
234
234
  */
235
235
  export interface CalleesData {
236
236
  enclosingScope: { name: string; startLine: number; endLine: number };
237
- callees: Array<{ name: string; startLine: number }>;
237
+ /** Distinct call sites with 1-based UTF-16 start coordinates. */
238
+ callees: Array<{
239
+ name: string;
240
+ /** Optional syntax-shortened label for presentation; does not replace `name`. */
241
+ displayName?: string;
242
+ startLine: number;
243
+ startCharacter: number;
244
+ }>;
238
245
  depth: CalleeDepth;
239
246
  }
240
247
 
@@ -21,6 +21,7 @@ pnpm add @mrclrchtr/supi-core
21
21
  ## Package surfaces
22
22
 
23
23
  - `@mrclrchtr/supi-core/api` — reusable helpers for other packages and extensions
24
+ - `@mrclrchtr/supi-core/llm` — PI-owned direct model requests and JSON helpers
24
25
  - `@mrclrchtr/supi-core/report` — shared text/report rendering helpers for TUI and plain-text summaries
25
26
 
26
27
  ## What you get from the API
@@ -48,6 +49,13 @@ Config file locations:
48
49
 
49
50
  - `wrapExtensionContext()` — wrap injected text in SuPi's `<extension-context>` tag
50
51
 
52
+ ### Model requests
53
+
54
+ - `completeModelRequest(ctx, model, context, options)` — complete through PI's model registry with stable feature affinity. PI owns auth and endpoint resolution.
55
+ - `callWithJsonResponse()` — retry a registry request, extract JSON, and validate it with TypeBox.
56
+
57
+ `completeModelRequest()` requires a stable `affinityScope`. It keeps cache retention defaults, does not include prompt content in the affinity ID, and adds OpenCode headers only when the provider or exact model endpoint matches OpenCode. Pass `maxTokens: model.maxTokens` when a caller needs the model's declared output cap without using PI private modules.
58
+
51
59
  ### Shared registries
52
60
 
53
61
  - context-provider registry for `/supi-context`
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrclrchtr/supi-core",
3
- "version": "6.3.0",
3
+ "version": "7.0.0",
4
4
  "description": "Shared settings, configuration, reporting, and session infrastructure",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -2,17 +2,24 @@
2
2
  //
3
3
  // Extensions register pre-styled text chunks with a placement hint
4
4
  // ("stats" for the metrics line, "status" for the extension status line).
5
- // The custom footer in supi-extras (or PI's built-in footer) reads these
6
- // contributions and renders them alongside the built-in metrics.
5
+ // The custom footer in supi-extras reads these contributions and renders them
6
+ // alongside the built-in metrics. Extensions can use PI's status API as a
7
+ // fallback when the custom footer is not installed.
7
8
 
8
9
  import { createRegistry } from "./registry-utils.ts";
9
10
 
11
+ /** Event emitted when a dynamic footer contribution needs a new render. */
12
+ export const FOOTER_INVALIDATE_EVENT = "supi:footer:invalidate";
13
+
10
14
  /** Where the contribution should appear in the footer. */
11
15
  export type FooterPlacement = "stats" | "stats-end" | "status";
12
16
 
13
17
  /** A single footer contribution registered by an extension. */
14
18
  export interface FooterContribution {
15
- /** Unique key for this contribution. Re-registering with the same key replaces it. */
19
+ /**
20
+ * Unique key for this contribution. Re-registering with the same key replaces it.
21
+ * A same-key Pi status is treated as this contribution's built-in-footer fallback.
22
+ */
16
23
  key: string;
17
24
  /** Which footer line this belongs on. */
18
25
  placement: FooterPlacement;
@@ -15,6 +15,8 @@ export * from "./debug.ts";
15
15
  // biome-ignore lint/performance/noReExportAll: intentional convenience barrel
16
16
  export * from "./footer-registry.ts";
17
17
  // biome-ignore lint/performance/noReExportAll: intentional convenience barrel
18
+ export * from "./llm.ts";
19
+ // biome-ignore lint/performance/noReExportAll: intentional convenience barrel
18
20
  export * from "./model-selection.ts";
19
21
  // biome-ignore lint/performance/noReExportAll: intentional convenience barrel
20
22
  export * from "./path.ts";
@@ -1,12 +1,131 @@
1
- import { complete } from "@earendil-works/pi-ai/compat";
1
+ import { createHash } from "node:crypto";
2
+ import type {
3
+ Api,
4
+ AssistantMessage,
5
+ Context,
6
+ Model,
7
+ ModelsApiStreamOptions,
8
+ ProviderHeaders,
9
+ } from "@earendil-works/pi-ai";
2
10
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
3
11
  import type { TSchema } from "typebox";
4
12
  import { Value } from "typebox/value";
5
13
 
6
14
  // Shared LLM utilities for SuPi extensions.
7
15
  //
8
- // Provides retry logic, structured LLM call helpers, and other
9
- // common patterns for extensions that interact with AI models.
16
+ // Provides PI-owned model requests, retry logic, structured LLM call helpers,
17
+ // and other common patterns for extensions that interact with AI models.
18
+
19
+ const MODEL_REQUEST_NAMESPACE = "supi-direct-model-request-v1";
20
+
21
+ /**
22
+ * Options for {@link completeModelRequest}.
23
+ *
24
+ * Authentication, provider environment, and session identity stay under PI
25
+ * control. The feature supplies a stable scope for its prompt stream.
26
+ */
27
+ export type CompleteModelRequestOptions<TApi extends Api = Api> = Omit<
28
+ ModelsApiStreamOptions<TApi>,
29
+ "apiKey" | "env" | "sessionId"
30
+ > & {
31
+ /** Stable feature scope. Do not include prompt, turn, or retry data. */
32
+ affinityScope: string;
33
+ /** PI owns these fields, including for APIs with open-ended option types. */
34
+ apiKey?: never;
35
+ env?: never;
36
+ sessionId?: never;
37
+ };
38
+
39
+ function createModelRequestAffinityId(
40
+ sessionId: string,
41
+ affinityScope: string,
42
+ model: Model<Api>,
43
+ ): string {
44
+ const material = JSON.stringify([
45
+ MODEL_REQUEST_NAMESPACE,
46
+ sessionId,
47
+ affinityScope,
48
+ model.provider,
49
+ model.id,
50
+ ]);
51
+ const digest = createHash("sha256").update(material, "utf8").digest("hex");
52
+ return `supi-${digest.slice(0, 56)}`;
53
+ }
54
+
55
+ function isOpenCodeModel(model: Model<Api>): boolean {
56
+ if (model.provider === "opencode" || model.provider === "opencode-go") return true;
57
+
58
+ try {
59
+ return new URL(model.baseUrl).hostname === "opencode.ai";
60
+ } catch {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ function hasHeader(headers: ProviderHeaders, name: string): boolean {
66
+ const lowerName = name.toLowerCase();
67
+ return Object.keys(headers).some((headerName) => headerName.toLowerCase() === lowerName);
68
+ }
69
+
70
+ function addOpenCodeDefaultHeaders(
71
+ model: Model<Api>,
72
+ affinityId: string,
73
+ headers: ProviderHeaders,
74
+ ): ProviderHeaders {
75
+ if (!isOpenCodeModel(model)) return headers;
76
+
77
+ const result = { ...headers };
78
+ if (!hasHeader(result, "x-opencode-session")) {
79
+ result["x-opencode-session"] = affinityId;
80
+ }
81
+ if (!hasHeader(result, "x-opencode-client")) {
82
+ result["x-opencode-client"] = "pi";
83
+ }
84
+ return result;
85
+ }
86
+
87
+ /**
88
+ * Complete a direct request through PI's model registry.
89
+ *
90
+ * PI resolves authentication, provider headers, environment, and the
91
+ * effective endpoint. This helper adds one stable opaque session identity for
92
+ * the feature prompt stream and applies the OpenCode compatibility defaults.
93
+ * It does not retry, validate output, or present errors.
94
+ *
95
+ * When `maxTokens` is omitted, the underlying registry receives no explicit
96
+ * output cap. A caller that needs the selected model's declared cap can pass
97
+ * `maxTokens: model.maxTokens` without importing PI internals.
98
+ */
99
+ export async function completeModelRequest<TApi extends Api>(
100
+ ctx: ExtensionContext,
101
+ model: Model<TApi>,
102
+ context: Context,
103
+ options: CompleteModelRequestOptions<TApi>,
104
+ ): Promise<AssistantMessage> {
105
+ const { affinityScope, transformHeaders: callerTransformHeaders, ...requestOptions } = options;
106
+ const safeRequestOptions = { ...requestOptions };
107
+ delete safeRequestOptions.apiKey;
108
+ delete safeRequestOptions.env;
109
+ delete safeRequestOptions.sessionId;
110
+
111
+ const affinityId = createModelRequestAffinityId(
112
+ ctx.sessionManager.getSessionId(),
113
+ affinityScope,
114
+ model,
115
+ );
116
+ const transformHeaders = async (headers: ProviderHeaders): Promise<ProviderHeaders> => {
117
+ const transformed = callerTransformHeaders ? await callerTransformHeaders(headers) : headers;
118
+ return addOpenCodeDefaultHeaders(model, affinityId, transformed);
119
+ };
120
+
121
+ // Restore PI's conditional provider-option type after removing owned fields.
122
+ return ctx.modelRegistry.complete(model, context, {
123
+ ...safeRequestOptions,
124
+ signal: safeRequestOptions.signal ?? ctx.signal,
125
+ sessionId: affinityId,
126
+ transformHeaders,
127
+ } as unknown as ModelsApiStreamOptions<TApi>);
128
+ }
10
129
 
11
130
  /**
12
131
  * Options for {@link withRetry}.
@@ -122,6 +241,8 @@ export function extractJsonFromResponse<T extends TSchema>(
122
241
  export interface CallWithJsonResponseOptions {
123
242
  /** The prompt to send to the LLM. */
124
243
  prompt: string;
244
+ /** Stable feature scope for request affinity. Do not include prompt or retry data. */
245
+ affinityScope: string;
125
246
  /** Optional data context appended to the prompt. */
126
247
  dataContext?: string;
127
248
  /** Maximum tokens for the response. Default: 4096 */
@@ -135,8 +256,9 @@ export interface CallWithJsonResponseOptions {
135
256
  /**
136
257
  * Call the LLM with a prompt and validate the JSON response against a TypeBox schema.
137
258
  *
138
- * Handles model resolution, auth, retry via `withRetry`, text extraction,
139
- * JSON regex matching, and TypeBox validation.
259
+ * Handles model resolution, retry via `withRetry`, text extraction, JSON
260
+ * matching, and TypeBox validation. The request itself stays under PI
261
+ * registry authority through {@link completeModelRequest}.
140
262
  *
141
263
  * Returns `null` when:
142
264
  * - No model is available
@@ -145,7 +267,7 @@ export interface CallWithJsonResponseOptions {
145
267
  * - JSON doesn't match the schema
146
268
  * - The request is aborted
147
269
  *
148
- * @param ctx - The extension context for model resolution and auth.
270
+ * @param ctx - The extension context for model selection and PI registry access.
149
271
  * @param options - Call options including prompt, schema, and retry config.
150
272
  * @param schema - TypeBox schema to validate the JSON response against.
151
273
  * @returns The parsed and validated result, or `null`.
@@ -155,14 +277,18 @@ export async function callWithJsonResponse<T extends TSchema>(
155
277
  options: CallWithJsonResponseOptions,
156
278
  schema: T,
157
279
  ): Promise<{ parsed: import("typebox").Static<T> } | null> {
158
- const { prompt, dataContext, maxTokens = 4096, systemPrompt = "", retries = 2 } = options;
280
+ const {
281
+ prompt,
282
+ affinityScope,
283
+ dataContext,
284
+ maxTokens = 4096,
285
+ systemPrompt = "",
286
+ retries = 2,
287
+ } = options;
159
288
 
160
289
  const model = ctx.model ?? ctx.modelRegistry.getAvailable()[0] ?? null;
161
290
  if (!model) return null;
162
291
 
163
- const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
164
- if (!auth.ok || !auth.apiKey) return null;
165
-
166
292
  const fullPrompt = dataContext
167
293
  ? `${prompt}
168
294
 
@@ -171,8 +297,9 @@ ${dataContext}`
171
297
  : prompt;
172
298
 
173
299
  const response = await withRetry(
174
- async () => {
175
- return complete(
300
+ async () =>
301
+ completeModelRequest(
302
+ ctx,
176
303
  model,
177
304
  {
178
305
  systemPrompt,
@@ -185,13 +312,11 @@ ${dataContext}`
185
312
  ],
186
313
  },
187
314
  {
188
- apiKey: auth.apiKey,
189
- headers: auth.headers,
315
+ affinityScope,
190
316
  signal: ctx.signal,
191
317
  maxTokens,
192
318
  },
193
- );
194
- },
319
+ ),
195
320
  { retries, baseDelayMs: 1000, signal: ctx.signal },
196
321
  );
197
322