@elevasis/core 0.46.0 → 0.47.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.
@@ -81,17 +81,18 @@ describe('AnthropicAdapter', () => {
81
81
  }
82
82
  }
83
83
 
84
- describe('isAnthropicModel', () => {
85
- it('returns true for claude models with anthropic provider', () => {
86
- expect(isAnthropicModel('claude-opus-4-5', 'anthropic')).toBe(true)
87
- expect(isAnthropicModel('claude-sonnet-4-5', 'anthropic')).toBe(true)
88
- expect(isAnthropicModel('claude-haiku-4-5', 'anthropic')).toBe(true)
89
- })
90
-
91
- it('returns false for claude models with other providers', () => {
92
- expect(isAnthropicModel('claude-opus-4-5', 'openrouter')).toBe(false)
93
- expect(isAnthropicModel('claude-sonnet-4-5', 'google')).toBe(false)
94
- })
84
+ describe('isAnthropicModel', () => {
85
+ it('returns true for claude models with anthropic provider', () => {
86
+ expect(isAnthropicModel('claude-opus-4-8', 'anthropic')).toBe(true)
87
+ expect(isAnthropicModel('claude-sonnet-4-6', 'anthropic')).toBe(true)
88
+ expect(isAnthropicModel('claude-haiku-4-5-20251001', 'anthropic')).toBe(true)
89
+ expect(isAnthropicModel('claude-haiku-4-5', 'anthropic')).toBe(true)
90
+ })
91
+
92
+ it('returns false for claude models with other providers', () => {
93
+ expect(isAnthropicModel('claude-opus-4-8', 'openrouter')).toBe(false)
94
+ expect(isAnthropicModel('claude-sonnet-4-6', 'google')).toBe(false)
95
+ })
95
96
 
96
97
  it('returns false for non-claude models', () => {
97
98
  expect(isAnthropicModel('gpt-5', 'anthropic')).toBe(false)
@@ -101,10 +102,10 @@ describe('AnthropicAdapter', () => {
101
102
 
102
103
  describe('Basic Configuration', () => {
103
104
  it('creates adapter without model options', async () => {
104
- const adapter = new AnthropicAdapter({
105
- apiKey: 'test-key',
106
- model: 'claude-sonnet-4-5'
107
- })
105
+ const adapter = new AnthropicAdapter({
106
+ apiKey: 'test-key',
107
+ model: 'claude-sonnet-4-6'
108
+ })
108
109
 
109
110
  mockStreamResponse(mockAnthropicResponse)
110
111
 
@@ -114,11 +115,11 @@ describe('AnthropicAdapter', () => {
114
115
  })
115
116
 
116
117
  it('creates adapter with model options', async () => {
117
- const adapter = new AnthropicAdapter({
118
- apiKey: 'test-key',
119
- model: 'claude-opus-4-5',
120
- modelOptions: {}
121
- })
118
+ const adapter = new AnthropicAdapter({
119
+ apiKey: 'test-key',
120
+ model: 'claude-opus-4-8',
121
+ modelOptions: {}
122
+ })
122
123
 
123
124
  mockStreamResponse(mockAnthropicResponse)
124
125
 
@@ -130,10 +131,10 @@ describe('AnthropicAdapter', () => {
130
131
 
131
132
  describe('Message Translation', () => {
132
133
  it('converts system messages to separate system field', async () => {
133
- const adapter = new AnthropicAdapter({
134
- apiKey: 'test-key',
135
- model: 'claude-sonnet-4-5'
136
- })
134
+ const adapter = new AnthropicAdapter({
135
+ apiKey: 'test-key',
136
+ model: 'claude-sonnet-4-6'
137
+ })
137
138
 
138
139
  mockStreamResponse(mockAnthropicResponse)
139
140
 
@@ -157,10 +158,10 @@ describe('AnthropicAdapter', () => {
157
158
  })
158
159
 
159
160
  it('combines multiple system messages', async () => {
160
- const adapter = new AnthropicAdapter({
161
- apiKey: 'test-key',
162
- model: 'claude-sonnet-4-5'
163
- })
161
+ const adapter = new AnthropicAdapter({
162
+ apiKey: 'test-key',
163
+ model: 'claude-sonnet-4-6'
164
+ })
164
165
 
165
166
  mockStreamResponse(mockAnthropicResponse)
166
167
 
@@ -179,10 +180,10 @@ describe('AnthropicAdapter', () => {
179
180
  })
180
181
 
181
182
  it('handles requests without system messages', async () => {
182
- const adapter = new AnthropicAdapter({
183
- apiKey: 'test-key',
184
- model: 'claude-sonnet-4-5'
185
- })
183
+ const adapter = new AnthropicAdapter({
184
+ apiKey: 'test-key',
185
+ model: 'claude-sonnet-4-6'
186
+ })
186
187
 
187
188
  mockStreamResponse(mockAnthropicResponse)
188
189
 
@@ -197,10 +198,10 @@ describe('AnthropicAdapter', () => {
197
198
  })
198
199
 
199
200
  it('preserves user and assistant roles', async () => {
200
- const adapter = new AnthropicAdapter({
201
- apiKey: 'test-key',
202
- model: 'claude-sonnet-4-5'
203
- })
201
+ const adapter = new AnthropicAdapter({
202
+ apiKey: 'test-key',
203
+ model: 'claude-sonnet-4-6'
204
+ })
204
205
 
205
206
  mockStreamResponse(mockAnthropicResponse)
206
207
 
@@ -223,10 +224,10 @@ describe('AnthropicAdapter', () => {
223
224
 
224
225
  describe('Tool-based Structured Output', () => {
225
226
  it('configures tool_use for structured output', async () => {
226
- const adapter = new AnthropicAdapter({
227
- apiKey: 'test-key',
228
- model: 'claude-sonnet-4-5'
229
- })
227
+ const adapter = new AnthropicAdapter({
228
+ apiKey: 'test-key',
229
+ model: 'claude-sonnet-4-6'
230
+ })
230
231
 
231
232
  mockStreamResponse(mockAnthropicResponse)
232
233
 
@@ -244,10 +245,10 @@ describe('AnthropicAdapter', () => {
244
245
  })
245
246
 
246
247
  it('extracts response from tool_use block', async () => {
247
- const adapter = new AnthropicAdapter({
248
- apiKey: 'test-key',
249
- model: 'claude-sonnet-4-5'
250
- })
248
+ const adapter = new AnthropicAdapter({
249
+ apiKey: 'test-key',
250
+ model: 'claude-sonnet-4-6'
251
+ })
251
252
 
252
253
  mockStreamResponse({
253
254
  content: [
@@ -278,10 +279,10 @@ describe('AnthropicAdapter', () => {
278
279
  })
279
280
 
280
281
  it('throws error when no tool_use block in response', async () => {
281
- const adapter = new AnthropicAdapter({
282
- apiKey: 'test-key',
283
- model: 'claude-sonnet-4-5'
284
- })
282
+ const adapter = new AnthropicAdapter({
283
+ apiKey: 'test-key',
284
+ model: 'claude-sonnet-4-6'
285
+ })
285
286
 
286
287
  mockStreamResponse({
287
288
  content: [{ type: 'text', text: 'Hello!' }],
@@ -296,10 +297,10 @@ describe('AnthropicAdapter', () => {
296
297
 
297
298
  describe('Usage Metadata', () => {
298
299
  it('calculates total tokens from input + output', async () => {
299
- const adapter = new AnthropicAdapter({
300
- apiKey: 'test-key',
301
- model: 'claude-sonnet-4-5'
302
- })
300
+ const adapter = new AnthropicAdapter({
301
+ apiKey: 'test-key',
302
+ model: 'claude-sonnet-4-6'
303
+ })
303
304
 
304
305
  mockStreamResponse({
305
306
  content: [mockAnthropicResponse.content[0]],
@@ -319,10 +320,10 @@ describe('AnthropicAdapter', () => {
319
320
  })
320
321
 
321
322
  it('extracts token usage correctly', async () => {
322
- const adapter = new AnthropicAdapter({
323
- apiKey: 'test-key',
324
- model: 'claude-sonnet-4-5'
325
- })
323
+ const adapter = new AnthropicAdapter({
324
+ apiKey: 'test-key',
325
+ model: 'claude-sonnet-4-6'
326
+ })
326
327
 
327
328
  mockStreamResponse(mockAnthropicResponse)
328
329
 
@@ -338,10 +339,10 @@ describe('AnthropicAdapter', () => {
338
339
 
339
340
  describe('MaxTokens Configuration', () => {
340
341
  it('passes maxOutputTokens to API', async () => {
341
- const adapter = new AnthropicAdapter({
342
- apiKey: 'test-key',
343
- model: 'claude-sonnet-4-5'
344
- })
342
+ const adapter = new AnthropicAdapter({
343
+ apiKey: 'test-key',
344
+ model: 'claude-sonnet-4-6'
345
+ })
345
346
 
346
347
  mockStreamResponse(mockAnthropicResponse)
347
348
 
@@ -355,10 +356,10 @@ describe('AnthropicAdapter', () => {
355
356
  })
356
357
 
357
358
  it('uses default 4000 when maxOutputTokens not specified', async () => {
358
- const adapter = new AnthropicAdapter({
359
- apiKey: 'test-key',
360
- model: 'claude-sonnet-4-5'
361
- })
359
+ const adapter = new AnthropicAdapter({
360
+ apiKey: 'test-key',
361
+ model: 'claude-sonnet-4-6'
362
+ })
362
363
 
363
364
  mockStreamResponse(mockAnthropicResponse)
364
365
 
@@ -373,12 +374,12 @@ describe('AnthropicAdapter', () => {
373
374
  })
374
375
  })
375
376
 
376
- describe('Temperature and TopP', () => {
377
- it('passes temperature to API', async () => {
378
- const adapter = new AnthropicAdapter({
379
- apiKey: 'test-key',
380
- model: 'claude-sonnet-4-5'
381
- })
377
+ describe('Temperature and TopP', () => {
378
+ it('passes temperature to API', async () => {
379
+ const adapter = new AnthropicAdapter({
380
+ apiKey: 'test-key',
381
+ model: 'claude-sonnet-4-6'
382
+ })
382
383
 
383
384
  mockStreamResponse(mockAnthropicResponse)
384
385
 
@@ -392,10 +393,10 @@ describe('AnthropicAdapter', () => {
392
393
  })
393
394
 
394
395
  it('passes topP to API', async () => {
395
- const adapter = new AnthropicAdapter({
396
- apiKey: 'test-key',
397
- model: 'claude-sonnet-4-5'
398
- })
396
+ const adapter = new AnthropicAdapter({
397
+ apiKey: 'test-key',
398
+ model: 'claude-sonnet-4-6'
399
+ })
399
400
 
400
401
  mockStreamResponse(mockAnthropicResponse)
401
402
 
@@ -404,17 +405,37 @@ describe('AnthropicAdapter', () => {
404
405
  topP: 0.9
405
406
  })
406
407
 
407
- const callParams = mockMessagesStream.mock.calls[0][0]
408
- expect(callParams.top_p).toBe(0.9)
409
- })
410
- })
408
+ const callParams = mockMessagesStream.mock.calls[0][0]
409
+ expect(callParams.top_p).toBe(0.9)
410
+ })
411
+
412
+ it('omits sampling parameters for Opus 4.8', async () => {
413
+ const adapter = new AnthropicAdapter({
414
+ apiKey: 'test-key',
415
+ model: 'claude-opus-4-8'
416
+ })
417
+
418
+ mockStreamResponse(mockAnthropicResponse)
419
+
420
+ await adapter.generate({
421
+ ...baseRequest,
422
+ temperature: 0.7,
423
+ topP: 0.9
424
+ })
425
+
426
+ const callParams = mockMessagesStream.mock.calls[0][0]
427
+ expect(callParams).not.toHaveProperty('temperature')
428
+ expect(callParams).not.toHaveProperty('top_p')
429
+ expect(callParams).not.toHaveProperty('top_k')
430
+ })
431
+ })
411
432
 
412
433
  describe('Error Handling', () => {
413
434
  it('propagates API errors', async () => {
414
- const adapter = new AnthropicAdapter({
415
- apiKey: 'test-key',
416
- model: 'claude-sonnet-4-5'
417
- })
435
+ const adapter = new AnthropicAdapter({
436
+ apiKey: 'test-key',
437
+ model: 'claude-sonnet-4-6'
438
+ })
418
439
 
419
440
  const apiError = new Error('API rate limit exceeded')
420
441
  mockStreamError(apiError)
@@ -425,10 +446,10 @@ describe('AnthropicAdapter', () => {
425
446
 
426
447
  describe('Multiple Calls', () => {
427
448
  it('reuses client across multiple generate calls', async () => {
428
- const adapter = new AnthropicAdapter({
429
- apiKey: 'test-key',
430
- model: 'claude-opus-4-5'
431
- })
449
+ const adapter = new AnthropicAdapter({
450
+ apiKey: 'test-key',
451
+ model: 'claude-sonnet-4-6'
452
+ })
432
453
 
433
454
  mockStreamResponsePersistent(mockAnthropicResponse)
434
455
 
@@ -443,7 +464,7 @@ describe('AnthropicAdapter', () => {
443
464
  })
444
465
 
445
466
  describe('Model Selection', () => {
446
- it.each(['claude-opus-4-5', 'claude-sonnet-4-5', 'claude-haiku-4-5'] as const)(
467
+ it.each(['claude-opus-4-8', 'claude-sonnet-4-6', 'claude-haiku-4-5-20251001', 'claude-haiku-4-5'] as const)(
447
468
  'supports %s model',
448
469
  async (model) => {
449
470
  const adapter = new AnthropicAdapter({
@@ -25,19 +25,34 @@ export interface AnthropicAdapterConfig {
25
25
  }
26
26
 
27
27
  /**
28
- * Check if the model and provider combination is for Anthropic
29
- *
30
- * @param model - Model identifier (e.g., 'claude-opus-4-5-20251101')
31
- * @param provider - Provider name
32
- * @returns True if this is an Anthropic model configuration
33
- */
34
- export function isAnthropicModel(model: LLMModel, provider: string): boolean {
35
- return model.startsWith('claude-') && provider === 'anthropic'
36
- }
37
-
38
- /**
39
- * Anthropic Claude Adapter - Implements universal protocol
40
- * Uses tool_use for structured output (Anthropic's recommended approach)
28
+ * Check if the model and provider combination is for Anthropic
29
+ *
30
+ * @param model - Model identifier (e.g., 'claude-opus-4-8')
31
+ * @param provider - Provider name
32
+ * @returns True if this is an Anthropic model configuration
33
+ */
34
+ export function isAnthropicModel(model: LLMModel, provider: string): boolean {
35
+ return model.startsWith('claude-') && provider === 'anthropic'
36
+ }
37
+
38
+ function shouldOmitSamplingParameters(model: LLMModel): boolean {
39
+ return model === 'claude-opus-4-8'
40
+ }
41
+
42
+ function getSamplingParameters(model: LLMModel, request: LLMGenerateRequest): { temperature?: number; top_p?: number } {
43
+ if (shouldOmitSamplingParameters(model)) {
44
+ return {}
45
+ }
46
+
47
+ return {
48
+ ...(request.temperature !== undefined ? { temperature: request.temperature } : {}),
49
+ ...(request.topP !== undefined ? { top_p: request.topP } : {})
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Anthropic Claude Adapter - Implements universal protocol
55
+ * Uses tool_use for structured output (Anthropic's recommended approach)
41
56
  *
42
57
  * Key differences from other adapters:
43
58
  * - System messages go in separate `system` field (not in messages array)
@@ -87,10 +102,10 @@ export class AnthropicAdapter implements LLMAdapter {
87
102
  // This guarantees schema compliance without requiring JSON mode
88
103
  // Stream + finalMessage() to avoid SDK non-streaming timeout rejection
89
104
  // at high max_tokens values (SDK calculates estimated time > 10 min → error)
90
- const stream = client.messages.stream(
91
- {
92
- model: this.model,
93
- max_tokens: request.maxOutputTokens || 4000, // Required for Anthropic
105
+ const stream = client.messages.stream(
106
+ {
107
+ model: this.model,
108
+ max_tokens: request.maxOutputTokens || 4000, // Required for Anthropic
94
109
  system: systemContent,
95
110
  messages: anthropicMessages,
96
111
  tools: [
@@ -99,13 +114,12 @@ export class AnthropicAdapter implements LLMAdapter {
99
114
  description: 'Return structured output matching the required schema',
100
115
  input_schema: request.responseSchema as import('@anthropic-ai/sdk').Anthropic.Tool['input_schema']
101
116
  }
102
- ],
103
- tool_choice: { type: 'tool', name: 'structured_output' },
104
- temperature: request.temperature,
105
- top_p: request.topP
106
- },
107
- { signal: composeSignal(DEFAULT_LLM_TIMEOUT, request.signal) }
108
- )
117
+ ],
118
+ tool_choice: { type: 'tool', name: 'structured_output' },
119
+ ...getSamplingParameters(this.model, request)
120
+ },
121
+ { signal: composeSignal(DEFAULT_LLM_TIMEOUT, request.signal) }
122
+ )
109
123
  const response = await stream.finalMessage()
110
124
 
111
125
  // Extract structured output from tool_use block
@@ -26,10 +26,15 @@ export type OpenRouterModel = 'openrouter/z-ai/glm-5'
26
26
  */
27
27
  export type GoogleModel = 'gemini-3-flash-preview' | 'gemini-3.1-flash-lite-preview'
28
28
 
29
- /**
30
- * Supported Anthropic models (direct SDK access via @anthropic-ai/sdk)
31
- */
32
- export type AnthropicModel = 'claude-sonnet-4-5'
29
+ /**
30
+ * Supported Anthropic models (direct SDK access via @anthropic-ai/sdk)
31
+ */
32
+ export type AnthropicModel =
33
+ | 'claude-opus-4-8'
34
+ | 'claude-sonnet-4-6'
35
+ | 'claude-haiku-4-5-20251001'
36
+ | 'claude-haiku-4-5'
37
+ | 'claude-sonnet-4-5'
33
38
 
34
39
  /** Supported LLM models */
35
40
  export type LLMModel = OpenAIModel | OpenRouterModel | GoogleModel | AnthropicModel | 'mock'
@@ -122,26 +127,48 @@ export const GoogleConfigSchema = z.object({
122
127
  modelOptions: GoogleOptionsSchema.optional()
123
128
  })
124
129
 
125
- /**
126
- * Anthropic model options schema
127
- * Currently empty - future options: budget_tokens for extended thinking
128
- */
129
- const AnthropicOptionsSchema = z.object({})
130
-
131
- /**
132
- * Anthropic config schema
133
- * Validates ModelConfig for Anthropic provider (direct SDK access)
134
- */
135
- export const AnthropicConfigSchema = z.object({
136
- model: z.enum(['claude-sonnet-4-5']),
137
- provider: z.literal('anthropic'),
138
- apiKey: z.string(),
139
- temperature: z.number().min(0).max(1).optional(),
140
- maxOutputTokens: z.number().min(1000).optional(), // Anthropic requires max_tokens
141
- topP: z.number().min(0).max(1).optional(),
142
- modelOptions: AnthropicOptionsSchema.optional()
143
- })
130
+ /**
131
+ * Anthropic model options schema
132
+ * Currently empty - future options must be added per supported model family
133
+ */
134
+ const AnthropicOptionsSchema = z.object({}).strict()
144
135
 
136
+ /**
137
+ * Anthropic config schema
138
+ * Validates ModelConfig for Anthropic provider (direct SDK access)
139
+ */
140
+ const AnthropicStandardConfigSchema = z.object({
141
+ model: z.enum([
142
+ 'claude-sonnet-4-6',
143
+ 'claude-haiku-4-5-20251001',
144
+ 'claude-haiku-4-5',
145
+ 'claude-sonnet-4-5'
146
+ ]),
147
+ provider: z.literal('anthropic'),
148
+ apiKey: z.string(),
149
+ temperature: z.number().min(0).max(1).optional(),
150
+ maxOutputTokens: z.number().min(1000).max(64000).optional(), // Anthropic requires max_tokens
151
+ topP: z.number().min(0).max(1).optional(),
152
+ modelOptions: AnthropicOptionsSchema.optional()
153
+ })
154
+
155
+ const AnthropicOpus48ConfigSchema = z.object({
156
+ model: z.literal('claude-opus-4-8'),
157
+ provider: z.literal('anthropic'),
158
+ apiKey: z.string(),
159
+ temperature: z.literal(1).optional(),
160
+ maxOutputTokens: z.number().min(1000).max(128000).optional(), // Anthropic requires max_tokens
161
+ topP: z.literal(1).optional(),
162
+ topK: z.undefined().optional(),
163
+ top_k: z.undefined().optional(),
164
+ modelOptions: AnthropicOptionsSchema.optional()
165
+ })
166
+
167
+ export const AnthropicConfigSchema = z.discriminatedUnion('model', [
168
+ AnthropicOpus48ConfigSchema,
169
+ AnthropicStandardConfigSchema
170
+ ])
171
+
145
172
  /**
146
173
  * Infer TypeScript types from schemas
147
174
  */
@@ -191,16 +218,18 @@ export interface ModelInfo {
191
218
  minTokens: number
192
219
  /** Recommended tokens for production use (typically 2x minimum) */
193
220
  recommendedTokens: number
194
- /** Maximum context window size (total tokens: input + output) */
195
- maxTokens: number
196
- /** Model category for grouping and documentation */
197
- category: 'reasoning' | 'standard' | 'embedding'
198
- /** Zod schema for validating complete ModelConfig (replaces constraints + optionsSchema) */
199
- configSchema?: z.ZodType<ModelConfig>
200
- }
221
+ /** Maximum context window size (total tokens: input + output) */
222
+ maxTokens: number
223
+ /** Maximum output tokens supported by the synchronous generation API */
224
+ maxOutputTokens?: number
225
+ /** Model category for grouping and documentation */
226
+ category: 'reasoning' | 'standard' | 'embedding'
227
+ /** Zod schema for validating complete ModelConfig (replaces constraints + optionsSchema) */
228
+ configSchema?: z.ZodType<ModelConfig>
229
+ }
201
230
 
202
- // Model configuration as of 2026-03-17
203
- export const MODEL_INFO: Record<LLMModel, ModelInfo> = {
231
+ // Model configuration as of 2026-06-09
232
+ export const MODEL_INFO: Record<LLMModel, ModelInfo> = {
204
233
  // OpenAI GPT-5 (Reasoning Models)
205
234
  'gpt-5': {
206
235
  inputCostPer1M: 125, // $1.25 per 1M tokens
@@ -268,17 +297,58 @@ export const MODEL_INFO: Record<LLMModel, ModelInfo> = {
268
297
  category: 'standard',
269
298
  configSchema: GoogleConfigSchema
270
299
  },
271
- // Anthropic Claude Models (direct SDK access via @anthropic-ai/sdk)
272
- 'claude-sonnet-4-5': {
273
- inputCostPer1M: 300, // $3.00 per 1M tokens
274
- outputCostPer1M: 1500, // $15.00 per 1M tokens
275
- minTokens: 4000,
276
- recommendedTokens: 8000,
277
- maxTokens: 200000, // 200k context window
278
- category: 'standard',
279
- configSchema: AnthropicConfigSchema
280
- }
281
- }
300
+ // Anthropic Claude Models (direct SDK access via @anthropic-ai/sdk)
301
+ 'claude-opus-4-8': {
302
+ inputCostPer1M: 500, // $5.00 per 1M tokens
303
+ outputCostPer1M: 2500, // $25.00 per 1M tokens
304
+ minTokens: 4000,
305
+ recommendedTokens: 8000,
306
+ maxTokens: 1000000, // 1M context window
307
+ maxOutputTokens: 128000,
308
+ category: 'reasoning',
309
+ configSchema: AnthropicConfigSchema
310
+ },
311
+ 'claude-sonnet-4-6': {
312
+ inputCostPer1M: 300, // $3.00 per 1M tokens
313
+ outputCostPer1M: 1500, // $15.00 per 1M tokens
314
+ minTokens: 4000,
315
+ recommendedTokens: 8000,
316
+ maxTokens: 1000000, // 1M context window
317
+ maxOutputTokens: 64000,
318
+ category: 'standard',
319
+ configSchema: AnthropicConfigSchema
320
+ },
321
+ 'claude-haiku-4-5-20251001': {
322
+ inputCostPer1M: 100, // $1.00 per 1M tokens
323
+ outputCostPer1M: 500, // $5.00 per 1M tokens
324
+ minTokens: 4000,
325
+ recommendedTokens: 8000,
326
+ maxTokens: 200000, // 200k context window
327
+ maxOutputTokens: 64000,
328
+ category: 'standard',
329
+ configSchema: AnthropicConfigSchema
330
+ },
331
+ 'claude-haiku-4-5': {
332
+ inputCostPer1M: 100, // $1.00 per 1M tokens
333
+ outputCostPer1M: 500, // $5.00 per 1M tokens
334
+ minTokens: 4000,
335
+ recommendedTokens: 8000,
336
+ maxTokens: 200000, // 200k context window
337
+ maxOutputTokens: 64000,
338
+ category: 'standard',
339
+ configSchema: AnthropicConfigSchema
340
+ },
341
+ 'claude-sonnet-4-5': {
342
+ inputCostPer1M: 300, // $3.00 per 1M tokens
343
+ outputCostPer1M: 1500, // $15.00 per 1M tokens
344
+ minTokens: 4000,
345
+ recommendedTokens: 8000,
346
+ maxTokens: 200000, // 200k context window
347
+ maxOutputTokens: 64000,
348
+ category: 'standard',
349
+ configSchema: AnthropicConfigSchema
350
+ }
351
+ }
282
352
 
283
353
  /**
284
354
  * Get model information (pricing and token requirements)
@@ -22,17 +22,19 @@ export type {
22
22
 
23
23
  // Session validation schemas
24
24
  export {
25
- CreateSessionSchema,
26
- ExecuteTurnSchema,
27
- ListSessionsQuerySchema,
28
- SessionIdParamSchema,
29
- ExecutionIdParamsSchema,
30
- WebSocketSessionTurnSchema,
31
- type CreateSessionInput,
32
- type ExecuteTurnInput,
33
- type ListSessionsQuery,
34
- type WebSocketSessionTurnMessage
35
- } from './sessions'
25
+ CreateSessionSchema,
26
+ ExecuteTurnSchema,
27
+ ListSessionsQuerySchema,
28
+ SessionMessagesQuerySchema,
29
+ SessionIdParamSchema,
30
+ ExecutionIdParamsSchema,
31
+ WebSocketSessionTurnSchema,
32
+ type CreateSessionInput,
33
+ type ExecuteTurnInput,
34
+ type ListSessionsQuery,
35
+ type SessionMessagesQuery,
36
+ type WebSocketSessionTurnMessage
37
+ } from './sessions'
36
38
 
37
39
  // Notification types and validation schemas
38
40
  export * from './notifications/index'
@@ -46,5 +48,8 @@ export * from './activities/index'
46
48
  // Triggers (includes webhook providers and trigger definitions)
47
49
  export * from './triggers/index'
48
50
 
49
- // Debug Logs
50
- export * from './debug-logs/index'
51
+ // Debug Logs
52
+ export * from './debug-logs/index'
53
+
54
+ // Public agent chat route schemas
55
+ export * from './public-agent-chat'
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod'
2
+ import { UuidSchema } from '../../platform/utils/validation'
3
+
4
+ export const PublicAgentChatSlugParamSchema = z
5
+ .object({
6
+ slug: z.string().min(1).max(120).regex(/^[a-zA-Z0-9._-]+$/)
7
+ })
8
+ .strict()
9
+
10
+ export const PublicAgentChatSessionParamSchema = z
11
+ .object({
12
+ sessionId: UuidSchema
13
+ })
14
+ .strict()
15
+
16
+ export const PublicAgentChatAuthorizeSchema = z
17
+ .object({
18
+ code: z.string().min(1).max(200).optional(),
19
+ visitorId: z.string().min(1).max(120).optional()
20
+ })
21
+ .strict()
22
+
23
+ export const PublicAgentChatCreateSessionSchema = z
24
+ .object({
25
+ capabilityToken: z.string().min(32).optional(),
26
+ metadata: z.record(z.string(), z.unknown()).optional()
27
+ })
28
+ .strict()
29
+
30
+ export const PublicAgentChatCapabilityQuerySchema = z
31
+ .object({
32
+ token: z.string().min(32)
33
+ })
34
+ .strict()
35
+
36
+ export type PublicAgentChatSlugParams = z.infer<typeof PublicAgentChatSlugParamSchema>
37
+ export type PublicAgentChatSessionParams = z.infer<typeof PublicAgentChatSessionParamSchema>
38
+ export type PublicAgentChatAuthorizeInput = z.infer<typeof PublicAgentChatAuthorizeSchema>
39
+ export type PublicAgentChatCreateSessionInput = z.infer<typeof PublicAgentChatCreateSessionSchema>
40
+ export type PublicAgentChatCapabilityQuery = z.infer<typeof PublicAgentChatCapabilityQuerySchema>