otto-cli-agent 0.1.0__py3-none-any.whl

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.
Files changed (129) hide show
  1. agent/README.md +22 -0
  2. agent/__init__.py +0 -0
  3. agent/cli/README.md +77 -0
  4. agent/cli/__init__.py +0 -0
  5. agent/cli/art.py +371 -0
  6. agent/cli/chat.py +309 -0
  7. agent/cli/clipboard.py +106 -0
  8. agent/cli/context.py +56 -0
  9. agent/cli/doctor.py +60 -0
  10. agent/cli/errors.py +58 -0
  11. agent/cli/eval.py +130 -0
  12. agent/cli/eval_claw.py +414 -0
  13. agent/cli/eval_compaction.py +106 -0
  14. agent/cli/eval_hle.py +92 -0
  15. agent/cli/eval_memory.py +253 -0
  16. agent/cli/eval_swe.py +172 -0
  17. agent/cli/lessons.py +97 -0
  18. agent/cli/main.py +67 -0
  19. agent/cli/modals.py +570 -0
  20. agent/cli/models.py +64 -0
  21. agent/cli/output.py +54 -0
  22. agent/cli/route.py +78 -0
  23. agent/cli/sessions.py +125 -0
  24. agent/cli/setup_screen.py +562 -0
  25. agent/cli/shell.py +548 -0
  26. agent/cli/tui.py +1807 -0
  27. agent/cli/ui.py +14 -0
  28. agent/cli/usage_panel.py +159 -0
  29. agent/config/README.md +7 -0
  30. agent/config/__init__.py +0 -0
  31. agent/config/envfile.py +76 -0
  32. agent/eval/README.md +76 -0
  33. agent/eval/__init__.py +0 -0
  34. agent/eval/claw_bench.py +1031 -0
  35. agent/eval/compaction_bench.py +229 -0
  36. agent/eval/data/README.md +10 -0
  37. agent/eval/data/claw/README.md +108 -0
  38. agent/eval/data/claw/llm_judge-gemini.patch +57 -0
  39. agent/eval/data/claw/otto.yaml +35 -0
  40. agent/eval/failures.py +276 -0
  41. agent/eval/golden/README.md +33 -0
  42. agent/eval/golden/code_01.json +6 -0
  43. agent/eval/golden/code_02.json +6 -0
  44. agent/eval/golden/code_03.json +6 -0
  45. agent/eval/golden/code_04.json +6 -0
  46. agent/eval/golden/code_05.json +6 -0
  47. agent/eval/golden/code_06.json +6 -0
  48. agent/eval/golden/math_01.json +6 -0
  49. agent/eval/golden/math_02.json +6 -0
  50. agent/eval/golden/math_03.json +6 -0
  51. agent/eval/golden/math_04.json +6 -0
  52. agent/eval/golden/math_05.json +6 -0
  53. agent/eval/golden/math_06.json +6 -0
  54. agent/eval/golden/nphard_gcp_01.json +6 -0
  55. agent/eval/golden/nphard_ksp_01.json +6 -0
  56. agent/eval/golden/nphard_math_binpacking_01.json +6 -0
  57. agent/eval/golden/nphard_math_clique_01.json +6 -0
  58. agent/eval/golden/nphard_math_setcover_01.json +6 -0
  59. agent/eval/golden/nphard_math_subsetsum_01.json +6 -0
  60. agent/eval/golden/nphard_tsp_01.json +6 -0
  61. agent/eval/golden/nphard_tsp_02.json +6 -0
  62. agent/eval/hle_bench.py +273 -0
  63. agent/eval/langfuse_sync.py +172 -0
  64. agent/eval/memory_bench.py +538 -0
  65. agent/eval/runner.py +174 -0
  66. agent/eval/single_agent.py +120 -0
  67. agent/eval/swe_bench.py +604 -0
  68. agent/eval/terminal_bench.py +345 -0
  69. agent/memory/README.md +102 -0
  70. agent/memory/__init__.py +42 -0
  71. agent/memory/embeddings.py +302 -0
  72. agent/memory/hashing.py +15 -0
  73. agent/memory/lessons.py +483 -0
  74. agent/memory/queue.py +531 -0
  75. agent/memory/retrieval.py +493 -0
  76. agent/memory/session.py +60 -0
  77. agent/memory/sessions.py +436 -0
  78. agent/memory/store.py +429 -0
  79. agent/memory/tokens.py +60 -0
  80. agent/memory/wiring.py +146 -0
  81. agent/pipeline/README.md +135 -0
  82. agent/pipeline/__init__.py +0 -0
  83. agent/pipeline/browsing.py +609 -0
  84. agent/pipeline/budget.py +403 -0
  85. agent/pipeline/codemap.py +254 -0
  86. agent/pipeline/evidence.py +325 -0
  87. agent/pipeline/execution.py +67 -0
  88. agent/pipeline/modes.py +137 -0
  89. agent/pipeline/native.py +1137 -0
  90. agent/pipeline/nodes.py +3644 -0
  91. agent/pipeline/pricing.py +209 -0
  92. agent/pipeline/progress.py +139 -0
  93. agent/pipeline/rag.py +139 -0
  94. agent/pipeline/research.py +1325 -0
  95. agent/pipeline/run.py +528 -0
  96. agent/pipeline/screen.py +77 -0
  97. agent/pipeline/state.py +220 -0
  98. agent/pipeline/toolkit.py +328 -0
  99. agent/pipeline/tools.py +1990 -0
  100. agent/pipeline/tracing.py +147 -0
  101. agent/pipeline/usage.py +251 -0
  102. agent/pipeline/vision.py +84 -0
  103. agent/pipeline/walkthrough.py +735 -0
  104. agent/pipeline/workspace.py +229 -0
  105. agent/router/README.md +60 -0
  106. agent/router/__init__.py +0 -0
  107. agent/router/automap.py +114 -0
  108. agent/router/health.py +229 -0
  109. agent/router/llm_provider/README.md +38 -0
  110. agent/router/llm_provider/__init__.py +202 -0
  111. agent/router/llm_provider/anthropic_provider.py +128 -0
  112. agent/router/llm_provider/base.py +507 -0
  113. agent/router/llm_provider/custom.py +152 -0
  114. agent/router/llm_provider/gemini_provider.py +122 -0
  115. agent/router/llm_provider/inception_provider.py +687 -0
  116. agent/router/llm_provider/openai_provider.py +151 -0
  117. agent/router/llm_provider/retired.py +145 -0
  118. agent/router/llm_provider/temperature.py +371 -0
  119. agent/router/mapping.py +579 -0
  120. agent/router/outcomes.py +363 -0
  121. agent/router/overrides.py +389 -0
  122. agent/router/reload.py +28 -0
  123. agent/router/router.py +413 -0
  124. agent/router/setup.py +123 -0
  125. otto_cli_agent-0.1.0.dist-info/METADATA +115 -0
  126. otto_cli_agent-0.1.0.dist-info/RECORD +129 -0
  127. otto_cli_agent-0.1.0.dist-info/WHEEL +4 -0
  128. otto_cli_agent-0.1.0.dist-info/entry_points.txt +2 -0
  129. otto_cli_agent-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,122 @@
