-
Notifications
You must be signed in to change notification settings - Fork 1
feat(api): Responses input/metadata/stream fail-closed honesty #387
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -222,14 +222,21 @@ class UsageRecord: | |
|
|
||
| def as_dict(self) -> Dict[str, Any]: | ||
| """Flatten the record (attribution inlined) for JSON + SQL storage.""" | ||
| # Prefer an explicit attribution model_name (client tag) for rollups; | ||
| # otherwise the served model id on the record. | ||
| rollup_model = ( | ||
| self.attribution.model_name | ||
| if self.attribution.model_name != UNATTRIBUTED | ||
| else self.model_name | ||
| ) | ||
| row = { | ||
| "usage_record_id": self.usage_record_id, | ||
| "created_at": self.created_at, | ||
| "workflow_run_id": self.workflow_run_id, | ||
| "request_channel": self.request_channel, | ||
| "route_mode": self.route_mode, | ||
| "provider_name": self.provider_name, | ||
| "model_name": self.model_name, | ||
| "model_name": rollup_model, | ||
| "prompt_tokens": self.prompt_tokens, | ||
| "completion_tokens": self.completion_tokens, | ||
| "total_tokens": self.total_tokens, | ||
|
|
@@ -583,12 +590,12 @@ 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 -- sqlalchemy-execute-raw-query FP: only the DB-API placeholder char is interpolated; the value is bound. | ||
| f"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}", # nosec B608 - ph is a DB-API placeholder. | ||
| (name,), | ||
| ) | ||
| if cur.fetchone() is None: | ||
| cur.execute( | ||
| cur.execute( # nosemgrep -- sqlalchemy-execute-raw-query FP: only DB-API placeholder chars are interpolated; values are bound. | ||
| "INSERT INTO cost_attribution_dimensions " | ||
| f"(dimension_name, dimension_label, dimension_order) VALUES ({ph}, {ph}, {ph})", # nosec B608 - ph is a DB-API placeholder. | ||
|
Comment on lines
+593
to
600
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
ruff check contextual_orchestrator/cost_ledger.py --select S608Repository: ContextualWisdomLab/contextual-orchestrator Length of output: 3840 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- target lines ---'
sed -n '580,640p' contextual_orchestrator/cost_ledger.py
printf '%s\n' '--- Ruff configuration ---'
rg -n -C 3 '^(target-version|select|extend-select|ignore|lint\.)|S608|noqa' pyproject.toml ruff.toml .ruff.toml 2>/dev/null || true
printf '%s\n' '--- Ruff version ---'
ruff --versionRepository: ContextualWisdomLab/contextual-orchestrator Length of output: 3771 🏁 Script executed: #!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import subprocess
path = Path("contextual_orchestrator/cost_ledger.py")
source = path.read_text()
variants = {
"current": source,
"requested_594_632": source.replace(
"f\"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}\", # nosec B608 - ph is a DB-API placeholder.",
"f\"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}\", # nosec B608 - ph is a DB-API placeholder. # noqa: S608",
).replace(
'cur.execute(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed. # nosemgrep -- sqlalchemy-execute-raw-query FP: fixed columns and clause templates; all values are bound.',
'cur.execute(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed. # noqa: S608 # nosemgrep -- sqlalchemy-execute-raw-query FP: fixed columns and clause templates; all values are bound.',
),
"all_expression_lines": source.replace(
"f\"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}\", # nosec B608 - ph is a DB-API placeholder.",
"f\"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}\", # nosec B608 - ph is a DB-API placeholder. # noqa: S608",
).replace(
'f"(dimension_name, dimension_label, dimension_order) VALUES ({ph}, {ph}, {ph})", # nosec B608 - ph is a DB-API placeholder.',
'f"(dimension_name, dimension_label, dimension_order) VALUES ({ph}, {ph}, {ph})", # nosec B608 - ph is a DB-API placeholder. # noqa: S608',
).replace(
'f"INSERT INTO llm_usage_records ({columns}) VALUES ({placeholders})", # nosec B608 - columns are fixed _USAGE_COLUMNS.',
'f"INSERT INTO llm_usage_records ({columns}) VALUES ({placeholders})", # nosec B608 - columns are fixed _USAGE_COLUMNS. # noqa: S608',
).replace(
'cur.execute(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed. # nosemgrep -- sqlalchemy-execute-raw-query FP: fixed columns and clause templates; all values are bound.',
'cur.execute(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed. # noqa: S608 # nosemgrep -- sqlalchemy-execute-raw-query FP: fixed columns and clause templates; all values are bound.',
),
}
for name, text in variants.items():
result = subprocess.run(
["ruff", "check", "--select", "S608", "--stdin-filename", str(path)],
input=text,
text=True,
capture_output=True,
)
diagnostics = [
line.strip()
for line in result.stdout.splitlines()
if "cost_ledger.py:" in line and "S608" in line
]
print(f"{name}: exit={result.returncode}; diagnostics={diagnostics}")
PYRepository: ContextualWisdomLab/contextual-orchestrator Length of output: 300 🏁 Script executed: #!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import subprocess
path = Path("contextual_orchestrator/cost_ledger.py")
source = path.read_text()
replacements = {
"select": (
'f"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}", # nosec B608 - ph is a DB-API placeholder.',
'f"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}", # nosec B608 - ph is a DB-API placeholder. # noqa: S608',
),
"insert": (
'f"(dimension_name, dimension_label, dimension_order) VALUES ({ph}, {ph}, {ph})", # nosec B608 - ph is a DB-API placeholder.',
'f"(dimension_name, dimension_label, dimension_order) VALUES ({ph}, {ph}, {ph})", # nosec B608 - ph is a DB-API placeholder. # noqa: S608',
),
"append": (
'f"INSERT INTO llm_usage_records ({columns}) VALUES ({placeholders})", # nosec B608 - columns are fixed _USAGE_COLUMNS.',
'f"INSERT INTO llm_usage_records ({columns}) VALUES ({placeholders})", # nosec B608 - columns are fixed _USAGE_COLUMNS. # noqa: S608',
),
"query": (
'cur.execute(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed. # nosemgrep -- sqlalchemy-execute-raw-query FP: fixed columns and clause templates; all values are bound.',
'cur.execute(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed. # noqa: S608 # nosemgrep -- sqlalchemy-execute-raw-query FP: fixed columns and clause templates; all values are bound.',
),
}
variants = {"current": source}
for label, (old, new) in replacements.items():
variants[label] = source.replace(old, new)
variants["select_and_query"] = source.replace(*replacements["select"]).replace(*replacements["query"])
variants["all_expression_lines"] = source
for old, new in replacements.values():
variants["all_expression_lines"] = variants["all_expression_lines"].replace(old, new)
for name, text in variants.items():
result = subprocess.run(
["ruff", "check", "--select", "S608", "--output-format", "concise",
"--stdin-filename", str(path)],
input=text,
text=True,
capture_output=True,
)
output = (result.stdout + result.stderr).strip()
print(f"\n{name}: exit={result.returncode}")
print(output or "(no output)")
PYRepository: ContextualWisdomLab/contextual-orchestrator Length of output: 3828 🏁 Script executed: #!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import subprocess
path = Path("contextual_orchestrator/cost_ledger.py")
text = path.read_text()
changes = {
'f"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}", # nosec B608 - ph is a DB-API placeholder.':
'f"SELECT 1 FROM cost_attribution_dimensions WHERE dimension_name = {ph}", # nosec B608 - ph is a DB-API placeholder. # noqa: S608',
'"INSERT INTO cost_attribution_dimensions "':
'"INSERT INTO cost_attribution_dimensions " # noqa: S608',
'f"(dimension_name, dimension_label, dimension_order) VALUES ({ph}, {ph}, {ph})", # nosec B608 - ph is a DB-API placeholder.':
'f"(dimension_name, dimension_label, dimension_order) VALUES ({ph}, {ph}, {ph})", # nosec B608 - ph is a DB-API placeholder. # noqa: S608',
'f"INSERT INTO llm_usage_records ({columns}) VALUES ({placeholders})", # nosec B608 - columns are fixed _USAGE_COLUMNS.':
'f"INSERT INTO llm_usage_records ({columns}) VALUES ({placeholders})", # nosec B608 - columns are fixed _USAGE_COLUMNS. # noqa: S608',
'cur.execute(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed. # nosemgrep -- sqlalchemy-execute-raw-query FP: fixed columns and clause templates; all values are bound.':
'cur.execute(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed. # noqa: S608 # nosemgrep -- sqlalchemy-execute-raw-query FP: fixed columns and clause templates; all values are bound.',
}
for old, new in changes.items():
if old not in text:
raise SystemExit(f"missing expected source text: {old}")
text = text.replace(old, new)
result = subprocess.run(
["ruff", "check", "--select", "S608", "--output-format", "concise",
"--stdin-filename", str(path)],
input=text, text=True, capture_output=True,
)
print(f"exit={result.returncode}")
print((result.stdout + result.stderr).strip() or "(no output)")
PYRepository: ContextualWisdomLab/contextual-orchestrator Length of output: 218 모든 Ruff S608 진단을 억제하십시오.
🧰 Tools🪛 Ruff (0.16.1)[error] 594-594: Possible SQL injection vector through string-based query construction (S608) [error] 599-600: Possible SQL injection vector through string-based query construction (S608) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
| (name, label, order), | ||
|
|
@@ -602,7 +609,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 -- sqlalchemy-execute-raw-query FP: columns are the fixed _USAGE_COLUMNS constant; values are bound. | ||
| 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), | ||
| ) | ||
|
|
@@ -622,7 +629,7 @@ 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(f"SELECT {columns} FROM llm_usage_records{where}", tuple(params)) # nosec B608 - columns and clauses are fixed. # nosemgrep -- sqlalchemy-execute-raw-query FP: fixed columns and clause templates; all values are bound. | ||
| return [dict(zip(_USAGE_COLUMNS, values)) for values in cur.fetchall()] | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -215,6 +215,10 @@ def __init__( | |
| ) -> None: | ||
| self.timeout = timeout | ||
| self.max_output_tokens = max_output_tokens | ||
| self.default_temperature = 0.2 | ||
| self.default_top_p: float | None = None | ||
| self.default_presence_penalty: float | None = None | ||
| self.default_frequency_penalty: float | None = None | ||
| self.max_retries = max_retries | ||
| self.retry_backoff = retry_backoff | ||
| self.retry_backoff_cap = retry_backoff_cap | ||
|
|
@@ -230,7 +234,7 @@ def __init__( | |
| @staticmethod | ||
| def _build_ssl_context(ca_bundle: str | None, verify_tls: bool) -> ssl.SSLContext: | ||
| if not verify_tls: | ||
| return ssl._create_unverified_context() # nosec B323 - explicit dev-only provider TLS opt-out. | ||
| return ssl._create_unverified_context() # nosec B323 - explicit dev-only provider TLS opt-out. # nosemgrep -- unverified-ssl-context: intentional, default-secure (verify_tls defaults True) dev-only opt-out for self-signed endpoints. | ||
| if ca_bundle: | ||
| if not os.path.isfile(ca_bundle): | ||
| raise ValueError(f"provider CA bundle does not exist: {ca_bundle}") | ||
|
|
@@ -246,9 +250,29 @@ def take_usage(self) -> dict[str, Any] | None: | |
| self._local.usage = None | ||
| return usage | ||
|
|
||
| def chat(self, agent: ModelAgent, messages: list[ChatMessage], temperature: float = 0.2) -> str: | ||
| """Send messages to a mock or OpenAI-compatible chat endpoint with retries.""" | ||
| def chat( | ||
| self, | ||
| agent: ModelAgent, | ||
| messages: list[ChatMessage], | ||
| temperature: float | None = None, | ||
| top_p: float | None = None, | ||
| ) -> str: | ||
| """Send messages to a mock or OpenAI-compatible chat endpoint with retries. | ||
|
|
||
| When ``temperature``/``top_p`` are omitted, ``default_temperature`` and | ||
| ``default_top_p`` are used so request-scoped Completions sampling can be | ||
| applied without threading kwargs through every orchestrator hop. | ||
| """ | ||
| self._local.usage = None | ||
| # Expose the effective sampling knobs for request-path tests / diagnostics. | ||
| effective_temperature = self.default_temperature if temperature is None else temperature | ||
| effective_top_p = self.default_top_p if top_p is None else top_p | ||
| effective_presence = self.default_presence_penalty | ||
| effective_frequency = self.default_frequency_penalty | ||
| self._local.last_temperature = effective_temperature | ||
| self._local.last_top_p = effective_top_p | ||
| self._local.last_presence_penalty = effective_presence | ||
| self._local.last_frequency_penalty = effective_frequency | ||
|
Comment on lines
+253
to
+275
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
ast-grep outline contextual_orchestrator/orchestrator.py --items all --match 'ModelClient|chat'
rg -n -C 5 --type py \
'(?:\.chat\s*\(|default_(?:presence|frequency)_penalty\s*=|presence_penalty|frequency_penalty)' \
contextual_orchestratorRepository: ContextualWisdomLab/contextual-orchestrator Length of output: 23163 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- ModelClient definition and chat implementation ---'
sed -n '190,315p' contextual_orchestrator/orchestrator.py
printf '%s\n' '--- Server request execution and sampling mutation ---'
sed -n '1855,1920p' contextual_orchestrator/server.py
sed -n '2125,2190p' contextual_orchestrator/server.py
printf '%s\n' '--- Server concurrency and synchronization references ---'
rg -n -C 3 --type py \
'Thread|thread|Lock|RLock|Semaphore|executor|asyncio|run_in_executor|ThreadPool|_run\(|def _run|default_(?:temperature|top_p|presence|frequency)_penalty' \
contextual_orchestrator
printf '%s\n' '--- Sampling-related tests and call sites ---'
rg -n -C 4 --type py \
'presence_penalty|frequency_penalty|last_presence_penalty|last_frequency_penalty|default_presence_penalty|default_frequency_penalty|ModelClient\.chat|client\.chat' \
tests contextual_orchestrator 2>/dev/null || trueRepository: ContextualWisdomLab/contextual-orchestrator Length of output: 50399 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- Threaded server construction and request-run helper ---'
sed -n '1425,1465p' contextual_orchestrator/server.py
rg -n -A18 -B8 --type py 'def _run\(' contextual_orchestrator/server.py
rg -n -A12 -B8 --type py '_run_semaphore|ThreadingHTTPServer\(' contextual_orchestrator/server.py
printf '%s\n' '--- Focused standalone race verifier ---'
python3 - <<'PY'
import threading
class SharedModelClient:
def __init__(self):
self.default_presence_penalty = None
self.default_frequency_penalty = None
self.read_barrier = threading.Barrier(2)
self.observed = {}
def chat(self, request_name):
# This is the relevant behavior of ModelClient.chat.
self.read_barrier.wait()
self.observed[request_name] = (
self.default_presence_penalty,
self.default_frequency_penalty,
)
client = SharedModelClient()
entered = threading.Barrier(2)
def request(name, presence, frequency):
old_presence = client.default_presence_penalty
old_frequency = client.default_frequency_penalty
client.default_presence_penalty = presence
client.default_frequency_penalty = frequency
entered.wait()
try:
client.chat(name)
finally:
client.default_presence_penalty = old_presence
client.default_frequency_penalty = old_frequency
threads = [
threading.Thread(target=request, args=("request-A", 0.1, 0.2)),
threading.Thread(target=request, args=("request-B", 0.7, 0.8)),
]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
print("observed:", client.observed)
print("request-specific isolation holds:",
client.observed == {
"request-A": (0.1, 0.2),
"request-B": (0.7, 0.8),
})
PYRepository: ContextualWisdomLab/contextual-orchestrator Length of output: 7285 요청별 penalty 값을
두 penalty를 요청 범위의 인자로 전달하고, 다른 sampling 값과 함께 유효 값을 계산하십시오. 🤖 Prompt for AI Agents |
||
| if agent.base_url.startswith("mock://"): | ||
| return self._mock(agent, messages) | ||
|
|
||
|
|
@@ -262,10 +286,16 @@ def chat(self, agent: ModelAgent, messages: list[ChatMessage], temperature: floa | |
| payload = { # pragma: no cover | ||
| "model": agent.model, | ||
| "messages": messages, | ||
| "temperature": temperature, | ||
| "temperature": effective_temperature, | ||
| "stream": False, | ||
| "max_tokens": self.max_output_tokens, | ||
| } | ||
| if effective_top_p is not None: # pragma: no cover | ||
| payload["top_p"] = effective_top_p | ||
| if effective_presence is not None: # pragma: no cover | ||
| payload["presence_penalty"] = effective_presence | ||
| if effective_frequency is not None: # pragma: no cover | ||
| payload["frequency_penalty"] = effective_frequency | ||
| return self._send_with_retry(agent, payload) | ||
|
|
||
| def _send_with_retry(self, agent: ModelAgent, payload: dict[str, Any]) -> str: | ||
|
|
@@ -307,7 +337,7 @@ def _send(self, agent: ModelAgent, payload: dict[str, Any]) -> str: | |
|
|
||
| def _open_provider(self, request: urllib.request.Request) -> Any: | ||
| """Open a provider request built from a validated provider URL.""" | ||
| return urllib.request.urlopen( # nosec B310 - request URL comes from _provider_url after provider validation. | ||
| return urllib.request.urlopen( # nosec B310 - request URL comes from _provider_url after provider validation. # nosemgrep -- dynamic-urllib-use: URL is built by _provider_url after scheme/host validation; egress to loopback/private/reserved is blocked. | ||
| request, | ||
| timeout=self.timeout, | ||
| context=self._ssl_context, | ||
|
|
@@ -8517,6 +8547,29 @@ def chat_completion_response( | |
| } | ||
|
|
||
|
|
||
| def text_completion_response( | ||
| result: dict[str, Any], | ||
| model: str = "contextual-orchestrator", | ||
| usage: dict[str, int] | None = None, | ||
| ) -> dict[str, Any]: # pragma: no cover | ||
| """Wrap orchestration output as OpenAI legacy ``text_completion`` (``/v1/completions``).""" | ||
| return { | ||
| "id": f"cmpl-{int(time.time() * 1000)}", | ||
| "object": "text_completion", | ||
| "created": int(time.time()), | ||
| "model": model, | ||
| "choices": [ | ||
| { | ||
| "index": 0, | ||
| "text": result["answer"], | ||
| "logprobs": None, | ||
| "finish_reason": "stop", | ||
| } | ||
| ], | ||
| "usage": usage or {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}, | ||
| } | ||
|
|
||
|
|
||
| _STREAM_CHUNK_SIZE = 32 | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: ContextualWisdomLab/contextual-orchestrator
Length of output: 41729
🏁 Script executed:
Repository: ContextualWisdomLab/contextual-orchestrator
Length of output: 16363
🏁 Script executed:
Repository: ContextualWisdomLab/contextual-orchestrator
Length of output: 6642
🏁 Script executed:
Repository: ContextualWisdomLab/contextual-orchestrator
Length of output: 33619
🏁 Script executed:
Repository: ContextualWisdomLab/contextual-orchestrator
Length of output: 1355
제공 모델 식별자를 별도 필드로 보존하십시오.
명시적
attribution.model_name이 있으면UsageRecord.as_dict()가 이를model_name으로 저장합니다. 현재 저장소와/api/v1/llm_usage_records응답에는 제공 모델 식별자가 없습니다.served_model_name을 추가하고 SQL 스키마 마이그레이션,_USAGE_COLUMNS, 관련 테스트를 갱신하십시오.🤖 Prompt for AI Agents