@holokai/holo-provider-claude 0.1.0
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/LICENSE +21 -0
- package/README.md +588 -0
- package/dist/claude.auditor.d.ts +12 -0
- package/dist/claude.auditor.d.ts.map +1 -0
- package/dist/claude.auditor.js +113 -0
- package/dist/claude.auditor.js.map +1 -0
- package/dist/claude.provider.d.ts +19 -0
- package/dist/claude.provider.d.ts.map +1 -0
- package/dist/claude.provider.js +53 -0
- package/dist/claude.provider.js.map +1 -0
- package/dist/claude.response.factory.d.ts +21 -0
- package/dist/claude.response.factory.d.ts.map +1 -0
- package/dist/claude.response.factory.js +132 -0
- package/dist/claude.response.factory.js.map +1 -0
- package/dist/claude.translator.d.ts +21 -0
- package/dist/claude.translator.d.ts.map +1 -0
- package/dist/claude.translator.js +76 -0
- package/dist/claude.translator.js.map +1 -0
- package/dist/claude.wire.adapter.d.ts +5 -0
- package/dist/claude.wire.adapter.d.ts.map +1 -0
- package/dist/claude.wire.adapter.js +9 -0
- package/dist/claude.wire.adapter.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +3 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +146 -0
- package/dist/manifest.js.map +1 -0
- package/dist/plugin.d.ts +20 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +53 -0
- package/dist/plugin.js.map +1 -0
- package/dist/translators/claude.content.translators.d.ts +12 -0
- package/dist/translators/claude.content.translators.d.ts.map +1 -0
- package/dist/translators/claude.content.translators.js +65 -0
- package/dist/translators/claude.content.translators.js.map +1 -0
- package/dist/translators/claude.message.translators.d.ts +14 -0
- package/dist/translators/claude.message.translators.d.ts.map +1 -0
- package/dist/translators/claude.message.translators.js +129 -0
- package/dist/translators/claude.message.translators.js.map +1 -0
- package/dist/translators/claude.request.translators.d.ts +18 -0
- package/dist/translators/claude.request.translators.d.ts.map +1 -0
- package/dist/translators/claude.request.translators.js +110 -0
- package/dist/translators/claude.request.translators.js.map +1 -0
- package/dist/translators/claude.response.content.translators.d.ts +12 -0
- package/dist/translators/claude.response.content.translators.d.ts.map +1 -0
- package/dist/translators/claude.response.content.translators.js +53 -0
- package/dist/translators/claude.response.content.translators.js.map +1 -0
- package/dist/translators/claude.response.message.translators.d.ts +14 -0
- package/dist/translators/claude.response.message.translators.d.ts.map +1 -0
- package/dist/translators/claude.response.message.translators.js +95 -0
- package/dist/translators/claude.response.message.translators.js.map +1 -0
- package/dist/translators/claude.response.translators.d.ts +18 -0
- package/dist/translators/claude.response.translators.d.ts.map +1 -0
- package/dist/translators/claude.response.translators.js +109 -0
- package/dist/translators/claude.response.translators.js.map +1 -0
- package/dist/translators/claude.tool.translators.d.ts +19 -0
- package/dist/translators/claude.tool.translators.d.ts.map +1 -0
- package/dist/translators/claude.tool.translators.js +68 -0
- package/dist/translators/claude.tool.translators.js.map +1 -0
- package/dist/translators/claude.usage.translators.d.ts +12 -0
- package/dist/translators/claude.usage.translators.d.ts.map +1 -0
- package/dist/translators/claude.usage.translators.js +51 -0
- package/dist/translators/claude.usage.translators.js.map +1 -0
- package/dist/translators/index.d.ts +10 -0
- package/dist/translators/index.d.ts.map +1 -0
- package/dist/translators/index.js +10 -0
- package/dist/translators/index.js.map +1 -0
- package/dist/translators/streaming/claude.content.block.delta.event.translator.d.ts +12 -0
- package/dist/translators/streaming/claude.content.block.delta.event.translator.d.ts.map +1 -0
- package/dist/translators/streaming/claude.content.block.delta.event.translator.js +91 -0
- package/dist/translators/streaming/claude.content.block.delta.event.translator.js.map +1 -0
- package/dist/translators/streaming/claude.content.block.start.event.translator.d.ts +12 -0
- package/dist/translators/streaming/claude.content.block.start.event.translator.d.ts.map +1 -0
- package/dist/translators/streaming/claude.content.block.start.event.translator.js +83 -0
- package/dist/translators/streaming/claude.content.block.start.event.translator.js.map +1 -0
- package/dist/translators/streaming/claude.content.block.stop.event.translator.d.ts +12 -0
- package/dist/translators/streaming/claude.content.block.stop.event.translator.d.ts.map +1 -0
- package/dist/translators/streaming/claude.content.block.stop.event.translator.js +48 -0
- package/dist/translators/streaming/claude.content.block.stop.event.translator.js.map +1 -0
- package/dist/translators/streaming/claude.message.delta.event.translator.d.ts +12 -0
- package/dist/translators/streaming/claude.message.delta.event.translator.d.ts.map +1 -0
- package/dist/translators/streaming/claude.message.delta.event.translator.js +74 -0
- package/dist/translators/streaming/claude.message.delta.event.translator.js.map +1 -0
- package/dist/translators/streaming/claude.message.start.event.translator.d.ts +14 -0
- package/dist/translators/streaming/claude.message.start.event.translator.d.ts.map +1 -0
- package/dist/translators/streaming/claude.message.start.event.translator.js +81 -0
- package/dist/translators/streaming/claude.message.start.event.translator.js.map +1 -0
- package/dist/translators/streaming/claude.message.stop.event.translator.d.ts +12 -0
- package/dist/translators/streaming/claude.message.stop.event.translator.d.ts.map +1 -0
- package/dist/translators/streaming/claude.message.stop.event.translator.js +52 -0
- package/dist/translators/streaming/claude.message.stop.event.translator.js.map +1 -0
- package/dist/translators/streaming/claude.stream.translator.d.ts +24 -0
- package/dist/translators/streaming/claude.stream.translator.d.ts.map +1 -0
- package/dist/translators/streaming/claude.stream.translator.js +136 -0
- package/dist/translators/streaming/claude.stream.translator.js.map +1 -0
- package/dist/translators/streaming/index.d.ts +8 -0
- package/dist/translators/streaming/index.d.ts.map +1 -0
- package/dist/translators/streaming/index.js +8 -0
- package/dist/translators/streaming/index.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/request.types.d.ts +8 -0
- package/dist/types/request.types.d.ts.map +1 -0
- package/dist/types/request.types.js +2 -0
- package/dist/types/request.types.js.map +1 -0
- package/dist/types/response.types.d.ts +16 -0
- package/dist/types/response.types.d.ts.map +1 -0
- package/dist/types/response.types.js +2 -0
- package/dist/types/response.types.js.map +1 -0
- package/dist/utils/finish.reason.mapper.d.ts +5 -0
- package/dist/utils/finish.reason.mapper.d.ts.map +1 -0
- package/dist/utils/finish.reason.mapper.js +40 -0
- package/dist/utils/finish.reason.mapper.js.map +1 -0
- package/dist/utils/stable-id.d.ts +2 -0
- package/dist/utils/stable-id.d.ts.map +1 -0
- package/dist/utils/stable-id.js +13 -0
- package/dist/utils/stable-id.js.map +1 -0
- package/package.json +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Holokai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
# @holokai/holo-provider-claude
|
|
2
|
+
|
|
3
|
+
> **Official Claude (Anthropic) provider plugin for Holo LLM Gateway**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@holokai/holo-provider-claude)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
The Claude provider plugin enables Holo to communicate with Anthropic's Claude API through the universal Holo format. This plugin is part of the migration from the monolithic provider architecture to a plugin-based system, providing complete bidirectional translation between Claude's native API and the portable Holo format.
|
|
13
|
+
|
|
14
|
+
### Key Features
|
|
15
|
+
|
|
16
|
+
- ✅ **Full Holo SDK Integration** - Uses `@holokai/sdk` types for strict type safety
|
|
17
|
+
- ✅ **Bidirectional Translation** - Claude ↔ Holo format with lossless core fields
|
|
18
|
+
- ✅ **Streaming Support** - 6 granular event types with proper orchestration
|
|
19
|
+
- ✅ **Tool Calling** - Complete function calling support with proper extraction
|
|
20
|
+
- ✅ **Vision/Multimodal** - Image support via URLs and base64 data URIs
|
|
21
|
+
- ✅ **Prompt Caching** - Cost optimization through content caching
|
|
22
|
+
- ✅ **Extended Thinking** - Claude 3.5 Sonnet+ reasoning capabilities
|
|
23
|
+
- ✅ **Plugin Architecture** - Auto-discovered, hot-reloadable, independently versioned
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @holokai/holo-provider-claude
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Peer Dependencies
|
|
34
|
+
|
|
35
|
+
This plugin requires:
|
|
36
|
+
- `@holokai/sdk` ^0.1.0 - Holo universal format types and plugin contracts
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Quick Start
|
|
41
|
+
|
|
42
|
+
### Automatic Discovery
|
|
43
|
+
|
|
44
|
+
When installed in a Holo worker environment, this plugin is automatically discovered and loaded by the plugin system. No manual registration required.
|
|
45
|
+
|
|
46
|
+
### Configuration
|
|
47
|
+
|
|
48
|
+
Add a provider configuration to your Holo deployment:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"id": "claude-primary",
|
|
53
|
+
"provider_type": "claude",
|
|
54
|
+
"plugin_id": "@holokai/holo-provider-claude",
|
|
55
|
+
"api_key": "${ANTHROPIC_API_KEY}",
|
|
56
|
+
"model": "claude-3-5-sonnet-20241022",
|
|
57
|
+
"config": {
|
|
58
|
+
"defaultModel": "claude-3-5-sonnet-20241022",
|
|
59
|
+
"timeoutMs": 60000,
|
|
60
|
+
"maxRetries": 2,
|
|
61
|
+
"enableVision": true
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Usage in Code
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { HoloRequest, HoloResponse } from '@holokai/sdk';
|
|
70
|
+
|
|
71
|
+
const request: HoloRequest = {
|
|
72
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
73
|
+
messages: [
|
|
74
|
+
{ role: 'user', content: 'Explain quantum computing briefly.' }
|
|
75
|
+
],
|
|
76
|
+
max_tokens: 1000,
|
|
77
|
+
temperature: 0.7
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Plugin handles translation automatically
|
|
81
|
+
const response: HoloResponse = await holoClient.chat(request);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Migration from Monolithic Architecture
|
|
87
|
+
|
|
88
|
+
### What Changed
|
|
89
|
+
|
|
90
|
+
This plugin represents the extraction of Claude provider logic from the monolithic `src/providers/claude/` codebase into a standalone, independently versioned package.
|
|
91
|
+
|
|
92
|
+
**Before** (Monolithic):
|
|
93
|
+
```
|
|
94
|
+
src/providers/claude/
|
|
95
|
+
├── claude.translator.ts
|
|
96
|
+
├── translators/
|
|
97
|
+
├── streaming/
|
|
98
|
+
└── types/
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**After** (Plugin):
|
|
102
|
+
```
|
|
103
|
+
@holokai/holo-provider-claude
|
|
104
|
+
├── src/
|
|
105
|
+
│ ├── plugin.ts # Plugin entrypoint
|
|
106
|
+
│ ├── manifest.ts # Plugin metadata
|
|
107
|
+
│ ├── claude.provider.ts # Provider implementation
|
|
108
|
+
│ └── translators/ # Translation logic (preserved)
|
|
109
|
+
└── package.json
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Migration Benefits
|
|
113
|
+
|
|
114
|
+
1. **Independent Versioning** - Update Claude support without core releases
|
|
115
|
+
2. **Hot Reload** - Deploy new Claude versions without downtime
|
|
116
|
+
3. **Type Safety** - Strict SDK types eliminate `Record<string, unknown>`
|
|
117
|
+
4. **Reduced Coupling** - Plugin contracts enforce clean boundaries
|
|
118
|
+
5. **Marketplace Ready** - Can be published to NPM independently
|
|
119
|
+
|
|
120
|
+
### Breaking Changes
|
|
121
|
+
|
|
122
|
+
- **Import paths changed**: Use `@holokai/sdk` for types instead of `../../types`
|
|
123
|
+
- **Configuration schema**: Now validated via plugin manifest
|
|
124
|
+
- **Dependency injection**: Uses plugin container instead of core DI
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Architecture
|
|
129
|
+
|
|
130
|
+
### Plugin Structure
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
@holokai/holo-provider-claude/
|
|
134
|
+
├── src/
|
|
135
|
+
│ ├── plugin.ts # ProviderPlugin implementation
|
|
136
|
+
│ ├── manifest.ts # Plugin metadata & config schema
|
|
137
|
+
│ ├── claude.provider.ts # Core provider logic
|
|
138
|
+
│ ├── claude.translator.ts # Main translator facade
|
|
139
|
+
│ ├── translators/
|
|
140
|
+
│ │ ├── claude.request.translator.ts
|
|
141
|
+
│ │ ├── claude.response.translator.ts
|
|
142
|
+
│ │ ├── claude.message.translator.ts
|
|
143
|
+
│ │ ├── claude.tool.translator.ts
|
|
144
|
+
│ │ └── claude.usage.translator.ts
|
|
145
|
+
│ ├── streaming/
|
|
146
|
+
│ │ ├── claude.stream.translator.ts # Orchestrator
|
|
147
|
+
│ │ ├── claude.message.start.event.translator.ts
|
|
148
|
+
│ │ ├── claude.message.delta.event.translator.ts
|
|
149
|
+
│ │ ├── claude.message.stop.event.translator.ts
|
|
150
|
+
│ │ ├── claude.content.block.start.event.translator.ts
|
|
151
|
+
│ │ ├── claude.content.block.delta.event.translator.ts
|
|
152
|
+
│ │ └── claude.content.block.stop.event.translator.ts
|
|
153
|
+
│ ├── types/
|
|
154
|
+
│ │ └── (Re-exports from @anthropic-ai/sdk)
|
|
155
|
+
│ └── utils/
|
|
156
|
+
│ └── (Helper functions)
|
|
157
|
+
└── package.json
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Translation Flow
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
┌─────────────────┐
|
|
164
|
+
│ Holo Request │
|
|
165
|
+
│ (SDK types) │
|
|
166
|
+
└────────┬────────┘
|
|
167
|
+
│
|
|
168
|
+
↓
|
|
169
|
+
┌─────────────────────────┐
|
|
170
|
+
│ ClaudeRequestTranslator │
|
|
171
|
+
│ - Maps Holo → Claude │
|
|
172
|
+
│ - Transforms content │
|
|
173
|
+
│ - Renames fields │
|
|
174
|
+
└────────┬────────────────┘
|
|
175
|
+
│
|
|
176
|
+
↓
|
|
177
|
+
┌─────────────────┐
|
|
178
|
+
│ Claude API │
|
|
179
|
+
│ (@anthropic) │
|
|
180
|
+
└────────┬────────┘
|
|
181
|
+
│
|
|
182
|
+
↓
|
|
183
|
+
┌──────────────────────────┐
|
|
184
|
+
│ ClaudeResponseTranslator │
|
|
185
|
+
│ - Maps Claude → Holo │
|
|
186
|
+
│ - Extracts tool calls │
|
|
187
|
+
│ - Normalizes finish │
|
|
188
|
+
└────────┬─────────────────┘
|
|
189
|
+
│
|
|
190
|
+
↓
|
|
191
|
+
┌─────────────────┐
|
|
192
|
+
│ Holo Response │
|
|
193
|
+
│ (SDK types) │
|
|
194
|
+
└─────────────────┘
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Holo Format Mapping
|
|
200
|
+
|
|
201
|
+
This plugin implements the official Holo format mappings as documented in the SDK.
|
|
202
|
+
|
|
203
|
+
### Request Mapping: Holo → Claude
|
|
204
|
+
|
|
205
|
+
| Holo Field | Claude Field | Transformation | Notes |
|
|
206
|
+
|------------|-------------|----------------|-------|
|
|
207
|
+
| **Direct 1:1** ||||
|
|
208
|
+
| `model` | `model` | Direct | Required |
|
|
209
|
+
| `temperature` | `temperature` | Direct | 0-1 for Claude |
|
|
210
|
+
| `top_p` | `top_p` | Direct | Optional |
|
|
211
|
+
| `top_k` | `top_k` | Direct | Optional |
|
|
212
|
+
| `stream` | `stream` | Direct | Optional |
|
|
213
|
+
| `max_tokens` | `max_tokens` | Direct | Required by Claude |
|
|
214
|
+
| `stop_sequences` | `stop_sequences` | Direct | Array format |
|
|
215
|
+
| **Structure Transforms** ||||
|
|
216
|
+
| `system` (string) | `system` | Direct | Top-level |
|
|
217
|
+
| `system` (string[]) | `system` | Join with `\n\n` + drop metadata | Lossy if structured |
|
|
218
|
+
| `metadata.user_id` | `metadata.user_id` | Direct | Optional |
|
|
219
|
+
| `tools[].parameters` | `tools[].input_schema` | Rename field | JSON Schema |
|
|
220
|
+
| `tool_choice.type: 'specific'` | `tool_choice.type: 'tool'` | Map type + name | Specific tool |
|
|
221
|
+
| `tool_choice.type: 'required'` | `tool_choice.type: 'any'` | Map type | Any tool |
|
|
222
|
+
| `messages[]` | `messages[]` | Transform content | See Content Mapping |
|
|
223
|
+
|
|
224
|
+
**Dropped Fields** (Holo → Claude):
|
|
225
|
+
- `response_format` - Claude doesn't support structured output modes
|
|
226
|
+
- `frequency_penalty` - Not supported
|
|
227
|
+
- `presence_penalty` - Not supported
|
|
228
|
+
- `seed` - Not supported
|
|
229
|
+
|
|
230
|
+
See [SDK Provider Mappings](../../packages/sdk/docs/PROVIDER_MAPPINGS.md#claude--holo-requests) for complete details.
|
|
231
|
+
|
|
232
|
+
### Response Mapping: Claude → Holo
|
|
233
|
+
|
|
234
|
+
| Claude Field | Holo Field | Transformation | Notes |
|
|
235
|
+
|-------------|------------|----------------|-------|
|
|
236
|
+
| **Direct 1:1** ||||
|
|
237
|
+
| `id` | `id` | Direct | Always present |
|
|
238
|
+
| `model` | `model` | Direct | Always present |
|
|
239
|
+
| `role: 'assistant'` | `messages[0].role` | Wrap in array | Always assistant |
|
|
240
|
+
| **Structure Transforms** ||||
|
|
241
|
+
| `content[]` blocks | `messages[0].content` | Extract text + tools | Multi-part |
|
|
242
|
+
| `stop_reason` | `finish_reason` | Map codes | See table below |
|
|
243
|
+
| `usage.input_tokens` | `usage.input_tokens` | Direct | Optional |
|
|
244
|
+
| `usage.output_tokens` | `usage.output_tokens` | Direct | Optional |
|
|
245
|
+
| `usage.cache_read_input_tokens` | `usage.cache_read_tokens` | Direct | Optional |
|
|
246
|
+
| `usage.cache_creation_input_tokens` | `usage.cache_write_tokens` | Direct | Optional |
|
|
247
|
+
| `usage.service_tier` | `service_tier` | Promote to top-level | Optional |
|
|
248
|
+
| N/A | `created` | Synthesize with `Date.now()` | Claude lacks timestamp |
|
|
249
|
+
|
|
250
|
+
**Finish Reason Mapping**:
|
|
251
|
+
|
|
252
|
+
| Claude `stop_reason` | Holo `finish_reason` |
|
|
253
|
+
|---------------------|---------------------|
|
|
254
|
+
| `end_turn` | `stop` |
|
|
255
|
+
| `max_tokens` | `length` |
|
|
256
|
+
| `tool_use` | `tool_calls` |
|
|
257
|
+
| `refusal` | `content_filter` |
|
|
258
|
+
| `pause_turn` | `stop` (preserve in metadata) |
|
|
259
|
+
|
|
260
|
+
### Content Mapping
|
|
261
|
+
|
|
262
|
+
#### Text Content
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
// Holo
|
|
266
|
+
{ type: 'text', text: 'Hello' }
|
|
267
|
+
|
|
268
|
+
// Claude (direct)
|
|
269
|
+
{ type: 'text', text: 'Hello' }
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### Image Content
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// Holo
|
|
276
|
+
{ type: 'image', url: 'https://example.com/image.png' }
|
|
277
|
+
|
|
278
|
+
// Claude
|
|
279
|
+
{ type: 'image', source: { type: 'url', url: 'https://example.com/image.png' } }
|
|
280
|
+
|
|
281
|
+
// Holo (base64)
|
|
282
|
+
{ type: 'image', url: 'data:image/png;base64,iVBORw...' }
|
|
283
|
+
|
|
284
|
+
// Claude (base64)
|
|
285
|
+
{ type: 'image', source: { type: 'base64', media_type: 'image/png', data: 'iVBORw...' } }
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
#### Tool Calls (Extraction Required)
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
// Claude Response (embedded in content)
|
|
292
|
+
{
|
|
293
|
+
content: [
|
|
294
|
+
{ type: 'text', text: 'Let me check that for you.' },
|
|
295
|
+
{ type: 'tool_use', id: 'toolu_123', name: 'get_weather', input: { location: 'SF' } }
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Holo Response (extracted)
|
|
300
|
+
{
|
|
301
|
+
messages: [{
|
|
302
|
+
role: 'assistant',
|
|
303
|
+
content: 'Let me check that for you.',
|
|
304
|
+
tool_calls: [{
|
|
305
|
+
id: 'toolu_123',
|
|
306
|
+
type: 'function',
|
|
307
|
+
function: { name: 'get_weather', arguments: { location: 'SF' } }
|
|
308
|
+
}]
|
|
309
|
+
}]
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Streaming
|
|
316
|
+
|
|
317
|
+
### Event Types
|
|
318
|
+
|
|
319
|
+
Claude provides the most granular streaming events (6 types):
|
|
320
|
+
|
|
321
|
+
| Event Type | Purpose | Holo Mapping |
|
|
322
|
+
|------------|---------|--------------|
|
|
323
|
+
| `message_start` | Initialize message | `type: 'message_start'` |
|
|
324
|
+
| `content_block_start` | Begin content block (text/tool) | Used internally |
|
|
325
|
+
| `content_block_delta` | Incremental content | `type: 'content_delta'` |
|
|
326
|
+
| `content_block_stop` | End content block | Used internally |
|
|
327
|
+
| `message_delta` | Usage/finish updates | `type: 'message_delta'` |
|
|
328
|
+
| `message_stop` | Completion marker | `type: 'message_stop'` |
|
|
329
|
+
|
|
330
|
+
### Orchestration
|
|
331
|
+
|
|
332
|
+
The `ClaudeStreamTranslator` maintains state to:
|
|
333
|
+
1. Track content blocks by index
|
|
334
|
+
2. Accumulate text and tool input deltas
|
|
335
|
+
3. Extract complete tool calls on block completion
|
|
336
|
+
4. Preserve raw provider events in `provider_delta`
|
|
337
|
+
|
|
338
|
+
### Streaming Example
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
import { HoloStreamChunk } from '@holokai/sdk';
|
|
342
|
+
|
|
343
|
+
const stream = await claudeProvider.streamChat(request);
|
|
344
|
+
|
|
345
|
+
for await (const chunk: HoloStreamChunk of stream) {
|
|
346
|
+
switch (chunk.delta?.type) {
|
|
347
|
+
case 'message_start':
|
|
348
|
+
console.log('Message started:', chunk.id);
|
|
349
|
+
break;
|
|
350
|
+
case 'content_delta':
|
|
351
|
+
process.stdout.write(chunk.delta.delta.content ?? '');
|
|
352
|
+
break;
|
|
353
|
+
case 'message_delta':
|
|
354
|
+
console.log('Usage:', chunk.usage);
|
|
355
|
+
break;
|
|
356
|
+
case 'message_stop':
|
|
357
|
+
console.log('Complete. Reason:', chunk.finish_reason);
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Claude-Specific Features
|
|
366
|
+
|
|
367
|
+
### Extended Thinking
|
|
368
|
+
|
|
369
|
+
Enable extended thinking for Claude 3.5 Sonnet+ models:
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
const request: HoloRequest = {
|
|
373
|
+
model: 'claude-3-5-sonnet-20241022',
|
|
374
|
+
messages: [{ role: 'user', content: 'Solve this complex problem...' }],
|
|
375
|
+
// Provider-specific config (passed through)
|
|
376
|
+
provider_config: {
|
|
377
|
+
thinking: {
|
|
378
|
+
type: 'enabled',
|
|
379
|
+
budget_tokens: 5000
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
**Note**: Thinking blocks (`content[].type = 'thinking'`) are Claude-specific and not part of the portable Holo format. They're preserved in `provider_delta` for debugging.
|
|
386
|
+
|
|
387
|
+
### Prompt Caching
|
|
388
|
+
|
|
389
|
+
Reduce costs by caching reusable prompts:
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
// Provider-specific caching (requires Claude API beta)
|
|
393
|
+
const cachedMessages = [
|
|
394
|
+
{
|
|
395
|
+
role: 'user',
|
|
396
|
+
content: 'Large document content...',
|
|
397
|
+
cache_control: { type: 'ephemeral' } // Cache this message
|
|
398
|
+
}
|
|
399
|
+
];
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**Note**: Cache control is Claude-specific and handled at the provider level, not in Holo format.
|
|
403
|
+
|
|
404
|
+
### Beta Features
|
|
405
|
+
|
|
406
|
+
Access beta features via plugin configuration:
|
|
407
|
+
|
|
408
|
+
```json
|
|
409
|
+
{
|
|
410
|
+
"config": {
|
|
411
|
+
"betas": ["prompt-caching-2024-07-31"]
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Type Safety
|
|
419
|
+
|
|
420
|
+
### SDK Integration
|
|
421
|
+
|
|
422
|
+
This plugin uses strict SDK types exclusively:
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
import type {
|
|
426
|
+
HoloRequest,
|
|
427
|
+
HoloResponse,
|
|
428
|
+
HoloMessage,
|
|
429
|
+
HoloTool,
|
|
430
|
+
HoloJsonSchema // ✅ Proper JSON Schema types
|
|
431
|
+
} from '@holokai/sdk';
|
|
432
|
+
|
|
433
|
+
// ❌ NO: Record<string, unknown>
|
|
434
|
+
// ✅ YES: HoloJsonSchema
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Migration from Legacy Types
|
|
438
|
+
|
|
439
|
+
**Before** (Legacy provider):
|
|
440
|
+
```typescript
|
|
441
|
+
import { HoloTool } from '../../types/holo/requests';
|
|
442
|
+
|
|
443
|
+
interface HoloTool {
|
|
444
|
+
parameters?: Record<string, unknown>; // ❌ Loose typing
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
**After** (Plugin SDK):
|
|
449
|
+
```typescript
|
|
450
|
+
import type { HoloTool, HoloJsonSchema } from '@holokai/sdk';
|
|
451
|
+
|
|
452
|
+
interface HoloTool {
|
|
453
|
+
parameters?: HoloJsonSchema; // ✅ Strict JSON Schema Draft 7
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Type Safety
|
|
458
|
+
|
|
459
|
+
All interfaces use strict TypeScript types from `@holokai/sdk` for compile-time validation.
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Configuration Schema
|
|
464
|
+
|
|
465
|
+
The plugin exposes a JSON Schema for configuration validation:
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
{
|
|
469
|
+
apiKey: string; // Required
|
|
470
|
+
baseUrl?: string; // Optional custom endpoint
|
|
471
|
+
defaultModel?: string; // Fallback model
|
|
472
|
+
allowedModels?: string[]; // Model allowlist
|
|
473
|
+
timeoutMs?: number; // Request timeout (default: 60000)
|
|
474
|
+
maxRetries?: number; // Retry attempts (default: 2)
|
|
475
|
+
enableVision?: boolean; // Vision support (default: true)
|
|
476
|
+
logRequests?: boolean; // Observability (default: false)
|
|
477
|
+
telemetrySampleRate?: number;// Sampling rate (default: 1.0)
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
See [manifest.ts](./src/manifest.ts) for the complete schema.
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## Development
|
|
486
|
+
|
|
487
|
+
### Setup
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
# Install dependencies
|
|
491
|
+
npm install
|
|
492
|
+
|
|
493
|
+
# Build
|
|
494
|
+
npm run build
|
|
495
|
+
|
|
496
|
+
# Type checking
|
|
497
|
+
npm run type-check
|
|
498
|
+
|
|
499
|
+
# Run tests
|
|
500
|
+
npm test
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Testing
|
|
504
|
+
|
|
505
|
+
```bash
|
|
506
|
+
# Unit tests
|
|
507
|
+
npm test
|
|
508
|
+
|
|
509
|
+
# Integration tests (requires API key)
|
|
510
|
+
ANTHROPIC_API_KEY=sk-... npm run test:integration
|
|
511
|
+
|
|
512
|
+
# Watch mode
|
|
513
|
+
npm run test:watch
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Building
|
|
517
|
+
|
|
518
|
+
```bash
|
|
519
|
+
# Production build
|
|
520
|
+
npm run build
|
|
521
|
+
|
|
522
|
+
# Watch mode
|
|
523
|
+
npm run build:watch
|
|
524
|
+
|
|
525
|
+
# Clean
|
|
526
|
+
npm run clean
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## Related Documentation
|
|
532
|
+
|
|
533
|
+
### SDK Documentation
|
|
534
|
+
- [SDK README](../sdk/README.md) - Plugin development guide and templates
|
|
535
|
+
|
|
536
|
+
### Claude API Documentation
|
|
537
|
+
- [Official API Reference](https://docs.anthropic.com/claude/reference)
|
|
538
|
+
- [Streaming Guide](https://docs.anthropic.com/claude/reference/streaming)
|
|
539
|
+
- [Tool Use](https://docs.anthropic.com/claude/docs/tool-use)
|
|
540
|
+
- [Vision](https://docs.anthropic.com/claude/docs/vision)
|
|
541
|
+
- [Prompt Caching](https://docs.anthropic.com/claude/docs/prompt-caching)
|
|
542
|
+
|
|
543
|
+
### Migration Notes
|
|
544
|
+
- This plugin was extracted from the monolithic `src/providers/claude/` codebase
|
|
545
|
+
- Migration to plugin architecture is complete
|
|
546
|
+
|
|
547
|
+
---
|
|
548
|
+
|
|
549
|
+
## Contributing
|
|
550
|
+
|
|
551
|
+
### Adding Features
|
|
552
|
+
|
|
553
|
+
1. Update types in `@holokai/sdk` first (if needed)
|
|
554
|
+
2. Implement translator logic
|
|
555
|
+
3. Write tests (unit + integration)
|
|
556
|
+
4. Update this README
|
|
557
|
+
|
|
558
|
+
### Reporting Issues
|
|
559
|
+
|
|
560
|
+
Found a bug or have a feature request?
|
|
561
|
+
- GitHub Issues: https://github.com/holokai/holo-provider-claude/issues
|
|
562
|
+
- Include: Holo version, Claude model, request/response samples
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
## License
|
|
567
|
+
|
|
568
|
+
MIT © Holokai
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
## Changelog
|
|
573
|
+
|
|
574
|
+
### v0.1.0 (Current)
|
|
575
|
+
- ✅ Initial plugin release
|
|
576
|
+
- ✅ Extracted from monolithic architecture
|
|
577
|
+
- ✅ Migrated to SDK types
|
|
578
|
+
- ✅ Validated against Holo format spec
|
|
579
|
+
- ✅ Complete streaming orchestration
|
|
580
|
+
- ✅ Tool calling with extraction
|
|
581
|
+
- ✅ Vision/multimodal support
|
|
582
|
+
- ✅ Prompt caching support
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
**Last Updated**: 2025-12-18
|
|
587
|
+
**Plugin Version**: 0.1.0
|
|
588
|
+
**SDK Version**: ^0.1.0
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseAuditor, HoloWorkerRequest, HoloWorkerResponse, ProviderEnvelope } from "@holokai/sdk";
|
|
2
|
+
import { MessageCreateParamsBase } from "@anthropic-ai/sdk/resources/messages";
|
|
3
|
+
import { LlmRequest, LlmResponse } from "@holokai/sdk/core/entities";
|
|
4
|
+
export declare class ClaudeAuditor extends BaseAuditor {
|
|
5
|
+
readonly provider = "claude";
|
|
6
|
+
protected toHoloRequest(workerRequest: HoloWorkerRequest, llmRequest: Omit<LlmRequest, 'id'>): void;
|
|
7
|
+
protected mapProviderPayload(workerRequest: HoloWorkerRequest, llmRequest: Omit<LlmRequest, 'id'>): void;
|
|
8
|
+
protected collectResponseMetrics(workerResponse: HoloWorkerResponse, llmResponse: Omit<LlmResponse, 'id'>): void;
|
|
9
|
+
private extractUserPromptFromMessages;
|
|
10
|
+
protected createProviderEnvelope(payload: MessageCreateParamsBase): Promise<ProviderEnvelope>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=claude.auditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.auditor.d.ts","sourceRoot":"","sources":["../src/claude.auditor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAe,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAC/G,OAAO,EAAC,uBAAuB,EAAC,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAC,UAAU,EAAE,WAAW,EAAY,MAAM,4BAA4B,CAAC;AAE9E,qBACa,aAAc,SAAQ,WAAW;IAC1C,QAAQ,CAAC,QAAQ,YAAY;IAE7B,SAAS,CAAC,aAAa,CAAC,aAAa,EAAE,iBAAiB,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,IAAI;IAiBnG,SAAS,CAAC,kBAAkB,CAAC,aAAa,EAAE,iBAAiB,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,IAAI;IAiBxG,SAAS,CAAC,sBAAsB,CAC5B,cAAc,EAAE,kBAAkB,EAClC,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,GACrC,IAAI;IA+BP,OAAO,CAAC,6BAA6B;cAmBrB,sBAAsB,CAClC,OAAO,EAAE,uBAAuB,GACjC,OAAO,CAAC,gBAAgB,CAAC;CAc/B"}
|