@nefevcore/abap-adt-dsh-plugin
v0.11.0
Published
DeepSeek Harness host adapter for @nefevcore/abap-adt-core: agent-native access to SAP ABAP systems via the ADT REST protocol — search, edit, activate, unit tests, ATC, transports, packages, plus agent-scale batch/export features.
Downloads
1,218
Maintainers
Readme
@nefevcore/abap-adt-dsh-plugin
Agent-native SAP ABAP access for the DeepSeek Harness (DSH): a Cordis plugin that registers 37 adt_* tools speaking the ADT REST protocol directly — no SAP libraries, no IDE required (headless). An AI agent gets the full development loop: search → read → edit → activate → unit test → ATC → transport → execute → error analysis, plus agent-scale capabilities (protocol-level $batch, DDIC structured editors, conflict-checked local snapshots, source export to local .abap, offline abaplint, release gates) and conversational destination management (create connections from the local SAP GUI list by just chatting). Releasing a transport is deliberately left to humans — the agent stages everything up to a releasable request.
Looking for more DSH plugins? Browse the dsh-plugin topic on GitHub (this plugin is listed there).
| Highlights | |
|---|---|
| Agent-native | tools designed for autonomous multi-step orchestration |
| Error analysis | adt_list_dumps / adt_get_dump: ST22 short-dump analysis in-tool |
| Execution | adt_execute: run programs / if_oo_adt_classrun classes, capture console output |
| Structured editors | adt_read/write_structure: message classes, domains, data elements, table types |
| Protocol $batch | adt_batch: many ADT requests in ONE round-trip (read-only GET fan-out by default) |
| Release gate | adt_release_gate: syntax + unit + ATC verdict before a transport release |
| Local versioning | adt_export_objects → local .abap files (explicit object lists); adt_local_check runs abaplint offline |
| Old-BASIS support | legacy /abapunit/testruns fallback (BASIS < 7.5x) handled automatically |
| Zero-config demo | built-in mock ADT server (demo destination) — try everything without an SAP system |
| Permission policy | global defaults + per-destination overrides: transport allowlists, package globs, transportable-edit / execution / batch-write switches |
Install & update
Install and update go through the dsh CLI only (requires pnpm on PATH). DSH profiles are pnpm-managed (~/.dsh/profiles/<name>/ has a pnpm-workspace.yaml) — don't run npm install inside a profile (it creates a package-lock.json and breaks the pnpm layout):
# install (into the web profile)
dsh plugin --profile web add @nefevcore/abap-adt-dsh-plugin
# update to the latest release
dsh plugin --profile web update @nefevcore/abap-adt-dsh-plugin
# or pin an exact version
dsh plugin --profile web add @nefevcore/[email protected]Restart DSH after install/update — HMR only re-runs config, not cached library modules.
Not loaded by default, by design. The package declares no dsh.bundle, so dsh plugin add installs it as a plain profile dependency and nothing activates: dsh plugin's reconcile only promotes bundle-declaring packages into the global layer, and per-session scoping is exactly what this plugin wants (dsh prints declares no dsh.bundle — installed as a plain dependency; that is expected). Activate it through a preset row — or, if you really want it globally, add a row with the same id to your own ~/.dsh/profiles/web/cordis.patch.yml.
System/permission settings live in the abap-adt: section of ${DSH_HOME:-~/.dsh}/settings.yaml (the DSH settings user layer): edits hot-apply without restarting DSH.
Upgrading from 0.1.0
0.2.0 activates nothing by default (the global bundle layer auto-drops via reconcile) and moved config into settings, so two one-time steps after updating:
dsh plugin --profile web update @nefevcore/abap-adt-dsh-plugin
dsh plugin --profile web exec abap-adt-preset --force # rebuild the preset (add --force over a 0.1.0-era manual one)Then merge ~/.dsh/abap-adt.yml (the deprecated 0.1.0 config file) into the abap-adt: section of ~/.dsh/settings.yaml — indent every key two spaces — and delete the old file (it warns until removed). Restart DSH once and pick the preset on new sessions.
Enable per session (agent preset — the intended way)
After installing, generate the preset with the bundled CLI:
dsh plugin --profile web exec abap-adt-presetThat copies your deployment default preset (usually cordis) to ~/.dsh/.agent-presets/abap-adt/, appends the plugin row below, and writes a preset.yml (--id/--from/--name/--force/--dry-run supported). Restart DSH once, then pick the preset from the chip beside your workspace when creating a session.
The appended row (for a manual setup):
- id: abap-adt
name: '@nefevcore/abap-adt-dsh-plugin'
config:
demo: true # built-in mock destination — no SAP system needed
# destinations live in the session WORKSPACE file
# <workspace>/.dsh-abap-adt/destinations.yaml (see below); global fallbacks
# and permission policy in settings.yaml `abap-adt:`A ready-to-share manual template lives at presets/abap-adt.example/ in the repository.
Config layering
The composition file (agent.cordis.yml / cordis.patch.yml) defines the whole toolset and should stay stable; environment-specific settings live in separate files. Effective values resolve nearest-wins:
1. inline config of the plugin row (agent preset / cordis.patch.yml)
2. legacy file ${DSH_HOME:-~/.dsh}/abap-adt.yml (deprecated, warns)
3. settings.yaml `abap-adt:` user section (global user layer, hot-applies)
4. explicit `configFile` (team-shared global override)
5. WORKSPACE file <session cwd>/.dsh-abap-adt/destinations.yaml — nearest layer,
resolved per tool call (destinations / defaultDestination / policy keys)
6. SAP_* environment variables (permission policy only, when unset above)destinations merge by name (a same-name entry in a nearer layer replaces the lower one), so a shipped destinations: [] never masks another layer. Typos and malformed YAML in any file fail loudly with the path; a missing explicitly-configured configFile logs a warning and falls back.
Connecting real SAP systems
Preferred: per-workspace config, created conversationally. Just ask the agent — "create the impc connection" — and it will search the local SAP GUI (SAP Logon) landscape (adt_list_gui_connections), offer the matches for you to pick, then write the destination (adt_create_destination, importing client/language/username from the GUI entry). The port-convention URL derived from a GUI entry is only a guess, so it is verified by probing the common candidates (443<nn>, 443, 80<nn>, 80 — credential-less; 401 counts as "alive"): the first candidate that actually responds is used. When no candidate shows a working ADT endpoint the creation is refused with the per-candidate evidence — for saprouter-routed entries (HTTP cannot ride the GUI's saprouter) the guidance asks for a web-dispatcher url, the HTTP counterpart of a saprouter, to be passed as the explicit url. With ping: true the destination is pinged with credentials before saving: connect-level failures also refuse (force: true overrides), while an HTTP-level failure (e.g. 401) proves the url alive and only warns about credentials. No GUI installed? The agent asks for url / client / username and creates it from explicit fields. Pass the password in the conversation and it is stored in the DSH credential store (~/.dsh/.credentials.yaml, referenced via passwordEnv — never written to destinations.yaml); plaintext in the file only when no credential service is mounted or passwordInFile: true. Permission knobs can be passed along too (enableTransports, allowedTransports, allowTransportableEdits, allowedPackages, allowExecution, allowBatchWrites) — they land in the entry's policy: block and override the global defaults for that destination only.
Or hand-write <workspace>/.dsh-abap-adt/destinations.yaml — files written by adt_create_destination are self-documenting: every option left unset is listed as a commented line with its default and purpose, so hand-editing is just "uncomment and change" (managed writes keep your set values and regenerate the templates):
defaultDestination: dev
destinations:
- name: dev
url: https://my-sap-host:44300/
client: '100'
language: EN
username: DEVUSER
passwordEnv: ADT_DEV_PASSWORD # preferred over a hardcoded password
strictSSL: false # for self-signed certificates
# Optional permission policy — global defaults (config > SAP_* env vars > defaults);
# every destination can override any key via its own `policy:` block:
enableTransports: true
allowedTransports: 'D01K96*' # glob allowlist of transport numbers
allowTransportableEdits: true
allowedPackages: 'Z*,$TMP' # glob allowlist of editable packages
destinations:
- name: qas
url: https://my-qas-host:44300/
# ...
policy: # stricter on QAS, key by key
enableTransports: falseInspect the effective policy at runtime with the adt_permissions tool.
Tool family (37 tools)
System & connections (adt_list_destinations, adt_list_gui_connections, adt_create_destination, adt_system_info, adt_ping, adt_permissions) · search & browse (adt_search, adt_package_content, adt_where_used) · source (adt_read_object with local snapshot, adt_write_object, adt_edit_object, adt_push_object, adt_create_object, adt_delete_object) · structured editors (adt_read_structure, adt_write_structure — MSAG/DOMA/DTEL/TTYP) · lifecycle (adt_activate, adt_check, adt_lock_info, adt_unlock_all) · testing (adt_run_unit_tests, adt_run_atc, adt_list_atc_runs, adt_get_atc_result) · transports (adt_object_versions, adt_list_transports, adt_get_transport — release is intentionally not exposed) · data (adt_data_preview with offset/length window) · versions (adt_version_diff) · batch/local (adt_batch, adt_release_gate, adt_export_objects, adt_local_check) · execution & errors (adt_execute, adt_list_dumps, adt_get_dump).
Full documentation: dsh-adt repository.
Companion packages: @nefevcore/abap-adt-protocol (protocol client), @nefevcore/abap-adt-mock (mock server).
License: MIT
