mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
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
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package browsercontexts
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type BrowserContext struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Config json.RawMessage `json:"config"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
type CreateRequest struct {
|
||||
Name string `json:"name"`
|
||||
Config json.RawMessage `json:"config"`
|
||||
}
|
||||
|
||||
type UpdateRequest struct {
|
||||
Name string `json:"name"`
|
||||
Config json.RawMessage `json:"config"`
|
||||
}
|
||||
Reference in New Issue
Block a user