Skip to content

feat(gemini): add GeminiGateway integration for Google Gemini - #10

Merged
Goldokpa merged 2 commits into
identArk:mainfrom
Kem-Ada:feat/gemini
Oct 8, 2026
Merged

Goldokpa merged 2 commits into
identArk:mainfrom
Kem-Ada:feat/gemini

Conversation

@Kem-Ada

@Kem-Ada Kem-Ada commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds GeminiGateway (alias IdentArkGeminiGateway), a port of the Python SDK's identark/integrations/gemini.py. It is published at the subpath identark/integrations/gemini and is deliberately not re-exported from the barrel, the same as the LangChain and Vercel integrations. It depends on @google/generative-ai, added as an optional peer dependency. Python's DirectGateway has no Gemini branch, so this PR does not touch DirectGateway.

Python → TS parity mapping

Python (identark/integrations/gemini.py) TypeScript (src/integrations/gemini.ts)
GeminiGateway(api_key, model, system_prompt, cost_cap_usd, workspace_dir, safety_settings, generation_config) new GeminiGateway({ apiKey, model, systemPrompt, costCapUsd, workspaceDir, safetySettings, generationConfig, client? })
ConfigurationError on empty key/model or missing SDK Same. The SDK is loaded with a synchronous createRequire, so construction stays sync.
invoke_llm / invoke_llm_stream invokeLlm / invokeLlmStream
persist_messages, request_file_url, get_session_cost, reset persistMessages, requestFileUrl, getSessionCost, reset
history, model, provider properties getHistory(), getModel(), getProvider() (same as DirectGateway)
_estimate_gemini_cost (private) estimateGeminiCost (exported for testing)
_convert_tools_to_gemini, _convert_role_to_gemini convertToolsToGemini, convertRoleToGemini
_classify_gemini_error (substring ladder) _classifyGeminiError, same ladder and order
IdentArkGeminiGateway alias IdentArkGeminiGateway

Deliberate differences, all forced by the JS SDK's shapes:

  • Parts are camelCase (functionResponse, inlineData.mimeType, functionDeclarations).
  • Finish reasons are matched by both numeric and string enum.
  • Structured history content is JSON.stringify'd. Python uses str(list), which is a repr and not portable.
  • client can be injected. The tests use it, since the SDK is not a devDependency.

Python quirks kept on purpose (rule 6):

  • A tool result's function name is the tool_call_id.
  • The stream's final finish_reason is always "stop".
  • Streaming drops function calls.
  • tool_choice is accepted and ignored.
  • Unknown models are priced as flash.

Test plan

Gate, run from identark-js on branch feat/gemini:

npm ci               -> added 235 packages (clean)
npm run lint         -> eslint src --max-warnings 0: clean
npm run typecheck    -> tsc --noEmit: clean
npx vitest run       -> Test Files 10 passed (10); Tests 231 passed (231)
../scripts/check_scope.sh -> check_scope: OK — no control-plane code touched.
  • Upstream/main baseline was 158 tests / 9 files. This PR adds 73 tests in tests/gemini-integration.test.ts.
  • The tests port all 14 cases in tests/unit/test_integrations_gemini.py.
  • Negative and edge cases beyond the Python tests:
    • constructor validation
    • each finish-reason mapping
    • multimodal, tool-result and system-role conversion
    • cost-cap enforcement on both the blocking and streaming paths
    • the full error-classification ladder (429/quota/rate, safety/blocked/harm/content, invalid API key, generic, non-Error rejections)
    • no history or cost recorded on failure
    • mid-stream errors
    • Object.prototype model names in cost estimation

Control-plane: untouched (check_scope OK)

🤖 Generated with Claude Code

Kem-Ada and others added 2 commits October 8, 2026 14:38
Port of identark/integrations/gemini.py: GeminiGateway (alias
IdentArkGeminiGateway) on the optional @google/generative-ai peer
dependency, with function calling, multimodal input, streaming, cost cap,
local file URLs and Gemini error classification. Exposed at
identark/integrations/gemini.

Co-Authored-By: Claude <noreply@anthropic.com>
The JS SDK prefixes every error with "[GoogleGenerativeAI Error]" and
includes the generativelanguage.googleapis.com URL, both of which contain
the substring "rate", so all failures became RateLimitError. Match
keywords at word starts and use the HTTP status when present.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Goldokpa
Goldokpa merged commit 133b2dc into identArk:main Oct 8, 2026
4 checks passed
Goldokpa pushed a commit that referenced this pull request Oct 9, 2026
* feat(gemini): add GeminiGateway integration for Google Gemini

Port of identark/integrations/gemini.py: GeminiGateway (alias
IdentArkGeminiGateway) on the optional @google/generative-ai peer
dependency, with function calling, multimodal input, streaming, cost cap,
local file URLs and Gemini error classification. Exposed at
identark/integrations/gemini.


* fix(gemini): stop classifying every SDK error as a rate limit

The JS SDK prefixes every error with "[GoogleGenerativeAI Error]" and
includes the generativelanguage.googleapis.com URL, both of which contain
the substring "rate", so all failures became RateLimitError. Match
keywords at word starts and use the HTTP status when present.


---------

Co-authored-by: Kem-Ada <283358351+Kem-Ada@users.noreply.github.com>
@Goldokpa Goldokpa mentioned this pull request Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants