arc-1 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +2 -1
  2. package/dist/adt/client.d.ts +6 -0
  3. package/dist/adt/client.d.ts.map +1 -1
  4. package/dist/adt/client.js +12 -0
  5. package/dist/adt/client.js.map +1 -1
  6. package/dist/adt/codeintel.js +1 -1
  7. package/dist/adt/codeintel.js.map +1 -1
  8. package/dist/adt/features.d.ts +29 -1
  9. package/dist/adt/features.d.ts.map +1 -1
  10. package/dist/adt/features.js +114 -2
  11. package/dist/adt/features.js.map +1 -1
  12. package/dist/adt/http.d.ts +24 -1
  13. package/dist/adt/http.d.ts.map +1 -1
  14. package/dist/adt/http.js +87 -28
  15. package/dist/adt/http.js.map +1 -1
  16. package/dist/adt/oauth.d.ts +19 -2
  17. package/dist/adt/oauth.d.ts.map +1 -1
  18. package/dist/adt/oauth.js +78 -28
  19. package/dist/adt/oauth.js.map +1 -1
  20. package/dist/adt/safety.d.ts +15 -0
  21. package/dist/adt/safety.d.ts.map +1 -1
  22. package/dist/adt/safety.js +50 -0
  23. package/dist/adt/safety.js.map +1 -1
  24. package/dist/adt/types.d.ts +14 -0
  25. package/dist/adt/types.d.ts.map +1 -1
  26. package/dist/handlers/hyperfocused.d.ts +1 -0
  27. package/dist/handlers/hyperfocused.d.ts.map +1 -1
  28. package/dist/handlers/hyperfocused.js +6 -5
  29. package/dist/handlers/hyperfocused.js.map +1 -1
  30. package/dist/handlers/intent.d.ts +17 -1
  31. package/dist/handlers/intent.d.ts.map +1 -1
  32. package/dist/handlers/intent.js +250 -25
  33. package/dist/handlers/intent.js.map +1 -1
  34. package/dist/handlers/schemas.d.ts +255 -0
  35. package/dist/handlers/schemas.d.ts.map +1 -0
  36. package/dist/handlers/schemas.js +232 -0
  37. package/dist/handlers/schemas.js.map +1 -0
  38. package/dist/handlers/tools.d.ts +1 -1
  39. package/dist/handlers/tools.d.ts.map +1 -1
  40. package/dist/handlers/tools.js +64 -32
  41. package/dist/handlers/tools.js.map +1 -1
  42. package/dist/handlers/zod-errors.d.ts +20 -0
  43. package/dist/handlers/zod-errors.d.ts.map +1 -0
  44. package/dist/handlers/zod-errors.js +43 -0
  45. package/dist/handlers/zod-errors.js.map +1 -0
  46. package/dist/server/config.d.ts +26 -0
  47. package/dist/server/config.d.ts.map +1 -1
  48. package/dist/server/config.js +162 -5
  49. package/dist/server/config.js.map +1 -1
  50. package/dist/server/http.d.ts +8 -0
  51. package/dist/server/http.d.ts.map +1 -1
  52. package/dist/server/http.js +134 -71
  53. package/dist/server/http.js.map +1 -1
  54. package/dist/server/server.d.ts +13 -2
  55. package/dist/server/server.d.ts.map +1 -1
  56. package/dist/server/server.js +82 -8
  57. package/dist/server/server.js.map +1 -1
  58. package/dist/server/types.d.ts +8 -0
  59. package/dist/server/types.d.ts.map +1 -1
  60. package/dist/server/types.js +1 -0
  61. package/dist/server/types.js.map +1 -1
  62. package/dist/server/xsuaa.d.ts +11 -1
  63. package/dist/server/xsuaa.d.ts.map +1 -1
  64. package/dist/server/xsuaa.js +127 -9
  65. package/dist/server/xsuaa.js.map +1 -1
  66. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"hyperfocused.js","sourceRoot":"","sources":["../../src/handlers/hyperfocused.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hyperfocused.js","sourceRoot":"","sources":["../../src/handlers/hyperfocused.ts"],"names":[],"mappings":"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"}
