arc-1 0.6.10 → 0.7.0

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.
Files changed (115) hide show
  1. package/README.md +8 -7
  2. package/bin/arc1-cli.js +10 -0
  3. package/bin/arc1.js +1 -1
  4. package/dist/adt/cds-impact.d.ts +35 -0
  5. package/dist/adt/cds-impact.d.ts.map +1 -1
  6. package/dist/adt/cds-impact.js +71 -0
  7. package/dist/adt/cds-impact.js.map +1 -1
  8. package/dist/adt/client.d.ts +4 -1
  9. package/dist/adt/client.d.ts.map +1 -1
  10. package/dist/adt/client.js +18 -5
  11. package/dist/adt/client.js.map +1 -1
  12. package/dist/adt/crud.d.ts.map +1 -1
  13. package/dist/adt/crud.js +32 -5
  14. package/dist/adt/crud.js.map +1 -1
  15. package/dist/adt/devtools.d.ts +39 -3
  16. package/dist/adt/devtools.d.ts.map +1 -1
  17. package/dist/adt/devtools.js +237 -25
  18. package/dist/adt/devtools.js.map +1 -1
  19. package/dist/adt/diagnostics.d.ts +69 -7
  20. package/dist/adt/diagnostics.d.ts.map +1 -1
  21. package/dist/adt/diagnostics.js +694 -36
  22. package/dist/adt/diagnostics.js.map +1 -1
  23. package/dist/adt/errors.d.ts +14 -1
  24. package/dist/adt/errors.d.ts.map +1 -1
  25. package/dist/adt/errors.js +40 -9
  26. package/dist/adt/errors.js.map +1 -1
  27. package/dist/adt/http.d.ts.map +1 -1
  28. package/dist/adt/http.js +86 -1
  29. package/dist/adt/http.js.map +1 -1
  30. package/dist/adt/rap-handlers.d.ts +165 -0
  31. package/dist/adt/rap-handlers.d.ts.map +1 -0
  32. package/dist/adt/rap-handlers.js +835 -0
  33. package/dist/adt/rap-handlers.js.map +1 -0
  34. package/dist/adt/rap-preflight.d.ts +43 -0
  35. package/dist/adt/rap-preflight.d.ts.map +1 -0
  36. package/dist/adt/rap-preflight.js +405 -0
  37. package/dist/adt/rap-preflight.js.map +1 -0
  38. package/dist/adt/safety.d.ts +60 -36
  39. package/dist/adt/safety.d.ts.map +1 -1
  40. package/dist/adt/safety.js +202 -120
  41. package/dist/adt/safety.js.map +1 -1
  42. package/dist/adt/transport.d.ts +1 -1
  43. package/dist/adt/transport.js +2 -2
  44. package/dist/adt/transport.js.map +1 -1
  45. package/dist/adt/types.d.ts +88 -0
  46. package/dist/adt/types.d.ts.map +1 -1
  47. package/dist/adt/xml-parser.d.ts +13 -1
  48. package/dist/adt/xml-parser.d.ts.map +1 -1
  49. package/dist/adt/xml-parser.js +26 -15
  50. package/dist/adt/xml-parser.js.map +1 -1
  51. package/dist/authz/policy.d.ts +53 -0
  52. package/dist/authz/policy.d.ts.map +1 -0
  53. package/dist/authz/policy.js +199 -0
  54. package/dist/authz/policy.js.map +1 -0
  55. package/dist/cli-args.d.ts +14 -0
  56. package/dist/cli-args.d.ts.map +1 -0
  57. package/dist/cli-args.js +62 -0
  58. package/dist/cli-args.js.map +1 -0
  59. package/dist/cli.d.ts +13 -7
  60. package/dist/cli.d.ts.map +1 -1
  61. package/dist/cli.js +252 -55
  62. package/dist/cli.js.map +1 -1
  63. package/dist/extract-sap-cookies.d.ts +24 -0
  64. package/dist/extract-sap-cookies.d.ts.map +1 -0
  65. package/dist/extract-sap-cookies.js +317 -0
  66. package/dist/extract-sap-cookies.js.map +1 -0
  67. package/dist/handlers/hyperfocused.d.ts +4 -3
  68. package/dist/handlers/hyperfocused.d.ts.map +1 -1
  69. package/dist/handlers/hyperfocused.js +25 -16
  70. package/dist/handlers/hyperfocused.js.map +1 -1
  71. package/dist/handlers/intent.d.ts +4 -12
  72. package/dist/handlers/intent.d.ts.map +1 -1
  73. package/dist/handlers/intent.js +1238 -114
  74. package/dist/handlers/intent.js.map +1 -1
  75. package/dist/handlers/schemas.d.ts +38 -10
  76. package/dist/handlers/schemas.d.ts.map +1 -1
  77. package/dist/handlers/schemas.js +69 -4
  78. package/dist/handlers/schemas.js.map +1 -1
  79. package/dist/handlers/tools.d.ts.map +1 -1
  80. package/dist/handlers/tools.js +251 -164
  81. package/dist/handlers/tools.js.map +1 -1
  82. package/dist/index.d.ts +1 -1
  83. package/dist/index.js +7 -6
  84. package/dist/index.js.map +1 -1
  85. package/dist/server/audit.d.ts +26 -3
  86. package/dist/server/audit.d.ts.map +1 -1
  87. package/dist/server/audit.js.map +1 -1
  88. package/dist/server/config.d.ts +34 -19
  89. package/dist/server/config.d.ts.map +1 -1
  90. package/dist/server/config.js +320 -193
  91. package/dist/server/config.js.map +1 -1
  92. package/dist/server/deny-actions.d.ts +31 -0
  93. package/dist/server/deny-actions.d.ts.map +1 -0
  94. package/dist/server/deny-actions.js +156 -0
  95. package/dist/server/deny-actions.js.map +1 -0
  96. package/dist/server/effective-policy-log.d.ts +27 -0
  97. package/dist/server/effective-policy-log.d.ts.map +1 -0
  98. package/dist/server/effective-policy-log.js +103 -0
  99. package/dist/server/effective-policy-log.js.map +1 -0
  100. package/dist/server/http.d.ts.map +1 -1
  101. package/dist/server/http.js +15 -16
  102. package/dist/server/http.js.map +1 -1
  103. package/dist/server/server.d.ts +37 -3
  104. package/dist/server/server.d.ts.map +1 -1
  105. package/dist/server/server.js +231 -30
  106. package/dist/server/server.js.map +1 -1
  107. package/dist/server/types.d.ts +29 -13
  108. package/dist/server/types.d.ts.map +1 -1
  109. package/dist/server/types.js +10 -11
  110. package/dist/server/types.js.map +1 -1
  111. package/dist/server/xsuaa.d.ts +1 -2
  112. package/dist/server/xsuaa.d.ts.map +1 -1
  113. package/dist/server/xsuaa.js +13 -14
  114. package/dist/server/xsuaa.js.map +1 -1
  115. package/package.json +6 -3
