python-delphi-lsp 1.0.0__tar.gz → 1.1.0__tar.gz
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.
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/MANIFEST.in +1 -0
- {python_delphi_lsp-1.0.0/python_delphi_lsp.egg-info → python_delphi_lsp-1.1.0}/PKG-INFO +153 -9
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/README.md +152 -8
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/__init__.py +4 -0
- python_delphi_lsp-1.1.0/delphiast/agent_cli.py +99 -0
- python_delphi_lsp-1.1.0/delphiast/agent_layers.py +331 -0
- python_delphi_lsp-1.1.0/delphiast/agent_templates.py +181 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/lsp_server.py +62 -3
- python_delphi_lsp-1.1.0/delphiast/project_discovery.py +375 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/opencode.json +1 -5
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/pyproject.toml +2 -1
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0/python_delphi_lsp.egg-info}/PKG-INFO +153 -9
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/python_delphi_lsp.egg-info/SOURCES.txt +8 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/python_delphi_lsp.egg-info/entry_points.txt +1 -0
- python_delphi_lsp-1.1.0/scripts/bootstrap_vllm_codebase_skill_test.py +227 -0
- python_delphi_lsp-1.1.0/tests/test_agent_codebase.py +138 -0
- python_delphi_lsp-1.1.0/tests/test_bootstrap_vllm_codebase_skill.py +56 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_opencode_config.py +9 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_package_metadata.py +6 -2
- python_delphi_lsp-1.1.0/tests/test_project_discovery.py +174 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/LICENSE +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/binary.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/comment_builder.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/consts.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/grammar.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/lark_builder.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/lark_tokens.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/nodes.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/parser.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/preprocessor.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/project_indexer.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/semantic.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/semantic_builder.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/source_reader.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/workspace.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/delphiast/writer.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/python_delphi_lsp.egg-info/dependency_links.txt +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/python_delphi_lsp.egg-info/requires.txt +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/python_delphi_lsp.egg-info/top_level.txt +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/audit_delphi_language_features.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/bootstrap_vllm_opencode_test.ps1 +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/bootstrap_vllm_opencode_test.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/bootstrap_vllm_opencode_test.sh +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/check_ornith_cache.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/generate_release_evidence.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/ollama/ornith-lspctx.Modelfile +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/prepare_ornith_cache.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/run_opencode_lsp_probe.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/start_ornith_vllm.sh +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/scripts/summarize_opencode_request_payloads.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/setup.cfg +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/DeprecatedOnConst.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/VariantRecordFieldAttributes.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/alignedrecords.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/constset.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/deprecatedtype.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/dottedtypes.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/endtoken.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/experimentals.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/externalfunction.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/finalizationinitializationexports.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/forwardoverloaded.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/forwardwithoutsemicolon.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/genericconstraints.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/genericinterfacemethoddelegation.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/implementsgenerictype.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/include file2.inc +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/includefile.inc +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/includefile.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/managedrecords.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/messagemethod.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/multiline.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/nonalignedrecords.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/numbers.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/pointerchars.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/properties.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/strictvisibility.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/tryexcept.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/umlauts.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/whitespacearoundifdefcondition.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/library_demo.dpr +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/package_demo.dpk +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/program_demo.dpr +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_advanced.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_attributes.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_basic.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_consumer.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_generics.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_inheritance.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_math.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_properties.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_sections.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_statements.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_types.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_unresolved.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_with.pas +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_bootstrap_vllm_opencode.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_diagnostics.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_language_feature_matrix.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_legacy_snippets.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_lsp_features.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_lsp_support.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_opencode_probe.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_opencode_request_payloads.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_ornith_cache_prepare.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_parser.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_preprocessor.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_project_indexer.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_release_evidence.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_semantic.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_vllm_start_script.py +0 -0
- {python_delphi_lsp-1.0.0 → python_delphi_lsp-1.1.0}/tests/test_workspace.py +0 -0
|
@@ -4,6 +4,7 @@ include opencode.json
|
|
|
4
4
|
include scripts/check_ornith_cache.py
|
|
5
5
|
include scripts/audit_delphi_language_features.py
|
|
6
6
|
include scripts/bootstrap_vllm_opencode_test.py
|
|
7
|
+
include scripts/bootstrap_vllm_codebase_skill_test.py
|
|
7
8
|
include scripts/bootstrap_vllm_opencode_test.ps1
|
|
8
9
|
include scripts/bootstrap_vllm_opencode_test.sh
|
|
9
10
|
include scripts/generate_release_evidence.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-delphi-lsp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Python Delphi/Object Pascal parser, semantic indexer, and language server.
|
|
5
5
|
Author: Dark Light
|
|
6
6
|
License-Expression: MPL-2.0
|
|
@@ -43,8 +43,9 @@ Python Delphi LSP is a standalone Python package for Delphi/Object Pascal
|
|
|
43
43
|
parsing, semantic indexing, diagnostics, and Language Server Protocol support.
|
|
44
44
|
|
|
45
45
|
The distributable package is named `python-delphi-lsp`. The import package keeps
|
|
46
|
-
the established `delphiast` name
|
|
47
|
-
`delphi-lsp
|
|
46
|
+
the established `delphiast` name. The language-server executable is
|
|
47
|
+
`delphi-lsp`, and the agent-facing codebase navigator executable is
|
|
48
|
+
`delphi-lsp-agent`.
|
|
48
49
|
|
|
49
50
|
## What It Provides
|
|
50
51
|
|
|
@@ -56,7 +57,10 @@ the established `delphiast` name, and the language-server executable is
|
|
|
56
57
|
- Workspace indexing across Delphi projects
|
|
57
58
|
- LSP support for document symbols, workspace symbols, hover, definition,
|
|
58
59
|
references, rename, completion, and diagnostics
|
|
59
|
-
-
|
|
60
|
+
- Automatic project path discovery from `.dpr`, `.dpk`, `.dproj`, `.cfg`, and
|
|
61
|
+
`.dof` files
|
|
62
|
+
- opencode integration through the experimental LSP tool and an installable
|
|
63
|
+
`.agents` skill with a dedicated codebase-inspection tool
|
|
60
64
|
|
|
61
65
|
## Installation
|
|
62
66
|
|
|
@@ -138,17 +142,124 @@ python -m delphiast.lsp_server
|
|
|
138
142
|
```
|
|
139
143
|
|
|
140
144
|
The server expects normal LSP JSON-RPC over stdio. Editors and tools should set
|
|
141
|
-
the workspace root to the Delphi project directory
|
|
142
|
-
|
|
145
|
+
the workspace root to the Delphi project directory.
|
|
146
|
+
|
|
147
|
+
Auto-discovery reads `.dpr`, `.dpk`, `.dproj`, `.cfg`, and `.dof` files to
|
|
148
|
+
collect unit search paths, include paths, defines, direct `Unit in 'path.pas'`
|
|
149
|
+
references, and workspace source directories. Manual initialization options are
|
|
150
|
+
still accepted as overrides, but a normal project should not require users to
|
|
151
|
+
set include or source paths by hand.
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"$schema": "https://opencode.ai/config.json",
|
|
156
|
+
"lsp": {
|
|
157
|
+
"delphi": {
|
|
158
|
+
"command": ["python", "-m", "delphiast.lsp_server"],
|
|
159
|
+
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
160
|
+
"initialization": {
|
|
161
|
+
"autoDiscoverPaths": true
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Agent Codebase Navigator
|
|
169
|
+
|
|
170
|
+
Install the opencode skill and custom tool in a Delphi checkout:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
delphi-lsp-agent opencode install --target . --write-config
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
This writes:
|
|
177
|
+
|
|
178
|
+
- `.agents/skills/delphi-codebase-navigator/SKILL.md`
|
|
179
|
+
- `.opencode/tools/delphi_codebase.ts`
|
|
180
|
+
- an optional `vllm-delphi-codebase` agent entry in `opencode.json`
|
|
181
|
+
|
|
182
|
+
The skill tells agents to inspect Delphi code through layered semantic views
|
|
183
|
+
instead of loading full source files. The custom opencode tool calls
|
|
184
|
+
`python -m delphiast.agent_cli` directly, so the agent does not need shell text
|
|
185
|
+
search or raw file-reading tools to understand the codebase.
|
|
186
|
+
|
|
187
|
+
Useful direct commands:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
delphi-lsp-agent view --root . --layer overview
|
|
191
|
+
delphi-lsp-agent view --root . --layer projects
|
|
192
|
+
delphi-lsp-agent view --root . --layer unit --query Mega100kUnit
|
|
193
|
+
delphi-lsp-agent view --root . --layer symbols --query TWorker --format json
|
|
194
|
+
delphi-lsp-agent view --root . --layer problems
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Available layers are `overview`, `projects`, `units`, `unit`, `symbols`,
|
|
198
|
+
`symbol`, `references`, and `problems`. The output includes file and line
|
|
199
|
+
citations, declarations, ownership, visibility, type information, and
|
|
200
|
+
dependency/problem summaries. Routine bodies are not emitted.
|
|
143
201
|
|
|
144
202
|
## opencode Usage
|
|
145
203
|
|
|
146
204
|
This repository includes an `opencode.json` that registers the Delphi LSP tool
|
|
147
205
|
and model aliases for local Ollama and vLLM endpoints.
|
|
148
206
|
|
|
149
|
-
|
|
207
|
+
To add the Delphi language server to another opencode project without the
|
|
208
|
+
agent tool, install the package in the Python environment used by opencode and
|
|
209
|
+
add an `lsp.delphi` entry to that project's `opencode.json`:
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"$schema": "https://opencode.ai/config.json",
|
|
214
|
+
"lsp": {
|
|
215
|
+
"delphi": {
|
|
216
|
+
"command": ["python", "-m", "delphiast.lsp_server"],
|
|
217
|
+
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
218
|
+
"initialization": {
|
|
219
|
+
"autoDiscoverPaths": true
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
For checkout development, this repository's own `opencode.json` uses the local
|
|
227
|
+
virtual environment and sets `PYTHONPATH` so opencode loads the source tree
|
|
228
|
+
directly:
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
{
|
|
232
|
+
"lsp": {
|
|
233
|
+
"delphi": {
|
|
234
|
+
"command": [".venv/bin/python", "-m", "delphiast.lsp_server"],
|
|
235
|
+
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
236
|
+
"env": {
|
|
237
|
+
"PYTHONPATH": "."
|
|
238
|
+
},
|
|
239
|
+
"initialization": {
|
|
240
|
+
"autoDiscoverPaths": true
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
On Windows checkout development, replace `.venv/bin/python` with
|
|
248
|
+
`.venv\\Scripts\\python.exe`. If `python-delphi-lsp` is installed normally, the
|
|
249
|
+
portable `["python", "-m", "delphiast.lsp_server"]` command above works without
|
|
250
|
+
`PYTHONPATH`.
|
|
251
|
+
|
|
252
|
+
For normal local opencode work, use the Ollama alias with a larger context and
|
|
253
|
+
enable opencode's experimental LSP tool when starting opencode:
|
|
150
254
|
|
|
151
255
|
```bash
|
|
256
|
+
OPENCODE_EXPERIMENTAL_LSP_TOOL=true opencode run --dir . --model ollama/ornith-lspctx
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
On Windows PowerShell:
|
|
260
|
+
|
|
261
|
+
```powershell
|
|
262
|
+
$env:OPENCODE_EXPERIMENTAL_LSP_TOOL = "true"
|
|
152
263
|
opencode run --dir . --model ollama/ornith-lspctx
|
|
153
264
|
```
|
|
154
265
|
|
|
@@ -244,6 +355,39 @@ The release evidence from the local proof recorded:
|
|
|
244
355
|
- `context_budget.status = "pass"`
|
|
245
356
|
- `goal_audit.status = "pass"`
|
|
246
357
|
|
|
358
|
+
## Reproducing the vLLM opencode Skill Test
|
|
359
|
+
|
|
360
|
+
The codebase skill proof validates the `.agents` skill and opencode custom tool
|
|
361
|
+
instead of only the raw LSP tool. It creates a sandbox Delphi project with:
|
|
362
|
+
|
|
363
|
+
- `Main.dpr`
|
|
364
|
+
- `Main.dproj`
|
|
365
|
+
- `src/Mega100kUnit.pas` with more than 100,000 lines
|
|
366
|
+
- `include/build.inc`
|
|
367
|
+
- `.agents/skills/delphi-codebase-navigator/SKILL.md`
|
|
368
|
+
- `.opencode/tools/delphi_codebase.ts`
|
|
369
|
+
|
|
370
|
+
Run it against the local Ornith vLLM endpoint:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
python scripts/bootstrap_vllm_codebase_skill_test.py --use-running-server
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Or let the macOS helper start vLLM without downloading model shards:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
python scripts/bootstrap_vllm_codebase_skill_test.py --start-vllm
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
This skill probe defaults the vLLM helper to `MAX_MODEL_LEN=32768`, which was
|
|
383
|
+
the stable local Metal setting for the complete skill + `delphi_codebase` tool
|
|
384
|
+
call. Override with `--max-model-len` when your machine has enough headroom.
|
|
385
|
+
|
|
386
|
+
The probe requires opencode to load `delphi-codebase-navigator`, call
|
|
387
|
+
`delphi_codebase`, and find `MegaProc02500`. It fails if opencode uses `bash`,
|
|
388
|
+
`read`, `glob`, `grep`, `edit`, `write`, `task`, `webfetch`, or `todowrite`
|
|
389
|
+
before the required evidence is complete.
|
|
390
|
+
|
|
247
391
|
## Verification
|
|
248
392
|
|
|
249
393
|
Run the local test suite:
|
|
@@ -267,8 +411,8 @@ python -m twine check dist/*
|
|
|
267
411
|
|
|
268
412
|
## Repository Layout
|
|
269
413
|
|
|
270
|
-
- `delphiast/` - parser, preprocessor,
|
|
271
|
-
LSP server
|
|
414
|
+
- `delphiast/` - parser, preprocessor, project discovery, semantic model,
|
|
415
|
+
workspace indexer, agent layers, and LSP server
|
|
272
416
|
- `scripts/` - release evidence, cache checks, opencode probes, and bootstrap
|
|
273
417
|
helpers
|
|
274
418
|
- `tests/` - parser, semantic, workspace, diagnostics, packaging, and LSP tests
|
|
@@ -4,8 +4,9 @@ Python Delphi LSP is a standalone Python package for Delphi/Object Pascal
|
|
|
4
4
|
parsing, semantic indexing, diagnostics, and Language Server Protocol support.
|
|
5
5
|
|
|
6
6
|
The distributable package is named `python-delphi-lsp`. The import package keeps
|
|
7
|
-
the established `delphiast` name
|
|
8
|
-
`delphi-lsp
|
|
7
|
+
the established `delphiast` name. The language-server executable is
|
|
8
|
+
`delphi-lsp`, and the agent-facing codebase navigator executable is
|
|
9
|
+
`delphi-lsp-agent`.
|
|
9
10
|
|
|
10
11
|
## What It Provides
|
|
11
12
|
|
|
@@ -17,7 +18,10 @@ the established `delphiast` name, and the language-server executable is
|
|
|
17
18
|
- Workspace indexing across Delphi projects
|
|
18
19
|
- LSP support for document symbols, workspace symbols, hover, definition,
|
|
19
20
|
references, rename, completion, and diagnostics
|
|
20
|
-
-
|
|
21
|
+
- Automatic project path discovery from `.dpr`, `.dpk`, `.dproj`, `.cfg`, and
|
|
22
|
+
`.dof` files
|
|
23
|
+
- opencode integration through the experimental LSP tool and an installable
|
|
24
|
+
`.agents` skill with a dedicated codebase-inspection tool
|
|
21
25
|
|
|
22
26
|
## Installation
|
|
23
27
|
|
|
@@ -99,17 +103,124 @@ python -m delphiast.lsp_server
|
|
|
99
103
|
```
|
|
100
104
|
|
|
101
105
|
The server expects normal LSP JSON-RPC over stdio. Editors and tools should set
|
|
102
|
-
the workspace root to the Delphi project directory
|
|
103
|
-
|
|
106
|
+
the workspace root to the Delphi project directory.
|
|
107
|
+
|
|
108
|
+
Auto-discovery reads `.dpr`, `.dpk`, `.dproj`, `.cfg`, and `.dof` files to
|
|
109
|
+
collect unit search paths, include paths, defines, direct `Unit in 'path.pas'`
|
|
110
|
+
references, and workspace source directories. Manual initialization options are
|
|
111
|
+
still accepted as overrides, but a normal project should not require users to
|
|
112
|
+
set include or source paths by hand.
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"$schema": "https://opencode.ai/config.json",
|
|
117
|
+
"lsp": {
|
|
118
|
+
"delphi": {
|
|
119
|
+
"command": ["python", "-m", "delphiast.lsp_server"],
|
|
120
|
+
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
121
|
+
"initialization": {
|
|
122
|
+
"autoDiscoverPaths": true
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Agent Codebase Navigator
|
|
130
|
+
|
|
131
|
+
Install the opencode skill and custom tool in a Delphi checkout:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
delphi-lsp-agent opencode install --target . --write-config
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
This writes:
|
|
138
|
+
|
|
139
|
+
- `.agents/skills/delphi-codebase-navigator/SKILL.md`
|
|
140
|
+
- `.opencode/tools/delphi_codebase.ts`
|
|
141
|
+
- an optional `vllm-delphi-codebase` agent entry in `opencode.json`
|
|
142
|
+
|
|
143
|
+
The skill tells agents to inspect Delphi code through layered semantic views
|
|
144
|
+
instead of loading full source files. The custom opencode tool calls
|
|
145
|
+
`python -m delphiast.agent_cli` directly, so the agent does not need shell text
|
|
146
|
+
search or raw file-reading tools to understand the codebase.
|
|
147
|
+
|
|
148
|
+
Useful direct commands:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
delphi-lsp-agent view --root . --layer overview
|
|
152
|
+
delphi-lsp-agent view --root . --layer projects
|
|
153
|
+
delphi-lsp-agent view --root . --layer unit --query Mega100kUnit
|
|
154
|
+
delphi-lsp-agent view --root . --layer symbols --query TWorker --format json
|
|
155
|
+
delphi-lsp-agent view --root . --layer problems
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Available layers are `overview`, `projects`, `units`, `unit`, `symbols`,
|
|
159
|
+
`symbol`, `references`, and `problems`. The output includes file and line
|
|
160
|
+
citations, declarations, ownership, visibility, type information, and
|
|
161
|
+
dependency/problem summaries. Routine bodies are not emitted.
|
|
104
162
|
|
|
105
163
|
## opencode Usage
|
|
106
164
|
|
|
107
165
|
This repository includes an `opencode.json` that registers the Delphi LSP tool
|
|
108
166
|
and model aliases for local Ollama and vLLM endpoints.
|
|
109
167
|
|
|
110
|
-
|
|
168
|
+
To add the Delphi language server to another opencode project without the
|
|
169
|
+
agent tool, install the package in the Python environment used by opencode and
|
|
170
|
+
add an `lsp.delphi` entry to that project's `opencode.json`:
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"$schema": "https://opencode.ai/config.json",
|
|
175
|
+
"lsp": {
|
|
176
|
+
"delphi": {
|
|
177
|
+
"command": ["python", "-m", "delphiast.lsp_server"],
|
|
178
|
+
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
179
|
+
"initialization": {
|
|
180
|
+
"autoDiscoverPaths": true
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
For checkout development, this repository's own `opencode.json` uses the local
|
|
188
|
+
virtual environment and sets `PYTHONPATH` so opencode loads the source tree
|
|
189
|
+
directly:
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"lsp": {
|
|
194
|
+
"delphi": {
|
|
195
|
+
"command": [".venv/bin/python", "-m", "delphiast.lsp_server"],
|
|
196
|
+
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
197
|
+
"env": {
|
|
198
|
+
"PYTHONPATH": "."
|
|
199
|
+
},
|
|
200
|
+
"initialization": {
|
|
201
|
+
"autoDiscoverPaths": true
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
On Windows checkout development, replace `.venv/bin/python` with
|
|
209
|
+
`.venv\\Scripts\\python.exe`. If `python-delphi-lsp` is installed normally, the
|
|
210
|
+
portable `["python", "-m", "delphiast.lsp_server"]` command above works without
|
|
211
|
+
`PYTHONPATH`.
|
|
212
|
+
|
|
213
|
+
For normal local opencode work, use the Ollama alias with a larger context and
|
|
214
|
+
enable opencode's experimental LSP tool when starting opencode:
|
|
111
215
|
|
|
112
216
|
```bash
|
|
217
|
+
OPENCODE_EXPERIMENTAL_LSP_TOOL=true opencode run --dir . --model ollama/ornith-lspctx
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
On Windows PowerShell:
|
|
221
|
+
|
|
222
|
+
```powershell
|
|
223
|
+
$env:OPENCODE_EXPERIMENTAL_LSP_TOOL = "true"
|
|
113
224
|
opencode run --dir . --model ollama/ornith-lspctx
|
|
114
225
|
```
|
|
115
226
|
|
|
@@ -205,6 +316,39 @@ The release evidence from the local proof recorded:
|
|
|
205
316
|
- `context_budget.status = "pass"`
|
|
206
317
|
- `goal_audit.status = "pass"`
|
|
207
318
|
|
|
319
|
+
## Reproducing the vLLM opencode Skill Test
|
|
320
|
+
|
|
321
|
+
The codebase skill proof validates the `.agents` skill and opencode custom tool
|
|
322
|
+
instead of only the raw LSP tool. It creates a sandbox Delphi project with:
|
|
323
|
+
|
|
324
|
+
- `Main.dpr`
|
|
325
|
+
- `Main.dproj`
|
|
326
|
+
- `src/Mega100kUnit.pas` with more than 100,000 lines
|
|
327
|
+
- `include/build.inc`
|
|
328
|
+
- `.agents/skills/delphi-codebase-navigator/SKILL.md`
|
|
329
|
+
- `.opencode/tools/delphi_codebase.ts`
|
|
330
|
+
|
|
331
|
+
Run it against the local Ornith vLLM endpoint:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
python scripts/bootstrap_vllm_codebase_skill_test.py --use-running-server
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Or let the macOS helper start vLLM without downloading model shards:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
python scripts/bootstrap_vllm_codebase_skill_test.py --start-vllm
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
This skill probe defaults the vLLM helper to `MAX_MODEL_LEN=32768`, which was
|
|
344
|
+
the stable local Metal setting for the complete skill + `delphi_codebase` tool
|
|
345
|
+
call. Override with `--max-model-len` when your machine has enough headroom.
|
|
346
|
+
|
|
347
|
+
The probe requires opencode to load `delphi-codebase-navigator`, call
|
|
348
|
+
`delphi_codebase`, and find `MegaProc02500`. It fails if opencode uses `bash`,
|
|
349
|
+
`read`, `glob`, `grep`, `edit`, `write`, `task`, `webfetch`, or `todowrite`
|
|
350
|
+
before the required evidence is complete.
|
|
351
|
+
|
|
208
352
|
## Verification
|
|
209
353
|
|
|
210
354
|
Run the local test suite:
|
|
@@ -228,8 +372,8 @@ python -m twine check dist/*
|
|
|
228
372
|
|
|
229
373
|
## Repository Layout
|
|
230
374
|
|
|
231
|
-
- `delphiast/` - parser, preprocessor,
|
|
232
|
-
LSP server
|
|
375
|
+
- `delphiast/` - parser, preprocessor, project discovery, semantic model,
|
|
376
|
+
workspace indexer, agent layers, and LSP server
|
|
233
377
|
- `scripts/` - release evidence, cache checks, opencode probes, and bootstrap
|
|
234
378
|
helpers
|
|
235
379
|
- `tests/` - parser, semantic, workspace, diagnostics, packaging, and LSP tests
|
|
@@ -46,6 +46,7 @@ from .semantic import (
|
|
|
46
46
|
from .semantic_builder import SemanticBuilder, SemanticModel, SemanticProblem
|
|
47
47
|
from .workspace import WorkspaceSemanticResult, build_workspace_semantics
|
|
48
48
|
from .lsp_server import LspWorkspaceState, create_server
|
|
49
|
+
from .project_discovery import DelphiProjectDiscovery, DiscoveryProblem, discover_delphi_project
|
|
49
50
|
from .project_indexer import (
|
|
50
51
|
GetUnitSyntaxHook,
|
|
51
52
|
IncludeFileInfo,
|
|
@@ -119,6 +120,9 @@ __all__ = [
|
|
|
119
120
|
'build_workspace_semantics',
|
|
120
121
|
'LspWorkspaceState',
|
|
121
122
|
'create_server',
|
|
123
|
+
'DelphiProjectDiscovery',
|
|
124
|
+
'DiscoveryProblem',
|
|
125
|
+
'discover_delphi_project',
|
|
122
126
|
'ProjectIndexer',
|
|
123
127
|
'ProjectIndexResult',
|
|
124
128
|
'ProjectProblemType',
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from .agent_layers import build_codebase_index, layer_payload, render_layer
|
|
9
|
+
from .agent_templates import install_opencode_support, install_skill
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
13
|
+
parser = argparse.ArgumentParser(
|
|
14
|
+
prog="delphi-lsp-agent",
|
|
15
|
+
description="Agent-facing Delphi/Object Pascal codebase navigation helpers.",
|
|
16
|
+
)
|
|
17
|
+
subcommands = parser.add_subparsers(dest="command", required=True)
|
|
18
|
+
|
|
19
|
+
view = subcommands.add_parser("view", help="Render a layered codebase view.")
|
|
20
|
+
view.add_argument("--root", type=Path, default=Path("."))
|
|
21
|
+
view.add_argument("--project-file", type=Path)
|
|
22
|
+
view.add_argument("--layer", required=True, choices=["overview", "projects", "units", "unit", "symbols", "symbol", "references", "problems"])
|
|
23
|
+
view.add_argument("--query", default="")
|
|
24
|
+
view.add_argument("--format", default="markdown", choices=["markdown", "json"])
|
|
25
|
+
view.add_argument("--deep-projects", action="store_true", help="Deep-parse project dependencies for the projects layer.")
|
|
26
|
+
view.set_defaults(func=_view)
|
|
27
|
+
|
|
28
|
+
index = subcommands.add_parser("index", help="Materialize a JSON codebase index.")
|
|
29
|
+
index.add_argument("--root", type=Path, default=Path("."))
|
|
30
|
+
index.add_argument("--project-file", type=Path)
|
|
31
|
+
index.add_argument("--out", type=Path, default=Path(".delphi-lsp") / "agent-index" / "index.json")
|
|
32
|
+
index.set_defaults(func=_index)
|
|
33
|
+
|
|
34
|
+
skill = subcommands.add_parser("skill", help="Install agent skill templates.")
|
|
35
|
+
skill_commands = skill.add_subparsers(dest="skill_command", required=True)
|
|
36
|
+
skill_install = skill_commands.add_parser("install", help="Install .agents skill.")
|
|
37
|
+
skill_install.add_argument("--target", type=Path, default=Path("."))
|
|
38
|
+
skill_install.add_argument("--force", action="store_true")
|
|
39
|
+
skill_install.set_defaults(func=_skill_install)
|
|
40
|
+
|
|
41
|
+
opencode = subcommands.add_parser("opencode", help="Install opencode integration.")
|
|
42
|
+
opencode_commands = opencode.add_subparsers(dest="opencode_command", required=True)
|
|
43
|
+
opencode_install = opencode_commands.add_parser("install", help="Install .agents skill and opencode custom tool.")
|
|
44
|
+
opencode_install.add_argument("--target", type=Path, default=Path("."))
|
|
45
|
+
opencode_install.add_argument("--python", default=sys.executable)
|
|
46
|
+
opencode_install.add_argument("--force", action="store_true")
|
|
47
|
+
opencode_install.add_argument("--write-config", action="store_true")
|
|
48
|
+
opencode_install.set_defaults(func=_opencode_install)
|
|
49
|
+
|
|
50
|
+
return parser
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def main(argv: list[str] | None = None) -> int:
|
|
54
|
+
parser = build_parser()
|
|
55
|
+
args = parser.parse_args(argv)
|
|
56
|
+
try:
|
|
57
|
+
args.func(args)
|
|
58
|
+
except BrokenPipeError:
|
|
59
|
+
return 1
|
|
60
|
+
return 0
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _view(args: argparse.Namespace) -> None:
|
|
64
|
+
index = build_codebase_index(args.root, project_file=args.project_file, index_projects=args.deep_projects)
|
|
65
|
+
sys.stdout.write(render_layer(index, args.layer, query=args.query, output_format=args.format))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _index(args: argparse.Namespace) -> None:
|
|
69
|
+
index = build_codebase_index(args.root, project_file=args.project_file, index_projects=True)
|
|
70
|
+
payload = {
|
|
71
|
+
"overview": layer_payload(index, "overview"),
|
|
72
|
+
"projects": layer_payload(index, "projects"),
|
|
73
|
+
"problems": layer_payload(index, "problems"),
|
|
74
|
+
}
|
|
75
|
+
args.out.parent.mkdir(parents=True, exist_ok=True)
|
|
76
|
+
args.out.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
77
|
+
print(args.out)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _skill_install(args: argparse.Namespace) -> None:
|
|
81
|
+
skill_path = install_skill(args.target, force=args.force)
|
|
82
|
+
print(skill_path)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _opencode_install(args: argparse.Namespace) -> None:
|
|
86
|
+
skill_path, tool_path, config_path = install_opencode_support(
|
|
87
|
+
args.target,
|
|
88
|
+
python_executable=args.python,
|
|
89
|
+
force=args.force,
|
|
90
|
+
write_config=args.write_config,
|
|
91
|
+
)
|
|
92
|
+
print(skill_path)
|
|
93
|
+
print(tool_path)
|
|
94
|
+
if config_path is not None:
|
|
95
|
+
print(config_path)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if __name__ == "__main__":
|
|
99
|
+
raise SystemExit(main())
|