arc-1 0.9.21 → 0.9.22

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 (85) hide show
  1. package/dist/adt/client.d.ts +2 -2
  2. package/dist/adt/client.d.ts.map +1 -1
  3. package/dist/adt/client.js +4 -3
  4. package/dist/adt/client.js.map +1 -1
  5. package/dist/adt/config.d.ts +7 -0
  6. package/dist/adt/config.d.ts.map +1 -1
  7. package/dist/adt/config.js.map +1 -1
  8. package/dist/adt/ddic-xml.d.ts +2 -2
  9. package/dist/adt/ddic-xml.js +3 -3
  10. package/dist/adt/ddic-xml.js.map +1 -1
  11. package/dist/adt/diagnostics.d.ts +11 -0
  12. package/dist/adt/diagnostics.d.ts.map +1 -1
  13. package/dist/adt/diagnostics.js +25 -2
  14. package/dist/adt/diagnostics.js.map +1 -1
  15. package/dist/adt/fm-signature.d.ts +1 -1
  16. package/dist/adt/fm-signature.js +1 -1
  17. package/dist/adt/http.d.ts +6 -0
  18. package/dist/adt/http.d.ts.map +1 -1
  19. package/dist/adt/http.js +10 -0
  20. package/dist/adt/http.js.map +1 -1
  21. package/dist/adt/structure-hierarchy.d.ts +41 -0
  22. package/dist/adt/structure-hierarchy.d.ts.map +1 -0
  23. package/dist/adt/structure-hierarchy.js +194 -0
  24. package/dist/adt/structure-hierarchy.js.map +1 -0
  25. package/dist/authz/policy.d.ts.map +1 -1
  26. package/dist/authz/policy.js +1 -0
  27. package/dist/authz/policy.js.map +1 -1
  28. package/dist/cli.js +3 -4
  29. package/dist/cli.js.map +1 -1
  30. package/dist/handlers/context.d.ts.map +1 -1
  31. package/dist/handlers/context.js +11 -1
  32. package/dist/handlers/context.js.map +1 -1
  33. package/dist/handlers/dispatch.js +1 -1
  34. package/dist/handlers/dispatch.js.map +1 -1
  35. package/dist/handlers/object-types.d.ts +1 -1
  36. package/dist/handlers/object-types.js +54 -54
  37. package/dist/handlers/object-types.js.map +1 -1
  38. package/dist/handlers/read.js +3 -3
  39. package/dist/handlers/read.js.map +1 -1
  40. package/dist/handlers/schemas.d.ts +7 -3
  41. package/dist/handlers/schemas.d.ts.map +1 -1
  42. package/dist/handlers/schemas.js +3 -3
  43. package/dist/handlers/schemas.js.map +1 -1
  44. package/dist/handlers/tool-registry.d.ts +2 -2
  45. package/dist/handlers/tool-registry.d.ts.map +1 -1
  46. package/dist/handlers/tool-registry.js +4 -3
  47. package/dist/handlers/tool-registry.js.map +1 -1
  48. package/dist/handlers/tools.d.ts +4 -1
  49. package/dist/handlers/tools.d.ts.map +1 -1
  50. package/dist/handlers/tools.js +178 -271
  51. package/dist/handlers/tools.js.map +1 -1
  52. package/dist/handlers/write/rap.js +2 -2
  53. package/dist/handlers/write/rap.js.map +1 -1
  54. package/dist/handlers/write-helpers.js +1 -1
  55. package/dist/handlers/write-helpers.js.map +1 -1
  56. package/dist/plugins/manifest-interpreter.js +1 -1
  57. package/dist/plugins/manifest-interpreter.js.map +1 -1
  58. package/dist/probe/catalog.js +2 -2
  59. package/dist/probe/catalog.js.map +1 -1
  60. package/dist/public/index.js +1 -1
  61. package/dist/public/index.js.map +1 -1
  62. package/dist/public/testing.js +1 -1
  63. package/dist/public/testing.js.map +1 -1
  64. package/dist/public/types.js +1 -1
  65. package/dist/public/types.js.map +1 -1
  66. package/dist/registry/tool-registry.js +1 -1
  67. package/dist/registry/tool-registry.js.map +1 -1
  68. package/dist/server/config.d.ts.map +1 -1
  69. package/dist/server/config.js +12 -0
  70. package/dist/server/config.js.map +1 -1
  71. package/dist/server/plugin-loader.js +1 -1
  72. package/dist/server/plugin-loader.js.map +1 -1
  73. package/dist/server/safe-http-client.js +1 -1
  74. package/dist/server/safe-http-client.js.map +1 -1
  75. package/dist/server/server.d.ts +22 -3
  76. package/dist/server/server.d.ts.map +1 -1
  77. package/dist/server/server.js +79 -11
  78. package/dist/server/server.js.map +1 -1
  79. package/dist/server/types.d.ts +4 -0
  80. package/dist/server/types.d.ts.map +1 -1
  81. package/dist/server/types.js +1 -0
  82. package/dist/server/types.js.map +1 -1
  83. package/dist/server/ui.js +1 -1
  84. package/dist/server/ui.js.map +1 -1
  85. package/package.json +4 -4
