trance 0.1.0__tar.gz

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 (64) hide show
  1. trance-0.1.0/.gitignore +33 -0
  2. trance-0.1.0/AGENTS.md +14 -0
  3. trance-0.1.0/LICENSE +21 -0
  4. trance-0.1.0/PKG-INFO +229 -0
  5. trance-0.1.0/README.md +190 -0
  6. trance-0.1.0/pyproject.toml +47 -0
  7. trance-0.1.0/src/trance/__init__.py +36 -0
  8. trance-0.1.0/src/trance/cli_model.py +724 -0
  9. trance-0.1.0/src/trance/discovery.py +230 -0
  10. trance-0.1.0/src/trance/models.py +481 -0
  11. trance-0.1.0/src/trance/sources/__init__.py +7 -0
  12. trance-0.1.0/src/trance/sources/aws_bedrock.py +221 -0
  13. trance-0.1.0/src/trance/sources/claude_code.py +120 -0
  14. trance-0.1.0/src/trance/sources/cloud_api.py +137 -0
  15. trance-0.1.0/src/trance/sources/codex.py +71 -0
  16. trance-0.1.0/src/trance/sources/cody.py +88 -0
  17. trance-0.1.0/src/trance/sources/compatible_api.py +67 -0
  18. trance-0.1.0/src/trance/sources/copilot.py +100 -0
  19. trance-0.1.0/src/trance/sources/cursor.py +86 -0
  20. trance-0.1.0/src/trance/sources/env_api.py +65 -0
  21. trance-0.1.0/src/trance/sources/gemini_cli.py +128 -0
  22. trance-0.1.0/src/trance/sources/google_vertex.py +155 -0
  23. trance-0.1.0/src/trance/sources/grok_consumer.py +126 -0
  24. trance-0.1.0/src/trance/sources/huggingface_login.py +58 -0
  25. trance-0.1.0/src/trance/sources/kimi_code.py +110 -0
  26. trance-0.1.0/src/trance/sources/kiro.py +38 -0
  27. trance-0.1.0/src/trance/sources/minimax_coding.py +49 -0
  28. trance-0.1.0/src/trance/sources/mistral_vibe.py +64 -0
  29. trance-0.1.0/src/trance/sources/opencode.py +130 -0
  30. trance-0.1.0/src/trance/sources/poe.py +29 -0
  31. trance-0.1.0/src/trance/sources/qwen_code.py +96 -0
  32. trance-0.1.0/src/trance/sources/tabnine.py +42 -0
  33. trance-0.1.0/src/trance/sources/zai.py +53 -0
  34. trance-0.1.0/src/trance/types.py +63 -0
  35. trance-0.1.0/tests/test_aws_bedrock_source.py +191 -0
  36. trance-0.1.0/tests/test_claude_code_source.py +305 -0
  37. trance-0.1.0/tests/test_cli_model.py +659 -0
  38. trance-0.1.0/tests/test_cloud_api_source.py +114 -0
  39. trance-0.1.0/tests/test_codex_source.py +105 -0
  40. trance-0.1.0/tests/test_cody_source.py +107 -0
  41. trance-0.1.0/tests/test_compatible_api_source.py +142 -0
  42. trance-0.1.0/tests/test_copilot_source.py +104 -0
  43. trance-0.1.0/tests/test_cursor_source.py +47 -0
  44. trance-0.1.0/tests/test_discovery.py +613 -0
  45. trance-0.1.0/tests/test_env_api_source.py +66 -0
  46. trance-0.1.0/tests/test_gemini_cli_source.py +130 -0
  47. trance-0.1.0/tests/test_google_vertex_source.py +146 -0
  48. trance-0.1.0/tests/test_grok_consumer_source.py +202 -0
  49. trance-0.1.0/tests/test_huggingface_login_source.py +50 -0
  50. trance-0.1.0/tests/test_kimi_code_source.py +94 -0
  51. trance-0.1.0/tests/test_kiro_source.py +19 -0
  52. trance-0.1.0/tests/test_local_integration.py +561 -0
  53. trance-0.1.0/tests/test_minimax_coding_source.py +53 -0
  54. trance-0.1.0/tests/test_mistral_vibe_source.py +51 -0
  55. trance-0.1.0/tests/test_models.py +498 -0
  56. trance-0.1.0/tests/test_opencode_source.py +82 -0
  57. trance-0.1.0/tests/test_poe_source.py +24 -0
  58. trance-0.1.0/tests/test_public_api.py +31 -0
  59. trance-0.1.0/tests/test_qwen_code_source.py +74 -0
  60. trance-0.1.0/tests/test_security.py +321 -0
  61. trance-0.1.0/tests/test_tabnine_source.py +39 -0
  62. trance-0.1.0/tests/test_types.py +48 -0
  63. trance-0.1.0/tests/test_zai_source.py +42 -0
  64. trance-0.1.0/uv.lock +3441 -0
