sap-adt-mcp 0.7.1
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.
- package/LICENSE +21 -0
- package/README.md +527 -0
- package/config.example.json +32 -0
- package/package.json +55 -0
- package/src/adt-client.js +278 -0
- package/src/adt-error.js +135 -0
- package/src/config.js +78 -0
- package/src/data-preview.js +148 -0
- package/src/diff.js +123 -0
- package/src/dump-feed.js +251 -0
- package/src/lock.js +52 -0
- package/src/node-structure.js +56 -0
- package/src/object-create.js +244 -0
- package/src/object-references.js +28 -0
- package/src/object-uris.js +156 -0
- package/src/prompts.js +533 -0
- package/src/result.js +23 -0
- package/src/server.js +206 -0
- package/src/tools/_shared.js +11 -0
- package/src/tools/cds.js +157 -0
- package/src/tools/connection.js +46 -0
- package/src/tools/cross-system.js +191 -0
- package/src/tools/data.js +86 -0
- package/src/tools/discovery.js +520 -0
- package/src/tools/jobs.js +107 -0
- package/src/tools/lifecycle.js +314 -0
- package/src/tools/notes.js +147 -0
- package/src/tools/quality.js +407 -0
- package/src/tools/rap.js +287 -0
- package/src/tools/request.js +103 -0
- package/src/tools/runtime.js +244 -0
- package/src/tools/source.js +622 -0
- package/src/tools/transports.js +163 -0
- package/src/tools/versions.js +154 -0
- package/src/tools/worklist.js +112 -0
- package/src/xml.js +8 -0
package/src/prompts.js
ADDED
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
// MCP prompts exposed by sap-adt-mcp.
|
|
2
|
+
//
|
|
3
|
+
// These surface in MCP-compatible clients (Claude Desktop, Claude Code, etc.)
|
|
4
|
+
// as user-invokable slash commands. Each prompt encodes a slice of SAP's
|
|
5
|
+
// Clean Core extensibility framework and tells the model how to combine the
|
|
6
|
+
// adt_* tools to deliver a specific outcome — grade an object, review a
|
|
7
|
+
// package's KPIs, refactor toward a higher cleanliness level, create new
|
|
8
|
+
// code at Level A, or design an extension architecture.
|
|
9
|
+
//
|
|
10
|
+
// In Claude Code these appear as e.g. /mcp__sap-adt__clean_core_grade.
|
|
11
|
+
// The "sap-adt" segment depends on the name the user gave the server when
|
|
12
|
+
// registering it (`claude mcp add sap-adt -- npx sap-adt-mcp`).
|
|
13
|
+
//
|
|
14
|
+
// The skill at skills/abap-clean-core/ remains as the long-form reference
|
|
15
|
+
// documentation. These prompts are the operational surface — they pull the
|
|
16
|
+
// relevant slice of that material and pair it with the MCP tool surface so
|
|
17
|
+
// the model can act on real systems instead of reasoning in the abstract.
|
|
18
|
+
|
|
19
|
+
const APPLICABILITY_GUARD = `
|
|
20
|
+
APPLICABILITY CHECK (run this first, every time):
|
|
21
|
+
- Clean Core is an SAP S/4HANA discipline (Public Cloud, Private Cloud, or
|
|
22
|
+
on-premise). It does NOT apply to ECC / R/3 / pre-S/4HANA systems.
|
|
23
|
+
- If the target system is ECC or you cannot tell, ask the user once. If it's
|
|
24
|
+
ECC, refuse to apply Clean Core grading. Help with classic ABAP idioms
|
|
25
|
+
instead, without level labels.
|
|
26
|
+
- Use adt_ping or adt_list_systems if you need to introspect the landscape.
|
|
27
|
+
`.trim();
|
|
28
|
+
|
|
29
|
+
const TONE = `
|
|
30
|
+
TONE:
|
|
31
|
+
- Descriptive, not judgmental. Name the level, name the trade-off, do not
|
|
32
|
+
moralize.
|
|
33
|
+
- The user is the engineer of record. If they say "I know it's Level D, just
|
|
34
|
+
ship it" — deliver, mark the level, sketch the Level A refactor for later,
|
|
35
|
+
and move on. Do not refuse, do not lecture twice.
|
|
36
|
+
`.trim();
|
|
37
|
+
|
|
38
|
+
const TOOL_REMINDER = `
|
|
39
|
+
RELEVANT MCP TOOLS:
|
|
40
|
+
- adt_get_source — fetch ABAP source by name + type
|
|
41
|
+
- adt_run_atc — run ATC (Cloud Readiness variant maps to A/B/C/D)
|
|
42
|
+
- adt_run_unit_tests — run ABAP Unit
|
|
43
|
+
- adt_syntax_check — syntax check before set_source
|
|
44
|
+
- adt_search_objects — name-pattern search (find released equivalents)
|
|
45
|
+
- adt_where_used — where-used list
|
|
46
|
+
- adt_browse_package — one level of package contents
|
|
47
|
+
- adt_list_packages — recursive walk
|
|
48
|
+
- adt_create_object — create new ABAP objects (Level A pipeline below)
|
|
49
|
+
- adt_set_source — replace source (orchestrates lock/PUT/unlock)
|
|
50
|
+
- adt_activate — activate one or more objects
|
|
51
|
+
- adt_compare_source — diff one object across two systems
|
|
52
|
+
`.trim();
|
|
53
|
+
|
|
54
|
+
const LEVELS_TABLE = `
|
|
55
|
+
LEVELS:
|
|
56
|
+
- Level A — Released APIs (CDS views, business object interfaces, released
|
|
57
|
+
BAdIs, RAP services). ATC: no finding. Upgrade-safe by SAP guarantee.
|
|
58
|
+
- Level B — Classic APIs (BAPIs, released user exits, classic ALV). ATC:
|
|
59
|
+
priority 3 (info). Wrap in Level A class when introducing in new code.
|
|
60
|
+
- Level C — Internal SAP objects (default state of any unreleased object).
|
|
61
|
+
ATC: priority 2 (warning). Risk: SAP can reclassify to noAPI any release.
|
|
62
|
+
Mitigate via Changelog for SAP Objects + encapsulation.
|
|
63
|
+
- Level D — Modifications, direct writes to SAP standard tables, implicit
|
|
64
|
+
enhancements, noAPI. ATC: priority 1 (error). Top refactor priority.
|
|
65
|
+
`.trim();
|
|
66
|
+
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// PROMPT 1 — clean_core_grade (atomic, single object)
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
const PROMPT_GRADE = {
|
|
71
|
+
name: "clean_core_grade",
|
|
72
|
+
description:
|
|
73
|
+
"Grade one ABAP object against SAP Clean Core levels A/B/C/D. Pulls source and ATC findings, classifies, cites reasons, and (if Level C/D) sketches the Level A refactor.",
|
|
74
|
+
arguments: [
|
|
75
|
+
{
|
|
76
|
+
name: "object",
|
|
77
|
+
description: "Object name (e.g., ZCL_PRICING).",
|
|
78
|
+
required: true,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "type",
|
|
82
|
+
description:
|
|
83
|
+
"Object type (program, class, interface, function, include, cds, etc.).",
|
|
84
|
+
required: true,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "system",
|
|
88
|
+
description: "Target system. Omit for default.",
|
|
89
|
+
required: false,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
build({ object, type, system }) {
|
|
93
|
+
return `
|
|
94
|
+
You are grading a single ABAP object against SAP's Clean Core extensibility
|
|
95
|
+
framework.
|
|
96
|
+
|
|
97
|
+
TARGET:
|
|
98
|
+
- Object: ${object}
|
|
99
|
+
- Type: ${type}
|
|
100
|
+
- System: ${system ?? "<default>"}
|
|
101
|
+
|
|
102
|
+
${APPLICABILITY_GUARD}
|
|
103
|
+
|
|
104
|
+
${TONE}
|
|
105
|
+
|
|
106
|
+
${LEVELS_TABLE}
|
|
107
|
+
|
|
108
|
+
${TOOL_REMINDER}
|
|
109
|
+
|
|
110
|
+
PROCEDURE:
|
|
111
|
+
1. Verify applicability (S/4HANA). Stop if ECC.
|
|
112
|
+
2. Fetch the source: adt_get_source { object: "${object}", type: "${type}"${system ? `, system: "${system}"` : ""} }.
|
|
113
|
+
3. Run ATC: adt_run_atc on the object. Map findings to A/B/C/D:
|
|
114
|
+
- priority 1 → Level D, priority 2 → Level C, priority 3 → Level B, no
|
|
115
|
+
finding → Level A (subject to source review).
|
|
116
|
+
4. Read the source for the patterns ATC misses or under-weights:
|
|
117
|
+
- UPDATE / INSERT / MODIFY on SAP standard tables (D)
|
|
118
|
+
- ENHANCEMENT-POINT ... INCLUDE BOUND on SAP code (D)
|
|
119
|
+
- Field-symbol tricks into SAP-internal structures (D)
|
|
120
|
+
- SELECT FROM SAP standard tables with no released CDS view used (C)
|
|
121
|
+
- CALL FUNCTION to internal (non-released) FMs (C)
|
|
122
|
+
- BAPI calls in new code without a wrapper (B, suggest wrap)
|
|
123
|
+
- Classic ALV / Web Dynpro / SE38 patterns in new code (B, legacy
|
|
124
|
+
acceptable)
|
|
125
|
+
5. Output, in this order:
|
|
126
|
+
- One-line verdict: "Level X" with a short reason.
|
|
127
|
+
- The 3-5 strongest evidence points (with file:line where useful).
|
|
128
|
+
- If Level C or D: a concrete refactor sketch in 5-10 lines (released
|
|
129
|
+
CDS view names, released BAdI names, business object interface).
|
|
130
|
+
- If the user says "I just need to ship": acknowledge, mark the level,
|
|
131
|
+
and put the refactor in a "later" callout. Do not block.
|
|
132
|
+
|
|
133
|
+
OUTPUT FORMAT: short, scannable. No filler. No lecturing on Clean Core
|
|
134
|
+
philosophy unless asked.
|
|
135
|
+
`.trim();
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
// PROMPT 2 — clean_core_review (atomic, package-wide KPIs)
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
const PROMPT_REVIEW = {
|
|
143
|
+
name: "clean_core_review",
|
|
144
|
+
description:
|
|
145
|
+
"Compute Clean Core KPIs for a package: level distribution (A/B/C/D %), Technical Debt Score, top Level D offenders.",
|
|
146
|
+
arguments: [
|
|
147
|
+
{
|
|
148
|
+
name: "package",
|
|
149
|
+
description: "ABAP package name (e.g., ZSALES).",
|
|
150
|
+
required: true,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: "system",
|
|
154
|
+
description: "Target system. Omit for default.",
|
|
155
|
+
required: false,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "maxObjects",
|
|
159
|
+
description: "Cap to avoid long runs. Default 50.",
|
|
160
|
+
required: false,
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
build({ package: pkg, system, maxObjects }) {
|
|
164
|
+
const cap = maxObjects ?? 50;
|
|
165
|
+
return `
|
|
166
|
+
Compute Clean Core KPIs across an ABAP package and surface the worst
|
|
167
|
+
offenders.
|
|
168
|
+
|
|
169
|
+
TARGET:
|
|
170
|
+
- Package: ${pkg}
|
|
171
|
+
- System: ${system ?? "<default>"}
|
|
172
|
+
- Object cap: ${cap} (do not exceed; prefer worst-likely subset if package is larger)
|
|
173
|
+
|
|
174
|
+
${APPLICABILITY_GUARD}
|
|
175
|
+
|
|
176
|
+
${TONE}
|
|
177
|
+
|
|
178
|
+
${LEVELS_TABLE}
|
|
179
|
+
|
|
180
|
+
${TOOL_REMINDER}
|
|
181
|
+
|
|
182
|
+
PROCEDURE:
|
|
183
|
+
1. Verify applicability (S/4HANA).
|
|
184
|
+
2. Walk the package: adt_browse_package { package: "${pkg}"${system ? `, system: "${system}"` : ""} }.
|
|
185
|
+
3. For each object up to the cap, run adt_run_atc and record the highest
|
|
186
|
+
finding priority. Map: 1→D, 2→C, 3→B, none→A.
|
|
187
|
+
4. Compute KPIs:
|
|
188
|
+
- **Clean Core Share** — % of objects at each level. Distribution shape
|
|
189
|
+
matters more than any single number.
|
|
190
|
+
- **Technical Debt Score** — sum of (errors × 10 + warnings × 5 + info × 1)
|
|
191
|
+
across the surveyed objects. Per-package number.
|
|
192
|
+
- **Modifications count** — objects flagged with modification-key /
|
|
193
|
+
SMODILOG patterns (heuristic from ATC findings).
|
|
194
|
+
5. Output:
|
|
195
|
+
- One-line summary: "%A / %B / %C / %D, score N, M modifications."
|
|
196
|
+
- Top 5-10 Level D offenders by name with their dominant finding.
|
|
197
|
+
- One-paragraph "what to attack first": Level D zero is the year-one
|
|
198
|
+
goal; identify the 2-3 highest-leverage targets.
|
|
199
|
+
- Note objects skipped due to the cap if any.
|
|
200
|
+
|
|
201
|
+
If the package is empty or doesn't exist, say so. Do not invent numbers.
|
|
202
|
+
`.trim();
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
// PROMPT 3 — clean_core_refactor (mode-loading, conversational)
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
const PROMPT_REFACTOR = {
|
|
210
|
+
name: "clean_core_refactor",
|
|
211
|
+
description:
|
|
212
|
+
"Enter Clean Core refactor mode for an ABAP object. Loads Level A patterns (BAPI wrapper, MARA→released CDS, modification→BAdI). Optionally takes an object to start with; otherwise waits for the user.",
|
|
213
|
+
arguments: [
|
|
214
|
+
{
|
|
215
|
+
name: "object",
|
|
216
|
+
description: "Optional object to start with.",
|
|
217
|
+
required: false,
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: "type",
|
|
221
|
+
description: "Object type. Required if 'object' is given.",
|
|
222
|
+
required: false,
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: "system",
|
|
226
|
+
description: "Target system. Omit for default.",
|
|
227
|
+
required: false,
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
build({ object, type, system }) {
|
|
231
|
+
const opening = object
|
|
232
|
+
? `Start with: ${object} (${type ?? "?type?"}) on ${system ?? "<default>"}. Fetch the source and propose a refactor plan before any writes.`
|
|
233
|
+
: `Wait for the user to point you at an object or paste source. Do not act until they do.`;
|
|
234
|
+
|
|
235
|
+
return `
|
|
236
|
+
You are in Clean Core REFACTOR mode. The user wants to lift an existing ABAP
|
|
237
|
+
object's cleanliness level — typically D→A or C→A — without changing
|
|
238
|
+
behavior.
|
|
239
|
+
|
|
240
|
+
${opening}
|
|
241
|
+
|
|
242
|
+
${APPLICABILITY_GUARD}
|
|
243
|
+
|
|
244
|
+
${TONE}
|
|
245
|
+
|
|
246
|
+
${LEVELS_TABLE}
|
|
247
|
+
|
|
248
|
+
${TOOL_REMINDER}
|
|
249
|
+
|
|
250
|
+
REFACTOR PATTERNS LOADED:
|
|
251
|
+
|
|
252
|
+
Pattern 1 — Wrap a classic API to expose Level A surface
|
|
253
|
+
Anti-pattern: BAPI called directly from new code.
|
|
254
|
+
Better: Z-class with a released-style interface; BAPI lives in one method.
|
|
255
|
+
Consumers see Level A. When SAP releases the successor, you change one file.
|
|
256
|
+
|
|
257
|
+
Pattern 2 — Replace internal table read with released CDS view
|
|
258
|
+
Anti-pattern: SELECT ... FROM MARA / VBAK / BSEG / etc.
|
|
259
|
+
Better: SELECT ... FROM I_Product / I_SalesOrder / ... (use
|
|
260
|
+
adt_search_objects to find the released "I_*" or "C_*" namespace
|
|
261
|
+
equivalent).
|
|
262
|
+
|
|
263
|
+
Pattern 3 — Replace modification with extension point
|
|
264
|
+
Anti-pattern: change to SAP standard via modification key.
|
|
265
|
+
Step 1: identify the business behavior changed.
|
|
266
|
+
Step 2: search for a released BAdI / extension point / business object
|
|
267
|
+
interface that exposes the same hook (adt_search_objects with relevant
|
|
268
|
+
pattern).
|
|
269
|
+
Step 3: reimplement the logic via that hook.
|
|
270
|
+
Step 4: if no released hook exists, file SAP Customer Influence and use a
|
|
271
|
+
Level B classic user exit as a bridge — never leave it as a Level D
|
|
272
|
+
modification.
|
|
273
|
+
|
|
274
|
+
WORKFLOW (every refactor):
|
|
275
|
+
1. Read current source (adt_get_source).
|
|
276
|
+
2. Run ATC to get the actual findings (adt_run_atc).
|
|
277
|
+
3. Propose a refactor plan: list each problem and the target Level A
|
|
278
|
+
pattern. Wait for user confirmation.
|
|
279
|
+
4. On confirm:
|
|
280
|
+
- For wrap-style refactors: adt_create_object (new wrapper class) →
|
|
281
|
+
adt_set_source → adt_syntax_check → adt_activate.
|
|
282
|
+
- For in-place edits: adt_lock → adt_set_source → adt_activate →
|
|
283
|
+
adt_unlock (use the sticky-lock pattern if multi-step).
|
|
284
|
+
- On any read-only system, refuse the writes and tell the user which
|
|
285
|
+
system would need to be writable.
|
|
286
|
+
5. Re-run ATC after the change. Confirm the level moved as intended.
|
|
287
|
+
6. If full Level A was not achievable, document why (no released
|
|
288
|
+
alternative, scheduled for SAP Customer Influence) and the new actual
|
|
289
|
+
level.
|
|
290
|
+
|
|
291
|
+
Never combine refactors with behavior changes. If the user asks for both,
|
|
292
|
+
sequence them: refactor first, behavior change second, two separate
|
|
293
|
+
activations so the diff is reviewable.
|
|
294
|
+
`.trim();
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
299
|
+
// PROMPT 4 — clean_core_create (mode-loading, ABAP Cloud default)
|
|
300
|
+
// ---------------------------------------------------------------------------
|
|
301
|
+
const PROMPT_CREATE = {
|
|
302
|
+
name: "clean_core_create",
|
|
303
|
+
description:
|
|
304
|
+
"Enter Clean Core creation mode. New ABAP objects default to Level A (ABAP Cloud, CDS views, RAP, business object interfaces). Optionally takes a requirement; otherwise waits for the user to describe what to build.",
|
|
305
|
+
arguments: [
|
|
306
|
+
{
|
|
307
|
+
name: "requirement",
|
|
308
|
+
description:
|
|
309
|
+
"Optional one-line description of what to build.",
|
|
310
|
+
required: false,
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
name: "package",
|
|
314
|
+
description: "Target package. Omit to ask the user.",
|
|
315
|
+
required: false,
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: "system",
|
|
319
|
+
description: "Target system. Omit for default.",
|
|
320
|
+
required: false,
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
build({ requirement, package: pkg, system }) {
|
|
324
|
+
const opening = requirement
|
|
325
|
+
? `Requirement: ${requirement}\nTarget package: ${pkg ?? "<ask the user>"}\nSystem: ${system ?? "<default>"}`
|
|
326
|
+
: `No requirement provided. Ask the user what they want to build, then proceed.`;
|
|
327
|
+
|
|
328
|
+
return `
|
|
329
|
+
You are in Clean Core CREATE mode. Every new object defaults to Level A.
|
|
330
|
+
|
|
331
|
+
${opening}
|
|
332
|
+
|
|
333
|
+
${APPLICABILITY_GUARD}
|
|
334
|
+
|
|
335
|
+
${TONE}
|
|
336
|
+
|
|
337
|
+
${TOOL_REMINDER}
|
|
338
|
+
|
|
339
|
+
ALLOWED IN ABAP CLOUD (use these):
|
|
340
|
+
- Released local APIs: released CDS views (I_*/C_* namespaces), business
|
|
341
|
+
object interfaces, released BAdIs, released CL_*/IF_* classes.
|
|
342
|
+
- Modeling: CDS for data models, RAP for stateful services, OData/web
|
|
343
|
+
services for remote consumption, released events for integration.
|
|
344
|
+
- Prebuilt services (no extra license): application logging, change
|
|
345
|
+
documents, number ranges, background jobs, factory calendar, currency
|
|
346
|
+
and UoM conversion, XLSX, printing, i18n.
|
|
347
|
+
- Custom: read/write your own Z-tables; CDS over them; RAP services
|
|
348
|
+
exposing them.
|
|
349
|
+
- Modern ABAP: inline DATA(), constructor expressions (NEW/VALUE/FOR/
|
|
350
|
+
REDUCE/COND/SWITCH), strict-mode Open SQL, ABAP Unit.
|
|
351
|
+
|
|
352
|
+
NOT ALLOWED IN ABAP CLOUD (compiler rejects):
|
|
353
|
+
- Direct write to SAP standard tables (UPDATE MARA, etc.) — use the BO
|
|
354
|
+
interface.
|
|
355
|
+
- Read access to non-released SAP tables — use a released CDS view.
|
|
356
|
+
- Calls to non-released SAP function modules / classes.
|
|
357
|
+
- Any reference to a noAPI object.
|
|
358
|
+
- Modifications, implicit enhancements (INCLUDE BOUND), code copy-paste
|
|
359
|
+
from SAP standard.
|
|
360
|
+
- Classic Dynpro, Web Dynpro ABAP, classic ALV grid (CL_GUI_ALV_GRID),
|
|
361
|
+
new SE38 reports.
|
|
362
|
+
- Native SQL, dynamic SQL bypassing the type system.
|
|
363
|
+
|
|
364
|
+
CREATION PIPELINE:
|
|
365
|
+
1. Confirm package + system with the user; check the system is writable.
|
|
366
|
+
2. Propose the design before writing code:
|
|
367
|
+
- Object type (class, RAP BO, CDS view, RAP service, ...).
|
|
368
|
+
- Released APIs / CDS views to consume (use adt_search_objects to find
|
|
369
|
+
them, e.g., pattern "I_Customer*" or "I_SalesOrder*").
|
|
370
|
+
- Wait for user confirmation on the design.
|
|
371
|
+
3. adt_create_object → adt_set_source → adt_syntax_check.
|
|
372
|
+
4. If syntax errors: report and stop. Do not paper over with broad pragmas.
|
|
373
|
+
5. adt_activate. If activation fails: report and stop.
|
|
374
|
+
6. If a Level B dependency was unavoidable (e.g., BAPI for write-back
|
|
375
|
+
while no successor BO interface exists yet): isolate it in a single
|
|
376
|
+
wrapper method, mark with a // Level B comment, and call out the
|
|
377
|
+
refactor trigger in your final summary.
|
|
378
|
+
|
|
379
|
+
DEFAULTS:
|
|
380
|
+
- UI? Fiori Elements + RAP, not SE38, not Web Dynpro.
|
|
381
|
+
- Custom field on SAP entity? Custom Fields app (key user extensibility),
|
|
382
|
+
not ABAP append.
|
|
383
|
+
- Business logic? ABAP Cloud class.
|
|
384
|
+
- Read-only data API? Released CDS view or projection over one.
|
|
385
|
+
- Write-back? Business object interface.
|
|
386
|
+
`.trim();
|
|
387
|
+
},
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
// ---------------------------------------------------------------------------
|
|
391
|
+
// PROMPT 5 — clean_core_design (mode-loading, architecture)
|
|
392
|
+
// ---------------------------------------------------------------------------
|
|
393
|
+
const PROMPT_DESIGN = {
|
|
394
|
+
name: "clean_core_design",
|
|
395
|
+
description:
|
|
396
|
+
"Enter Clean Core architecture mode. Walks fit-to-standard, the SAP Application Extension Methodology (3 phases), and the on-stack vs side-by-side decision. No code writes — produces a target solution design.",
|
|
397
|
+
arguments: [
|
|
398
|
+
{
|
|
399
|
+
name: "use_case",
|
|
400
|
+
description:
|
|
401
|
+
"Optional one-line description of the extension use case.",
|
|
402
|
+
required: false,
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
build({ use_case: useCase }) {
|
|
406
|
+
const opening = useCase
|
|
407
|
+
? `Use case: ${useCase}`
|
|
408
|
+
: `No use case provided. Ask the user to describe the business need first.`;
|
|
409
|
+
|
|
410
|
+
return `
|
|
411
|
+
You are in Clean Core DESIGN mode. The output is an extension architecture
|
|
412
|
+
proposal, not code. No writes.
|
|
413
|
+
|
|
414
|
+
${opening}
|
|
415
|
+
|
|
416
|
+
${APPLICABILITY_GUARD}
|
|
417
|
+
|
|
418
|
+
${TONE}
|
|
419
|
+
|
|
420
|
+
PROCEDURE:
|
|
421
|
+
|
|
422
|
+
PHASE 0 — Fit to standard (run this BEFORE any technology discussion)
|
|
423
|
+
1. Does SAP standard cover the requirement? If yes, configure and stop.
|
|
424
|
+
2. Is there a certified add-on with the "SAP-certified for clean core"
|
|
425
|
+
designation? If yes, evaluate it and stop.
|
|
426
|
+
3. Can configuration (SPRO, business configuration) cover it? If yes,
|
|
427
|
+
configure.
|
|
428
|
+
4. Only when 1-3 fail and the requirement is genuinely differentiating
|
|
429
|
+
does a custom extension begin.
|
|
430
|
+
|
|
431
|
+
If you can stop the conversation at Phase 0, do so. The most common form
|
|
432
|
+
of unnecessary technical debt is custom code for something the standard
|
|
433
|
+
already does.
|
|
434
|
+
|
|
435
|
+
PHASE 1 — Assess the use case
|
|
436
|
+
- Business need, why now, who's the user.
|
|
437
|
+
- Which SAP standard data and processes does it touch.
|
|
438
|
+
- Is transactional consistency with SAP core required (one LUW writing
|
|
439
|
+
custom + standard tables)?
|
|
440
|
+
- Data volume — small lookups vs high-volume joins.
|
|
441
|
+
- Consumer — internal, partners, customers, machines.
|
|
442
|
+
- Change cadence — weekly UI update vs annual ERP-aligned release.
|
|
443
|
+
|
|
444
|
+
PHASE 2 — Map to technology
|
|
445
|
+
|
|
446
|
+
| Task | On-stack options | Side-by-side options |
|
|
447
|
+
|---|---|---|
|
|
448
|
+
| Custom UI | SAPUI5/Fiori (A), Dynpro (B), Web Dynpro (B) | SAPUI5/Fiori (A), SAP Build Apps (A) |
|
|
449
|
+
| New business logic | ABAP Cloud (A), Classic ABAP (B-D) | CAP (A), ABAP Cloud on BTP (A) |
|
|
450
|
+
| Data integration | Released CDS (A), classic APIs (B), internal (C-D) | Released remote APIs (A), classic remote (B) |
|
|
451
|
+
| Custom field on SAP entity | Custom Fields framework (A), append (B-D) | n/a |
|
|
452
|
+
| Stand-alone app | n/a | CAP / SAP Build Apps / low-code (A) |
|
|
453
|
+
| Process automation | Workflow (A) | SAP Build Process Automation (A) |
|
|
454
|
+
|
|
455
|
+
ON-STACK vs SIDE-BY-SIDE — default is "BTP first" (side-by-side).
|
|
456
|
+
Pick on-stack only when ONE of these is clearly true:
|
|
457
|
+
- Transactional consistency with SAP core required.
|
|
458
|
+
- High-volume reads with complex joins on SAP standard data.
|
|
459
|
+
- Frequent reads/writes to SAP standard data (latency-sensitive).
|
|
460
|
+
- Extending core SAP UI / data model / business object behavior tightly.
|
|
461
|
+
|
|
462
|
+
If both groups apply: hybrid candidate. The on-stack half exposes a
|
|
463
|
+
released remote API (typically OData via RAP); the side-by-side half
|
|
464
|
+
consumes that. Best of both.
|
|
465
|
+
|
|
466
|
+
PHASE 3 — Define the target solution
|
|
467
|
+
Pick the highest-Level combination that satisfies Phase 1. Output:
|
|
468
|
+
- Extension style (on-stack / side-by-side / hybrid)
|
|
469
|
+
- Technologies for each component
|
|
470
|
+
- Clean core level for each component
|
|
471
|
+
- For anything below Level A: why, and the refactor trigger that would
|
|
472
|
+
move it up later.
|
|
473
|
+
|
|
474
|
+
OUTPUT:
|
|
475
|
+
A short architectural memo. ASCII diagram of components if useful.
|
|
476
|
+
Decisions made, decisions deferred (with what info would unblock them),
|
|
477
|
+
and the level achieved at each component.
|
|
478
|
+
|
|
479
|
+
If the user pushes for a Level D solution ("just modify the standard,
|
|
480
|
+
it's faster"): reframe in Phase 1. The same business outcome usually has
|
|
481
|
+
a Level A path the requester didn't know existed — released BAdI, BTP
|
|
482
|
+
workflow, configuration. Reframing requirements is the highest-leverage
|
|
483
|
+
clean core move there is.
|
|
484
|
+
`.trim();
|
|
485
|
+
},
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// ---------------------------------------------------------------------------
|
|
489
|
+
|
|
490
|
+
const PROMPTS = [
|
|
491
|
+
PROMPT_GRADE,
|
|
492
|
+
PROMPT_REVIEW,
|
|
493
|
+
PROMPT_REFACTOR,
|
|
494
|
+
PROMPT_CREATE,
|
|
495
|
+
PROMPT_DESIGN,
|
|
496
|
+
];
|
|
497
|
+
|
|
498
|
+
const PROMPT_INDEX = new Map(PROMPTS.map((p) => [p.name, p]));
|
|
499
|
+
|
|
500
|
+
export function listPrompts() {
|
|
501
|
+
return PROMPTS.map(({ name, description, arguments: args }) => ({
|
|
502
|
+
name,
|
|
503
|
+
description,
|
|
504
|
+
arguments: args,
|
|
505
|
+
}));
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
export function getPrompt(name, args = {}) {
|
|
509
|
+
const def = PROMPT_INDEX.get(name);
|
|
510
|
+
if (!def) {
|
|
511
|
+
throw new Error(`Unknown prompt: ${name}`);
|
|
512
|
+
}
|
|
513
|
+
// Validate required arguments.
|
|
514
|
+
for (const a of def.arguments) {
|
|
515
|
+
if (a.required && (args[a.name] == null || args[a.name] === "")) {
|
|
516
|
+
throw new Error(
|
|
517
|
+
`Prompt ${name}: missing required argument '${a.name}'`
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
const text = def.build(args);
|
|
522
|
+
return {
|
|
523
|
+
description: def.description,
|
|
524
|
+
messages: [
|
|
525
|
+
{
|
|
526
|
+
role: "user",
|
|
527
|
+
content: { type: "text", text },
|
|
528
|
+
},
|
|
529
|
+
],
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export const __forTests = { PROMPTS, PROMPT_INDEX };
|
package/src/result.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { parseAdtError } from "./adt-error.js";
|
|
2
|
+
|
|
3
|
+
export function textResult(text, isError = false) {
|
|
4
|
+
return { content: [{ type: "text", text }], isError };
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function jsonResult(value, isError = false) {
|
|
8
|
+
return textResult(JSON.stringify(value, null, 2), isError);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function errorResult(system, status, body, contentType, extra = {}) {
|
|
12
|
+
const parsed = parseAdtError(body, contentType);
|
|
13
|
+
return jsonResult(
|
|
14
|
+
{
|
|
15
|
+
system,
|
|
16
|
+
status,
|
|
17
|
+
ok: false,
|
|
18
|
+
...extra,
|
|
19
|
+
error: parsed ?? { raw: typeof body === "string" ? body.slice(0, 4000) : body },
|
|
20
|
+
},
|
|
21
|
+
true
|
|
22
|
+
);
|
|
23
|
+
}
|