@@ -133,7 +133,8 @@ const SAPWRITE_DESC_ONPREM = 'Create or update ABAP source code and DDIC metadat
133
133
  'SKTD (Knowledge Transfer Documents, Markdown docs attached to an ABAP object): create requires refObjectType (parent ADT type+subtype, e.g., "DDLS/DF"). A KTD inherits the name of the object it documents — so "name" MUST equal the parent object name (one KTD per object; refObjectName defaults to name and cannot differ). Update takes Markdown in "source"; delete uses the ADT deletion framework (two-step check/delete). Follow creates/updates with SAPActivate(type="SKTD", name="..."). ' +
134
134
  'For edit_method: surgically replace a single method body in a CLAS without sending the full class source. ' +
135
135
  'Provide just the new method implementation code in "source" — 95% fewer tokens than full-class updates. ' +
136
- 'For batch_create: create and activate multiple objects in a single call — ideal for RAP stacks (TABL → DDLS → DCLS → BDEF → SRVD). Pass "objects" array with dependency order.';
136
+ 'For batch_create: create and activate multiple objects in a single call — ideal for RAP stacks (TABL → DDLS → DCLS → BDEF → SRVD). Pass "objects" array with dependency order. ' +
137
+ 'For scaffold_rap_handlers: derive missing RAP behavior handler signatures from an interface BDEF and optionally inject declarations plus empty implementation stubs into an existing behavior pool class.';
137
138
  const SAPWRITE_DESC_BTP = 'Create or update ABAP source code and DDIC metadata (BTP ABAP Environment). Handles lock/modify/unlock automatically. Supports CLAS, INTF, DDLS, DDLX, BDEF, SRVD, SRVB, SKTD, TABL, DOMA, DTEL, MSAG. ' +
138
139
  'Type codes are auto-normalized and case-insensitive (e.g., "CLAS/OC" → "CLAS"). ' +
139
140
  'TABL supports custom table source writes via /source/main (define table syntax). ' +
@@ -144,7 +145,8 @@ const SAPWRITE_DESC_BTP = 'Create or update ABAP source code and DDIC metadata (
144
145
  'SKTD (Knowledge Transfer Documents, Markdown docs attached to an ABAP object): create requires refObjectType (parent ADT type+subtype, e.g., "DDLS/DF"). A KTD inherits the name of the object it documents — so "name" MUST equal the parent object name (one KTD per object; refObjectName defaults to name and cannot differ). Update takes Markdown in "source"; delete uses the ADT deletion framework (two-step check/delete). Follow creates/updates with SAPActivate(type="SKTD", name="..."). ' +
145
146
  'Must use ABAP Cloud language version (no classic statements). Only Z*/Y* namespace allowed on BTP. ' +
146
147
  'For edit_method: surgically replace a single method body in a CLAS without sending the full class source. ' +
147
- 'For batch_create: create and activate multiple objects in a single call — ideal for RAP stacks (TABL → DDLS → DCLS → BDEF → SRVD).';
148
+ 'For batch_create: create and activate multiple objects in a single call — ideal for RAP stacks (TABL → DDLS → DCLS → BDEF → SRVD). ' +
149
+ 'For scaffold_rap_handlers: derive missing RAP behavior handler signatures from an interface BDEF and optionally inject declarations plus empty implementation stubs into an existing behavior pool class.';
148
150
  // ─── SAPContext Types ───────────────────────────────────────────────
149
151
  const SAPCONTEXT_TYPES_ONPREM = ['CLAS', 'INTF', 'PROG', 'FUNC', 'DDLS'];
150
152
  const SAPCONTEXT_TYPES_BTP = ['CLAS', 'INTF', 'DDLS'];
@@ -153,7 +155,7 @@ const SAPCONTEXT_DESC_ONPREM = 'Get compressed dependency context or CDS blast-r
153
155
  '- "What breaks if I change <CDS view>?" / "Who consumes <I_*>?" / "Impact analysis on <DDLS>" / "Blast radius" → action="impact"\n' +
154
156
  '- "Understand dependencies before editing <object>" / "What does X depend on?" → action="deps" (default)\n' +
155
157
  '- "Find all callers of <object>" (cache-warmup required) → action="usages"\n\n' +
156
- 'action="impact" (CDS blast-radius, DDLS only): ALWAYS use this for CDS change-impact questions. Returns upstream AST dependencies plus downstream where-used results classified into RAP-aware buckets: projectionViews, bdefs, serviceDefinitions, serviceBindings, accessControls (DCLS), metadataExtensions (DDLX), abapConsumers, documentation (SKTD), tables, other. DO NOT replicate this with SAPQuery against DDDDLSRC/ACMDCLSRC/DDLXSRC_SRC/SRVDSRC_SRC — those text scans produce noise (non-dependency matches, package group nodes) that this classifier already filters out. Optional includeIndirect=true widens to transitive consumers.\n\n' +
158
+ 'action="impact" (CDS blast-radius, DDLS only): ALWAYS use this for CDS change-impact questions. Returns upstream AST dependencies plus downstream where-used results classified into RAP-aware buckets: projectionViews, bdefs, serviceDefinitions, serviceBindings, accessControls (DCLS), metadataExtensions (DDLX), abapConsumers, documentation (SKTD), tables, other. Also emits additive sibling-consistency diagnostics (consistencyHints + siblingExtensionAnalysis) when sibling DDLS variants in the same package show asymmetric metadata-extension coverage. DO NOT replicate this with SAPQuery against DDDDLSRC/ACMDCLSRC/DDLXSRC_SRC/SRVDSRC_SRC — those text scans produce noise (non-dependency matches, package group nodes) that this classifier already filters out. Optional includeIndirect=true widens to transitive consumers. Optional siblingCheck=false disables sibling analysis; siblingMaxCandidates controls fan-out (default 4, hard cap 10).\n\n' +
157
159
  'action="deps" (default): Returns only the public API contracts (method signatures, interface definitions, type declarations) of all objects that the target depends on — NOT the full source code. The most token-efficient way to understand dependencies. Instead of N separate SAPRead calls returning full source (~200 lines each), returns ONE response with compressed contracts (~15-30 lines each). Typical compression: 7-30x fewer tokens.\n\n' +
158
160
  'What deps extracts per dependency:\n' +
159
161
  '- Classes: CLASS DEFINITION with PUBLIC SECTION only (methods, types, constants). PROTECTED, PRIVATE and IMPLEMENTATION stripped.\n' +
