Skip to content

Commit 6679478

Browse files
authored
Merge branch 'main' into feat/extensions-utils
2 parents b3e7296 + 56cd2ab commit 6679478

File tree

2 files changed

+84
-3
lines changed

2 files changed

+84
-3
lines changed

.github/workflows/server.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,9 @@ jobs:
210210
ARCH: ${{ matrix.arch }}
211211
TARGET: binary
212212
PLATFORM: ${{ matrix.platform }}
213-
# Use PR head SHA for pull requests to match the image tag expected by run-examples.yml
214-
GITHUB_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
213+
# Use SDK_SHA for PR head SHA - GITHUB_SHA is a built-in that gets overwritten by checkout
214+
# build.py checks SDK_SHA before GITHUB_SHA (see _git_info priority order)
215+
SDK_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
215216
GITHUB_REF: ${{ github.ref }}
216217
CI: 'true'
217218

@@ -254,7 +255,8 @@ jobs:
254255
echo "tags=$TAGS" >> $GITHUB_OUTPUT
255256
256257
# Extract short SHA for consolidation
257-
SHORT_SHA=$(echo ${{ github.sha }} | cut -c1-7)
258+
# Use SDK_SHA env var (set above to PR head SHA for PRs)
259+
SHORT_SHA=$(echo $SDK_SHA | cut -c1-7)
258260
echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT
259261
260262
# Extract versioned tags CSV for consolidation

tests/sdk/llm/test_llm.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from openai.types.responses.response_output_text import ResponseOutputText
1010
from pydantic import SecretStr
1111

12+
from openhands.sdk import ConversationStats, RegistryEvent
1213
from openhands.sdk.llm import LLM, LLMResponse, Message, TextContent
1314
from openhands.sdk.llm.exceptions import LLMNoResponseError
1415
from openhands.sdk.llm.options.responses_options import select_responses_options
@@ -1095,6 +1096,84 @@ def test_issue_2459_restore_metrics_syncs_telemetry():
10951096
assert llm.telemetry.metrics is llm.metrics
10961097

10971098

1099+
@pytest.fixture
1100+
def llm():
1101+
"""Create a minimal SDK LLM for testing."""
1102+
return LLM(
1103+
model="openai/gpt-4o",
1104+
api_key=SecretStr("test-key"),
1105+
usage_id="test-service",
1106+
)
1107+
1108+
1109+
def test_cost_recorded_in_restored_metrics(llm):
1110+
"""Costs added via telemetry after restore must land in the restored Metrics."""
1111+
restored = Metrics(model_name="openai/gpt-4o")
1112+
restored.add_cost(5.00)
1113+
llm.restore_metrics(restored)
1114+
1115+
llm.telemetry.metrics.add_cost(0.50)
1116+
1117+
assert llm.metrics.accumulated_cost == 5.50
1118+
assert len(llm.metrics.costs) == 2
1119+
1120+
1121+
def test_stale_metrics_not_updated(llm):
1122+
"""The original (pre-restore) Metrics must not receive new costs."""
1123+
original_metrics = llm.metrics
1124+
1125+
restored = Metrics(model_name="openai/gpt-4o")
1126+
restored.add_cost(2.00)
1127+
llm.restore_metrics(restored)
1128+
1129+
llm.telemetry.metrics.add_cost(0.75)
1130+
1131+
assert original_metrics.accumulated_cost == 0.0
1132+
assert llm.metrics.accumulated_cost == 2.75
1133+
1134+
1135+
def test_restore_metrics_telemetry_none():
1136+
"""restore_metrics() must not crash when telemetry has not been initialized."""
1137+
llm = LLM(
1138+
model="openai/gpt-4o",
1139+
api_key=SecretStr("test-key"),
1140+
usage_id="test-service",
1141+
)
1142+
llm._telemetry = None
1143+
1144+
restored = Metrics(model_name="openai/gpt-4o")
1145+
restored.add_cost(1.00)
1146+
llm.restore_metrics(restored)
1147+
1148+
assert llm.metrics is restored
1149+
assert llm.metrics.accumulated_cost == 1.00
1150+
1151+
1152+
def test_conversation_stats_restore_then_track():
1153+
"""End-to-end: ConversationStats restores metrics, then new costs are tracked."""
1154+
saved_metrics = Metrics(model_name="openai/gpt-4o")
1155+
saved_metrics.add_cost(10.00)
1156+
1157+
stats = ConversationStats(usage_to_metrics={"agent": saved_metrics})
1158+
1159+
with patch("openhands.sdk.llm.llm.litellm_completion"):
1160+
llm = LLM(
1161+
model="openai/gpt-4o",
1162+
api_key=SecretStr("test-key"),
1163+
usage_id="agent",
1164+
)
1165+
event = RegistryEvent(llm=llm)
1166+
stats.register_llm(event)
1167+
1168+
assert llm.metrics.accumulated_cost == 10.00
1169+
1170+
# Simulate a new LLM response adding cost via telemetry
1171+
llm.telemetry.metrics.add_cost(0.25)
1172+
1173+
assert llm.metrics.accumulated_cost == 10.25
1174+
assert stats.get_combined_metrics().accumulated_cost == 10.25
1175+
1176+
10981177
# max_output_tokens Capping Tests
10991178

11001179

0 commit comments

Comments
 (0)