sap-ai-dev-toolkit 0.9.9921 → 0.9.9922

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/NOTICE CHANGED
@@ -2,7 +2,8 @@ Third-party notices for sap-ai-dev-toolkit
2
2
 
3
3
  This package includes patched VSP (vibing-steampunk) binaries built from upstream commit
4
4
  9886d2727f47506368b0a3c2f1c1766f1200f747. The BAS proxy-auth change is documented in
5
- patches/vsp-bas-proxy-auth.patch. The following upstream notice is reproduced from VSP:
5
+ patches/vsp-bas-proxy-auth.patch; the namespaced class-include EditSource fix is documented in
6
+ patches/vsp-namespaced-class-include-edit.patch. The following upstream notice is reproduced from VSP:
6
7
 
7
8
  vibing-steampunk (vsp)
8
9
  Copyright (c) 2025-2026 Alice Vinogradova and contributors
@@ -1,5 +1,5 @@
1
- 885ba61e5aa31e1bfe21953040a5cdb5e06c3eb648495f03b7cb035b2fd9d2c2 vsp-linux-x64
2
- 34f392bfbd853dd2b24abd95fda351d25633b538728371f881ee475a65904b31 vsp-linux-arm64
3
- cee27c146031fd932bf974ca359c6c0263c1ea1c20fe120f5244948af5ae1743 vsp-darwin-x64
4
- 320deb50652f0a29c8624c56e7cb150cb27a4e381b42c9b8c1edda1c3ad64a81 vsp-darwin-arm64
5
- 574885013902ccd93645ca7890cdff1c02ea769799df019f1d086d41f9e2cb71 vsp-win32-x64.exe
1
+ 31902921b0d2b5349be8e392aae3632ca8c3dee26950ea30c412ec83271722f3 vsp-linux-x64
2
+ df39b324fe419348f5157954d56c5f8d60e5bac28edc04a56e90c380b67de10d vsp-linux-arm64
3
+ 754338fbbbe66260cac722677753b16a0a2f23127b947bf1f3a189044fa66c32 vsp-darwin-x64
4
+ ac153052b5d02b2f19a536623c957369af3412f5bbe2eed0f6a43e8597ed0f1b vsp-darwin-arm64
5
+ 722c6de352719dd9374932b56546189a75c29800e74da3bdcb0308b2034248ac vsp-win32-x64.exe
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sap-ai-dev-toolkit",
3
- "version": "0.9.9921",
3
+ "version": "0.9.9922",
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",
@@ -0,0 +1,134 @@
1
+ diff --git a/pkg/adt/edit_namespaced_include_test.go b/pkg/adt/edit_namespaced_include_test.go
2
+ new file mode 100644
3
+ index 0000000..514ab35
4
+ --- /dev/null
5
+ +++ b/pkg/adt/edit_namespaced_include_test.go
6
+ @@ -0,0 +1,80 @@
7
+ +package adt
8
+ +
9
+ +import (
10
+ + "context"
11
+ + "io"
12
+ + "net/http"
13
+ + "net/http/httptest"
14
+ + "strings"
15
+ + "sync"
16
+ + "testing"
17
+ +)
18
+ +
19
+ +// TestEditSource_NamespacedClassInclude guards against double-encoding the
20
+ +// class name of a namespaced class include: the object URL arrives with
21
+ +// "%2FABC%2F", and every request (read, lock, hash check, PUT, unlock,
22
+ +// activate) must keep exactly one encoding — never "%252F".
23
+ +func TestEditSource_NamespacedClassInclude(t *testing.T) {
24
+ + const source = "CLASS lcl_x DEFINITION.\n \" old\nENDCLASS.\n"
25
+ + const classPath = "/sap/bc/adt/oo/classes/%2FABC%2FCL_TEST"
26
+ +
27
+ + for _, include := range []string{"definitions", "implementations", "testclasses"} {
28
+ + for _, withHash := range []bool{false, true} {
29
+ + name := include
30
+ + if withHash {
31
+ + name += "/hash"
32
+ + }
33
+ + t.Run(name, func(t *testing.T) {
34
+ + includePath := classPath + "/includes/" + include
35
+ + var mu sync.Mutex
36
+ + var puts []string
37
+ + current := source
38
+ + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
39
+ + w.Header().Set("x-csrf-token", "TOKEN")
40
+ + raw := r.URL.EscapedPath()
41
+ + if strings.Contains(raw, "%25") {
42
+ + t.Errorf("double-encoded request: %s %s", r.Method, r.RequestURI)
43
+ + w.WriteHeader(http.StatusNotFound)
44
+ + return
45
+ + }
46
+ + switch {
47
+ + case r.URL.Query().Get("_action") == "LOCK":
48
+ + w.Header().Set("Content-Type", "application/xml")
49
+ + _, _ = w.Write([]byte(`<?xml version="1.0"?><asx:abap xmlns:asx="http://www.sap.com/abapxml">
50
+ + <asx:values><DATA><LOCK_HANDLE>HANDLE-1</LOCK_HANDLE>
51
+ + <MODIFICATION_SUPPORT>Modification</MODIFICATION_SUPPORT></DATA></asx:values></asx:abap>`))
52
+ + case r.Method == http.MethodGet && raw == includePath:
53
+ + mu.Lock()
54
+ + _, _ = w.Write([]byte(current))
55
+ + mu.Unlock()
56
+ + case r.Method == http.MethodPut:
57
+ + mu.Lock()
58
+ + puts = append(puts, raw)
59
+ + body, _ := io.ReadAll(r.Body)
60
+ + current = string(body)
61
+ + mu.Unlock()
62
+ + default:
63
+ + w.WriteHeader(http.StatusOK)
64
+ + }
65
+ + }))
66
+ + defer srv.Close()
67
+ +
68
+ + opts := &EditSourceOptions{}
69
+ + if withHash {
70
+ + opts.ExpectedSourceHash = SourceHash(source)
71
+ + }
72
+ + c := NewClient(srv.URL, "TESTUSER", "pw")
73
+ + res, err := c.EditSourceWithOptions(context.Background(), includePath, "\" old", "\" new", opts)
74
+ + if err != nil {
75
+ + t.Fatalf("EditSourceWithOptions: %v", err)
76
+ + }
77
+ + if !res.Success {
78
+ + t.Fatalf("edit failed: %s", res.Message)
79
+ + }
80
+ + if len(puts) != 1 || puts[0] != includePath {
81
+ + t.Fatalf("PUT paths = %v, want [%s]", puts, includePath)
82
+ + }
83
+ + })
84
+ + }
85
+ + }
86
+ +}
87
+ diff --git a/pkg/adt/workflows_edit.go b/pkg/adt/workflows_edit.go
88
+ index 6da5df7..01c02e0 100644
89
+ --- a/pkg/adt/workflows_edit.go
90
+ +++ b/pkg/adt/workflows_edit.go
91
+ @@ -3,6 +3,7 @@ package adt
92
+ import (
93
+ "context"
94
+ "fmt"
95
+ + "net/url"
96
+ "strings"
97
+ )
98
+
99
+ @@ -204,9 +205,9 @@ func (c *Client) EditSourceWithOptions(ctx context.Context, objectURL, oldString
100
+ if idx := strings.Index(objectURL, classesPrefix); idx >= 0 {
101
+ rest := objectURL[idx+len(classesPrefix):]
102
+ if slashIdx := strings.Index(rest, "/"); slashIdx > 0 {
103
+ - classNameForMethod = rest[:slashIdx]
104
+ + classNameForMethod = decodeClassNameSegment(rest[:slashIdx])
105
+ } else {
106
+ - classNameForMethod = rest
107
+ + classNameForMethod = decodeClassNameSegment(rest)
108
+ }
109
+ }
110
+ result.Method = opts.Method
111
+ @@ -227,7 +228,7 @@ func (c *Client) EditSourceWithOptions(ctx context.Context, objectURL, oldString
112
+ classesPrefix := "/sap/bc/adt/oo/classes/"
113
+ if strings.Contains(objectURL, classesPrefix) {
114
+ classStart := strings.Index(objectURL, classesPrefix) + len(classesPrefix)
115
+ - className = objectURL[classStart:includesIdx]
116
+ + className = decodeClassNameSegment(objectURL[classStart:includesIdx])
117
+ includeType = ClassIncludeType(objectURL[includesIdx+len("/includes/"):])
118
+ parentClassURL = objectURL[:includesIdx]
119
+ }
120
+ @@ -488,3 +489,14 @@ func (c *Client) EditSourceWithOptions(ctx context.Context, objectURL, oldString
121
+ }
122
+ return result, nil
123
+ }
124
+ +
125
+ +// decodeClassNameSegment turns the class-name path segment of an object URL
126
+ +// ("%2FABC%2FCL_TEST") into the raw name ("/ABC/CL_TEST"). Downstream helpers
127
+ +// (GetClassIncludeSourceURL, GetClassMethods, activation) escape the name
128
+ +// themselves, so passing the still-encoded segment would yield "%252F".
129
+ +func decodeClassNameSegment(segment string) string {
130
+ + if decoded, err := url.PathUnescape(segment); err == nil {
131
+ + return decoded
132
+ + }
133
+ + return segment
134
+ +}
@@ -33,7 +33,9 @@ async function main() {
33
33
  await mkdir(dirname(source), { recursive: true });
34
34
  await run('git', ['clone', '--filter=blob:none', upstream, source]);
35
35
  await run('git', ['-C', source, 'checkout', '--detach', commit]);
36
- await run('patch', ['-p1', '-i', join(root, 'patches', 'vsp-bas-proxy-auth.patch')], { cwd: source });
36
+ for (const patchFile of ['vsp-bas-proxy-auth.patch', 'vsp-namespaced-class-include-edit.patch']) {
37
+ await run('patch', ['-p1', '-i', join(root, 'patches', patchFile)], { cwd: source });
38
+ }
37
39
  await mkdir(dist, { recursive: true });
38
40
  const checksums = [];
39
41
  for (const [goos, goarch, os, arch, extension] of targets) {