@@ -170,7 +172,7 @@ const SAPCONTEXT_DESC_BTP = 'Get compressed dependency context or CDS blast-radi
170
172
  "Decision rule — pick the action based on the user's question:\n" +
171
173
  '- "What breaks if I change <CDS view>?" / "Who consumes <I_*>?" / "Impact analysis on <DDLS>" / "Blast radius" → action="impact"\n' +
172
174
  '- "Understand dependencies before editing <object>" / "What does X depend on?" → action="deps" (default)\n\n' +
173
- 'action="impact" (CDS blast-radius, DDLS only): ALWAYS use this for CDS change-impact questions. Returns upstream AST dependencies plus downstream where-used results classified into RAP-aware buckets: projectionViews, bdefs, serviceDefinitions, serviceBindings, accessControls (DCLS), metadataExtensions (DDLX), abapConsumers, documentation (SKTD), tables, other. DO NOT replicate this with SAPQuery — the classifier already filters noise. Optional includeIndirect=true widens to transitive consumers.\n\n' +
175
+ 'action="impact" (CDS blast-radius, DDLS only): ALWAYS use this for CDS change-impact questions. Returns upstream AST dependencies plus downstream where-used results classified into RAP-aware buckets: projectionViews, bdefs, serviceDefinitions, serviceBindings, accessControls (DCLS), metadataExtensions (DDLX), abapConsumers, documentation (SKTD), tables, other. Also emits additive sibling-consistency diagnostics (consistencyHints + siblingExtensionAnalysis) when sibling DDLS variants in the same package show asymmetric metadata-extension coverage. DO NOT replicate this with SAPQuery — the classifier already filters noise. Optional includeIndirect=true widens to transitive consumers. Optional siblingCheck=false disables sibling analysis; siblingMaxCandidates controls fan-out (default 4, hard cap 10).\n\n' +
174
176
  'action="deps" (default): Returns only the public API contracts (method signatures, interface definitions, type declarations) of all objects that the target depends on — NOT the full source code.\n\n' +
175
177
  'What deps extracts per dependency:\n' +
176
178
  '- Classes: CLASS DEFINITION with PUBLIC SECTION only (methods, types, constants).\n' +
@@ -185,7 +187,7 @@ const SAPQUERY_DESC_ONPREM = 'Execute ABAP SQL queries against SAP tables. Retur
185
187
  'Powerful for reverse-engineering: query metadata tables like DD02L (table catalog), DD03L (field catalog), ' +
186
188
  'SWOTLV (BOR method implementations), TADIR (object directory), TFDIR (function modules). ' +
187
189
  'If a table is not found, similar table names will be suggested automatically. ' +
188
- 'Note: Uses the ADT freestyle SQL endpoint (same as ADT SQL Console in Eclipse). Supports ABAP SQL syntax including JOINs, but the endpoint parser has known edge cases with complex queries on some system versions (SAP Note 3605050). If a complex query fails, try simplifying split JOINs into separate single-table SELECTs.\n\n' +
190
+ 'Note: Uses the ADT freestyle SQL endpoint (same family as ADT SQL Console in Eclipse). ABAP SQL language supports JOINs and subqueries, but this endpoint parser can reject valid-looking statements on some backend versions (for example grammar errors, single-SELECT enforcement). If parsing fails, simplify to one SELECT and split multi-table logic into staged single-table queries (SAP Note 3605050).\n\n' +
189
191
  'CDS impact analysis: DO NOT query DDDDLSRC, ACMDCLSRC, DDLXSRC_SRC, or SRVDSRC_SRC to find CDS consumers — those text scans produce noise (substring matches, package group nodes, generated patterns). Use SAPContext(action="impact", type="DDLS", name="...") instead — it uses SAP\'s where-used index and returns bucketed, filtered results (projection views, BDEFs, SRVDs, access controls, documentation, ABAP consumers).';
190
192
  const SAPQUERY_DESC_BTP = 'Execute ABAP SQL queries (BTP ABAP Environment). Returns structured data with column names and rows. ' +
191
193
  'IMPORTANT: On BTP, only custom Z/Y tables and released CDS entities can be queried. ' +
@@ -207,14 +209,14 @@ const SAPTRANSPORT_DESC_ONPREM = 'Manage CTS transport requests (SE09/SE10 equiv
207
209
  'get (details with tasks and objects), create (K=Workbench, W=Customizing, T=Transport of Copies), ' +
208
210
  'release, delete, reassign (change owner), release_recursive (release tasks first, then parent), ' +
209
211
  'check (check if a package requires a transport — provide type, name, package), ' +
210
- 'history (find transports referencing an object — provide type, name; read-only, works without --enable-transports). ' +
212
+ 'history (find transports referencing an object — provide type, name; read-only, works without SAP_ALLOW_TRANSPORT_WRITES). ' +
211
213
  'Transport IDs look like A4HK900123. Status: D=modifiable, R=released.';
212
214
  const SAPTRANSPORT_DESC_BTP = 'Manage transport requests (BTP ABAP Environment, SE09/SE10 equivalent). ' +
213
215
  'Actions: list (defaults to current user, modifiable transports — both Workbench and Customizing), ' +
214
216
  'get (details with tasks and objects), create (K=Workbench, W=Customizing, T=Transport of Copies), ' +
215
217
  'release, delete, reassign (change owner), release_recursive (release tasks first, then parent), ' +
216
218
  'check (check if a package requires a transport — provide type, name, package), ' +
217
- 'history (find transports referencing an object — provide type, name; read-only, works without --enable-transports). ' +
219
+ 'history (find transports referencing an object — provide type, name; read-only, works without SAP_ALLOW_TRANSPORT_WRITES). ' +
218
220
  'On BTP, transport release triggers a gCTS push to the software component Git repository. ' +
219
221
  'Import into target systems is done via the Manage Software Components app or Cloud Transport Management Service (cTMS), not via this tool.';
220
222
  // ─── SAPManage ──────────────────────────────────────────────────────
@@ -223,14 +225,14 @@ const SAPMANAGE_DESC_ONPREM = 'Probe and report SAP system capabilities. Use thi
223
225
  'Actions:\n' +
224
226
  '- "features": Get cached feature status from last probe (fast, no SAP round-trip). ' +
225
227
  'Returns which features are available, their mode (auto/on/off), and when they were last probed.\n' +
226
- '- "probe": Re-probe the SAP system now (makes 8 parallel requests, ~1-2s). ' +
228
+ '- "probe": Re-probe the SAP system now (runs feature probes, auth checks, and ADT discovery refresh). ' +
227
229
  'Use this on first use or if you suspect feature availability has changed.\n' +
228
230
  '- "cache_stats": Show object cache health and warmup state.\n' +
