create employee table
Some checks failed
CI / test (push) Failing after 4m38s
CI / fixture (push) Failing after 9s

This commit is contained in:
2026-09-05 10:44:47 +05:30
parent dc785b917c
commit cf99866e12
11 changed files with 820 additions and 26 deletions

View File

@@ -345,15 +345,33 @@ func translate(err error) error {
return &Error{Code: CodeUpstream, Message: "the model call failed", Cause: err}
}
// The upstream reason, carried through when there is one — the same rule the
// OpenAI path already follows, and for the same reason it gives: a 400 that
// says which model id or tool schema was rejected is worth more than "the
// model rejected the request", and the trajectory records only the message.
//
// This was not a hypothetical. Every run on a deployment failed with a bare
// `gateway.invalid_request`, and neither the run detail nor anything a
// client could read said why — the one fact needed to fix it was discarded
// here, three lines from where it arrived. `Cause` keeps the full error for
// a Go caller; nothing reads it by the time a run is persisted.
detail := anthropicErrorMessage(apierr.RawJSON())
withDetail := func(base string) string {
if detail == "" {
return base
}
return base + ": " + detail
}
switch apierr.StatusCode {
case 400:
return &Error{Code: CodeInvalidRequest, Message: "the model rejected the request", Status: 400, Cause: err}
return &Error{Code: CodeInvalidRequest, Message: withDetail("the model rejected the request"), Status: 400, Cause: err}
case 401, 403:
return &Error{Code: CodeUnauthorized, Message: "the model credentials were refused", Status: apierr.StatusCode, Cause: err}
return &Error{Code: CodeUnauthorized, Message: withDetail("the model credentials were refused"), Status: apierr.StatusCode, Cause: err}
case 408:
return &Error{Code: CodeTimeout, Message: "the model call timed out", Status: 408, Cause: err}
return &Error{Code: CodeTimeout, Message: withDetail("the model call timed out"), Status: 408, Cause: err}
case 429:
return &Error{Code: CodeRateLimited, Message: "the model is rate limiting this deployment", Status: 429, Cause: err}
return &Error{Code: CodeRateLimited, Message: withDetail("the model is rate limiting this deployment"), Status: 429, Cause: err}
case 529:
// Anthropic's "overloaded" — the service is up and temporarily out of
// capacity. Named separately from the 500s because it is the one that
@@ -368,12 +386,36 @@ func translate(err error) error {
// message.
return &Error{
Code: CodeUpstream,
Message: fmt.Sprintf("the model call failed (http %d)", apierr.StatusCode),
Message: withDetail(fmt.Sprintf("the model call failed (http %d)", apierr.StatusCode)),
Status: apierr.StatusCode, Cause: err,
}
}
}
// anthropicErrorMessage digs the human-readable reason out of an error body.
//
// Best-effort, exactly like its OpenAI counterpart: the envelope is documented
// and stable enough to be worth reading, and an unparseable body yields nothing
// rather than failing a failure.
func anthropicErrorMessage(raw string) string {
if raw == "" {
return ""
}
var envelope struct {
Error struct {
Message string `json:"message"`
Type string `json:"type"`
} `json:"error"`
}
if err := json.Unmarshal([]byte(raw), &envelope); err != nil {
return ""
}
if envelope.Error.Message != "" {
return envelope.Error.Message
}
return envelope.Error.Type
}
/* ── Streaming ──────────────────────────────────────────────────────────── */
// Stream is Complete, with the assistant's text delivered as it arrives.