sap-ai-dev-toolkit 0.9.9912 → 0.9.9914

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 (37) hide show
  1. package/.github/agents/abap-developer.agent.md +1 -1
  2. package/.github/agents/sap-integration-architect.agent.md +38 -0
  3. package/.github/agents/sap-integration-developer.agent.md +31 -0
  4. package/.github/agents/sap-solution-architect.agent.md +1 -0
  5. package/.github/skills/abap-development/SKILL.md +1 -1
  6. package/.github/skills/cds-development/SKILL.md +1 -1
  7. package/.github/skills/integration-suite-delivery/SKILL.md +74 -0
  8. package/.github/skills/sap-integration-architect/SKILL.md +76 -0
  9. package/NOTICE +10 -0
  10. package/README.md +36 -8
  11. package/dist/checksums.txt +5 -5
  12. package/dist/vsp-darwin-arm64 +0 -0
  13. package/dist/vsp-darwin-x64 +0 -0
  14. package/dist/vsp-linux-arm64 +0 -0
  15. package/dist/vsp-linux-x64 +0 -0
  16. package/dist/vsp-win32-x64.exe +0 -0
  17. package/inventory.md +66 -2
  18. package/package.json +5 -2
  19. package/patches/vsp-bas-proxy-auth.patch +88 -7
  20. package/scripts/run-live-integration.mjs +1079 -0
  21. package/src/apim-bundle.mjs +381 -0
  22. package/src/apim-tools.mjs +641 -0
  23. package/src/cpi-tools.mjs +1042 -0
  24. package/src/engineering-tools.mjs +105 -0
  25. package/src/iflow-bundle.mjs +282 -0
  26. package/src/integration-common.mjs +232 -0
  27. package/src/integration-config.mjs +167 -0
  28. package/src/integration-credentials.mjs +65 -0
  29. package/src/integration-http.mjs +266 -0
  30. package/src/integration-server.mjs +125 -0
  31. package/src/integration-templates/https-request-reply-http.iflw +391 -0
  32. package/src/integration-tools.mjs +27 -0
  33. package/src/integration-verify.mjs +118 -0
  34. package/src/launcher.mjs +14 -2
  35. package/src/mcp-config.mjs +18 -3
  36. package/src/setup.mjs +189 -11
  37. package/tools.md +81 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sap-ai-dev-toolkit",
3
- "version": "0.9.9912",
3
+ "version": "0.9.9914",
4
4
  "description": "SAP AI development toolkit for BAS, ABAP, RAP, CAP, HANA Cloud, Fiori, UI5, and MCP",
5
5
  "author": "Gurkan Yilmaz",
6
6
  "type": "module",
@@ -11,6 +11,7 @@
11
11
  "@abaplint/core": "2.119.0",
12
12
  "@modelcontextprotocol/sdk": "1.32.1",
13
13
  "@sap/hana-client": "2.30.27",
14
+ "fflate": "0.8.3",
14
15
  "terminal-kit": "^3.1.4",
15
16
  "undici": "^6.21.3",
16
17
  "zod": "4.6.5"
@@ -18,13 +19,15 @@
18
19
  "bin": {
19
20
  "sap-ai-dev": "src/launcher.mjs",
20
21
  "sap-ai-dev-toolkit": "src/launcher.mjs",
21
- "sap-ai-hana": "src/hana-inspector.mjs"
22
+ "sap-ai-hana": "src/hana-inspector.mjs",
23
+ "sap-ai-integration": "src/integration-server.mjs"
22
24
  },
