Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
module load time, which is only installed in the dedicated CI job. Ignore that
directory during normal collection so the suite runs without the native
toolchain. The Hypothesis property tests under ``tests/fuzz/`` are unaffected.

``scripts/`` is also ignored: helper modules named ``*_test.py`` are not tests,
and importing them during collection must not write files into ``tests/``.
"""

collect_ignore = ["fuzz"]
collect_ignore = ["fuzz", "scripts"]
8 changes: 5 additions & 3 deletions contextual_orchestrator/cost_ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ def _seed_dimension_catalog(self) -> None:
ph = self._placeholder()
cur = self._conn.cursor()
for order, (name, label, _column) in enumerate(ATTRIBUTION_DIMENSION_CATALOG):
cur.execute(
cur.execute( # nosemgrep: python.sqlalchemy.security.sqlalchemy-execute-raw-query.sqlalchemy-execute-raw-query -- ph is a DB-API placeholder, value is parameterized below.
f"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}", # nosec B608 - ph is a DB-API placeholder.
(name,),
)
Expand All @@ -602,7 +602,7 @@ def append(self, record: UsageRecord) -> None:
placeholders = ", ".join(ph for _ in _USAGE_COLUMNS)
columns = ", ".join(_USAGE_COLUMNS)
cur = self._conn.cursor()
cur.execute(
cur.execute( # nosemgrep: python.sqlalchemy.security.sqlalchemy-execute-raw-query.sqlalchemy-execute-raw-query -- columns are fixed _USAGE_COLUMNS, values are parameterized below.
f"INSERT INTO llm_usage_records ({columns}) VALUES ({placeholders})", # nosec B608 - columns are fixed _USAGE_COLUMNS.
tuple(row.get(column) for column in _USAGE_COLUMNS),
)
Expand All @@ -622,7 +622,9 @@ def query(self, start: Optional[int] = None, end: Optional[int] = None) -> List[
where = f" WHERE {' AND '.join(clauses)}" if clauses else ""
columns = ", ".join(_USAGE_COLUMNS)
cur = self._conn.cursor()
cur.execute(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed.
cur.execute( # nosemgrep: python.sqlalchemy.security.sqlalchemy-execute-raw-query.sqlalchemy-execute-raw-query -- columns/clauses are fixed, values are parameterized.
f"SELECT {columns} FROM llm_usage_records{where}", tuple(params) # nosec B608 - columns and clauses are fixed.
)
return [dict(zip(_USAGE_COLUMNS, values)) for values in cur.fetchall()]


Expand Down
8 changes: 7 additions & 1 deletion contextual_orchestrator/cost_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,17 @@ def complete(
hints: Optional[Dict[str, Any]] = None,
model_name: str = "contextual-orchestrator",
workflow_run_id: Optional[str] = None,
reasoning_effort: Optional[str] = None,
) -> Dict[str, Any]:
"""Route a request (sync or batch) and record its usage + cost.

Sync requests run the orchestrator immediately and return the completion
augmented with ``channel``, ``routing_reason``, ``usage``, and the
``usage_record_id``. Batch requests are dispatched to the batch backend
and return a job envelope; their cost is recorded on retrieval.
``reasoning_effort`` only applies to the sync path today — ``BatchRequest``
has no reasoning_effort field, so a request routed to the batch channel
drops the hint rather than partially threading it through pg-llm-batch.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A caller who set reasoning_effort=high plus a batch hint gets HTTP 202 and default provider effort.

Documenting the drop in this docstring is not wire honesty. Put reasoning_effort: {requested, status: dropped, reason} on the 202 envelope so the buyer can see the knob was discarded. Do not silently succeed.

"""
routing_hints = hints if isinstance(hints, RoutingHints) else RoutingHints.from_mapping(hints)
prompt_tokens_estimate = self.token_counter.count_messages(messages, model_name)
Expand All @@ -145,7 +149,9 @@ def complete(
"request_count": job.request_count,
}

result = self.orchestrator.run(messages, mode=mode, workflow_run_id=workflow_run_id)
result = self.orchestrator.run(
messages, mode=mode, workflow_run_id=workflow_run_id, reasoning_effort=reasoning_effort
)
record = self._record_completion(
messages=messages,
answer=result.get("answer", ""),
Expand Down
Loading
Loading