229
- '- "create_package": Create a package (DEVC) via ADT packages API.\n' +
230
- '- "delete_package": Delete an existing package.\n' +
231
231
  '- "flp_list_catalogs": List FLP business catalogs.\n' +
232
232
  '- "flp_list_groups": List FLP groups.\n' +
233
233
  '- "flp_list_tiles": List tiles in a catalog (requires "catalogId").\n' +
234
+ '- "create_package": Create a package (DEVC) via ADT packages API.\n' +
235
+ '- "delete_package": Delete an existing package.\n' +
234
236
  '- "flp_create_catalog": Create a business catalog (requires "domainId", "title").\n' +
235
237
  '- "flp_create_group": Create a group (requires "groupId", "title").\n' +
236
238
  '- "flp_create_tile": Create a tile in a catalog (requires "catalogId", "tile").\n' +
@@ -243,20 +245,51 @@ const SAPMANAGE_DESC_BTP = 'Probe and report SAP system capabilities (BTP ABAP E
243
245
  'Returns feature status and system type. Also handles package (DEVC) lifecycle operations.\n\n' +
244
246
  'Actions:\n' +
245
247
  '- "features": Get cached feature status from last probe.\n' +
246
- '- "probe": Re-probe the SAP system now.\n' +
248
+ '- "probe": Re-probe the SAP system now (feature probes + discovery refresh).\n' +
247
249
  '- "cache_stats": Show object cache health and warmup state.\n' +
248
250
  '- "create_package": Create a package (DEVC) via ADT packages API.\n' +
249
251
  '- "delete_package": Delete an existing package.\n' +
250
252
  '- FLP actions: flp_list_catalogs, flp_list_groups, flp_list_tiles, flp_create_catalog, flp_create_group, flp_create_tile, flp_add_tile_to_group, flp_delete_catalog.\n\n' +
251
253
  'Returns JSON with features and systemType="btp". On BTP, RAP/CDS and transports are always available. ' +
252
254
  'abapGit, AMDP, UI5/BSP, and FLP customization may not be available depending on the BTP ABAP configuration.';
255
+ const SAPMANAGE_ACTIONS_READ = [
256
+ 'features',
257
+ 'probe',
258
+ 'cache_stats',
259
+ 'flp_list_catalogs',
260
+ 'flp_list_groups',
261
+ 'flp_list_tiles',
262
+ ];
263
+ const SAPMANAGE_ACTIONS_WRITE = [
264
+ 'create_package',
265
+ 'delete_package',
266
+ 'change_package',
267
+ 'flp_create_catalog',
268
+ 'flp_create_group',
269
+ 'flp_create_tile',
270
+ 'flp_add_tile_to_group',
271
+ 'flp_delete_catalog',
272
+ ];
273
+ const SAPTRANSPORT_ACTIONS_READ = ['list', 'get', 'check', 'history'];
274
+ const SAPTRANSPORT_ACTIONS_WRITE = ['create', 'release', 'delete', 'reassign', 'release_recursive'];
275
+ const SAPGIT_ACTIONS_READ = [
276
+ 'list_repos',
277
+ 'whoami',
278
+ 'config',
279
+ 'branches',
280
+ 'external_info',
281
+ 'history',
282
+ 'objects',
283
+ 'check',
284
+ ];
285
+ const SAPGIT_ACTIONS_WRITE = ['stage', 'clone', 'pull', 'push', 'commit', 'switch_branch', 'create_branch', 'unlink'];
253
286
  // ─── SAPGit ─────────────────────────────────────────────────────────
254
287
  const SAPGIT_DESC_ONPREM = 'Git-based ABAP repository workflows with backend auto-selection: gCTS is preferred when available, otherwise abapGit bridge is used. ' +
255
288
  'Actions: list_repos (both), whoami/config/branches/history/objects (gCTS only), external_info/check/stage/push (abapGit only), clone/pull/commit/switch_branch/create_branch/unlink (backend-specific implementation). ' +
256
- 'Use backend="gcts" or backend="abapgit" to force a backend. Write actions require --enable-git and package allowlist compliance.';
289
+ 'Use backend="gcts" or backend="abapgit" to force a backend. Write actions require SAP_ALLOW_WRITES=true, SAP_ALLOW_GIT_WRITES=true, git scope, and package allowlist compliance.';
257
290
  const SAPGIT_DESC_BTP = 'Git-based ABAP repository workflows for BTP ABAP and S/4 systems. Backend auto-selection prefers gCTS and falls back to abapGit bridge when gCTS is unavailable. ' +
258
291
  'Actions: list_repos (both), whoami/config/branches/history/objects (gCTS only), external_info/check/stage/push (abapGit only), clone/pull/commit/switch_branch/create_branch/unlink (backend-specific implementation). ' +
259
- 'Use backend="gcts" or backend="abapgit" to force a backend. Write actions require --enable-git and package allowlist compliance.';
292
+ 'Use backend="gcts" or backend="abapgit" to force a backend. Write actions require SAP_ALLOW_WRITES=true, SAP_ALLOW_GIT_WRITES=true, git scope, and package allowlist compliance.';
260
293
  // ─── SAPSearch Builder ─────────────────────────────────────────────
261
294
  /** Strip source_code-specific lines from a SAPSearch description when textSearch is unavailable */