23
25
  "scripts": {
24
26
  "postinstall": "node scripts/postinstall.mjs",
25
27
  "install:local": "node scripts/install-local.mjs",
26
28
  "test": "node --test --test-force-exit test/*.test.mjs",
27
29
  "test:live:s4h": "node scripts/run-live-s4h.mjs",
30
+ "test:live:integration": "node scripts/run-live-integration.mjs",
28
31
  "test:visibility": "node --test test/setup.test.mjs test/terminal-ui.test.mjs",
29
32
  "test:mutation": "node scripts/mutation-terminal-ui.mjs",
30
33
  "publish:npm": "node scripts/publish-npm.mjs",
@@ -148,6 +148,23 @@ index 5007935..3b1fdd8 100755
148
148
  cookieFile, _ := cmd.Flags().GetString("cookie-file")
149
149
  cookieString, _ := cmd.Flags().GetString("cookie-string")
150
150
 
151
+ diff --git a/internal/mcp/handlers_source.go b/internal/mcp/handlers_source.go
152
+ index d23089b..8e7e5ff 100644
153
+ --- a/internal/mcp/handlers_source.go
154
+ +++ b/internal/mcp/handlers_source.go
155
+ @@ -132,10 +132,10 @@ func (s *Server) registerGetSource() {
156
+ // registerWriteSource registers the unified WriteSource tool
157
+ func (s *Server) registerWriteSource() {
158
+ s.mcpServer.AddTool(mcp.NewTool("WriteSource",
159
+ - mcp.WithDescription("Unified tool for writing ABAP source code with automatic create/update detection. Supports PROG, CLAS, INTF, INCL, and RAP types (DDLS, BDEF, SRVD)."),
160
+ + mcp.WithDescription("Unified tool for writing ABAP source code with automatic create/update detection. Supports PROG, CLAS, INTF, INCL, RAP types (DDLS, BDEF, SRVD), and updates to existing DDIC tables (TABL). New tables must be created with CreateTable."),
161
+ mcp.WithString("object_type",
162
+ mcp.Required(),
163
+ - mcp.Description("Object type: PROG (program), CLAS (class), INTF (interface), INCL (include), DDLS (CDS view), BDEF (behavior definition), SRVD (service definition)"),
164
+ + mcp.Description("Object type: PROG (program), CLAS (class), INTF (interface), INCL (include), DDLS (CDS view), BDEF (behavior definition), SRVD (service definition), or TABL (existing DDIC table update only)"),
165
+ ),
166
+ mcp.WithString("name",
167
+ mcp.Required(),
151
168
  diff --git a/internal/mcp/server.go b/internal/mcp/server.go
152
169
  index 9337857..11fc940 100644
153
170
  --- a/internal/mcp/server.go
@@ -290,7 +307,7 @@ index 7740e56..b4c2faf 100755
290
307
  + }
291
308
  +}
292
309
  diff --git a/internal/mcp/tools_register.go b/internal/mcp/tools_register.go
293
- index dd433d6..5553b7f 100644
310
+ index dd433d6..d9ea365 100644
294
311
  --- a/internal/mcp/tools_register.go
295
312
  +++ b/internal/mcp/tools_register.go
296
313
  @@ -837,6 +837,19 @@ func (s *Server) registerDevTools(shouldRegister func(string) bool) {
@@ -313,6 +330,24 @@ index dd433d6..5553b7f 100644
313
330
  ),
314
331
  ), s.handleActivateMultiple)
315
332
  }
333
+ @@ -1070,7 +1083,7 @@ func (s *Server) registerCRUDTools(shouldRegister func(string) bool) {
334
+
335
+ if shouldRegister("CreateTable") {
336
+ s.mcpServer.AddTool(mcp.NewTool("CreateTable",
337
+ - mcp.WithDescription("Create a DDIC transparent table from a simple JSON definition. Handles full workflow: create → set source → activate. Supports common ABAP types: CHAR, NUMC, INT4, DEC, STRING, TIMESTAMPL, UUID, etc."),
338
+ + mcp.WithDescription("Create a DDIC transparent table from a simple JSON definition. Handles full workflow: create → set source → activate. Supports common ABAP types: CHAR, NUMC, INT4, DEC, STRING, TIMESTAMPL, UUID, etc. Client-dependent tables get one implicit CLIENT key; supplied CLIENT or MANDT fields are treated as that same key."),
339
+ mcp.WithString("name",
340
+ mcp.Required(),
341
+ mcp.Description("Table name (uppercase, max 30 chars, must start with Z/Y)"),
342
+ @@ -1084,7 +1097,7 @@ func (s *Server) registerCRUDTools(shouldRegister func(string) bool) {
343
+ ),
344
+ mcp.WithString("fields",
345
+ mcp.Required(),
346
+ - mcp.Description("JSON array of fields: [{\"name\":\"ID\",\"type\":\"CHAR32\",\"key\":true},{\"name\":\"VALUE\",\"type\":\"STRING\"}]. Types: CHAR/CHARnn, NUMC/NUMCnn, INT4, DEC, STRING, TIMESTAMPL, UUID, DATS, TIMS, or data element name."),
347
+ + mcp.Description("JSON array of user fields: [{\"name\":\"ID\",\"type\":\"CHAR32\",\"key\":true},{\"name\":\"VALUE\",\"type\":\"STRING\"}]. Do not include CLIENT or MANDT; the client key is added automatically. Types: CHAR/CHARnn, NUMC/NUMCnn, INT4, DEC, STRING, TIMESTAMPL, UUID, DATS, TIMS, or data element name."),
348
+ ),
349
+ mcp.WithString("transport",
350
+ mcp.Description("Transport request number (optional for $TMP)"),
316
351
  diff --git a/pkg/adt/browser_auth.go b/pkg/adt/browser_auth.go
317
352
  index ea3c1a9..5bc7a01 100644
318
353
  --- a/pkg/adt/browser_auth.go
@@ -436,7 +471,7 @@ index 0000000..1ed3c2b
436
471
  + }
437
472
  +}
438
473
  diff --git a/pkg/adt/crud.go b/pkg/adt/crud.go
439
- index f412fb1..15ac38a 100755
474
+ index f412fb1..8021a5a 100755
440
475
  --- a/pkg/adt/crud.go
441
476
  +++ b/pkg/adt/crud.go
442
477
  @@ -1250,7 +1250,12 @@ func (c *Client) publishUnpublishServiceBinding(ctx context.Context, action, ser
@@ -453,6 +488,23 @@ index f412fb1..15ac38a 100755
453
488
 
454
489
  resp, err := c.transport.Request(ctx, path, &RequestOptions{
455
490
  Method: http.MethodPost,
491
+ @@ -1427,11 +1432,15 @@ func generateTableDDL(opts CreateTableOptions) string {
492
+ sb.WriteString("@AbapCatalog.dataMaintenance : #ALLOWED\n")
493
+ sb.WriteString(fmt.Sprintf("define table %s {\n\n", strings.ToLower(opts.Name)))
494
+
495
+ - // Auto-add MANDT as first key field (standard SAP practice)
496
+ + // The table's implicit client field is named CLIENT in DDL; callers may
497
+ + // provide CLIENT or MANDT, but the schema must contain it only once.
498
+ sb.WriteString(" key client : abap.clnt not null;\n")
499
+
500
+ // User-defined fields
501
+ for _, f := range opts.Fields {
502
+ + if strings.EqualFold(strings.TrimSpace(f.Name), "CLIENT") || strings.EqualFold(strings.TrimSpace(f.Name), "MANDT") {
503
+ + continue
504
+ + }
505
+ fieldName := strings.ToLower(f.Name)
506
+ fieldType := mapFieldType(f)
507
+
456
508
  diff --git a/pkg/adt/features.go b/pkg/adt/features.go
457
509
  index 13aa4b0..8fb7376 100755
458
510
  --- a/pkg/adt/features.go
@@ -620,7 +672,7 @@ index 0000000..5e880bd
620
672
  + }
621
673
  +}
622
674
  diff --git a/pkg/adt/http.go b/pkg/adt/http.go
623
- index 0b4d9f1..f0b5b51 100755
675
+ index 0b4d9f1..e420573 100755
624
676
  --- a/pkg/adt/http.go
625
677
  +++ b/pkg/adt/http.go
626
678
  @@ -313,7 +313,7 @@ func (t *Transport) request(ctx context.Context, path string, opts *RequestOptio
@@ -723,7 +775,8 @@ index 0b4d9f1..f0b5b51 100755
723
775
  + }
724
776
  // Drain the body so the connection can be reused.
725
777
  _, _ = io.Copy(io.Discard, resp.Body)
726
- traceHTTPResponse(resp, nil)
778
+ - traceHTTPResponse(resp, nil)
779
+ + traceHTTPResponse(resp, body)
727
780
  t.adoptServerCookies(resp)
728
781
 
729
782
  - return resp.Header.Get("X-CSRF-Token"), resp.StatusCode, t.redirectedAwayFromSAP(resp), nil
@@ -751,10 +804,10 @@ index 0b4d9f1..f0b5b51 100755
751
804
  // redirectedAwayFromSAP reports whether a response was ultimately served by
752
805
  diff --git a/pkg/adt/http_csrf_discovery_test.go b/pkg/adt/http_csrf_discovery_test.go
753
806
  new file mode 100644
754
- index 0000000..80741da
807
+ index 0000000..ee932b3
755
808
  --- /dev/null
756
809
  +++ b/pkg/adt/http_csrf_discovery_test.go
757
- @@ -0,0 +1,56 @@
810
+ @@ -0,0 +1,55 @@
758
811
  +package adt
759
812
  +
760
813
  +import (
@@ -810,7 +863,6 @@ index 0000000..80741da
810
863
  + t.Fatalf("expected both endpoint failures, got %v", err)
811
864
  + }
812
865
  +}
813
- +
814
866
  diff --git a/pkg/adt/http_sso_same_host_test.go b/pkg/adt/http_sso_same_host_test.go
815
867
  new file mode 100644
816
868
  index 0000000..0c39b96
@@ -1290,3 +1342,32 @@ index 0000000..1385d6d
1290
1342
  + }
1291
1343
  + }
1292
1344
  +}
1345
+ diff --git a/pkg/adt/workflows_source_tabl_test.go b/pkg/adt/workflows_source_tabl_test.go
1346
+ index 220e91b..61e1691 100644
1347
+ --- a/pkg/adt/workflows_source_tabl_test.go
1348
+ +++ b/pkg/adt/workflows_source_tabl_test.go
1349
+ @@ -44,3 +44,24 @@ func TestCreatingATableFromSourceSaysWhatDoesWork(t *testing.T) {
1350
+ t.Errorf("the refusal should name the route that does work, got %q", result.Message)
1351
+ }
1352
+ }
1353
+ +
1354
+ +func TestCreateTableEmitsOnlyTheAutomaticClientField(t *testing.T) {
1355
+ + source := generateTableDDL(CreateTableOptions{
1356
+ + Name: "ZADK_SESSION",
1357
+ + Fields: []TableField{
1358
+ + {Name: "MANDT", Type: "mandt", IsKey: true},
1359
+ + {Name: "CLIENT", Type: "abap.clnt", IsKey: true},
1360
+ + {Name: "SESSION_ID", Type: "CHAR", Length: 32, IsKey: true},
1361
+ + },
1362
+ + })
1363
+ +
1364
+ + if got := strings.Count(source, "key client : abap.clnt not null;"); got != 1 {
1365
+ + t.Fatalf("got %d client keys, want exactly 1:\n%s", got, source)
1366
+ + }
1367
+ + if strings.Contains(source, "key mandt :") || strings.Contains(source, "key client : abap.clnt not null;\n key client :") {
1368
+ + t.Fatalf("generated DDL contains a duplicate client field:\n%s", source)
1369
+ + }
1370
+ + if !strings.Contains(source, "key session_id : abap.char(32) not null;") {
1371
+ + t.Fatalf("generated DDL lost the business key:\n%s", source)
1372
+ + }
1373
+ +}