Misbahuddin Claude Opus 4.8 commited on
Commit
d641c27
·
1 Parent(s): 2cd43d3

fix: hide inert provider toggle on public demo; report real model name in telemetry

Browse files

On the public Space (PUBLIC_DEMO=1) the provider is forced to Anthropic, so the
Anthropic/Ollama toggle was inert — now hidden on the public demo, kept for local
dev. Also fixes a telemetry label bug: the run footer always showed the Claude
model id even on Ollama runs; triage() now reads the real model's .model_name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

api.py CHANGED
@@ -95,6 +95,9 @@ def stats() -> dict:
95
  "precedent_cases": count(CONFIG.cases_collection),
96
  "provider": CONFIG.llm_provider,
97
  "providers": list(_PROVIDERS),
 
 
 
98
  }
99
 
100
 
 
95
  "precedent_cases": count(CONFIG.cases_collection),
96
  "provider": CONFIG.llm_provider,
97
  "providers": list(_PROVIDERS),
98
+ # On the public demo the provider is forced to Anthropic (see run_triage), so the UI hides
99
+ # the otherwise-inert provider toggle.
100
+ "public_demo": CONFIG.public_demo,
101
  }
102
 
103
 
frontend/src/components/Header.tsx CHANGED
@@ -53,22 +53,26 @@ export function Header({
53
  </div>
54
  )}
55
 
56
- <div
57
- className="flex items-center rounded-lg border border-line p-0.5 bg-panel"
58
- title="Anthropic = Claude (demo). Ollama = free local model — watch the policy gate hold it to the same floor."
59
- >
60
- {["anthropic", "ollama"].map((p) => (
61
- <button
62
- key={p}
63
- onClick={() => onProvider(p)}
64
- className={`px-3 py-1 text-xs rounded-md capitalize transition ${
65
- provider === p ? "bg-surface shadow-sm text-accent font-semibold" : "text-muted hover:text-heading"
66
- }`}
67
- >
68
- {p}
69
- </button>
70
- ))}
71
- </div>
 
 
 
 
72
 
73
  <button
74
  onClick={onHelp}
 
53
  </div>
54
  )}
55
 
56
+ {/* Provider toggle — hidden on the public demo, where the provider is forced to Anthropic and
57
+ the toggle would be inert/misleading. It stays for local dev (Anthropic vs free Ollama). */}
58
+ {!stats?.public_demo && (
59
+ <div
60
+ className="flex items-center rounded-lg border border-line p-0.5 bg-panel"
61
+ title="Anthropic = Claude (demo). Ollama = free local model — watch the policy gate hold it to the same floor."
62
+ >
63
+ {["anthropic", "ollama"].map((p) => (
64
+ <button
65
+ key={p}
66
+ onClick={() => onProvider(p)}
67
+ className={`px-3 py-1 text-xs rounded-md capitalize transition ${
68
+ provider === p ? "bg-surface shadow-sm text-accent font-semibold" : "text-muted hover:text-heading"
69
+ }`}
70
+ >
71
+ {p}
72
+ </button>
73
+ ))}
74
+ </div>
75
+ )}
76
 
77
  <button
78
  onClick={onHelp}
frontend/src/components/TriagePanel.tsx CHANGED
@@ -69,8 +69,10 @@ export function TriagePanel({
69
  <Scale size={14} className="mt-0.5 shrink-0 text-gold-deep" />
70
  <span>
71
  The model only recommends. A deterministic <b>policy gate</b> then enforces the rules in
72
- code and can only route a case to a human — never auto-approve/reject. On <b>ollama</b> (a
73
- weak local model) you'll see the gate fire more often.
 
 
74
  </span>
75
  </div>
76
  </div>
 
69
  <Scale size={14} className="mt-0.5 shrink-0 text-gold-deep" />
70
  <span>
71
  The model only recommends. A deterministic <b>policy gate</b> then enforces the rules in
72
+ code and can only route a case to a human — never auto-approve/reject.
73
+ {provider === "ollama" && (
74
+ <> On <b>ollama</b> (a weak local model) you'll see the gate fire more often.</>
75
+ )}
76
  </span>
77
  </div>
78
  </div>
frontend/src/types.ts CHANGED
@@ -80,6 +80,9 @@ export interface Stats {
80
  precedent_cases: number;
81
  provider: string;
82
  providers: string[];
 
 
 
83
  }
84
 
85
  export interface PolicyRuleRef {
 
80
  precedent_cases: number;
81
  provider: string;
82
  providers: string[];
83
+ // True on the deployed public demo, where the provider is forced to Anthropic — the UI hides the
84
+ // (then-inert) provider toggle.
85
+ public_demo: boolean;
86
  }
87
 
88
  export interface PolicyRuleRef {
scripts/test_api.py CHANGED
@@ -44,6 +44,7 @@ def t_stats():
44
  body = r.json()
45
  assert "policy_rules" in body and "precedent_cases" in body
46
  assert body["provider"] in body["providers"]
 
47
 
48
 
49
  def t_list_campaigns():
 
44
  body = r.json()
45
  assert "policy_rules" in body and "precedent_cases" in body
46
  assert body["provider"] in body["providers"]
47
+ assert isinstance(body["public_demo"], bool) # drives the UI's provider-toggle visibility
48
 
49
 
50
  def t_list_campaigns():
src/agent.py CHANGED
@@ -166,9 +166,16 @@ def triage(campaign: Campaign, model: object | None = None) -> GatedDecision:
166
  gated = apply_policy_gate(campaign, result.output)
167
  gated.tokens_in, gated.tokens_out = _usage_tokens(result)
168
  gated.latency_ms = latency_ms
169
- # The default deploy/demo path is Anthropic; reflect the configured model unless a string model
170
- # override carries its own name (e.g. "anthropic:claude-..."). Strip the provider prefix for display.
171
- name = model if isinstance(model, str) else CONFIG.anthropic_model
 
 
 
 
 
 
 
172
  gated.model_name = name.split(":", 1)[1] if isinstance(name, str) and ":" in name else name
173
  return gated
174
 
 
166
  gated = apply_policy_gate(campaign, result.output)
167
  gated.tokens_in, gated.tokens_out = _usage_tokens(result)
168
  gated.latency_ms = latency_ms
169
+ # Report the model that actually ran. A string model carries its own name (e.g.
170
+ # "anthropic:claude-..."); None is the default Anthropic path; a model *object* is the Ollama path
171
+ # (OllamaModel.model_name, e.g. "qwen2.5:7b-instruct") so the footer reflects the real provider,
172
+ # not always Anthropic. Strip any "provider:" prefix for display.
173
+ if isinstance(model, str):
174
+ name = model
175
+ elif model is None:
176
+ name = CONFIG.anthropic_model
177
+ else:
178
+ name = getattr(model, "model_name", None) or CONFIG.ollama_model
179
  gated.model_name = name.split(":", 1)[1] if isinstance(name, str) and ":" in name else name
180
  return gated
181