262
295
  function stripSourceCodeLines(desc) {
@@ -316,7 +349,7 @@ function buildSAPSearchTool(btp, textSearchAvailable) {
316
349
  export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures) {
317
350
  // Hyperfocused mode: single universal SAP tool (~200 tokens)
318
351
  if (config.toolMode === 'hyperfocused') {
319
- return [getHyperfocusedToolDefinition(config)];
352
+ return [getHyperfocusedToolDefinition(config, resolvedFeatures)];
320
353
  }
321
354
  const btp = isBtpMode(config);
322
355
  const tools = [
@@ -365,7 +398,10 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
365
398
  description: 'Output format. "text" (default): raw source code. "structured" (CLAS only): JSON with metadata (description, language, category) + decomposed source (main, testclasses, definitions, implementations, macros). Useful when you need to understand class structure or separate test code from production code.',
366
399
  },
367
400
  maxRows: { type: 'number', description: 'For TABLE_CONTENTS: max rows to return (default 100)' },
368
- sqlFilter: { type: 'string', description: 'For TABLE_CONTENTS: SQL WHERE clause filter' },
401
+ sqlFilter: {
402
+ type: 'string',
403
+ description: 'For TABLE_CONTENTS: condition expression only (no WHERE, no SELECT), e.g. "MANDT = \'100\'" or "MATNR LIKE \'Z%\'".',
404
+ },
369
405
  objectType: {
370
406
  type: 'string',
371
407
  description: 'For API_STATE and VERSIONS: SAP object type (CLAS, INTF, PROG, FUNC, INCL, DDLS, DCLS, BDEF, SRVD, etc.). For API_STATE: auto-detected from name if omitted. For VERSIONS: required to pick the correct revisions endpoint (e.g., "FUNC" + group for function modules); inferred from CL_/IF_/CX_ name prefixes when possible, defaults to PROG.',
@@ -380,8 +416,8 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
380
416
  },
381
417
  buildSAPSearchTool(btp, textSearchAvailable),
382
418
  ];
383
- // Write tools — only registered when not in read-only mode
384
- if (!config.readOnly) {
419
+ // Write tools — only registered when writes are enabled
420
+ if (config.allowWrites) {
385
421
  let sapWriteDesc = btp ? SAPWRITE_DESC_BTP : SAPWRITE_DESC_ONPREM;
386
422
  // Append package restriction info so the LLM knows its boundaries
387
423
  if (config.allowedPackages.length > 0) {
@@ -396,8 +432,8 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
396
432
  properties: {
397
433
  action: {
398
434
  type: 'string',
399
- enum: ['create', 'update', 'delete', 'edit_method', 'batch_create'],
400
- description: 'Write action. edit_method: surgically replace a single method body (requires type=CLAS, method, and source params). batch_create: create and activate multiple objects in sequence (requires objects array)',
435
+ enum: ['create', 'update', 'delete', 'edit_method', 'batch_create', 'scaffold_rap_handlers'],
436
+ description: 'Write action. edit_method: surgically replace a single method body (requires type=CLAS, method, and source params). batch_create: create and activate multiple objects in sequence (requires objects array). scaffold_rap_handlers: derive missing behavior-pool handler signatures from interface BDEF declarations and optionally inject declarations plus empty implementation stubs.',
401
437
  },
402
438
  type: {
403
439
  type: 'string',
@@ -412,6 +448,18 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
412
448
  type: 'string',
413
449
  description: 'For edit_method action: method name to replace (e.g., "get_name", "zif_order~process")',
414
450
  },
451
+ bdefName: {
452
+ type: 'string',
453
+ description: 'For scaffold_rap_handlers action: interface BDEF name used to derive required handler signatures (e.g., ZI_TRAVELREQ). The BDEF is parsed to find every action/determination/validation/authorization that must exist in the behavior pool.',
454
+ },
455
+ autoApply: {
456
+ type: 'boolean',
457
+ description: 'For scaffold_rap_handlers: when true, missing METHODS signatures are inserted into matching lhc_* class definitions, empty METHOD stubs are inserted into matching implementation blocks where possible, and the class source is written back under a single lock. When false (default), returns a JSON report of required vs. missing signatures without modifying the class — use this first to preview, then re-run with autoApply=true to commit.',
458
+ },
459
+ targetAlias: {
460
+ type: 'string',
461
+ description: 'For scaffold_rap_handlers: optional RAP entity alias filter (e.g., Travel, Segment) to scaffold only one handler class. When omitted, all entities declared in the BDEF are scaffolded. Case-insensitive.',
462
+ },
415
463
  description: {
416
464
  type: 'string',
417
465
  description: 'Object description for create action (defaults to name if omitted). Max 60 chars for most types.',
@@ -479,7 +527,15 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
479
527
  version: { type: 'string', description: 'SRVB: service version number (default: 0001)' },
480
528
  lintBeforeWrite: {
481
529
  type: 'boolean',
482
- description: 'Override server lint-before-write setting for this call. Set false to skip pre-write lint validation. Lint applies to ABAP types (PROG, CLAS, INTF, FUNC) and CDS views (DDLS). BDEF/SRVD/SRVB/DDLX/TABL are skipped (not supported by offline linter).',
530
+ description: 'Override server lint-before-write setting for this call. Set false to skip pre-write lint validation. Lint applies to ABAP types (PROG, CLAS, INTF, FUNC) and CDS views (DDLS). BDEF/SRVD/SRVB/DDLX/TABL are skipped by offline linter; RAP preflight may still catch deterministic issues for those types.',
531
+ },
532
+ preflightBeforeWrite: {
533
+ type: 'boolean',
534
+ description: 'Enable/disable deterministic RAP preflight checks for this call (default: true). Useful for TABL/BDEF/DDLX static rules (e.g., curr/quan semantics, invalid BDEF enums, unsupported DDLX annotation scope on on-prem 7.5x).',
535
+ },
536
+ checkBeforeWrite: {
537
+ type: 'boolean',
538
+ description: 'Override server check-before-write setting (default off). When true, SAPWrite sends the proposed source to /sap/bc/adt/checkruns with inline <chkrun:content> and appends any error/warning messages to the success response — the write is NOT blocked. Useful for single-file edits to see compile diagnostics without a separate SAPDiagnose call. Off by default because (a) it adds a round-trip per write and (b) intermediate writes during multi-file refactors will legitimately trip dependency errors that resolve once the whole sequence lands. Activation remains the definitive compile check.',
483
539
  },
484
540
  refObjectType: {
485
541
  type: 'string',
@@ -650,7 +706,7 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
650
706
  },
651
707
  });
652
708
  // SAPQuery — only registered when free SQL is allowed
653
- if (!config.blockFreeSQL) {
709
+ if (config.allowFreeSQL) {
654
710
  tools.push({
655
711
  name: 'SAPQuery',
656
712
  description: btp ? SAPQUERY_DESC_BTP : SAPQUERY_DESC_ONPREM,
@@ -709,20 +765,32 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
709
765
  name: 'SAPDiagnose',
710
766
  description: 'Run diagnostics on ABAP objects and analyze runtime errors.\n\n' +
711
767
  'Actions:\n' +
712
- '- "syntax": Syntax check an ABAP object. Requires name + type.\n' +
768
+ '- "syntax": Syntax check an ABAP object. Requires name + type. Optional: version ("active" or "inactive", defaults to active). Optional: source — when supplied, SAP compiles the given content as if it lived at the object\'s URI (pre-write dry-run, nothing is written). Omit source to check what is stored.\n' +
713
769
  '- "unittest": Run ABAP unit tests. Requires name + type.\n' +
714
770
  '- "atc": Run ATC code quality checks. Requires name + type. Optional: variant.\n' +
715
771
  '- "quickfix": Get SAP quick fix proposals for a specific source position. Requires name + type + source + line. Optional: column.\n' +
716
772
  '- "apply_quickfix": Apply one quick fix proposal and return text deltas (does not write source). Requires name + type + source + line + proposalUri + proposalUserContent. Optional: column.\n' +
717
- '- "dumps": List or read ABAP short dumps (ST22). Without id: lists recent dumps (filter by user, maxResults). With id: returns full dump detail including formatted text, error analysis, source code extract, and call stack.\n' +
773
+ '- "dumps": List or read ABAP short dumps (ST22). Without id: lists recent dumps (filter by user, maxResults). With id: returns focused chapter sections by default; set includeFullText=true to include the full formatted dump blob. Optional sections=[kap0,kap3,...] to request specific chapter IDs.\n' +
718
774
  '- "traces": List or analyze ABAP profiler traces. Without id: lists trace files. With id + analysis: returns trace analysis (hitlist = hot spots, statements = call tree, dbAccesses = database access statistics).\n\n' +
775
+ '- "system_messages": List SM02 system messages via ADT feed (filter by user, maxResults, from, to).\n' +
776
+ '- "gateway_errors": List SAP Gateway error log entries (/IWFND/ERROR_LOG, on-prem). For detail mode provide detailUrl (preferred) or id+errorType.\n\n' +
719
777
  'Quickfix workflow: run syntax/ATC first to identify issues and line positions, then call quickfix to retrieve SAP-verified proposals, then apply_quickfix to get exact text deltas, and finally write the updated source via SAPWrite.',
720
778
  inputSchema: {
721
779
  type: 'object',
722
780
  properties: {
723
781
  action: {
724
782
  type: 'string',
725
- enum: ['syntax', 'unittest', 'atc', 'dumps', 'traces', 'quickfix', 'apply_quickfix'],
783
+ enum: [
784
+ 'syntax',
785
+ 'unittest',
786
+ 'atc',
787
+ 'dumps',
788
+ 'traces',
789
+ 'system_messages',
790
+ 'gateway_errors',
791
+ 'quickfix',
792
+ 'apply_quickfix',
793
+ ],
726
794
  description: 'Diagnostic action',
727
795
  },
728
796
  name: { type: 'string', description: 'Object name (for syntax/unittest/atc)' },
@@ -739,6 +807,11 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
739
807
  type: 'number',
740
808
  description: 'Source column number for quickfix evaluation (default 0 for quickfix actions).',
741
809
  },
810
+ version: {
811
+ type: 'string',
812
+ enum: ['active', 'inactive'],
813
+ description: 'Source version for syntax check (default "active"). Use "inactive" to validate pending changes.',
814
+ },
742
815
  proposalUri: {
743
816
  type: 'string',
744
817
  description: 'Quickfix proposal URI from quickfix action (required for apply_quickfix).',
@@ -752,8 +825,36 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
752
825
  type: 'string',
753
826
  description: 'Dump or trace ID (for dumps/traces actions). Omit to list, provide to get details.',
754
827
  },
828
+ detailUrl: {
829
+ type: 'string',
830
+ description: 'ADT detail URL for gateway_errors detail mode (preferred over id+errorType). Accepts absolute or /sap/bc/adt/... path.',
831
+ },
832
+ errorType: {
833
+ type: 'string',
834
+ description: 'Gateway error type for gateway_errors detail by id (for example "Frontend Error"). Required when using id without detailUrl.',
835
+ },
755
836
  user: { type: 'string', description: 'Filter dumps by SAP user (for dumps action)' },
756
- maxResults: { type: 'number', description: 'Maximum results to return (for dumps action, default 50)' },
837
+ from: {
838
+ type: 'string',
839
+ description: 'Optional lower time boundary for feed-based diagnostics actions (system_messages/gateway_errors).',
840
+ },
841
+ to: {
842
+ type: 'string',
843
+ description: 'Optional upper time boundary for feed-based diagnostics actions (system_messages/gateway_errors).',
844
+ },
845
+ maxResults: {
846
+ type: 'number',
847
+ description: 'Maximum results to return for dumps/system_messages/gateway_errors (default 50, bounded to a safe cap).',
848
+ },
849
+ sections: {
850
+ type: 'array',
851
+ items: { type: 'string' },
852
+ description: 'Dump chapter IDs to include for dumps detail mode (for example ["kap0","kap3","kap8"]). Omit to use focused defaults.',
853
+ },
854
+ includeFullText: {
855
+ type: 'boolean',
856
+ description: 'For dumps detail mode only: include full formattedText blob. Default false to reduce token usage.',
857
+ },
757
858
  analysis: {
758
859
  type: 'string',
759
860
  enum: ['hitlist', 'statements', 'dbAccesses'],
@@ -774,7 +875,7 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
774
875
  type: 'string',
775
876
  enum: ['impact', 'deps', 'usages'],
776
877
  description: 'Action:\n' +
777
- '"impact" = CDS blast-radius analysis (DDLS only). USE THIS for any question like "what breaks if I change <view>", "who consumes <I_*>", "impact analysis on <CDS>", "downstream of <view>". Returns upstream AST dependencies + downstream where-used classified into RAP buckets (projectionViews, bdefs, serviceDefinitions, serviceBindings, accessControls, metadataExtensions, abapConsumers, documentation, tables, other). ALWAYS prefer over SAPQuery against DDDDLSRC/ACMDCLSRC/DDLXSRC_SRC/SRVDSRC_SRC (those text-scans produce noise this classifier filters out). Non-DDLS input returns a guardrail error.\n' +
878
+ '"impact" = CDS blast-radius analysis (DDLS only). USE THIS for any question like "what breaks if I change <view>", "who consumes <I_*>", "impact analysis on <CDS>", "downstream of <view>". Returns upstream AST dependencies + downstream where-used classified into RAP buckets (projectionViews, bdefs, serviceDefinitions, serviceBindings, accessControls, metadataExtensions, abapConsumers, documentation, tables, other), plus additive sibling-consistency diagnostics (consistencyHints + siblingExtensionAnalysis) when related DDLS siblings show asymmetric DDLX coverage. ALWAYS prefer over SAPQuery against DDDDLSRC/ACMDCLSRC/DDLXSRC_SRC/SRVDSRC_SRC (those text-scans produce noise this classifier filters out). Non-DDLS input returns a guardrail error.\n' +
778
879
  '"deps" (default, can be omitted) = forward dependency context — "what does <object> depend on?". Returns public API contracts of dependencies.\n' +
779
880
  '"usages" = reverse dependency lookup — "who calls <object>?". Requires cache warmup (--cache-warmup). Only "name" is needed. For CDS entities prefer action="impact" instead.',
780
881
  },
@@ -814,129 +915,129 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
814
915
  type: 'boolean',
815
916
  description: 'Only for action="impact". Include indirect (transitive) downstream where-used entries. Default false.',
816
917
  },
918
+ siblingCheck: {
919
+ type: 'boolean',
920
+ description: 'Only for action="impact". Enable sibling metadata-extension consistency analysis. Default true.',
921
+ },
922
+ siblingMaxCandidates: {
923
+ type: 'number',
924
+ description: 'Only for action="impact". Maximum sibling DDLS candidates to compare. Default 4; hard cap 10.',
925
+ },
817
926
  },
818
927
  required: ['name'],
819
928
  },
820
929
  });
821
- // SAPManage — registered when not in read-only mode
822
- if (!config.readOnly) {
823
- tools.push({
824
- name: 'SAPManage',
825
- description: btp ? SAPMANAGE_DESC_BTP : SAPMANAGE_DESC_ONPREM,
826
- inputSchema: {
827
- type: 'object',
828
- properties: {
829
- action: {
830
- type: 'string',
831
- enum: [
832
- 'features',
833
- 'probe',
834
- 'cache_stats',
835
- 'create_package',
836
- 'delete_package',
837
- 'change_package',
838
- 'flp_list_catalogs',
839
- 'flp_list_groups',
840
- 'flp_list_tiles',
841
- 'flp_create_catalog',
842
- 'flp_create_group',
843
- 'flp_create_tile',
844
- 'flp_add_tile_to_group',
845
- 'flp_delete_catalog',
846
- ],
847
- description: 'Action to execute. Includes package lifecycle (create/delete/move) and FLP actions for catalogs/groups/tiles via PAGE_BUILDER_CUST OData service.',
848
- },
849
- name: {
850
- type: 'string',
851
- description: 'Package name (required for create_package and delete_package).',
852
- },
853
- description: {
854
- type: 'string',
855
- description: 'Package description (required for create_package).',
856
- },
857
- superPackage: {
858
- type: 'string',
859
- description: 'Parent package for create_package (defaults to empty root package).',
860
- },
861
- softwareComponent: {
862
- type: 'string',
863
- description: 'Software component for create_package (default: LOCAL).',
864
- },
865
- transportLayer: {
866
- type: 'string',
867
- description: 'Transport layer for create_package (optional; required by some transportable landscapes).',
868
- },
869
- packageType: {
870
- type: 'string',
871
- enum: ['development', 'structure', 'main'],
872
- description: 'Package type for create_package (default: development).',
873
- },
874
- transport: {
875
- type: 'string',
876
- description: 'Optional transport request (corrNr) for create_package, delete_package, or change_package.',
877
- },
878
- objectUri: {
879
- type: 'string',
880
- description: 'ADT URI of the object to move (e.g., /sap/bc/adt/oo/classes/zcl_my_class). If not provided, resolved automatically from objectName + objectType via search.',
881
- },
882
- objectType: {
883
- type: 'string',
884
- description: 'ADT object type (e.g., CLAS/OC, DDLS/DF, PROG/P). Required for change_package.',
885
- },
886
- objectName: {
887
- type: 'string',
888
- description: 'Object name to move (e.g., ZCL_MY_CLASS). Required for change_package.',
889
- },
890
- oldPackage: {
891
- type: 'string',
892
- description: 'Current package of the object. Required for change_package.',
893
- },
894
- newPackage: {
895
- type: 'string',
896
- description: 'Target package to move the object to. Required for change_package.',
897
- },
898
- catalogId: {
899
- type: 'string',
900
- description: 'FLP catalog identifier — accepts either full ID (X-SAP-UI2-CATALOGPAGE:MY_CAT) or domain ID (MY_CAT). Required for flp_list_tiles, flp_create_tile, flp_add_tile_to_group, flp_delete_catalog.',
901
- },
902
- groupId: {
903
- type: 'string',
904
- description: 'FLP group/page identifier (required for flp_create_group, flp_add_tile_to_group).',
905
- },
906
- title: {
907
- type: 'string',
908
- description: 'Title for FLP catalog/group creation.',
909
- },
910
- domainId: {
911
- type: 'string',
912
- description: 'Domain ID for FLP catalog creation (e.g., ZARC1_SALES).',
913
- },
914
- tileInstanceId: {
915
- type: 'string',
916
- description: 'Tile instance ID in the source catalog (required for flp_add_tile_to_group).',
917
- },
918
- tile: {
919
- type: 'object',
920
- description: 'Tile definition for flp_create_tile.',
921
- properties: {
922
- id: { type: 'string', description: 'Tile ID (client-side logical id).' },
923
- title: { type: 'string', description: 'Display title.' },
924
- icon: { type: 'string', description: 'Optional icon URI.' },
925
- semanticObject: { type: 'string', description: 'Semantic object for intent navigation.' },
926
- semanticAction: { type: 'string', description: 'Semantic action for intent navigation.' },
927
- url: { type: 'string', description: 'Optional target URL.' },
928
- subtitle: { type: 'string', description: 'Optional subtitle text.' },
929
- info: { type: 'string', description: 'Optional info text.' },
930
- },
931
- required: ['id', 'title', 'semanticObject', 'semanticAction'],
932
- },
930
+ // SAPManage — always registered; mutating actions remain safety/scope-protected.
931
+ const sapManageActions = config.allowWrites
932
+ ? [...SAPMANAGE_ACTIONS_READ, ...SAPMANAGE_ACTIONS_WRITE]
933
+ : SAPMANAGE_ACTIONS_READ;
934
+ tools.push({
935
+ name: 'SAPManage',
936
+ description: btp ? SAPMANAGE_DESC_BTP : SAPMANAGE_DESC_ONPREM,
937
+ inputSchema: {
938
+ type: 'object',
939
+ properties: {
940
+ action: {
941
+ type: 'string',
942
+ enum: sapManageActions,
943
+ description: 'Action to execute. Read actions: features, probe, cache_stats, flp_list_catalogs, flp_list_groups, flp_list_tiles. ' +
944
+ 'Mutating package/FLP actions require writable safety config and write scope in authenticated mode.',
945
+ },
946
+ name: {
947
+ type: 'string',
948
+ description: 'Package name (required for create_package and delete_package).',
949
+ },
950
+ description: {
951
+ type: 'string',
952
+ description: 'Package description (required for create_package).',
953
+ },
954
+ superPackage: {
955
+ type: 'string',
956
+ description: 'Parent package for create_package (defaults to empty root package).',
957
+ },
958
+ softwareComponent: {
959
+ type: 'string',
960
+ description: 'Software component for create_package (default: LOCAL).',
961
+ },
962
+ transportLayer: {
963
+ type: 'string',
964
+ description: 'Transport layer for create_package (optional; required by some transportable landscapes).',
965
+ },
966
+ packageType: {
967
+ type: 'string',
968
+ enum: ['development', 'structure', 'main'],
969
+ description: 'Package type for create_package (default: development).',
970
+ },
971
+ transport: {
972
+ type: 'string',
973
+ description: 'Optional transport request (corrNr) for create_package, delete_package, or change_package.',
974
+ },
975
+ objectUri: {
976
+ type: 'string',
977
+ description: 'ADT URI of the object to move (e.g., /sap/bc/adt/oo/classes/zcl_my_class). If not provided, resolved automatically from objectName + objectType via search.',
978
+ },
979
+ objectType: {
980
+ type: 'string',
981
+ description: 'ADT object type (e.g., CLAS/OC, DDLS/DF, PROG/P). Required for change_package.',
982
+ },
983
+ objectName: {
984
+ type: 'string',
985
+ description: 'Object name to move (e.g., ZCL_MY_CLASS). Required for change_package.',
986
+ },
987
+ oldPackage: {
988
+ type: 'string',
989
+ description: 'Current package of the object. Required for change_package.',
990
+ },
991
+ newPackage: {
992
+ type: 'string',
993
+ description: 'Target package to move the object to. Required for change_package.',
994
+ },
995
+ catalogId: {
996
+ type: 'string',
997
+ description: 'FLP catalog identifier accepts either full ID (X-SAP-UI2-CATALOGPAGE:MY_CAT) or domain ID (MY_CAT). Required for flp_list_tiles, flp_create_tile, flp_add_tile_to_group, flp_delete_catalog.',
998
+ },
999
+ groupId: {
1000
+ type: 'string',
1001
+ description: 'FLP group/page identifier (required for flp_create_group, flp_add_tile_to_group).',
1002
+ },
1003
+ title: {
1004
+ type: 'string',
1005
+ description: 'Title for FLP catalog/group creation.',
1006
+ },
1007
+ domainId: {
1008
+ type: 'string',
1009
+ description: 'Domain ID for FLP catalog creation (e.g., ZARC1_SALES).',
1010
+ },
1011
+ tileInstanceId: {
1012
+ type: 'string',
1013
+ description: 'Tile instance ID in the source catalog (required for flp_add_tile_to_group).',
1014
+ },
1015
+ tile: {
1016
+ type: 'object',
1017
+ description: 'Tile definition for flp_create_tile.',
1018
+ properties: {
1019
+ id: { type: 'string', description: 'Tile ID (client-side logical id).' },
1020
+ title: { type: 'string', description: 'Display title.' },
1021
+ icon: { type: 'string', description: 'Optional icon URI.' },
1022
+ semanticObject: { type: 'string', description: 'Semantic object for intent navigation.' },
1023
+ semanticAction: { type: 'string', description: 'Semantic action for intent navigation.' },
1024
+ url: { type: 'string', description: 'Optional target URL.' },
1025
+ subtitle: { type: 'string', description: 'Optional subtitle text.' },
1026
+ info: { type: 'string', description: 'Optional info text.' },
1027
+ },
1028
+ required: ['id', 'title', 'semanticObject', 'semanticAction'],
933
1029
  },
934
- required: ['action'],
935
1030
  },
936
- });
937
- }
938
- // Transport tools — registered when transports are explicitly enabled
939
- if (config.enableTransports) {
1031
+ required: ['action'],
1032
+ },
1033
+ });
1034
+ // Transport tools — always registered when the feature is available.
1035
+ // Read actions (list/get/check/history) work with read scope.
1036
+ // Write actions (create/release/delete/...) require 'transports' scope + allowTransportWrites=true.
1037
+ if (config.featureTransport !== 'off') {
1038
+ const sapTransportActions = config.allowWrites && config.allowTransportWrites
1039
+ ? [...SAPTRANSPORT_ACTIONS_READ, ...SAPTRANSPORT_ACTIONS_WRITE]
1040
+ : SAPTRANSPORT_ACTIONS_READ;
940
1041
  tools.push({
941
1042
  name: 'SAPTransport',
942
1043
  description: btp ? SAPTRANSPORT_DESC_BTP : SAPTRANSPORT_DESC_ONPREM,
@@ -945,7 +1046,7 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
945
1046
  properties: {
946
1047
  action: {
947
1048
  type: 'string',
948
- enum: ['list', 'get', 'create', 'release', 'delete', 'reassign', 'release_recursive', 'check', 'history'],
1049
+ enum: sapTransportActions,
949
1050
  description: 'list: show transports (defaults to current user, modifiable only). ' +
950
1051
  'get: fetch transport details including tasks and objects. ' +
951
1052
  'create: create a new transport request. ' +
@@ -954,7 +1055,7 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
954
1055
  'reassign: change transport owner (use recursive=true for tasks too). ' +
955
1056
  'release_recursive: release all unreleased tasks first, then the transport itself. ' +
956
1057
  'check: check if a transport is needed for a package/object (requires type, name, package). ' +
957
- 'history: list transports referencing an object (reverse lookup; requires type, name; works without --enable-transports).',
1058
+ 'history: list transports referencing an object (reverse lookup; requires type, name; works without SAP_ALLOW_TRANSPORT_WRITES).',
958
1059
  },
959
1060
  id: {
960
1061
  type: 'string',
@@ -987,6 +1088,9 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
987
1088
  }
988
1089
  // SAPGit — registered only when gCTS or abapGit backend is available
989
1090
  if (resolvedFeatures?.gcts?.available || resolvedFeatures?.abapGit?.available) {
1091
+ const sapGitActions = config.allowWrites && config.allowGitWrites
1092
+ ? [...SAPGIT_ACTIONS_READ, ...SAPGIT_ACTIONS_WRITE]
1093
+ : SAPGIT_ACTIONS_READ;
990
1094
  tools.push({
991
1095
  name: 'SAPGit',
992
1096
  description: btp ? SAPGIT_DESC_BTP : SAPGIT_DESC_ONPREM,
@@ -995,26 +1099,9 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
995
1099
  properties: {
996
1100
  action: {
997
1101
  type: 'string',
998
- enum: [
999
- 'list_repos',
1000
- 'whoami',
1001
- 'config',
1002
- 'branches',
1003
- 'external_info',
1004
- 'history',
1005
- 'objects',
1006
- 'check',
1007
- 'stage',
1008
- 'clone',
1009
- 'pull',
1010
- 'push',
1011
- 'commit',
1012
- 'switch_branch',
1013
- 'create_branch',
1014
- 'unlink',
1015
- ],
1102
+ enum: sapGitActions,
1016
1103
  description: 'Git action. Read: list_repos, whoami, config, branches, external_info, history, objects, check. ' +
1017
- 'Write (requires --enable-git): clone, pull, push, commit, stage, switch_branch, create_branch, unlink.',
1104
+ 'Write (requires SAP_ALLOW_WRITES=true and SAP_ALLOW_GIT_WRITES=true): clone, pull, push, commit, stage, switch_branch, create_branch, unlink.',
1018
1105
  },
1019
1106
  backend: {
1020
1107
  type: 'string',