1
+ """Gemini provider, on the `google-genai` SDK.
2
+
3
+ Note this is `google-genai` (``from google import genai``), not the legacy
4
+ `google-generativeai` package -- the two have incompatible APIs and the newer
5
+ one is what `langchain-google-genai` pulls in here.
6
+
7
+ As with Anthropic: SDK for discovery, `ChatGoogleGenerativeAI` for chat.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import Any
13
+
14
+ import httpx
15
+ from google import genai
16
+ from google.genai import errors as genai_errors
17
+ from langchain_core.language_models import BaseChatModel
18
+ from langchain_google_genai import ChatGoogleGenerativeAI
19
+
20
+ from agent.router.llm_provider.base import (
21
+ AuthError,
22
+ BaseProvider,
23
+ Capability,
24
+ ModelInfo,
25
+ ProviderError,
26
+ ProviderUnavailable,
27
+ )
28
+
29
+ __all__ = ["GeminiProvider"]
30
+
31
+
32
+ def _translate(exc: Exception) -> ProviderError:
33
+ if isinstance(exc, genai_errors.APIError):
34
+ code = getattr(exc, "code", None)
35
+ if code in (401, 403):
36
+ return AuthError(f"gemini: HTTP {code}")
37
+ return ProviderError(f"gemini: HTTP {code}: {exc}")
38
+ if isinstance(exc, httpx.TransportError):
39
+ # The SDK only wraps HTTP-level failures; DNS, TLS and timeout errors
40
+ # arrive as raw httpx exceptions and would otherwise reach health_check
41
+ # untranslated.
42
+ return ProviderUnavailable(f"gemini: {exc}")
43
+ return ProviderError(f"gemini: {exc}")
44
+
45
+
46
+ #: `Model.supported_actions` values that matter to us. This is the only
47
+ #: capability metadata Gemini publishes.
48
+ _ACTION_MAP: dict[str, Capability] = {
49
+ "generateContent": Capability.CHAT,
50
+ "embedContent": Capability.EMBEDDINGS,
51
+ }
52
+
53
+
54
+ def _capabilities_of(model: Any, model_id: str) -> set[Capability]:
55
+ caps = {
56
+ _ACTION_MAP[action]
57
+ for action in (model.supported_actions or [])
58
+ if action in _ACTION_MAP
59
+ }
60
+
61
+ # Gemini publishes no tool-use or modality flags, so these two are a
62
+ # heuristic -- flagged as such, exactly like the OpenAI classifier. Every
63
+ # current gemini-* model does function calling and image input; the
64
+ # gemma-*, embedding-* and aqa entries in the same list do not.
65
+ if Capability.CHAT in caps and model_id.startswith("gemini-"):
66
+ caps |= {Capability.TOOLS, Capability.VISION,
67
+ Capability.STRUCTURED_OUTPUT, Capability.REASONING}
68
+
69
+ return caps
70
+
71
+
72
+ class GeminiProvider(BaseProvider):
73
+ name = "gemini"
74
+ env_var = "GEMINI_API_KEY"
75
+ default_base_url = None
76
+ capabilities = frozenset(
77
+ {
78
+ Capability.CHAT,
79
+ Capability.TOOLS,
80
+ Capability.VISION,
81
+ Capability.STRUCTURED_OUTPUT,
82
+ Capability.EMBEDDINGS,
83
+ }
84
+ )
85
+
86
+ def _build_client(self) -> genai.Client:
87
+ # Explicit key: the SDK would otherwise fall back to GOOGLE_API_KEY or
88
+ # GEMINI_API_KEY on its own, which makes it ambiguous which one won.
89
+ return genai.Client(api_key=self._api_key)
90
+
91
+ def _fetch_models(self) -> list[ModelInfo]:
92
+ try:
93
+ # The Pager auto-fetches subsequent pages while iterating; page_size
94
+ # only controls how many round trips that takes.
95
+ models = list(self._client.models.list(config={"page_size": 100}))
96
+ except Exception as exc:
97
+ raise _translate(exc) from exc
98
+
99
+ found: list[ModelInfo] = []
100
+ for model in models:
101
+ # `name` arrives as "models/gemini-2.5-pro"; the bare id is what
102
+ # every other API surface expects.
103
+ model_id = (model.name or "").removeprefix("models/")
104
+ if not model_id:
105
+ continue
106
+ found.append(
107
+ ModelInfo(
108
+ id=model_id,
109
+ provider=self.name,
110
+ display_name=model.display_name,
111
+ capabilities=frozenset(_capabilities_of(model, model_id)),
112
+ context_window=model.input_token_limit,
113
+ max_output_tokens=model.output_token_limit,
114
+ raw=model.model_dump(mode="json"),
115
+ )
116
+ )
117
+ return found
118
+
119
+ def chat_model(self, model_id: str, **kwargs: Any) -> BaseChatModel:
120
+ return ChatGoogleGenerativeAI(
121
+ model=model_id, google_api_key=self._api_key, **kwargs
122
+ )