python-delphi-lsp 1.0.1__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.1 → python_delphi_lsp-1.1.0}/MANIFEST.in +1 -0
- {python_delphi_lsp-1.0.1/python_delphi_lsp.egg-info → python_delphi_lsp-1.1.0}/PKG-INFO +107 -18
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/README.md +106 -17
- {python_delphi_lsp-1.0.1 → 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.1 → 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.1 → python_delphi_lsp-1.1.0}/opencode.json +1 -5
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/pyproject.toml +2 -1
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0/python_delphi_lsp.egg-info}/PKG-INFO +107 -18
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/python_delphi_lsp.egg-info/SOURCES.txt +8 -0
- {python_delphi_lsp-1.0.1 → 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.1 → python_delphi_lsp-1.1.0}/tests/test_opencode_config.py +9 -0
- {python_delphi_lsp-1.0.1 → 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.1 → python_delphi_lsp-1.1.0}/LICENSE +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/binary.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/comment_builder.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/consts.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/grammar.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/lark_builder.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/lark_tokens.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/nodes.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/parser.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/preprocessor.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/project_indexer.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/semantic.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/semantic_builder.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/source_reader.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/workspace.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/delphiast/writer.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/python_delphi_lsp.egg-info/dependency_links.txt +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/python_delphi_lsp.egg-info/requires.txt +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/python_delphi_lsp.egg-info/top_level.txt +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/audit_delphi_language_features.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/bootstrap_vllm_opencode_test.ps1 +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/bootstrap_vllm_opencode_test.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/bootstrap_vllm_opencode_test.sh +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/check_ornith_cache.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/generate_release_evidence.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/ollama/ornith-lspctx.Modelfile +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/prepare_ornith_cache.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/run_opencode_lsp_probe.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/start_ornith_vllm.sh +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/scripts/summarize_opencode_request_payloads.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/setup.cfg +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/DeprecatedOnConst.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/VariantRecordFieldAttributes.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/alignedrecords.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/constset.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/deprecatedtype.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/dottedtypes.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/endtoken.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/experimentals.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/externalfunction.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/finalizationinitializationexports.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/forwardoverloaded.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/forwardwithoutsemicolon.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/genericconstraints.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/genericinterfacemethoddelegation.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/implementsgenerictype.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/include file2.inc +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/includefile.inc +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/includefile.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/managedrecords.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/messagemethod.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/multiline.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/nonalignedrecords.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/numbers.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/pointerchars.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/properties.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/strictvisibility.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/tryexcept.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/umlauts.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/legacy_snippets/whitespacearoundifdefcondition.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/library_demo.dpr +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/package_demo.dpk +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/program_demo.dpr +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_advanced.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_attributes.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_basic.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_consumer.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_generics.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_inheritance.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_math.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_properties.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_sections.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_statements.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_types.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_unresolved.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/fixtures/unit_with.pas +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_bootstrap_vllm_opencode.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_diagnostics.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_language_feature_matrix.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_legacy_snippets.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_lsp_features.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_lsp_support.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_opencode_probe.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_opencode_request_payloads.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_ornith_cache_prepare.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_parser.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_preprocessor.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_project_indexer.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_release_evidence.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_semantic.py +0 -0
- {python_delphi_lsp-1.0.1 → python_delphi_lsp-1.1.0}/tests/test_vllm_start_script.py +0 -0
- {python_delphi_lsp-1.0.1 → 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.0
|
|
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,71 @@ 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
|
-
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`:
|
|
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`:
|
|
152
210
|
|
|
153
211
|
```json
|
|
154
212
|
{
|
|
@@ -158,17 +216,16 @@ entry to that project's `opencode.json`:
|
|
|
158
216
|
"command": ["python", "-m", "delphiast.lsp_server"],
|
|
159
217
|
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
160
218
|
"initialization": {
|
|
161
|
-
"
|
|
162
|
-
"defines": ["MSWINDOWS"]
|
|
219
|
+
"autoDiscoverPaths": true
|
|
163
220
|
}
|
|
164
221
|
}
|
|
165
222
|
}
|
|
166
223
|
}
|
|
167
224
|
```
|
|
168
225
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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:
|
|
172
229
|
|
|
173
230
|
```json
|
|
174
231
|
{
|
|
@@ -180,8 +237,7 @@ environment and sets `PYTHONPATH` so opencode loads the source tree directly:
|
|
|
180
237
|
"PYTHONPATH": "."
|
|
181
238
|
},
|
|
182
239
|
"initialization": {
|
|
183
|
-
"
|
|
184
|
-
"defines": []
|
|
240
|
+
"autoDiscoverPaths": true
|
|
185
241
|
}
|
|
186
242
|
}
|
|
187
243
|
}
|
|
@@ -299,6 +355,39 @@ The release evidence from the local proof recorded:
|
|
|
299
355
|
- `context_budget.status = "pass"`
|
|
300
356
|
- `goal_audit.status = "pass"`
|
|
301
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
|
+
|
|
302
391
|
## Verification
|
|
303
392
|
|
|
304
393
|
Run the local test suite:
|
|
@@ -322,8 +411,8 @@ python -m twine check dist/*
|
|
|
322
411
|
|
|
323
412
|
## Repository Layout
|
|
324
413
|
|
|
325
|
-
- `delphiast/` - parser, preprocessor,
|
|
326
|
-
LSP server
|
|
414
|
+
- `delphiast/` - parser, preprocessor, project discovery, semantic model,
|
|
415
|
+
workspace indexer, agent layers, and LSP server
|
|
327
416
|
- `scripts/` - release evidence, cache checks, opencode probes, and bootstrap
|
|
328
417
|
helpers
|
|
329
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,71 @@ 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
|
-
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`:
|
|
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`:
|
|
113
171
|
|
|
114
172
|
```json
|
|
115
173
|
{
|
|
@@ -119,17 +177,16 @@ entry to that project's `opencode.json`:
|
|
|
119
177
|
"command": ["python", "-m", "delphiast.lsp_server"],
|
|
120
178
|
"extensions": [".pas", ".dpr", ".dpk", ".inc"],
|
|
121
179
|
"initialization": {
|
|
122
|
-
"
|
|
123
|
-
"defines": ["MSWINDOWS"]
|
|
180
|
+
"autoDiscoverPaths": true
|
|
124
181
|
}
|
|
125
182
|
}
|
|
126
183
|
}
|
|
127
184
|
}
|
|
128
185
|
```
|
|
129
186
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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:
|
|
133
190
|
|
|
134
191
|
```json
|
|
135
192
|
{
|
|
@@ -141,8 +198,7 @@ environment and sets `PYTHONPATH` so opencode loads the source tree directly:
|
|
|
141
198
|
"PYTHONPATH": "."
|
|
142
199
|
},
|
|
143
200
|
"initialization": {
|
|
144
|
-
"
|
|
145
|
-
"defines": []
|
|
201
|
+
"autoDiscoverPaths": true
|
|
146
202
|
}
|
|
147
203
|
}
|
|
148
204
|
}
|
|
@@ -260,6 +316,39 @@ The release evidence from the local proof recorded:
|
|
|
260
316
|
- `context_budget.status = "pass"`
|
|
261
317
|
- `goal_audit.status = "pass"`
|
|
262
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
|
+
|
|
263
352
|
## Verification
|
|
264
353
|
|
|
265
354
|
Run the local test suite:
|
|
@@ -283,8 +372,8 @@ python -m twine check dist/*
|
|
|
283
372
|
|
|
284
373
|
## Repository Layout
|
|
285
374
|
|
|
286
|
-
- `delphiast/` - parser, preprocessor,
|
|
287
|
-
LSP server
|
|
375
|
+
- `delphiast/` - parser, preprocessor, project discovery, semantic model,
|
|
376
|
+
workspace indexer, agent layers, and LSP server
|
|
288
377
|
- `scripts/` - release evidence, cache checks, opencode probes, and bootstrap
|
|
289
378
|
helpers
|
|
290
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())
|