cadenya 0.23.0 → 0.25.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.
@@ -8,22 +8,29 @@ module Cadenya
8
8
  T.any(Cadenya::AIProviderKeySpec, Cadenya::Internal::AnyHash)
9
9
  end
10
10
 
11
- # The provider credential. Accepted on create/update; never populated in responses
12
- # (the server returns an empty value to avoid leaking it).
13
- sig { returns(T.nilable(String)) }
14
- attr_reader :api_key
11
+ # AIProviderConfig holds non-secret, provider-specific settings. The set case must
12
+ # correspond to AIProviderKeySpec.provider. Providers with no settings (Anthropic,
13
+ # Gemini) simply leave this unset. The endpoint of a named provider is fixed and
14
+ # intentionally not overridable here; use the OpenAI-compatible provider to target
15
+ # a custom endpoint.
16
+ sig { returns(T.nilable(Cadenya::AIProviderKeySpec::Config)) }
17
+ attr_reader :config
15
18
 
16
- sig { params(api_key: String).void }
17
- attr_writer :api_key
19
+ sig { params(config: Cadenya::AIProviderKeySpec::Config::OrHash).void }
20
+ attr_writer :config
18
21
 
19
- # OpenRouterConfig holds OpenRouter-specific settings. Empty for now; it exists as
20
- # the oneof seam so provider-specific options (region, base URL, etc.) can be
21
- # added later without restructuring the spec.
22
- sig { returns(T.nilable(T.anything)) }
23
- attr_reader :openrouter
22
+ # AIProviderCredential is the secret material used to authenticate with a
23
+ # provider. The set case must correspond to AIProviderKeySpec.provider. The server
24
+ # encrypts the serialized message at rest and never returns it on reads.
25
+ sig { returns(T.nilable(Cadenya::AIProviderKeySpec::Credentials)) }
26
+ attr_reader :credentials
24
27
 
25
- sig { params(openrouter: T.anything).void }
26
- attr_writer :openrouter
28
+ sig do
29
+ params(
30
+ credentials: Cadenya::AIProviderKeySpec::Credentials::OrHash
31
+ ).void
32
+ end
33
+ attr_writer :credentials
27
34
 
28
35
  # The AI provider this key authenticates against.
29
36
  sig { returns(T.nilable(Cadenya::AIProviderKeySpec::Provider::OrSymbol)) }
@@ -36,19 +43,22 @@ module Cadenya
36
43
 
37
44
  sig do
38
45
  params(
39
- api_key: String,
40
- openrouter: T.anything,
46
+ config: Cadenya::AIProviderKeySpec::Config::OrHash,
47
+ credentials: Cadenya::AIProviderKeySpec::Credentials::OrHash,
41
48
  provider: Cadenya::AIProviderKeySpec::Provider::OrSymbol
42
49
  ).returns(T.attached_class)
43
50
  end
44
51
  def self.new(
45
- # The provider credential. Accepted on create/update; never populated in responses
46
- # (the server returns an empty value to avoid leaking it).
47
- api_key: nil,
48
- # OpenRouterConfig holds OpenRouter-specific settings. Empty for now; it exists as
49
- # the oneof seam so provider-specific options (region, base URL, etc.) can be
50
- # added later without restructuring the spec.
51
- openrouter: nil,
52
+ # AIProviderConfig holds non-secret, provider-specific settings. The set case must
53
+ # correspond to AIProviderKeySpec.provider. Providers with no settings (Anthropic,
54
+ # Gemini) simply leave this unset. The endpoint of a named provider is fixed and
55
+ # intentionally not overridable here; use the OpenAI-compatible provider to target
56
+ # a custom endpoint.
57
+ config: nil,
58
+ # AIProviderCredential is the secret material used to authenticate with a
59
+ # provider. The set case must correspond to AIProviderKeySpec.provider. The server
60
+ # encrypts the serialized message at rest and never returns it on reads.
61
+ credentials: nil,
52
62
  # The AI provider this key authenticates against.
53
63
  provider: nil
54
64
  )
@@ -57,8 +67,8 @@ module Cadenya
57
67
  sig do
58
68
  override.returns(
59
69
  {
60
- api_key: String,
61
- openrouter: T.anything,
70
+ config: Cadenya::AIProviderKeySpec::Config,
71
+ credentials: Cadenya::AIProviderKeySpec::Credentials,
62
72
  provider: Cadenya::AIProviderKeySpec::Provider::OrSymbol
63
73
  }
64
74
  )
@@ -66,6 +76,315 @@ module Cadenya
66
76
  def to_hash
67
77
  end
68
78
 
79
+ class Config < Cadenya::Internal::Type::BaseModel
80
+ OrHash =
81
+ T.type_alias do
82
+ T.any(
83
+ Cadenya::AIProviderKeySpec::Config,
84
+ Cadenya::Internal::AnyHash
85
+ )
86
+ end
87
+
88
+ # OpenAIConfig holds OpenAI-specific settings.
89
+ sig { returns(T.nilable(Cadenya::AIProviderKeySpec::Config::OpenAI)) }
90
+ attr_reader :openai
91
+
92
+ sig do
93
+ params(
94
+ openai: Cadenya::AIProviderKeySpec::Config::OpenAI::OrHash
95
+ ).void
96
+ end
97
+ attr_writer :openai
98
+
99
+ # OpenAICompatibleConfig configures a generic endpoint that speaks the OpenAI Chat
100
+ # Completions API. The base URL is required and its model catalog is discovered
101
+ # live via GET {base_url}/models.
102
+ sig do
103
+ returns(
104
+ T.nilable(Cadenya::AIProviderKeySpec::Config::OpenAICompatible)
105
+ )
106
+ end
107
+ attr_reader :openai_compatible
108
+
109
+ sig do
110
+ params(
111
+ openai_compatible:
112
+ Cadenya::AIProviderKeySpec::Config::OpenAICompatible::OrHash
113
+ ).void
114
+ end
115
+ attr_writer :openai_compatible
116
+
117
+ # OpenRouterConfig holds OpenRouter-specific settings.
118
+ sig do
119
+ returns(T.nilable(Cadenya::AIProviderKeySpec::Config::Openrouter))
120
+ end
121
+ attr_reader :openrouter
122
+
123
+ sig do
124
+ params(
125
+ openrouter: Cadenya::AIProviderKeySpec::Config::Openrouter::OrHash
126
+ ).void
127
+ end
128
+ attr_writer :openrouter
129
+
130
+ # AIProviderConfig holds non-secret, provider-specific settings. The set case must
131
+ # correspond to AIProviderKeySpec.provider. Providers with no settings (Anthropic,
132
+ # Gemini) simply leave this unset. The endpoint of a named provider is fixed and
133
+ # intentionally not overridable here; use the OpenAI-compatible provider to target
134
+ # a custom endpoint.
135
+ sig do
136
+ params(
137
+ openai: Cadenya::AIProviderKeySpec::Config::OpenAI::OrHash,
138
+ openai_compatible:
139
+ Cadenya::AIProviderKeySpec::Config::OpenAICompatible::OrHash,
140
+ openrouter: Cadenya::AIProviderKeySpec::Config::Openrouter::OrHash
141
+ ).returns(T.attached_class)
142
+ end
143
+ def self.new(
144
+ # OpenAIConfig holds OpenAI-specific settings.
145
+ openai: nil,
146
+ # OpenAICompatibleConfig configures a generic endpoint that speaks the OpenAI Chat
147
+ # Completions API. The base URL is required and its model catalog is discovered
148
+ # live via GET {base_url}/models.
149
+ openai_compatible: nil,
150
+ # OpenRouterConfig holds OpenRouter-specific settings.
151
+ openrouter: nil
152
+ )
153
+ end
154
+
155
+ sig do
156
+ override.returns(
157
+ {
158
+ openai: Cadenya::AIProviderKeySpec::Config::OpenAI,
159
+ openai_compatible:
160
+ Cadenya::AIProviderKeySpec::Config::OpenAICompatible,
161
+ openrouter: Cadenya::AIProviderKeySpec::Config::Openrouter
162
+ }
163
+ )
164
+ end
165
+ def to_hash
166
+ end
167
+
168
+ class OpenAI < Cadenya::Internal::Type::BaseModel
169
+ OrHash =
170
+ T.type_alias do
171
+ T.any(
172
+ Cadenya::AIProviderKeySpec::Config::OpenAI,
173
+ Cadenya::Internal::AnyHash
174
+ )
175
+ end
176
+
177
+ # Sent as the OpenAI-Organization header when set.
178
+ sig { returns(T.nilable(String)) }
179
+ attr_reader :organization_id
180
+
181
+ sig { params(organization_id: String).void }
182
+ attr_writer :organization_id
183
+
184
+ # Sent as the OpenAI-Project header when set.
185
+ sig { returns(T.nilable(String)) }
186
+ attr_reader :project_id
187
+
188
+ sig { params(project_id: String).void }
189
+ attr_writer :project_id
190
+
191
+ # OpenAIConfig holds OpenAI-specific settings.
192
+ sig do
193
+ params(organization_id: String, project_id: String).returns(
194
+ T.attached_class
195
+ )
196
+ end
197
+ def self.new(
198
+ # Sent as the OpenAI-Organization header when set.
199
+ organization_id: nil,
200
+ # Sent as the OpenAI-Project header when set.
201
+ project_id: nil
202
+ )
203
+ end
204
+
205
+ sig do
206
+ override.returns({ organization_id: String, project_id: String })
207
+ end
208
+ def to_hash
209
+ end
210
+ end
211
+
212
+ class OpenAICompatible < Cadenya::Internal::Type::BaseModel
213
+ OrHash =
214
+ T.type_alias do
215
+ T.any(
216
+ Cadenya::AIProviderKeySpec::Config::OpenAICompatible,
217
+ Cadenya::Internal::AnyHash
218
+ )
219
+ end
220
+
221
+ sig { returns(T.nilable(String)) }
222
+ attr_reader :base_url
223
+
224
+ sig { params(base_url: String).void }
225
+ attr_writer :base_url
226
+
227
+ # OpenAICompatibleConfig configures a generic endpoint that speaks the OpenAI Chat
228
+ # Completions API. The base URL is required and its model catalog is discovered
229
+ # live via GET {base_url}/models.
230
+ sig { params(base_url: String).returns(T.attached_class) }
231
+ def self.new(base_url: nil)
232
+ end
233
+
234
+ sig { override.returns({ base_url: String }) }
235
+ def to_hash
236
+ end
237
+ end
238
+
239
+ class Openrouter < Cadenya::Internal::Type::BaseModel
240
+ OrHash =
241
+ T.type_alias do
242
+ T.any(
243
+ Cadenya::AIProviderKeySpec::Config::Openrouter,
244
+ Cadenya::Internal::AnyHash
245
+ )
246
+ end
247
+
248
+ # Data-residency region (e.g. "us", "eu"). Empty uses the provider default.
249
+ sig { returns(T.nilable(String)) }
250
+ attr_reader :region
251
+
252
+ sig { params(region: String).void }
253
+ attr_writer :region
254
+
255
+ # OpenRouterConfig holds OpenRouter-specific settings.
256
+ sig { params(region: String).returns(T.attached_class) }
257
+ def self.new(
258
+ # Data-residency region (e.g. "us", "eu"). Empty uses the provider default.
259
+ region: nil
260
+ )
261
+ end
262
+
263
+ sig { override.returns({ region: String }) }
264
+ def to_hash
265
+ end
266
+ end
267
+ end
268
+
269
+ class Credentials < Cadenya::Internal::Type::BaseModel
270
+ OrHash =
271
+ T.type_alias do
272
+ T.any(
273
+ Cadenya::AIProviderKeySpec::Credentials,
274
+ Cadenya::Internal::AnyHash
275
+ )
276
+ end
277
+
278
+ # CredentialAPIKey carries a single bearer/header API key.
279
+ sig do
280
+ returns(T.nilable(Cadenya::AIProviderKeySpec::Credentials::APIKey))
281
+ end
282
+ attr_reader :api_key
283
+
284
+ sig do
285
+ params(
286
+ api_key: Cadenya::AIProviderKeySpec::Credentials::APIKey::OrHash
287
+ ).void
288
+ end
289
+ attr_writer :api_key
290
+
291
+ # CredentialHeaders carries arbitrary HTTP headers sent with every request to the
292
+ # provider (e.g. {"Authorization": "Bearer ...", "X-Api-Key": "..."}).
293
+ sig do
294
+ returns(T.nilable(Cadenya::AIProviderKeySpec::Credentials::Headers))
295
+ end
296
+ attr_reader :headers
297
+
298
+ sig do
299
+ params(
300
+ headers: Cadenya::AIProviderKeySpec::Credentials::Headers::OrHash
301
+ ).void
302
+ end
303
+ attr_writer :headers
304
+
305
+ # AIProviderCredential is the secret material used to authenticate with a
306
+ # provider. The set case must correspond to AIProviderKeySpec.provider. The server
307
+ # encrypts the serialized message at rest and never returns it on reads.
308
+ sig do
309
+ params(
310
+ api_key: Cadenya::AIProviderKeySpec::Credentials::APIKey::OrHash,
311
+ headers: Cadenya::AIProviderKeySpec::Credentials::Headers::OrHash
312
+ ).returns(T.attached_class)
313
+ end
314
+ def self.new(
315
+ # CredentialAPIKey carries a single bearer/header API key.
316
+ api_key: nil,
317
+ # CredentialHeaders carries arbitrary HTTP headers sent with every request to the
318
+ # provider (e.g. {"Authorization": "Bearer ...", "X-Api-Key": "..."}).
319
+ headers: nil
320
+ )
321
+ end
322
+
323
+ sig do
324
+ override.returns(
325
+ {
326
+ api_key: Cadenya::AIProviderKeySpec::Credentials::APIKey,
327
+ headers: Cadenya::AIProviderKeySpec::Credentials::Headers
328
+ }
329
+ )
330
+ end
331
+ def to_hash
332
+ end
333
+
334
+ class APIKey < Cadenya::Internal::Type::BaseModel
335
+ OrHash =
336
+ T.type_alias do
337
+ T.any(
338
+ Cadenya::AIProviderKeySpec::Credentials::APIKey,
339
+ Cadenya::Internal::AnyHash
340
+ )
341
+ end
342
+
343
+ sig { returns(T.nilable(String)) }
344
+ attr_reader :api_key
345
+
346
+ sig { params(api_key: String).void }
347
+ attr_writer :api_key
348
+
349
+ # CredentialAPIKey carries a single bearer/header API key.
350
+ sig { params(api_key: String).returns(T.attached_class) }
351
+ def self.new(api_key: nil)
352
+ end
353
+
354
+ sig { override.returns({ api_key: String }) }
355
+ def to_hash
356
+ end
357
+ end
358
+
359
+ class Headers < Cadenya::Internal::Type::BaseModel
360
+ OrHash =
361
+ T.type_alias do
362
+ T.any(
363
+ Cadenya::AIProviderKeySpec::Credentials::Headers,
364
+ Cadenya::Internal::AnyHash
365
+ )
366
+ end
367
+
368
+ sig { returns(T.nilable(T::Hash[Symbol, String])) }
369
+ attr_reader :headers
370
+
371
+ sig { params(headers: T::Hash[Symbol, String]).void }
372
+ attr_writer :headers
373
+
374
+ # CredentialHeaders carries arbitrary HTTP headers sent with every request to the
375
+ # provider (e.g. {"Authorization": "Bearer ...", "X-Api-Key": "..."}).
376
+ sig do
377
+ params(headers: T::Hash[Symbol, String]).returns(T.attached_class)
378
+ end
379
+ def self.new(headers: nil)
380
+ end
381
+
382
+ sig { override.returns({ headers: T::Hash[Symbol, String] }) }
383
+ def to_hash
384
+ end
385
+ end
386
+ end
387
+
69
388
  # The AI provider this key authenticates against.
