npm package: @geertjanklaps/cds-toon-ai-protocol-adapter
Description: Token-Oriented Object Notation (TOON) protocol adapter for SAP Cloud Application Programming Model (CAP).
Author: Geert-Jan Klaps
Latest version: 1.0.2

# Toon AI Protocol Adapter Plugin for SAP CAP

> Token-Oriented Object Notation (TOON) protocol adapter for SAP Cloud Application Programming Model (CAP)

[![npm version](https://img.shields.io/npm/v/@geertjanklaps/cds-toon-ai-protocol-adapter.svg)](https://www.npmjs.com/package/@geertjanklaps/cds-toon-ai-protocol-adapter)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Overview

The Toon AI Protocol Adapter Plugin extends SAP Cloud Application Programming Model (CAP) with support for the **Toon (Token-Oriented Object Notation)** format. This plugin provides automatic conversion between JSON and Toon format, optimizing data exchange for AI applications by typically reducing token counts while maintaining data integrity.

### Key Features

- 🚀 **Two Protocol Variants**: REST-based (`toon`) and OData-based (`toon-odata`) adapters
- 🔄 **Bidirectional Conversion**: Automatic JSON ↔ Toon format conversion
- 📊 **Token Count Optimization**: Built-in token statistics and smart content-type selection
- 🔧 **Configurable Processing**: Flexible request/response processing controls
- 📈 **Performance Monitoring**: Real-time token count comparison and logging
- 🔌 **Plugin Architecture**: Easy integration with existing CAP applications

![Toon protocol adapter in action](docs/toon-demo.gif "Toon protocol adapter in action")

## Installation

```bash
npm install @geertjanklaps/cds-toon-ai-protocol-adapter
```

### Dependencies

- **@sap/cds**: >=9 (peer dependency)
- **@toon-format/toon**: ^2.1.0
- **tokenx**: ^1.3.0

## Quick Start

### 1. Basic Service Configuration

Define a CAP service with Toon protocol support:

```cds
// srv/my-service.cds
@protocol: ['toon']
service MyToonService {
}
```

### 2. Alternative: OData + Toon Protocol

For OData compatibility with Toon optimization:

```cds
// srv/my-service.cds
@protocol: ['toon-odata']
service MyToonODataService {
}
```

## Protocol Endpoints

The plugin automatically creates endpoints for your services:

### REST Protocol (`@protocol: ['toon']`)

- **Base URL**: `http://localhost:4004/toon/`
- **Service Path**: `/toon/{service-name}/{function-or-action}`
- **Example**: `GET /toon/my-toon-service/getData`

### OData Protocol (`@protocol: ['toon-odata']`)

- **Base URL**: `http://localhost:4004/toon-odata/`
- **Service Path**: `/toon-odata/{service-name}/{function-or-action}`
- **Example**: `GET /toon-odata/my-toon-odata-service/getData`

## Configuration

Configure the plugin behavior in your `package.json`:

```json
{
  "cds": {
    "toonAdapter": {
      "requestProcessingEnabled": false,
      "responseProcessingEnabled": true,
      "logTokenStatistics": true,
      "autoDetermineResponseContentType": true
    }
  }
}
```

### Configuration Parameters

| Parameter                          | Type      | Default | Description                                                      |
| ---------------------------------- | --------- | ------- | ---------------------------------------------------------------- |
| `requestProcessingEnabled`         | `boolean` | `false` | Enable automatic conversion of incoming Toon requests to JSON    |
| `responseProcessingEnabled`        | `boolean` | `true`  | Enable automatic conversion of JSON responses to Toon format     |
| `logTokenStatistics`               | `boolean` | `true`  | Log token count comparisons between JSON and Toon formats        |
| `autoDetermineResponseContentType` | `boolean` | `true`  | Automatically choose between JSON/Toon based on token efficiency |

## Usage Examples

### Making Requests

#### JSON Request (Standard)

```http
GET /toon-odata/catalog/Books?$select=createdAt,createdBy,modifiedAt,modifiedBy,ID,title,author_ID,genre_ID,stock,price,currency_code
Content-Type: application/json
```

### Response Formats

#### JSON Response (auto-selected when more efficient)

```json
{
  "@odata.context": "$metadata#Books",
  "value": [
    {
      "createdAt": "2026-01-25T18:27:05.907Z",
      "createdBy": "anonymous",
      "modifiedAt": "2026-01-25T18:27:05.907Z",
      "modifiedBy": "anonymous",
      "ID": 201,
      "title": "Wuthering Heights",
      "author_ID": 101,
      "genre_ID": 11,
      "stock": 12,
      "price": 11.11,
      "currency_code": "GBP"
    },
    {
      "createdAt": "2026-01-25T18:27:05.907Z",
      "createdBy": "anonymous",
      "modifiedAt": "2026-01-25T18:27:05.907Z",
      "modifiedBy": "anonymous",
      "ID": 207,
      "title": "Jane Eyre",
      "author_ID": 107,
      "genre_ID": 11,
      "stock": 11,
      "price": 12.34,
      "currency_code": "GBP"
    },
    {
      "createdAt": "2026-01-25T18:27:05.907Z",
      "createdBy": "anonymous",
      "modifiedAt": "2026-01-25T18:27:05.907Z",
      "modifiedBy": "anonymous",
      "ID": 251,
      "title": "The Raven",
      "author_ID": 150,
      "genre_ID": 16,
      "stock": 333,
      "price": 13.13,
      "currency_code": "USD"
    },
    {
      "createdAt": "2026-01-25T18:27:05.907Z",
      "createdBy": "anonymous",
      "modifiedAt": "2026-01-25T18:27:05.907Z",
      "modifiedBy": "anonymous",
      "ID": 252,
      "title": "Eleonora",
      "author_ID": 150,
      "genre_ID": 16,
      "stock": 555,
      "price": 14,
      "currency_code": "USD"
    },
    {
      "createdAt": "2026-01-25T18:27:05.907Z",
      "createdBy": "anonymous",
      "modifiedAt": "2026-01-25T18:27:05.907Z",
      "modifiedBy": "anonymous",
      "ID": 271,
      "title": "Catweazle",
      "author_ID": 170,
      "genre_ID": 13,
      "stock": 22,
      "price": 150,
      "currency_code": "JPY"
    }
  ]
}
```

#### Toon Response (default when responseProcessingEnabled: true)

```
[5]{createdAt,createdBy,modifiedAt,modifiedBy,ID,title,author_ID,genre_ID,stock,price,currency_code}:
  "2026-01-25T18:27:05.907Z",anonymous,"2026-01-25T18:27:05.907Z",anonymous,201,Wuthering Heights,101,11,12,11.11,GBP
  "2026-01-25T18:27:05.907Z",anonymous,"2026-01-25T18:27:05.907Z",anonymous,207,Jane Eyre,107,11,11,12.34,GBP
  "2026-01-25T18:27:05.907Z",anonymous,"2026-01-25T18:27:05.907Z",anonymous,251,The Raven,150,16,333,13.13,USD
  "2026-01-25T18:27:05.907Z",anonymous,"2026-01-25T18:27:05.907Z",anonymous,252,Eleonora,150,16,555,14,USD
  "2026-01-25T18:27:05.907Z",anonymous,"2026-01-25T18:27:05.907Z",anonymous,271,Catweazle,170,13,22,150,JPY
```

## Token Count Optimization

The plugin provides intelligent token count optimization:

### Automatic Content Type Selection

When `autoDetermineResponseContentType` is enabled:

- **JSON**: Used when JSON format has fewer tokens
- **Toon**: Used when Toon format has fewer tokens (typical case)

### Token Statistics Logging

When `logTokenStatistics` is enabled, the plugin logs:

```
[toon] - Token count - JSON: 150, TOON: 95, Difference: 55 (36.7%)
```

## Advanced Configuration

### Custom Protocol Registration

The plugin automatically registers protocols, but you can customize them:

```typescript
// cds-plugin.js
const cds = require("@sap/cds");

cds.protocol.toon = {
  path: "/custom-toon",
  impl: "@geertjanklaps/cds-toon-ai-protocol-adapter",
};
```

### Environment-Specific Settings

```json
{
  "cds": {
    "profiles": {
      "production": {
        "toonAdapter": {
          "logTokenStatistics": false,
          "autoDetermineResponseContentType": true
        }
      },
      "development": {
        "toonAdapter": {
          "logTokenStatistics": true,
          "autoDetermineResponseContentType": false
        }
      }
    }
  }
}
```

## Testing Your Implementation

Use the provided test files as reference:

```http
### OData GET request
GET http://localhost:4004/odata/v4/catalog/Books?$select=createdAt,createdBy,modifiedAt,modifiedBy,ID,title,author_ID,genre_ID,stock,price,currency_code
Content-Type: application/json; charset=utf-8
Authorization: Basic alice:

### Toon OData GET Request
GET http://localhost:4004/toon-odata/catalog/Books?$select=createdAt,createdBy,modifiedAt,modifiedBy,ID,title,author_ID,genre_ID,stock,price,currency_code
Content-Type: application/json; charset=utf-8
Authorization: Basic alice:
```

## When to Use

### Ideal Use Cases

- **AI/LLM Integration**: Optimize token usage for AI model communication
- **Large Data Payloads**: Reduce bandwidth and token costs for complex responses
- **Real-time Applications**: Minimize payload size for faster transmission
- **Cost Optimization**: Reduce AI API costs through token count reduction

### Performance Benefits

- **Token Reduction**: Typically 20-50% fewer tokens compared to JSON
- **Bandwidth Optimization**: Smaller payload sizes
- **AI Cost Reduction**: Lower token consumption in AI model interactions

## API Reference

### Adapters

#### `ToonAdapter`

Extends SAP CAP's REST adapter with Toon protocol support.

#### `ToonODataAdapter`

Extends SAP CAP's OData adapter with Toon protocol support.

## Troubleshooting

### Common Issues

1. **Plugin Not Loading**
   - Ensure plugin is in dependencies, not devDependencies
   - Check CDS version compatibility (>=9 required)

2. **Toon Endpoints Not Available**
   - Verify service has `@protocol` annotation
   - Check service registration in CDS

3. **Token Statistics Not Showing**
   - Enable `logTokenStatistics: true` in configuration
   - Check log level configuration

### Debug Logging

Enable debug logging:

```bash
DEBUG=toon cds watch
```

## Contributing

Contributions are welcome! Please submit pull requests to the GitHub repository.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## Support

- **GitHub Issues**: [Report bugs or request features](https://github.com/geert-janklaps/cds-toon-ai-protocol-adapter/issues)
- **Documentation**: Check the inline code documentation for detailed API information

## Related Projects

- **@toon-format/toon**: Core Toon format implementation
- **@sap/cds**: SAP Cloud Application Programming Model
- **tokenx**: Token counting utilities

---