tina4ruby 3.13.136 → 3.13.137
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/lib/tina4/ai_client.rb +14 -6
- data/lib/tina4/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20aca573e3cde8679e7391e5a6678adaee5900575f6c4859adbe910bc0338687
|
|
4
|
+
data.tar.gz: b49f226dd8fdb7d873b3a23d7e0c2eb23678f37738ae78f84c7de2a880e4e189
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2ec416a1fc6f9d397258e688015e5af18139d7b6379c9f7a473c35c44f615711db5301e2cc18a9d4c654bea226473c0849ed61ab57daa246829ec27208a45c7d
|
|
7
|
+
data.tar.gz: 27c9a2952ce239f555cc9e9977623c4e66cc5e9505d43b96212ad571ea43afd75d6ceb04f4527fcf9dbc6fffbb8b4b6e9a900ff8314828804793d49591d267c4
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,24 @@ number means the same thing everywhere.
|
|
|
6
6
|
**The authoritative release notes for every shipped version live in the documentation:**
|
|
7
7
|
https://tina4.com/ruby/36-releases
|
|
8
8
|
|
|
9
|
+
## 3.13.137
|
|
10
|
+
|
|
11
|
+
Gemini joins the Ai client as a first-class provider. Set TINA4_AI_PROVIDER=gemini with a
|
|
12
|
+
TINA4_AI_KEY and the AI client reaches Google Gemini through its OpenAI-compatible endpoint,
|
|
13
|
+
with the same normalised responses, streaming, tool-use, retries and embeddings every other
|
|
14
|
+
provider gets and no new dependency. Gemini rides the existing OpenAI wire family, so the
|
|
15
|
+
whole provider is a thin alias: the base URL, the endpoint suffix, and the Bearer key.
|
|
16
|
+
|
|
17
|
+
## 3.13.136
|
|
18
|
+
|
|
19
|
+
The AI skills learn to build to the user journeys. The tina4-architect skill now maps goals,
|
|
20
|
+
user journeys, and system flows with a completeness net before it scaffolds a file (a visible
|
|
21
|
+
map marker flags that work while it happens), the developer skills build to those journeys,
|
|
22
|
+
and a new tina4-design skill runs the visual-identity chain (brand guidelines plus an
|
|
23
|
+
interactive UI guide). Framework fixes: the bundled Swagger UI no longer answers a route miss
|
|
24
|
+
with a document that cannot load (#46); and a spec proves the gemspec names no third-party
|
|
25
|
+
runtime dependency. Full notes: https://tina4.com/ruby/36-releases
|
|
26
|
+
|
|
9
27
|
## 3.13.135
|
|
10
28
|
|
|
11
29
|
Fix release. The dev-admin version check returns no version and a reason when it cannot
|
data/lib/tina4/ai_client.rb
CHANGED
|
@@ -27,7 +27,7 @@ module Tina4
|
|
|
27
27
|
# shape); ADR-0060 extended it with typed streaming events and multimodal
|
|
28
28
|
# content parts. Both live here so the AI surface is a single file.
|
|
29
29
|
class Ai
|
|
30
|
-
PROVIDERS = %w[local openai anthropic].freeze
|
|
30
|
+
PROVIDERS = %w[local openai anthropic gemini].freeze
|
|
31
31
|
|
|
32
32
|
class << self
|
|
33
33
|
# chat(stream: false) still returns a ChatResponse (ADR-0053).
|
|
@@ -219,16 +219,20 @@ module Tina4
|
|
|
219
219
|
|
|
220
220
|
def resolve_config(capability, model, timeout, provider)
|
|
221
221
|
selected = (provider || ENV["TINA4_AI_PROVIDER"] || "local").strip.downcase
|
|
222
|
-
raise AiConfigError, "TINA4_AI_PROVIDER must be local, openai, or
|
|
222
|
+
raise AiConfigError, "TINA4_AI_PROVIDER must be local, openai, anthropic, or gemini" unless PROVIDERS.include?(selected)
|
|
223
223
|
|
|
224
224
|
key = ENV["TINA4_AI_KEY"]
|
|
225
|
-
if %w[openai anthropic].include?(selected) && (key.nil? || key.empty?)
|
|
225
|
+
if %w[openai anthropic gemini].include?(selected) && (key.nil? || key.empty?)
|
|
226
226
|
raise AiConfigError, "TINA4_AI_KEY is required for the #{selected} provider"
|
|
227
227
|
end
|
|
228
228
|
defaults = {
|
|
229
229
|
"local" => ["http://localhost:11437", "llama3.2"],
|
|
230
230
|
"openai" => ["https://api.openai.com/v1", "gpt-4o-mini"],
|
|
231
|
-
"anthropic" => ["https://api.anthropic.com/v1", "claude-3-5-haiku-latest"]
|
|
231
|
+
"anthropic" => ["https://api.anthropic.com/v1", "claude-3-5-haiku-latest"],
|
|
232
|
+
# Gemini speaks the OpenAI wire format at its OpenAI-compatible base, so it
|
|
233
|
+
# rides the openai body/parse/stream path — only the base URL, the endpoint
|
|
234
|
+
# suffix append, and the Bearer key differ.
|
|
235
|
+
"gemini" => ["https://generativelanguage.googleapis.com/v1beta/openai", "gemini-2.5-flash"]
|
|
232
236
|
}
|
|
233
237
|
value = capability == "embed" && ENV["TINA4_EMBED_URL"] ? ENV["TINA4_EMBED_URL"] : (ENV["TINA4_AI_URL"] || defaults[selected][0])
|
|
234
238
|
total = timeout.nil? ? number("TINA4_AI_TIMEOUT", 60, 0.001) : Float(timeout)
|
|
@@ -255,7 +259,11 @@ module Tina4
|
|
|
255
259
|
raise AiConfigError, "AI URL must be an http or https URL" unless %w[http https].include?(uri.scheme) && uri.host
|
|
256
260
|
|
|
257
261
|
path = uri.path.to_s.sub(%r{/+$}, "")
|
|
258
|
-
|
|
262
|
+
# "/v1beta/openai" is Gemini's OpenAI-compatible base; append the suffix onto
|
|
263
|
+
# it exactly as onto a bare host / "/v1" / "/api", so the default gemini base
|
|
264
|
+
# resolves to .../v1beta/openai/chat/completions (or /embeddings). A full
|
|
265
|
+
# endpoint URL the caller supplies verbatim still passes through untouched.
|
|
266
|
+
if ["", "/v1", "/api", "/v1beta/openai"].include?(path)
|
|
259
267
|
suffix = provider == "anthropic" ? "/messages" : (capability == "embed" ? "/embeddings" : "/chat/completions")
|
|
260
268
|
uri.path = (path.empty? ? "/v1" : path) + suffix
|
|
261
269
|
end
|
|
@@ -266,7 +274,7 @@ module Tina4
|
|
|
266
274
|
|
|
267
275
|
def headers(config)
|
|
268
276
|
result = { "Content-Type" => "application/json", "Accept" => "application/json" }
|
|
269
|
-
if config[:provider]
|
|
277
|
+
if %w[openai gemini].include?(config[:provider])
|
|
270
278
|
result["Authorization"] = "Bearer #{config[:key]}"
|
|
271
279
|
elsif config[:provider] == "anthropic"
|
|
272
280
|
result["x-api-key"] = config[:key]
|
data/lib/tina4/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tina4ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.13.
|
|
4
|
+
version: 3.13.137
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tina4 Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|