Files
Memoh/internal/browsercontexts/service.go
T
Acbox Liu bafd327b6b feat: agent browser (#200)
* feat: agent browser

* chore: complete docker and action config

* feat: more actions

* feat: browser tab switch

* fix: browser build

* fix: lint

* fix: migrations
2026-03-07 15:06:00 +08:00

127 lines
3.1 KiB
Go

package browsercontexts
import (
"context"
"encoding/json"
"errors"
"fmt"
"log/slog"
"github.com/google/uuid"
"github.com/memohai/memoh/internal/db"
"github.com/memohai/memoh/internal/db/sqlc"
)
type Service struct {
queries *sqlc.Queries
logger *slog.Logger
}
func NewService(log *slog.Logger, queries *sqlc.Queries) *Service {
return &Service{
queries: queries,
logger: log.With(slog.String("service", "browser_contexts")),
}
}
func (s *Service) Create(ctx context.Context, req CreateRequest) (BrowserContext, error) {
configBytes, err := marshalConfig(req.Config)
if err != nil {
return BrowserContext{}, err
}
row, err := s.queries.CreateBrowserContext(ctx, sqlc.CreateBrowserContextParams{
Name: req.Name,
Config: configBytes,
})
if err != nil {
return BrowserContext{}, fmt.Errorf("create browser context: %w", err)
}
return rowToContext(row)
}
func (s *Service) GetByID(ctx context.Context, id string) (BrowserContext, error) {
pgID, err := db.ParseUUID(id)
if err != nil {
return BrowserContext{}, err
}
row, err := s.queries.GetBrowserContextByID(ctx, pgID)
if err != nil {
return BrowserContext{}, fmt.Errorf("get browser context: %w", err)
}
return rowToContext(row)
}
func (s *Service) List(ctx context.Context) ([]BrowserContext, error) {
rows, err := s.queries.ListBrowserContexts(ctx)
if err != nil {
return nil, fmt.Errorf("list browser contexts: %w", err)
}
result := make([]BrowserContext, 0, len(rows))
for _, row := range rows {
bc, err := rowToContext(row)
if err != nil {
return nil, err
}
result = append(result, bc)
}
return result, nil
}
func (s *Service) Update(ctx context.Context, id string, req UpdateRequest) (BrowserContext, error) {
pgID, err := db.ParseUUID(id)
if err != nil {
return BrowserContext{}, err
}
configBytes, err := marshalConfig(req.Config)
if err != nil {
return BrowserContext{}, err
}
row, err := s.queries.UpdateBrowserContext(ctx, sqlc.UpdateBrowserContextParams{
ID: pgID,
Name: req.Name,
Config: configBytes,
})
if err != nil {
return BrowserContext{}, fmt.Errorf("update browser context: %w", err)
}
return rowToContext(row)
}
func (s *Service) Delete(ctx context.Context, id string) error {
pgID, err := db.ParseUUID(id)
if err != nil {
return err
}
if err := s.queries.DeleteBrowserContext(ctx, pgID); err != nil {
return fmt.Errorf("delete browser context: %w", err)
}
return nil
}
func rowToContext(row sqlc.BrowserContext) (BrowserContext, error) {
id, err := uuid.FromBytes(row.ID.Bytes[:])
if err != nil {
return BrowserContext{}, fmt.Errorf("convert UUID: %w", err)
}
return BrowserContext{
ID: id.String(),
Name: row.Name,
Config: json.RawMessage(row.Config),
CreatedAt: db.TimeFromPg(row.CreatedAt).Format("2006-01-02T15:04:05Z07:00"),
UpdatedAt: db.TimeFromPg(row.UpdatedAt).Format("2006-01-02T15:04:05Z07:00"),
}, nil
}
func marshalConfig(raw json.RawMessage) ([]byte, error) {
if len(raw) == 0 {
return []byte("{}"), nil
}
if !json.Valid(raw) {
return nil, errors.New("config is not valid JSON")
}
return raw, nil
}