@@ -34,6 +34,12 @@ export interface ToolResult {
34
34
  * A user with `write` scope but `readOnly=true` in config still can't write.
35
35
  */
36
36
  export declare const TOOL_SCOPES: Record<string, string>;
37
+ /**
38
+ * Check if authInfo has the required scope, respecting implied scopes:
39
+ * - `write` implies `read`
40
+ * - `sql` implies `data`
41
+ */
42
+ export declare function hasRequiredScope(authInfo: AuthInfo, requiredScope: string): boolean;
37
43
  /**
38
44
  * Handle an MCP tool call.
39
45
  *
@@ -42,9 +48,19 @@ export declare const TOOL_SCOPES: Record<string, string>;
42
48
  * all tools are allowed (backward compatibility).
43
49
  * @param server - MCP Server instance for elicitation support.
44
50
  */
45
- export declare function handleToolCall(client: AdtClient, config: ServerConfig, toolName: string, args: Record<string, unknown>, authInfo?: AuthInfo, _server?: Server, cachingLayer?: CachingLayer): Promise<ToolResult>;
51
+ export declare function handleToolCall(client: AdtClient, config: ServerConfig, toolName: string, args: Record<string, unknown>, authInfo?: AuthInfo, _server?: Server, cachingLayer?: CachingLayer, isPerUserClient?: boolean): Promise<ToolResult>;
52
+ /**
53
+ * Build the type-specific XML body for ADT object creation.
54
+ *
55
+ * SAP ADT requires each object type to have its own root XML element.
56
+ * Using a generic body (e.g. adtcore:objectReferences) returns 400:
57
+ * "System expected the element '{http://www.sap.com/adt/programs/programs}abapProgram'"
58
+ */
59
+ export declare function buildCreateXml(type: string, name: string, pkg: string, description: string): string;
46
60
  /** Reset cached features (for testing) */
47
61
  export declare function resetCachedFeatures(): void;
48
62
  /** Set cached features directly (for testing BTP mode, etc.) */
49
63
  export declare function setCachedFeatures(features: ResolvedFeatures | undefined): void;
64
+ /** Get cached features (for tool definition adaptation) */
65
+ export declare function getCachedFeatures(): ResolvedFeatures | undefined;
50
66
  //# sourceMappingURL=intent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/handlers/intent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAuBlD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAc9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,2BAA2B;AAC3B,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAY9C,CAAC;AAuCF;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,CAAC,EAAE,QAAQ,EACnB,OAAO,CAAC,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,YAAY,GAC1B,OAAO,CAAC,UAAU,CAAC,CA4JrB;AAs9BD,0CAA0C;AAC1C,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI,CAE9E"}
1
+ {"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../src/handlers/intent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gDAAgD,CAAC;AAC/E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAuBlD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAc9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,2BAA2B;AAC3B,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAY9C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CASnF;AAuCD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,CAAC,EAAE,QAAQ,EACnB,OAAO,CAAC,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,YAAY,EAC3B,eAAe,CAAC,EAAE,OAAO,GACxB,OAAO,CAAC,UAAU,CAAC,CAqLrB;AAyYD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAyGnG;AAkqBD,0CAA0C;AAC1C,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,SAAS,GAAG,IAAI,CAE9E;AAED,2DAA2D;AAC3D,wBAAgB,iBAAiB,IAAI,gBAAgB,GAAG,SAAS,CAEhE"}
@@ -13,8 +13,8 @@ import { findDefinition, findReferences, findWhereUsed, getCompletion, } from '.
13
13
  import { createObject, deleteObject, lockObject, safeUpdateSource, unlockObject } from '../adt/crud.js';
14
14
  import { activate, activateBatch, runAtcCheck, runUnitTests, syntaxCheck } from '../adt/devtools.js';
15
15
  import { getDump, getTraceDbAccesses, getTraceHitlist, getTraceStatements, listDumps, listTraces, } from '../adt/diagnostics.js';
16
- import { AdtApiError, AdtNetworkError, AdtSafetyError } from '../adt/errors.js';
17
- import { mapSapReleaseToAbaplintVersion, probeFeatures } from '../adt/features.js';
16
+ import { AdtApiError, AdtNetworkError, AdtSafetyError, isNotFoundError } from '../adt/errors.js';
17
+ import { classifyTextSearchError, mapSapReleaseToAbaplintVersion, probeFeatures } from '../adt/features.js';
18
18
  import { isOperationAllowed, OperationType } from '../adt/safety.js';
19
19
  import { createTransport, getTransport, listTransports, releaseTransport } from '../adt/transport.js';
20
20
  import { extractCdsElements } from '../context/cds-deps.js';
@@ -26,6 +26,8 @@ import { sanitizeArgs } from '../server/audit.js';
26
26
  import { generateRequestId, requestContext } from '../server/context.js';
27
27
  import { logger } from '../server/logger.js';
28
28
  import { expandHyperfocusedArgs, getHyperfocusedScope } from './hyperfocused.js';
29
+ import { getToolSchema } from './schemas.js';
30
+ import { formatZodError } from './zod-errors.js';
29
31
  /**
30
32
  * Scope required for each tool.
31
33
  *
@@ -39,7 +41,7 @@ import { expandHyperfocusedArgs, getHyperfocusedScope } from './hyperfocused.js'
39
41
  export const TOOL_SCOPES = {
40
42
  SAPRead: 'read',
41
43
  SAPSearch: 'read',
42
- SAPQuery: 'read',
44
+ SAPQuery: 'sql',
43
45
  SAPNavigate: 'read',
44
46
  SAPContext: 'read',
45
47
  SAPLint: 'read',
@@ -47,8 +49,24 @@ export const TOOL_SCOPES = {
47
49
  SAPWrite: 'write',
48
50
  SAPActivate: 'write',
49
51
  SAPManage: 'write',
50
- SAPTransport: 'admin',
52
+ SAPTransport: 'write',
51
53
  };
54
+ /**
55
+ * Check if authInfo has the required scope, respecting implied scopes:
56
+ * - `write` implies `read`
57
+ * - `sql` implies `data`
58
+ */
59
+ export function hasRequiredScope(authInfo, requiredScope) {
60
+ const scopes = authInfo.scopes;
61
+ if (scopes.includes(requiredScope))
62
+ return true;
63
+ // Implied scopes
64
+ if (requiredScope === 'read' && scopes.includes('write'))
65
+ return true;
66
+ if (requiredScope === 'data' && scopes.includes('sql'))
67
+ return true;
68
+ return false;
69
+ }
52
70
  function textResult(text) {
53
71
  return { content: [{ type: 'text', text }] };
54
72
  }
@@ -92,7 +110,7 @@ function classifyError(err) {
92
110
  * all tools are allowed (backward compatibility).
93
111
  * @param server - MCP Server instance for elicitation support.
94
112
  */
95
- export async function handleToolCall(client, config, toolName, args, authInfo, _server, cachingLayer) {
113
+ export async function handleToolCall(client, config, toolName, args, authInfo, _server, cachingLayer, isPerUserClient) {
96
114
  const reqId = generateRequestId();
97
115
  const start = Date.now();
98
116
  // Build user context for audit logging
@@ -112,7 +130,7 @@ export async function handleToolCall(client, config, toolName, args, authInfo, _
112
130
  // Scope enforcement — only when authInfo is present (XSUAA/OIDC mode)
113
131
  if (authInfo) {
114
132
  const requiredScope = TOOL_SCOPES[toolName];
115
- if (requiredScope && !authInfo.scopes.includes(requiredScope)) {
133
+ if (requiredScope && !hasRequiredScope(authInfo, requiredScope)) {
116
134
  logger.emitAudit({
117
135
  timestamp: new Date().toISOString(),
118
136
  level: 'warn',
@@ -127,6 +145,29 @@ export async function handleToolCall(client, config, toolName, args, authInfo, _
127
145
  return errorResult(`Insufficient scope: '${requiredScope}' required for ${toolName}. Your scopes: [${authInfo.scopes.join(', ')}]`);
128
146
  }
129
147
  }
148
+ // Validate tool arguments with Zod schema
149
+ const isBtp = config.systemType === 'btp';
150
+ // Always use the full search schema for validation — the handler checks text search availability
151
+ // and returns a proper error message with the probe reason when source_code search is unavailable
152
+ const schema = getToolSchema(toolName, isBtp);
153
+ if (schema) {
154
+ const parsed = schema.safeParse(args);
155
+ if (!parsed.success) {
156
+ const validationError = formatZodError(parsed.error, toolName);
157
+ logger.emitAudit({
158
+ timestamp: new Date().toISOString(),
159
+ level: 'warn',
160
+ event: 'safety_blocked',
161
+ requestId: reqId,
162
+ user,
163
+ clientId,
164
+ operation: toolName,
165
+ reason: 'Input validation failed',
166
+ });
167
+ return errorResult(validationError);
168
+ }
169
+ args = parsed.data;
170
+ }
130
171
  // Run within request context so HTTP-level logs get the requestId
131
172
  return requestContext.run({ requestId: reqId, user, tool: toolName }, async () => {
132
173
  try {
@@ -163,7 +204,7 @@ export async function handleToolCall(client, config, toolName, args, authInfo, _
163
204
  result = await handleSAPContext(client, args, cachingLayer);
164
205
  break;
165
206
  case 'SAPManage':
166
- result = await handleSAPManage(client, config, args, cachingLayer);
207
+ result = await handleSAPManage(client, config, args, cachingLayer, isPerUserClient);
167
208
  break;
168
209
  case 'SAP': {
169
210
  // Hyperfocused mode: route to the appropriate handler
@@ -175,13 +216,13 @@ export async function handleToolCall(client, config, toolName, args, authInfo, _
175
216
  // Check scope for the delegated action
176
217
  if (authInfo) {
177
218
  const requiredScope = getHyperfocusedScope(String(args.action ?? ''));
178
- if (!authInfo.scopes.includes(requiredScope)) {
219
+ if (!hasRequiredScope(authInfo, requiredScope)) {
179
220
  result = errorResult(`Insufficient scope: '${requiredScope}' required for SAP(action="${args.action}"). Your scopes: [${authInfo.scopes.join(', ')}]`);
180
221
  break;
181
222
  }
182
223
  }
183
224
  // Delegate to the real handler (recursive call, but with the mapped tool name)
184
- result = await handleToolCall(client, config, expanded.toolName, expanded.expandedArgs, authInfo, _server, cachingLayer);
225
+ result = await handleToolCall(client, config, expanded.toolName, expanded.expandedArgs, authInfo, _server, cachingLayer, isPerUserClient);
185
226
  break;
186
227
  }
187
228
  default:
@@ -336,8 +377,17 @@ async function handleSAPRead(client, args, cachingLayer) {
336
377
  return textResult(await cachedGet('BDEF', name, () => client.getBdef(name)));
337
378
  case 'SRVD':
338
379
  return textResult(await cachedGet('SRVD', name, () => client.getSrvd(name)));
339
- case 'DDLX':
340
- return textResult(await cachedGet('DDLX', name, () => client.getDdlx(name)));
380
+ case 'DDLX': {
381
+ try {
382
+ return textResult(await cachedGet('DDLX', name, () => client.getDdlx(name)));
383
+ }
384
+ catch (err) {
385
+ if (isNotFoundError(err)) {
386
+ return textResult(`No metadata extension (DDLX) found for "${name}". This means no @UI annotations are defined via DDLX for this view. The view may use inline annotations in the DDLS source, or the Fiori app may configure columns via manifest.json / app descriptor.`);
387
+ }
388
+ throw err;
389
+ }
390
+ }
341
391
  case 'SRVB':
342
392
  return textResult(await cachedGet('SRVB', name, () => client.getSrvb(name)));
343
393
  case 'TABL':
@@ -421,7 +471,9 @@ async function handleSAPRead(client, args, cachingLayer) {
421
471
  case 'VARIANTS':
422
472
  return textResult(await client.getVariants(name));
423
473
  default:
424
- return errorResult(`Unknown SAPRead type: ${type}. Supported: PROG, CLAS, INTF, FUNC, FUGR, INCL, DDLS, DDLX, BDEF, SRVD, SRVB, TABL, VIEW, STRU, DOMA, DTEL, TRAN, TABLE_CONTENTS, DEVC, SOBJ, SYSTEM, COMPONENTS, MESSAGES, TEXT_ELEMENTS, VARIANTS`);
474
+ return errorResult(`Unknown SAPRead type: "${type}". Supported types: PROG, CLAS, INTF, FUNC, FUGR, INCL, DDLS, DDLX, BDEF, SRVD, SRVB, TABL, VIEW, STRU, DOMA, DTEL, TRAN, TABLE_CONTENTS, DEVC, SOBJ, SYSTEM, COMPONENTS, MESSAGES, TEXT_ELEMENTS, VARIANTS. ` +
475
+ 'Tip: Map objectType from SAPSearch results by dropping the slash suffix (e.g., DDLS/DF → type="DDLS", CLAS/OC → type="CLAS", PROG/P → type="PROG"). ' +
476
+ 'Do not pass a URI — use the "type" and "name" parameters instead.');
425
477
  }
426
478
  }
427
479
  async function handleSAPSearch(client, args) {
@@ -429,6 +481,11 @@ async function handleSAPSearch(client, args) {
429
481
  const maxResults = Number(args.maxResults ?? 100);
430
482
  const searchType = String(args.searchType ?? 'object');
431
483
  if (searchType === 'source_code') {
484
+ // If probe already determined textSearch is unavailable, return the precise reason
485
+ if (cachedFeatures?.textSearch && !cachedFeatures.textSearch.available) {
486
+ return errorResult(`Source code search is not available on this SAP system. ${cachedFeatures.textSearch.reason ?? ''}` +
487
+ `\nUse SAPSearch with searchType="object" to search by object name instead, or use SAPQuery to search metadata tables.`);
488
+ }
432
489
  const objectType = args.objectType;
433
490
  const packageName = args.packageName;
434
491
  try {
@@ -436,9 +493,13 @@ async function handleSAPSearch(client, args) {
436
493
  return textResult(JSON.stringify(results, null, 2));
437
494
  }
438
495
  catch (err) {
439
- if (err instanceof AdtApiError && (err.statusCode === 404 || err.statusCode === 501)) {
440
- return errorResult(`Source code search is not available on this SAP system (requires SAP_BASIS ≥ 7.51). ` +
441
- `Use SAPSearch with searchType="object" to search by object name instead, or use SAPQuery to search metadata tables.`);
496
+ if (err instanceof AdtApiError) {
497
+ const permanentCodes = [401, 403, 404, 501];
498
+ if (permanentCodes.includes(err.statusCode)) {
499
+ const classified = classifyTextSearchError(err.statusCode);
500
+ return errorResult(`Source code search is not available on this SAP system. ${classified.reason ?? ''}` +
501
+ `\nUse SAPSearch with searchType="object" to search by object name instead, or use SAPQuery to search metadata tables.`);
502
+ }
442
503
  }
443
504
  throw err;
444
505
  }
@@ -474,6 +535,10 @@ async function handleSAPQuery(client, args) {
474
535
  }
475
536
  }
476
537
  }
538
+ // JOIN-aware error: ADT freestyle SQL parser has known edge cases with JOINs (SAP Note 3605050)
539
+ if (err instanceof AdtApiError && err.statusCode === 400 && /\bJOIN\b/i.test(sql)) {
540
+ return errorResult(`${err.message}\n\nMulti-table JOIN query failed. The ADT freestyle SQL endpoint has known parser edge cases with JOINs (SAP Note 3605050). Try splitting into separate single-table queries.`);
541
+ }
477
542
  throw err;
478
543
  }
479
544
  }
@@ -540,6 +605,129 @@ function buildLintConfigOptions(config, ruleOverrides) {
540
605
  ruleOverrides,
541
606
  };
542
607
  }
608
+ // ─── Object Creation XML ─────────────────────────────────────────────
609
+ /**
610
+ * Build the type-specific XML body for ADT object creation.
611
+ *
612
+ * SAP ADT requires each object type to have its own root XML element.
613
+ * Using a generic body (e.g. adtcore:objectReferences) returns 400:
614
+ * "System expected the element '{http://www.sap.com/adt/programs/programs}abapProgram'"
615
+ */
616
+ export function buildCreateXml(type, name, pkg, description) {
617
+ switch (type) {
618
+ case 'PROG':
619
+ return `<?xml version="1.0" encoding="UTF-8"?>
620
+ <program:abapProgram xmlns:program="http://www.sap.com/adt/programs/programs"
621
+ xmlns:adtcore="http://www.sap.com/adt/core"
622
+ adtcore:description="${escapeXml(description)}"
623
+ adtcore:name="${escapeXml(name)}"
624
+ adtcore:type="PROG/P"
625
+ adtcore:masterLanguage="EN"
626
+ adtcore:masterSystem="H00"
627
+ adtcore:responsible="DEVELOPER">
628
+ <adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
629
+ </program:abapProgram>`;
630
+ case 'CLAS':
631
+ return `<?xml version="1.0" encoding="UTF-8"?>
632
+ <class:abapClass xmlns:class="http://www.sap.com/adt/oo/classes"
633
+ xmlns:adtcore="http://www.sap.com/adt/core"
634
+ adtcore:description="${escapeXml(description)}"
635
+ adtcore:name="${escapeXml(name)}"
636
+ adtcore:type="CLAS/OC"
637
+ adtcore:masterLanguage="EN"
638
+ adtcore:masterSystem="H00"
639
+ adtcore:responsible="DEVELOPER">
640
+ <adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
641
+ </class:abapClass>`;
642
+ case 'INTF':
643
+ return `<?xml version="1.0" encoding="UTF-8"?>
644
+ <intf:abapInterface xmlns:intf="http://www.sap.com/adt/oo/interfaces"
645
+ xmlns:adtcore="http://www.sap.com/adt/core"
646
+ adtcore:description="${escapeXml(description)}"
647
+ adtcore:name="${escapeXml(name)}"
648
+ adtcore:type="INTF/OI"
649
+ adtcore:masterLanguage="EN"
650
+ adtcore:masterSystem="H00"
651
+ adtcore:responsible="DEVELOPER">
652
+ <adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
653
+ </intf:abapInterface>`;
654
+ case 'INCL':
655
+ return `<?xml version="1.0" encoding="UTF-8"?>
656
+ <include:abapInclude xmlns:include="http://www.sap.com/adt/programs/includes"
657
+ xmlns:adtcore="http://www.sap.com/adt/core"
658
+ adtcore:description="${escapeXml(description)}"
659
+ adtcore:name="${escapeXml(name)}"
660
+ adtcore:type="PROG/I"
661
+ adtcore:masterLanguage="EN"
662
+ adtcore:masterSystem="H00"
663
+ adtcore:responsible="DEVELOPER">
664
+ <adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
665
+ </include:abapInclude>`;
666
+ case 'DDLS':
667
+ return `<?xml version="1.0" encoding="UTF-8"?>
668
+ <ddl:ddlSource xmlns:ddl="http://www.sap.com/adt/ddic/ddlsources"
669
+ xmlns:adtcore="http://www.sap.com/adt/core"
670
+ adtcore:description="${escapeXml(description)}"
671
+ adtcore:name="${escapeXml(name)}"
672
+ adtcore:type="DDLS/DF"
673
+ adtcore:masterLanguage="EN"
674
+ adtcore:masterSystem="H00"
675
+ adtcore:responsible="DEVELOPER">
676
+ <adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
677
+ </ddl:ddlSource>`;
678
+ case 'BDEF':
679
+ return `<?xml version="1.0" encoding="UTF-8"?>
680
+ <bdef:behaviorDefinition xmlns:bdef="http://www.sap.com/adt/bo/behaviordefinitions"
681
+ xmlns:adtcore="http://www.sap.com/adt/core"
682
+ adtcore:description="${escapeXml(description)}"
683
+ adtcore:name="${escapeXml(name)}"
684
+ adtcore:type="BDEF/BDO"
685
+ adtcore:masterLanguage="EN"
686
+ adtcore:masterSystem="H00"
687
+ adtcore:responsible="DEVELOPER">
688
+ <adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
689
+ </bdef:behaviorDefinition>`;
690
+ case 'SRVD':
691
+ return `<?xml version="1.0" encoding="UTF-8"?>
692
+ <srvd:srvdSource xmlns:srvd="http://www.sap.com/adt/ddic/srvd/sources"
693
+ xmlns:adtcore="http://www.sap.com/adt/core"
694
+ adtcore:description="${escapeXml(description)}"
695
+ adtcore:name="${escapeXml(name)}"
696
+ adtcore:type="SRVD/SRV"
697
+ adtcore:masterLanguage="EN"
698
+ adtcore:masterSystem="H00"
699
+ adtcore:responsible="DEVELOPER">
700
+ <adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
701
+ </srvd:srvdSource>`;
702
+ case 'DDLX':
703
+ return `<?xml version="1.0" encoding="UTF-8"?>
704
+ <ddlx:ddlxSource xmlns:ddlx="http://www.sap.com/adt/ddic/ddlx/sources"
705
+ xmlns:adtcore="http://www.sap.com/adt/core"
706
+ adtcore:description="${escapeXml(description)}"
707
+ adtcore:name="${escapeXml(name)}"
708
+ adtcore:type="DDLX/EX"
709
+ adtcore:masterLanguage="EN"
710
+ adtcore:masterSystem="H00"
711
+ adtcore:responsible="DEVELOPER">
712
+ <adtcore:packageRef adtcore:name="${escapeXml(pkg)}"/>
713
+ </ddlx:ddlxSource>`;
714
+ default:
715
+ // Fallback — generic objectReferences using the correct URL for the type
716
+ return `<?xml version="1.0" encoding="UTF-8"?>
717
+ <adtcore:objectReferences xmlns:adtcore="http://www.sap.com/adt/core">
718
+ <adtcore:objectReference adtcore:uri="${escapeXml(objectUrlForType(type, name))}" adtcore:type="${escapeXml(type)}" adtcore:name="${escapeXml(name)}" adtcore:packageName="${escapeXml(pkg)}"/>
719
+ </adtcore:objectReferences>`;
720
+ }
721
+ }
722
+ /** Escape special characters for XML attribute values */
723
+ function escapeXml(s) {
724
+ return s
725
+ .replace(/&/g, '&amp;')
726
+ .replace(/"/g, '&quot;')
727
+ .replace(/'/g, '&apos;')
728
+ .replace(/</g, '&lt;')
729
+ .replace(/>/g, '&gt;');
730
+ }
543
731
  // ─── Object URL Mapping ──────────────────────────────────────────────
544
732
  /** Map object type + name to the ADT object URL used by CRUD/DevTools/etc. */
545
733
  function objectUrlForType(type, name) {
@@ -607,12 +795,26 @@ async function handleSAPWrite(client, args, config, cachingLayer) {
607
795
  }
608
796
  case 'create': {
609
797
  const pkg = String(args.package ?? '$TMP');
610
- // Build creation XML body
611
- const body = `<?xml version="1.0" encoding="UTF-8"?>
612
- <adtcore:objectReferences xmlns:adtcore="http://www.sap.com/adt/core">
613
- <adtcore:objectReference adtcore:uri="${objectUrl}" adtcore:type="${type}" adtcore:name="${name}" adtcore:packageName="${pkg}"/>
614
- </adtcore:objectReferences>`;
615
- const result = await createObject(client.http, client.safety, objectUrl, body, 'application/xml', transport);
798
+ const description = String(args.description ?? name);
799
+ // Build type-specific creation XML body.
800
+ // SAP ADT requires the root element to match the object type —
801
+ // a generic objectReferences body returns 400 "System expected the element ...".
802
+ const body = buildCreateXml(type, name, pkg, description);
803
+ // Step 1: Create the object (metadata only)
804
+ const createUrl = objectUrl.replace(/\/[^/]+$/, ''); // parent collection URL
805
+ const result = await createObject(client.http, client.safety, createUrl, body, 'application/xml', transport);
806
+ // Step 2: Write source code if provided
807
+ if (source) {
808
+ // Pre-write lint validation
809
+ const lintWarnings = runPreWriteLint(source, type, name, config);
810
+ if (lintWarnings.blocked) {
811
+ return textResult(`Created ${type} ${name} in package ${pkg}, but source was rejected by lint:\n${lintWarnings.result.content[0].text}`);
812
+ }
813
+ await safeUpdateSource(client.http, client.safety, objectUrl, srcUrl, source, transport);
814
+ cachingLayer?.invalidate(type, name);
815
+ const msg = `Created ${type} ${name} in package ${pkg} and wrote source code.`;
816
+ return lintWarnings.warnings ? textResult(`${msg}\n\n${lintWarnings.warnings}`) : textResult(msg);
817
+ }
616
818
  return textResult(`Created ${type} ${name} in package ${pkg}.\n${result}`);
617
819
  }
618
820
  case 'edit_method': {
@@ -1033,7 +1235,7 @@ async function handleSAPContext(client, args, cachingLayer) {
1033
1235
  // ─── SAPManage Handler ────────────────────────────────────────────────
1034
1236
  /** Cached feature status — populated on first probe */
1035
1237
  let cachedFeatures;
1036
- async function handleSAPManage(client, config, args, cachingLayer) {
1238
+ async function handleSAPManage(client, config, args, cachingLayer, isPerUserClient) {
1037
1239
  const action = String(args.action ?? '');
1038
1240
  switch (action) {
1039
1241
  case 'features': {
@@ -1063,11 +1265,30 @@ async function handleSAPManage(client, config, args, cachingLayer) {
1063
1265
  featureConfig.amdp = config.featureAmdp;
1064
1266
  featureConfig.ui5 = config.featureUi5;
1065
1267
  featureConfig.transport = config.featureTransport;
1066
- cachedFeatures = await probeFeatures(client.http, featureConfig, config.systemType);
1067
- return textResult(JSON.stringify(cachedFeatures, null, 2));
1268
+ const probed = await probeFeatures(client.http, featureConfig, config.systemType);
1269
+ // In PP mode with a per-user client, auth-sensitive results (401/403 on any
1270
+ // feature) must not poison the global cache — another user may have different
1271
+ // authorizations. Return the per-user result to the caller but keep the global
1272
+ // cache unchanged. However, when PP is enabled but the request fell back to the
1273
+ // shared/default client (no JWT, missing btpConfig, or non-strict fallback), the
1274
+ // probe ran with the same service-account credentials as the startup probe, so
1275
+ // updating the cache is safe and allows a manual probe to repair a failed startup.
1276
+ // Apply the same auth-failure sanitization as the startup probe: in PP mode,
1277
+ // shared-client 401/403 on textSearch must not hide source_code from users who
1278
+ // might have authorization via per-user clients.
1279
+ if (!isPerUserClient) {
1280
+ if (config.ppEnabled && probed.textSearch && !probed.textSearch.available) {
1281
+ const reason = probed.textSearch.reason ?? '';
1282
+ if (reason.includes('authorization') || reason.includes('401') || reason.includes('403')) {
1283
+ probed.textSearch = undefined;
1284
+ }
1285
+ }
1286
+ cachedFeatures = probed;
1287
+ }
1288
+ return textResult(JSON.stringify(probed, null, 2));
1068
1289
  }
1069
1290
  default:
1070
- return errorResult(`Unknown SAPManage action: ${action}. Supported: features, probe`);
1291
+ return errorResult(`Unknown SAPManage action: ${action}. Supported: features, probe, cache_stats`);
1071
1292
  }
1072
1293
  }
1073
1294
  /** Reset cached features (for testing) */
@@ -1078,4 +1299,8 @@ export function resetCachedFeatures() {
1078
1299
  export function setCachedFeatures(features) {
1079
1300
  cachedFeatures = features;
1080
1301
  }
1302
+ /** Get cached features (for tool definition adaptation) */
1303
+ export function getCachedFeatures() {
1304
+ return cachedFeatures;
1305
+ }
1081
1306
  //# sourceMappingURL=intent.js.map