@viveka10/cap-ai-token-optimizer 0.1.0 → 0.1.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.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.1] - 2026-10-10
10
+
11
+ ### Added
12
+
13
+ - Guide "Add to an existing CAP app on SAP BTP" (`docs/existing-cap-app-on-btp.md`): AI Core
14
+ service binding, `mta.yaml`, secrets, HANA usage log, admin role, and SAP Cloud ALM setup.
15
+
16
+ ### Changed
17
+
18
+ - Package description, keywords and README introduction, so the package is easier to find.
19
+
9
20
  ## [0.1.0] - 2026-10-10
10
21
 
11
22
  First public release.
@@ -67,5 +78,6 @@ First public release.
67
78
  - The `http` exporter supports Internet destinations only.
68
79
  - Not yet verified against SAP Cloud ALM; live AI Core tests are opt-in.
69
80
 
70
- [Unreleased]: https://github.com/viveka10/npm_token_optimizer/compare/v0.1.0...HEAD
81
+ [Unreleased]: https://github.com/viveka10/npm_token_optimizer/compare/v0.1.1...HEAD
82
+ [0.1.1]: https://github.com/viveka10/npm_token_optimizer/compare/v0.1.0...v0.1.1
71
83
  [0.1.0]: https://github.com/viveka10/npm_token_optimizer/releases/tag/v0.1.0
