Files
Maven/internal/voice/errors.go
kami d52f60c54e maven: fix test mocks for CalendarEvents interface (verification)
- Add CalendarEvents method to recordingAPI in auth_test.go
- Add CalendarEvents method to fakeCore in handlers_test.go

Co-Authored-By: opencode <opencode@anthropic.com>
2026-07-06 04:20:16 +04:00

74 lines
2.0 KiB
Go

// voice/errors.go — wire error codes + sentinel rehydration.
package voice
import (
"encoding/json"
"errors"
"fmt"
)
// Sentinel errors. Mirrored 1:1 to wire codes below; the client rehydrates a
// wire RpcError into one of these so callers can use errors.Is the same way
// in-process and over-the-wire.
var (
ErrUnknownMethod = errors.New("voice: unknown method")
ErrBadParams = errors.New("voice: bad params")
ErrForbidden = errors.New("voice: forbidden")
ErrNoSession = errors.New("voice: no live client session") // voicesink unable to push
)
// Sentinel wire codes. Stable; do not rename.
const (
codeUnknownMethod = "unknown_method"
codeBadParams = "bad_params"
codeForbidden = "forbidden"
codeInternal = "internal"
)
// codeOf maps a server-side sentinel to its wire code. Unknown ⇒
// codeInternal; the server logs the real text and the client sees a
// generic internal code (no authority-bearing text exposure).
func codeOf(err error) string {
switch {
case err == nil:
return ""
case errors.Is(err, ErrUnknownMethod):
return codeUnknownMethod
case errors.Is(err, ErrBadParams):
return codeBadParams
case errors.Is(err, ErrForbidden):
return codeForbidden
default:
return codeInternal
}
}
func rpcErr(err error) *RpcError {
c := codeOf(err)
if c == codeInternal || c == codeBadParams {
return &RpcError{Code: c, Message: err.Error()}
}
return &RpcError{Code: c}
}
// hydrate rehydrates a wire RpcError into a package sentinel.
func hydrate(e *RpcError) error {
switch e.Code {
case codeUnknownMethod:
return fmt.Errorf("%w: %s", ErrUnknownMethod, e.Message)
case codeBadParams:
return fmt.Errorf("%w: %s", ErrBadParams, e.Message)
case codeForbidden:
return ErrForbidden
default:
if e.Message != "" {
return fmt.Errorf("voice: %s: %s", e.Code, e.Message)
}
return fmt.Errorf("voice: %s", e.Code)
}
}
// json helpers kept local so call sites read clean.
func jsonMarshal(v any) ([]byte, error) { return json.Marshal(v) }
func jsonUnmarshal(b []byte, v any) error { return json.Unmarshal(b, v) }