@@ -57,55 +57,37 @@ function isBtpMode(config) {
57
57
  // ─── SAPRead Types ──────────────────────────────────────────────────
58
58
  /** All SAPRead types available on on-premise */
59
59
  /** SAPRead types available on BTP ABAP Environment (no PROG, INCL, VIEW, TEXT_ELEMENTS, VARIANTS) */
60
- const SAPREAD_DESC_ONPREM = 'Read SAP ABAP objects. Use SAPRead when you need exact raw source, a specific method body, grep output, inactive drafts, revision history, or metadata. For "what does this object do?", object explanation, spec work, reviews, or pre-change orientation, prefer SAPContext first because it returns intent-level context before raw source. Types: PROG, CLAS, INTF, FUNC, FUGR (use expand_includes=true to get all include sources), INCL, DDLS, DCLS (CDS access controls), DDLX (CDS metadata extensions — UI annotations), BDEF, SRVD, SRVB (service bindings — returns structured binding info: OData version, publish status, service definition ref), SKTD/KTD (Knowledge Transfer Documents — Markdown documentation attached to KTD-capable ABAP objects like DDLS, BDEF, SRVD, SRVB, and packages; KTD is a friendly alias for SKTD), TABL (DDIC TABL — covers transparent tables like T000 AND DDIC structures like BAPIRET2; returns CDS-like source. ARC-1 auto-resolves the URL: tries /sap/bc/adt/ddic/tables/ first, falls back to /sap/bc/adt/ddic/structures/. Note: there is no separate STRU type — TABL is the canonical short type for both, mirroring TADIR R3TR TABL and abapGit conventions), VIEW, DOMA (DDIC domains — returns type info, value table, fixed values), DTEL (data elements — returns domain, labels, search help), TRAN (transaction codes — returns description, program, package), TABLE_CONTENTS (simple row preview — no filter or single-column filter; use TABLE_QUERY for multi-column WHERE), TABLE_QUERY (structured multi-column query on DDIC tables and CDS views via the freestyle endpoint — supports AND conditions, column selection; gated by allowDataPreview; use instead of TABLE_CONTENTS when filtering on multiple fields. Note: CDS views require SAP_BASIS 752+ — NW 7.50/7.51 rejects them with "TABLE is invalid here"), DEVC, SOBJ (BOR business objects — returns method catalog or full implementation), SYSTEM, COMPONENTS, MSAG (message classes — returns class metadata + messages array), TEXT_ELEMENTS, VARIANTS. For CLAS: omit include to get the full class source (definition + implementation combined). The include param is optional — use it only to read class-local sections: definitions (local types), implementations (local helper classes), macros, testclasses (ABAP Unit). For CLAS with method param: use method="*" to list all methods with signatures and visibility, or method="method_name" to read a single method implementation (95% fewer tokens than full source). For SOBJ: returns BOR method catalog; use method param to read a specific method implementation. BSP (deployed UI5/Fiori apps — list apps, browse files, read content; use name to browse app structure, include for subfolder or file), BSP_DEPLOY (query deployed UI5 apps via ABAP Repository OData Service — returns name, package, description). API_STATE (API release state — checks if an object is released for ABAP Cloud / S/4HANA Clean Core; returns contract states C0-C4, successor info; use objectType param for non-class objects). INACTIVE_OBJECTS (list all objects pending activation — no name param needed; use before SAPActivate batch_activate to see what needs activating). AUTH (Authorization Fields — returns check table, domain, conversion exit, org-level flags; on-prem only). FEATURE_TOGGLE (Feature Toggles — returns current toggle state per system from SAP switch framework; on-prem only). ENHO (Enhancement Implementations / BAdI — returns technology type, referenced enhancement object, and BAdI implementations with implementing classes; on-prem only). VERSIONS (list revision history of an object — returns JSON with object metadata and revisions [{id, author, timestamp, versionTitle?, transport?, uri}]; pass optional include for CLAS or group for FUNC; on-prem only and may return 404 for some DDIC types on non-S/4 backends). VERSION_SOURCE (fetch source at a specific revision URI from VERSIONS response; returns raw source text; on-prem only). ' +
61
- 'Optional grep parameter: pass a case-insensitive regex to return only matching source lines (+context, with line numbers) instead of the full objecttoken-efficient search across source-bearing types; for CLAS, matches are annotated with the owning class/method. ' +
62
- 'Optional version parameter (default "active"): set to "inactive" to read the user\'s unactivated draft, or "auto" for the developer view. Active reads include a note when an inactive draft exists.';
63
- const SAPREAD_DESC_BTP = 'Read SAP ABAP objects (BTP ABAP Environment). Use SAPRead when you need exact raw source, a specific method body, grep output, inactive drafts, or metadata. For "what does this object do?", object explanation, spec work, reviews, or pre-change orientation, prefer SAPContext first because it returns intent-level context before raw source. Types: CLAS, INTF, FUNC (released/custom only), FUGR (released/custom only), DDLS (CDS views — primary data model on BTP), DCLS (CDS access controls), DDLX (CDS metadata extensions — UI annotations for Fiori Elements), BDEF (RAP behavior definitions), SRVD (service definitions), SRVB (service bindings — returns structured binding info: OData version, publish status, service definition ref), SKTD/KTD (Knowledge Transfer Documents — Markdown documentation attached to KTD-capable ABAP objects like DDLS, BDEF, SRVD, SRVB, and packages; KTD is a friendly alias for SKTD), TABL (DDIC TABL — covers both custom transparent tables AND DDIC structures; returns CDS-like source. ARC-1 auto-resolves /tables/ vs /structures/ via fallback. Note: there is no separate STRU type — TABL is the canonical short type for both), DOMA (DDIC domains — type info, value table, fixed values), DTEL (data elements — domain, labels, search help), TABLE_CONTENTS (custom tables and released CDS only — SAP standard tables are blocked; no filter or single-column filter only), TABLE_QUERY (structured multi-column query on custom DDIC tables and released CDS views; use when filtering on multiple fields. Requires SAP_BASIS 752+ for CDS view support), DEVC, SYSTEM, COMPONENTS, MSAG (custom message classes only). For CLAS: omit include to get the full class source. The include param reads class-local sections: definitions, implementations, macros, testclasses. For CLAS with method param: use method="*" to list all methods with signatures and visibility, or method="method_name" to read a single method (95% fewer tokens). Note: PROG, INCL, VIEW, TRAN, TEXT_ELEMENTS, VARIANTS are not available on BTP — use CLAS with IF_OO_ADT_CLASSRUN for console applications, and DDLS for data models instead of classic views. VERSIONS and VERSION_SOURCE are currently on-prem only in ARC-1 and are intentionally not exposed on BTP yet. BSP (deployed UI5/Fiori apps — list apps, browse files, read content; use name to browse app structure, include for subfolder or file), BSP_DEPLOY (query deployed UI5 apps via ABAP Repository OData Service — returns name, package, description). API_STATE (API release state — checks if an object is released for ABAP Cloud / Clean Core; returns contract states C0-C4, successor info; essential for cloud development; use objectType param for non-class objects). INACTIVE_OBJECTS (list all objects pending activation — no name param needed; use before SAPActivate batch_activate to see what needs activating). ' +
64
- 'Optional grep parameter: pass a case-insensitive regex to return only matching source lines (+context, with line numbers) instead of the full object token-efficient search across source-bearing types; for CLAS, matches are annotated with the owning class/method. ' +
65
- 'Optional version parameter (default "active"): set to "inactive" to read the user\'s unactivated draft, or "auto" for the developer view. Active reads include a note when an inactive draft exists.';
60
+ const SAPREAD_DESC_ONPREM = 'Read SAP ABAP objects exact raw source, a method body, grep output, inactive drafts, revision history, or metadata. For "what does this object do?", explanations, spec work, reviews, or pre-change orientation, prefer SAPContext first (intent-level context before raw source). ' +
61
+ 'Types: PROG, CLAS, INTF, FUNC, FUGR (expand_includes=true for all include sources), INCL, DDLS, DCLS, DDLX, BDEF, SRVD, SRVB, SKTD/KTD (KTD aliases SKTD), TABL (covers both transparent tables AND DDIC structures — no separate STRU type), VIEW, DOMA, DTEL, TRAN, TABLE_CONTENTS (single-column filter), TABLE_QUERY (multi-column WHERE via the freestyle endpoint; gated by allowDataPreview; CDS views need SAP_BASIS 752+), DEVC, SOBJ (BOR method param reads one method), SYSTEM, COMPONENTS, MSAG, TEXT_ELEMENTS, VARIANTS, BSP, BSP_DEPLOY, API_STATE (contract states C0-C4; objectType for non-class), INACTIVE_OBJECTS (no name; pending-activation list), AUTH, FEATURE_TOGGLE, ENHO, VERSIONS, VERSION_SOURCE. AUTH/FEATURE_TOGGLE/ENHO/VERSIONS/VERSION_SOURCE are on-prem only. ' +
62
+ 'CLAS: to save tokens, prefer method="*" (all signatures), method="NAME" (one body, ~95% fewer tokens than the full class), or grep over reading the full source. Omit include for the full source, or include=definitions|implementations|macros|testclasses for a local section. Full per-type detail: docs_page SAPRead. ' +
63
+ 'Optional grep: case-insensitive regex returning only matching source lines (+context, line numbers); for CLAS, matches are annotated with the owning class/method. ' +
64
+ 'Optional version parameter (default "active"): "inactive" reads the user\'s draft, "auto" the developer view. Active reads note when an inactive draft exists.';
65
+ const SAPREAD_DESC_BTP = 'Read SAP ABAP objects (BTP ABAP Environment) exact raw source, a method body, grep output, inactive drafts, or metadata. For "what does this object do?", explanations, spec work, reviews, or pre-change orientation, prefer SAPContext first (intent-level context before raw source). ' +
66
+ 'Types: CLAS, INTF, FUNC (released/custom only), FUGR (released/custom only), DDLS (primary data model on BTP), DCLS, DDLX, BDEF, SRVD, SRVB, SKTD/KTD (KTD aliases SKTD), TABL (custom tables AND structures — no separate STRU type), DOMA, DTEL, TABLE_CONTENTS (custom tables + released CDS only; standard tables blocked), TABLE_QUERY (multi-column WHERE on custom tables + released CDS; needs SAP_BASIS 752+), DEVC, SYSTEM, COMPONENTS, MSAG (custom only), BSP, BSP_DEPLOY, API_STATE (contract states C0-C4; objectType for non-class), INACTIVE_OBJECTS (no name; pending-activation list). PROG/INCL/VIEW/TRAN/TEXT_ELEMENTS/VARIANTS and VERSIONS/VERSION_SOURCE are not available on BTP (use CLAS with IF_OO_ADT_CLASSRUN for console apps, DDLS for data models). ' +
67
+ 'CLAS: to save tokens, prefer method="*" (all signatures), method="NAME" (one body, ~95% fewer tokens than the full class), or grep over reading the full source. Omit include for the full source, or include=definitions|implementations|macros|testclasses for a local section. Full per-type detail: docs_page SAPRead. ' +
68
+ 'Optional grep: case-insensitive regex returning only matching source lines (+context, line numbers); for CLAS, matches are annotated with the owning class/method. ' +
69
+ 'Optional version parameter (default "active"): "inactive" reads the user\'s draft, "auto" the developer view.';
66
70
  // ─── SAPWrite Types ─────────────────────────────────────────────────
67
71
  const SAPWRITE_DESC_ONPREM = 'Create or update ABAP source code and DDIC metadata. Handles lock/modify/unlock automatically. Supports PROG, CLAS, INTF, FUNC, FUGR, INCL, DDLS, DCLS, DDLX, BDEF, SRVD, SRVB, SKTD/KTD, TABL, TABL/DT, TABL/DS, DOMA, DTEL, MSAG. ' +
68
- 'Type codes are auto-normalized and case-insensitive (e.g., "CLAS/OC" → "CLAS"). ' +
69
- 'For delete, only type and name are required (plus optional transport); other fields are ignored. ' +
70
- 'Optional fields may be omitted entirely do not send empty strings or null to "skip" a field; irrelevant ones are ignored. ' +
71
- 'For CLAS update, pass include="definitions"|"implementations"|"macros"|"testclasses" to update that local include natively; omit include to update source/main. ' +
72
- 'TABL uses source-based writes via /source/main (define table syntax), similar to DDLS/BDEF/SRVD. ' +
73
- 'TABL create: bare "TABL" or "TABL/DT" transparent table (16-char name limit); "TABL/DS" DDIC structure (30-char limit, accepts namespaces like /LEOWM/X). Update/delete/activate discover subtype via SAP search, so the slash form is optional there. ' +
74
- 'DOMA/DTEL use metadata XML writes (not /source/main): provide DDIC fields like dataType, length, fixedValues, typeKind, labels, searchHelp. ' +
75
- 'MSAG (message classes) use metadata XML writes: provide "messages" array with {number, shortText} entries. Create empty then update, or provide messages at creation. ' +
76
- 'SRVB (service bindings) use metadata XML writes: provide serviceDefinition (SRVD name), odataVersion ("V2"/"V4"), optional category (0=UI, 1=Web API). ' +
77
- 'bindingType accepts human-readable values like "ODataV4-UI" which are auto-normalized. ' +
78
- 'SKTD/KTD (Knowledge Transfer Documents, Markdown docs attached to a KTD-capable ABAP object; KTD is a friendly alias for SKTD): create requires refObjectType (parent ADT type+subtype, e.g., "DDLS/DF", "BDEF/BDO", "SRVD/SRV", "SRVB/SVB", "DEVC/K"). Do not use CLAS/OC, INTF/OI, or PROG/P; use ABAP Doc for code objects. 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="..."). ' +
79
- 'FUGR (function groups): create with package; serves as the parent container for FUNC. Delete the FUGR after deleting all its FMs. ' +
80
- 'FUNC (function modules): require "group" parameter — the parent FUGR must exist (create it first via SAPWrite type=FUGR). Pass structured `parameters` array to manage FM signatures (IMPORTING/EXPORTING/CHANGING/TABLES/EXCEPTIONS/RAISING). Example: parameters=[{kind:"importing",name:"IV_X",type:"STRING",byValue:true},{kind:"exporting",name:"EV_Y",type:"STRING",byValue:true},{kind:"raising",name:"CX_ROOT"}]. Use SAPRead(type=FUNC, includeSignature=true) to read parameters back as structured JSON. SAPGUI-style *"...IMPORTING..."* parameter comment blocks in source are stripped before PUT as defense-in-depth (SAP rejects them with FUNC_ADT028); a warning is appended in that case. ' +
81
- 'For edit_method: surgically replace a single method body in a CLAS without sending the full class source. ' +
82
- 'Provide just the new method implementation code in "source" — 95% fewer tokens than full-class updates. ' +
83
- 'For local handler classes inside a class include (RAP behavior pools, local helpers, test classes), pass the qualified specifier "lhc_project~approve_project" — ARC-1 routes the read+write to /includes/implementations automatically. ' +
84
- 'Auto-detection prefixes: lhc_*/lcl_* → implementations, ltc_* → testclasses. Override with include="definitions"|"implementations"|"macros"|"testclasses" for explicit control. ' +
85
- 'Global-interface methods like "zif_order~create" continue to use /source/main. ' +
86
- '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. ' +
87
- 'For scaffold_rap_handlers: derive missing RAP behavior handler signatures from an interface BDEF and optionally create missing lhc_* skeletons plus inject declarations and empty implementation stubs into an existing behavior pool class. ' +
88
- 'For generate_behavior_implementation: one-shot RAP behavior pool — auto-discover the bound BDEF via class metadata (rootEntityRef), scaffold every required handler (creating lhc_<alias> skeletons when missing), write under one lock, and (by default) activate. Reliable equivalent of Eclipse ADT\'s "Generate Behavior Implementation" Cmd+1 quickfix without the broken /sap/bc/adt/quickfixes/proposals/.../create_class_implementation server endpoint. ' +
89
- 'Server-driven objects (ABAP Platform 2025 / SAP_BASIS 8.16+, discovery-gated): DESD (CDS Logical External Schema), DTSC (CDS Static Cache), CSNM (CSN Model), EVTB (RAP Event Binding), EVTO (RAP Event Object), COTA (Communication Target). For these, create/update/delete operate on the generic AFF blue:blueSource object — pass the AFF JSON in "source" (e.g. {"formatVersion":"1","header":{...}}); create leaves the object inactive, so follow with SAPActivate. On pre-8.16 systems these types return a clean "requires SAP_BASIS 8.16+" error.';
72
+ 'Type codes are auto-normalized and case-insensitive (e.g., "CLAS/OC" → "CLAS"). For delete, only type and name are required (plus optional transport). ' +
73
+ 'Source objects (PROG/CLAS/INTF/DDLS/DCLS/DDLX/BDEF/SRVD/TABL/INCL) write via /source/main. CLAS update: pass include=definitions|implementations|macros|testclasses to write a local include; omit for source/main. ' +
74
+ 'TABL create: "TABL"/"TABL/DT" transparent table (16-char name); "TABL/DS" structure (30-char, namespaces OK); update/delete/activate auto-discover the subtype. ' +
75
+ 'Metadata-XML writes (not /source/main): DOMA/DTEL (dataType, length, fixedValues, typeKind, labels, searchHelp); MSAG (messages array of {number, shortText}); SRVB (serviceDefinition, odataVersion V2/V4, optional category 0=UI/1=Web API; bindingType like "ODataV4-UI" auto-normalized). ' +
76
+ 'SKTD/KTD (Markdown docs on a KTD-capable object; KTD aliases SKTD): create needs refObjectType (parent type+subtype, e.g. "DDLS/DF"); "name" MUST equal the parent name; update takes Markdown in source; then SAPActivate(type="SKTD"). ' +
77
+ 'FUNC: require "group" (parent FUGR must exist create it first); pass structured `parameters` for the signature (read back via SAPRead includeSignature=true). ' +
78
+ 'edit_method: replace one CLAS method body via source (95% fewer tokens than full-class). Local-class methods use the qualified specifier (e.g. "lhc_project~approve_project"); auto-routing: lhc_*/lcl_* implementations, ltc_* testclasses (override with include=); zif_*~* stays on /source/main. ' +
79
+ 'batch_create: create+activate multiple objects in dependency order via the "objects" array (RAP stacks TABL→DDLS→DCLS→BDEF→SRVD). scaffold_rap_handlers / generate_behavior_implementation: derive RAP behavior-pool handlers from the BDEF (the latter auto-discovers the BDEF via rootEntityRef and activates by default). ' +
80
+ 'Server-driven objects (SAP_BASIS 8.16+, discovery-gated): DESD, DTSC, CSNM, EVTB, EVTO, COTA create/update/delete with AFF JSON in "source", then SAPActivate; pre-8.16 returns a clean "requires 8.16+" error. ' +
81
+ 'Full per-type field reference: docs_page SAPWrite. ';
90
82
  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, DCLS, DDLX, BDEF, SRVD, SRVB, SKTD/KTD, TABL, TABL/DT, TABL/DS, DOMA, DTEL, MSAG. ' +
91
- 'Type codes are auto-normalized and case-insensitive (e.g., "CLAS/OC" → "CLAS"). ' +
92
- 'For delete, only type and name are required (plus optional transport); other fields are ignored. ' +
93
- 'Optional fields may be omitted entirely do not send empty strings or null to "skip" a field; irrelevant ones are ignored. ' +
94
- 'For CLAS update, pass include="definitions"|"implementations"|"macros"|"testclasses" to update that local include natively; omit include to update source/main. ' +
95
- 'TABL supports custom table source writes via /source/main (define table syntax). ' +
96
- 'DOMA/DTEL use metadata XML writes (not /source/main): provide DDIC fields like dataType, length, fixedValues, typeKind, labels, searchHelp. ' +
97
- 'MSAG (message classes) use metadata XML writes: provide "messages" array with {number, shortText} entries. ' +
98
- 'SRVB (service bindings) use metadata XML writes: provide serviceDefinition (SRVD name), odataVersion ("V2"/"V4"), optional category (0=UI, 1=Web API). ' +
99
- 'bindingType accepts human-readable values like "ODataV4-UI" which are auto-normalized. ' +
100
- 'SKTD/KTD (Knowledge Transfer Documents, Markdown docs attached to a KTD-capable ABAP object; KTD is a friendly alias for SKTD): create requires refObjectType (parent ADT type+subtype, e.g., "DDLS/DF", "BDEF/BDO", "SRVD/SRV", "SRVB/SVB", "DEVC/K"). Do not use CLAS/OC, INTF/OI, or PROG/P; use ABAP Doc for code objects. 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="..."). ' +
101
- 'Must use ABAP Cloud language version (no classic statements). Only Z*/Y* namespace allowed on BTP. ' +
102
- 'For edit_method: surgically replace a single method body in a CLAS without sending the full class source. ' +
103
- 'For local handler classes inside a class include (RAP behavior pools, local helpers, test classes), pass the qualified specifier "lhc_project~approve_project" — ARC-1 routes the read+write to /includes/implementations automatically. ' +
104
- 'Auto-detection prefixes: lhc_*/lcl_* → implementations, ltc_* → testclasses. Override with include= for explicit control. ' +
105
- 'For batch_create: create and activate multiple objects in a single call — ideal for RAP stacks (TABL → DDLS → DCLS → BDEF → SRVD). ' +
106
- 'For scaffold_rap_handlers: derive missing RAP behavior handler signatures from an interface BDEF and optionally create missing lhc_* skeletons plus inject declarations and empty implementation stubs into an existing behavior pool class. ' +
107
- 'For generate_behavior_implementation: one-shot RAP behavior pool — auto-discover the bound BDEF via class metadata (rootEntityRef), scaffold every required handler (creating lhc_<alias> skeletons when missing), write under one lock, and (by default) activate. ' +
108
- 'Server-driven objects (8.16+ / ABAP Cloud, discovery-gated): DESD, DTSC, CSNM, EVTB, EVTO, COTA — create/update/delete operate on the generic AFF blue:blueSource object (pass AFF JSON in "source"); create leaves the object inactive, so follow with SAPActivate. Pre-8.16 systems return a clean "requires SAP_BASIS 8.16+" error.';
83
+ 'Must use ABAP Cloud language version (no classic statements); only Z*/Y* namespace. Type codes are auto-normalized (e.g. "CLAS/OC" → "CLAS"). For delete, only type and name are required (plus optional transport). ' +
84
+ 'Source objects (CLAS/INTF/DDLS/DCLS/DDLX/BDEF/SRVD/TABL) write via /source/main. CLAS update: pass include=definitions|implementations|macros|testclasses for a local include; omit for source/main. ' +
85
+ 'Metadata-XML writes (not /source/main): DOMA/DTEL (dataType, length, fixedValues, typeKind, labels, searchHelp); MSAG (messages array of {number, shortText}); SRVB (serviceDefinition, odataVersion V2/V4, optional category 0=UI/1=Web API). ' +
86
+ 'SKTD/KTD (Markdown docs on a KTD-capable object; KTD aliases SKTD): create needs refObjectType (e.g. "DDLS/DF"); "name" MUST equal the parent name; update takes Markdown in source; then SAPActivate(type="SKTD"). ' +
87
+ 'edit_method: replace one CLAS method body via source. Local-class methods use the qualified specifier (e.g. "lhc_project~approve_project"); auto-routing lhc_*/lcl_* → implementations, ltc_* → testclasses (override with include=). ' +
88
+ 'batch_create: create+activate multiple objects in dependency order (RAP stacks TABL→DDLS→DCLS→BDEF→SRVD). scaffold_rap_handlers / generate_behavior_implementation: derive RAP behavior-pool handlers from the BDEF (the latter auto-discovers via rootEntityRef and activates by default). ' +
89
+ 'Server-driven objects (8.16+, discovery-gated): DESD, DTSC, CSNM, EVTB, EVTO, COTA create/update/delete with AFF JSON in "source", then SAPActivate; pre-8.16 returns a clean "requires 8.16+" error. ' +
90
+ 'Full per-type field reference: docs_page SAPWrite. ';
109
91
  // Prepended to both SAPWrite descriptions. The schema lists every optional field for every
110
92
  // object type/action, but each call uses only a small subset — GPT/OpenAI callers tend to
111
93
  // fill the rest with empty/null/placeholder values. This steers the model to a minimal first
@@ -117,103 +99,65 @@ const SAPWRITE_MINIMAL_PAYLOAD_GUIDE = 'MINIMAL PAYLOAD — send ONLY the fields
117
99
  "delete needs only {action, type, name}; DOMA/DTEL/MSAG/SRVB need {action, type, name} plus that type's own DDIC fields; FUNC also needs group. " +
118
100
  'Do NOT send `include` unless type=CLAS, and do NOT send DDIC/metadata fields (dataType, length, decimals, signExists, lowercase, typeKind, domainName, odataVersion, category, version, labels, …) on a source-object or delete call. ';
119
101
  // ─── SAPContext Types ───────────────────────────────────────────────
120
- const SAPCONTEXT_DESC_ONPREM = 'Primary tool for understanding ABAP objects before specs, reviews, explanations, or changes. Use SAPContext instead of SAPRead when the user asks what a class, interface, program, function module, or CDS view does. For action="deps" it returns intent/context first: the object KTD when available, then compressed dependency contracts. Use SAPRead later only for exact source, method bodies, grep, drafts, revisions, or metadata.\n\n' +
121
- 'Get compressed dependency context or CDS blast-radius impact for an ABAP / CDS object.\n\n' +
122
- "Decision rule pick the action based on the user's question:\n" +
123
- '- "What breaks if I change <CDS view>?" / "Who consumes <I_*>?" / "Impact analysis on <DDLS>" / "Blast radius" → action="impact"\n' +
124
- '- "What does <object> do?" / "Explain <object>" / "Prepare a spec/change/review for <object>" / "Understand dependencies before editing <object>" / "What does X depend on?" → action="deps" (default)\n' +
125
- '- "Find all callers of <object>" (cache-warmup required) → action="usages"\n\n' +
126
- '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' +
127
- 'action="deps" (default): Returns the target object KTD first when one exists, then 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 an object before editing. Instead of N separate SAPRead calls returning full source (~200 lines each), returns ONE response with KTD context plus compressed contracts (~15-30 lines each). Typical compression: 7-30x fewer tokens.\n\n' +
128
- 'What deps extracts per dependency:\n' +
129
- '- Classes: CLASS DEFINITION with PUBLIC SECTION only (methods, types, constants). PROTECTED, PRIVATE and IMPLEMENTATION stripped.\n' +
130
- '- Interfaces: Full interface definition (interfaces are already public contracts).\n' +
131
- '- Function modules: FUNCTION signature block only (IMPORTING/EXPORTING parameters).\n' +
132
- '- CDS views (DDLS): All data sources (tables, other CDS views), association targets, and compositions. ' +
133
- "Each dependency's full source is included (table definitions, CDS DDL). Essential for CDS unit test generation — " +
134
- 'provides the dependency graph and field catalogs needed for cl_cds_test_environment doubles.\n\n' +
135
- 'Filtering (deps): SAP standard objects (CL_ABAP_*, IF_ABAP_*, CX_SY_*) are excluded. Custom objects (Z*, Y*) are prioritized.\n\n' +
136
- 'Use SAPContext BEFORE writing code that modifies or extends existing objects. ' +
137
- 'Use SAPRead after SAPContext when you need exact source or method-level detail.\n\n' +
138
- 'For non-CDS reverse-lookup, use SAPNavigate(action="references"). For CDS reverse-lookup, ALWAYS prefer action="impact" over SAPNavigate it returns the same where-used data pre-classified into RAP buckets.';
139
- const SAPCONTEXT_DESC_BTP = 'Primary tool for understanding ABAP objects before specs, reviews, explanations, or changes (BTP ABAP Environment). Use SAPContext instead of SAPRead when the user asks what a class, interface, or CDS view does. For action="deps" it returns intent/context first: the object KTD when available, then compressed dependency contracts. Use SAPRead later only for exact source, method bodies, grep, drafts, or metadata.\n\n' +
140
- 'Get compressed dependency context or CDS blast-radius impact for an ABAP / CDS object (BTP ABAP Environment).\n\n' +
141
- "Decision rule — pick the action based on the user's question:\n" +
142
- '- "What breaks if I change <CDS view>?" / "Who consumes <I_*>?" / "Impact analysis on <DDLS>" / "Blast radius" → action="impact"\n' +
143
- '- "What does <object> do?" / "Explain <object>" / "Prepare a spec/change/review for <object>" / "Understand dependencies before editing <object>" / "What does X depend on?" → action="deps" (default)\n\n' +
144
- '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' +
145
- 'action="deps" (default): Returns the target object KTD first when one exists, then 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' +
146
- 'What deps extracts per dependency:\n' +
147
- '- Classes: CLASS DEFINITION with PUBLIC SECTION only (methods, types, constants).\n' +
148
- '- Interfaces: Full interface definition (interfaces are already public contracts).\n' +
149
- '- CDS views (DDLS): All data sources (tables, other CDS views), association targets, and compositions. ' +
150
- "Each dependency's full source is included. Essential for CDS unit test generation.\n\n" +
151
- 'On BTP: released SAP objects (CL_ABAP_*, IF_ABAP_*) are included since they form the primary development API surface. ' +
152
- 'Custom objects (Z*, Y*) are also included.\n\n' +
153
- 'Use SAPContext BEFORE writing code that modifies or extends existing objects. Use SAPRead after SAPContext when you need exact source or method-level detail.';
102
+ const SAPCONTEXT_DESC_ONPREM = 'Primary tool for understanding ABAP/CDS objects before specs, reviews, explanations, or changes use instead of SAPRead when the user asks what an object does. Returns intent first (the object KTD when available) then compressed dependency contracts. Use SAPRead after SAPContext for exact source/method bodies/grep/drafts.\n\n' +
103
+ "Decision rule pick the action from the user's question:\n" +
104
+ '- "What breaks if I change <CDS>?" / "Who consumes <I_*>?" / "Blast radius" → action="impact" (DDLS only).\n' +
105
+ '- "Which includes/appends extend <TABL>?" action="structure", type="TABL".\n' +
106
+ '- "What does <object> do?" / "Explain" / "deps before editing" → action="deps" (default).\n' +
107
+ '- "Find all callers of <object>" (needs cache warmup) → action="usages".\n\n' +
108
+ 'impact (CDS blast-radius): upstream AST deps + downstream where-used, classified into RAP buckets (projectionViews, bdefs, serviceDefinitions, serviceBindings, accessControls, metadataExtensions, abapConsumers, documentation, tables, other) + sibling-consistency hints. Use this instead of text-scanning DDDDLSRC/ACMDCLSRC with SAPQuery (it filters the noise). Optional includeIndirect, siblingCheck, siblingMaxCandidates.\n' +
109
+ 'deps (default): target KTD + the public API contracts of its dependencies (not full source) one compact response vs N SAPRead calls (7-30x fewer tokens); SAP standard objects filtered out. For CDS, includes dependency DDL/field catalogs for cl_cds_test_environment.\n' +
110
+ 'structure (TABL only): the DDIC include/append tree.\n\n' +
111
+ 'Use SAPContext BEFORE editing existing objects. For non-CDS reverse-lookup use SAPNavigate(references); for CDS prefer impact. Full detail: docs_page SAPContext.';
112
+ const SAPCONTEXT_DESC_BTP = 'Primary tool for understanding ABAP/CDS objects before specs, reviews, explanations, or changes (BTP ABAP Environment) use instead of SAPRead when the user asks what an object does. Returns intent first (object KTD when available) then compressed dependency contracts.\n\n' +
113
+ "Decision rule pick the action from the user's question:\n" +
114
+ '- "What breaks if I change <CDS>?" / "Who consumes <I_*>?" / "Blast radius" action="impact" (DDLS only).\n' +
115
+ '- "Which includes/appends extend <TABL>?" action="structure", type="TABL".\n' +
116
+ '- "What does <object> do?" / "Explain" / "deps before editing" → action="deps" (default).\n\n' +
117
+ 'impact (CDS blast-radius): upstream AST deps + downstream where-used classified into RAP buckets (projectionViews, bdefs, serviceDefinitions, serviceBindings, accessControls, metadataExtensions, abapConsumers, documentation, tables, other) + sibling-consistency hints; filters the noise that text-scanning with SAPQuery produces. Optional includeIndirect, siblingCheck, siblingMaxCandidates.\n' +
118
+ 'deps (default): target KTD + the public API contracts of its dependencies (not full source). On BTP, released SAP objects (CL_ABAP_*/IF_ABAP_*) and custom Z/Y are included.\n' +
119
+ 'structure (TABL only): the DDIC include/append tree.\n\n' +
120
+ 'Use SAPContext BEFORE editing existing objects; SAPRead afterwards for exact source. Full detail: docs_page SAPContext.';
154
121
  // ─── SAPQuery ───────────────────────────────────────────────────────
155
- const SAPQUERY_DESC_ONPREM = 'Execute ABAP SQL queries against SAP tables. Returns structured data with column names and rows. ' +
156
- 'Powerful for reverse-engineering: query metadata tables like DD02L (table catalog), DD03L (field catalog), ' +
157
- 'SWOTLV (BOR method implementations), TADIR (object directory), TFDIR (function modules). ' +
158
- 'If a table is not found, similar table names will be suggested automatically. ' +
159
- '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). ARC-1 automatically chunks simple long literal IN lists; if parsing still fails, simplify to one SELECT and split multi-table logic into staged single-table queries (SAP Note 3605050).\n\n' +
160
- '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).';
122
+ const SAPQUERY_DESC_ONPREM = 'Execute ABAP SQL queries against SAP tables. Returns columns + rows. Good for reverse-engineering metadata tables (DD02L, DD03L, TADIR, TFDIR, SWOTLV). Unknown tables get name suggestions. ' +
123
+ 'Uses the ADT freestyle SQL endpoint; its parser can reject valid-looking statements on some releases ARC-1 automatically chunks simple long literal IN lists; if parsing still fails, use one SELECT and stage multi-table logic (SAP Note 3605050). ' +
124
+ 'To find CDS consumers do NOT text-scan DDDDLSRC/ACMDCLSRC/DDLXSRC_SRC — use SAPContext(action="impact", type="DDLS") (where-used index, filtered buckets).';
161
125
  const SAPQUERY_DESC_BTP = 'Execute ABAP SQL queries (BTP ABAP Environment). Returns structured data with column names and rows. ' +
162
126
  'IMPORTANT: On BTP, only custom Z/Y tables and released CDS entities can be queried. ' +
163
127
  'SAP standard tables (MARA, VBAK, DD02L, DD03L, TADIR, etc.) are blocked. ' +
164
128
  'Use released CDS views instead: I_LANGUAGE, I_COUNTRY, I_CURRENCY, I_UnitOfMeasure, etc. ' +
165
129
  'If a table is not found, similar table names will be suggested automatically.';
166
130
  // ─── SAPSearch ──────────────────────────────────────────────────────
167
- const SAPSEARCH_DESC_ONPREM = 'Search for ABAP objects, exact object-directory entries, or source code. Three modes:\n' +
168
- '1. Object search (default): Search by name pattern with wildcards (* for any characters). Returns object type, name, package, description, and ADT URI. Use this to find classes, programs, function modules, tables, etc.\n' +
169
- '2. TADIR lookup (searchType="tadir_lookup"): Exact cross-package object lookup for one or more names via ADT repository quick search. Use this before create/reset workflows instead of long SAPQuery TADIR IN-lists.\n' +
170
- '3. Source code search (searchType="source_code"): Full-text search within ABAP source code across the system. Use this to find all objects containing a specific string (e.g., a method call, variable name, or class reference). Requires SAP_BASIS >= 7.51.\n\n' +
171
- "Tips: BOR business objects appear as SOBJ type in results. The uri field from results can be used directly with SAPNavigate for references. The objectType field from results can be passed directly to SAPRead/SAPWrite/SAPActivate (ARC-1 auto-normalizes slash suffixes like DDLS/DF, CLAS/OC, PROG/P).\n\nNote: Searches object names only (classes, tables, CDS views, etc.) — field/column names are not searchable here. To find fields by name, use SAPRead(type='DDLS', include='elements') for CDS views or SAPQuery against DD03L.";
131
+ const SAPSEARCH_DESC_ONPREM = 'Search for ABAP objects, exact object-directory entries, or source code. Modes:\n' +
132
+ '1. Object search (default): name pattern with wildcards (*); returns type, name, package, description, ADT URI.\n' +
133
+ '2. TADIR lookup (searchType="tadir_lookup"): exact cross-package lookup of one or more names (prefer over long SAPQuery TADIR IN-lists).\n' +
134
+ '3. Source code search (searchType="source_code"): full-text search across source (SAP_BASIS 7.51).\n' +
135
+ "Tips: BOR objects appear as SOBJ; the uri field feeds SAPNavigate, objectType feeds SAPRead/SAPWrite/SAPActivate. Searches object NAMES only for field names use SAPRead(type='DDLS', include='elements') or SAPQuery on DD03L.";
172
136
  const SAPSEARCH_DESC_BTP = 'Search for ABAP objects, exact object-directory entries, or source code (BTP ABAP Environment). Three modes:\n' +
173
137
  '1. Object search (default): Search by name pattern with wildcards. Returns released SAP objects and custom Z/Y objects. Classic programs, includes, and DDIC views are not searchable on BTP.\n' +
174
138
  '2. TADIR lookup (searchType="tadir_lookup"): Exact object lookup for one or more names via ADT repository quick search.\n' +
175
139
  '3. Source code search (searchType="source_code"): Full-text search within ABAP source code.\n\n' +
176
140
  "Tips: On BTP, focus on classes (CL_*), interfaces (IF_*), CDS views (I_*), and custom Z/Y objects.\n\nNote: Searches object names only (classes, CDS views, etc.) — field/column names are not searchable here. To find fields by name, use SAPRead(type='DDLS', include='elements') for CDS views.";
177
141
  // ─── SAPTransport ───────────────────────────────────────────────────
178
- const SAPTRANSPORT_DESC_ONPREM = 'Manage CTS transport requests (SE09/SE10 equivalent). ' +
179
- 'Actions: list (defaults to current user, modifiable transports both Workbench and Customizing), ' +
180
- 'get (details with tasks and objects), create (always a Workbench (K) request — the package/target sets the transport target & layer, not the request category; optional explicit target. Customizing (W) and Transport-of-Copies (T) requests are not created here), ' +
181
- 'release, delete, remove_object (remove an object, keep the request), reassign (change owner), release_recursive (release tasks first, then parent), ' +
182
- 'check (check if a package requires a transport — provide type, name, package), ' +
183
- 'history (find transports referencing an object provide type, name; read-only, works without SAP_ALLOW_TRANSPORT_WRITES). ' +
184
- 'Transport IDs look like A4HK900123. Status: D=modifiable, R=released.';
185
- const SAPTRANSPORT_DESC_BTP = 'Manage transport requests (BTP ABAP Environment, SE09/SE10 equivalent). ' +
186
- 'Actions: list (defaults to current user, modifiable transports both Workbench and Customizing), ' +
187
- 'get (details with tasks and objects), create (always a Workbench (K) request the package/target sets the transport target & layer, not the request category; optional explicit target. Customizing (W) and Transport-of-Copies (T) requests are not created here), ' +
188
- 'release, delete, remove_object (remove an object, keep the request), reassign (change owner), release_recursive (release tasks first, then parent), ' +
189
- 'check (check if a package requires a transport — provide type, name, package), ' +
190
- 'history (find transports referencing an object — provide type, name; read-only, works without SAP_ALLOW_TRANSPORT_WRITES). ' +
191
- 'On BTP, transport release triggers a gCTS push to the software component Git repository. ' +
192
- 'Import into target systems is done via the Manage Software Components app or Cloud Transport Management Service (cTMS), not via this tool.';
142
+ const SAPTRANSPORT_DESC_ONPREM = 'Manage CTS transport requests (SE09/SE10). Actions: list (current user, modifiable), get (tasks + objects), ' +
143
+ 'create (always a Workbench (K) request the package/target sets target & layer, not the request category; optional explicit target), ' +
144
+ 'release, delete, remove_object (keep the request), reassign (change owner), release_recursive (tasks then parent), ' +
145
+ 'check (does a package need a transport type, name, package), history (transports referencing an object — type, name; read-only, no write scope needed). ' +
146
+ 'IDs look like A4HK900123. Status: D=modifiable, R=released.';
147
+ const SAPTRANSPORT_DESC_BTP = 'Manage transport requests (BTP ABAP Environment, SE09/SE10). Actions: list (current user, modifiable), get (tasks + objects), ' +
148
+ 'create (always a Workbench (K) request — the package/target sets target & layer; optional explicit target), ' +
149
+ 'release, delete, remove_object (keep the request), reassign (change owner), release_recursive (tasks then parent), ' +
150
+ 'check (does a package need a transport — type, name, package), history (transports referencing an object type, name; read-only). ' +
151
+ 'On BTP, release triggers a gCTS push to the software-component Git repo; import is via Manage Software Components / cTMS, not this tool.';
193
152
  // ─── SAPManage ──────────────────────────────────────────────────────
194
- const SAPMANAGE_DESC_ONPREM = 'Probe and report SAP system capabilities. Use this BEFORE attempting operations that depend on optional ' +
195
- 'features (abapGit, RAP/CDS, AMDP, HANA, UI5/Fiori, CTS transports, FLP customization). Also handles package (DEVC) lifecycle operations.\n\n' +
153
+ const SAPMANAGE_DESC_ONPREM = 'Probe and report SAP system capabilities. Use BEFORE operations that depend on optional features ' +
154
+ '(abapGit, RAP/CDS, AMDP, HANA, UI5/Fiori, CTS transports, FLP). Also handles package (DEVC) lifecycle.\n\n' +
196
155
  'Actions:\n' +
197
- '- "features": Get cached feature status from last probe (fast, no SAP round-trip). ' +
198
- 'Returns which features are available, their mode (auto/on/off), and when they were last probed.\n' +
199
- '- "probe": Re-probe the SAP system now (runs feature probes, auth checks, and ADT discovery refresh). ' +
200
- 'Use this on first use or if you suspect feature availability has changed.\n' +
201
- '- "cache_stats": Show object cache health and warmup state.\n' +
202
- '- "flp_list_catalogs": List FLP business catalogs.\n' +
203
- '- "flp_list_groups": List FLP groups.\n' +
204
- '- "flp_list_tiles": List tiles in a catalog (requires "catalogId").\n' +
205
- '- "create_package": Create a package (DEVC) via ADT packages API.\n' +
206
- '- "delete_package": Delete an existing package.\n' +
207
- '- "flp_create_catalog": Create a business catalog (requires "domainId", "title").\n' +
208
- '- "flp_create_group": Create a group (requires "groupId", "title").\n' +
209
- '- "flp_create_tile": Create a tile in a catalog (requires "catalogId", "tile").\n' +
210
- '- "flp_add_tile_to_group": Add a catalog tile to a group (requires "groupId", "catalogId", "tileInstanceId").\n' +
211
- '- "flp_delete_catalog": Delete a business catalog (requires "catalogId").\n' +
212
- '- "set_api_state": Release (or revoke) an object\'s API release contract for ABAP Cloud / Clean Core ' +
213
- '(requires "objectUri", or "name" + "objectType"; "apiState" defaults to RELEASED, "contract" defaults to C1 — pass C0 for SRVD, C3 for classic views). The write counterpart of SAPRead(type="API_STATE").\n\n' +
214
- 'Returns JSON with features, each having: id, available (bool), mode, message, and probedAt timestamp. ' +
215
- 'Also returns systemType ("btp" or "onprem") for understanding available capabilities. ' +
216
- '"available: false" means do NOT attempt operations that depend on it.';
156
+ '- "features": cached feature status (fast, no round-trip; id, available, mode, probedAt). "probe": re-probe now (feature probes + auth + discovery refresh). "cache_stats": object cache health.\n' +
157
+ '- "create_package" / "delete_package" / "change_package": DEVC lifecycle via ADT packages API.\n' +
158
+ '- FLP read: flp_list_catalogs, flp_list_groups, flp_list_tiles (catalogId). FLP write: flp_create_catalog, flp_create_group, flp_create_tile, flp_add_tile_to_group, flp_delete_catalog.\n' +
159
+ '- "set_api_state": release/revoke an object\'s API release contract (objectUri, or name+objectType; apiState defaults RELEASED, contract defaults C1 — C0 for SRVD, C3 for classic views). Write counterpart of SAPRead(type="API_STATE").\n\n' +
160
+ 'Returns features + systemType ("onprem"/"btp"); "available: false" means do NOT attempt dependent operations.';
217
161
  const SAPMANAGE_DESC_BTP = 'Probe and report SAP system capabilities (BTP ABAP Environment). ' +
218
162
  'Returns feature status and system type. Also handles package (DEVC) lifecycle operations.\n\n' +
219
163
  'Actions:\n' +
@@ -342,8 +286,8 @@ function buildSAPSearchTool(btp, textSearchAvailable) {
342
286
  };
343
287
  }