70
389
  module Provider
71
390
  extend Cadenya::Internal::Type::Enum
@@ -84,6 +403,26 @@ module Cadenya
84
403
  :AI_PROVIDER_OPENROUTER,
85
404
  Cadenya::AIProviderKeySpec::Provider::TaggedSymbol
86
405
  )
406
+ AI_PROVIDER_OPENAI =
407
+ T.let(
408
+ :AI_PROVIDER_OPENAI,
409
+ Cadenya::AIProviderKeySpec::Provider::TaggedSymbol
410
+ )
411
+ AI_PROVIDER_ANTHROPIC =
412
+ T.let(
413
+ :AI_PROVIDER_ANTHROPIC,
414
+ Cadenya::AIProviderKeySpec::Provider::TaggedSymbol
415
+ )
416
+ AI_PROVIDER_GEMINI =
417
+ T.let(
418
+ :AI_PROVIDER_GEMINI,
419
+ Cadenya::AIProviderKeySpec::Provider::TaggedSymbol
420
+ )
421
+ AI_PROVIDER_OPENAI_COMPATIBLE =
422
+ T.let(
423
+ :AI_PROVIDER_OPENAI_COMPATIBLE,
424
+ Cadenya::AIProviderKeySpec::Provider::TaggedSymbol
425
+ )
87
426
 
