You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Resolve TEE endpoint and TLS cert from on-chain registry (#175)
* feat: resolve TEE endpoint and TLS cert from on-chain registry
Instead of blindly trusting the TLS certificate presented by the TEE
server (TOFU), the SDK now queries the on-chain TEERegistry contract
to discover active LLM proxy endpoints and their verified certificates.
Key changes:
- Add TEERegistry.abi and tee_registry.py to query the registry contract
- Replace TOFU cert fetch in llm.py with registry-verified DER cert
- Client.init queries the registry by default; og_llm_server_url still
works as an explicit override (falls back to system CA verification)
- Add DEFAULT_TEE_REGISTRY_ADDRESS and DEFAULT_TEE_REGISTRY_RPC_URL to
defaults.py (OG EVM chain at http://13.59.43.94:8545)
- Surface tee_id, tee_endpoint, tee_payment_address on every
TextGenerationOutput and on the final StreamChunk so callers can
audit which enclave served their request
- Print TEE node info (endpoint, TEE ID, payment address) in all three
CLI print helpers (completion, chat, streaming)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: fall back to non-streaming endpoint when tool calls are requested with stream=True
The TEE streaming endpoint returns an empty delta ("delta": {}) and no
tool call content in SSE events when tools is supplied — the server-side
streaming path simply does not emit tool call data.
Introduce _tee_llm_chat_tools_as_stream which transparently calls the
non-streaming /v1/chat/completions endpoint and wraps the complete
TextGenerationOutput as a single final StreamChunk (with tool_calls
populated in delta). chat() now routes stream=True + tools to this
method, preserving the streaming iterator interface for callers and
the CLI while returning correct results.
Also removes the temporary [SSE RAW] debug print added during diagnosis,
and fixes from_sse_data to accept "message" as a fallback for "delta"
when the proxy sends a non-streaming format in SSE events.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(tests): update client_test fixtures to mock TEERegistry and fix TEE_LLM references
Two issues caused CI failures:
1. The mock_web3 fixture didn't patch TEERegistry, so Client.__init__ tried
to instantiate a real TEERegistry (with a live Web3 connection) even in
unit tests. The mock_abi_files fallback returned {} for TEERegistry.abi
but web3.eth.contract() requires a list, causing ValueError. Fix: patch
src.opengradient.client.client.TEERegistry inside mock_web3 and return a
fake TEEEndpoint with a stub endpoint/tee_id/payment_address.
2. Three LLM tests referenced TEE_LLM.GPT_4O which no longer exists in the
enum. Updated to TEE_LLM.GPT_5.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(cli): guard against empty choices in streaming loop and format tool calls consistently
Two bugs caused tool call results to be invisible in the CLI:
1. print_streaming_chat_result accessed chunk.choices[0] unconditionally.
Usage-only SSE chunks carry an empty choices list, which caused an
IndexError that was silently swallowed by the outer except block,
truncating output before tool calls or finish_reason were printed.
Fixed by guarding all choices[0] accesses with `if chunk.choices:`.
2. print_llm_chat_result (non-streaming) printed tool_calls as a raw
Python dict repr. Updated to use the same formatted output as the
streaming path: "Tool Calls: / Function: ... / Arguments: ...".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update pyproject.toml
* fix(makefile): add system prompt to chat-tool targets to reliably trigger tool calls
With tool_choice="auto", models like GPT-5 require a system prompt
instructing them to use tools, otherwise they respond with finish_reason
"stop" and empty content. Updated chat-tool and chat-stream-tool to
include a system message matching the pattern that works in the SDK.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(makefile): use proven Dallas/Texas payload to reliably trigger GPT-5 tool calls
The previous Tokyo/get_weather(location) payload still failed with
finish_reason: stop on GPT-5. Switch chat-tool and chat-stream-tool
to use get_current_weather(city, state, unit) with Dallas, Texas
which consistently triggers tool_calls finish_reason.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* in memory cert + registry test
* use new abi
* fix types
* rm unused
* rm tee rpc and update contract
* rm _og_llm_streaming_server_url
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: balogh.adam@icloud.com <adambalogh@mac.mynetworksettings.com>
--messages '[{"role":"user","content":"What is the weather in Tokyo?"}]'\
91
-
--tools '[{"type":"function","function":{"name":"get_weather","description":"Get weather for a location","parameters":{"type":"object","properties":{"location":{"type":"string"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}]'\
92
-
--max-tokens 100
93
+
--messages '[{"role":"system","content":"You are a helpful assistant. Use tools when needed."},{"role":"user","content":"What'\''s the weather like in Dallas, Texas? Give me the temperature in fahrenheit."}]'\
94
+
--tools '[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"city":{"type":"string"},"state":{"type":"string"},"unit":{"type":"string","enum":["fahrenheit","celsius"]}},"required":["city","state","unit"]}}}]'\
95
+
--max-tokens 200
93
96
94
97
chat-stream-tool:
95
98
python -m opengradient.cli chat \
96
99
--model $(MODEL)\
97
-
--messages '[{"role":"user","content":"What is the weather in Tokyo?"}]'\
98
-
--tools '[{"type":"function","function":{"name":"get_weather","description":"Get weather for a location","parameters":{"type":"object","properties":{"location":{"type":"string"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}]'\
99
-
--max-tokens 100\
100
+
--messages '[{"role":"system","content":"You are a helpful assistant. Use tools when needed."},{"role":"user","content":"What'\''s the weather like in Dallas, Texas? Give me the temperature in fahrenheit."}]'\
101
+
--tools '[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"city":{"type":"string"},"state":{"type":"string"},"unit":{"type":"string","enum":["fahrenheit","celsius"]}},"required":["city","state","unit"]}}}]'\
0 commit comments