344
288
  // ─── GPT/OpenAI strict-mode nullable helper (issue #360) ────────────
345
- /** Add `null` to a property's `type` (string ["string","null"]). Per OpenAI's Structured
346
- * Outputs guide, null goes in `type` ONLY never added to `enum`. */
289
+ /** Add `null` to a property's `type` (string -> ["string","null"]). Per OpenAI's Structured
290
+ * Outputs guide, null goes in `type` only, never into `enum`. */
347
291
  function makeNullableType(def) {
348
292
  const d = { ...def };
349
293
  const t = d.type;
@@ -357,17 +301,15 @@ function makeNullableType(def) {
357
301
  return d;
358
302
  }
359
303
  /**
360
- * Recursively make every NON-required property of a JSON-schema object nullable.
304
+ * Recursively make every non-required property of a JSON-schema object nullable.
361
305
  *
362
- * GPT/OpenAI strict mode (the default for the Responses API) marks every property required;
363
- * a non-nullable optional field then leaves the model no way to signal "unused" for an enum
364
- * it is FORCED to emit one of the values (the hallucinated typeKind=domain / odataVersion=V4
365
- * seen on unrelated writes, issue #360). The OpenAI-documented fix is a union with null
366
- * (`"type": ["string","null"]`) so the model can emit null = "not used"; ARC-1's runtime
367
- * `stripLlmEmptyValues` then drops the nulls before Zod. Each object node's OWN `required`
368
- * array decides what stays non-nullable, so it is correct at every nesting level (top level
369
- * keeps `action`; batch `objects[]` items keep `type`/`name`; leaf arrays keep their keys).
370
- * Pure — returns a copy, does not mutate the input.
306
+ * This exists only for explicit OpenAI/Azure strict-mode compatibility (#360), where a strict
307
+ * function schema can force every optional field to be present and enum optionals then get
308
+ * fabricated values. Several MCP clients reject `type: ["x","null"]` unions, so the default
309
+ * visible schema stays plain for broad client compatibility (#520).
310
+ *
311
+ * Pure returns a copy and does not mutate the input. Each object node's own `required` array
312
+ * decides what stays non-nullable, so top-level `action` and batch-item `type`/`name` remain plain.
371
313
  */
372
314
  function makeOptionalPropertiesNullable(node) {
373
315
  if (Array.isArray(node))
@@ -393,7 +335,7 @@ function makeOptionalPropertiesNullable(node) {
393
335
  return result;
394
336
  }
395
337
  // ─── Main Tool Definitions ──────────────────────────────────────────
396
- export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures) {
338
+ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures, options = {}) {
397
339
  // Hyperfocused mode: single universal SAP tool (~200 tokens)
398
340
  if (config.toolMode === 'hyperfocused') {
399
341
  return [getHyperfocusedToolDefinition(config, resolvedFeatures)];
@@ -534,12 +476,12 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
534
476
  const pkgList = config.allowedPackages.join(', ');
535
477
  sapWriteDesc += ` Write access is restricted to packages: ${pkgList}.`;
536
478
  }
537
- tools.push({
479
+ const sapWriteTool = {
538
480
  name: 'SAPWrite',
539
481
  description: sapWriteDesc,
540
- // Make optional fields nullable so GPT/OpenAI strict-mode callers can emit null for
541
- // unused fields instead of fabricating values; the runtime strip removes the nulls (#360).
542
- inputSchema: makeOptionalPropertiesNullable({
482
+ // Keep visible schemas on widely supported JSON Schema primitives. Runtime argument
483
+ // normalization still strips null-valued optionals from strict clients before Zod (#360).
484
+ inputSchema: {
543
485
  type: 'object',
544
486
  properties: {
545
487
  action: {
@@ -558,7 +500,7 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
558
500
  'scaffold_rap_handlers',
559
501
  'generate_behavior_implementation',
560
502
  ],
561
- description: "Write action. edit_method: surgically replace a single method body (requires type=CLAS, method, and source params). Class-section surgery actions (issue #303, type=CLAS only) target a global class without re-sending /source/main: edit_class_definition without include= replaces the global DEFINITION block (caller passes the new block via source; ARC-1 refuses if the diff would leave the class non-activatable e.g. added concrete method without IMPL stub — and suggests add_method/delete_method instead); edit_class_definition with include= whole-replaces that class-local include (CCDEF/CCIMP/macros/testclasses) and auto-creates the include first if missing; add_method atomically inserts a METHODS clause AND empty METHOD/ENDMETHOD stub (caller passes the METHODS clause via method, optional visibility=public|protected|private, optional abstract=true to skip the stub); edit_method_signature replaces one method's METHODS clause via the source param (no IMPL changes); delete_method removes both the DEFINITION clause and METHOD/ENDMETHOD body atomically — WARNING: this is destructive (it discards the method body). To change a method's visibility/section, use change_method_visibility (NOT delete_method + add_method, which would discard the body). change_method_visibility moves a method between PUBLIC/PROTECTED/PRIVATE sections (requires method=NAME and visibility=target); it touches only the DEFINITION, so the IMPLEMENTATION body is preserved. add_method/edit_method_signature/delete_method/change_method_visibility operate on the global class /source/main only. 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. generate_behavior_implementation: one-shot RAP behavior pool auto-discover the bound BDEF via class rootEntityRef, scaffold every required handler (creating lhc_<alias> skeletons when missing), write under one lock, and optionally activate. The reliable equivalent of Eclipse ADT's \"Generate Behavior Implementation\" Cmd+1 quickfix.",
503
+ description: 'Write action. create/update/delete: standard object writes. edit_method: replace one method body (type=CLAS, method, source). Class-section surgery (type=CLAS only): edit_class_definition without include= replaces the global DEFINITION block (refuses a diff that would leave the class non-activatable, e.g. a concrete method with no IMPL stub); with include= it whole-replaces a class-local include (CCDEF/CCIMP/macros/testclasses), auto-creating it. add_method inserts a METHODS clause + empty stub (visibility, abstract=true skips the stub); edit_method_signature replaces one METHODS clause (no IMPL change); delete_method removes the clause AND body — WARNING: destructive, discards the method body (to re-section a method use change_method_visibility, NOT delete+add); change_method_visibility moves a method between PUBLIC/PROTECTED/PRIVATE, preserves the body. add_method/edit_method_signature/delete_method/change_method_visibility act on /source/main only. batch_create: create+activate multiple objects (objects array). scaffold_rap_handlers / generate_behavior_implementation: derive RAP behavior-pool handlers from the BDEF (the latter the equivalent of Eclipse\'s "Generate Behavior Implementation").',
562
504
  },
563
505
  type: {
564
506
  type: 'string',
@@ -573,16 +515,16 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
573
515
  },
574
516
  source: {
575
517
  type: 'string',
576
- description: 'ABAP source code. For create/update: the full source body. For edit_method: the new method body. For edit_class_definition without include=: ONLY the new global CLASS DEFINITION ENDCLASS. block (~10–80 lines for a typical class — no IMPLEMENTATION block needed). For edit_class_definition with include=: the FULL replacement body of that local include; for include="testclasses" this usually means local CLASS ltc_* DEFINITION plus CLASS ltc_* IMPLEMENTATION. For edit_method_signature: ONLY the new METHODS clause for one method (~1–5 lines). For add_method/delete_method/change_method_visibility: not used — pass the new method clause, method name, or target section via `method`/`visibility` instead.',
518
+ description: 'ABAP source code. create/update: full source body. edit_method: the new method body. edit_class_definition without include=: only the new global CLASS…DEFINITION…ENDCLASS block (no IMPLEMENTATION); with include=: the full replacement body of that include. edit_method_signature: only the new METHODS clause. Not used by add_method/delete_method/change_method_visibility (use `method`/`visibility`).',
577
519
  },
578
520
  include: {
579
521
  type: 'string',
580
522
  enum: CLASS_WRITE_INCLUDES,
581
- description: 'CLAS-ONLY. Do NOT send this field unless type=CLAS AND action is one of update / edit_method / edit_class_definition. OMIT it entirely for every other object type (PROG, INTF, INCL, FUNC, FUGR, DDLS, DCLS, DDLX, BDEF, SRVD, SRVB, TABL, DOMA, DTEL, MSAG) and for delete / batch_create / add_method / edit_method_signature / delete_method / change_method_visibility (those operate on the global class /source/main). When it does apply: target a class-local include instead of /source/main — definitions (CCDEF), implementations (CCIMP), macros, testclasses. For edit_method, ARC-1 auto-detects the include from the method specifier (lhc_*/lcl_* → implementations, ltc_* → testclasses), so you usually need not pass it; use update or edit_class_definition with include=testclasses to create a new local test class. Whole-include writes (update and edit_class_definition with include=) auto-create a missing include first, including fresh testclasses/CCAU. Include writes create an inactive draft; read with SAPRead version="inactive" before activation. NOTE: edit_class_definition with include= skips the symmetry refuse-policy — cross-include validation is not performed; rely on SAPActivate to catch breaks.',
523
+ description: 'CLAS-ONLY. Do NOT send unless type=CLAS AND action is update / edit_method / edit_class_definition. OMIT it entirely for every other type and for delete / batch_create / add_method / edit_method_signature / delete_method / change_method_visibility (those use /source/main). Targets a class-local include: definitions (CCDEF), implementations (CCIMP), macros, testclasses. edit_method auto-detects it from the method specifier (lhc_*/lcl_* → implementations, ltc_* → testclasses), so you rarely pass it; use include=testclasses to create a new local test class. Whole-include writes auto-create a missing include and produce an inactive draft (read with SAPRead version="inactive" before activation).',
582
524
  },
583
525
  method: {
584
526
  type: 'string',
585
- description: 'For edit_method/edit_method_signature: method NAME (e.g., "get_name", "zif_order~process", "lhc_project~approve_project"). For delete_method and change_method_visibility: the method NAME. For add_method: the full METHODS clause as ABAP source (e.g. "METHODS greet IMPORTING who TYPE string RETURNING VALUE(r) TYPE string."). edit_method auto-detects CCIMP from local-class prefix (lhc_*/lcl_* → implementations, ltc_* → testclasses); same auto-detection applies to the class-section surgery actions. When two local classes in the same CCIMP share a bare method name, the qualified <localclass>~<method> form is required to disambiguate.',
527
+ description: 'edit_method/edit_method_signature/delete_method/change_method_visibility: the method NAME (e.g. "get_name", "zif_order~process", "lhc_project~approve_project"). add_method: the full METHODS clause as ABAP source. Local-class methods auto-route by prefix (lhc_*/lcl_* → implementations, ltc_* → testclasses); use the qualified <localclass>~<method> form when a bare name is ambiguous.',
586
528
  },
587
529
  visibility: {
588
530
  type: 'string',
@@ -595,11 +537,11 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
595
537
  },
596
538
  bdefName: {
597
539
  type: 'string',
598
- 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. For generate_behavior_implementation: optional override; default discovery reads the class metadata's rootEntityRef to locate the BDEF automatically.",
540
+ description: 'For scaffold_rap_handlers: interface BDEF name whose actions/determinations/validations/authorizations define the required handlers (e.g. ZI_TRAVELREQ). For generate_behavior_implementation: optional override (default discovery reads the class rootEntityRef).',
599
541
  },
600
542
  autoApply: {
601
543
  type: 'boolean',
602
- 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. (Not used by generate_behavior_implementation, which always applies; use dryRun=true there to preview.)',
544
+ description: 'For scaffold_rap_handlers: true inserts missing METHODS signatures + empty stubs and writes the class under one lock; false (default) returns a required-vs-missing report without modifying (preview, then re-run with autoApply=true). Not used by generate_behavior_implementation (use dryRun to preview there).',
603
545
  },
604
546
  targetAlias: {
605
547
  type: 'string',
@@ -607,11 +549,11 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
607
549
  },
608
550
  activate: {
609
551
  type: 'boolean',
610
- description: 'For generate_behavior_implementation: when true (default), runs SAPActivate on the class after writing. When false, only the source is written. Activation failures matching the well-known "Local classes of CL_ABAP_BEHAVIOR_HANDLER…" stale-active coupling do not throw — they return activation.success=false with a guided recovery hint so the source remains usable.',
552
+ description: 'For generate_behavior_implementation: true (default) activates the class after writing; false writes source only. The known "Local classes of CL_ABAP_BEHAVIOR_HANDLER…" stale-active activation failure does not throw — it returns activation.success=false with a recovery hint.',
611
553
  },
612
554
  activateAtEnd: {
613
555
  type: 'boolean',
614
- description: 'For action="batch_create" only. Default false: per-object inline activation (each object is created → source written → activated, in order). When true: ARC-1 writes inactive drafts for every object then issues a single terminal activateBatch SAP\'s activator sees the whole graph and resolves cross-references between siblings (e.g. composition-linked DDLS where the parent references a not-yet-active child). Use this for interdependent RAP stacks (TABL DDLS DCLS BDEF SRVD). Has no effect on other actions. Partial-failure semantics: a write-phase failure still breaks the loop; the terminal activateBatch only runs over the already-written subset.',
556
+ description: 'For batch_create only. false (default): per-object inline activation in order. true: write all inactive drafts then one terminal activateBatch so SAP resolves cross-references between siblings use for interdependent RAP stacks (TABL→DDLS→DCLS→BDEF→SRVD). A write-phase failure still breaks the loop; the terminal activate runs over the already-written subset.',
615
557
  },
616
558
  dryRun: {
617
559
  type: 'boolean',
@@ -693,7 +635,7 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
693
635
  },
694
636
  parameters: {
695
637
  type: 'array',
696
- description: 'FUNC: structured signature parameters. ARC-1 builds the IMPORTING/EXPORTING/CHANGING/TABLES/EXCEPTIONS/RAISING clause from this array and splices it into the FM source body. Example: [{kind: "importing", name: "IV_INPUT", type: "STRING", byValue: true, optional: true, default: "\'X\'"}, {kind: "exporting", name: "EV_OUTPUT", type: "STRING", byValue: true}, {kind: "raising", name: "CX_ROOT"}]. When omitted, the user-supplied source is PUT verbatim (backward compatible).',
638
+ description: 'FUNC: structured signature parameters. ARC-1 builds the IMPORTING/EXPORTING/CHANGING/TABLES/EXCEPTIONS/RAISING clause and splices it into the FM body. When omitted, the supplied source is PUT verbatim.',
697
639
  items: {
698
640
  type: 'object',
699
641
  properties: {
@@ -723,7 +665,7 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
723
665
  serviceDefinition: { type: 'string', description: 'SRVB: service definition name (SRVD) to bind to' },
724
666
  bindingType: {
725
667
  type: 'string',
726
- description: 'SRVB: binding type — accepts human-readable values like "ODataV4-UI", "OData V2 - Web API", "ODATA_V4" which are auto-normalized to SAP ADT values (type=ODATA, correct odataVersion + category)',
668
+ description: 'SRVB: binding type — human-readable values like "ODataV4-UI", "OData V2 - Web API" are auto-normalized (sets odataVersion + category).',
727
669
  },
728
670
  odataVersion: {
729
671
  type: 'string',
@@ -738,19 +680,19 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
738
680
  version: { type: 'string', description: 'SRVB: service version number (default: 0001)' },
739
681
  lintBeforeWrite: {
740
682
  type: 'boolean',
741
- 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.',
683
+ description: 'Override server lint-before-write for this call (false skips it). Lint covers PROG/CLAS/INTF/FUNC and DDLS; other types rely on RAP preflight.',
742
684
  },
743
685
  preflightBeforeWrite: {
744
686
  type: 'boolean',
745
- 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).',
687
+ description: 'Enable/disable deterministic RAP preflight checks (default true) TABL/BDEF/DDLX static rules (curr/quan semantics, invalid BDEF enums, DDLX scope on 7.5x).',
746
688
  },
747
689
  checkBeforeWrite: {
748
690
  type: 'boolean',
749
- 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.',
691
+ description: 'Override server check-before-write (default off). When true, runs a SAP syntax check and appends diagnostics to the response — the write is NOT blocked. Off by default (adds a round-trip; intermediate refactor writes legitimately trip transient dependency errors). Activation remains the definitive check.',
750
692
  },
751
693
  refObjectType: {
752
694
  type: 'string',
753
- description: 'SKTD/KTD create: ADT type+subtype of the parent object the KTD documents (e.g., "DDLS/DF", "BDEF/BDO", "SRVD/SRV", "SRVB/SVB", "DEVC/K"). Do not use CLAS/OC, INTF/OI, or PROG/P; use ABAP Doc for code objects. Required for SKTD/KTD create.',
695
+ description: 'SKTD/KTD create (required): ADT type+subtype of the documented parent (e.g. "DDLS/DF", "BDEF/BDO", "SRVD/SRV", "DEVC/K"). Not CLAS/INTF/PROG (use ABAP Doc for code).',
754
696
  },
755
697
  refObjectName: {
756
698
  type: 'string',
@@ -781,92 +723,69 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
781
723
  type: 'string',
782
724
  description: 'Object-specific transport request. Overrides top-level transport for this item.',
783
725
  },
784
- dataType: { type: 'string', description: 'DOMA/DTEL: ABAP data type' },
785
- rowType: {
786
- type: 'string',
787
- description: 'TTYP: row type (built-in ABAP type or DDIC structure/type name)',
788
- },
789
- rowTypeKind: { type: 'string', enum: ['builtin', 'structure'], description: 'TTYP: row-type mode' },
790
- length: { type: 'number', description: 'DOMA/DTEL: data type length' },
791
- decimals: { type: 'number', description: 'DOMA/DTEL: decimal places' },
792
- outputLength: { type: 'number', description: 'DOMA: output length' },
793
- conversionExit: { type: 'string', description: 'DOMA: conversion exit' },
794
- signExists: { type: 'boolean', description: 'DOMA: signed values allowed' },
795
- lowercase: { type: 'boolean', description: 'DOMA: lowercase allowed' },
726
+ // DDIC metadata fields (DOMA/DTEL/TTYP/MSAG/SRVB) mirror the top-level SAPWrite
727
+ // params 1:1 — descriptions omitted here to keep the tools/list payload small (#520).
728
+ dataType: { type: 'string' },
729
+ rowType: { type: 'string' },
730
+ rowTypeKind: { type: 'string', enum: ['builtin', 'structure'] },
731
+ length: { type: 'number' },
732
+ decimals: { type: 'number' },
733
+ outputLength: { type: 'number' },
734
+ conversionExit: { type: 'string' },
735
+ signExists: { type: 'boolean' },
736
+ lowercase: { type: 'boolean' },
796
737
  fixedValues: {
797
738
  type: 'array',
798
- description: 'DOMA: fixed value ranges',
799
739
  items: {
800
740
  type: 'object',
801
- properties: {
802
- low: { type: 'string' },
803
- high: { type: 'string' },
804
- description: { type: 'string' },
805
- },
741
+ properties: { low: { type: 'string' }, high: { type: 'string' }, description: { type: 'string' } },
806
742
  required: ['low'],
807
743
  },
808
744
  },
809
- valueTable: { type: 'string', description: 'DOMA: value table' },
810
- typeKind: { type: 'string', enum: ['domain', 'predefinedAbapType'], description: 'DTEL: type mode' },
811
- typeName: { type: 'string', description: 'DTEL: domain/type name reference' },
812
- domainName: { type: 'string', description: 'DTEL: alias for typeName' },
813
- shortLabel: { type: 'string', description: 'DTEL: short field label' },
814
- mediumLabel: { type: 'string', description: 'DTEL: medium field label' },
815
- longLabel: { type: 'string', description: 'DTEL: long field label' },
816
- headingLabel: { type: 'string', description: 'DTEL: heading field label' },
817
- searchHelp: { type: 'string', description: 'DTEL: search help' },
818
- searchHelpParameter: { type: 'string', description: 'DTEL: search help parameter' },
819
- setGetParameter: { type: 'string', description: 'DTEL: SET/GET parameter ID' },
820
- defaultComponentName: { type: 'string', description: 'DTEL: default component name' },
821
- changeDocument: { type: 'boolean', description: 'DTEL: change document flag' },
745
+ valueTable: { type: 'string' },
746
+ typeKind: { type: 'string', enum: ['domain', 'predefinedAbapType'] },
747
+ typeName: { type: 'string' },
748
+ domainName: { type: 'string' },
749
+ shortLabel: { type: 'string' },
750
+ mediumLabel: { type: 'string' },
751
+ longLabel: { type: 'string' },
752
+ headingLabel: { type: 'string' },
753
+ searchHelp: { type: 'string' },
754
+ searchHelpParameter: { type: 'string' },
755
+ setGetParameter: { type: 'string' },
756
+ defaultComponentName: { type: 'string' },
757
+ changeDocument: { type: 'boolean' },
822
758
  messages: {
823
759
  type: 'array',
824
- description: 'MSAG: message entries',
825
760
  items: {
826
761
  type: 'object',
827
- properties: {
828
- number: { type: 'string', description: 'Message number (e.g., "001")' },
829
- shortText: { type: 'string', description: 'Message short text' },
830
- },
762
+ properties: { number: { type: 'string' }, shortText: { type: 'string' } },
831
763
  required: ['number', 'shortText'],
832
764
  },
833
765
  },
834
- serviceDefinition: { type: 'string', description: 'SRVB: service definition (SRVD)' },
835
- bindingType: {
836
- type: 'string',
837
- description: 'SRVB: binding type accepts human-readable values like "ODataV4-UI" (auto-normalized)',
838
- },
839
- odataVersion: {
840
- type: 'string',
841
- enum: ['V2', 'V4'],
842
- description: 'SRVB: OData protocol version (default: V2)',
843
- },
844
- category: {
845
- type: 'string',
846
- enum: ['0', '1'],
847
- description: 'SRVB: binding category (0=UI, 1=Web API)',
848
- },
849
- version: { type: 'string', description: 'SRVB: service version number (default 0001)' },
766
+ serviceDefinition: { type: 'string' },
767
+ bindingType: { type: 'string' },
768
+ odataVersion: { type: 'string', enum: ['V2', 'V4'] },
769
+ category: { type: 'string', enum: ['0', '1'] },
770
+ version: { type: 'string' },
850
771
  },
851
772
  required: ['type', 'name'],
852
773
  },
853
- description: 'For batch_create: ordered list of objects to create and activate. Each object needs type, name, and source (if applicable). ' +
854
- 'Objects are created and activated in array order — put dependencies first (e.g., TABL before DDLS, BDEF after DDLS). ' +
855
- 'Each item may include package and transport; item-level values override top-level package/transport. ' +
856
- 'Example: [{type:"TABL",name:"ZTRAVEL",source:"..."},{type:"DDLS",name:"ZI_TRAVEL",source:"..."},{type:"BDEF",name:"ZI_TRAVEL",source:"..."},{type:"SRVD",name:"ZSD_TRAVEL",source:"..."}]',
774
+ description: 'For batch_create: ordered list of objects to create+activate (each needs type, name, and source if applicable). Created in array order — dependencies first (TABL before DDLS, BDEF after DDLS). Item-level package/transport override the top-level. Use activateAtEnd=true for interdependent stacks.',
857
775
  },
858
776
  },
859
777
  required: ['action'],
860
- }),
861
- });
778
+ },
779
+ };
780
+ if (options.nullableOptionals) {
781
+ sapWriteTool.inputSchema = makeOptionalPropertiesNullable(sapWriteTool.inputSchema);
782
+ }
783
+ tools.push(sapWriteTool);
862
784
  tools.push({
863
785
  name: 'SAPActivate',
864
- description: 'Activate (publish) ABAP objects. Supports single object or batch activation.\n' +
865
- 'Type codes are auto-normalized and case-insensitive (e.g., "CLAS/OC" or "clas" map to CLAS).\n' +
866
- 'ALWAYS prefer batch activation when activating 2+ objects — pass "objects" array with {type, name} entries. ' +
867
- 'Batch activation is more efficient (one SAP round-trip) and works for ANY combination of objects, not just dependent ones. ' +
868
- 'It is required for RAP stacks where DDLS, BDEF, SRVD depend on each other, but equally useful for unrelated objects like multiple DTELs or DOMAs.\n' +
869
- 'For publish_srvb/unpublish_srvb: publish or unpublish an OData service binding (SRVB) — makes the OData service available for consumption.',
786
+ description: 'Activate (publish) ABAP objects, single or batch. Type codes auto-normalized (e.g. "CLAS/OC" → CLAS). ' +
787
+ 'ALWAYS prefer batch activation for 2+ objects pass an "objects" array of {type, name}: one round-trip, works for any mix (required for interdependent RAP stacks, useful for unrelated objects too). ' +
788
+ 'publish_srvb/unpublish_srvb: publish or unpublish an OData service binding (SRVB).',
870
789
  inputSchema: {
871
790
  type: 'object',
872
791
  properties: {
@@ -883,14 +802,11 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
883
802
  service_type: {
884
803
  type: 'string',
885
804
  enum: ['odatav2', 'odatav4'],
886
- description: 'OData service type for publish/unpublish endpoint routing. ' +
887
- 'Auto-detected from SRVB metadata when omitted. Only needed if auto-detection fails.',
805
+ description: 'OData service type for publish/unpublish routing. Auto-detected from SRVB metadata when omitted.',
888
806
  },
889
807
  preaudit: {
890
808
  type: 'boolean',
891
- description: 'Request pre-activation audit from SAP (default: true). ' +
892
- 'When true, SAP checks for issues before activating and returns warnings/errors. ' +
893
- 'Set to false to skip pre-audit for faster activation when confident the code is correct.',
809
+ description: 'Request pre-activation audit (default true) — SAP returns warnings/errors before activating. false skips it for speed.',
894
810
  },
895
811
  objects: {
896
812
  type: 'array',
@@ -902,8 +818,7 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
902
818
  },
903
819
  required: ['type', 'name'],
904
820
  },
905
- description: 'Batch activation: array of objects to activate in one call. Use whenever activating 2+ objects. ' +
906
- 'Works for any mix of types — e.g., [{type:"DOMA",name:"Z_DOM"},{type:"DTEL",name:"Z_DEL"}] or RAP stacks like [{type:"DDLS",name:"ZI_TRAVEL"},{type:"BDEF",name:"ZI_TRAVEL"},{type:"SRVD",name:"ZSD_TRAVEL"}].',
821
+ description: 'Batch activation: array of {type, name} to activate in one call. Use whenever activating 2+ objects (any mix of types).',
907
822
  },
908
823
  },
909
824
  },
@@ -912,8 +827,8 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
912
827
  tools.push({
913
828
  name: 'SAPNavigate',
914
829
  description: btp
915
- ? 'Navigate code (BTP ABAP Environment): find definitions, references (where-used), code completion, and class hierarchy. Use for "go to definition", "where is this used?", "what does this class inherit?", and auto-complete. For references: uses the full scope-based Where-Used API returning detailed results with line numbers, snippets, and package info. Optional objectType filter narrows results to a specific ADT type in slash format (e.g., CLAS/OC, PROG/P). Type+name params are auto-normalized (e.g., type="clas" works). On BTP, navigation scope is limited to released SAP objects and custom Z/Y objects.\n\nFor CDS entities (DDLS), prefer SAPContext(action="impact") — it returns the same where-used data pre-classified into RAP buckets (projection views, BDEFs, SRVDs, access controls, etc.), which is more useful than the flat reference list returned here.'
916
- : 'Navigate code: find definitions, references (where-used), code completion, and class hierarchy. Use for "go to definition", "where is this used?", "what does this class inherit?", and auto-complete. For references: uses the full scope-based Where-Used API returning detailed results with line numbers, snippets, and package info. Optional objectType filter narrows results to a specific ADT type in slash format (e.g., CLAS/OC, PROG/P). Type+name params are auto-normalized (e.g., type="clas" works). For hierarchy: returns superclass, implemented interfaces, and direct subclasses via SEOMETAREL. You can use type+name instead of uri (e.g., type="CLAS", name="ZCL_ORDER") for a where-used list without needing the full ADT URI.\n\nFor CDS entities (DDLS), prefer SAPContext(action="impact") — it returns the same where-used data pre-classified into RAP buckets (projection views, BDEFs, SRVDs, access controls, metadata extensions, documentation, ABAP consumers), which answers "what breaks if I change this view" directly without manual bucketing.',
830
+ ? 'Navigate code (BTP ABAP Environment): definitions, references (where-used), completion, class hierarchy. references uses the scope-based Where-Used API (line numbers, snippets, package); optional objectType filters by ADT slash type (e.g. CLAS/OC). type+name auto-normalized. Scope = released SAP + custom Z/Y. For CDS (DDLS), prefer SAPContext(action="impact") — the same where-used pre-classified into RAP buckets.'
831
+ : 'Navigate code: definitions, references (where-used), completion, class hierarchy. references uses the scope-based Where-Used API (line numbers, snippets, package); optional objectType filters by ADT slash type (e.g. CLAS/OC, PROG/P); pass type+name instead of uri. hierarchy returns superclass + interfaces + direct subclasses. For CDS (DDLS), prefer SAPContext(action="impact") — the same where-used pre-classified into RAP buckets, answering "what breaks if I change this view".',
917
832
  inputSchema: {
918
833
  type: 'object',
919
834
  properties: {
@@ -959,16 +874,13 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
959
874
  }
960
875
  tools.push({
961
876
  name: 'SAPLint',
962
- description: 'Run local abaplint rules on ABAP and CDS source code. System-aware: auto-selects cloud or on-prem rules based on detected system type.\n\n' +
963
- 'Actions:\n' +
964
- '- "lint": Check source for issues. Returns errors and warnings. Works for ABAP (PROG, CLAS, INTF, FUNC) and CDS views (DDLS) — catches syntax errors, naming conventions, field order, legacy view patterns.\n' +
965
- '- "lint_and_fix": Lint + auto-fix all fixable issues (keyword case, obsolete statements, etc.). Returns fixed source.\n' +
966
- '- "list_rules": List all available rules with current config. No source needed.\n' +
967
- '- "format": Pretty-print ABAP source via SAP\'s ADT formatter (uses the SAP system\'s global formatter settings). Requires source. Returns the formatted source.\n' +
968
- '- "get_formatter_settings": Read the SAP system\'s global PrettyPrinter settings (indentation, keyword style). No params.\n' +
969
- '- "set_formatter_settings": Update the SAP system\'s global PrettyPrinter settings. Requires indentation (bool) and/or style (keywordUpper|keywordLower|keywordAuto|none). Blocked in read-only mode.\n\n' +
970
- 'For server-side checks (ATC, syntax check, unit tests), use SAPDiagnose instead.\n' +
971
- 'Note: lint/lint_and_fix/list_rules run locally; format/*_formatter_settings call the SAP system.',
877
+ description: 'Run local abaplint rules on ABAP/CDS source (auto-selects cloud or on-prem rules by system type). Actions:\n' +
878
+ '- "lint": check source (errors+warnings) for ABAP (PROG/CLAS/INTF/FUNC) and CDS (DDLS).\n' +
879
+ '- "lint_and_fix": lint + auto-fix fixable issues (keyword case, obsolete statements); returns fixed source.\n' +
880
+ '- "list_rules": list rules + current config (no source).\n' +
881
+ '- "format": pretty-print via SAP\'s ADT formatter (needs source).\n' +
882
+ '- "get_formatter_settings" / "set_formatter_settings": read/update the system\'s global PrettyPrinter (indentation bool, style keywordUpper|keywordLower|keywordAuto|none; set is blocked read-only).\n' +
883
+ 'lint/lint_and_fix/list_rules run locally; format/*_formatter_settings call SAP. For ATC/syntax/unit tests use SAPDiagnose.',
972
884
  inputSchema: {
973
885
  type: 'object',
974
886
  properties: {
@@ -1000,28 +912,23 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
1000
912
  },
1001
913
  }, {
1002
914
  name: 'SAPDiagnose',
1003
- description: 'Run diagnostics on ABAP objects and analyze runtime errors.\n\n' +
1004
- 'Actions:\n' +
1005
- '- "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' +
1006
- '- "unittest": Run ABAP unit tests. Requires name + type.\n' +
1007
- '- "atc": Run ATC code quality checks. Requires name + type. Optional: variant.\n' +
1008
- '- "cds_testcases": Get SAP-suggested ABAP Unit test cases for a CDS entity (CDS Test Double Framework). Requires name (the CDS entity / DDLS source name; no type needed). Returns one test-method suggestion per testable semantic (whole view, calculated fields, CAST/JOIN/CASE) to scaffold a cl_cds_test_environment unit test. Read-only; SAP_BASIS 8.16+ (ABAP Platform 2025 / S/4HANA 2025) only.\n' +
1009
- '- "object_state": Compare active and inactive source versions. Requires name + type. For CLAS, also compares main, definitions, implementations, macros, and testclasses includes (up to 10 parallel reads per class; sequence calls when sweeping many classes). Returns ETags, byte lengths, hashes, and divergence flags.\n' +
1010
- '- "quickfix": Get SAP quick fix proposals for a specific source position. Requires name + type + source + line. Optional: column, sourceUri for exact ADT include/source targets.\n' +
1011
- '- "apply_quickfix": Apply one quick fix proposal and return text deltas (does not write source). Requires name + type + source + line + proposalUri + proposalUserContent. Optional: column, sourceUri, proposalAffectedObjects. proposalUserContent may be an empty string; pass it through exactly from quickfix.\n' +
1012
- '- "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' +
1013
- '- "traces": List or analyze ABAP profiler traces. Without id: lists recorded trace files. With id + analysis: returns trace analysis (hitlist = hot spots, statements = call tree, dbAccesses = database access statistics).\n' +
1014
- '- "trace_start": ARM an ABAP profiler trace so the NEXT matching execution is recorded — for debugging a slow OData/Gateway call or report. Defaults: trace the next HTTP/URL request by the connected user with SQL tracing on. Then reproduce the slow action and read it via action="traces" with the returned id (analysis="dbAccesses" shows which tables/joins dominate). Optional: traceUser, processType (any/http/dialog/batch/rfc; default http), objectType (default = the valid type for the process type, e.g. url for http), maxExecutions (default 1), expiresHours (default 24), sqlTrace (default true), aggregate (default true), description. Write scope (mutates server state).\n' +
1015
- '- "trace_requests": List armed (not-yet-consumed) trace requests for a user (default the connected user) — to confirm a request is armed or find a stale one to cancel.\n' +
1016
- '- "trace_cancel": Cancel an armed trace request by id (from trace_start or trace_requests). Write scope.\n\n' +
1017
- '- "system_messages": List SM02 system messages via ADT feed (filter by user, maxResults, from, to).\n' +
1018
- '- "gateway_errors": List SAP Gateway error log entries (/IWFND/ERROR_LOG, on-prem). For detail mode provide detailUrl (preferred) or id+errorType.\n' +
1019
- '- "odata_perf": Diagnose WHY a Fiori/OData request is slow. Requires url (the host-relative OData path from the app\'s Network tab). ARC-1 GETs it with ?sap-statistics=true and a wall-clock timer, then returns the server-side timing split (gwtotal, gwapp, gwappdb=DB time, gwfw=framework, icfauth=auth) plus a verdict routing you to the dominant cost (DB vs ABAP/SADL vs framework vs auth). Read-only GET; gated like data preview.\n' +
1020
- '- "cds_sql": Show the native SQL a CDS view compiles to (ADT "Show SQL Create Statement"). Requires name (the CDS DDL source / DDLS, e.g. "I_CURRENCY"). Returns the CREATE VIEW statement(s) so you can see the joins/scans behind a slow entity. Read-only; may be unavailable on older releases (e.g. NW 7.50).\n' +
1021
- '- "sql_trace_state": Read the current ST05 trace state (SQL/buffer/enqueue/RFC/HTTP/… on-off per app server + filters). Read-only.\n' +
1022
- '- "set_sql_trace_state": Arm or disarm the ST05 SQL trace. Requires sqlOn (true=arm, false=disarm); optional user filters the trace to one SAP user. Workflow: arm → reproduce the slow request → sql_trace_directory for the record link. Needs SAP_ALLOW_WRITES (mutates server trace state).\n' +
1023
- '- "sql_trace_directory": Return where the recorded SQL statements are read — SAP answers with the TMC "SQL Trace Analysis" deep-link (there is no ADT SQL-record API; open the URL in a browser, needs /sap/bc/stmc active). Read-only.\n\n' +
1024
- '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.',
915
+ description: 'Run diagnostics on ABAP objects and analyze runtime errors. Actions:\n' +
916
+ '- "syntax": syntax-check (name+type; optional version; optional source = pre-write dry-run, nothing written).\n' +
917
+ '- "unittest": run ABAP Unit tests (name+type).\n' +
918
+ '- "atc": run ATC checks (name+type; optional variant).\n' +
919
+ '- "cds_testcases": SAP-suggested ABAP Unit test cases for a CDS entity (name; read-only; SAP_BASIS 8.16+).\n' +
920
+ '- "object_state": compare active and inactive source versions without fetching both (name+type; CLAS compares all includes). Returns ETags, hashes, divergence flags.\n' +
921
+ '- "quickfix": get quick-fix proposals at a position (name+type+source+line; optional column, sourceUri).\n' +
922
+ '- "apply_quickfix": apply one proposal, return text deltas, no write (name+type+source+line+proposalUri+proposalUserContent; pass proposalUserContent through exactly, may be empty).\n' +
923
+ '- "dumps": list/read ST22 short dumps (no id = list; id = read; includeFullText, sections).\n' +
924
+ '- "traces": list/analyze profiler traces (id+analysis: hitlist=hot spots, statements=call tree, dbAccesses=DB stats).\n' +
925
+ '- "trace_start": arm a profiler trace for the NEXT matching execution, then reproduce and read via "traces" (write scope; defaults: next HTTP request, SQL on; optional traceUser/processType/maxExecutions/expiresHours/sqlTrace/…).\n' +
926
+ '- "trace_requests": list armed trace requests. "trace_cancel": cancel one by id (write scope).\n' +
927
+ '- "system_messages": list SM02 messages. "gateway_errors": list /IWFND/ERROR_LOG (on-prem; detailUrl or id+errorType for detail).\n' +
928
+ '- "odata_perf": diagnose why an OData call is slow (url = host-relative path from the Network tab); returns the sap-statistics timing split (DB/ABAP/framework/auth) + a verdict. Read-only; needs allowDataPreview.\n' +
929
+ '- "cds_sql": show the native SQL a CDS view compiles to (name; read-only; may be absent on old releases).\n' +
930
+ '- "sql_trace_state" / "set_sql_trace_state" (sqlOn; needs SAP_ALLOW_WRITES) / "sql_trace_directory": ST05 SQL-trace control.\n' +
931
+ 'Quickfix workflow: syntax/ATC quickfix apply_quickfix write via SAPWrite. Full action reference: docs_page SAPDiagnose.',
1025
932
  inputSchema: {
1026
933
  type: 'object',
1027
934
  properties: {
@@ -1056,7 +963,7 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
1056
963
  },
1057
964
  url: {
1058
965
  type: 'string',
1059
- description: 'For action="odata_perf": the host-relative OData path to probe, copied from the Fiori app\'s Network tab (e.g. "/sap/opu/odata4/sap/.../Entity?$filter=..." or "/sap/opu/odata/sap/<SRV>/<EntitySet>?$top=20"). Must be a path on the SAP system ARC-1 connects to — absolute URLs are rejected.',
966
+ description: 'For odata_perf: the host-relative OData path to probe, from the Fiori app\'s Network tab (e.g. "/sap/opu/odata4/sap/.../Entity?$filter=…"). Must be a path on the connected system — absolute URLs are rejected.',
1060
967
  },
1061
968
  type: {
1062
969
  type: 'string',
@@ -1201,17 +1108,17 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
1201
1108
  properties: {
1202
1109
  action: {
1203
1110
  type: 'string',
1204
- enum: ['impact', 'deps', 'usages'],
1111
+ enum: ['impact', 'deps', 'usages', 'structure'],
1205
1112
  description: 'Action:\n' +
1206
1113
  '"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' +
1207
1114
  '"deps" (default, can be omitted) = object understanding / forward dependency context — "what does <object> do?" or "what does <object> depend on?". Returns the object KTD when available plus public API contracts of dependencies.\n' +
1208
- '"usages" = reverse dependency lookup — "who calls <object>?". Requires cache warmup (--cache-warmup). Only "name" is needed. For CDS entities prefer action="impact" instead.',
1115
+ '"usages" = reverse dependency lookup — "who calls <object>?". Requires cache warmup (--cache-warmup). Only "name" is needed. For CDS entities prefer action="impact" instead.\n' +
1116
+ '"structure" = TABL includes/appends.',
1209
1117
  },
1210
1118
  type: {
1211
1119
  type: 'string',
1212
1120
  enum: btp ? SAPCONTEXT_TYPES_BTP : SAPCONTEXT_TYPES_ONPREM,
1213
- description: 'Object type. Required for action="deps" and action="usages". ' +
1214
- 'Optional for action="impact" — defaults to DDLS (the only supported type for impact).',
1121
+ description: 'Object type. Optional for action="impact" (defaults to DDLS); required otherwise.',
1215
1122
  },
1216
1123
  name: {
1217
1124
  type: 'string',
@@ -1348,11 +1255,11 @@ export function getToolDefinitions(config, textSearchAvailable, resolvedFeatures
1348
1255
  },
1349
1256
  title: {
1350
1257
  type: 'string',
1351
- description: 'Title for FLP catalog/group creation.',
1258
+ description: 'Title — required for flp_create_catalog and flp_create_group.',
1352
1259
  },
1353
1260
  domainId: {
1354
1261
  type: 'string',
1355
- description: 'Domain ID for FLP catalog creation (e.g., ZARC1_SALES).',
1262
+ description: 'Domain ID required for flp_create_catalog (e.g., ZARC1_SALES).',
1356
1263
  },
1357
1264
  tileInstanceId: {
1358
1265
  type: 'string',