88
427
  sig do
89
428
  override.returns(
@@ -3,7 +3,46 @@
3
3
  module Cadenya
4
4
  module Models
5
5
  module ToolSets
6
- ConfigMcp = T.let(T.anything, Cadenya::Internal::Type::Converter)
6
+ class ConfigMcp < Cadenya::Internal::Type::BaseModel
7
+ OrHash =
8
+ T.type_alias do
9
+ T.any(Cadenya::ToolSets::ConfigMcp, Cadenya::Internal::AnyHash)
10
+ end
11
+
12
+ # Behavior hints synced from the MCP server's tool definition (ToolAnnotations in
13
+ # the MCP specification). All hints are advisory: servers are not required to send
14
+ # them, and clients should not rely on them for security decisions. Absent hints
15
+ # keep the MCP spec defaults (destructiveHint and openWorldHint default to true;
16
+ # readOnlyHint and idempotentHint default to false).
17
+ sig { returns(T.nilable(Cadenya::ToolSets::McpAnnotations)) }
18
+ attr_reader :annotations
19
+
20
+ sig do
21
+ params(annotations: Cadenya::ToolSets::McpAnnotations::OrHash).void
22
+ end
23
+ attr_writer :annotations
24
+
25
+ sig do
26
+ params(
27
+ annotations: Cadenya::ToolSets::McpAnnotations::OrHash
28
+ ).returns(T.attached_class)
29
+ end
30
+ def self.new(
31
+ # Behavior hints synced from the MCP server's tool definition (ToolAnnotations in
32
+ # the MCP specification). All hints are advisory: servers are not required to send
33
+ # them, and clients should not rely on them for security decisions. Absent hints
34
+ # keep the MCP spec defaults (destructiveHint and openWorldHint default to true;
35
+ # readOnlyHint and idempotentHint default to false).
36
+ annotations: nil
37
+ )
38
+ end
39
+
40
+ sig do
41
+ override.returns({ annotations: Cadenya::ToolSets::McpAnnotations })
42
+ end
43
+ def to_hash
44
+ end
45
+ end
7
46
  end
8
47
  end
9
48
  end
@@ -0,0 +1,97 @@
1
+ # typed: strong
2
+
3
+ module Cadenya
4
+ module Models
5
+ module ToolSets
6
+ class McpAnnotations < Cadenya::Internal::Type::BaseModel
7
+ OrHash =
8
+ T.type_alias do
9
+ T.any(Cadenya::ToolSets::McpAnnotations, Cadenya::Internal::AnyHash)
10
+ end
11
+
12
+ # If true, the tool may perform destructive updates to its environment. Only
13
+ # meaningful when read_only_hint is false.
14
+ sig { returns(T.nilable(T::Boolean)) }
15
+ attr_reader :destructive_hint
16
+
17
+ sig { params(destructive_hint: T::Boolean).void }
18
+ attr_writer :destructive_hint
19
+
20
+ # If true, calling the tool repeatedly with the same arguments has no additional
21
+ # effect. Only meaningful when read_only_hint is false.
22
+ sig { returns(T.nilable(T::Boolean)) }
23
+ attr_reader :idempotent_hint
24
+
25
+ sig { params(idempotent_hint: T::Boolean).void }
26
+ attr_writer :idempotent_hint
27
+
28
+ # If true, the tool may interact with an "open world" of external entities (e.g.
29
+ # web search); if false, its domain is closed.
30
+ sig { returns(T.nilable(T::Boolean)) }
31
+ attr_reader :open_world_hint
32
+
33
+ sig { params(open_world_hint: T::Boolean).void }
34
+ attr_writer :open_world_hint
35
+
36
+ # If true, the tool does not modify its environment.
37
+ sig { returns(T.nilable(T::Boolean)) }
38
+ attr_reader :read_only_hint
39
+
40
+ sig { params(read_only_hint: T::Boolean).void }
41
+ attr_writer :read_only_hint
42
+
43
+ # A human-readable title for the tool.
44
+ sig { returns(T.nilable(String)) }
45
+ attr_reader :title
46
+
47
+ sig { params(title: String).void }
48
+ attr_writer :title
49
+
50
+ # Behavior hints synced from the MCP server's tool definition (ToolAnnotations in
51
+ # the MCP specification). All hints are advisory: servers are not required to send
52
+ # them, and clients should not rely on them for security decisions. Absent hints
53
+ # keep the MCP spec defaults (destructiveHint and openWorldHint default to true;
54
+ # readOnlyHint and idempotentHint default to false).
55
+ sig do
56
+ params(
57
+ destructive_hint: T::Boolean,
58
+ idempotent_hint: T::Boolean,
59
+ open_world_hint: T::Boolean,
60
+ read_only_hint: T::Boolean,
61
+ title: String
62
+ ).returns(T.attached_class)
63
+ end
64
+ def self.new(
65
+ # If true, the tool may perform destructive updates to its environment. Only
66
+ # meaningful when read_only_hint is false.
67
+ destructive_hint: nil,
68
+ # If true, calling the tool repeatedly with the same arguments has no additional
69
+ # effect. Only meaningful when read_only_hint is false.
70
+ idempotent_hint: nil,
71
+ # If true, the tool may interact with an "open world" of external entities (e.g.
72
+ # web search); if false, its domain is closed.
73
+ open_world_hint: nil,
74
+ # If true, the tool does not modify its environment.
75
+ read_only_hint: nil,
76
+ # A human-readable title for the tool.
77
+ title: nil
78
+ )
79
+ end
80
+
81
+ sig do
82
+ override.returns(
83
+ {
84
+ destructive_hint: T::Boolean,
85
+ idempotent_hint: T::Boolean,
86
+ open_world_hint: T::Boolean,
87
+ read_only_hint: T::Boolean,
88
+ title: String
89
+ }
90
+ )
91
+ end
92
+ def to_hash
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -15,10 +15,10 @@ module Cadenya
15
15
  sig { params(http: Cadenya::ToolSets::ConfigHTTP::OrHash).void }
16
16
  attr_writer :http
17
17
 
18
- sig { returns(T.nilable(T.anything)) }
18
+ sig { returns(T.nilable(Cadenya::ToolSets::ConfigMcp)) }
19
19
  attr_reader :mcp
20
20
 
21
- sig { params(mcp: T.anything).void }
21
+ sig { params(mcp: Cadenya::ToolSets::ConfigMcp::OrHash).void }
22
22
  attr_writer :mcp
23
23
 
24
24
  sig { returns(T.nilable(Cadenya::ToolSets::ConfigOpenAPI)) }
@@ -33,7 +33,7 @@ module Cadenya
33
33
  sig do
34
34
  params(
35
35
  http: Cadenya::ToolSets::ConfigHTTP::OrHash,
36
- mcp: T.anything,
36
+ mcp: Cadenya::ToolSets::ConfigMcp::OrHash,
37
37
  openapi: Cadenya::ToolSets::ConfigOpenAPI::OrHash
38
38
  ).returns(T.attached_class)
39
39
  end
@@ -44,7 +44,7 @@ module Cadenya
44
44
  override.returns(
45
45
  {
46
46
  http: Cadenya::ToolSets::ConfigHTTP,
47
- mcp: T.anything,
47
+ mcp: Cadenya::ToolSets::ConfigMcp,
48
48
  openapi: Cadenya::ToolSets::ConfigOpenAPI
49
49
  }
50
50
  )