argo-proxy 3.0.1b2__tar.gz → 3.0.2__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 (78) hide show
  1. argo_proxy-3.0.2/PKG-INFO +334 -0
  2. argo_proxy-3.0.2/README.md +292 -0
  3. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/pyproject.toml +4 -2
  4. argo_proxy-3.0.2/src/argo_proxy.egg-info/PKG-INFO +334 -0
  5. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argo_proxy.egg-info/requires.txt +1 -1
  6. argo_proxy-3.0.2/src/argoproxy/__init__.py +1 -0
  7. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_vendor/semver.py +143 -164
  8. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_vendor/yaml.py +2 -3
  9. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/endpoints/dispatch.py +31 -0
  10. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/models.py +1 -0
  11. argo_proxy-3.0.1b2/PKG-INFO +0 -467
  12. argo_proxy-3.0.1b2/README.md +0 -425
  13. argo_proxy-3.0.1b2/src/argo_proxy.egg-info/PKG-INFO +0 -467
  14. argo_proxy-3.0.1b2/src/argoproxy/__init__.py +0 -1
  15. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/LICENSE +0 -0
  16. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/setup.cfg +0 -0
  17. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argo_proxy.egg-info/SOURCES.txt +0 -0
  18. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argo_proxy.egg-info/dependency_links.txt +0 -0
  19. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argo_proxy.egg-info/entry_points.txt +0 -0
  20. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argo_proxy.egg-info/top_level.txt +0 -0
  21. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/__init__.py +0 -0
  22. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/endpoints/__init__.py +0 -0
  23. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/endpoints/chat.py +0 -0
  24. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/endpoints/completions.py +0 -0
  25. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/endpoints/embed.py +0 -0
  26. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/endpoints/native_anthropic.py +0 -0
  27. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/endpoints/native_openai.py +0 -0
  28. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/endpoints/responses.py +0 -0
  29. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/tool_calls/deprecated.py +0 -0
  30. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/tool_calls/google_helpers.py +0 -0
  31. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/tool_calls/handler.py +0 -0
  32. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/tool_calls/input_handle.py +0 -0
  33. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/tool_calls/leaked_tool_parser.py +0 -0
  34. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/tool_calls/output_handle.py +0 -0
  35. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/tool_calls/tool_prompts.py +0 -0
  36. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/types/__init__.py +0 -0
  37. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/types/chat_completion.py +0 -0
  38. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/types/completions.py +0 -0
  39. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/types/embedding.py +0 -0
  40. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/types/function_call.py +0 -0
  41. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/types/responses.py +0 -0
  42. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/utils/__init__.py +0 -0
  43. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/utils/input_handle.py +0 -0
  44. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/utils/models.py +0 -0
  45. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/utils/stream_decoder.py +0 -0
  46. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/utils/tokens.py +0 -0
  47. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_legacy/utils/usage.py +0 -0
  48. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/_vendor/__init__.py +0 -0
  49. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/app.py +0 -0
  50. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/cli/__init__.py +0 -0
  51. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/cli/display.py +0 -0
  52. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/cli/handlers.py +0 -0
  53. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/cli/parser.py +0 -0
  54. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/config/__init__.py +0 -0
  55. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/config/interactive.py +0 -0
  56. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/config/io.py +0 -0
  57. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/config/model.py +0 -0
  58. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/config/validation.py +0 -0
  59. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/endpoints/dev_proxy.py +0 -0
  60. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/endpoints/extras.py +0 -0
  61. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/endpoints/passthrough.py +0 -0
  62. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/performance.py +0 -0
  63. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/py.typed +0 -0
  64. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/utils/attack_logger.py +0 -0
  65. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/utils/image_processing.py +0 -0
  66. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/utils/logging.py +0 -0
  67. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/utils/misc.py +0 -0
  68. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/utils/models.py +0 -0
  69. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/utils/tool_calls.py +0 -0
  70. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/src/argoproxy/utils/transports.py +0 -0
  71. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/test/test_chat_completions.py +0 -0
  72. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/test/test_embeddings.py +0 -0
  73. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/test/test_function_calling_multiple.py +0 -0
  74. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/test/test_function_calling_single.py +0 -0
  75. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/test/test_leaked_tool_parser.py +0 -0
  76. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/test/test_legacy_completions.py +0 -0
  77. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/test/test_model_resolution.py +0 -0
  78. {argo_proxy-3.0.1b2 → argo_proxy-3.0.2}/tests/test_config_migrate.py +0 -0
