* feat(io): add streaming API to Medium interface and optimize agentic context - Added ReadStream and WriteStream to io.Medium interface. - Implemented streaming methods in local and mock mediums. - Updated pkg/agentic/context.go to use streaming I/O with LimitReader. - Added 5000-byte truncation limit for all AI context file reads to reduce memory usage. - Documented when to use streaming vs full-file APIs in io.Medium. * feat(io): optimize streaming API and fix PR feedback - Fixed resource leak in agentic context by using defer for closing file streams. - Improved truncation logic in agentic context to handle multibyte characters correctly by checking byte length before string conversion. - Added comprehensive documentation to ReadStream and WriteStream in local medium. - Added unit tests for ReadStream and WriteStream in local medium. - Applied formatting and fixed auto-merge CI configuration. * feat(io): add streaming API and fix CI failures (syntax fix) - Introduced ReadStream and WriteStream to io.Medium interface. - Implemented streaming methods in local and mock mediums. - Optimized agentic context with streaming reads and truncation logic. - Fixed syntax error in local client tests by overwriting the file. - Fixed auto-merge CI by adding checkout and repository context. - Applied formatting fixes.
124 lines
4.6 KiB
Go
124 lines
4.6 KiB
Go
package cli
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/host-uk/core/pkg/i18n"
|
|
)
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Error Creation (replace fmt.Errorf)
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
// Err creates a new error from a format string.
|
|
// This is a direct replacement for fmt.Errorf.
|
|
func Err(format string, args ...any) error {
|
|
return fmt.Errorf(format, args...)
|
|
}
|
|
|
|
// Wrap wraps an error with a message.
|
|
// Returns nil if err is nil.
|
|
//
|
|
// return cli.Wrap(err, "load config") // "load config: <original error>"
|
|
func Wrap(err error, msg string) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("%s: %w", msg, err)
|
|
}
|
|
|
|
// WrapVerb wraps an error using i18n grammar for "Failed to verb subject".
|
|
// Uses the i18n.ActionFailed function for proper grammar composition.
|
|
// Returns nil if err is nil.
|
|
//
|
|
// return cli.WrapVerb(err, "load", "config") // "Failed to load config: <original error>"
|
|
func WrapVerb(err error, verb, subject string) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
msg := i18n.ActionFailed(verb, subject)
|
|
return fmt.Errorf("%s: %w", msg, err)
|
|
}
|
|
|
|
// WrapAction wraps an error using i18n grammar for "Failed to verb".
|
|
// Uses the i18n.ActionFailed function for proper grammar composition.
|
|
// Returns nil if err is nil.
|
|
//
|
|
// return cli.WrapAction(err, "connect") // "Failed to connect: <original error>"
|
|
func WrapAction(err error, verb string) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
msg := i18n.ActionFailed(verb, "")
|
|
return fmt.Errorf("%s: %w", msg, err)
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Error Helpers
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
// Is reports whether any error in err's tree matches target.
|
|
// This is a re-export of errors.Is for convenience.
|
|
func Is(err, target error) bool {
|
|
return errors.Is(err, target)
|
|
}
|
|
|
|
// As finds the first error in err's tree that matches target.
|
|
// This is a re-export of errors.As for convenience.
|
|
func As(err error, target any) bool {
|
|
return errors.As(err, target)
|
|
}
|
|
|
|
// Join returns an error that wraps the given errors.
|
|
// This is a re-export of errors.Join for convenience.
|
|
func Join(errs ...error) error {
|
|
return errors.Join(errs...)
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// Fatal Functions (print and exit)
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
// Fatal prints an error message and exits with code 1.
|
|
func Fatal(err error) {
|
|
if err != nil {
|
|
fmt.Println(ErrorStyle.Render(Glyph(":cross:") + " " + err.Error()))
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// Fatalf prints a formatted error message and exits with code 1.
|
|
func Fatalf(format string, args ...any) {
|
|
msg := fmt.Sprintf(format, args...)
|
|
fmt.Println(ErrorStyle.Render(Glyph(":cross:") + " " + msg))
|
|
os.Exit(1)
|
|
}
|
|
|
|
// FatalWrap prints a wrapped error message and exits with code 1.
|
|
// Does nothing if err is nil.
|
|
//
|
|
// cli.FatalWrap(err, "load config") // Prints "✗ load config: <error>" and exits
|
|
func FatalWrap(err error, msg string) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
fullMsg := fmt.Sprintf("%s: %v", msg, err)
|
|
fmt.Println(ErrorStyle.Render(Glyph(":cross:") + " " + fullMsg))
|
|
os.Exit(1)
|
|
}
|
|
|
|
// FatalWrapVerb prints a wrapped error using i18n grammar and exits with code 1.
|
|
// Does nothing if err is nil.
|
|
//
|
|
// cli.FatalWrapVerb(err, "load", "config") // Prints "✗ Failed to load config: <error>" and exits
|
|
func FatalWrapVerb(err error, verb, subject string) {
|
|
if err == nil {
|
|
return
|
|
}
|
|
msg := i18n.ActionFailed(verb, subject)
|
|
fullMsg := fmt.Sprintf("%s: %v", msg, err)
|
|
fmt.Println(ErrorStyle.Render(Glyph(":cross:") + " " + fullMsg))
|
|
os.Exit(1)
|
|
}
|