@turingpulse/sdk 1.0.1

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 (160) hide show
  1. package/.github/dependabot.yml +38 -0
  2. package/.github/workflows/ci.yml +246 -0
  3. package/.github/workflows/framework-compat.yml +169 -0
  4. package/.github/workflows/security.yml +336 -0
  5. package/CHANGELOG.md +29 -0
  6. package/LICENSE +13 -0
  7. package/MIGRATION.md +30 -0
  8. package/README.md +221 -0
  9. package/dist/attachments.d.ts +28 -0
  10. package/dist/attachments.d.ts.map +1 -0
  11. package/dist/attachments.js +59 -0
  12. package/dist/attachments.js.map +1 -0
  13. package/dist/config.d.ts +72 -0
  14. package/dist/config.d.ts.map +1 -0
  15. package/dist/config.js +78 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/context.d.ts +126 -0
  18. package/dist/context.d.ts.map +1 -0
  19. package/dist/context.js +163 -0
  20. package/dist/context.js.map +1 -0
  21. package/dist/decorators.d.ts +6 -0
  22. package/dist/decorators.d.ts.map +1 -0
  23. package/dist/decorators.js +52 -0
  24. package/dist/decorators.js.map +1 -0
  25. package/dist/deploy.d.ts +89 -0
  26. package/dist/deploy.d.ts.map +1 -0
  27. package/dist/deploy.js +203 -0
  28. package/dist/deploy.js.map +1 -0
  29. package/dist/errors.d.ts +18 -0
  30. package/dist/errors.d.ts.map +1 -0
  31. package/dist/errors.js +34 -0
  32. package/dist/errors.js.map +1 -0
  33. package/dist/eventBuilder.d.ts +21 -0
  34. package/dist/eventBuilder.d.ts.map +1 -0
  35. package/dist/eventBuilder.js +127 -0
  36. package/dist/eventBuilder.js.map +1 -0
  37. package/dist/fingerprint.d.ts +158 -0
  38. package/dist/fingerprint.d.ts.map +1 -0
  39. package/dist/fingerprint.js +339 -0
  40. package/dist/fingerprint.js.map +1 -0
  41. package/dist/governance.d.ts +47 -0
  42. package/dist/governance.d.ts.map +1 -0
  43. package/dist/governance.js +104 -0
  44. package/dist/governance.js.map +1 -0
  45. package/dist/http.d.ts +62 -0
  46. package/dist/http.d.ts.map +1 -0
  47. package/dist/http.js +181 -0
  48. package/dist/http.js.map +1 -0
  49. package/dist/index.d.ts +15 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +23 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/instrumentation.d.ts +40 -0
  54. package/dist/instrumentation.d.ts.map +1 -0
  55. package/dist/instrumentation.js +31 -0
  56. package/dist/instrumentation.js.map +1 -0
  57. package/dist/integrations/mastra.d.ts +64 -0
  58. package/dist/integrations/mastra.d.ts.map +1 -0
  59. package/dist/integrations/mastra.js +256 -0
  60. package/dist/integrations/mastra.js.map +1 -0
  61. package/dist/kpi.d.ts +21 -0
  62. package/dist/kpi.d.ts.map +1 -0
  63. package/dist/kpi.js +83 -0
  64. package/dist/kpi.js.map +1 -0
  65. package/dist/llmDetector.d.ts +22 -0
  66. package/dist/llmDetector.d.ts.map +1 -0
  67. package/dist/llmDetector.js +269 -0
  68. package/dist/llmDetector.js.map +1 -0
  69. package/dist/plugin.d.ts +33 -0
  70. package/dist/plugin.d.ts.map +1 -0
  71. package/dist/plugin.js +312 -0
  72. package/dist/plugin.js.map +1 -0
  73. package/dist/registry.d.ts +13 -0
  74. package/dist/registry.d.ts.map +1 -0
  75. package/dist/registry.js +18 -0
  76. package/dist/registry.js.map +1 -0
  77. package/dist/tracing.d.ts +10 -0
  78. package/dist/tracing.d.ts.map +1 -0
  79. package/dist/tracing.js +30 -0
  80. package/dist/tracing.js.map +1 -0
  81. package/dist/triggerState.d.ts +5 -0
  82. package/dist/triggerState.d.ts.map +1 -0
  83. package/dist/triggerState.js +19 -0
  84. package/dist/triggerState.js.map +1 -0
  85. package/dist/utils.d.ts +27 -0
  86. package/dist/utils.d.ts.map +1 -0
  87. package/dist/utils.js +72 -0
  88. package/dist/utils.js.map +1 -0
  89. package/package.json +37 -0
  90. package/packages/anthropic/package.json +16 -0
  91. package/packages/anthropic/src/index.ts +5 -0
  92. package/packages/anthropic/src/wrapper.ts +102 -0
  93. package/packages/anthropic/tsconfig.build.json +20 -0
  94. package/packages/langchain/package.json +16 -0
  95. package/packages/langchain/src/index.ts +7 -0
  96. package/packages/langchain/src/wrapper.ts +51 -0
  97. package/packages/mastra/package.json +17 -0
  98. package/packages/mastra/src/index.ts +8 -0
  99. package/packages/mastra/src/wrapper.ts +301 -0
  100. package/packages/openai/package.json +16 -0
  101. package/packages/openai/src/index.ts +8 -0
  102. package/packages/openai/src/wrapper.ts +103 -0
  103. package/packages/openai/tsconfig.build.json +20 -0
  104. package/packages/openclaw/openclaw.plugin.json +100 -0
  105. package/packages/openclaw/package.json +41 -0
  106. package/packages/openclaw/src/buffer.ts +99 -0
  107. package/packages/openclaw/src/config.ts +139 -0
  108. package/packages/openclaw/src/hooks/governance.ts +267 -0
  109. package/packages/openclaw/src/hooks/lifecycle.ts +75 -0
  110. package/packages/openclaw/src/hooks/telemetry.ts +207 -0
  111. package/packages/openclaw/src/index.ts +91 -0
  112. package/packages/openclaw/src/mapper.ts +233 -0
  113. package/packages/openclaw/src/session-tracker.ts +181 -0
  114. package/packages/openclaw/src/types.ts +220 -0
  115. package/packages/openclaw/tests/buffer.test.ts +148 -0
  116. package/packages/openclaw/tests/config.test.ts +122 -0
  117. package/packages/openclaw/tests/governance.test.ts +232 -0
  118. package/packages/openclaw/tests/mapper.test.ts +242 -0
  119. package/packages/openclaw/tests/session-tracker.test.ts +124 -0
  120. package/packages/openclaw/tsconfig.json +18 -0
  121. package/packages/openclaw/vitest.config.ts +8 -0
  122. package/packages/vercel-ai/package.json +16 -0
  123. package/packages/vercel-ai/src/index.ts +5 -0
  124. package/packages/vercel-ai/src/wrapper.ts +49 -0
  125. package/scripts/bump-version.sh +58 -0
  126. package/scripts/update-readme-compat.mjs +151 -0
  127. package/src/__tests__/fingerprint.test.ts +328 -0
  128. package/src/attachments.ts +88 -0
  129. package/src/config.ts +164 -0
  130. package/src/context.ts +258 -0
  131. package/src/decorators.ts +61 -0
  132. package/src/deploy.ts +260 -0
  133. package/src/errors.ts +44 -0
  134. package/src/eventBuilder.ts +153 -0
  135. package/src/fingerprint.ts +421 -0
  136. package/src/governance.ts +156 -0
  137. package/src/http.ts +241 -0
  138. package/src/index.ts +57 -0
  139. package/src/instrumentation.ts +68 -0
  140. package/src/integrations/mastra.ts +335 -0
  141. package/src/kpi.ts +112 -0
  142. package/src/llmDetector.ts +330 -0
  143. package/src/plugin.ts +384 -0
  144. package/src/registry.ts +27 -0
  145. package/src/tracing.ts +39 -0
  146. package/src/triggerState.ts +27 -0
  147. package/src/utils.ts +78 -0
  148. package/tests/compat/anthropic.test.ts +61 -0
  149. package/tests/compat/cohere.test.ts +57 -0
  150. package/tests/compat/google-genai.test.ts +61 -0
  151. package/tests/compat/langchain-openai.test.ts +41 -0
  152. package/tests/compat/langchain.test.ts +64 -0
  153. package/tests/compat/mistral.test.ts +58 -0
  154. package/tests/compat/openai.test.ts +71 -0
  155. package/tests/compat/vercel-ai.test.ts +56 -0
  156. package/tests/plugins/anthropic-wrapper.test.ts +120 -0
  157. package/tests/plugins/langchain-wrapper.test.ts +128 -0
  158. package/tests/plugins/openai-wrapper.test.ts +165 -0
  159. package/tsconfig.json +21 -0
  160. package/vitest.config.ts +9 -0
