python-delphi-lsp 1.0.1__tar.gz → 1.1.1__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.1 → python_delphi_lsp-1.1.1}/MANIFEST.in +1 -0
- {python_delphi_lsp-1.0.1/python_delphi_lsp.egg-info → python_delphi_lsp-1.1.1}/PKG-INFO +117 -18
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/README.md +116 -17
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/__init__.py +4 -0
- python_delphi_lsp-1.1.1/delphiast/agent_cli.py +113 -0
- python_delphi_lsp-1.1.1/delphiast/agent_layers.py +497 -0
- python_delphi_lsp-1.1.1/delphiast/agent_templates.py +180 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/lsp_server.py +62 -3
- python_delphi_lsp-1.1.1/delphiast/project_discovery.py +375 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/opencode.json +1 -5
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/pyproject.toml +2 -1
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1/python_delphi_lsp.egg-info}/PKG-INFO +117 -18
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/python_delphi_lsp.egg-info/SOURCES.txt +8 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/python_delphi_lsp.egg-info/entry_points.txt +1 -0
- python_delphi_lsp-1.1.1/scripts/bootstrap_vllm_codebase_skill_test.py +235 -0
- python_delphi_lsp-1.1.1/tests/test_agent_codebase.py +217 -0
- python_delphi_lsp-1.1.1/tests/test_bootstrap_vllm_codebase_skill.py +68 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_opencode_config.py +9 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_package_metadata.py +6 -2
- python_delphi_lsp-1.1.1/tests/test_project_discovery.py +174 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/LICENSE +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/binary.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/comment_builder.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/consts.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/grammar.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/lark_builder.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/lark_tokens.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/nodes.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/parser.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/preprocessor.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/project_indexer.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/semantic.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/semantic_builder.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/source_reader.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/workspace.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/delphiast/writer.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/python_delphi_lsp.egg-info/dependency_links.txt +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/python_delphi_lsp.egg-info/requires.txt +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/python_delphi_lsp.egg-info/top_level.txt +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/audit_delphi_language_features.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/bootstrap_vllm_opencode_test.ps1 +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/bootstrap_vllm_opencode_test.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/bootstrap_vllm_opencode_test.sh +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/check_ornith_cache.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/generate_release_evidence.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/ollama/ornith-lspctx.Modelfile +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/prepare_ornith_cache.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/run_opencode_lsp_probe.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/start_ornith_vllm.sh +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/scripts/summarize_opencode_request_payloads.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/setup.cfg +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/DeprecatedOnConst.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/VariantRecordFieldAttributes.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/alignedrecords.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/constset.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/deprecatedtype.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/dottedtypes.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/endtoken.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/experimentals.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/externalfunction.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/finalizationinitializationexports.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/forwardoverloaded.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/forwardwithoutsemicolon.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/genericconstraints.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/genericinterfacemethoddelegation.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/implementsgenerictype.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/include file2.inc +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/includefile.inc +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/includefile.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/managedrecords.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/messagemethod.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/multiline.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/nonalignedrecords.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/numbers.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/pointerchars.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/properties.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/strictvisibility.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/tryexcept.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/umlauts.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/legacy_snippets/whitespacearoundifdefcondition.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/library_demo.dpr +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/package_demo.dpk +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/program_demo.dpr +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_advanced.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_attributes.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_basic.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_consumer.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_generics.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_inheritance.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_math.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_properties.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_sections.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_statements.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_types.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_unresolved.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/fixtures/unit_with.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_bootstrap_vllm_opencode.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_diagnostics.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_language_feature_matrix.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_legacy_snippets.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_lsp_features.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_lsp_support.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_opencode_probe.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_opencode_request_payloads.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_ornith_cache_prepare.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_parser.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_preprocessor.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_project_indexer.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_release_evidence.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_semantic.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/tests/test_vllm_start_script.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.1}/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.1
|
|
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,77 @@ 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 implementation --query TWorker.Run
|
|
195
|
+
delphi-lsp-agent view --root . --layer implementation --query TWorker --format json
|
|
196
|
+
delphi-lsp-agent view --root . --layer problems
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Available layers are `overview`, `projects`, `units`, `unit`, `symbols`,
|
|
200
|
+
`symbol`, `implementation`, `references`, and `problems`. The output includes
|
|
201
|
+
file and line citations, declarations, ownership, visibility, type information,
|
|
202
|
+
and dependency/problem summaries. Outline layers keep routine bodies out of the
|
|
203
|
+
agent context. Use `implementation` with a concrete class, routine, or member
|
|
204
|
+
query to read only that complete source fragment from the original file. For a
|
|
205
|
+
class query, the layer returns the class declaration plus matching method
|
|
206
|
+
implementations; for a routine query, it returns the full routine body.
|
|
143
207
|
|
|
144
208
|
## opencode Usage
|
|
145
209
|
|
|
146
210
|
This repository includes an `opencode.json` that registers the Delphi LSP tool
|
|
147
211
|
and model aliases for local Ollama and vLLM endpoints.
|
|
148
212
|
|
|
149
|
-
To add the Delphi language server to another opencode project
|
|
150
|
-
package in the Python environment used by opencode and
|
|
151
|
-
entry to that project's `opencode.json`:
|
|
213
|
+
To add the Delphi language server to another opencode project without the
|
|
214
|
+
agent tool, install the package in the Python environment used by opencode and
|
|
215
|
+
add an `lsp.delphi` entry to that project's `opencode.json`:
|
|
152
216
|
|
|
153
217
|
```json
|
|
154
218
|
{
|
|
@@ -158,17 +222,16 @@ entry to that project's `opencode.json`:
|
|
|
158
222
|
"command": ["python", "-m", "delphiast.lsp_server"],
|
|
159
223
|
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
160
224
|
"initialization": {
|
|
161
|
-
"
|
|
162
|
-
"defines": ["MSWINDOWS"]
|
|
225
|
+
"autoDiscoverPaths": true
|
|
163
226
|
}
|
|
164
227
|
}
|
|
165
228
|
}
|
|
166
229
|
}
|
|
167
230
|
```
|
|
168
231
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
232
|
+
For checkout development, this repository's own `opencode.json` uses the local
|
|
233
|
+
virtual environment and sets `PYTHONPATH` so opencode loads the source tree
|
|
234
|
+
directly:
|
|
172
235
|
|
|
173
236
|
```json
|
|
174
237
|
{
|
|
@@ -180,8 +243,7 @@ environment and sets `PYTHONPATH` so opencode loads the source tree directly:
|
|
|
180
243
|
"PYTHONPATH": "."
|
|
181
244
|
},
|
|
182
245
|
"initialization": {
|
|
183
|
-
"
|
|
184
|
-
"defines": []
|
|
246
|
+
"autoDiscoverPaths": true
|
|
185
247
|
}
|
|
186
248
|
}
|
|
187
249
|
}
|
|
@@ -299,6 +361,43 @@ The release evidence from the local proof recorded:
|
|
|
299
361
|
- `context_budget.status = "pass"`
|
|
300
362
|
- `goal_audit.status = "pass"`
|
|
301
363
|
|
|
364
|
+
## Reproducing the vLLM opencode Skill Test
|
|
365
|
+
|
|
366
|
+
The codebase skill proof validates the `.agents` skill and opencode custom tool
|
|
367
|
+
instead of only the raw LSP tool. It creates a sandbox Delphi project with:
|
|
368
|
+
|
|
369
|
+
- `Main.dpr`
|
|
370
|
+
- `Main.dproj`
|
|
371
|
+
- `src/Mega100kUnit.pas` with more than 100,000 lines
|
|
372
|
+
- `include/build.inc`
|
|
373
|
+
- `.agents/skills/delphi-codebase-navigator/SKILL.md`
|
|
374
|
+
- `.opencode/tools/delphi_codebase.ts`
|
|
375
|
+
|
|
376
|
+
Run it against the local Ornith vLLM endpoint:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
python scripts/bootstrap_vllm_codebase_skill_test.py --use-running-server
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Or let the macOS helper start vLLM without downloading model shards:
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
python scripts/bootstrap_vllm_codebase_skill_test.py --start-vllm
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
This skill probe defaults the vLLM helper to `MAX_MODEL_LEN=32768`, which was
|
|
389
|
+
the stable local Metal setting for the reduced codebase-agent prompt plus the
|
|
390
|
+
`delphi_codebase` tool call. Override with `--max-model-len` when your machine
|
|
391
|
+
has enough headroom.
|
|
392
|
+
|
|
393
|
+
The probe verifies that the `delphi-codebase-navigator` skill is installed, then
|
|
394
|
+
requires opencode to call `delphi_codebase`, find `MegaProc02500`, and read the
|
|
395
|
+
method body through the `implementation` layer. The vLLM test agent keeps
|
|
396
|
+
opencode's generic `skill` tool disabled so the model context stays focused on
|
|
397
|
+
the Delphi navigation tool. The probe fails if opencode uses `bash`, `read`,
|
|
398
|
+
`glob`, `grep`, `edit`, `write`, `task`, `webfetch`, or `todowrite` before the
|
|
399
|
+
required evidence is complete.
|
|
400
|
+
|
|
302
401
|
## Verification
|
|
303
402
|
|
|
304
403
|
Run the local test suite:
|
|
@@ -322,8 +421,8 @@ python -m twine check dist/*
|
|
|
322
421
|
|
|
323
422
|
## Repository Layout
|
|
324
423
|
|
|
325
|
-
- `delphiast/` - parser, preprocessor,
|
|
326
|
-
LSP server
|
|
424
|
+
- `delphiast/` - parser, preprocessor, project discovery, semantic model,
|
|
425
|
+
workspace indexer, agent layers, and LSP server
|
|
327
426
|
- `scripts/` - release evidence, cache checks, opencode probes, and bootstrap
|
|
328
427
|
helpers
|
|
329
428
|
- `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,77 @@ 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 implementation --query TWorker.Run
|
|
156
|
+
delphi-lsp-agent view --root . --layer implementation --query TWorker --format json
|
|
157
|
+
delphi-lsp-agent view --root . --layer problems
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Available layers are `overview`, `projects`, `units`, `unit`, `symbols`,
|
|
161
|
+
`symbol`, `implementation`, `references`, and `problems`. The output includes
|
|
162
|
+
file and line citations, declarations, ownership, visibility, type information,
|
|
163
|
+
and dependency/problem summaries. Outline layers keep routine bodies out of the
|
|
164
|
+
agent context. Use `implementation` with a concrete class, routine, or member
|
|
165
|
+
query to read only that complete source fragment from the original file. For a
|
|
166
|
+
class query, the layer returns the class declaration plus matching method
|
|
167
|
+
implementations; for a routine query, it returns the full routine body.
|
|
104
168
|
|
|
105
169
|
## opencode Usage
|
|
106
170
|
|
|
107
171
|
This repository includes an `opencode.json` that registers the Delphi LSP tool
|
|
108
172
|
and model aliases for local Ollama and vLLM endpoints.
|
|
109
173
|
|
|
110
|
-
To add the Delphi language server to another opencode project
|
|
111
|
-
package in the Python environment used by opencode and
|
|
112
|
-
entry to that project's `opencode.json`:
|
|
174
|
+
To add the Delphi language server to another opencode project without the
|
|
175
|
+
agent tool, install the package in the Python environment used by opencode and
|
|
176
|
+
add an `lsp.delphi` entry to that project's `opencode.json`:
|
|
113
177
|
|
|
114
178
|
```json
|
|
115
179
|
{
|
|
@@ -119,17 +183,16 @@ entry to that project's `opencode.json`:
|
|
|
119
183
|
"command": ["python", "-m", "delphiast.lsp_server"],
|
|
120
184
|
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
121
185
|
"initialization": {
|
|
122
|
-
"
|
|
123
|
-
"defines": ["MSWINDOWS"]
|
|
186
|
+
"autoDiscoverPaths": true
|
|
124
187
|
}
|
|
125
188
|
}
|
|
126
189
|
}
|
|
127
190
|
}
|
|
128
191
|
```
|
|
129
192
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
193
|
+
For checkout development, this repository's own `opencode.json` uses the local
|
|
194
|
+
virtual environment and sets `PYTHONPATH` so opencode loads the source tree
|
|
195
|
+
directly:
|
|
133
196
|
|
|
134
197
|
```json
|
|
135
198
|
{
|
|
@@ -141,8 +204,7 @@ environment and sets `PYTHONPATH` so opencode loads the source tree directly:
|
|
|
141
204
|
"PYTHONPATH": "."
|
|
142
205
|
},
|
|
143
206
|
"initialization": {
|
|
144
|
-
"
|
|
145
|
-
"defines": []
|
|
207
|
+
"autoDiscoverPaths": true
|
|
146
208
|
}
|
|
147
209
|
}
|
|
148
210
|
}
|
|
@@ -260,6 +322,43 @@ The release evidence from the local proof recorded:
|
|
|
260
322
|
- `context_budget.status = "pass"`
|
|
261
323
|
- `goal_audit.status = "pass"`
|
|
262
324
|
|
|
325
|
+
## Reproducing the vLLM opencode Skill Test
|
|
326
|
+
|
|
327
|
+
The codebase skill proof validates the `.agents` skill and opencode custom tool
|
|
328
|
+
instead of only the raw LSP tool. It creates a sandbox Delphi project with:
|
|
329
|
+
|
|
330
|
+
- `Main.dpr`
|
|
331
|
+
- `Main.dproj`
|
|
332
|
+
- `src/Mega100kUnit.pas` with more than 100,000 lines
|
|
333
|
+
- `include/build.inc`
|
|
334
|
+
- `.agents/skills/delphi-codebase-navigator/SKILL.md`
|
|
335
|
+
- `.opencode/tools/delphi_codebase.ts`
|
|
336
|
+
|
|
337
|
+
Run it against the local Ornith vLLM endpoint:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
python scripts/bootstrap_vllm_codebase_skill_test.py --use-running-server
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Or let the macOS helper start vLLM without downloading model shards:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
python scripts/bootstrap_vllm_codebase_skill_test.py --start-vllm
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
This skill probe defaults the vLLM helper to `MAX_MODEL_LEN=32768`, which was
|
|
350
|
+
the stable local Metal setting for the reduced codebase-agent prompt plus the
|
|
351
|
+
`delphi_codebase` tool call. Override with `--max-model-len` when your machine
|
|
352
|
+
has enough headroom.
|
|
353
|
+
|
|
354
|
+
The probe verifies that the `delphi-codebase-navigator` skill is installed, then
|
|
355
|
+
requires opencode to call `delphi_codebase`, find `MegaProc02500`, and read the
|
|
356
|
+
method body through the `implementation` layer. The vLLM test agent keeps
|
|
357
|
+
opencode's generic `skill` tool disabled so the model context stays focused on
|
|
358
|
+
the Delphi navigation tool. The probe fails if opencode uses `bash`, `read`,
|
|
359
|
+
`glob`, `grep`, `edit`, `write`, `task`, `webfetch`, or `todowrite` before the
|
|
360
|
+
required evidence is complete.
|
|
361
|
+
|
|
263
362
|
## Verification
|
|
264
363
|
|
|
265
364
|
Run the local test suite:
|
|
@@ -283,8 +382,8 @@ python -m twine check dist/*
|
|
|
283
382
|
|
|
284
383
|
## Repository Layout
|
|
285
384
|
|
|
286
|
-
- `delphiast/` - parser, preprocessor,
|
|
287
|
-
LSP server
|
|
385
|
+
- `delphiast/` - parser, preprocessor, project discovery, semantic model,
|
|
386
|
+
workspace indexer, agent layers, and LSP server
|
|
288
387
|
- `scripts/` - release evidence, cache checks, opencode probes, and bootstrap
|
|
289
388
|
helpers
|
|
290
389
|
- `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,113 @@
|
|
|
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(
|
|
23
|
+
"--layer",
|
|
24
|
+
required=True,
|
|
25
|
+
choices=[
|
|
26
|
+
"overview",
|
|
27
|
+
"projects",
|
|
28
|
+
"units",
|
|
29
|
+
"unit",
|
|
30
|
+
"symbols",
|
|
31
|
+
"symbol",
|
|
32
|
+
"implementation",
|
|
33
|
+
"references",
|
|
34
|
+
"problems",
|
|
35
|
+
],
|
|
36
|
+
)
|
|
37
|
+
view.add_argument("--query", default="")
|
|
38
|
+
view.add_argument("--format", default="markdown", choices=["markdown", "json"])
|
|
39
|
+
view.add_argument("--deep-projects", action="store_true", help="Deep-parse project dependencies for the projects layer.")
|
|
40
|
+
view.set_defaults(func=_view)
|
|
41
|
+
|
|
42
|
+
index = subcommands.add_parser("index", help="Materialize a JSON codebase index.")
|
|
43
|
+
index.add_argument("--root", type=Path, default=Path("."))
|
|
44
|
+
index.add_argument("--project-file", type=Path)
|
|
45
|
+
index.add_argument("--out", type=Path, default=Path(".delphi-lsp") / "agent-index" / "index.json")
|
|
46
|
+
index.set_defaults(func=_index)
|
|
47
|
+
|
|
48
|
+
skill = subcommands.add_parser("skill", help="Install agent skill templates.")
|
|
49
|
+
skill_commands = skill.add_subparsers(dest="skill_command", required=True)
|
|
50
|
+
skill_install = skill_commands.add_parser("install", help="Install .agents skill.")
|
|
51
|
+
skill_install.add_argument("--target", type=Path, default=Path("."))
|
|
52
|
+
skill_install.add_argument("--force", action="store_true")
|
|
53
|
+
skill_install.set_defaults(func=_skill_install)
|
|
54
|
+
|
|
55
|
+
opencode = subcommands.add_parser("opencode", help="Install opencode integration.")
|
|
56
|
+
opencode_commands = opencode.add_subparsers(dest="opencode_command", required=True)
|
|
57
|
+
opencode_install = opencode_commands.add_parser("install", help="Install .agents skill and opencode custom tool.")
|
|
58
|
+
opencode_install.add_argument("--target", type=Path, default=Path("."))
|
|
59
|
+
opencode_install.add_argument("--python", default=sys.executable)
|
|
60
|
+
opencode_install.add_argument("--force", action="store_true")
|
|
61
|
+
opencode_install.add_argument("--write-config", action="store_true")
|
|
62
|
+
opencode_install.set_defaults(func=_opencode_install)
|
|
63
|
+
|
|
64
|
+
return parser
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def main(argv: list[str] | None = None) -> int:
|
|
68
|
+
parser = build_parser()
|
|
69
|
+
args = parser.parse_args(argv)
|
|
70
|
+
try:
|
|
71
|
+
args.func(args)
|
|
72
|
+
except BrokenPipeError:
|
|
73
|
+
return 1
|
|
74
|
+
return 0
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _view(args: argparse.Namespace) -> None:
|
|
78
|
+
index = build_codebase_index(args.root, project_file=args.project_file, index_projects=args.deep_projects)
|
|
79
|
+
sys.stdout.write(render_layer(index, args.layer, query=args.query, output_format=args.format))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _index(args: argparse.Namespace) -> None:
|
|
83
|
+
index = build_codebase_index(args.root, project_file=args.project_file, index_projects=True)
|
|
84
|
+
payload = {
|
|
85
|
+
"overview": layer_payload(index, "overview"),
|
|
86
|
+
"projects": layer_payload(index, "projects"),
|
|
87
|
+
"problems": layer_payload(index, "problems"),
|
|
88
|
+
}
|
|
89
|
+
args.out.parent.mkdir(parents=True, exist_ok=True)
|
|
90
|
+
args.out.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
|
|
91
|
+
print(args.out)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _skill_install(args: argparse.Namespace) -> None:
|
|
95
|
+
skill_path = install_skill(args.target, force=args.force)
|
|
96
|
+
print(skill_path)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _opencode_install(args: argparse.Namespace) -> None:
|
|
100
|
+
skill_path, tool_path, config_path = install_opencode_support(
|
|
101
|
+
args.target,
|
|
102
|
+
python_executable=args.python,
|
|
103
|
+
force=args.force,
|
|
104
|
+
write_config=args.write_config,
|
|
105
|
+
)
|
|
106
|
+
print(skill_path)
|
|
107
|
+
print(tool_path)
|
|
108
|
+
if config_path is not None:
|
|
109
|
+
print(config_path)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
raise SystemExit(main())
|