@@ -0,0 +1,33 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .dist/
6
+ build/
7
+ dist/
8
+
9
+ # Environments and tooling
10
+ .venv/
11
+ venv/
12
+ .ruff_cache/
13
+ .pytest_cache/
14
+ .mypy_cache/
15
+ .coverage
16
+
17
+ # Local configuration and credentials
18
+ .env
19
+ .env.*
20
+ !.env.example
21
+ *.token
22
+ *.tokens
23
+ *.credentials
24
+
25
+ # IDE and operating system
26
+ .vscode/
27
+ .idea/
28
+ .DS_Store
29
+ Thumbs.db
30
+
31
+ # Local run outputs
32
+ logs/
33
+ outputs/
trance-0.1.0/AGENTS.md ADDED
@@ -0,0 +1,14 @@
1
+ # Development
2
+
3
+ Use `xonsh` and `uv` for project commands. This package is a `src`-layout Python
4
+ library. Keep provider discovery isolated behind small source adapters, keep
5
+ credential values out of logs and fixtures, and keep optional provider SDKs in
6
+ separate extras. The base dependency uses Pydantic AI's OpenAI adapter; install
7
+ a named provider extra only when an adapter needs its native SDK (for example,
8
+ `uv sync --extra dev --extra anthropic`).
9
+
10
+ Set up the development environment with `uv sync --extra dev`. Run the suite
11
+ with `uv run pytest` and lint with `uv run ruff check .`.
12
+
13
+ Do not commit local credentials, environment files, virtual environments, or
14
+ generated build and test artifacts.
trance-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 trance contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
trance-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,229 @@
1
+ Metadata-Version: 2.5
2
+ Name: trance
3
+ Version: 0.1.0
4
+ Summary: Discover local model provider sessions and expose them through Pydantic AI
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: pydantic-ai-slim[openai]<3,>=2.51.0
9
+ Provides-Extra: anthropic
10
+ Requires-Dist: pydantic-ai-slim[anthropic]<3,>=2.51.0; extra == 'anthropic'
11
+ Provides-Extra: bedrock
12
+ Requires-Dist: pydantic-ai-slim[bedrock]<3,>=2.51.0; extra == 'bedrock'
13
+ Provides-Extra: cerebras
14
+ Requires-Dist: pydantic-ai-slim[cerebras]<3,>=2.51.0; extra == 'cerebras'
15
+ Provides-Extra: cohere
16
+ Requires-Dist: pydantic-ai-slim[cohere]<3,>=2.51.0; extra == 'cohere'
17
+ Provides-Extra: crusoe
18
+ Requires-Dist: pydantic-ai-slim[crusoe]<3,>=2.51.0; extra == 'crusoe'
19
+ Provides-Extra: dev
20
+ Requires-Dist: pytest<10,>=8.3; extra == 'dev'
21
+ Requires-Dist: ruff<1,>=0.12; extra == 'dev'
22
+ Provides-Extra: google
23
+ Requires-Dist: pydantic-ai-slim[google]<3,>=2.51.0; extra == 'google'
24
+ Provides-Extra: groq
25
+ Requires-Dist: pydantic-ai-slim[groq]<3,>=2.51.0; extra == 'groq'
26
+ Provides-Extra: huggingface
27
+ Requires-Dist: pydantic-ai-slim[huggingface]<3,>=2.51.0; extra == 'huggingface'
28
+ Provides-Extra: mistral
29
+ Requires-Dist: pydantic-ai-slim[mistral]<3,>=2.51.0; extra == 'mistral'
30
+ Provides-Extra: openrouter
31
+ Requires-Dist: pydantic-ai-slim[openrouter]<3,>=2.51.0; extra == 'openrouter'
32
+ Provides-Extra: voyageai
33
+ Requires-Dist: pydantic-ai-slim[voyageai]<3,>=2.51.0; extra == 'voyageai'
34
+ Provides-Extra: xai
35
+ Requires-Dist: pydantic-ai-slim[xai]<3,>=2.51.0; extra == 'xai'
36
+ Provides-Extra: zai
37
+ Requires-Dist: pydantic-ai-slim[zai]<3,>=2.51.0; extra == 'zai'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # trance
41
+
42
+ `trance` discovers a limited set of documented credentials and signed-in
43
+ coding tools already configured on your machine, then builds model objects
44
+ using [Pydantic AI](https://ai.pydantic.dev/). It is a small Python library
45
+ for applications that want to reuse supported local provider setups.
46
+
47
+ Consumer subscriptions do not automatically grant general API access. A
48
+ credential being present does not establish that a provider permits using it
49
+ from arbitrary software. `trance` scans only documented local auth state. It
50
+ does not search private browser stores or undocumented application stores;
51
+ raw token strings are not returned or logged, although model objects may retain
52
+ auth internally for requests. Supported CLI adapters may privately stage
53
+ documented saved credentials for a request. Gemini CLI OAuth
54
+ is surfaced only with a warning because its [terms prohibit third-party
55
+ access to the service through its OAuth session and may suspend or terminate
56
+ accounts](https://github.com/google-gemini/gemini-cli/blob/main/docs/resources/tos-privacy.md).
57
+
58
+ ## Coverage at a glance
59
+
60
+ | Product | Current supported path |
61
+ | --- | --- |
62
+ | OpenAI Codex | Subscription authentication delegated to the documented Codex CLI/Pydantic AI integration |
63
+ | Claude Code | Subscription authentication delegated to the documented Claude CLI, including a saved CLI login or `CLAUDE_CODE_OAUTH_TOKEN` |
64
+ | Grok Build consumer | Optional integration requiring the installed official `grok` CLI and an authenticated saved session; the CLI adapter validates the session lazily when a request runs |
65
+ | Grok API (xAI) | `XAI_API_KEY` through the regular API-key registry; this is a separate API credential path |
66
+ | Gemini CLI consumer | Optional saved-login integration using the installed `gemini` CLI and `~/.gemini/oauth_creds.json`; discovery emits the documented terms warning and does not provide an opt-in switch |
67
+ | Gemini API | `GOOGLE_API_KEY` or `GEMINI_API_KEY` through the regular API-key registry; this is a separate API credential path |
68
+ | Sourcegraph Cody | Optional saved account login delegated to the installed `cody` CLI |
69
+ | OpenCode | Optional provider-keyed `auth.json` entries for known defaults and model overrides; account/API credentials are delegated to an isolated, no-tools `opencode` CLI |
70
+ | AWS Bedrock | Optional local environment, profile, or SSO credential chain; uses the `bedrock` extra |
71
+ | Google Vertex AI | Optional local Application Default Credentials (ADC); uses the `google` extra |
72
+
73
+ Grok Build and the xAI API are separate credential paths. A consumer account
74
+ or subscription does not by itself provide an xAI API credential. Gemini CLI
75
+ OAuth is a separate, warned integration with Google's terms risk; Gemini API
76
+ keys remain a separate credential path.
77
+
78
+ ## Install
79
+
80
+ For a checkout, install the package and development dependencies with:
81
+
82
+ ```sh
83
+ uv sync --extra dev
84
+ ```
85
+
86
+ The core dependency includes Pydantic AI's OpenAI support. Optional extras for
87
+ provider integrations supported by `trance` are `anthropic`, `bedrock`,
88
+ `cerebras`, `cohere`, `crusoe`, `google`, `groq`, `huggingface`, `mistral`,
89
+ `openrouter`, and `xai`. The fixed compatible adapters, including Crusoe, use
90
+ the core OpenAI-compatible model path, so the `crusoe` extra is not required
91
+ for them.
92
+
93
+ ## Quick start
94
+
95
+ Sign in with a supported local CLI or configure a documented provider key,
96
+ then scan:
97
+
98
+ ```python
99
+ from trance.discovery import scan
100
+ from pydantic_ai import Agent
101
+
102
+ found = scan()
103
+ for item in found:
104
+ print(item.provider, item.auth_kind, item.source, item.model_name)
105
+
106
+ # Use a discovered Pydantic AI Model with Agent. Calling run() sends a request.
107
+ agents = [Agent(model=item.model) for item in found]
108
+ ```
109
+
110
+ `scan()` returns `list[FoundModel]`. Each record identifies the provider,
111
+ authentication kind, discovery source, and model name alongside a Pydantic AI
112
+ `Model`. It constructs objects without sending a request. It does not check
113
+ whether a credential is currently valid, permitted for a particular use, or
114
+ within quota. A `FoundModel` represents a successfully constructed model;
115
+ source adapters that cannot be safely connected to a supported model are
116
+ skipped in the default non-strict mode. Set `strict=True` to raise on a source
117
+ or model construction failure.
118
+
119
+ You can restrict discovery by provider ID, or pass an environment mapping and
120
+ home directory for controlled runs:
121
+
122
+ ```python
123
+ from pathlib import Path
124
+ from trance.discovery import scan
125
+
126
+ found = scan(
127
+ environ={"OPENAI_API_KEY": "sk-example-not-a-real-key"},
128
+ home=Path("/home/me"),
129
+ providers={"openai"},
130
+ )
131
+ ```
132
+
133
+ Avoid printing or logging the model object: it may retain provider
134
+ authentication material for requests. `FoundModel` and candidate
135
+ representations redact their model and secret fields. The `source` field
136
+ describes where a credential was found and is safe to display.
137
+
138
+ ## Discovery sources
139
+
140
+ `scan()` currently registers these adapters. Subscription and account
141
+ integrations are scanned first; ordinary API credentials are scanned after
142
+ them. A subscription login is an integration with the vendor's documented
143
+ account or CLI flow. It is not a general-purpose API key.
144
+
145
+ | Provider or source | What is read | Result and model factory |
146
+ | --- | --- | --- |
147
+ | OpenAI Codex | Bounded metadata from `~/.codex/auth.json` or the file under `CODEX_HOME` (`auth_mode` and the `tokens` shape); token values are never exposed | Subscription candidate; `OpenAICodexModel` resolves the credential |
148
+ | GitHub Copilot | `GITHUB_COPILOT_API_KEY`, `GITHUB_COPILOT_API_TOKEN`, `COPILOT_GITHUB_TOKEN`, or a saved `gh` login | Subscription candidate; `GitHubCopilotModel` |
149
+ | Claude Code | `CLAUDE_CODE_OAUTH_TOKEN`, or a saved first-party login confirmed by `claude auth status` plus `~/.claude/.credentials.json` (or `CLAUDE_CONFIG_DIR/.credentials.json`) | Subscription candidate; text-only Claude CLI model, defaulting to `sonnet` |
150
+ | Poe | `POE_API_KEY` | Subscription candidate; OpenAI-compatible model at Poe's endpoint |
151
+ | MiniMax Coding Plan | `MINIMAX_API_KEY` with the `sk-cp-` prefix and an allowed `MINIMAX_API_HOST` | Subscription candidate; OpenAI-compatible model |
152
+ | Mistral Vibe | `MISTRAL_API_KEY` or `~/.vibe/.env:MISTRAL_API_KEY` | API-key candidate; Mistral model |
153
+ | Qwen Code Coding Plan | `BAILIAN_CODING_PLAN_API_KEY` or supported `~/.qwen/settings.json`, with an `sk-sp-` key | Subscription candidate; OpenAI-compatible model at an allowed Coding Plan endpoint |
154
+ | Hugging Face Hub | Saved login resolved by `huggingface_hub.get_token()` in the real process context | Account candidate; Hugging Face model |
155
+ | Grok Build consumer | Installed `grok` executable and bounded metadata from a non-symlink `~/.grok/auth.json` (or `GROK_HOME/auth.json`) confirming an OIDC record; token values are not retained | Optional account candidate; isolated, text-only Grok CLI model; session validity is checked lazily by the CLI when a request runs, and refreshed auth is promoted back safely |
156
+ | Gemini CLI consumer | Installed `gemini` executable and bounded metadata from `~/.gemini/oauth_creds.json` (or `GEMINI_CLI_HOME/.gemini/oauth_creds.json`) confirming a refresh token; emits a terms warning | Optional account candidate; isolated, text-only Gemini CLI model; no opt-in bypass for the warning |
157
+ | Sourcegraph Cody | Installed `cody` executable and a successful local `cody auth whoami` check with dedicated PAT variables removed | Account candidate; text-only Cody CLI model |
158
+ | OpenCode | Installed `opencode` executable and bounded, provider-keyed `~/.local/share/opencode/auth.json` metadata; recognized OAuth, API-key, and well-known entries only | Account or API-key candidate; isolated `opencode --pure` text-only model with tools disabled; OpenCode manages its own provider-specific OAuth flow |
159
+ | AWS Bedrock | `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`, or bounded AWS profile credentials/SSO configuration plus a region | Account candidate; Bedrock model through the optional `bedrock` integration |
160
+ | Google Vertex AI | Bounded local ADC metadata from `GOOGLE_APPLICATION_CREDENTIALS` or gcloud ADC, plus a project and optional location | Account candidate; Vertex model through the optional `google` integration |
161
+ | Z.AI | `ZAI_API_KEY` for the general API and `ZAI_CODING_PLAN_API_KEY` for the Coding Plan endpoint | General API-key candidate or Coding Plan subscription candidate; OpenAI-compatible models at separate official endpoints |
162
+ | Fixed compatible API registry | `MOONSHOT_API_KEY`, `NEBIUS_API_KEY`, `DEEPINFRA_TOKEN`/`DEEPINFRA_API_KEY`, `NVIDIA_API_KEY`, `NOVITA_API_KEY`, `AIML_API_KEY`, `OVH_AI_ENDPOINTS_ACCESS_TOKEN`, `HELICONE_API_KEY`, `REQUESTY_API_KEY`, `FEATHERLESS_API_KEY`, `HYPERBOLIC_API_KEY`, `CRUSOE_API_KEY`, `SILICONFLOW_API_KEY`, `VENICE_API_KEY`, `CHUTES_API_KEY`, `AKASH_API_KEY`, `SCW_SECRET_KEY`, `FRIENDLI_API_KEY`, `CLARIFAI_PAT`, `MODEL_API_KEY`, `PARASAIL_API_KEY`, and `NSCALE_API_KEY` | API-key candidates; OpenAI-compatible models at fixed provider endpoints |
163
+ | Validated cloud API registry | Azure OpenAI (`AZURE_OPENAI_API_KEY`, `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_DEPLOYMENT`), Cloudflare Workers AI (`CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_API_KEY`), Databricks (`DATABRICKS_TOKEN`, `DATABRICKS_HOST`, `DATABRICKS_MODEL`), and DashScope (`DASHSCOPE_API_KEY`, optional `DASHSCOPE_BASE_URL`) | API-key candidates; OpenAI-compatible models with provider-owned HTTPS endpoints |
164
+ | Generic API-key registry | `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`/`GEMINI_API_KEY`, `XAI_API_KEY`, `GROQ_API_KEY`, `MISTRAL_API_KEY`, `COHERE_API_KEY`, `CEREBRAS_API_KEY`, `HF_TOKEN`/`HUGGINGFACE_API_KEY`, `OPENROUTER_API_KEY`, `DEEPSEEK_API_KEY`, `FIREWORKS_API_KEY`, `TOGETHER_API_KEY`, `PERPLEXITY_API_KEY`, `SAMBANOVA_API_KEY` | API-key candidates; the Pydantic AI provider factory, with documented OpenAI-compatible fallbacks where available |
165
+
166
+ The fixed compatible registry currently covers 22 API-key providers, including
167
+ AkashML, Scaleway, Friendli, Clarifai, Meta Model API, Parasail, and Nscale.
168
+ These credentials are ordinary API credentials, not subscription or account-
169
+ login integrations.
170
+
171
+ The model construction path supports the registered provider IDs: API and
172
+ account integrations use `trance.models.build_model()`, while Claude Code,
173
+ Grok Build, Gemini CLI, Cody, and OpenCode use text-only CLI adapters. It creates Pydantic AI model objects
174
+ without sending a request and loads optional provider dependencies lazily. Use
175
+ `TRANCE_MODEL_<PROVIDER>` variables to override defaults where the source
176
+ supports them. To use the optional Grok Build integration, install the
177
+ official `grok` CLI and authenticate it with `grok login` (or
178
+ `grok login --device-auth` on a headless machine). Discovery only checks the
179
+ CLI and bounded OIDC metadata in the saved `auth.json`; it does not claim that
180
+ the session is valid until the CLI handles a model request. The optional Gemini
181
+ CLI integration similarly requires the official `gemini` CLI and a saved
182
+ `oauth_creds.json`; discovery emits its terms warning whenever it finds one.
183
+ The optional Cody and OpenCode integrations likewise require their respective
184
+ CLIs to be installed; discovery performs only their documented local login or
185
+ metadata checks and does not make a model request.
186
+
187
+ Discovery performs no live model API validation and does not establish that a
188
+ credential is valid, permitted for a particular use, or within quota. It may
189
+ inspect explicitly supported local files, including bounded Codex auth metadata,
190
+ Grok OIDC metadata, Gemini OAuth metadata, OpenCode auth metadata, bounded AWS
191
+ profiles, and local Vertex ADC metadata, run `cody auth whoami` and `gh auth
192
+ status` and (when materializing a Copilot candidate) `gh auth token`, resolve a
193
+ saved Hugging Face token, and run `claude auth status` plus a credentials-file
194
+ existence check to detect a saved Claude subscription login. The Claude CLI is not used for a model request until a
195
+ Pydantic AI request is made. Its adapter supports text requests only; it does
196
+ not support Pydantic AI tools or structured output.
197
+
198
+ Cursor, Kiro, Tabnine, and Kimi Code adapters remain source-only and are
199
+ intentionally excluded from `scan()` results because they have no safe,
200
+ supported model bridge. In particular, their CLIs can expose hooks,
201
+ integrations, or credential flows that cannot be constrained to the supported
202
+ text-only request path.
203
+
204
+ Read the vendors' documentation for their authentication and use conditions:
205
+ [Codex CLI sign-in](https://help.openai.com/en/articles/11381614-api-codex-cli-and-sign-in-with-chatgpt),
206
+ [Copilot CLI authentication](https://docs.github.com/en/copilot/how-tos/copilot-cli/set-up-copilot-cli/authenticate-copilot-cli),
207
+ [Claude Code authentication](https://code.claude.com/docs/en/iam),
208
+ [Grok Build overview](https://docs.x.ai/build/overview),
209
+ [Grok Build CLI reference](https://docs.x.ai/build/cli/reference),
210
+ [Sourcegraph Cody CLI](https://sourcegraph.com/docs/cody/overview),
211
+ [OpenCode documentation](https://opencode.ai/docs/),
212
+ [Amazon Bedrock authentication](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html),
213
+ [Google Vertex AI authentication](https://cloud.google.com/docs/authentication/application-default-credentials),
214
+ [Z.AI documentation](https://docs.z.ai/),
215
+ [Qwen Code Coding Plan](https://github.com/QwenLM/qwen-code/blob/main/docs/users/configuration/model-providers.md),
216
+ [Hugging Face Hub login](https://huggingface.co/docs/huggingface_hub/quick-start#login),
217
+ [Poe API keys](https://creator.poe.com/docs/external-applications),
218
+ [MiniMax API](https://platform.minimax.io/docs/api-reference),
219
+ [Mistral Vibe](https://docs.mistral.ai/capabilities/vibe/).
220
+
221
+ ## Development
222
+
223
+ This repository uses `uv` and `xonsh`:
224
+
225
+ ```sh
226
+ uv sync --extra dev
227
+ uv run pytest
228
+ uv run ruff check .
229
+ ```
trance-0.1.0/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # trance
2
+
3
+ `trance` discovers a limited set of documented credentials and signed-in
4
+ coding tools already configured on your machine, then builds model objects
5
+ using [Pydantic AI](https://ai.pydantic.dev/). It is a small Python library
6
+ for applications that want to reuse supported local provider setups.
7
+
8
+ Consumer subscriptions do not automatically grant general API access. A
9
+ credential being present does not establish that a provider permits using it
10
+ from arbitrary software. `trance` scans only documented local auth state. It
11
+ does not search private browser stores or undocumented application stores;
12
+ raw token strings are not returned or logged, although model objects may retain
13
+ auth internally for requests. Supported CLI adapters may privately stage
14
+ documented saved credentials for a request. Gemini CLI OAuth
15
+ is surfaced only with a warning because its [terms prohibit third-party
16
+ access to the service through its OAuth session and may suspend or terminate
17
+ accounts](https://github.com/google-gemini/gemini-cli/blob/main/docs/resources/tos-privacy.md).
18
+
19
+ ## Coverage at a glance
20
+
21
+ | Product | Current supported path |
22
+ | --- | --- |
23
+ | OpenAI Codex | Subscription authentication delegated to the documented Codex CLI/Pydantic AI integration |
24
+ | Claude Code | Subscription authentication delegated to the documented Claude CLI, including a saved CLI login or `CLAUDE_CODE_OAUTH_TOKEN` |
25
+ | Grok Build consumer | Optional integration requiring the installed official `grok` CLI and an authenticated saved session; the CLI adapter validates the session lazily when a request runs |
26
+ | Grok API (xAI) | `XAI_API_KEY` through the regular API-key registry; this is a separate API credential path |
27
+ | Gemini CLI consumer | Optional saved-login integration using the installed `gemini` CLI and `~/.gemini/oauth_creds.json`; discovery emits the documented terms warning and does not provide an opt-in switch |
28
+ | Gemini API | `GOOGLE_API_KEY` or `GEMINI_API_KEY` through the regular API-key registry; this is a separate API credential path |
29
+ | Sourcegraph Cody | Optional saved account login delegated to the installed `cody` CLI |
30
+ | OpenCode | Optional provider-keyed `auth.json` entries for known defaults and model overrides; account/API credentials are delegated to an isolated, no-tools `opencode` CLI |
31
+ | AWS Bedrock | Optional local environment, profile, or SSO credential chain; uses the `bedrock` extra |
32
+ | Google Vertex AI | Optional local Application Default Credentials (ADC); uses the `google` extra |
33
+
34
+ Grok Build and the xAI API are separate credential paths. A consumer account
35
+ or subscription does not by itself provide an xAI API credential. Gemini CLI
36
+ OAuth is a separate, warned integration with Google's terms risk; Gemini API
37
+ keys remain a separate credential path.
38
+
39
+ ## Install
40
+
41
+ For a checkout, install the package and development dependencies with:
42
+
43
+ ```sh
44
+ uv sync --extra dev
45
+ ```
46
+
47
+ The core dependency includes Pydantic AI's OpenAI support. Optional extras for
48
+ provider integrations supported by `trance` are `anthropic`, `bedrock`,
49
+ `cerebras`, `cohere`, `crusoe`, `google`, `groq`, `huggingface`, `mistral`,
50
+ `openrouter`, and `xai`. The fixed compatible adapters, including Crusoe, use
51
+ the core OpenAI-compatible model path, so the `crusoe` extra is not required
52
+ for them.
53
+
54
+ ## Quick start
55
+
56
+ Sign in with a supported local CLI or configure a documented provider key,
57
+ then scan:
58
+
59
+ ```python
60
+ from trance.discovery import scan
61
+ from pydantic_ai import Agent
62
+
63
+ found = scan()
64
+ for item in found:
65
+ print(item.provider, item.auth_kind, item.source, item.model_name)
66
+
67
+ # Use a discovered Pydantic AI Model with Agent. Calling run() sends a request.
68
+ agents = [Agent(model=item.model) for item in found]
69
+ ```
70
+
71
+ `scan()` returns `list[FoundModel]`. Each record identifies the provider,
72
+ authentication kind, discovery source, and model name alongside a Pydantic AI
73
+ `Model`. It constructs objects without sending a request. It does not check
74
+ whether a credential is currently valid, permitted for a particular use, or
75
+ within quota. A `FoundModel` represents a successfully constructed model;
76
+ source adapters that cannot be safely connected to a supported model are
77
+ skipped in the default non-strict mode. Set `strict=True` to raise on a source
78
+ or model construction failure.
79
+
80
+ You can restrict discovery by provider ID, or pass an environment mapping and
81
+ home directory for controlled runs:
82
+
83
+ ```python
84
+ from pathlib import Path
85
+ from trance.discovery import scan
86
+
87
+ found = scan(
88
+ environ={"OPENAI_API_KEY": "sk-example-not-a-real-key"},
89
+ home=Path("/home/me"),
90
+ providers={"openai"},
91
+ )
92
+ ```
93
+
94
+ Avoid printing or logging the model object: it may retain provider
95
+ authentication material for requests. `FoundModel` and candidate
96
+ representations redact their model and secret fields. The `source` field
97
+ describes where a credential was found and is safe to display.
98
+
99
+ ## Discovery sources
100
+
101
+ `scan()` currently registers these adapters. Subscription and account
102
+ integrations are scanned first; ordinary API credentials are scanned after
103
+ them. A subscription login is an integration with the vendor's documented
104
+ account or CLI flow. It is not a general-purpose API key.
105
+
106
+ | Provider or source | What is read | Result and model factory |
107
+ | --- | --- | --- |
108
+ | OpenAI Codex | Bounded metadata from `~/.codex/auth.json` or the file under `CODEX_HOME` (`auth_mode` and the `tokens` shape); token values are never exposed | Subscription candidate; `OpenAICodexModel` resolves the credential |
109
+ | GitHub Copilot | `GITHUB_COPILOT_API_KEY`, `GITHUB_COPILOT_API_TOKEN`, `COPILOT_GITHUB_TOKEN`, or a saved `gh` login | Subscription candidate; `GitHubCopilotModel` |
110
+ | Claude Code | `CLAUDE_CODE_OAUTH_TOKEN`, or a saved first-party login confirmed by `claude auth status` plus `~/.claude/.credentials.json` (or `CLAUDE_CONFIG_DIR/.credentials.json`) | Subscription candidate; text-only Claude CLI model, defaulting to `sonnet` |
111
+ | Poe | `POE_API_KEY` | Subscription candidate; OpenAI-compatible model at Poe's endpoint |
112
+ | MiniMax Coding Plan | `MINIMAX_API_KEY` with the `sk-cp-` prefix and an allowed `MINIMAX_API_HOST` | Subscription candidate; OpenAI-compatible model |
113
+ | Mistral Vibe | `MISTRAL_API_KEY` or `~/.vibe/.env:MISTRAL_API_KEY` | API-key candidate; Mistral model |
114
+ | Qwen Code Coding Plan | `BAILIAN_CODING_PLAN_API_KEY` or supported `~/.qwen/settings.json`, with an `sk-sp-` key | Subscription candidate; OpenAI-compatible model at an allowed Coding Plan endpoint |
115
+ | Hugging Face Hub | Saved login resolved by `huggingface_hub.get_token()` in the real process context | Account candidate; Hugging Face model |
116
+ | Grok Build consumer | Installed `grok` executable and bounded metadata from a non-symlink `~/.grok/auth.json` (or `GROK_HOME/auth.json`) confirming an OIDC record; token values are not retained | Optional account candidate; isolated, text-only Grok CLI model; session validity is checked lazily by the CLI when a request runs, and refreshed auth is promoted back safely |
117
+ | Gemini CLI consumer | Installed `gemini` executable and bounded metadata from `~/.gemini/oauth_creds.json` (or `GEMINI_CLI_HOME/.gemini/oauth_creds.json`) confirming a refresh token; emits a terms warning | Optional account candidate; isolated, text-only Gemini CLI model; no opt-in bypass for the warning |
118
+ | Sourcegraph Cody | Installed `cody` executable and a successful local `cody auth whoami` check with dedicated PAT variables removed | Account candidate; text-only Cody CLI model |
119
+ | OpenCode | Installed `opencode` executable and bounded, provider-keyed `~/.local/share/opencode/auth.json` metadata; recognized OAuth, API-key, and well-known entries only | Account or API-key candidate; isolated `opencode --pure` text-only model with tools disabled; OpenCode manages its own provider-specific OAuth flow |
120
+ | AWS Bedrock | `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`, or bounded AWS profile credentials/SSO configuration plus a region | Account candidate; Bedrock model through the optional `bedrock` integration |
121
+ | Google Vertex AI | Bounded local ADC metadata from `GOOGLE_APPLICATION_CREDENTIALS` or gcloud ADC, plus a project and optional location | Account candidate; Vertex model through the optional `google` integration |
122
+ | Z.AI | `ZAI_API_KEY` for the general API and `ZAI_CODING_PLAN_API_KEY` for the Coding Plan endpoint | General API-key candidate or Coding Plan subscription candidate; OpenAI-compatible models at separate official endpoints |
123
+ | Fixed compatible API registry | `MOONSHOT_API_KEY`, `NEBIUS_API_KEY`, `DEEPINFRA_TOKEN`/`DEEPINFRA_API_KEY`, `NVIDIA_API_KEY`, `NOVITA_API_KEY`, `AIML_API_KEY`, `OVH_AI_ENDPOINTS_ACCESS_TOKEN`, `HELICONE_API_KEY`, `REQUESTY_API_KEY`, `FEATHERLESS_API_KEY`, `HYPERBOLIC_API_KEY`, `CRUSOE_API_KEY`, `SILICONFLOW_API_KEY`, `VENICE_API_KEY`, `CHUTES_API_KEY`, `AKASH_API_KEY`, `SCW_SECRET_KEY`, `FRIENDLI_API_KEY`, `CLARIFAI_PAT`, `MODEL_API_KEY`, `PARASAIL_API_KEY`, and `NSCALE_API_KEY` | API-key candidates; OpenAI-compatible models at fixed provider endpoints |
124
+ | Validated cloud API registry | Azure OpenAI (`AZURE_OPENAI_API_KEY`, `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_DEPLOYMENT`), Cloudflare Workers AI (`CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_API_KEY`), Databricks (`DATABRICKS_TOKEN`, `DATABRICKS_HOST`, `DATABRICKS_MODEL`), and DashScope (`DASHSCOPE_API_KEY`, optional `DASHSCOPE_BASE_URL`) | API-key candidates; OpenAI-compatible models with provider-owned HTTPS endpoints |
125
+ | Generic API-key registry | `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`/`GEMINI_API_KEY`, `XAI_API_KEY`, `GROQ_API_KEY`, `MISTRAL_API_KEY`, `COHERE_API_KEY`, `CEREBRAS_API_KEY`, `HF_TOKEN`/`HUGGINGFACE_API_KEY`, `OPENROUTER_API_KEY`, `DEEPSEEK_API_KEY`, `FIREWORKS_API_KEY`, `TOGETHER_API_KEY`, `PERPLEXITY_API_KEY`, `SAMBANOVA_API_KEY` | API-key candidates; the Pydantic AI provider factory, with documented OpenAI-compatible fallbacks where available |
126
+
127
+ The fixed compatible registry currently covers 22 API-key providers, including
128
+ AkashML, Scaleway, Friendli, Clarifai, Meta Model API, Parasail, and Nscale.
129
+ These credentials are ordinary API credentials, not subscription or account-
130
+ login integrations.
131
+
132
+ The model construction path supports the registered provider IDs: API and
133
+ account integrations use `trance.models.build_model()`, while Claude Code,
134
+ Grok Build, Gemini CLI, Cody, and OpenCode use text-only CLI adapters. It creates Pydantic AI model objects
135
+ without sending a request and loads optional provider dependencies lazily. Use
136
+ `TRANCE_MODEL_<PROVIDER>` variables to override defaults where the source
137
+ supports them. To use the optional Grok Build integration, install the
138
+ official `grok` CLI and authenticate it with `grok login` (or
139
+ `grok login --device-auth` on a headless machine). Discovery only checks the
140
+ CLI and bounded OIDC metadata in the saved `auth.json`; it does not claim that
141
+ the session is valid until the CLI handles a model request. The optional Gemini
142
+ CLI integration similarly requires the official `gemini` CLI and a saved
143
+ `oauth_creds.json`; discovery emits its terms warning whenever it finds one.
144
+ The optional Cody and OpenCode integrations likewise require their respective
145
+ CLIs to be installed; discovery performs only their documented local login or
146
+ metadata checks and does not make a model request.
147
+
148
+ Discovery performs no live model API validation and does not establish that a
149
+ credential is valid, permitted for a particular use, or within quota. It may
150
+ inspect explicitly supported local files, including bounded Codex auth metadata,
151
+ Grok OIDC metadata, Gemini OAuth metadata, OpenCode auth metadata, bounded AWS
152
+ profiles, and local Vertex ADC metadata, run `cody auth whoami` and `gh auth
153
+ status` and (when materializing a Copilot candidate) `gh auth token`, resolve a
154
+ saved Hugging Face token, and run `claude auth status` plus a credentials-file
155
+ existence check to detect a saved Claude subscription login. The Claude CLI is not used for a model request until a
156
+ Pydantic AI request is made. Its adapter supports text requests only; it does
157
+ not support Pydantic AI tools or structured output.
158
+
159
+ Cursor, Kiro, Tabnine, and Kimi Code adapters remain source-only and are
160
+ intentionally excluded from `scan()` results because they have no safe,
161
+ supported model bridge. In particular, their CLIs can expose hooks,
162
+ integrations, or credential flows that cannot be constrained to the supported
163
+ text-only request path.
164
+
165
+ Read the vendors' documentation for their authentication and use conditions:
166
+ [Codex CLI sign-in](https://help.openai.com/en/articles/11381614-api-codex-cli-and-sign-in-with-chatgpt),
167
+ [Copilot CLI authentication](https://docs.github.com/en/copilot/how-tos/copilot-cli/set-up-copilot-cli/authenticate-copilot-cli),
168
+ [Claude Code authentication](https://code.claude.com/docs/en/iam),
169
+ [Grok Build overview](https://docs.x.ai/build/overview),
170
+ [Grok Build CLI reference](https://docs.x.ai/build/cli/reference),
171
+ [Sourcegraph Cody CLI](https://sourcegraph.com/docs/cody/overview),
172
+ [OpenCode documentation](https://opencode.ai/docs/),
173
+ [Amazon Bedrock authentication](https://docs.aws.amazon.com/bedrock/latest/userguide/security-iam.html),
174
+ [Google Vertex AI authentication](https://cloud.google.com/docs/authentication/application-default-credentials),
175
+ [Z.AI documentation](https://docs.z.ai/),
176
+ [Qwen Code Coding Plan](https://github.com/QwenLM/qwen-code/blob/main/docs/users/configuration/model-providers.md),
177
+ [Hugging Face Hub login](https://huggingface.co/docs/huggingface_hub/quick-start#login),
178
+ [Poe API keys](https://creator.poe.com/docs/external-applications),
179
+ [MiniMax API](https://platform.minimax.io/docs/api-reference),
180
+ [Mistral Vibe](https://docs.mistral.ai/capabilities/vibe/).
181
+
182
+ ## Development
183
+
184
+ This repository uses `uv` and `xonsh`:
185
+
186
+ ```sh
187
+ uv sync --extra dev
188
+ uv run pytest
189
+ uv run ruff check .
190
+ ```
@@ -0,0 +1,47 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "trance"
7
+ version = "0.1.0"
8
+ description = "Discover local model provider sessions and expose them through Pydantic AI"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ dependencies = [
13
+ "pydantic-ai-slim[openai]>=2.51.0,<3",
14
+ ]
15
+
16
+ [project.optional-dependencies]
17
+ anthropic = ["pydantic-ai-slim[anthropic]>=2.51.0,<3"]
18
+ bedrock = ["pydantic-ai-slim[bedrock]>=2.51.0,<3"]
19
+ cerebras = ["pydantic-ai-slim[cerebras]>=2.51.0,<3"]
20
+ cohere = ["pydantic-ai-slim[cohere]>=2.51.0,<3"]
21
+ crusoe = ["pydantic-ai-slim[crusoe]>=2.51.0,<3"]
22
+ google = ["pydantic-ai-slim[google]>=2.51.0,<3"]
23
+ groq = ["pydantic-ai-slim[groq]>=2.51.0,<3"]
24
+ huggingface = ["pydantic-ai-slim[huggingface]>=2.51.0,<3"]
25
+ mistral = ["pydantic-ai-slim[mistral]>=2.51.0,<3"]
26
+ openrouter = ["pydantic-ai-slim[openrouter]>=2.51.0,<3"]
27
+ voyageai = ["pydantic-ai-slim[voyageai]>=2.51.0,<3"]
28
+ xai = ["pydantic-ai-slim[xai]>=2.51.0,<3"]
29
+ zai = ["pydantic-ai-slim[zai]>=2.51.0,<3"]
30
+ dev = [
31
+ "pytest>=8.3,<10",
32
+ "ruff>=0.12,<1",
33
+ ]
34
+
35
+ [tool.hatch.build.targets.wheel]
36
+ packages = ["src/trance"]
37
+
38
+ [tool.pytest.ini_options]
39
+ testpaths = ["tests"]
40
+ addopts = "-q"
41
+
42
+ [tool.ruff]
43
+ line-length = 100
44
+ target-version = "py311"
45
+
46
+ [tool.ruff.lint]
47
+ select = ["E", "F", "I", "UP"]
@@ -0,0 +1,36 @@
1
+ """Discover local model sessions and expose them through a stable API.
2
+
3
+ The package root intentionally avoids importing discovery and model adapters
4
+ until a caller uses them. This keeps a plain ``import trance`` inexpensive.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from importlib import import_module
10
+ from typing import Any
11
+
12
+ __version__ = "0.1.0"
13
+
14
+ _EXPORTS = {
15
+ "scan": ("trance.discovery", "scan"),
16
+ "clients": ("trance.discovery", "clients"),
17
+ "Candidate": ("trance.types", "Candidate"),
18
+ "FoundModel": ("trance.types", "FoundModel"),
19
+ }
20
+
21
+ __all__ = ["__version__", *_EXPORTS]
22
+
23
+
24
+ def __getattr__(name: str) -> Any:
25
+ """Load public API objects only when requested."""
26
+ try:
27
+ module_name, attribute = _EXPORTS[name]
28
+ except KeyError:
29
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from None
30
+ value = getattr(import_module(module_name), attribute)
31
+ globals()[name] = value
32
+ return value
33
+
34
+
35
+ def __dir__() -> list[str]:
36
+ return sorted(set(globals()) | set(__all__))