feat: per-run model selection, usage in diagnosis results and a Claude Messages API provider
캠페인마다 진단 모델을 고를 수 있게 한다. 하네스는 runs.model 열을 추가해 POST /runs의 model을 저장하고, 활성 런의 model을 /diagnose 요청에 실어 보낸다. 에이전트는 요청의 model을 우선 사용하고(없으면 OPENAI_MODEL 기본값), 모델 id가 claude-로 시작하면 internal/anthropic(Claude Messages API 어댑터)로 라우팅한다. 어댑터는 Responses API 항목(message/function_call/function_call_output)을 system·tools(input_schema)·tool_use/ tool_result로 변환하고 previous_response_id 체인을 클라이언트 쪽에서 재현하며, Claude 5.5가 강제 tool_choice를 거부하므로 강제 호출은 auto + 지시문으로 바꾼다. 키는 ANTHROPIC_KEY_FILE(/run/secrets/anthropic-api-key)에서 읽고 비어 있으면 명확한 오류를 낸다. Result에 usage(입력·출력·합계 토큰)를 추가해 하네스 diagnosis 이벤트에 비용 근거를 남긴다.
This commit is contained in:
1 parent
fa9c08c778
commit
53ff243183
8 files changed
+492
-12
No files matched your search
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/selfheal-lab/selfheal-lab-apps/ai/internal/agent"
|
||||
"github.com/selfheal-lab/selfheal-lab-apps/ai/internal/anthropic"
|
||||
"github.com/selfheal-lab/selfheal-lab-apps/ai/internal/diag"
|
||||
"github.com/selfheal-lab/selfheal-lab-apps/ai/internal/harness"
|
||||
"github.com/selfheal-lab/selfheal-lab-apps/ai/internal/jev"
|
||||
@@ -95,6 +96,10 @@ func main() {
|
||||
HitlURL: env("HITL_URL", "http://hitl:8081"),
|
||||
}
|
||||
ag := agent.New(acfg, oai, tr, hc, store, enums, pv)
|
||||
// Claude Messages API for claude-* model ids chosen per campaign; the key may be registered later (empty = diagnoses with
|
||||
// a claude-* model fail with "anthropic api key is empty", recorded in the harness diagnosis event).
|
||||
anth := anthropic.New(env("ANTHROPIC_BASE_URL", ""), keyReader(env("ANTHROPIC_KEY_FILE", "/run/secrets/anthropic-api-key")))
|
||||
ag.SetAnthropic(anth)
|
||||
jevMode := env("JEV_MODE", "off") // off | shadow | enforce (shadow records Jev answers next to the diagnosis; enforce also applies the two review rules)
|
||||
var jc *jev.Client
|
||||
if jevMode == "shadow" || jevMode == "enforce" {
|
||||
@@ -130,6 +135,7 @@ func main() {
|
||||
out := map[string]any{"model": acfg.Model, "prompt_version": pv, "labels": enums.Labels, "actions": enums.Actions}
|
||||
key, kerr := keyReader(env("OPENAI_KEY_FILE", "/run/secrets/openai-api-key"))()
|
||||
out["openai_key_present"] = kerr == nil && key != ""
|
||||
out["anthropic_key_present"] = anth.KeyPresent()
|
||||
out["jev_mode"] = jevMode
|
||||
if jc != nil {
|
||||
out["jev_key_present"] = jc.KeyPresent()
|
||||
|
||||
Reference in new issue
Block a user