@@ -0,0 +1,38 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "npm"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ day: "monday"
8
+ open-pull-requests-limit: 10
9
+ labels:
10
+ - "dependencies"
11
+ - "security"
12
+ commit-message:
13
+ prefix: "deps"
14
+ groups:
15
+ production-dependencies:
16
+ dependency-type: "production"
17
+ patterns:
18
+ - "*"
19
+ update-types:
20
+ - "patch"
21
+ - "minor"
22
+
23
+ - package-ecosystem: "docker"
24
+ directory: "/"
25
+ schedule:
26
+ interval: "weekly"
27
+ labels:
28
+ - "dependencies"
29
+ - "docker"
30
+ - "security"
31
+
32
+ - package-ecosystem: "github-actions"
33
+ directory: "/"
34
+ schedule:
35
+ interval: "weekly"
36
+ labels:
37
+ - "dependencies"
38
+ - "github-actions"
@@ -0,0 +1,246 @@
1
+ # CI + Publish for TypeScript SDK
2
+ name: CI
3
+
4
+ on:
5
+ push:
6
+ branches: [main]
7
+ pull_request:
8
+ branches: [main]
9
+ release:
10
+ types: [published]
11
+
12
+ jobs:
13
+ build:
14
+ name: Build and Lint
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ matrix:
18
+ node-version: ['18', '20']
19
+
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Set up Node.js ${{ matrix.node-version }}
24
+ uses: actions/setup-node@v4
25
+ with:
26
+ node-version: ${{ matrix.node-version }}
27
+
28
+ - name: Install dependencies
29
+ run: npm install
30
+
31
+ - name: Type check
32
+ run: npm run lint
33
+
34
+ - name: Build
35
+ run: npm run build
36
+
37
+ pre-publish-scan:
38
+ name: Pre-Publish Security Scan
39
+ runs-on: ubuntu-latest
40
+ if: github.event_name == 'release'
41
+ permissions:
42
+ contents: write
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ with:
46
+ fetch-depth: 0
47
+
48
+ # ── 1. Secret Detection (git history + filesystem) ──────────────
49
+ - name: Run TruffleHog secret scan
50
+ run: |
51
+ echo '.git/' > .trufflehog-exclude
52
+ docker run --rm -v "$PWD:/pwd" trufflesecurity/trufflehog:latest \
53
+ filesystem /pwd --exclude-paths=/pwd/.trufflehog-exclude --json > trufflehog-report.json 2>&1
54
+ SECRETS_FOUND=$(grep -c '"SourceMetadata"' trufflehog-report.json 2>/dev/null || echo "0")
55
+ if [ "$SECRETS_FOUND" -gt 0 ]; then
56
+ echo "::error::TruffleHog found ${SECRETS_FOUND} potential secrets — publish blocked"
57
+ cat trufflehog-report.json
58
+ exit 1
59
+ fi
60
+ echo "TruffleHog: no secrets detected"
61
+
62
+ # ── 2. Sensitive Pattern Scan (source code) ─────────────────────
63
+ - name: Scan source code for hardcoded secrets and sensitive patterns
64
+ run: |
65
+ PATTERNS=(
66
+ 'AKIA[0-9A-Z]{16}' # AWS Access Key ID
67
+ 'AIza[0-9A-Za-z\-_]{35}' # Google API Key
68
+ 'sk-[a-zA-Z0-9]{20,}' # OpenAI / Stripe secret key
69
+ 'ghp_[a-zA-Z0-9]{36}' # GitHub PAT
70
+ 'glpat-[a-zA-Z0-9\-]{20,}' # GitLab PAT
71
+ 'xox[bpors]-[a-zA-Z0-9\-]+' # Slack token
72
+ 'eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*' # JWT token
73
+ 'password\s*=\s*["\x27][^"\x27]{8,}' # Hardcoded passwords
74
+ 'mongodb(\+srv)?://[^\s]+' # MongoDB URIs
75
+ 'redis://[^\s]+' # Redis URIs
76
+ )
77
+ FOUND=0
78
+ for pattern in "${PATTERNS[@]}"; do
79
+ MATCHES=$(grep -rEn "$pattern" src/ packages/ --include="*.ts" --include="*.js" 2>/dev/null || true)
80
+ if [ -n "$MATCHES" ]; then
81
+ echo "::error::Sensitive pattern found: $pattern"
82
+ echo "$MATCHES"
83
+ FOUND=$((FOUND + 1))
84
+ fi
85
+ done
86
+ if [ "$FOUND" -gt 0 ]; then
87
+ echo "::error::Found $FOUND sensitive patterns in source — publish blocked"
88
+ exit 1
89
+ fi
90
+ echo "Source scan: no hardcoded secrets found"
91
+
92
+ - name: Set up Node.js
93
+ uses: actions/setup-node@v4
94
+ with:
95
+ node-version: '20'
96
+
97
+ - name: Set up Python (for Semgrep)
98
+ uses: actions/setup-python@v5
99
+ with:
100
+ python-version: '3.12'
101
+
102
+ - name: Install dependencies
103
+ run: npm install
104
+
105
+ # ── 3. SAST — Semgrep (TypeScript rules) ───────────────────────
106
+ - name: Run Semgrep SAST scan
107
+ run: |
108
+ pip install semgrep
109
+ semgrep --config=auto --config=p/typescript \
110
+ --severity ERROR \
111
+ --json --output=semgrep-report.json \
112
+ src/ packages/ 2>&1 || true
113
+ python3 -c '
114
+ import json, sys
115
+ try:
116
+ data = json.load(open("semgrep-report.json"))
117
+ errors = [r for r in data.get("results", []) if r.get("extra", {}).get("severity") == "ERROR"]
118
+ if errors:
119
+ for e in errors:
120
+ msg = e.get("extra", {}).get("message", "")[:120]
121
+ print(" " + e["path"] + ":" + str(e["start"]["line"]) + " - " + e["check_id"] + ": " + msg)
122
+ sys.exit(1)
123
+ except Exception as e:
124
+ print("Semgrep parse warning: " + str(e))
125
+ ' || { echo "::error::Semgrep found ERROR-level issues — publish blocked"; exit 1; }
126
+ echo "Semgrep SAST: no error-level issues"
127
+
128
+ # ── 4. Dependency CVE Audit (HARD GATE) ─────────────────────────
129
+ - name: Run npm audit (hard gate on high/critical)
130
+ run: |
131
+ npm audit --json > npm-audit-report.json 2>&1 || true
132
+ VULNS=$(node -e "
133
+ const r = require('./npm-audit-report.json');
134
+ const meta = r.metadata?.vulnerabilities || {};
135
+ const high = (meta.high || 0) + (meta.critical || 0);
136
+ console.log(high);
137
+ " 2>/dev/null || echo "0")
138
+ if [ "$VULNS" -gt 0 ]; then
139
+ echo "::error::npm audit found ${VULNS} high/critical vulnerabilities — publish blocked"
140
+ npm audit --audit-level=high || true
141
+ exit 1
142
+ fi
143
+ echo "npm audit: no high/critical vulnerabilities"
144
+
145
+ # ── 5. License Compliance ───────────────────────────────────────
146
+ - name: Check dependency licenses
147
+ run: |
148
+ npx license-checker --json --out licenses.json
149
+ npx license-checker --summary
150
+ BLOCKED=$(npx license-checker --failOn \
151
+ 'GPL-2.0;GPL-3.0;AGPL-1.0;AGPL-3.0;SSPL-1.0;LGPL-2.0;LGPL-2.1;LGPL-3.0;GPL-2.0-only;GPL-3.0-only;AGPL-3.0-only' \
152
+ 2>&1 || true)
153
+ if echo "$BLOCKED" | grep -q "Found restricted license"; then
154
+ echo "::error::Copyleft-licensed dependencies found — publish blocked for enterprise safety"
155
+ echo "$BLOCKED"
156
+ exit 1
157
+ fi
158
+ echo "License check: all dependencies have permissive licenses"
159
+
160
+ # ── 6. Publish Payload Deep Inspection ──────────────────────────
161
+ - name: Inspect npm pack contents for sensitive data
162
+ run: |
163
+ npm pack --dry-run 2>&1 | tee pack-listing.txt
164
+ echo "--- Checking file listing ---"
165
+ SENSITIVE_FILES=$(grep -iE \
166
+ '\.env|\.pem|\.key|\.p12|\.pfx|\.jks|credentials|secret|service.account|\.sqlite|\.db$' \
167
+ pack-listing.txt || true)
168
+ if [ -n "$SENSITIVE_FILES" ]; then
169
+ echo "::error::Sensitive files in publish payload — publish blocked:"
170
+ echo "$SENSITIVE_FILES"
171
+ exit 1
172
+ fi
173
+ echo "--- Packing and scanning content ---"
174
+ TARBALL=$(npm pack 2>/dev/null)
175
+ EXTRACT_DIR=$(mktemp -d)
176
+ tar xzf "$TARBALL" -C "$EXTRACT_DIR"
177
+ CONTENT_SECRETS=$(grep -rEn \
178
+ 'AKIA[0-9A-Z]{16}|sk-[a-zA-Z0-9]{20,}|password\s*=\s*["\x27][^"\x27]{8,}|BEGIN (RSA |EC |DSA )?PRIVATE KEY' \
179
+ "$EXTRACT_DIR" --include="*.js" --include="*.ts" --include="*.json" 2>/dev/null || true)
180
+ if [ -n "$CONTENT_SECRETS" ]; then
181
+ echo "::error::Secrets found inside packed artifact content — publish blocked:"
182
+ echo "$CONTENT_SECRETS"
183
+ exit 1
184
+ fi
185
+ rm -rf "$EXTRACT_DIR" "$TARBALL"
186
+ echo "Payload inspection: clean"
187
+
188
+ # ── 7. SBOM Generation ─────────────────────────────────────────
189
+ - name: Generate SBOM (CycloneDX)
190
+ run: npx @cyclonedx/cyclonedx-npm --output-file sbom.json --output-format JSON
191
+
192
+ - name: Upload security reports
193
+ uses: actions/upload-artifact@v4
194
+ if: always()
195
+ with:
196
+ name: security-reports
197
+ path: |
198
+ trufflehog-report.json
199
+ semgrep-report.json
200
+ npm-audit-report.json
201
+ licenses.json
202
+ sbom.json
203
+ retention-days: 90
204
+
205
+ - name: Attach SBOM to release
206
+ if: success()
207
+ run: gh release upload "${{ github.ref_name }}" sbom.json --clobber
208
+ env:
209
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
210
+
211
+ publish:
212
+ name: Publish to npm
213
+ runs-on: ubuntu-latest
214
+ needs: [build, pre-publish-scan]
215
+ if: github.event_name == 'release'
216
+ permissions:
217
+ contents: read
218
+ id-token: write
219
+ steps:
220
+ - uses: actions/checkout@v4
221
+
222
+ - name: Set up Node.js
223
+ uses: actions/setup-node@v4
224
+ with:
225
+ node-version: '20'
226
+ registry-url: 'https://registry.npmjs.org'
227
+
228
+ - name: Install and build
229
+ run: npm install && npm run build
230
+
231
+ - name: Publish core package
232
+ run: npm publish --access public
233
+ env:
234
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
235
+
236
+ - name: Publish satellite packages
237
+ run: |
238
+ for pkg_dir in packages/*/; do
239
+ if [ -f "${pkg_dir}package.json" ]; then
240
+ PKG_NAME=$(node -e "console.log(require('./${pkg_dir}package.json').name)")
241
+ echo "Publishing ${PKG_NAME} from ${pkg_dir}..."
242
+ (cd "$pkg_dir" && npm publish --access public) || echo "WARN: ${PKG_NAME} publish failed"
243
+ fi
244
+ done
245
+ env:
246
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -0,0 +1,169 @@
1
+ # Framework Compatibility Matrix
2
+ # Tests the SDK against multiple versions of every supported LLM framework.
3
+ # Results are published as workflow summary + auto-update README badges/table.
4
+ name: Framework Compatibility
5
+
6
+ on:
7
+ schedule:
8
+ - cron: '0 6 * * *' # Daily 6am UTC
9
+ workflow_dispatch:
10
+ push:
11
+ branches: [main]
12
+ paths:
13
+ - 'src/fingerprint.ts'
14
+ - 'src/llmDetector.ts'
15
+ - 'tests/compat/**'
16
+ - '.github/workflows/framework-compat.yml'
17
+ pull_request:
18
+ branches: [main]
19
+ paths:
20
+ - 'src/fingerprint.ts'
21
+ - 'src/llmDetector.ts'
22
+ - 'tests/compat/**'
23
+
24
+ jobs:
25
+ compat-test:
26
+ name: "${{ matrix.framework }} ${{ matrix.version }} (node ${{ matrix.node-version }})"
27
+ runs-on: ubuntu-latest
28
+ strategy:
29
+ fail-fast: false
30
+ matrix:
31
+ node-version: ['18', '20', '22']
32
+ include:
33
+ # OpenAI
34
+ - { framework: openai, package: openai, version: '4.0.0', test-file: openai, node-version: '18' }
35
+ - { framework: openai, package: openai, version: '4.0.0', test-file: openai, node-version: '20' }
36
+ - { framework: openai, package: openai, version: latest, test-file: openai, node-version: '18' }
37
+ - { framework: openai, package: openai, version: latest, test-file: openai, node-version: '20' }
38
+ - { framework: openai, package: openai, version: latest, test-file: openai, node-version: '22' }
39
+ # Anthropic
40
+ - { framework: anthropic, package: '@anthropic-ai/sdk', version: '0.20.0', test-file: anthropic, node-version: '18' }
41
+ - { framework: anthropic, package: '@anthropic-ai/sdk', version: '0.20.0', test-file: anthropic, node-version: '20' }
42
+ - { framework: anthropic, package: '@anthropic-ai/sdk', version: latest, test-file: anthropic, node-version: '18' }
43
+ - { framework: anthropic, package: '@anthropic-ai/sdk', version: latest, test-file: anthropic, node-version: '20' }
44
+ - { framework: anthropic, package: '@anthropic-ai/sdk', version: latest, test-file: anthropic, node-version: '22' }
45
+ # Google GenAI
46
+ - { framework: google-genai, package: '@google/generative-ai', version: '0.7.0', test-file: google-genai, node-version: '18' }
47
+ - { framework: google-genai, package: '@google/generative-ai', version: '0.7.0', test-file: google-genai, node-version: '20' }
48
+ - { framework: google-genai, package: '@google/generative-ai', version: latest, test-file: google-genai, node-version: '18' }
49
+ - { framework: google-genai, package: '@google/generative-ai', version: latest, test-file: google-genai, node-version: '20' }
50
+ - { framework: google-genai, package: '@google/generative-ai', version: latest, test-file: google-genai, node-version: '22' }
51
+ # LangChain
52
+ - { framework: langchain, package: '@langchain/core', version: '0.1.0', test-file: langchain, node-version: '18' }
53
+ - { framework: langchain, package: '@langchain/core', version: '0.1.0', test-file: langchain, node-version: '20' }
54
+ - { framework: langchain, package: '@langchain/core', version: latest, test-file: langchain, node-version: '18' }
55
+ - { framework: langchain, package: '@langchain/core', version: latest, test-file: langchain, node-version: '20' }
56
+ - { framework: langchain, package: '@langchain/core', version: latest, test-file: langchain, node-version: '22' }
57
+ # LangChain-OpenAI
58
+ - { framework: langchain-openai, package: '@langchain/openai', version: '0.0.14', test-file: langchain-openai, node-version: '18' }
59
+ - { framework: langchain-openai, package: '@langchain/openai', version: '0.0.14', test-file: langchain-openai, node-version: '20' }
60
+ - { framework: langchain-openai, package: '@langchain/openai', version: latest, test-file: langchain-openai, node-version: '18' }
61
+ - { framework: langchain-openai, package: '@langchain/openai', version: latest, test-file: langchain-openai, node-version: '20' }
62
+ - { framework: langchain-openai, package: '@langchain/openai', version: latest, test-file: langchain-openai, node-version: '22' }
63
+ # Vercel AI SDK
64
+ - { framework: vercel-ai, package: ai, version: '3.0.0', test-file: vercel-ai, node-version: '18' }
65
+ - { framework: vercel-ai, package: ai, version: '3.0.0', test-file: vercel-ai, node-version: '20' }
66
+ - { framework: vercel-ai, package: ai, version: latest, test-file: vercel-ai, node-version: '18' }
67
+ - { framework: vercel-ai, package: ai, version: latest, test-file: vercel-ai, node-version: '20' }
68
+ - { framework: vercel-ai, package: ai, version: latest, test-file: vercel-ai, node-version: '22' }
69
+ # Cohere
70
+ - { framework: cohere, package: cohere-ai, version: '7.0.0', test-file: cohere, node-version: '18' }
71
+ - { framework: cohere, package: cohere-ai, version: '7.0.0', test-file: cohere, node-version: '20' }
72
+ - { framework: cohere, package: cohere-ai, version: latest, test-file: cohere, node-version: '18' }
73
+ - { framework: cohere, package: cohere-ai, version: latest, test-file: cohere, node-version: '20' }
74
+ - { framework: cohere, package: cohere-ai, version: latest, test-file: cohere, node-version: '22' }
75
+ # Mistral
76
+ - { framework: mistral, package: '@mistralai/mistralai', version: '0.1.0', test-file: mistral, node-version: '18' }
77
+ - { framework: mistral, package: '@mistralai/mistralai', version: '0.1.0', test-file: mistral, node-version: '20' }
78
+ - { framework: mistral, package: '@mistralai/mistralai', version: latest, test-file: mistral, node-version: '18' }
79
+ - { framework: mistral, package: '@mistralai/mistralai', version: latest, test-file: mistral, node-version: '20' }
80
+ - { framework: mistral, package: '@mistralai/mistralai', version: latest, test-file: mistral, node-version: '22' }
81
+
82
+ steps:
83
+ - uses: actions/checkout@v4
84
+
85
+ - name: Set up Node.js ${{ matrix.node-version }}
86
+ uses: actions/setup-node@v4
87
+ with:
88
+ node-version: ${{ matrix.node-version }}
89
+
90
+ - name: Install SDK
91
+ run: npm install
92
+
93
+ - name: Install framework
94
+ run: |
95
+ if [ "${{ matrix.version }}" = "latest" ]; then
96
+ npm install "${{ matrix.package }}"
97
+ else
98
+ npm install "${{ matrix.package }}@${{ matrix.version }}"
99
+ fi
100
+
101
+ - name: Get installed version
102
+ id: fwver
103
+ run: |
104
+ VER=$(npm list "${{ matrix.package }}" --depth=0 --json 2>/dev/null | node -e "const d=require('fs').readFileSync('/dev/stdin','utf8');const j=JSON.parse(d);const deps={...j.dependencies,...j.devDependencies};const pkg='${{ matrix.package }}';console.log(deps[pkg]?.version||'unknown')")
105
+ echo "installed_version=$VER" >> "$GITHUB_OUTPUT"
106
+
107
+ - name: Run compat tests
108
+ id: test
109
+ run: |
110
+ npx vitest run tests/compat/${{ matrix.test-file }}.test.ts --reporter=verbose 2>&1 | tee test-output.txt
111
+ echo "exit_code=${PIPESTATUS[0]}" >> "$GITHUB_OUTPUT"
112
+
113
+ - name: Write result
114
+ if: always()
115
+ run: |
116
+ mkdir -p results
117
+ cat > results/${{ matrix.framework }}-${{ matrix.version }}-node${{ matrix.node-version }}.json <<RESEOF
118
+ {
119
+ "framework": "${{ matrix.framework }}",
120
+ "package": "${{ matrix.package }}",
121
+ "requested_version": "${{ matrix.version }}",
122
+ "installed_version": "${{ steps.fwver.outputs.installed_version }}",
123
+ "node_version": "${{ matrix.node-version }}",
124
+ "passed": ${{ steps.test.outcome == 'success' }}
125
+ }
126
+ RESEOF
127
+
128
+ - name: Upload result
129
+ if: always()
130
+ uses: actions/upload-artifact@v4
131
+ with:
132
+ name: compat-${{ matrix.framework }}-${{ matrix.version }}-node${{ matrix.node-version }}
133
+ path: results/
134
+ retention-days: 7
135
+
136
+ update-readme:
137
+ name: Update README
138
+ needs: [compat-test]
139
+ if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
140
+ runs-on: ubuntu-latest
141
+ permissions:
142
+ contents: write
143
+ steps:
144
+ - uses: actions/checkout@v4
145
+
146
+ - name: Download all results
147
+ uses: actions/download-artifact@v4
148
+ with:
149
+ pattern: compat-*
150
+ path: all-results/
151
+ merge-multiple: true
152
+
153
+ - name: Set up Node.js
154
+ uses: actions/setup-node@v4
155
+ with:
156
+ node-version: '20'
157
+
158
+ - name: Generate README sections
159
+ run: node scripts/update-readme-compat.mjs all-results/ README.md
160
+
161
+ - name: Commit if changed
162
+ run: |
163
+ git diff --quiet README.md || {
164
+ git config user.name "github-actions[bot]"
165
+ git config user.email "github-actions[bot]@users.noreply.github.com"
166
+ git add README.md
167
+ git commit -m "docs: update framework compatibility matrix [skip ci]"
168
+ git push
169
+ }