package/README.md CHANGED
@@ -5,7 +5,12 @@
5
5
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/viveka10/npm_token_optimizer/blob/main/cap-ai-token-optimizer/LICENSE)
6
6
  ![Node](https://img.shields.io/node/v/@viveka10/cap-ai-token-optimizer)
7
7
 
8
- Reduce, measure and report the tokens your SAP CAP Node.js app spends on SAP AI Core.
8
+ **SAP CAP plugin** that reduces, measures and reports the LLM tokens your SAP CAP Node.js app
9
+ spends on **SAP AI Core**, and with them your generative AI costs.
10
+
11
+ ```sh
12
+ npm add @viveka10/cap-ai-token-optimizer
13
+ ```
9
14
 
10
15
  - **Optimize** prompts without changing what they mean: whitespace and JSON, duplicate
11
16
  instructions, long histories, large tool lists, output limits, and an exact-match response cache.
@@ -20,6 +25,8 @@ Node.js. Wraps the SAP Cloud SDK for AI (`@sap-ai-sdk/orchestration`, `@sap-ai-s
20
25
  > **Status: pre-release.** Not affiliated with or endorsed by SAP.
21
26
 
22
27
  **New here?** [Add it to an existing CAP app in 5 minutes](https://github.com/viveka10/npm_token_optimizer/blob/main/cap-ai-token-optimizer/docs/integration-guide.md): no code changes needed.
28
+ Deploying on SAP BTP with an AI Core binding and SAP Cloud ALM? See
29
+ [Existing CAP app on SAP BTP](https://github.com/viveka10/npm_token_optimizer/blob/main/cap-ai-token-optimizer/docs/existing-cap-app-on-btp.md).
23
30
 
24
31
  **Contents:** [Requirements](#requirements) · [Setup](#setup) · [Usage](#usage) ·
25
32
  [Existing code and LangChain](#instrumenting-existing-code-and-langchain) · [Compatibility](#compatibility) ·
@@ -0,0 +1,425 @@
1
+ # Add @viveka10/cap-ai-token-optimizer to an existing CAP app on SAP BTP
2
+
3
+ This guide is for a CAP Node.js app on SAP BTP Cloud Foundry that already calls SAP AI Core
4
+ through the SAP Cloud SDK for AI (`@sap-ai-sdk/*`) with an **AI Core service binding**. It
5
+ covers the changes to the app, deployment (`mta.yaml`, `xs-security.json`) and SAP Cloud ALM.
6
+
7
+ **What stays the same**
8
+
9
+ - **AI Core binding:** no change. The SDK keeps reading it from `VCAP_SERVICES`.
10
+ - **AI code:** no change needed. Automatic instrumentation measures the existing calls.
11
+ - **Prompts:** you start in `shadow` mode, which sends your original prompts unchanged.
12
+
13
+ **Contents**
14
+
15
+ 1. [Check the prerequisites](#1-check-the-prerequisites)
16
+ 2. [Install the package](#2-install-the-package)
17
+ 3. [Configure it](#3-configure-it)
18
+ 4. [Code changes (optional)](#4-code-changes-optional)
19
+ 5. [Local testing with the AI Core binding](#5-local-testing-with-the-ai-core-binding)
20
+ 6. [Secrets and environment](#6-secrets-and-environment)
21
+ 7. [Usage log in SAP HANA (optional)](#7-usage-log-in-sap-hana-optional)
22
+ 8. [Admin service and roles (optional)](#8-admin-service-and-roles-optional)
23
+ 9. [SAP Cloud ALM](#9-sap-cloud-alm)
24
+ 10. [Deploy and verify](#10-deploy-and-verify)
25
+ 11. [Switch from shadow to active](#11-switch-from-shadow-to-active)
26
+ 12. [Turn it off or roll back](#12-turn-it-off-or-roll-back)
27
+
28
+ ---
29
+
30
+ ## 1. Check the prerequisites
31
+
32
+ In the app's root folder:
33
+
34
+ ```sh
35
+ node --version
36
+ npm ls @sap/cds @sap-ai-sdk/orchestration @sap-ai-sdk/foundation-models @sap-ai-sdk/langchain
37
+ ```
38
+
39
+ | Requirement | Why |
40
+ |---|---|
41
+ | Node.js **22.12 or later**, locally and on Cloud Foundry | The SAP Cloud SDK for AI is ESM-only; Node 22.12+ can load it from CommonJS. |
42
+ | `"engines": { "node": ">=22.12" }` in the app's `package.json` | The Cloud Foundry Node.js buildpack picks the Node version from `engines`. |
43
+ | `@sap/cds` 9 or 10 | Tested versions. |
44
+ | `@sap-ai-sdk/*` **2.8 or later**, all packages on the **same** version, each listed **once** | The packages share internal APIs. Automatic instrumentation only hooks the copy resolved from the app root. If `npm ls` shows nested copies, run `npm dedupe` or align the versions. |
45
+
46
+ ## 2. Install the package
47
+
48
+ ```sh
49
+ npm add @viveka10/cap-ai-token-optimizer
50
+ ```
51
+
52
+ It is a CAP plugin, so there's nothing to register: CAP loads it at startup.
53
+
54
+ ## 3. Configure it
55
+
56
+ Add the `tokenOptimizer` block to `cds.requires` in the app's `package.json` (or `.cdsrc.json`).
57
+ This starting configuration measures everything without changing any AI call:
58
+
59
+ ```json
60
+ {
61
+ "cds": {
62
+ "requires": {
63
+ "tokenOptimizer": {
64
+ "mode": "shadow",
65
+ "autoInstrument": true,
66
+ "pricing": {
67
+ "gpt-4.1": { "inputPer1k": 0.0, "outputPer1k": 0.0 }
68
+ },
69
+ "metrics": { "exporters": ["console"] },
70
+ "[production]": {
71
+ "metrics": { "exporters": ["console", "otel"] },
72
+ "admin": { "enabled": true }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ | Setting | What it does |
81
+ |---|---|
82
+ | `mode: "shadow"` | Runs the optimizer and records what it *would* save, but sends the original prompts. |
83
+ | `autoInstrument: true` | Hooks the SDK's `OrchestrationClient` and `AzureOpenAiChatClient`, so existing calls are measured without code changes. |
84
+ | `pricing` | Price per 1k tokens per model, from your SAP contract. Leave it out if you don't need cost estimates. |
85
+ | `metrics.exporters` | Where events go. `console` writes one JSON line per AI call to the app log (`cf logs`). `otel` sends OpenTelemetry metrics and spans (see [SAP Cloud ALM](#9-sap-cloud-alm)). `db` writes a usage table (see [step 7](#7-usage-log-in-sap-hana-optional)). |
86
+ | `admin.enabled` | Serves the read-only statistics service at `/odata/v4/token-optimizer` (see [step 8](#8-admin-service-and-roles-optional)). |
87
+
88
+ All options are described in the [configuration reference](https://github.com/viveka10/npm_token_optimizer/blob/main/cap-ai-token-optimizer/README.md#configuration-reference).
89
+
90
+ ## 4. Code changes (optional)
91
+
92
+ With `autoInstrument: true`, no code change is needed. All hooked calls are recorded under
93
+ the use case `default`. These optional changes give you better reporting and per-use-case
94
+ settings:
95
+
96
+ **Name the use cases** where your handlers call AI Core:
97
+
98
+ ```js
99
+ const { optimizer } = require('@viveka10/cap-ai-token-optimizer')
100
+
101
+ this.on('summarizeTicket', req =>
102
+ optimizer.withUseCase('ticket-summary', () => this.summarize(req.data.ID)))
103
+ ```
104
+
105
+ **LangChain models** from `@sap-ai-sdk/langchain`: wrap them once where you create them:
106
+
107
+ ```js
108
+ const model = optimizer.wrapLangChain(new OrchestrationClient(config), { useCase: 'support-agent' })
109
+ ```
110
+
111
+ **Better error responses** (optional): the SDK's errors are passed through unchanged, and
112
+ `classifyError` tells you what happened:
113
+
114
+ ```js
115
+ const { classifyError } = require('@viveka10/cap-ai-token-optimizer')
116
+ try { /* AI call */ } catch (err) {
117
+ const { category } = classifyError(err) // RATE_LIMIT, CONTENT_FILTER, CONTEXT_LENGTH, TIMEOUT, …
118
+ return req.reject(category === 'RATE_LIMIT' ? 429 : 502, `AI service error: ${category}`)
119
+ }
120
+ ```
121
+
122
+ Use cases can then get their own settings, for example
123
+ `"useCases": { "ticket-summary": { "steps": { "outputCap": { "default": 300 } } } }`.
124
+
125
+ ## 5. Local testing with the AI Core binding
126
+
127
+ Nothing changes in how the app gets its AI Core credentials. The SDK reads the `aicore` binding
128
+ from `VCAP_SERVICES`. If you already test locally with `cds bind`, keep doing that:
129
+
130
+ ```sh
131
+ cf login …
132
+ cds bind aicore --to <your-aicore-instance>:<service-key> # once; writes .cdsrc-private.json (keep it out of git)
133
+ cds bind --exec -- cds watch --profile hybrid # VCAP_SERVICES is set for the SDK
134
+ ```
135
+
136
+ Call the feature that uses AI Core. The console shows one line per call:
137
+
138
+ ```json
139
+ {"type":"ai-core-call","useCase":"default","mode":"shadow","model":"gpt-4.1",
140
+ "tokens":{"promptEstimatedBefore":2015,"promptEstimatedAfter":805,"prompt":2010,"completion":41,…},
141
+ "savings":{"estimatedTokens":1210,"byStep":{"history":774,"dedupe":340,…},…},"status":"success",…}
142
+ ```
143
+
144
+ `savings` shows what `active` mode would have saved on that call.
145
+
146
+ ## 6. Secrets and environment
147
+
148
+ **User-id hash salt.** User ids are recorded as a hash. Set a random salt per landscape, but
149
+ **not** in `package.json` or `mta.yaml` if they are in git. Use an MTA extension descriptor that
150
+ you keep out of git:
151
+
152
+ ```yaml
153
+ # secrets.mtaext (do not commit)
154
+ _schema-version: '3.1'
155
+ ID: my-cap-app.secrets
156
+ extends: my-cap-app
157
+ modules:
158
+ - name: my-cap-app-srv
159
+ properties:
160
+ cds_requires_tokenOptimizer_metrics_userHashSalt: <long random string>
161
+ ```
162
+
163
+ ```sh
164
+ cf deploy mta_archives/my-cap-app_1.0.0.mtar -e secrets.mtaext
165
+ ```
166
+
167
+ **Overriding settings without a rebuild.** Any setting can be overridden with an environment
168
+ variable in the same format, for example `cds_requires_tokenOptimizer_mode=off`, followed by
169
+ `cf restart`.
170
+
171
+ Never set `captureContent: true` in production. It adds prompt and answer text to events.
172
+
173
+ ## 7. Usage log in SAP HANA (optional)
174
+
175
+ To keep one row per AI call in the app's database (for reporting or your own analytics), add
176
+ the `db` exporter:
177
+
178
+ ```json
179
+ "[production]": { "metrics": { "exporters": ["console", "otel", "db"] }, "admin": { "enabled": true } }
180
+ ```
181
+
182
+ - The plugin adds the entity `cap.ai.token_optimizer.TokenUsageLog` to your model. It is
183
+ deployed with your normal HANA deployment (the `db-deployer` module in the MTA), so there's
184
+ no extra step.
185
+ - **Multitenant apps (MTX):** each tenant's rows go to that tenant's container. Run your
186
+ usual tenant upgrade after deploying, so existing tenants get the new table.
187
+ - Rows older than 30 days are deleted (`metrics.db.retentionDays`). No prompt or answer text
188
+ is stored.
189
+ - With the admin service enabled, the rows are readable at `/odata/v4/token-optimizer/UsageLog`.
190
+ - To expose the table in your own service:
191
+ ```cds
192
+ using { cap.ai.token_optimizer.TokenUsageLog } from '@viveka10/cap-ai-token-optimizer/db/token-usage-log';
193
+ service ReportingService { @readonly entity AiUsage as projection on TokenUsageLog; }
194
+ ```
195
+
196
+ > The usage log has been tested with SQLite. It hasn't been tested on SAP HANA or with MTX
197
+ > yet, so check it in a development space first.
198
+
199
+ ## 8. Admin service and roles (optional)
200
+
201
+ With `admin.enabled`, the app serves `/odata/v4/token-optimizer`:
202
+
203
+ | Path | Content |
204
+ |---|---|
205
+ | `summary()` | totals, mode, latency percentiles |
206
+ | `UseCases`, `Models`, `ErrorCategories`, `StepSavings`, `PromptPrefixChanges`, `Exporters` | statistics of the app instance that answers (in memory, since its start) |
207
+ | `UsageLog` | the usage table, when the `db` exporter is on |
208
+
209
+ It requires the role `TokenOptimizerAdmin` (configurable with `admin.role`). Add it to
210
+ `xs-security.json`:
211
+
212
+ ```json
213
+ {
214
+ "scopes": [
215
+ { "name": "$XSAPPNAME.TokenOptimizerAdmin", "description": "Read AI token usage statistics" }
216
+ ],
217
+ "role-templates": [
218
+ { "name": "TokenOptimizerAdmin", "scope-references": ["$XSAPPNAME.TokenOptimizerAdmin"] }
219
+ ],
220
+ "role-collections": [
221
+ { "name": "AI_Token_Optimizer_Admin", "role-template-references": ["$XSAPPNAME.TokenOptimizerAdmin"] }
222
+ ]
223
+ }
224
+ ```
225
+
226
+ Merge this into your existing file; don't replace it. After deploying, assign the role
227
+ collection to the right users in the BTP cockpit (Security → Role Collections).
228
+
229
+ ## 9. SAP Cloud ALM
230
+
231
+ The optimizer has no Cloud ALM-specific code. Its `otel` exporter writes OpenTelemetry metrics
232
+ and one span per AI call through whatever OpenTelemetry setup the app has. For Cloud ALM, that
233
+ setup is SAP's Cloud ALM agent plus `@cap-js/telemetry`. The agent setup below follows SAP's
234
+ documentation:
235
+ [Data Collection Infrastructure](https://support.sap.com/en/alm/sap-cloud-alm/operations/expert-portal/data-collection-infrastructure.html) and
236
+ [Auto-instrumentation for Node.js](https://support.sap.com/en/alm/sap-cloud-alm/operations/expert-portal/data-collection-infrastructure/autoinstrumentation-nodejs.html).
237
+ Check those pages for changes before you start.
238
+
239
+ ### 9.1 Prerequisites
240
+
241
+ - An SAP Cloud ALM tenant, with the **SAP Cloud ALM API** enabled and a service key for it
242
+ ([Enabling SAP Cloud ALM API](https://help.sap.com/docs/cloud-alm/setup-administration/enabling-sap-cloud-alm-api)).
243
+ - A technical user for SAP's **Repository Based Shipment Channel** (RBSC), which distributes
244
+ the agent. Request it at https://ui.repositories.cloud.sap/www/webapp/users. The agent isn't
245
+ on the public npm registry.
246
+
247
+ ### 9.2 Get access to SAP's package repository
248
+
249
+ Set `SAP_NPM_AUTH` to the "NPM Base64 Credentials" of the technical user (`base64(user:password)`),
250
+ in your shell and in your CI/build pipeline (as a secret), and add to the app's `.npmrc`:
251
+
252
+ ```
253
+ //73555000100200018064.npmsrv.cdn.repositories.cloud.sap/:_auth=${SAP_NPM_AUTH}
254
+ ```
255
+
256
+ ### 9.3 Add the agent and @cap-js/telemetry
257
+
258
+ In the app's `package.json`:
259
+
260
+ ```json
261
+ {
262
+ "dependencies": {
263
+ "@sap/xotel-agent-ext-js": "https://73555000100200018064.npmsrv.cdn.repositories.cloud.sap/@sap/xotel-agent-ext-js/-/xotel-agent-ext-js-2.0.4.tgz",
264
+ "@cap-js/telemetry": "^2.1.0"
265
+ },
266
+ "scripts": {
267
+ "start": "node ${NODE_ARGS} ./node_modules/.bin/cds-serve"
268
+ }
269
+ }
270
+ ```
271
+
272
+ - **Agent version:** 2.0.4 or later. That is the version from which `@cap-js/telemetry`
273
+ supports it, and it uses OpenTelemetry 2.x.
274
+ - **`@cap-js/telemetry` version:** 2.1.0 or later. It detects the agent and adds its span
275
+ processor, metric reader and log processor to the agent's pipeline instead of starting a
276
+ second OpenTelemetry SDK. Version 2.0.x doesn't have this integration.
277
+ - **Start script:** loads the agent before CAP via `NODE_ARGS` (set in `mta.yaml` below).
278
+ After `cds build`, check that `gen/srv/package.json` contains this start script.
279
+ - **Dependency conflicts:** SAP notes that the agent's OpenTelemetry 2.x libraries can
280
+ conflict with other OpenTelemetry packages in the app. `@viveka10/cap-ai-token-optimizer`
281
+ itself only uses `@opentelemetry/api`.
282
+
283
+ ### 9.4 Enable the otel exporter
284
+
285
+ ```json
286
+ "tokenOptimizer": { "[production]": { "metrics": { "exporters": ["console", "otel"] } } }
287
+ ```
288
+
289
+ ### 9.5 mta.yaml
290
+
291
+ ```yaml
292
+ modules:
293
+ - name: my-cap-app-srv
294
+ type: nodejs
295
+ path: gen/srv
296
+ properties:
297
+ SAP_CALM_SERVICE_NAME: my-cap-app-srv # name shown in Cloud ALM
298
+ SAP_CALM_SERVICE_TYPE: SAP_CP_CF
299
+ NODE_ARGS: -r @sap/xotel-agent-ext-js
300
+ requires:
301
+ - name: my-cap-app-aicore # existing AI Core binding, unchanged
302
+ - name: my-cap-app-auth # existing XSUAA
303
+ - name: my-cap-app-db # existing, only needed for the db exporter
304
+ - name: my-cap-app-destination # new: used by the Cloud ALM agent
305
+
306
+ resources:
307
+ - name: my-cap-app-destination
308
+ type: org.cloudfoundry.managed-service
309
+ parameters:
310
+ service: destination
311
+ service-plan: lite
312
+ ```
313
+
314
+ **Staging needs the agent's repository.** Cloud Foundry installs dependencies during staging,
315
+ so it has to reach SAP's repository too. SAP suggests, if staging fails, shipping
316
+ `node_modules` and `package-lock.json` inside the MTA archive: remove them from the module's
317
+ `build-parameters.ignore` list, and install them into `gen/srv` with a `before-all` custom
318
+ build step (`npm install --production` and `npm install --prefix ./gen/srv`).
319
+
320
+ ### 9.6 Destination for Cloud ALM
321
+
322
+ In the **provider subaccount** (BTP cockpit → Connectivity → Destinations), create:
323
+
324
+ | Field | Value |
325
+ |---|---|
326
+ | Name | `CALM_datacollector` (exactly this name) |
327
+ | Type | HTTP |
328
+ | URL | the `Api` URL from the Cloud ALM API service key, e.g. `https://eu10.alm.cloud.sap/api` |
329
+ | Proxy Type | Internet |
330
+ | Authentication | OAuth2ClientCredentials |
331
+ | Client ID / Client Secret | from the Cloud ALM API service key |
332
+ | Token Service URL | the `url` from the service key |
333
+
334
+ SAP notes that "Check Connection" can return 404 even when the destination is correct.
335
+
336
+ ### 9.7 Activate monitoring in Cloud ALM
337
+
338
+ In SAP Cloud ALM, activate the monitoring use cases you need for the service (for example
339
+ Health Monitoring and Exception Monitoring). Optional agent settings and how to turn the agent
340
+ off (`SAP_CALM_INSTRUMENTATION_ENABLED=false`) are on SAP's auto-instrumentation page.
341
+
342
+ ### 9.8 What you'll see, and what isn't verified
343
+
344
+ - **App log after deploying:** a line from `@cap-js/telemetry` saying it found
345
+ `@sap/xotel-agent-ext-js` and added its span processor as a delegate. The optimizer logs a
346
+ warning if no OpenTelemetry metrics provider is registered.
347
+ - **Spans:** the optimizer's `chat <model>` spans are children of the CAP request spans and
348
+ carry token usage, savings and error category, never prompt text. They go through the same
349
+ pipeline as the CAP spans.
350
+ - **Not documented by SAP:** whether Cloud ALM shows **custom** OpenTelemetry metrics (like
351
+ `gen_ai.client.token.usage` or `cap_ai_optimizer.tokens.saved`) in its UIs. Its documented
352
+ use cases are Health, Exception, Job & Automation, Business Process and Real User Monitoring.
353
+ - **Not verified:** this setup hasn't been tested against a Cloud ALM tenant.
354
+
355
+ If you need token dashboards, use the `db` exporter with the admin service or your own
356
+ reporting service, or send the `otel` data to SAP Cloud Logging or Dynatrace via
357
+ `@cap-js/telemetry` (`cds.requires.telemetry.kind` = `to-cloud-logging` / `to-dynatrace`).
358
+ Note that with the agent present, `@cap-js/telemetry` also exports through its own
359
+ configured kind (console by default), so check the log volume after deploying.
360
+
361
+ ## 10. Deploy and verify
362
+
363
+ ```sh
364
+ npm install # updates package-lock.json
365
+ mbt build
366
+ cf deploy mta_archives/<your-app>_<version>.mtar -e secrets.mtaext
367
+ ```
368
+
369
+ Then check:
370
+
371
+ 1. **Logs:** `cf logs my-cap-app-srv --recent` shows
372
+ `autoInstrument: OrchestrationClient … calls are optimized and measured` at startup, and one
373
+ `"type":"ai-core-call"` line per AI call.
374
+ 2. **Admin service:** with the `TokenOptimizerAdmin` role, open
375
+ `https://<app-url>/odata/v4/token-optimizer/summary()`.
376
+ 3. **Cloud ALM:** the service appears under `SAP_CALM_SERVICE_NAME` in the activated
377
+ monitoring apps.
378
+ 4. **Behavior:** your AI features answer exactly as before (shadow mode sends the original prompts).
379
+
380
+ ## 11. Switch from shadow to active
381
+
382
+ After a few days in shadow mode, compare `savings.estimatedTokens` and the notes in the events
383
+ or the admin service per use case. Then switch one use case at a time:
384
+
385
+ ```json
386
+ "tokenOptimizer": {
387
+ "mode": "shadow",
388
+ "useCases": {
389
+ "ticket-summary": { "mode": "active" }
390
+ }
391
+ }
392
+ ```
393
+
394
+ In `active` mode the optimized prompts are sent, and identical calls with `temperature` ≤ 0.2
395
+ are answered from the cache, which is per app instance and per tenant. Check answer quality
396
+ for that use case before switching the next one. If an agent needs more context or tools,
397
+ raise `steps.history.maxTurns` or `steps.tools.maxTools`, or pin the tools it needs, for that
398
+ use case.
399
+
400
+ ## 12. Turn it off or roll back
401
+
402
+ | Goal | How |
403
+ |---|---|
404
+ | Stop optimizing, keep measuring | `cds_requires_tokenOptimizer_mode=off`, then `cf restart` |
405
+ | Stop hooking the SDK | `cds_requires_tokenOptimizer_autoInstrument=false`, then `cf restart` |
406
+ | Turn off the Cloud ALM agent | `SAP_CALM_INSTRUMENTATION_ENABLED=false`, then `cf restart` |
407
+ | Remove the package | `npm rm @viveka10/cap-ai-token-optimizer`, delete the `tokenOptimizer` block, redeploy. If you used the `db` exporter, the `TokenUsageLog` table stays until you drop it. |
408
+
409
+ ## Checklist
410
+
411
+ - [ ] Node ≥ 22.12 and `engines` set; `@sap-ai-sdk/*` ≥ 2.8, same version, no duplicates
412
+ - [ ] `npm add @viveka10/cap-ai-token-optimizer`
413
+ - [ ] `tokenOptimizer` block with `mode: "shadow"` and `autoInstrument: true`; `pricing` filled in
414
+ - [ ] Salt and other secrets in an `.mtaext` that is not committed
415
+ - [ ] Optional: `withUseCase` / `wrapLangChain` for named use cases
416
+ - [ ] Optional: `db` exporter (HANA table deployed with the app; MTX upgrade)
417
+ - [ ] Optional: admin service plus `TokenOptimizerAdmin` role collection
418
+ - [ ] Cloud ALM:
419
+ - [ ] RBSC user and `SAP_NPM_AUTH`
420
+ - [ ] agent ≥ 2.0.4 and `@cap-js/telemetry` ≥ 2.1.0
421
+ - [ ] `NODE_ARGS`, `SAP_CALM_*` properties and destination service in `mta.yaml`
422
+ - [ ] `CALM_datacollector` destination
423
+ - [ ] monitoring use cases activated in Cloud ALM
424
+ - [ ] `otel` exporter enabled
425
+ - [ ] Deploy, check logs and the admin service, then switch use cases to `active` one by one
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@viveka10/cap-ai-token-optimizer",
3
- "version": "0.1.0",
4
- "description": "Reduce, measure and report SAP AI Core token usage in SAP CAP Node.js apps: prompt optimization, response cache, metrics for SAP Cloud ALM / OpenTelemetry, HTTP and HANA",
3
+ "version": "0.1.1",
4
+ "description": "SAP CAP plugin to reduce, measure and report SAP AI Core LLM token usage: prompt optimization, response cache, cost tracking, and metrics for SAP Cloud ALM / OpenTelemetry",
5
5
  "keywords": [
6
6
  "sap",
7
7
  "cap",
@@ -20,7 +20,17 @@
20
20
  "mcp",
21
21
  "agents",
22
22
  "langchain",
23
- "btp"
23
+ "btp",
24
+ "sap-cap",
25
+ "sap-btp",
26
+ "sap-ai",
27
+ "token-optimizer",
28
+ "ai-token-optimization",
29
+ "prompt-optimization",
30
+ "llm-cost",
31
+ "cost-optimization",
32
+ "openai",
33
+ "observability"
24
34
  ],
25
35
  "homepage": "https://github.com/viveka10/npm_token_optimizer/tree/main/cap-ai-token-optimizer#readme",
26
36
  "bugs": {