@@ -0,0 +1,334 @@
1
+ Metadata-Version: 2.4
2
+ Name: argo-proxy
3
+ Version: 3.0.2
4
+ Summary: Proxy server to Argo API, OpenAI format compatible
5
+ Author-email: Peng Ding <oaklight@gmx.com>
6
+ License-Expression: MIT
7
+ Project-URL: Documentation, https://github.com/Oaklight/argo-openai-proxy#readme
8
+ Project-URL: Repository, https://github.com/Oaklight/argo-openai-proxy
9
+ Project-URL: Issuses, https://github.com/Oaklight/argo-openai-proxy/issues
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Software Development
13
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: aiohttp>=3.12.2
18
+ Requires-Dist: llm-rosetta<0.7.0,>=0.6.0
19
+ Requires-Dist: pydantic>=2.11.7
20
+ Requires-Dist: tiktoken>=0.9.0
21
+ Requires-Dist: tqdm>=4.67.1
22
+ Requires-Dist: Pillow>=12.0.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: dotenv>=0.9.9; extra == "dev"
25
+ Requires-Dist: openai>=1.79.0; extra == "dev"
26
+ Requires-Dist: ruff>=0.15.0; extra == "dev"
27
+ Requires-Dist: ty>=0.0.31; extra == "dev"
28
+ Requires-Dist: complexipy>=5.2.0; extra == "dev"
29
+ Requires-Dist: build>=1.2.2.post1; extra == "dev"
30
+ Requires-Dist: twine>=6.1.0; extra == "dev"
31
+ Requires-Dist: httpx>=0.28.1; extra == "dev"
32
+ Requires-Dist: requests>=2.25.1; extra == "dev"
33
+ Provides-Extra: test
34
+ Requires-Dist: openai>=1.79.0; extra == "test"
35
+ Requires-Dist: python-dotenv>=1.0.0; extra == "test"
36
+ Requires-Dist: numpy>=1.24.0; extra == "test"
37
+ Requires-Dist: pytest>=7.0.0; extra == "test"
38
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
39
+ Provides-Extra: all
40
+ Requires-Dist: argo-proxy[dev,test]; extra == "all"
41
+ Dynamic: license-file
42
+
43
+ # argo-proxy
44
+
45
+ [![PyPI version](https://img.shields.io/pypi/v/argo-proxy?color=green)](https://pypi.org/project/argo-proxy/)
46
+ [![PyPI pre-release](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/Oaklight/c6a14fa27347321adfed1a01964b17c1/raw/pypi-badge.json)](https://pypi.org/project/argo-proxy/#history)
47
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
48
+
49
+ A universal API gateway for LLM services via ARGO. Translates between OpenAI, Anthropic, and Google GenAI API formats, routing requests to optimal upstream ARGO endpoints. Works with AI coding tools like Claude Code, Codex CLI, Aider, Gemini CLI, and more.
50
+
51
+ For detailed documentation, visit the [argo-proxy ReadTheDocs page](https://argo-proxy.readthedocs.io/en/latest/).
52
+
53
+ ## TL;DR
54
+
55
+ ```bash
56
+ pip install argo-proxy # install
57
+ argo-proxy serve # start the proxy
58
+ ```
59
+
60
+ A single proxy instance serves **all 4 major LLM API formats**:
61
+
62
+ | API Format | Endpoint | Example Client |
63
+ | --- | --- | --- |
64
+ | OpenAI Chat Completions | `/v1/chat/completions` | OpenAI SDK, Aider, OpenCode |
65
+ | OpenAI Responses | `/v1/responses` | Codex CLI |
66
+ | Anthropic Messages | `/v1/messages` | Claude Code, Kilo Code |
67
+ | Google GenAI | `/v1beta/models/{model}:generateContent` | Gemini CLI |
68
+
69
+ ## NOTICE OF USAGE
70
+
71
+ The machine or server making API calls to Argo must be connected to the Argonne internal network or through a VPN on an Argonne-managed computer if you are working off-site. Your instance of the argo proxy should always be on-premise at an Argonne machine. The software is provided "as is," without any warranties. By using this software, you accept that the authors, contributors, and affiliated organizations will not be liable for any damages or issues arising from its use. You are solely responsible for ensuring the software meets your requirements.
72
+
73
+ - [Notice of Usage](#notice-of-usage)
74
+ - [Deployment](#deployment)
75
+ - [Prerequisites](#prerequisites)
76
+ - [Configuration](#configuration)
77
+ - [Running the Proxy](#running-the-proxy)
78
+ - [First-Time Setup](#first-time-setup)
79
+ - [Configuration Options Reference](#configuration-options-reference)
80
+ - [CLI Reference](#cli-reference)
81
+ - [Usage](#usage)
82
+ - [Endpoints](#endpoints)
83
+ - [Models](#models)
84
+ - [Tool Calls](#tool-calls)
85
+ - [AI Coding Tools Integration](#ai-coding-tools-integration)
86
+ - [Examples](#examples)
87
+ - [Bug Reports and Contributions](#bug-reports-and-contributions)
88
+
89
+ ## Deployment
90
+
91
+ ### Prerequisites
92
+
93
+ - **Python 3.10+** is required. </br>
94
+ Recommended: use conda, mamba, or pipx to manage an exclusive environment. </br>
95
+ **Conda/Mamba** Download and install from: <https://conda-forge.org/download/> </br>
96
+ **pipx** Download and install from: <https://pipx.pypa.io/stable/installation/>
97
+
98
+ - Install:
99
+
100
+ PyPI current version: ![PyPI - Version](https://img.shields.io/pypi/v/argo-proxy)
101
+
102
+ ```bash
103
+ pip install argo-proxy
104
+ ```
105
+
106
+ To upgrade:
107
+
108
+ ```bash
109
+ argo-proxy update check # check for updates (includes dependency status)
110
+ argo-proxy update install # install latest stable
111
+ argo-proxy update install --pre # install latest pre-release
112
+ ```
113
+
114
+ Or, from source (at the repo root):
115
+ ![GitHub Release](https://img.shields.io/github/v/release/Oaklight/argo-proxy)
116
+
117
+ ```bash
118
+ pip install .
119
+ ```
120
+
121
+ ### Configuration
122
+
123
+ The application uses a YAML config file (v3 format). If you don't have one, [First-Time Setup](#first-time-setup) will create it interactively.
124
+
125
+ ```yaml
126
+ config_version: "3"
127
+ user: "your_username"
128
+ host: 0.0.0.0
129
+ port: 44497
130
+ verbose: true
131
+
132
+ argo_base_url: "https://apps.inside.anl.gov/argoapi"
133
+ ```
134
+
135
+ Config file search order (first found is used):
136
+
137
+ 1. `./config.yaml` (current directory)
138
+ 2. `~/.config/argoproxy/config.yaml`
139
+ 3. `~/.argoproxy/config.yaml`
140
+
141
+ Migrate from v1/v2 config:
142
+
143
+ ```bash
144
+ argo-proxy config migrate /path/to/old/config.yaml
145
+ ```
146
+
147
+ ### Running the Proxy
148
+
149
+ ```bash
150
+ argo-proxy serve # default config search
151
+ argo-proxy serve /path/to/config.yaml # explicit config
152
+ argo-proxy serve --verbose --show # verbose mode, show config at startup
153
+ ```
154
+
155
+ ### First-Time Setup
156
+
157
+ Create a new config interactively:
158
+
159
+ ```bash
160
+ argo-proxy config init
161
+ ```
162
+
163
+ This will:
164
+
165
+ 1. Prompt for your ANL username
166
+ 2. Select a random available port (can be overridden)
167
+ 3. Choose upstream environment (prod/dev/test)
168
+ 4. Validate connectivity to upstream URLs
169
+ 5. Write the config file to `~/.config/argoproxy/config.yaml`
170
+
171
+ ### Configuration Options Reference
172
+
173
+ | Option | Description | Default |
174
+ | --- | --- | --- |
175
+ | `config_version` | Config format version | `"3"` |
176
+ | `user` | Your ANL username | (required) |
177
+ | `host` | Host address to bind to | `0.0.0.0` |
178
+ | `port` | Port number | `44497` |
179
+ | `verbose` | Enable verbose logging | `true` |
180
+ | `argo_base_url` | Base URL for ARGO API | Dev URL |
181
+ | `native_openai_base_url` | Custom OpenAI endpoint (auto-derived if unset) | — |
182
+ | `native_anthropic_base_url` | Custom Anthropic endpoint (auto-derived if unset) | — |
183
+ | `anthropic_stream_mode` | Non-streaming Anthropic handling: `force`/`retry`/`passthrough` | `force` |
184
+ | `force_conversion` | Always run full format conversion | `false` |
185
+ | `use_legacy_argo` | Use legacy ARGO gateway pipeline | `false` |
186
+ | `skip_url_validation` | Skip upstream URL checks on startup | `false` |
187
+ | `connection_test_timeout` | Seconds for URL validation | `5` |
188
+ | `resolve_overrides` | DNS overrides for SSH tunnels (host:port -> IP) | `{}` |
189
+ | `max_log_history` | Keep last N messages in verbose logs | `3` |
190
+ | `enable_payload_control` | Enable image payload size control | `false` |
191
+ | `max_payload_size` | Max image payload size in MB | `20` |
192
+ | `image_timeout` | Image download timeout in seconds | `30` |
193
+ | `concurrent_downloads` | Parallel image downloads | `10` |
194
+
195
+ ### CLI Reference
196
+
197
+ ```
198
+ argo-proxy [-h] [--version] {serve,config,logs,update,models}
199
+ ```
200
+
201
+ | Command | Description |
202
+ | --- | --- |
203
+ | `serve [config]` | Start the proxy server |
204
+ | `config edit` | Open config in default editor |
205
+ | `config validate` | Validate config and check connectivity |
206
+ | `config show` | Display resolved config |
207
+ | `config migrate` | Migrate v1/v2 config to v3 |
208
+ | `config init` | Interactive config setup |
209
+ | `config list` | List all found config files |
210
+ | `config env [prod\|dev\|test]` | Show or switch upstream environment |
211
+ | `logs collect [--type TYPE]` | Collect diagnostic logs |
212
+ | `update check` | Check for updates (argo-proxy + llm-rosetta) |
213
+ | `update install [--pre]` | Install latest version |
214
+ | `models [--json]` | List available models and aliases |
215
+
216
+ Key `serve` flags:
217
+
218
+ ```bash
219
+ argo-proxy serve --verbose # verbose logging
220
+ argo-proxy serve --force-conversion # always convert via llm-rosetta
221
+ argo-proxy serve --username-passthrough # use API key as username
222
+ argo-proxy serve --anthropic-stream-mode retry # try non-streaming first
223
+ argo-proxy serve --legacy-argo # use legacy ARGO gateway pipeline
224
+ argo-proxy serve --dump-requests # dump request/response for debugging
225
+ ```
226
+
227
+ ## Usage
228
+
229
+ ### Endpoints
230
+
231
+ #### API Format Endpoints
232
+
233
+ All four formats are served simultaneously from a single proxy instance:
234
+
235
+ | Endpoint | Format | Typical Client |
236
+ | --- | --- | --- |
237
+ | `/v1/chat/completions` | OpenAI Chat Completions | OpenAI SDK, Aider, OpenCode |
238
+ | `/v1/responses` | OpenAI Responses | Codex CLI |
239
+ | `/v1/messages` | Anthropic Messages | Claude Code, Anthropic SDK |
240
+ | `/v1beta/models/{model}:generateContent` | Google GenAI | Gemini CLI |
241
+ | `/v1beta/models/{model}:streamGenerateContent` | Google GenAI (streaming) | Gemini CLI |
242
+ | `/v1/embeddings` | Embeddings | OpenAI SDK |
243
+
244
+ #### Utility Endpoints
245
+
246
+ | Endpoint | Description |
247
+ | --- | --- |
248
+ | `/v1/models` | List available models (OpenAI-compatible format) |
249
+ | `/refresh` | Reload model list from upstream (POST) |
250
+ | `/health` | Health check |
251
+ | `/version` | Version info with update status |
252
+
253
+ #### Timeout Override
254
+
255
+ You can override the default timeout with a `timeout` parameter in your request body. See [Timeout Override Examples](https://argo-proxy.readthedocs.io/en/latest/usage/basics/timeout_examples/) for details.
256
+
257
+ ### Models
258
+
259
+ Models are **fetched dynamically from upstream** at startup. Use `argo-proxy models` or `GET /v1/models` to list all available models and aliases. Refresh without restart via `POST /refresh`.
260
+
261
+ #### Model Naming
262
+
263
+ Model names are flexible and case-insensitive:
264
+
265
+ - **OpenAI**: `argo:gpt-4o`, `gpt-4o`, `argo:gpt-4.1-mini`, `argo:o3-mini`
266
+ - **Claude**: `argo:claude-4-opus` or `argo:claude-opus-4`, `argo:claude-4.6-sonnet`
267
+ - **Gemini**: `argo:gemini-2.5-pro`, `argo:gemini-2.5-flash`
268
+ - **Embedding**: `argo:text-embedding-ada-002`, `argo:text-embedding-3-small`
269
+
270
+ The `argo:` prefix is optional -- bare model names like `gpt-4o` or `claude-4-sonnet` work too.
271
+
272
+ ### Tool Calls
273
+
274
+ Native function calling is supported for **all three providers**:
275
+
276
+ - **OpenAI models**: Full native function calling
277
+ - **Anthropic models**: Full native function calling
278
+ - **Gemini models**: Full native function calling
279
+
280
+ Available on `/v1/chat/completions` in both streaming and non-streaming modes. Cross-format tool call translation is handled automatically via [llm-rosetta](https://github.com/Oaklight/llm-rosetta).
281
+
282
+ For usage details, refer to the [OpenAI function calling guide](https://platform.openai.com/docs/guides/function-calling) and the [tool calls documentation](https://argo-proxy.readthedocs.io/en/latest/usage/advanced/tools/getting-started/).
283
+
284
+ A lightweight tool management library is also available: [ToolRegistry](https://github.com/Oaklight/ToolRegistry).
285
+
286
+ ### AI Coding Tools Integration
287
+
288
+ Argo-proxy works out of the box with popular AI coding tools:
289
+
290
+ | Tool | API Format | Base URL Env Var | Value |
291
+ | --- | --- | --- | --- |
292
+ | [Claude Code](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#claude-code) | Anthropic | `ANTHROPIC_BASE_URL` | `http://localhost:<port>` |
293
+ | [Codex CLI](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#codex-cli) | OpenAI Responses | `OPENAI_BASE_URL` | `http://localhost:<port>/v1` |
294
+ | [Aider](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#aider) | OpenAI or Anthropic | `OPENAI_API_BASE` / `ANTHROPIC_BASE_URL` | `http://localhost:<port>/v1` |
295
+ | [Gemini CLI](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#gemini-cli) | Google GenAI | `GOOGLE_GEMINI_BASE_URL` | `http://localhost:<port>` |
296
+ | [OpenCode](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#opencode) | OpenAI | `OPENAI_BASE_URL` | `http://localhost:<port>/v1` |
297
+ | [Kilo Code](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#kilo-code) | Anthropic | (VS Code settings) | `http://localhost:<port>` |
298
+
299
+ All tools use your ANL username as the API key. For detailed setup instructions, see the [CLI Tools Integration Guide](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/).
300
+
301
+ ### Examples
302
+
303
+ #### OpenAI Format
304
+
305
+ **SDK-based** (`openai.OpenAI`):
306
+ - [Chat Completions](examples/openai/sdk_based/chat_completions.py) | [Streaming](examples/openai/sdk_based/chat_completions_stream.py)
307
+ - [Responses](examples/openai/sdk_based/responses.py) | [Streaming](examples/openai/sdk_based/responses_stream.py)
308
+ - [Function Calling (Chat)](examples/openai/sdk_based/function_calling_chat.py) | [Function Calling (Responses)](examples/openai/sdk_based/function_calling_response.py)
309
+ - [Image Chat](examples/openai/sdk_based/image_chat_direct_urls.py) | [Image Base64](examples/openai/sdk_based/image_chat_base64.py)
310
+ - [Embedding](examples/openai/sdk_based/embedding.py)
311
+ - [Legacy Completions](examples/openai/sdk_based/legacy_completions.py) | [Streaming](examples/openai/sdk_based/legacy_completions_stream.py)
312
+
313
+ **REST-based** (`httpx` / `requests`):
314
+ - [Chat Completions](examples/openai/rest_based/chat_completions.py) | [Streaming](examples/openai/rest_based/chat_completions_stream.py)
315
+ - [Responses](examples/openai/rest_based/responses.py) | [Streaming](examples/openai/rest_based/responses_stream.py)
316
+ - [Function Calling](examples/openai/rest_based/function_calling_chat.py) | [Embedding](examples/openai/rest_based/embedding.py)
317
+
318
+ #### Anthropic Format
319
+
320
+ **SDK-based** (`anthropic.Anthropic`):
321
+ - [Native Messages](examples/anthropic/sdk_based/native_anthropic_test.py)
322
+ - [Function Calling](examples/anthropic/sdk_based/function_calling.py) | [Image Chat](examples/anthropic/sdk_based/image_chat.py)
323
+
324
+ **REST-based**:
325
+ - [Native Messages](examples/anthropic/rest_based/native_anthropic_messages.py) | [Streaming](examples/anthropic/rest_based/native_anthropic_messages_stream.py)
326
+ - [Function Calling](examples/anthropic/rest_based/function_calling.py) | [Image Chat](examples/anthropic/rest_based/image_chat.py)
327
+
328
+ #### Direct ARGO Access
329
+
330
+ - [Chat](examples/argo/argo_chat.py) | [Stream](examples/argo/argo_chat_stream.py) | [Embed](examples/argo/argo_embed.py)
331
+
332
+ ## Bug Reports and Contributions
333
+
334
+ This project is developed in my spare time. Bugs and issues may exist. If you encounter any or have suggestions for improvements, please [open an issue](https://github.com/Oaklight/argo-openai-proxy/issues/new) or [submit a pull request](https://github.com/Oaklight/argo-openai-proxy/compare). Your contributions are highly appreciated!
@@ -0,0 +1,292 @@
1
+ # argo-proxy
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/argo-proxy?color=green)](https://pypi.org/project/argo-proxy/)
4
+ [![PyPI pre-release](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/Oaklight/c6a14fa27347321adfed1a01964b17c1/raw/pypi-badge.json)](https://pypi.org/project/argo-proxy/#history)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ A universal API gateway for LLM services via ARGO. Translates between OpenAI, Anthropic, and Google GenAI API formats, routing requests to optimal upstream ARGO endpoints. Works with AI coding tools like Claude Code, Codex CLI, Aider, Gemini CLI, and more.
8
+
9
+ For detailed documentation, visit the [argo-proxy ReadTheDocs page](https://argo-proxy.readthedocs.io/en/latest/).
10
+
11
+ ## TL;DR
12
+
13
+ ```bash
14
+ pip install argo-proxy # install
15
+ argo-proxy serve # start the proxy
16
+ ```
17
+
18
+ A single proxy instance serves **all 4 major LLM API formats**:
19
+
20
+ | API Format | Endpoint | Example Client |
21
+ | --- | --- | --- |
22
+ | OpenAI Chat Completions | `/v1/chat/completions` | OpenAI SDK, Aider, OpenCode |
23
+ | OpenAI Responses | `/v1/responses` | Codex CLI |
24
+ | Anthropic Messages | `/v1/messages` | Claude Code, Kilo Code |
25
+ | Google GenAI | `/v1beta/models/{model}:generateContent` | Gemini CLI |
26
+
27
+ ## NOTICE OF USAGE
28
+
29
+ The machine or server making API calls to Argo must be connected to the Argonne internal network or through a VPN on an Argonne-managed computer if you are working off-site. Your instance of the argo proxy should always be on-premise at an Argonne machine. The software is provided "as is," without any warranties. By using this software, you accept that the authors, contributors, and affiliated organizations will not be liable for any damages or issues arising from its use. You are solely responsible for ensuring the software meets your requirements.
30
+
31
+ - [Notice of Usage](#notice-of-usage)
32
+ - [Deployment](#deployment)
33
+ - [Prerequisites](#prerequisites)
34
+ - [Configuration](#configuration)
35
+ - [Running the Proxy](#running-the-proxy)
36
+ - [First-Time Setup](#first-time-setup)
37
+ - [Configuration Options Reference](#configuration-options-reference)
38
+ - [CLI Reference](#cli-reference)
39
+ - [Usage](#usage)
40
+ - [Endpoints](#endpoints)
41
+ - [Models](#models)
42
+ - [Tool Calls](#tool-calls)
43
+ - [AI Coding Tools Integration](#ai-coding-tools-integration)
44
+ - [Examples](#examples)
45
+ - [Bug Reports and Contributions](#bug-reports-and-contributions)
46
+
47
+ ## Deployment
48
+
49
+ ### Prerequisites
50
+
51
+ - **Python 3.10+** is required. </br>
52
+ Recommended: use conda, mamba, or pipx to manage an exclusive environment. </br>
53
+ **Conda/Mamba** Download and install from: <https://conda-forge.org/download/> </br>
54
+ **pipx** Download and install from: <https://pipx.pypa.io/stable/installation/>
55
+
56
+ - Install:
57
+
58
+ PyPI current version: ![PyPI - Version](https://img.shields.io/pypi/v/argo-proxy)
59
+
60
+ ```bash
61
+ pip install argo-proxy
62
+ ```
63
+
64
+ To upgrade:
65
+
66
+ ```bash
67
+ argo-proxy update check # check for updates (includes dependency status)
68
+ argo-proxy update install # install latest stable
69
+ argo-proxy update install --pre # install latest pre-release
70
+ ```
71
+
72
+ Or, from source (at the repo root):
73
+ ![GitHub Release](https://img.shields.io/github/v/release/Oaklight/argo-proxy)
74
+
75
+ ```bash
76
+ pip install .
77
+ ```
78
+
79
+ ### Configuration
80
+
81
+ The application uses a YAML config file (v3 format). If you don't have one, [First-Time Setup](#first-time-setup) will create it interactively.
82
+
83
+ ```yaml
84
+ config_version: "3"
85
+ user: "your_username"
86
+ host: 0.0.0.0
87
+ port: 44497
88
+ verbose: true
89
+
90
+ argo_base_url: "https://apps.inside.anl.gov/argoapi"
91
+ ```
92
+
93
+ Config file search order (first found is used):
94
+
95
+ 1. `./config.yaml` (current directory)
96
+ 2. `~/.config/argoproxy/config.yaml`
97
+ 3. `~/.argoproxy/config.yaml`
98
+
99
+ Migrate from v1/v2 config:
100
+
101
+ ```bash
102
+ argo-proxy config migrate /path/to/old/config.yaml
103
+ ```
104
+
105
+ ### Running the Proxy
106
+
107
+ ```bash
108
+ argo-proxy serve # default config search
109
+ argo-proxy serve /path/to/config.yaml # explicit config
110
+ argo-proxy serve --verbose --show # verbose mode, show config at startup
111
+ ```
112
+
113
+ ### First-Time Setup
114
+
115
+ Create a new config interactively:
116
+
117
+ ```bash
118
+ argo-proxy config init
119
+ ```
120
+
121
+ This will:
122
+
123
+ 1. Prompt for your ANL username
124
+ 2. Select a random available port (can be overridden)
125
+ 3. Choose upstream environment (prod/dev/test)
126
+ 4. Validate connectivity to upstream URLs
127
+ 5. Write the config file to `~/.config/argoproxy/config.yaml`
128
+
129
+ ### Configuration Options Reference
130
+
131
+ | Option | Description | Default |
132
+ | --- | --- | --- |
133
+ | `config_version` | Config format version | `"3"` |
134
+ | `user` | Your ANL username | (required) |
135
+ | `host` | Host address to bind to | `0.0.0.0` |
136
+ | `port` | Port number | `44497` |
137
+ | `verbose` | Enable verbose logging | `true` |
138
+ | `argo_base_url` | Base URL for ARGO API | Dev URL |
139
+ | `native_openai_base_url` | Custom OpenAI endpoint (auto-derived if unset) | — |
140
+ | `native_anthropic_base_url` | Custom Anthropic endpoint (auto-derived if unset) | — |
141
+ | `anthropic_stream_mode` | Non-streaming Anthropic handling: `force`/`retry`/`passthrough` | `force` |
142
+ | `force_conversion` | Always run full format conversion | `false` |
143
+ | `use_legacy_argo` | Use legacy ARGO gateway pipeline | `false` |
144
+ | `skip_url_validation` | Skip upstream URL checks on startup | `false` |
145
+ | `connection_test_timeout` | Seconds for URL validation | `5` |
146
+ | `resolve_overrides` | DNS overrides for SSH tunnels (host:port -> IP) | `{}` |
147
+ | `max_log_history` | Keep last N messages in verbose logs | `3` |
148
+ | `enable_payload_control` | Enable image payload size control | `false` |
149
+ | `max_payload_size` | Max image payload size in MB | `20` |
150
+ | `image_timeout` | Image download timeout in seconds | `30` |
151
+ | `concurrent_downloads` | Parallel image downloads | `10` |
152
+
153
+ ### CLI Reference
154
+
155
+ ```
156
+ argo-proxy [-h] [--version] {serve,config,logs,update,models}
157
+ ```
158
+
159
+ | Command | Description |
160
+ | --- | --- |
161
+ | `serve [config]` | Start the proxy server |
162
+ | `config edit` | Open config in default editor |
163
+ | `config validate` | Validate config and check connectivity |
164
+ | `config show` | Display resolved config |
165
+ | `config migrate` | Migrate v1/v2 config to v3 |
166
+ | `config init` | Interactive config setup |
167
+ | `config list` | List all found config files |
168
+ | `config env [prod\|dev\|test]` | Show or switch upstream environment |
169
+ | `logs collect [--type TYPE]` | Collect diagnostic logs |
170
+ | `update check` | Check for updates (argo-proxy + llm-rosetta) |
171
+ | `update install [--pre]` | Install latest version |
172
+ | `models [--json]` | List available models and aliases |
173
+
174
+ Key `serve` flags:
175
+
176
+ ```bash
177
+ argo-proxy serve --verbose # verbose logging
178
+ argo-proxy serve --force-conversion # always convert via llm-rosetta
179
+ argo-proxy serve --username-passthrough # use API key as username
180
+ argo-proxy serve --anthropic-stream-mode retry # try non-streaming first
181
+ argo-proxy serve --legacy-argo # use legacy ARGO gateway pipeline
182
+ argo-proxy serve --dump-requests # dump request/response for debugging
183
+ ```
184
+
185
+ ## Usage
186
+
187
+ ### Endpoints
188
+
189
+ #### API Format Endpoints
190
+
191
+ All four formats are served simultaneously from a single proxy instance:
192
+
193
+ | Endpoint | Format | Typical Client |
194
+ | --- | --- | --- |
195
+ | `/v1/chat/completions` | OpenAI Chat Completions | OpenAI SDK, Aider, OpenCode |
196
+ | `/v1/responses` | OpenAI Responses | Codex CLI |
197
+ | `/v1/messages` | Anthropic Messages | Claude Code, Anthropic SDK |
198
+ | `/v1beta/models/{model}:generateContent` | Google GenAI | Gemini CLI |
199
+ | `/v1beta/models/{model}:streamGenerateContent` | Google GenAI (streaming) | Gemini CLI |
200
+ | `/v1/embeddings` | Embeddings | OpenAI SDK |
201
+
202
+ #### Utility Endpoints
203
+
204
+ | Endpoint | Description |
205
+ | --- | --- |
206
+ | `/v1/models` | List available models (OpenAI-compatible format) |
207
+ | `/refresh` | Reload model list from upstream (POST) |
208
+ | `/health` | Health check |
209
+ | `/version` | Version info with update status |
210
+
211
+ #### Timeout Override
212
+
213
+ You can override the default timeout with a `timeout` parameter in your request body. See [Timeout Override Examples](https://argo-proxy.readthedocs.io/en/latest/usage/basics/timeout_examples/) for details.
214
+
215
+ ### Models
216
+
217
+ Models are **fetched dynamically from upstream** at startup. Use `argo-proxy models` or `GET /v1/models` to list all available models and aliases. Refresh without restart via `POST /refresh`.
218
+
219
+ #### Model Naming
220
+
221
+ Model names are flexible and case-insensitive:
222
+
223
+ - **OpenAI**: `argo:gpt-4o`, `gpt-4o`, `argo:gpt-4.1-mini`, `argo:o3-mini`
224
+ - **Claude**: `argo:claude-4-opus` or `argo:claude-opus-4`, `argo:claude-4.6-sonnet`
225
+ - **Gemini**: `argo:gemini-2.5-pro`, `argo:gemini-2.5-flash`
226
+ - **Embedding**: `argo:text-embedding-ada-002`, `argo:text-embedding-3-small`
227
+
228
+ The `argo:` prefix is optional -- bare model names like `gpt-4o` or `claude-4-sonnet` work too.
229
+
230
+ ### Tool Calls
231
+
232
+ Native function calling is supported for **all three providers**:
233
+
234
+ - **OpenAI models**: Full native function calling
235
+ - **Anthropic models**: Full native function calling
236
+ - **Gemini models**: Full native function calling
237
+
238
+ Available on `/v1/chat/completions` in both streaming and non-streaming modes. Cross-format tool call translation is handled automatically via [llm-rosetta](https://github.com/Oaklight/llm-rosetta).
239
+
240
+ For usage details, refer to the [OpenAI function calling guide](https://platform.openai.com/docs/guides/function-calling) and the [tool calls documentation](https://argo-proxy.readthedocs.io/en/latest/usage/advanced/tools/getting-started/).
241
+
242
+ A lightweight tool management library is also available: [ToolRegistry](https://github.com/Oaklight/ToolRegistry).
243
+
244
+ ### AI Coding Tools Integration
245
+
246
+ Argo-proxy works out of the box with popular AI coding tools:
247
+
248
+ | Tool | API Format | Base URL Env Var | Value |
249
+ | --- | --- | --- | --- |
250
+ | [Claude Code](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#claude-code) | Anthropic | `ANTHROPIC_BASE_URL` | `http://localhost:<port>` |
251
+ | [Codex CLI](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#codex-cli) | OpenAI Responses | `OPENAI_BASE_URL` | `http://localhost:<port>/v1` |
252
+ | [Aider](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#aider) | OpenAI or Anthropic | `OPENAI_API_BASE` / `ANTHROPIC_BASE_URL` | `http://localhost:<port>/v1` |
253
+ | [Gemini CLI](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#gemini-cli) | Google GenAI | `GOOGLE_GEMINI_BASE_URL` | `http://localhost:<port>` |
254
+ | [OpenCode](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#opencode) | OpenAI | `OPENAI_BASE_URL` | `http://localhost:<port>/v1` |
255
+ | [Kilo Code](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/#kilo-code) | Anthropic | (VS Code settings) | `http://localhost:<port>` |
256
+
257
+ All tools use your ANL username as the API key. For detailed setup instructions, see the [CLI Tools Integration Guide](https://argo-proxy.readthedocs.io/en/latest/usage/cli-tools/).
258
+
259
+ ### Examples
260
+
261
+ #### OpenAI Format
262
+
263
+ **SDK-based** (`openai.OpenAI`):
264
+ - [Chat Completions](examples/openai/sdk_based/chat_completions.py) | [Streaming](examples/openai/sdk_based/chat_completions_stream.py)
265
+ - [Responses](examples/openai/sdk_based/responses.py) | [Streaming](examples/openai/sdk_based/responses_stream.py)
266
+ - [Function Calling (Chat)](examples/openai/sdk_based/function_calling_chat.py) | [Function Calling (Responses)](examples/openai/sdk_based/function_calling_response.py)
267
+ - [Image Chat](examples/openai/sdk_based/image_chat_direct_urls.py) | [Image Base64](examples/openai/sdk_based/image_chat_base64.py)
268
+ - [Embedding](examples/openai/sdk_based/embedding.py)
269
+ - [Legacy Completions](examples/openai/sdk_based/legacy_completions.py) | [Streaming](examples/openai/sdk_based/legacy_completions_stream.py)
270
+
271
+ **REST-based** (`httpx` / `requests`):
272
+ - [Chat Completions](examples/openai/rest_based/chat_completions.py) | [Streaming](examples/openai/rest_based/chat_completions_stream.py)
273
+ - [Responses](examples/openai/rest_based/responses.py) | [Streaming](examples/openai/rest_based/responses_stream.py)
274
+ - [Function Calling](examples/openai/rest_based/function_calling_chat.py) | [Embedding](examples/openai/rest_based/embedding.py)
275
+
276
+ #### Anthropic Format
277
+
278
+ **SDK-based** (`anthropic.Anthropic`):
279
+ - [Native Messages](examples/anthropic/sdk_based/native_anthropic_test.py)
280
+ - [Function Calling](examples/anthropic/sdk_based/function_calling.py) | [Image Chat](examples/anthropic/sdk_based/image_chat.py)
281
+
282
+ **REST-based**:
283
+ - [Native Messages](examples/anthropic/rest_based/native_anthropic_messages.py) | [Streaming](examples/anthropic/rest_based/native_anthropic_messages_stream.py)
284
+ - [Function Calling](examples/anthropic/rest_based/function_calling.py) | [Image Chat](examples/anthropic/rest_based/image_chat.py)
285
+
286
+ #### Direct ARGO Access
287
+
288
+ - [Chat](examples/argo/argo_chat.py) | [Stream](examples/argo/argo_chat_stream.py) | [Embed](examples/argo/argo_embed.py)
289
+
290
+ ## Bug Reports and Contributions
291
+
292
+ This project is developed in my spare time. Bugs and issues may exist. If you encounter any or have suggestions for improvements, please [open an issue](https://github.com/Oaklight/argo-openai-proxy/issues/new) or [submit a pull request](https://github.com/Oaklight/argo-openai-proxy/compare). Your contributions are highly appreciated!
@@ -20,7 +20,7 @@ classifiers = [
20
20
 
21
21
  dependencies = [
22
22
  "aiohttp>=3.12.2",
23
- "llm-rosetta>=0.5.3,<0.6.0",
23
+ "llm-rosetta>=0.6.0,<0.7.0",
24
24
  "pydantic>=2.11.7",
25
25
  "tiktoken>=0.9.0",
26
26
  "tqdm>=4.67.1",
@@ -67,7 +67,8 @@ version = { attr = "argoproxy.__version__" }
67
67
 
68
68
  [tool.ruff]
69
69
  target-version = "py310"
70
- exclude = ["dev_scripts", "test"]
70
+ exclude = ["dev_scripts", "test", "**/_vendor"]
71
+ force-exclude = true
71
72
 
72
73
  [tool.ruff.lint]
73
74
  select = ["E", "F", "UP"]
@@ -78,6 +79,7 @@ python-version = "3.10"
78
79
 
79
80
  [tool.ty.src]
80
81
  include = ["src"]
82
+ exclude = ["src/argoproxy/_legacy"]
81
83
 
82
84
  [tool.ty.rules]
83
85
  unresolved-import = "ignore"