diff --git a/cmd/agent/main.go b/cmd/agent/main.go index 58a0a1e3..cd6cce55 100644 --- a/cmd/agent/main.go +++ b/cmd/agent/main.go @@ -12,7 +12,6 @@ import ( "strings" "time" - containerd "github.com/containerd/containerd/v2/client" "github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgxpool" "go.uber.org/fx" @@ -131,12 +130,11 @@ func runServe() { provideConfig, boot.ProvideRuntimeConfig, provideLogger, - provideContainerdClient, + provideContainerService, provideDBConn, provideDBQueries, - // containerd & mcp infrastructure - fx.Annotate(ctr.NewDefaultService, fx.As(new(ctr.Service))), + // container & mcp infrastructure provideMCPManager, // memory pipeline @@ -255,18 +253,18 @@ func provideLogger(cfg config.Config) *slog.Logger { return logger.L } -func provideContainerdClient(lc fx.Lifecycle, rc *boot.RuntimeConfig) (*containerd.Client, error) { - factory := ctr.DefaultClientFactory{SocketPath: rc.ContainerdSocketPath} - client, err := factory.New(context.Background()) +func provideContainerService(lc fx.Lifecycle, log *slog.Logger, cfg config.Config, rc *boot.RuntimeConfig) (ctr.Service, error) { + svc, cleanup, err := ctr.ProvideService(context.Background(), log, cfg, rc.ContainerBackend) if err != nil { - return nil, fmt.Errorf("connect containerd: %w", err) + return nil, err } lc.Append(fx.Hook{ OnStop: func(ctx context.Context) error { - return client.Close() + cleanup() + return nil }, }) - return client, nil + return svc, nil } func provideDBConn(lc fx.Lifecycle, cfg config.Config) (*pgxpool.Pool, error) { @@ -444,8 +442,8 @@ func provideChannelLifecycleService(channelStore *channel.Store, channelManager // containerd handler & tool gateway // --------------------------------------------------------------------------- -func provideContainerdHandler(log *slog.Logger, service ctr.Service, manager *mcp.Manager, cfg config.Config, botService *bots.Service, accountService *accounts.Service, policyService *policy.Service, queries *dbsqlc.Queries) *handlers.ContainerdHandler { - return handlers.NewContainerdHandler(log, service, manager, cfg.MCP, cfg.Containerd.Namespace, botService, accountService, policyService, queries) +func provideContainerdHandler(log *slog.Logger, service ctr.Service, manager *mcp.Manager, cfg config.Config, rc *boot.RuntimeConfig, botService *bots.Service, accountService *accounts.Service, policyService *policy.Service, queries *dbsqlc.Queries) *handlers.ContainerdHandler { + return handlers.NewContainerdHandler(log, service, manager, cfg.MCP, cfg.Containerd.Namespace, rc.ContainerBackend, botService, accountService, policyService, queries) } func provideToolGatewayService(log *slog.Logger, cfg config.Config, channelManager *channel.Manager, registry *channel.Registry, routeService *route.DBService, scheduleService *schedule.Service, memoryService *memory.Service, chatService *conversation.Service, accountService *accounts.Service, settingsService *settings.Service, searchProviderService *searchproviders.Service, manager *mcp.Manager, containerdHandler *handlers.ContainerdHandler, mcpConnService *mcp.ConnectionService, mediaService *media.Service, inboxService *inbox.Service) *mcp.ToolGatewayService { diff --git a/conf/app.apple.toml b/conf/app.apple.toml new file mode 100644 index 00000000..dc0e8482 --- /dev/null +++ b/conf/app.apple.toml @@ -0,0 +1,51 @@ +# Memoh Apple Container configuration (macOS / Darwin) +# Uses socktainer + Apple Containerization framework instead of containerd. + +[log] +level = "debug" +format = "text" + +[server] +addr = ":8080" + +[admin] +username = "admin" +password = "admin123" +email = "dev@memoh.local" + +[auth] +jwt_secret = "memoh-dev-secret-do-not-use-in-production" +jwt_expires_in = "168h" + +[containerd] +# socket_path / namespace are unused on macOS; socktainer takes over. + +[containerd.socktainer] +# NOTE: Apple Container are now experimental feature and only support on macOS 26 and later. +# socket_path and binary_path use sensible defaults when left empty. +# socket_path = "/path/to/your/.socktainer/container.sock" +# binary_path = "/opt/homebrew/bin/socktainer" + +[mcp] +image = "memohai/mcp:latest" +data_root = "data" +data_mount = "/data" + +[postgres] +host = "127.0.0.1" +port = 5432 +user = "memoh" +password = "memoh123" +database = "memoh" +sslmode = "disable" + +[qdrant] +base_url = "http://127.0.0.1:6334" +api_key = "" +collection = "memory" +timeout_seconds = 10 + +[agent_gateway] +host = "127.0.0.1" +port = 8081 +server_addr = "127.0.0.1:8080" \ No newline at end of file diff --git a/go.mod b/go.mod index 837070a3..8437ec9e 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/labstack/echo-jwt/v4 v4.4.0 github.com/labstack/echo/v4 v4.15.0 github.com/larksuite/oapi-sdk-go/v3 v3.5.3 + github.com/memohai/acgo v0.0.0-20260221232113-babac0d6acd7 github.com/modelcontextprotocol/go-sdk v1.3.0 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.1.1 diff --git a/go.sum b/go.sum index 6092496a..01da829c 100644 --- a/go.sum +++ b/go.sum @@ -199,6 +199,8 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/memohai/acgo v0.0.0-20260221232113-babac0d6acd7 h1:beehwOQperqGWj4m4EhcPhnSZKtDiuHK/7ZMoTPaQjw= +github.com/memohai/acgo v0.0.0-20260221232113-babac0d6acd7/go.mod h1:OvmxM7JmnXBmwJWWVqtreL3HSHSKuzPbtbhlg5MvBg0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= diff --git a/internal/boot/runtime.go b/internal/boot/runtime.go index 0ef1acbc..7f6ef8a3 100644 --- a/internal/boot/runtime.go +++ b/internal/boot/runtime.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "os" + "runtime" "strings" "time" @@ -15,6 +16,7 @@ type RuntimeConfig struct { JwtExpiresIn time.Duration ServerAddr string ContainerdSocketPath string + ContainerBackend string // "containerd" or "apple" } func ProvideRuntimeConfig(cfg config.Config) (*RuntimeConfig, error) { @@ -27,11 +29,17 @@ func ProvideRuntimeConfig(cfg config.Config) (*RuntimeConfig, error) { return nil, fmt.Errorf("invalid jwt expires in: %w", err) } + backend := "containerd" + if runtime.GOOS == "darwin" { + backend = "apple" + } + ret := &RuntimeConfig{ JwtSecret: cfg.Auth.JWTSecret, JwtExpiresIn: jwtExpiresIn, ServerAddr: cfg.Server.Addr, ContainerdSocketPath: cfg.Containerd.SocketPath, + ContainerBackend: backend, } if value := os.Getenv("HTTP_ADDR"); value != "" { @@ -41,5 +49,8 @@ func ProvideRuntimeConfig(cfg config.Config) (*RuntimeConfig, error) { if value := os.Getenv("CONTAINERD_SOCKET"); value != "" { ret.ContainerdSocketPath = value } + if value := os.Getenv("CONTAINER_BACKEND"); value != "" { + ret.ContainerBackend = value + } return ret, nil } diff --git a/internal/config/config.go b/internal/config/config.go index 54c67415..1dafca06 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -15,8 +15,8 @@ const ( DefaultMCPImage = "docker.io/library/memoh-mcp:latest" DefaultDataRoot = "data" DefaultDataMount = "/data" - DefaultCNIBinaryDir = "/opt/cni/bin" - DefaultCNIConfigDir = "/etc/cni/net.d" + DefaultCNIBinaryDir = "/opt/cni/bin" + DefaultCNIConfigDir = "/etc/cni/net.d" DefaultJWTExpiresIn = "24h" DefaultPGHost = "127.0.0.1" DefaultPGPort = 5432 @@ -60,8 +60,14 @@ type AuthConfig struct { } type ContainerdConfig struct { + SocketPath string `toml:"socket_path"` + Namespace string `toml:"namespace"` + Socktainer SocktainerConfig `toml:"socktainer"` +} + +type SocktainerConfig struct { SocketPath string `toml:"socket_path"` - Namespace string `toml:"namespace"` + BinaryPath string `toml:"binary_path"` } type MCPConfig struct { diff --git a/internal/containerd/factory.go b/internal/containerd/factory.go index 36cce0ff..4f23e7e6 100644 --- a/internal/containerd/factory.go +++ b/internal/containerd/factory.go @@ -2,13 +2,19 @@ package containerd import ( "context" + "fmt" + "log/slog" containerd "github.com/containerd/containerd/v2/client" + "github.com/memohai/memoh/internal/config" ) const ( DefaultSocketPath = "/run/containerd/containerd.sock" DefaultNamespace = "default" + + BackendContainerd = "containerd" + BackendApple = "apple" ) type ClientFactory interface { @@ -26,3 +32,29 @@ func (f DefaultClientFactory) New(_ context.Context) (*containerd.Client, error) } return containerd.New(socket) } + +// ProvideService creates the appropriate Service based on the backend type. +func ProvideService(ctx context.Context, log *slog.Logger, cfg config.Config, backend string) (Service, func(), error) { + switch backend { + case BackendApple: + svc, err := NewAppleService(ctx, log, AppleServiceConfig{ + SocketPath: cfg.Containerd.Socktainer.SocketPath, + BinaryPath: cfg.Containerd.Socktainer.BinaryPath, + }) + if err != nil { + return nil, nil, fmt.Errorf("create apple container service: %w", err) + } + cleanup := func() { _ = svc.Close() } + return svc, cleanup, nil + + default: + factory := DefaultClientFactory{SocketPath: cfg.Containerd.SocketPath} + client, err := factory.New(ctx) + if err != nil { + return nil, nil, fmt.Errorf("connect containerd: %w", err) + } + svc := NewDefaultService(log, client, cfg) + cleanup := func() { _ = client.Close() } + return svc, cleanup, nil + } +} diff --git a/internal/containerd/mount.go b/internal/containerd/mount.go index 2899131b..b5e4912b 100644 --- a/internal/containerd/mount.go +++ b/internal/containerd/mount.go @@ -5,13 +5,12 @@ import ( "fmt" "os" - "github.com/containerd/containerd/v2/core/containers" "github.com/containerd/containerd/v2/core/mount" ) type MountedSnapshot struct { Dir string - Info containers.Container + Info ContainerInfo Unmount func() error } @@ -21,20 +20,25 @@ func MountContainerSnapshot(ctx context.Context, service Service, containerID st return nil, ErrInvalidArgument } - container, err := service.GetContainer(ctx, containerID) - if err != nil { - return nil, err - } - info, err := container.Info(ctx) + info, err := service.GetContainer(ctx, containerID) if err != nil { return nil, err } - mounts, err := service.SnapshotMounts(ctx, info.Snapshotter, info.SnapshotKey) + mountInfos, err := service.SnapshotMounts(ctx, info.Snapshotter, info.SnapshotKey) if err != nil { return nil, err } + mounts := make([]mount.Mount, len(mountInfos)) + for i, m := range mountInfos { + mounts[i] = mount.Mount{ + Type: m.Type, + Source: m.Source, + Options: m.Options, + } + } + dir, err := os.MkdirTemp("", "memoh-snapshot-*") if err != nil { return nil, err @@ -66,11 +70,20 @@ func MountSnapshot(ctx context.Context, service Service, snapshotter, key string return "", nil, ErrInvalidArgument } - mounts, err := service.SnapshotMounts(ctx, snapshotter, key) + mountInfos, err := service.SnapshotMounts(ctx, snapshotter, key) if err != nil { return "", nil, err } + mounts := make([]mount.Mount, len(mountInfos)) + for i, m := range mountInfos { + mounts[i] = mount.Mount{ + Type: m.Type, + Source: m.Source, + Options: m.Options, + } + } + dir, err := os.MkdirTemp("", "memoh-snapshot-*") if err != nil { return "", nil, err diff --git a/internal/containerd/network.go b/internal/containerd/network.go index 1cd15259..483323e0 100644 --- a/internal/containerd/network.go +++ b/internal/containerd/network.go @@ -11,8 +11,7 @@ import ( gocni "github.com/containerd/go-cni" ) -// SetupNetwork attaches CNI networking to a running task. -func SetupNetwork(ctx context.Context, task client.Task, containerID string, CNIBinDir string, CNIConfDir string) error { +func setupCNINetwork(ctx context.Context, task client.Task, containerID string, CNIBinDir string, CNIConfDir string) error { if task == nil { return ErrInvalidArgument } @@ -65,8 +64,7 @@ func SetupNetwork(ctx context.Context, task client.Task, containerID string, CNI return nil } -// RemoveNetwork detaches CNI networking for a running task. -func RemoveNetwork(ctx context.Context, task client.Task, containerID string, CNIBinDir string, CNIConfDir string) error { +func removeCNINetwork(ctx context.Context, task client.Task, containerID string, CNIBinDir string, CNIConfDir string) error { if task == nil { return ErrInvalidArgument } diff --git a/internal/containerd/service.go b/internal/containerd/service.go index df245616..f46726e7 100644 --- a/internal/containerd/service.go +++ b/internal/containerd/service.go @@ -19,7 +19,6 @@ import ( containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/core/content" "github.com/containerd/containerd/v2/core/images" - "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/namespaces" @@ -52,7 +51,7 @@ type CreateContainerRequest struct { SnapshotID string Snapshotter string Labels map[string]string - SpecOpts []oci.SpecOpts + Spec ContainerSpec } type DeleteContainerOptions struct { @@ -75,30 +74,6 @@ type DeleteTaskOptions struct { Force bool } -type ExecTaskRequest struct { - Args []string - Env []string - WorkDir string - Terminal bool - UseStdio bool - FIFODir string - Stdin io.Reader - Stdout io.Writer - Stderr io.Writer -} - -type ExecTaskSession struct { - Stdin io.WriteCloser - Stdout io.ReadCloser - Stderr io.ReadCloser - Wait func() (ExecTaskResult, error) - Close func() error -} - -type ExecTaskResult struct { - ExitCode uint32 -} - type SnapshotCommitResult struct { VersionSnapshotName string ActiveSnapshotName string @@ -108,38 +83,34 @@ type ListTasksOptions struct { Filter string } -type TaskInfo struct { - ContainerID string - ID string - PID uint32 - Status tasktypes.Status - ExitStatus uint32 -} - type Service interface { - PullImage(ctx context.Context, ref string, opts *PullImageOptions) (containerd.Image, error) - GetImage(ctx context.Context, ref string) (containerd.Image, error) - ListImages(ctx context.Context) ([]containerd.Image, error) + PullImage(ctx context.Context, ref string, opts *PullImageOptions) (ImageInfo, error) + GetImage(ctx context.Context, ref string) (ImageInfo, error) + ListImages(ctx context.Context) ([]ImageInfo, error) DeleteImage(ctx context.Context, ref string, opts *DeleteImageOptions) error - CreateContainer(ctx context.Context, req CreateContainerRequest) (containerd.Container, error) - GetContainer(ctx context.Context, id string) (containerd.Container, error) - ListContainers(ctx context.Context) ([]containerd.Container, error) + CreateContainer(ctx context.Context, req CreateContainerRequest) (ContainerInfo, error) + GetContainer(ctx context.Context, id string) (ContainerInfo, error) + ListContainers(ctx context.Context) ([]ContainerInfo, error) DeleteContainer(ctx context.Context, id string, opts *DeleteContainerOptions) error + ListContainersByLabel(ctx context.Context, key, value string) ([]ContainerInfo, error) - StartTask(ctx context.Context, containerID string, opts *StartTaskOptions) (containerd.Task, error) - GetTask(ctx context.Context, containerID string) (containerd.Task, error) - ListTasks(ctx context.Context, opts *ListTasksOptions) ([]TaskInfo, error) - StopTask(ctx context.Context, containerID string, opts *StopTaskOptions) error + StartContainer(ctx context.Context, containerID string, opts *StartTaskOptions) error + StopContainer(ctx context.Context, containerID string, opts *StopTaskOptions) error DeleteTask(ctx context.Context, containerID string, opts *DeleteTaskOptions) error + GetTaskInfo(ctx context.Context, containerID string) (TaskInfo, error) + ListTasks(ctx context.Context, opts *ListTasksOptions) ([]TaskInfo, error) ExecTask(ctx context.Context, containerID string, req ExecTaskRequest) (ExecTaskResult, error) ExecTaskStreaming(ctx context.Context, containerID string, req ExecTaskRequest) (*ExecTaskSession, error) - ListContainersByLabel(ctx context.Context, key, value string) ([]containerd.Container, error) + + SetupNetwork(ctx context.Context, req NetworkSetupRequest) error + RemoveNetwork(ctx context.Context, req NetworkSetupRequest) error + CommitSnapshot(ctx context.Context, snapshotter, name, key string) error - ListSnapshots(ctx context.Context, snapshotter string) ([]snapshots.Info, error) + ListSnapshots(ctx context.Context, snapshotter string) ([]SnapshotInfo, error) PrepareSnapshot(ctx context.Context, snapshotter, key, parent string) error - CreateContainerFromSnapshot(ctx context.Context, req CreateContainerRequest) (containerd.Container, error) - SnapshotMounts(ctx context.Context, snapshotter, key string) ([]mount.Mount, error) + CreateContainerFromSnapshot(ctx context.Context, req CreateContainerRequest) (ContainerInfo, error) + SnapshotMounts(ctx context.Context, snapshotter, key string) ([]MountInfo, error) } type DefaultService struct { @@ -160,9 +131,9 @@ func NewDefaultService(log *slog.Logger, client *containerd.Client, cfg config.C } } -func (s *DefaultService) PullImage(ctx context.Context, ref string, opts *PullImageOptions) (containerd.Image, error) { +func (s *DefaultService) PullImage(ctx context.Context, ref string, opts *PullImageOptions) (ImageInfo, error) { if ref == "" { - return nil, ErrInvalidArgument + return ImageInfo{}, ErrInvalidArgument } ctx = s.withNamespace(ctx) @@ -174,20 +145,36 @@ func (s *DefaultService) PullImage(ctx context.Context, ref string, opts *PullIm pullOpts = append(pullOpts, containerd.WithPullSnapshotter(opts.Snapshotter)) } - return s.client.Pull(ctx, ref, pullOpts...) + img, err := s.client.Pull(ctx, ref, pullOpts...) + if err != nil { + return ImageInfo{}, err + } + return toImageInfo(img), nil } -func (s *DefaultService) GetImage(ctx context.Context, ref string) (containerd.Image, error) { +func (s *DefaultService) GetImage(ctx context.Context, ref string) (ImageInfo, error) { if ref == "" { - return nil, ErrInvalidArgument + return ImageInfo{}, ErrInvalidArgument } ctx = s.withNamespace(ctx) - return s.client.GetImage(ctx, ref) + img, err := s.getImageWithFallback(ctx, ref) + if err != nil { + return ImageInfo{}, err + } + return toImageInfo(img), nil } -func (s *DefaultService) ListImages(ctx context.Context) ([]containerd.Image, error) { +func (s *DefaultService) ListImages(ctx context.Context) ([]ImageInfo, error) { ctx = s.withNamespace(ctx) - return s.client.ListImages(ctx) + imgs, err := s.client.ListImages(ctx) + if err != nil { + return nil, err + } + result := make([]ImageInfo, len(imgs)) + for i, img := range imgs { + result[i] = toImageInfo(img) + } + return result, nil } func (s *DefaultService) DeleteImage(ctx context.Context, ref string, opts *DeleteImageOptions) error { @@ -202,15 +189,49 @@ func (s *DefaultService) DeleteImage(ctx context.Context, ref string, opts *Dele return s.client.ImageService().Delete(ctx, ref, deleteOpts...) } -func (s *DefaultService) CreateContainer(ctx context.Context, req CreateContainerRequest) (containerd.Container, error) { +func specOptsFromSpec(spec ContainerSpec) []oci.SpecOpts { + var opts []oci.SpecOpts + + if len(spec.Cmd) > 0 { + opts = append(opts, oci.WithProcessArgs(spec.Cmd...)) + } + if len(spec.Env) > 0 { + opts = append(opts, oci.WithEnv(spec.Env)) + } + if spec.WorkDir != "" { + opts = append(opts, oci.WithProcessCwd(spec.WorkDir)) + } + if spec.User != "" { + opts = append(opts, oci.WithUser(spec.User)) + } + if spec.TTY { + opts = append(opts, oci.WithTTY) + } + if len(spec.Mounts) > 0 { + mounts := make([]specs.Mount, len(spec.Mounts)) + for i, m := range spec.Mounts { + mounts[i] = specs.Mount{ + Destination: m.Destination, + Type: m.Type, + Source: m.Source, + Options: m.Options, + } + } + opts = append(opts, oci.WithMounts(mounts)) + } + + return opts +} + +func (s *DefaultService) CreateContainer(ctx context.Context, req CreateContainerRequest) (ContainerInfo, error) { if req.ID == "" || req.ImageRef == "" { - return nil, ErrInvalidArgument + return ContainerInfo{}, ErrInvalidArgument } ctx = s.withNamespace(ctx) ctx, done, err := s.client.WithLease(ctx) if err != nil { - return nil, err + return ContainerInfo{}, err } defer done(ctx) image, err := s.getImageWithFallback(ctx, req.ImageRef) @@ -219,9 +240,13 @@ func (s *DefaultService) CreateContainer(ctx context.Context, req CreateContaine Unpack: true, Snapshotter: req.Snapshotter, } - image, err = s.PullImage(ctx, req.ImageRef, pullOpts) + _, err = s.PullImage(ctx, req.ImageRef, pullOpts) if err != nil { - return nil, err + return ContainerInfo{}, err + } + image, err = s.getImageWithFallback(ctx, req.ImageRef) + if err != nil { + return ContainerInfo{}, err } } snapshotID := req.SnapshotID @@ -233,9 +258,7 @@ func (s *DefaultService) CreateContainer(ctx context.Context, req CreateContaine oci.WithDefaultSpecForPlatform("linux/" + runtime.GOARCH), oci.WithImageConfig(image), } - if len(req.SpecOpts) > 0 { - specOpts = append(specOpts, req.SpecOpts...) - } + specOpts = append(specOpts, specOptsFromSpec(req.Spec)...) containerOpts := []containerd.NewContainerOpts{ containerd.WithImage(image), @@ -246,17 +269,17 @@ func (s *DefaultService) CreateContainer(ctx context.Context, req CreateContaine if req.Snapshotter != "" { parent, err := s.snapshotParentFromLayers(ctx, image) if err != nil { - return nil, err + return ContainerInfo{}, err } ok, err := s.snapshotExists(ctx, req.Snapshotter, parent) if err != nil { - return nil, err + return ContainerInfo{}, err } if !ok { - return nil, fmt.Errorf("parent snapshot %s does not exist", parent) + return ContainerInfo{}, fmt.Errorf("parent snapshot %s does not exist", parent) } if err := s.prepareSnapshot(ctx, req.Snapshotter, snapshotID, parent); err != nil { - return nil, err + return ContainerInfo{}, err } containerOpts = append(containerOpts, containerd.WithSnapshot(snapshotID)) } else { @@ -269,7 +292,11 @@ func (s *DefaultService) CreateContainer(ctx context.Context, req CreateContaine containerOpts = append(containerOpts, containerd.WithContainerLabels(req.Labels)) } - return s.client.NewContainer(ctx, req.ID, containerOpts...) + ctrObj, err := s.client.NewContainer(ctx, req.ID, containerOpts...) + if err != nil { + return ContainerInfo{}, err + } + return toContainerInfo(ctx, ctrObj) } func (s *DefaultService) snapshotParentFromLayers(ctx context.Context, image containerd.Image) (string, error) { @@ -340,20 +367,20 @@ func (s *DefaultService) prepareSnapshot(ctx context.Context, snapshotter, key, } func (s *DefaultService) getImageWithFallback(ctx context.Context, ref string) (containerd.Image, error) { - image, err := s.GetImage(ctx, ref) + image, err := s.client.GetImage(ctx, ref) if err == nil { return image, nil } if strings.HasPrefix(ref, "docker.io/library/") { alt := strings.TrimPrefix(ref, "docker.io/library/") - image, altErr := s.GetImage(ctx, alt) + image, altErr := s.client.GetImage(ctx, alt) if altErr == nil { return image, nil } } - images, listErr := s.ListImages(ctx) + imgs, listErr := s.client.ListImages(ctx) if listErr == nil { - for _, img := range images { + for _, img := range imgs { name := img.Name() if name == ref || strings.HasSuffix(ref, "/"+name) || strings.HasSuffix(name, "/"+ref) { return img, nil @@ -369,17 +396,33 @@ func (s *DefaultService) getImageWithFallback(ctx context.Context, ref string) ( return nil, err } -func (s *DefaultService) GetContainer(ctx context.Context, id string) (containerd.Container, error) { +func (s *DefaultService) GetContainer(ctx context.Context, id string) (ContainerInfo, error) { if id == "" { - return nil, ErrInvalidArgument + return ContainerInfo{}, ErrInvalidArgument } ctx = s.withNamespace(ctx) - return s.client.LoadContainer(ctx, id) + ctrObj, err := s.client.LoadContainer(ctx, id) + if err != nil { + return ContainerInfo{}, err + } + return toContainerInfo(ctx, ctrObj) } -func (s *DefaultService) ListContainers(ctx context.Context) ([]containerd.Container, error) { +func (s *DefaultService) ListContainers(ctx context.Context) ([]ContainerInfo, error) { ctx = s.withNamespace(ctx) - return s.client.Containers(ctx) + ctrs, err := s.client.Containers(ctx) + if err != nil { + return nil, err + } + result := make([]ContainerInfo, 0, len(ctrs)) + for _, c := range ctrs { + info, err := toContainerInfo(ctx, c) + if err != nil { + return nil, err + } + result = append(result, info) + } + return result, nil } func (s *DefaultService) DeleteContainer(ctx context.Context, id string, opts *DeleteContainerOptions) error { @@ -405,15 +448,15 @@ func (s *DefaultService) DeleteContainer(ctx context.Context, id string, opts *D return container.Delete(ctx, deleteOpts...) } -func (s *DefaultService) StartTask(ctx context.Context, containerID string, opts *StartTaskOptions) (containerd.Task, error) { +func (s *DefaultService) StartContainer(ctx context.Context, containerID string, opts *StartTaskOptions) error { if containerID == "" { - return nil, ErrInvalidArgument + return ErrInvalidArgument } ctx = s.withNamespace(ctx) container, err := s.client.LoadContainer(ctx, containerID) if err != nil { - return nil, err + return err } var ioCreator cio.Creator @@ -432,15 +475,12 @@ func (s *DefaultService) StartTask(ctx context.Context, containerID string, opts task, err := container.NewTask(ctx, ioCreator) if err != nil { - return nil, err + return err } - if err := task.Start(ctx); err != nil { - return nil, err - } - return task, nil + return task.Start(ctx) } -func (s *DefaultService) GetTask(ctx context.Context, containerID string) (containerd.Task, error) { +func (s *DefaultService) getTask(ctx context.Context, containerID string) (containerd.Task, error) { if containerID == "" { return nil, ErrInvalidArgument } @@ -453,6 +493,24 @@ func (s *DefaultService) GetTask(ctx context.Context, containerID string) (conta return container.Task(ctx, nil) } +func (s *DefaultService) GetTaskInfo(ctx context.Context, containerID string) (TaskInfo, error) { + task, err := s.getTask(ctx, containerID) + if err != nil { + return TaskInfo{}, err + } + status, err := task.Status(ctx) + if err != nil { + return TaskInfo{}, err + } + return TaskInfo{ + ContainerID: containerID, + ID: task.ID(), + PID: task.Pid(), + Status: convertTaskStatus(status.Status), + ExitCode: status.ExitStatus, + }, nil +} + func (s *DefaultService) ListTasks(ctx context.Context, opts *ListTasksOptions) ([]TaskInfo, error) { ctx = s.withNamespace(ctx) request := &tasksv1.ListTasksRequest{} @@ -471,21 +529,21 @@ func (s *DefaultService) ListTasks(ctx context.Context, opts *ListTasksOptions) ContainerID: task.ContainerID, ID: task.ID, PID: task.Pid, - Status: task.Status, - ExitStatus: task.ExitStatus, + Status: convertContainerdTaskStatus(task.Status), + ExitCode: task.ExitStatus, }) } return tasks, nil } -func (s *DefaultService) StopTask(ctx context.Context, containerID string, opts *StopTaskOptions) error { +func (s *DefaultService) StopContainer(ctx context.Context, containerID string, opts *StopTaskOptions) error { if containerID == "" { return ErrInvalidArgument } ctx = s.withNamespace(ctx) - task, err := s.GetTask(ctx, containerID) + task, err := s.getTask(ctx, containerID) if err != nil { return err } @@ -536,7 +594,7 @@ func (s *DefaultService) DeleteTask(ctx context.Context, containerID string, opt } ctx = s.withNamespace(ctx) - task, err := s.GetTask(ctx, containerID) + task, err := s.getTask(ctx, containerID) if err != nil { return err } @@ -582,7 +640,7 @@ func (s *DefaultService) ExecTask(ctx context.Context, containerID string, req E spec.Process.Terminal = true } - task, err := container.Task(ctx, nil) + task, err := s.getTask(ctx, containerID) if err != nil { return ExecTaskResult{}, err } @@ -659,7 +717,7 @@ func (s *DefaultService) ExecTaskStreaming(ctx context.Context, containerID stri spec.Process.Terminal = true } - task, err := container.Task(ctx, nil) + task, err := s.getTask(ctx, containerID) if err != nil { return nil, err } @@ -767,7 +825,7 @@ func resolveExecFIFODir(preferred string) (string, error) { return "", lastErr } -func (s *DefaultService) ListContainersByLabel(ctx context.Context, key, value string) ([]containerd.Container, error) { +func (s *DefaultService) ListContainersByLabel(ctx context.Context, key, value string) ([]ContainerInfo, error) { if key == "" { return nil, ErrInvalidArgument } @@ -778,14 +836,14 @@ func (s *DefaultService) ListContainersByLabel(ctx context.Context, key, value s return nil, err } - filtered := make([]containerd.Container, 0, len(containers)) + filtered := make([]ContainerInfo, 0, len(containers)) for _, container := range containers { - info, err := container.Info(ctx) + ci, err := toContainerInfo(ctx, container) if err != nil { return nil, err } - if labelValue, ok := info.Labels[key]; ok && (value == "" || value == labelValue) { - filtered = append(filtered, container) + if labelValue, ok := ci.Labels[key]; ok && (value == "" || value == labelValue) { + filtered = append(filtered, ci) } } return filtered, nil @@ -799,14 +857,21 @@ func (s *DefaultService) CommitSnapshot(ctx context.Context, snapshotter, name, return s.client.SnapshotService(snapshotter).Commit(ctx, name, key) } -func (s *DefaultService) ListSnapshots(ctx context.Context, snapshotter string) ([]snapshots.Info, error) { +func (s *DefaultService) ListSnapshots(ctx context.Context, snapshotter string) ([]SnapshotInfo, error) { if snapshotter == "" { return nil, ErrInvalidArgument } ctx = s.withNamespace(ctx) - infos := []snapshots.Info{} + var infos []SnapshotInfo if err := s.client.SnapshotService(snapshotter).Walk(ctx, func(ctx context.Context, info snapshots.Info) error { - infos = append(infos, info) + infos = append(infos, SnapshotInfo{ + Name: info.Name, + Parent: info.Parent, + Kind: info.Kind.String(), + Created: info.Created, + Updated: info.Updated, + Labels: info.Labels, + }) return nil }); err != nil { return nil, err @@ -823,26 +888,30 @@ func (s *DefaultService) PrepareSnapshot(ctx context.Context, snapshotter, key, return err } -func (s *DefaultService) CreateContainerFromSnapshot(ctx context.Context, req CreateContainerRequest) (containerd.Container, error) { +func (s *DefaultService) CreateContainerFromSnapshot(ctx context.Context, req CreateContainerRequest) (ContainerInfo, error) { if req.ID == "" || req.SnapshotID == "" { - return nil, ErrInvalidArgument + return ContainerInfo{}, ErrInvalidArgument } ctx = s.withNamespace(ctx) imageRef := req.ImageRef if imageRef == "" { - return nil, ErrInvalidArgument + return ContainerInfo{}, ErrInvalidArgument } - image, err := s.GetImage(ctx, imageRef) + image, err := s.getImageWithFallback(ctx, imageRef) if err != nil { - image, err = s.PullImage(ctx, imageRef, &PullImageOptions{ + _, pullErr := s.PullImage(ctx, imageRef, &PullImageOptions{ Unpack: true, Snapshotter: req.Snapshotter, }) + if pullErr != nil { + return ContainerInfo{}, pullErr + } + image, err = s.getImageWithFallback(ctx, imageRef) if err != nil { - return nil, err + return ContainerInfo{}, err } } @@ -850,9 +919,7 @@ func (s *DefaultService) CreateContainerFromSnapshot(ctx context.Context, req Cr oci.WithDefaultSpecForPlatform("linux/" + runtime.GOARCH), oci.WithImageConfig(image), } - if len(req.SpecOpts) > 0 { - specOpts = append(specOpts, req.SpecOpts...) - } + specOpts = append(specOpts, specOptsFromSpec(req.Spec)...) containerOpts := []containerd.NewContainerOpts{ containerd.WithImage(image), @@ -871,17 +938,106 @@ func (s *DefaultService) CreateContainerFromSnapshot(ctx context.Context, req Cr runtimeName := "io.containerd.runc.v2" containerOpts = append(containerOpts, containerd.WithRuntime(runtimeName, nil)) - return s.client.NewContainer(ctx, req.ID, containerOpts...) + ctrObj, err := s.client.NewContainer(ctx, req.ID, containerOpts...) + if err != nil { + return ContainerInfo{}, err + } + return toContainerInfo(ctx, ctrObj) } -func (s *DefaultService) SnapshotMounts(ctx context.Context, snapshotter, key string) ([]mount.Mount, error) { +func (s *DefaultService) SnapshotMounts(ctx context.Context, snapshotter, key string) ([]MountInfo, error) { if snapshotter == "" || key == "" { return nil, ErrInvalidArgument } ctx = s.withNamespace(ctx) - return s.client.SnapshotService(snapshotter).Mounts(ctx, key) + mounts, err := s.client.SnapshotService(snapshotter).Mounts(ctx, key) + if err != nil { + return nil, err + } + result := make([]MountInfo, len(mounts)) + for i, m := range mounts { + result[i] = MountInfo{ + Type: m.Type, + Source: m.Source, + Options: m.Options, + } + } + return result, nil +} + +func (s *DefaultService) SetupNetwork(ctx context.Context, req NetworkSetupRequest) error { + ctx = s.withNamespace(ctx) + task, err := s.getTask(ctx, req.ContainerID) + if err != nil { + return err + } + return setupCNINetwork(ctx, task, req.ContainerID, req.CNIBinDir, req.CNIConfDir) +} + +func (s *DefaultService) RemoveNetwork(ctx context.Context, req NetworkSetupRequest) error { + ctx = s.withNamespace(ctx) + task, err := s.getTask(ctx, req.ContainerID) + if err != nil { + return err + } + return removeCNINetwork(ctx, task, req.ContainerID, req.CNIBinDir, req.CNIConfDir) } func (s *DefaultService) withNamespace(ctx context.Context) context.Context { return namespaces.WithNamespace(ctx, s.namespace) } + +func toImageInfo(img containerd.Image) ImageInfo { + return ImageInfo{ + Name: img.Name(), + ID: img.Target().Digest.String(), + Tags: []string{img.Name()}, + } +} + +func toContainerInfo(ctx context.Context, c containerd.Container) (ContainerInfo, error) { + info, err := c.Info(ctx) + if err != nil { + return ContainerInfo{}, err + } + return ContainerInfo{ + ID: info.ID, + Image: info.Image, + Labels: info.Labels, + Snapshotter: info.Snapshotter, + SnapshotKey: info.SnapshotKey, + Runtime: RuntimeInfo{Name: info.Runtime.Name}, + CreatedAt: info.CreatedAt, + UpdatedAt: info.UpdatedAt, + }, nil +} + +func convertTaskStatus(s containerd.ProcessStatus) TaskStatus { + switch s { + case containerd.Running: + return TaskStatusRunning + case containerd.Created: + return TaskStatusCreated + case containerd.Stopped: + return TaskStatusStopped + case containerd.Paused, containerd.Pausing: + return TaskStatusPaused + default: + return TaskStatusUnknown + } +} + +func convertContainerdTaskStatus(s tasktypes.Status) TaskStatus { + switch s { + case tasktypes.Status_RUNNING: + return TaskStatusRunning + case tasktypes.Status_CREATED: + return TaskStatusCreated + case tasktypes.Status_STOPPED: + return TaskStatusStopped + case tasktypes.Status_PAUSED, tasktypes.Status_PAUSING: + return TaskStatusPaused + default: + return TaskStatusUnknown + } +} diff --git a/internal/containerd/service_apple.go b/internal/containerd/service_apple.go new file mode 100644 index 00000000..282d3ca7 --- /dev/null +++ b/internal/containerd/service_apple.go @@ -0,0 +1,510 @@ +package containerd + +import ( + "context" + "fmt" + "io" + "log/slog" + "os" + "path/filepath" + "strings" + "sync" + "syscall" + + "github.com/memohai/acgo" + "github.com/memohai/acgo/socktainer" +) + +// --------------------------------------------------------------------------- +// Service & lifecycle +// --------------------------------------------------------------------------- + +type AppleService struct { + client *acgo.Client + manager *socktainer.Manager + managerOpts []socktainer.Option + socketPath string + logger *slog.Logger + mu sync.Mutex +} + +type AppleServiceConfig struct { + SocketPath string + BinaryPath string +} + +func NewAppleService(ctx context.Context, log *slog.Logger, cfg AppleServiceConfig) (*AppleService, error) { + var managerOpts []socktainer.Option + if cfg.BinaryPath != "" { + managerOpts = append(managerOpts, socktainer.WithBinary(cfg.BinaryPath)) + } + if cfg.SocketPath != "" { + managerOpts = append(managerOpts, socktainer.WithSocket(expandHome(cfg.SocketPath))) + } + + svc := &AppleService{ + managerOpts: managerOpts, + logger: log.With(slog.String("service", "apple-container")), + } + if err := svc.startSocktainer(ctx); err != nil { + return nil, err + } + return svc, nil +} + +func (s *AppleService) startSocktainer(ctx context.Context) error { + mgr := socktainer.NewManager(s.managerOpts...) + if err := mgr.Start(ctx); err != nil { + return fmt.Errorf("start socktainer: %w", err) + } + client, err := acgo.New(acgo.WithSocketPath(mgr.SocketPath())) + if err != nil { + _ = mgr.Stop() + return fmt.Errorf("create acgo client: %w", err) + } + s.manager = mgr + s.client = client + s.socketPath = mgr.SocketPath() + return nil +} + +func (s *AppleService) ensureHealthy(ctx context.Context) error { + if ok, _ := s.client.IsServing(ctx); ok { + return nil + } + s.mu.Lock() + defer s.mu.Unlock() + if ok, _ := s.client.IsServing(ctx); ok { + return nil + } + s.logger.Warn("socktainer not responding, restarting") + _ = s.client.Close() + _ = s.manager.Stop() + _ = os.Remove(s.socketPath) + if err := s.startSocktainer(ctx); err != nil { + s.logger.Error("socktainer restart failed", slog.Any("error", err)) + return err + } + s.logger.Info("socktainer restarted successfully") + return nil +} + +func (s *AppleService) Close() error { + _ = s.client.Close() + return s.manager.Stop() +} + +// --------------------------------------------------------------------------- +// Images +// --------------------------------------------------------------------------- + +func (s *AppleService) PullImage(ctx context.Context, ref string, opts *PullImageOptions) (ImageInfo, error) { + if ref == "" { + return ImageInfo{}, ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return ImageInfo{}, err + } + img, err := s.client.Pull(ctx, ref) + if err != nil { + return ImageInfo{}, err + } + return toAcgoImageInfo(img), nil +} + +func (s *AppleService) GetImage(ctx context.Context, ref string) (ImageInfo, error) { + if ref == "" { + return ImageInfo{}, ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return ImageInfo{}, err + } + img, err := s.client.GetImage(ctx, ref) + if err != nil { + return ImageInfo{}, err + } + return toAcgoImageInfo(img), nil +} + +func (s *AppleService) ListImages(ctx context.Context) ([]ImageInfo, error) { + if err := s.ensureHealthy(ctx); err != nil { + return nil, err + } + imgs, err := s.client.ListImages(ctx) + if err != nil { + return nil, err + } + out := make([]ImageInfo, len(imgs)) + for i, img := range imgs { + out[i] = toAcgoImageInfo(img) + } + return out, nil +} + +func (s *AppleService) DeleteImage(ctx context.Context, ref string, opts *DeleteImageOptions) error { + if ref == "" { + return ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return err + } + return s.client.DeleteImage(ctx, ref) +} + +// --------------------------------------------------------------------------- +// Containers +// --------------------------------------------------------------------------- + +func (s *AppleService) CreateContainer(ctx context.Context, req CreateContainerRequest) (ContainerInfo, error) { + if req.ID == "" || req.ImageRef == "" { + return ContainerInfo{}, ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return ContainerInfo{}, err + } + if _, err := s.client.GetImage(ctx, req.ImageRef); err != nil { + s.logger.Info("image not found locally, pulling", slog.String("image", req.ImageRef)) + if _, pullErr := s.client.Pull(ctx, req.ImageRef); pullErr != nil { + return ContainerInfo{}, fmt.Errorf("pull image %s: %w", req.ImageRef, pullErr) + } + } + ctr, err := s.client.NewContainer(ctx, req.ID, specToCreateOpts(req)...) + if err != nil { + return ContainerInfo{}, err + } + return acgoContainerToInfo(ctx, ctr) +} + +func (s *AppleService) GetContainer(ctx context.Context, id string) (ContainerInfo, error) { + if id == "" { + return ContainerInfo{}, ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return ContainerInfo{}, err + } + ctr, err := s.client.LoadContainer(ctx, id) + if err != nil { + return ContainerInfo{}, err + } + return acgoContainerToInfo(ctx, ctr) +} + +func (s *AppleService) ListContainers(ctx context.Context) ([]ContainerInfo, error) { + if err := s.ensureHealthy(ctx); err != nil { + return nil, err + } + ctrs, err := s.client.Containers(ctx, acgo.WithListAll()) + if err != nil { + return nil, err + } + out := make([]ContainerInfo, 0, len(ctrs)) + for _, c := range ctrs { + info, err := acgoContainerToInfo(ctx, c) + if err != nil { + return nil, err + } + out = append(out, info) + } + return out, nil +} + +func (s *AppleService) DeleteContainer(ctx context.Context, id string, opts *DeleteContainerOptions) error { + if id == "" { + return ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return err + } + ctr, err := s.client.LoadContainer(ctx, id) + if err != nil { + return err + } + var deleteOpts []acgo.DeleteOpt + if opts != nil && opts.CleanupSnapshot { + deleteOpts = append(deleteOpts, acgo.WithRemoveVolumes()) + } + deleteOpts = append(deleteOpts, acgo.WithForceDelete()) + return ctr.Delete(ctx, deleteOpts...) +} + +func (s *AppleService) ListContainersByLabel(ctx context.Context, key, value string) ([]ContainerInfo, error) { + if key == "" { + return nil, ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return nil, err + } + filtersJSON := fmt.Sprintf(`{"label":["%s=%s"]}`, key, value) + ctrs, err := s.client.Containers(ctx, acgo.WithListAll(), acgo.WithListFilters(filtersJSON)) + if err != nil { + return nil, err + } + var out []ContainerInfo + for _, c := range ctrs { + info, err := acgoContainerToInfo(ctx, c) + if err != nil { + return nil, err + } + if v, ok := info.Labels[key]; ok && (value == "" || v == value) { + out = append(out, info) + } + } + return out, nil +} + +// --------------------------------------------------------------------------- +// Task / process lifecycle +// --------------------------------------------------------------------------- + +func (s *AppleService) StartContainer(ctx context.Context, containerID string, opts *StartTaskOptions) error { + if containerID == "" { + return ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return err + } + ctr, err := s.client.LoadContainer(ctx, containerID) + if err != nil { + return err + } + return ctr.Start(ctx) +} + +func (s *AppleService) StopContainer(ctx context.Context, containerID string, opts *StopTaskOptions) error { + if containerID == "" { + return ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return err + } + ctr, err := s.client.LoadContainer(ctx, containerID) + if err != nil { + return err + } + timeout := 10 + if opts != nil && opts.Timeout > 0 { + timeout = int(opts.Timeout.Seconds()) + } + var stopOpts []acgo.StopOpt + stopOpts = append(stopOpts, acgo.WithStopTimeout(timeout)) + if opts != nil && opts.Signal != 0 { + stopOpts = append(stopOpts, acgo.WithStopSignal(syscall.Signal(opts.Signal).String())) + } + if err := ctr.Stop(ctx, stopOpts...); err != nil && opts != nil && opts.Force { + return ctr.Kill(ctx) + } + return nil +} + +func (s *AppleService) DeleteTask(context.Context, string, *DeleteTaskOptions) error { + return nil +} + +func (s *AppleService) GetTaskInfo(ctx context.Context, containerID string) (TaskInfo, error) { + if containerID == "" { + return TaskInfo{}, ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return TaskInfo{}, err + } + ctr, err := s.client.LoadContainer(ctx, containerID) + if err != nil { + return TaskInfo{}, err + } + info, err := ctr.Info(ctx) + if err != nil { + return TaskInfo{}, err + } + return TaskInfo{ + ContainerID: containerID, + ID: containerID, + Status: containerStateToTaskStatus(info.State), + }, nil +} + +func (s *AppleService) ListTasks(ctx context.Context, opts *ListTasksOptions) ([]TaskInfo, error) { + if err := s.ensureHealthy(ctx); err != nil { + return nil, err + } + ctrs, err := s.client.Containers(ctx, acgo.WithListAll()) + if err != nil { + return nil, err + } + var out []TaskInfo + for _, c := range ctrs { + info, err := c.Info(ctx) + if err != nil { + continue + } + if opts != nil && opts.Filter != "" { + if strings.Contains(opts.Filter, "container.id==") { + if strings.TrimPrefix(opts.Filter, "container.id==") != info.ID { + continue + } + } + } + out = append(out, TaskInfo{ + ContainerID: info.ID, + ID: info.ID, + Status: containerStateToTaskStatus(info.State), + }) + } + return out, nil +} + +// ExecTask executes a command inside the container. +// +// Limitations compared to the containerd backend: +// - WorkDir: the Apple Container exec API (ExecCreateRequest) has no working-directory +// field; req.WorkDir is silently ignored. +// - Env: similarly, environment variables cannot be injected at exec time via this +// API; req.Env is silently ignored. +// - Stdin: the acgo exec interface does not expose a write channel, so req.Stdin +// is not connected and the process receives no stdin input. +// - Stderr: the Apple Container API returns stdout and stderr as a single combined +// stream; they cannot be routed to separate writers. The combined output is sent +// to req.Stdout when set, otherwise to req.Stderr when set, otherwise discarded. +// - FIFODir: a containerd-specific concept; not applicable here. +func (s *AppleService) ExecTask(ctx context.Context, containerID string, req ExecTaskRequest) (ExecTaskResult, error) { + if containerID == "" || len(req.Args) == 0 { + return ExecTaskResult{}, ErrInvalidArgument + } + if err := s.ensureHealthy(ctx); err != nil { + return ExecTaskResult{}, err + } + ctr, err := s.client.LoadContainer(ctx, containerID) + if err != nil { + return ExecTaskResult{}, err + } + var execOpts []acgo.ExecOpt + if req.Terminal { + execOpts = append(execOpts, acgo.WithExecTTY()) + } + result, err := ctr.Exec(ctx, req.Args, execOpts...) + if err != nil { + return ExecTaskResult{}, err + } + if result.Output != nil { + dest := req.Stdout + if dest == nil { + dest = req.Stderr + } + _, _ = io.Copy(dest, result.Output) + _ = result.Output.Close() + } + return ExecTaskResult{ExitCode: 0}, nil +} + +func (s *AppleService) ExecTaskStreaming(context.Context, string, ExecTaskRequest) (*ExecTaskSession, error) { + return nil, ErrNotSupported +} + +// --------------------------------------------------------------------------- +// Network (no-op — Apple Container handles networking natively) +// --------------------------------------------------------------------------- + +func (s *AppleService) SetupNetwork(context.Context, NetworkSetupRequest) error { return nil } +func (s *AppleService) RemoveNetwork(context.Context, NetworkSetupRequest) error { return nil } + +// --------------------------------------------------------------------------- +// Snapshots (not supported on Apple Container) +// --------------------------------------------------------------------------- + +func (s *AppleService) CommitSnapshot(context.Context, string, string, string) error { + return ErrNotSupported +} +func (s *AppleService) ListSnapshots(context.Context, string) ([]SnapshotInfo, error) { + return nil, ErrNotSupported +} +func (s *AppleService) PrepareSnapshot(context.Context, string, string, string) error { + return ErrNotSupported +} +func (s *AppleService) CreateContainerFromSnapshot(context.Context, CreateContainerRequest) (ContainerInfo, error) { + return ContainerInfo{}, ErrNotSupported +} +func (s *AppleService) SnapshotMounts(context.Context, string, string) ([]MountInfo, error) { + return nil, ErrNotSupported +} + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +func specToCreateOpts(req CreateContainerRequest) []acgo.CreateOpt { + var opts []acgo.CreateOpt + opts = append(opts, acgo.WithImage(req.ImageRef)) + if len(req.Spec.Cmd) > 0 { + opts = append(opts, acgo.WithEntrypoint(req.Spec.Cmd[0])) + if len(req.Spec.Cmd) > 1 { + opts = append(opts, acgo.WithCmd(req.Spec.Cmd[1:]...)) + } + } + if req.Spec.WorkDir != "" { + opts = append(opts, acgo.WithWorkdir(req.Spec.WorkDir)) + } + if req.Spec.User != "" { + opts = append(opts, acgo.WithUser(req.Spec.User)) + } + if req.Spec.TTY { + opts = append(opts, acgo.WithTTY()) + } + for _, env := range req.Spec.Env { + if k, v, ok := strings.Cut(env, "="); ok { + opts = append(opts, acgo.WithEnv(k, v)) + } + } + for _, m := range req.Spec.Mounts { + opts = append(opts, acgo.WithVolume(m.Source, m.Destination)) + } + for _, dns := range req.Spec.DNS { + opts = append(opts, acgo.WithDNS(dns)) + } + for k, v := range req.Labels { + opts = append(opts, acgo.WithLabel(k, v)) + } + return opts +} + +func toAcgoImageInfo(img acgo.Image) ImageInfo { + return ImageInfo{Name: img.Name(), ID: img.ID(), Tags: img.RepoTags()} +} + +func acgoContainerToInfo(ctx context.Context, c acgo.Container) (ContainerInfo, error) { + info, err := c.Info(ctx) + if err != nil { + return ContainerInfo{}, err + } + return ContainerInfo{ + ID: info.ID, + Image: info.Image, + Labels: info.Labels, + Runtime: RuntimeInfo{Name: "apple-container"}, + CreatedAt: info.CreatedAt, + UpdatedAt: info.CreatedAt, + }, nil +} + +func containerStateToTaskStatus(state string) TaskStatus { + switch state { + case "running": + return TaskStatusRunning + case "created": + return TaskStatusCreated + case "exited", "dead": + return TaskStatusStopped + case "paused": + return TaskStatusPaused + default: + return TaskStatusUnknown + } +} + +func expandHome(path string) string { + if !strings.HasPrefix(path, "~/") { + return path + } + if home, err := os.UserHomeDir(); err == nil { + return filepath.Join(home, path[2:]) + } + return path +} diff --git a/internal/containerd/timezone.go b/internal/containerd/timezone.go index 25fba758..44c77093 100644 --- a/internal/containerd/timezone.go +++ b/internal/containerd/timezone.go @@ -2,25 +2,23 @@ package containerd import ( "os" - - "github.com/containerd/containerd/v2/pkg/oci" - "github.com/opencontainers/runtime-spec/specs-go" ) -// TimezoneSpecOpts returns OCI spec options that propagate the host timezone -// into the container via /etc/localtime bind-mount and TZ environment variable. -func TimezoneSpecOpts() []oci.SpecOpts { - var opts []oci.SpecOpts +// TimezoneSpec returns mount specs and environment variables that propagate the host +// timezone into the container via /etc/localtime bind-mount and TZ environment variable. +func TimezoneSpec() ([]MountSpec, []string) { + var mounts []MountSpec + var env []string if _, err := os.Stat("/etc/localtime"); err == nil { - opts = append(opts, oci.WithMounts([]specs.Mount{{ + mounts = append(mounts, MountSpec{ Destination: "/etc/localtime", Type: "bind", Source: "/etc/localtime", Options: []string{"rbind", "ro"}, - }})) + }) } if tz := os.Getenv("TZ"); tz != "" { - opts = append(opts, oci.WithEnv([]string{"TZ=" + tz})) + env = append(env, "TZ="+tz) } - return opts + return mounts, env } diff --git a/internal/containerd/timezone_test.go b/internal/containerd/timezone_test.go index 29f7134f..650d8da7 100644 --- a/internal/containerd/timezone_test.go +++ b/internal/containerd/timezone_test.go @@ -5,32 +5,26 @@ import ( "testing" ) -func TestTimezoneSpecOpts_WithTZ(t *testing.T) { +func TestTimezoneSpec_WithTZ(t *testing.T) { t.Setenv("TZ", "Asia/Shanghai") - opts := TimezoneSpecOpts() + mounts, env := TimezoneSpec() if _, err := os.Stat("/etc/localtime"); err == nil { - if len(opts) < 1 { - t.Fatal("expected at least mount opt when /etc/localtime exists") + if len(mounts) < 1 { + t.Fatal("expected at least one mount when /etc/localtime exists") } } - found := false - for range opts { - found = true - } - if !found { - t.Fatal("expected at least one spec opt when TZ is set") + if len(env) == 0 { + t.Fatal("expected at least one env var when TZ is set") } } -func TestTimezoneSpecOpts_WithoutTZ(t *testing.T) { +func TestTimezoneSpec_WithoutTZ(t *testing.T) { t.Setenv("TZ", "") - opts := TimezoneSpecOpts() - for _, opt := range opts { - if opt == nil { - t.Fatal("unexpected nil spec opt") - } + mounts, env := TimezoneSpec() + if len(env) != 0 { + t.Fatalf("expected no env when TZ empty, got %d", len(env)) } - if _, err := os.Stat("/etc/localtime"); err != nil && len(opts) != 0 { - t.Fatalf("expected no opts when /etc/localtime absent and TZ empty, got %d", len(opts)) + if _, err := os.Stat("/etc/localtime"); err != nil && len(mounts) != 0 { + t.Fatalf("expected no mounts when /etc/localtime absent and TZ empty, got %d", len(mounts)) } } diff --git a/internal/containerd/types.go b/internal/containerd/types.go new file mode 100644 index 00000000..6b1c3193 --- /dev/null +++ b/internal/containerd/types.go @@ -0,0 +1,127 @@ +package containerd + +import ( + "errors" + "io" + "time" +) + +var ErrNotSupported = errors.New("operation not supported on this backend") + +type TaskStatus int + +const ( + TaskStatusUnknown TaskStatus = iota + TaskStatusCreated + TaskStatusRunning + TaskStatusStopped + TaskStatusPaused +) + +func (s TaskStatus) String() string { + switch s { + case TaskStatusCreated: + return "CREATED" + case TaskStatusRunning: + return "RUNNING" + case TaskStatusStopped: + return "STOPPED" + case TaskStatusPaused: + return "PAUSED" + default: + return "UNKNOWN" + } +} + +type ContainerInfo struct { + ID string + Image string + Labels map[string]string + Snapshotter string + SnapshotKey string + Runtime RuntimeInfo + CreatedAt time.Time + UpdatedAt time.Time +} + +type RuntimeInfo struct { + Name string +} + +type ImageInfo struct { + Name string + ID string + Tags []string +} + +type TaskInfo struct { + ContainerID string + ID string + PID uint32 + Status TaskStatus + ExitCode uint32 +} + +type SnapshotInfo struct { + Name string + Parent string + Kind string + Created time.Time + Updated time.Time + Labels map[string]string +} + +type MountInfo struct { + Type string + Source string + Target string + Options []string +} + +type MountSpec struct { + Destination string + Type string + Source string + Options []string +} + +type ContainerSpec struct { + Cmd []string + Env []string + WorkDir string + User string + Mounts []MountSpec + DNS []string + TTY bool +} + +type NetworkSetupRequest struct { + ContainerID string + PID uint32 + CNIBinDir string + CNIConfDir string +} + +type ExecTaskRequest struct { + Args []string + Env []string + WorkDir string + Terminal bool + UseStdio bool + FIFODir string + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer +} + +type ExecTaskSession struct { + Stdin io.WriteCloser + Stdout io.ReadCloser + Stderr io.ReadCloser + Wait func() (ExecTaskResult, error) + Close func() error +} + +type ExecTaskResult struct { + ExitCode uint32 +} diff --git a/internal/handlers/containerd.go b/internal/handlers/containerd.go index dc56ca94..fc8d8334 100644 --- a/internal/handlers/containerd.go +++ b/internal/handlers/containerd.go @@ -13,16 +13,11 @@ import ( "sync" "time" - tasktypes "github.com/containerd/containerd/api/types/task" - "github.com/containerd/containerd/v2/core/snapshots" - "github.com/containerd/containerd/v2/pkg/namespaces" - "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/errdefs" "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "github.com/labstack/echo/v4" - "github.com/opencontainers/runtime-spec/specs-go" "github.com/memohai/memoh/internal/accounts" "github.com/memohai/memoh/internal/bots" @@ -35,20 +30,21 @@ import ( ) type ContainerdHandler struct { - service ctr.Service - manager *mcp.Manager - cfg config.MCPConfig - namespace string - logger *slog.Logger - toolGateway *mcp.ToolGatewayService - mcpMu sync.Mutex - mcpSess map[string]*mcpSession - mcpStdioMu sync.Mutex - mcpStdioSess map[string]*mcpStdioSession - botService *bots.Service - accountService *accounts.Service - policyService *policy.Service - queries *dbsqlc.Queries + service ctr.Service + manager *mcp.Manager + cfg config.MCPConfig + namespace string + containerBackend string + logger *slog.Logger + toolGateway *mcp.ToolGatewayService + mcpMu sync.Mutex + mcpSess map[string]*mcpSession + mcpStdioMu sync.Mutex + mcpStdioSess map[string]*mcpStdioSession + botService *bots.Service + accountService *accounts.Service + policyService *policy.Service + queries *dbsqlc.Queries } type CreateContainerRequest struct { @@ -104,19 +100,20 @@ type ListSnapshotsResponse struct { Snapshots []SnapshotInfo `json:"snapshots"` } -func NewContainerdHandler(log *slog.Logger, service ctr.Service, manager *mcp.Manager, cfg config.MCPConfig, namespace string, botService *bots.Service, accountService *accounts.Service, policyService *policy.Service, queries *dbsqlc.Queries) *ContainerdHandler { +func NewContainerdHandler(log *slog.Logger, service ctr.Service, manager *mcp.Manager, cfg config.MCPConfig, namespace string, containerBackend string, botService *bots.Service, accountService *accounts.Service, policyService *policy.Service, queries *dbsqlc.Queries) *ContainerdHandler { return &ContainerdHandler{ - service: service, - manager: manager, - cfg: cfg, - namespace: namespace, - logger: log.With(slog.String("handler", "containerd")), - mcpSess: make(map[string]*mcpSession), - mcpStdioSess: make(map[string]*mcpStdioSession), - botService: botService, - accountService: accountService, - policyService: policyService, - queries: queries, + service: service, + manager: manager, + cfg: cfg, + namespace: namespace, + containerBackend: containerBackend, + logger: log.With(slog.String("handler", "containerd")), + mcpSess: make(map[string]*mcpSession), + mcpStdioSess: make(map[string]*mcpStdioSession), + botService: botService, + accountService: accountService, + policyService: policyService, + queries: queries, } } @@ -176,9 +173,6 @@ func (h *ContainerdHandler) CreateContainer(c echo.Context) error { } ctx := c.Request().Context() - if strings.TrimSpace(h.namespace) != "" { - ctx = namespaces.WithNamespace(ctx, h.namespace) - } dataRoot := strings.TrimSpace(h.cfg.DataRoot) if dataRoot == "" { dataRoot = config.DefaultDataRoot @@ -203,24 +197,7 @@ func (h *ContainerdHandler) CreateContainer(c echo.Context) error { return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } - specOpts := []oci.SpecOpts{ - oci.WithMounts([]specs.Mount{ - { - Destination: dataMount, - Type: "bind", - Source: dataDir, - Options: []string{"rbind", "rw"}, - }, - { - Destination: "/etc/resolv.conf", - Type: "bind", - Source: resolvPath, - Options: []string{"rbind", "ro"}, - }, - }), - oci.WithProcessArgs("/bin/sh", "-lc", fmt.Sprintf("bootstrap(){ [ -e /app/mcp ] || { mkdir -p /app; [ -f /opt/mcp ] && cp -a /opt/mcp /app/mcp 2>/dev/null || true; }; if [ -d /opt/mcp-template ]; then mkdir -p %q; for f in /opt/mcp-template/*; do name=$(basename \"$f\"); [ -e %q/\"$name\" ] || cp -a \"$f\" %q/\"$name\" 2>/dev/null || true; done; fi; }; bootstrap; exec /app/mcp", dataMount, dataMount, dataMount)), - } - specOpts = append(specOpts, ctr.TimezoneSpecOpts()...) + spec := h.buildMCPContainerSpec(dataDir, dataMount, resolvPath) _, err = h.service.CreateContainer(ctx, ctr.CreateContainerRequest{ ID: containerID, @@ -229,7 +206,7 @@ func (h *ContainerdHandler) CreateContainer(c echo.Context) error { Labels: map[string]string{ mcp.BotLabelKey: botID, }, - SpecOpts: specOpts, + Spec: spec, }) if err != nil && !errdefs.IsAlreadyExists(err) { return echo.NewHTTPError(http.StatusInternalServerError, "snapshotter="+snapshotter+" image="+image+" err="+err.Error()) @@ -260,11 +237,15 @@ func (h *ContainerdHandler) CreateContainer(c echo.Context) error { } started := false - if task, err := h.service.StartTask(ctx, containerID, &ctr.StartTaskOptions{ + if err := h.service.StartContainer(ctx, containerID, &ctr.StartTaskOptions{ UseStdio: false, }); err == nil { started = true - if netErr := ctr.SetupNetwork(ctx, task, containerID, h.cfg.CNIBinaryDir, h.cfg.CNIConfigDir); netErr != nil { + if netErr := h.service.SetupNetwork(ctx, ctr.NetworkSetupRequest{ + ContainerID: containerID, + CNIBinDir: h.cfg.CNIBinaryDir, + CNIConfDir: h.cfg.CNIConfigDir, + }); netErr != nil { h.logger.Warn("mcp container network setup failed, task kept running", slog.String("container_id", containerID), slog.Any("error", netErr), @@ -297,13 +278,11 @@ func (h *ContainerdHandler) CreateContainer(c echo.Context) error { // running. If the container is missing (e.g. after a VM restart) it is recreated via // SetupBotContainer. This prevents permanent desync between DB and containerd state. func (h *ContainerdHandler) ensureContainerAndTask(ctx context.Context, containerID, botID string) error { - // Check whether the container exists in containerd. _, err := h.service.GetContainer(ctx, containerID) if err != nil { if !errdefs.IsNotFound(err) { return err } - // Container gone — rebuild from scratch. h.logger.Warn("container missing in containerd, rebuilding", slog.String("bot_id", botID), slog.String("container_id", containerID), @@ -311,7 +290,6 @@ func (h *ContainerdHandler) ensureContainerAndTask(ctx context.Context, containe return h.SetupBotContainer(ctx, botID) } - // Container exists — make sure the task is running. tasks, err := h.service.ListTasks(ctx, &ctr.ListTasksOptions{ Filter: "container.id==" + containerID, }) @@ -319,14 +297,14 @@ func (h *ContainerdHandler) ensureContainerAndTask(ctx context.Context, containe return err } if len(tasks) > 0 { - if tasks[0].Status == tasktypes.Status_RUNNING { - // Task is running but CNI state may be stale (e.g. server container restarted). - // Re-apply network to ensure connectivity. - if task, taskErr := h.service.GetTask(ctx, containerID); taskErr == nil { - if netErr := ctr.SetupNetwork(ctx, task, containerID, h.cfg.CNIBinaryDir, h.cfg.CNIConfigDir); netErr != nil { - h.logger.Warn("network re-setup failed for running task", - slog.String("container_id", containerID), slog.Any("error", netErr)) - } + if tasks[0].Status == ctr.TaskStatusRunning { + if netErr := h.service.SetupNetwork(ctx, ctr.NetworkSetupRequest{ + ContainerID: containerID, + CNIBinDir: h.cfg.CNIBinaryDir, + CNIConfDir: h.cfg.CNIConfigDir, + }); netErr != nil { + h.logger.Warn("network re-setup failed for running task", + slog.String("container_id", containerID), slog.Any("error", netErr)) } return nil } @@ -335,13 +313,16 @@ func (h *ContainerdHandler) ensureContainerAndTask(ctx context.Context, containe } } - task, err := h.service.StartTask(ctx, containerID, &ctr.StartTaskOptions{ + if err := h.service.StartContainer(ctx, containerID, &ctr.StartTaskOptions{ UseStdio: false, - }) - if err != nil { + }); err != nil { return err } - if netErr := ctr.SetupNetwork(ctx, task, containerID, h.cfg.CNIBinaryDir, h.cfg.CNIConfigDir); netErr != nil { + if netErr := h.service.SetupNetwork(ctx, ctr.NetworkSetupRequest{ + ContainerID: containerID, + CNIBinDir: h.cfg.CNIBinaryDir, + CNIConfDir: h.cfg.CNIConfigDir, + }); netErr != nil { h.logger.Warn("network setup failed, task kept running", slog.String("container_id", containerID), slog.Any("error", netErr)) } @@ -363,7 +344,6 @@ func (h *ContainerdHandler) botContainerID(ctx context.Context, botID string) (s } } } - // Fallback: search by containerd label containers, err := h.service.ListContainersByLabel(ctx, mcp.BotLabelKey, botID) if err != nil { return "", err @@ -371,17 +351,9 @@ func (h *ContainerdHandler) botContainerID(ctx context.Context, botID string) (s if len(containers) == 0 { return "", echo.NewHTTPError(http.StatusNotFound, "container not found") } - infoCtx := ctx - if strings.TrimSpace(h.namespace) != "" { - infoCtx = namespaces.WithNamespace(ctx, h.namespace) - } bestID := "" var bestUpdated time.Time - for _, container := range containers { - info, err := container.Info(infoCtx) - if err != nil { - return "", err - } + for _, info := range containers { if bestID == "" || info.UpdatedAt.After(bestUpdated) { bestID = info.ID bestUpdated = info.UpdatedAt @@ -442,21 +414,13 @@ func (h *ContainerdHandler) GetContainer(c echo.Context) error { if err != nil { return echo.NewHTTPError(http.StatusNotFound, "container not found for bot") } - infoCtx := ctx - if strings.TrimSpace(h.namespace) != "" { - infoCtx = namespaces.WithNamespace(ctx, h.namespace) - } - container, err := h.service.GetContainer(infoCtx, containerID) + info, err := h.service.GetContainer(ctx, containerID) if err != nil { if errdefs.IsNotFound(err) { return echo.NewHTTPError(http.StatusNotFound, "container not found") } return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } - info, err := container.Info(infoCtx) - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) - } return c.JSON(http.StatusOK, GetContainerResponse{ ContainerID: info.ID, Image: info.Image, @@ -537,7 +501,7 @@ func (h *ContainerdHandler) StopContainer(c echo.Context) error { if err != nil { return echo.NewHTTPError(http.StatusNotFound, "container not found for bot") } - if err := h.service.StopTask(ctx, containerID, &ctr.StopTaskOptions{ + if err := h.service.StopContainer(ctx, containerID, &ctr.StopTaskOptions{ Timeout: 10 * time.Second, Force: true, }); err != nil && !errdefs.IsNotFound(err) { @@ -565,8 +529,12 @@ func (h *ContainerdHandler) StopContainer(c echo.Context) error { // @Success 200 {object} CreateSnapshotResponse // @Failure 404 {object} ErrorResponse // @Failure 500 {object} ErrorResponse +// @Failure 501 {object} ErrorResponse "Snapshots currently not supported on this backend" // @Router /bots/{bot_id}/container/snapshots [post] func (h *ContainerdHandler) CreateSnapshot(c echo.Context) error { + if h.containerBackend == "apple" { + return echo.NewHTTPError(http.StatusNotImplemented, "snapshots currently not supported on Apple Container backend") + } botID, err := h.requireBotAccess(c) if err != nil { return err @@ -600,8 +568,12 @@ func (h *ContainerdHandler) CreateSnapshot(c echo.Context) error { // @Param bot_id path string true "Bot ID" // @Param snapshotter query string false "Snapshotter name" // @Success 200 {object} ListSnapshotsResponse +// @Failure 501 {object} ErrorResponse "Snapshots currently not supported on this backend" // @Router /bots/{bot_id}/container/snapshots [get] func (h *ContainerdHandler) ListSnapshots(c echo.Context) error { + if h.containerBackend == "apple" { + return echo.NewHTTPError(http.StatusNotImplemented, "snapshots currently not supported on Apple Container backend") + } botID, err := h.requireBotAccess(c) if err != nil { return err @@ -611,21 +583,13 @@ func (h *ContainerdHandler) ListSnapshots(c echo.Context) error { if err != nil { return echo.NewHTTPError(http.StatusNotFound, "container not found for bot") } - container, err := h.service.GetContainer(ctx, containerID) + containerInfo, err := h.service.GetContainer(ctx, containerID) if err != nil { if errdefs.IsNotFound(err) { return echo.NewHTTPError(http.StatusNotFound, "container not found") } return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } - infoCtx := ctx - if strings.TrimSpace(h.namespace) != "" { - infoCtx = namespaces.WithNamespace(ctx, h.namespace) - } - containerInfo, err := container.Info(infoCtx) - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) - } requestedSnapshotter := strings.TrimSpace(c.QueryParam("snapshotter")) snapshotter := strings.TrimSpace(containerInfo.Snapshotter) @@ -650,7 +614,7 @@ func (h *ContainerdHandler) ListSnapshots(c echo.Context) error { if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } - runtimeByName := make(map[string]snapshots.Info, len(allSnapshots)) + runtimeByName := make(map[string]ctr.SnapshotInfo, len(allSnapshots)) for _, info := range allSnapshots { name := strings.TrimSpace(info.Name) if name == "" { @@ -685,7 +649,7 @@ func (h *ContainerdHandler) ListSnapshots(c echo.Context) error { items := make([]SnapshotInfo, 0, len(lineage)+len(metadataByName)) seen := make(map[string]struct{}, len(lineage)+len(metadataByName)) - appendRuntime := func(runtimeInfo snapshots.Info, fallbackSource string, meta *dbsqlc.ListSnapshotsWithVersionByContainerIDRow) { + appendRuntime := func(runtimeInfo ctr.SnapshotInfo, fallbackSource string, meta *dbsqlc.ListSnapshotsWithVersionByContainerIDRow) { source := fallbackSource managed := false var version *int @@ -703,7 +667,7 @@ func (h *ContainerdHandler) ListSnapshots(c echo.Context) error { Snapshotter: snapshotter, Name: runtimeInfo.Name, Parent: runtimeInfo.Parent, - Kind: runtimeInfo.Kind.String(), + Kind: runtimeInfo.Kind, CreatedAt: runtimeInfo.Created, UpdatedAt: runtimeInfo.Updated, Labels: runtimeInfo.Labels, @@ -751,12 +715,12 @@ func (h *ContainerdHandler) ListSnapshots(c echo.Context) error { }) } -func snapshotLineage(root string, all []snapshots.Info) ([]snapshots.Info, bool) { +func snapshotLineage(root string, all []ctr.SnapshotInfo) ([]ctr.SnapshotInfo, bool) { root = strings.TrimSpace(root) if root == "" { return nil, false } - index := make(map[string]snapshots.Info, len(all)) + index := make(map[string]ctr.SnapshotInfo, len(all)) for _, info := range all { name := strings.TrimSpace(info.Name) if name == "" { @@ -767,7 +731,7 @@ func snapshotLineage(root string, all []snapshots.Info) ([]snapshots.Info, bool) if _, ok := index[root]; !ok { return nil, false } - lineage := make([]snapshots.Info, 0, len(index)) + lineage := make([]ctr.SnapshotInfo, 0, len(index)) visited := make(map[string]struct{}, len(index)) current := root for current != "" { @@ -843,10 +807,6 @@ func (h *ContainerdHandler) SetupBotContainer(ctx context.Context, botID string) image := h.mcpImageRef() snapshotter := strings.TrimSpace(h.cfg.Snapshotter) - if strings.TrimSpace(h.namespace) != "" { - ctx = namespaces.WithNamespace(ctx, h.namespace) - } - dataRoot := strings.TrimSpace(h.cfg.DataRoot) if dataRoot == "" { dataRoot = config.DefaultDataRoot @@ -872,24 +832,7 @@ func (h *ContainerdHandler) SetupBotContainer(ctx context.Context, botID string) return err } - specOpts := []oci.SpecOpts{ - oci.WithMounts([]specs.Mount{ - { - Destination: dataMount, - Type: "bind", - Source: dataDir, - Options: []string{"rbind", "rw"}, - }, - { - Destination: "/etc/resolv.conf", - Type: "bind", - Source: resolvPath, - Options: []string{"rbind", "ro"}, - }, - }), - oci.WithProcessArgs("/bin/sh", "-lc", fmt.Sprintf("bootstrap(){ [ -e /app/mcp ] || { mkdir -p /app; [ -f /opt/mcp ] && cp -a /opt/mcp /app/mcp 2>/dev/null || true; }; if [ -d /opt/mcp-template ]; then mkdir -p %q; for f in /opt/mcp-template/*; do name=$(basename \"$f\"); [ -e %q/\"$name\" ] || cp -a \"$f\" %q/\"$name\" 2>/dev/null || true; done; fi; }; bootstrap; exec /app/mcp", dataMount, dataMount, dataMount)), - } - specOpts = append(specOpts, ctr.TimezoneSpecOpts()...) + spec := h.buildMCPContainerSpec(dataDir, dataMount, resolvPath) _, err = h.service.CreateContainer(ctx, ctr.CreateContainerRequest{ ID: containerID, @@ -898,7 +841,7 @@ func (h *ContainerdHandler) SetupBotContainer(ctx context.Context, botID string) Labels: map[string]string{ mcp.BotLabelKey: botID, }, - SpecOpts: specOpts, + Spec: spec, }) if err != nil && !errdefs.IsAlreadyExists(err) { return err @@ -928,10 +871,14 @@ func (h *ContainerdHandler) SetupBotContainer(ctx context.Context, botID string) } } - if task, err := h.service.StartTask(ctx, containerID, &ctr.StartTaskOptions{ + if err := h.service.StartContainer(ctx, containerID, &ctr.StartTaskOptions{ UseStdio: false, }); err == nil { - if netErr := ctr.SetupNetwork(ctx, task, containerID, h.cfg.CNIBinaryDir, h.cfg.CNIConfigDir); netErr != nil { + if netErr := h.service.SetupNetwork(ctx, ctr.NetworkSetupRequest{ + ContainerID: containerID, + CNIBinDir: h.cfg.CNIBinaryDir, + CNIConfDir: h.cfg.CNIConfigDir, + }); netErr != nil { h.logger.Warn("setup bot container: network setup failed, task kept running", slog.String("bot_id", botID), slog.String("container_id", containerID), @@ -981,14 +928,16 @@ func (h *ContainerdHandler) CleanupBotContainer(ctx context.Context, botID strin slog.String("container_id", containerID), ) - if task, taskErr := h.service.GetTask(ctx, containerID); taskErr == nil { - h.logger.Info("CleanupBotContainer: removing network", slog.String("container_id", containerID)) - if err := ctr.RemoveNetwork(ctx, task, containerID, h.cfg.CNIBinaryDir, h.cfg.CNIConfigDir); err != nil { - h.logger.Warn("cleanup: remove network failed", slog.String("container_id", containerID), slog.Any("error", err)) - } + h.logger.Info("CleanupBotContainer: removing network", slog.String("container_id", containerID)) + if err := h.service.RemoveNetwork(ctx, ctr.NetworkSetupRequest{ + ContainerID: containerID, + CNIBinDir: h.cfg.CNIBinaryDir, + CNIConfDir: h.cfg.CNIConfigDir, + }); err != nil { + h.logger.Warn("cleanup: remove network failed", slog.String("container_id", containerID), slog.Any("error", err)) } h.logger.Info("CleanupBotContainer: stopping task", slog.String("container_id", containerID)) - if err := h.service.StopTask(ctx, containerID, &ctr.StopTaskOptions{ + if err := h.service.StopContainer(ctx, containerID, &ctr.StopTaskOptions{ Timeout: 5 * time.Second, Force: true, }); err != nil { @@ -1027,7 +976,7 @@ func (h *ContainerdHandler) isTaskRunning(ctx context.Context, containerID strin tasks, err := h.service.ListTasks(ctx, &ctr.ListTasksOptions{ Filter: "container.id==" + containerID, }) - return err == nil && len(tasks) > 0 && tasks[0].Status == tasktypes.Status_RUNNING + return err == nil && len(tasks) > 0 && tasks[0].Status == ctr.TaskStatusRunning } // ReconcileContainers compares the DB containers table against actual containerd @@ -1086,19 +1035,15 @@ func (h *ContainerdHandler) ReconcileContainers(ctx context.Context) { slog.String("bot_id", botID), slog.Any("error", dbErr)) } } - // Re-apply CNI networking: server container restart drops cni0 bridge, - // veth endpoints and iptables masquerade rules while the MCP task keeps - // running inside containerd. - if task, taskErr := h.service.GetTask(ctx, containerID); taskErr == nil { - if netErr := ctr.SetupNetwork(ctx, task, containerID, h.cfg.CNIBinaryDir, h.cfg.CNIConfigDir); netErr != nil { - h.logger.Warn("reconcile: network re-setup failed for running task", - slog.String("bot_id", botID), - slog.String("container_id", containerID), - slog.Any("error", netErr)) - } - } else { - h.logger.Warn("reconcile: failed to get task for network re-setup", - slog.String("bot_id", botID), slog.Any("error", taskErr)) + if netErr := h.service.SetupNetwork(ctx, ctr.NetworkSetupRequest{ + ContainerID: containerID, + CNIBinDir: h.cfg.CNIBinaryDir, + CNIConfDir: h.cfg.CNIConfigDir, + }); netErr != nil { + h.logger.Warn("reconcile: network re-setup failed for running task", + slog.String("bot_id", botID), + slog.String("container_id", containerID), + slog.Any("error", netErr)) } h.logger.Info("reconcile: container healthy", slog.String("bot_id", botID), slog.String("container_id", containerID)) @@ -1125,6 +1070,38 @@ func (h *ContainerdHandler) ReconcileContainers(ctx context.Context) { h.logger.Info("reconcile: completed") } +func (h *ContainerdHandler) buildMCPContainerSpec(dataDir, dataMount, resolvPath string) ctr.ContainerSpec { + mounts := []ctr.MountSpec{ + { + Destination: dataMount, + Type: "bind", + Source: dataDir, + Options: []string{"rbind", "rw"}, + }, + { + Destination: "/etc/resolv.conf", + Type: "bind", + Source: resolvPath, + Options: []string{"rbind", "ro"}, + }, + } + tzMounts, tzEnv := ctr.TimezoneSpec() + mounts = append(mounts, tzMounts...) + + bootScript := fmt.Sprintf( + "[ -e /app/mcp ] || { mkdir -p /app; cp -a /opt/mcp /app/mcp 2>/dev/null; true; }; "+ + "cp -an /opt/mcp-template/* %s/ 2>/dev/null; true; "+ + "exec /app/mcp", + dataMount, + ) + + return ctr.ContainerSpec{ + Cmd: []string{"/bin/sh", "-c", bootScript}, + Env: tzEnv, + Mounts: mounts, + } +} + func (h *ContainerdHandler) ensureBotDataRoot(botID string) (string, error) { dataRoot := strings.TrimSpace(h.cfg.DataRoot) if dataRoot == "" { diff --git a/internal/handlers/containerd_snapshot_lineage_test.go b/internal/handlers/containerd_snapshot_lineage_test.go index a4423c67..149488e4 100644 --- a/internal/handlers/containerd_snapshot_lineage_test.go +++ b/internal/handlers/containerd_snapshot_lineage_test.go @@ -3,7 +3,7 @@ package handlers import ( "testing" - "github.com/containerd/containerd/v2/core/snapshots" + ctr "github.com/memohai/memoh/internal/containerd" ) func TestSnapshotLineage(t *testing.T) { @@ -12,14 +12,14 @@ func TestSnapshotLineage(t *testing.T) { tests := []struct { name string root string - input []snapshots.Info + input []ctr.SnapshotInfo wantFound bool wantNames []string }{ { name: "walk full snapshot ancestry", root: "active-3", - input: []snapshots.Info{ + input: []ctr.SnapshotInfo{ {Name: "active-3", Parent: "version-2"}, {Name: "version-2", Parent: "version-1"}, {Name: "version-1", Parent: "sha256:base-layer"}, @@ -32,7 +32,7 @@ func TestSnapshotLineage(t *testing.T) { { name: "root snapshot not found", root: "missing", - input: []snapshots.Info{ + input: []ctr.SnapshotInfo{ {Name: "active-1", Parent: "sha256:base-layer"}, {Name: "sha256:base-layer", Parent: ""}, }, @@ -42,7 +42,7 @@ func TestSnapshotLineage(t *testing.T) { { name: "missing parent keeps known chain", root: "active-1", - input: []snapshots.Info{ + input: []ctr.SnapshotInfo{ {Name: "active-1", Parent: "version-1"}, }, wantFound: true, @@ -51,7 +51,7 @@ func TestSnapshotLineage(t *testing.T) { { name: "cycle is bounded by visited set", root: "a", - input: []snapshots.Info{ + input: []ctr.SnapshotInfo{ {Name: "a", Parent: "b"}, {Name: "b", Parent: "a"}, }, diff --git a/internal/handlers/fs.go b/internal/handlers/fs.go index 04faf852..b7cff5db 100644 --- a/internal/handlers/fs.go +++ b/internal/handlers/fs.go @@ -14,7 +14,6 @@ import ( "strings" "sync" - "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/errdefs" "github.com/labstack/echo/v4" sdkjsonrpc "github.com/modelcontextprotocol/go-sdk/jsonrpc" @@ -28,22 +27,13 @@ func (h *ContainerdHandler) validateMCPContainer(ctx context.Context, containerI if strings.TrimSpace(botID) == "" { return echo.NewHTTPError(http.StatusBadRequest, "bot id is required") } - container, err := h.service.GetContainer(ctx, containerID) + info, err := h.service.GetContainer(ctx, containerID) if err != nil { if errdefs.IsNotFound(err) { return echo.NewHTTPError(http.StatusNotFound, "container not found") } return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } - - infoCtx := ctx - if strings.TrimSpace(h.namespace) != "" { - infoCtx = namespaces.WithNamespace(ctx, h.namespace) - } - info, err := container.Info(infoCtx) - if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) - } labelBotID := strings.TrimSpace(info.Labels[mcptools.BotLabelKey]) if labelBotID != "" && labelBotID != botID { return echo.NewHTTPError(http.StatusForbidden, "bot mismatch") diff --git a/internal/handlers/ping.go b/internal/handlers/ping.go index e21ff554..49f88b27 100644 --- a/internal/handlers/ping.go +++ b/internal/handlers/ping.go @@ -5,14 +5,25 @@ import ( "net/http" "github.com/labstack/echo/v4" + "github.com/memohai/memoh/internal/boot" ) -type PingHandler struct { - logger *slog.Logger +type PingResponse struct { + Status string `json:"status"` + ContainerBackend string `json:"container_backend"` + SnapshotSupported bool `json:"snapshot_supported"` } -func NewPingHandler(log *slog.Logger) *PingHandler { - return &PingHandler{logger: log.With(slog.String("handler", "ping"))} +type PingHandler struct { + logger *slog.Logger + runtime *boot.RuntimeConfig +} + +func NewPingHandler(log *slog.Logger, rc *boot.RuntimeConfig) *PingHandler { + return &PingHandler{ + logger: log.With(slog.String("handler", "ping")), + runtime: rc, + } } func (h *PingHandler) Register(e *echo.Echo) { @@ -20,9 +31,16 @@ func (h *PingHandler) Register(e *echo.Echo) { e.HEAD("/health", h.PingHead) } +// Ping godoc +// @Summary Health check with server capabilities +// @Tags system +// @Success 200 {object} PingResponse +// @Router /ping [get] func (h *PingHandler) Ping(c echo.Context) error { - return c.JSON(http.StatusOK, map[string]string{ - "status": "ok", + return c.JSON(http.StatusOK, PingResponse{ + Status: "ok", + ContainerBackend: h.runtime.ContainerBackend, + SnapshotSupported: h.runtime.ContainerBackend != "apple", }) } diff --git a/internal/mcp/manager.go b/internal/mcp/manager.go index bfdf8b0b..fd4237cf 100644 --- a/internal/mcp/manager.go +++ b/internal/mcp/manager.go @@ -11,10 +11,8 @@ import ( "sync" "time" - "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/errdefs" "github.com/jackc/pgx/v5/pgxpool" - "github.com/opencontainers/runtime-spec/specs-go" "github.com/memohai/memoh/internal/config" ctr "github.com/memohai/memoh/internal/containerd" @@ -118,23 +116,22 @@ func (m *Manager) EnsureBot(ctx context.Context, botID string) error { return err } - specOpts := []oci.SpecOpts{ - oci.WithMounts([]specs.Mount{ - { - Destination: dataMount, - Type: "bind", - Source: dataDir, - Options: []string{"rbind", "rw"}, - }, - { - Destination: "/etc/resolv.conf", - Type: "bind", - Source: resolvPath, - Options: []string{"rbind", "ro"}, - }, - }), + mounts := []ctr.MountSpec{ + { + Destination: dataMount, + Type: "bind", + Source: dataDir, + Options: []string{"rbind", "rw"}, + }, + { + Destination: "/etc/resolv.conf", + Type: "bind", + Source: resolvPath, + Options: []string{"rbind", "ro"}, + }, } - specOpts = append(specOpts, ctr.TimezoneSpecOpts()...) + tzMounts, tzEnv := ctr.TimezoneSpec() + mounts = append(mounts, tzMounts...) _, err = m.service.CreateContainer(ctx, ctr.CreateContainerRequest{ ID: m.containerID(botID), @@ -143,7 +140,10 @@ func (m *Manager) EnsureBot(ctx context.Context, botID string) error { Labels: map[string]string{ BotLabelKey: botID, }, - SpecOpts: specOpts, + Spec: ctr.ContainerSpec{ + Mounts: mounts, + Env: tzEnv, + }, }) if err == nil { return nil @@ -164,11 +164,7 @@ func (m *Manager) ListBots(ctx context.Context) ([]string, error) { } botIDs := make([]string, 0, len(containers)) - for _, container := range containers { - info, err := container.Info(ctx) - if err != nil { - return nil, err - } + for _, info := range containers { if strings.HasPrefix(info.ID, ContainerPrefix) { if botID, ok := info.Labels[BotLabelKey]; ok { botIDs = append(botIDs, botID) @@ -183,14 +179,17 @@ func (m *Manager) Start(ctx context.Context, botID string) error { return err } - task, err := m.service.StartTask(ctx, m.containerID(botID), &ctr.StartTaskOptions{ + if err := m.service.StartContainer(ctx, m.containerID(botID), &ctr.StartTaskOptions{ UseStdio: false, - }) - if err != nil { + }); err != nil { return err } - if err := ctr.SetupNetwork(ctx, task, m.containerID(botID), m.cfg.CNIBinaryDir, m.cfg.CNIConfigDir); err != nil { - if stopErr := m.service.StopTask(ctx, m.containerID(botID), &ctr.StopTaskOptions{Force: true}); stopErr != nil { + if err := m.service.SetupNetwork(ctx, ctr.NetworkSetupRequest{ + ContainerID: m.containerID(botID), + CNIBinDir: m.cfg.CNIBinaryDir, + CNIConfDir: m.cfg.CNIConfigDir, + }); err != nil { + if stopErr := m.service.StopContainer(ctx, m.containerID(botID), &ctr.StopTaskOptions{Force: true}); stopErr != nil { m.logger.Warn("cleanup: stop task failed", slog.String("container_id", m.containerID(botID)), slog.Any("error", stopErr)) } return err @@ -202,7 +201,7 @@ func (m *Manager) Stop(ctx context.Context, botID string, timeout time.Duration) if err := validateBotID(botID); err != nil { return err } - return m.service.StopTask(ctx, m.containerID(botID), &ctr.StopTaskOptions{ + return m.service.StopContainer(ctx, m.containerID(botID), &ctr.StopTaskOptions{ Timeout: timeout, Force: true, }) @@ -213,10 +212,12 @@ func (m *Manager) Delete(ctx context.Context, botID string) error { return err } - if task, taskErr := m.service.GetTask(ctx, m.containerID(botID)); taskErr == nil { - if err := ctr.RemoveNetwork(ctx, task, m.containerID(botID), m.cfg.CNIBinaryDir, m.cfg.CNIConfigDir); err != nil { - m.logger.Warn("cleanup: remove network failed", slog.String("container_id", m.containerID(botID)), slog.Any("error", err)) - } + if err := m.service.RemoveNetwork(ctx, ctr.NetworkSetupRequest{ + ContainerID: m.containerID(botID), + CNIBinDir: m.cfg.CNIBinaryDir, + CNIConfDir: m.cfg.CNIConfigDir, + }); err != nil { + m.logger.Warn("cleanup: remove network failed", slog.String("container_id", m.containerID(botID)), slog.Any("error", err)) } if err := m.service.DeleteTask(ctx, m.containerID(botID), &ctr.DeleteTaskOptions{Force: true}); err != nil { m.logger.Warn("cleanup: delete task failed", slog.String("container_id", m.containerID(botID)), slog.Any("error", err)) diff --git a/internal/mcp/providers/container/fsops.go b/internal/mcp/providers/container/fsops.go index f3c05387..ee4fccb3 100644 --- a/internal/mcp/providers/container/fsops.go +++ b/internal/mcp/providers/container/fsops.go @@ -22,11 +22,18 @@ type FileEntry struct { ModTime time.Time } +func wrapWithCd(workDir, script string) string { + if workDir == "" { + return script + } + return "cd " + ShellQuote(workDir) + " && " + script +} + // ExecRead reads a file inside the container via cat. func ExecRead(ctx context.Context, runner ExecRunner, botID, workDir, filePath string) (string, error) { result, err := runner.ExecWithCapture(ctx, mcpgw.ExecRequest{ BotID: botID, - Command: []string{"/bin/sh", "-c", "cat " + ShellQuote(filePath)}, + Command: []string{"/bin/sh", "-c", wrapWithCd(workDir, "cat "+ShellQuote(filePath))}, WorkDir: workDir, }) if err != nil { @@ -47,7 +54,7 @@ func ExecWrite(ctx context.Context, runner ExecRunner, botID, workDir, filePath, ShellQuote(dir), ShellQuote(encoded), ShellQuote(filePath)) result, err := runner.ExecWithCapture(ctx, mcpgw.ExecRequest{ BotID: botID, - Command: []string{"/bin/sh", "-c", script}, + Command: []string{"/bin/sh", "-c", wrapWithCd(workDir, script)}, WorkDir: workDir, }) if err != nil { @@ -74,7 +81,7 @@ func ExecList(ctx context.Context, runner ExecRunner, botID, workDir, dirPath st ) result, err := runner.ExecWithCapture(ctx, mcpgw.ExecRequest{ BotID: botID, - Command: []string{"/bin/sh", "-c", script}, + Command: []string{"/bin/sh", "-c", wrapWithCd(workDir, script)}, WorkDir: workDir, }) if err != nil { diff --git a/internal/mcp/providers/container/provider.go b/internal/mcp/providers/container/provider.go index c65e4e55..5bd8288f 100644 --- a/internal/mcp/providers/container/provider.go +++ b/internal/mcp/providers/container/provider.go @@ -227,9 +227,13 @@ func (p *Executor) CallTool(ctx context.Context, session mcpgw.ToolSessionContex if workDir == "" { workDir = p.execWorkDir } + wrappedCmd := command + if workDir != "" { + wrappedCmd = "cd " + ShellQuote(workDir) + " && " + command + } result, err := p.execRunner.ExecWithCapture(ctx, mcpgw.ExecRequest{ BotID: botID, - Command: []string{shellCommandName, shellCommandFlag, command}, + Command: []string{shellCommandName, shellCommandFlag, wrappedCmd}, WorkDir: workDir, }) if err != nil { diff --git a/internal/mcp/versioning.go b/internal/mcp/versioning.go index cadb7be5..a9a9ce67 100644 --- a/internal/mcp/versioning.go +++ b/internal/mcp/versioning.go @@ -7,11 +7,9 @@ import ( "strings" "time" - "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/errdefs" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" - "github.com/opencontainers/runtime-spec/specs-go" "github.com/memohai/memoh/internal/config" @@ -53,11 +51,7 @@ func (m *Manager) CreateSnapshot(ctx context.Context, botID, snapshotName, sourc unlock := m.lockContainer(containerID) defer unlock() - container, err := m.service.GetContainer(ctx, containerID) - if err != nil { - return nil, err - } - info, err := container.Info(ctx) + info, err := m.service.GetContainer(ctx, containerID) if err != nil { return nil, err } @@ -116,12 +110,7 @@ func (m *Manager) CreateVersion(ctx context.Context, botID string) (*VersionInfo unlock := m.lockContainer(containerID) defer unlock() - container, err := m.service.GetContainer(ctx, containerID) - if err != nil { - return nil, err - } - - info, err := container.Info(ctx) + info, err := m.service.GetContainer(ctx, containerID) if err != nil { return nil, err } @@ -148,36 +137,10 @@ func (m *Manager) CreateVersion(ctx context.Context, botID string) (*VersionInfo return nil, err } - dataDir, err := m.ensureBotDir(botID) + spec, err := m.buildVersionSpec(botID) if err != nil { return nil, err } - dataMount := m.cfg.DataMount - if dataMount == "" { - dataMount = config.DefaultDataMount - } - resolvPath, err := ctr.ResolveConfSource(dataDir) - if err != nil { - return nil, err - } - - specOpts := []oci.SpecOpts{ - oci.WithMounts([]specs.Mount{ - { - Destination: dataMount, - Type: "bind", - Source: dataDir, - Options: []string{"rbind", "rw"}, - }, - { - Destination: "/etc/resolv.conf", - Type: "bind", - Source: resolvPath, - Options: []string{"rbind", "ro"}, - }, - }), - } - specOpts = append(specOpts, ctr.TimezoneSpecOpts()...) _, err = m.service.CreateContainerFromSnapshot(ctx, ctr.CreateContainerRequest{ ID: containerID, @@ -185,7 +148,7 @@ func (m *Manager) CreateVersion(ctx context.Context, botID string) (*VersionInfo SnapshotID: activeSnapshotName, Snapshotter: info.Snapshotter, Labels: info.Labels, - SpecOpts: specOpts, + Spec: spec, }) if err != nil { return nil, err @@ -269,11 +232,7 @@ func (m *Manager) RollbackVersion(ctx context.Context, botID string, version int return err } - container, err := m.service.GetContainer(ctx, containerID) - if err != nil { - return err - } - info, err := container.Info(ctx) + info, err := m.service.GetContainer(ctx, containerID) if err != nil { return err } @@ -291,35 +250,10 @@ func (m *Manager) RollbackVersion(ctx context.Context, botID string, version int return err } - dataDir, err := m.ensureBotDir(botID) + spec, err := m.buildVersionSpec(botID) if err != nil { return err } - dataMount := m.cfg.DataMount - if dataMount == "" { - dataMount = config.DefaultDataMount - } - resolvPath, err := ctr.ResolveConfSource(dataDir) - if err != nil { - return err - } - specOpts := []oci.SpecOpts{ - oci.WithMounts([]specs.Mount{ - { - Destination: dataMount, - Type: "bind", - Source: dataDir, - Options: []string{"rbind", "rw"}, - }, - { - Destination: "/etc/resolv.conf", - Type: "bind", - Source: resolvPath, - Options: []string{"rbind", "ro"}, - }, - }), - } - specOpts = append(specOpts, ctr.TimezoneSpecOpts()...) _, err = m.service.CreateContainerFromSnapshot(ctx, ctr.CreateContainerRequest{ ID: containerID, @@ -327,7 +261,7 @@ func (m *Manager) RollbackVersion(ctx context.Context, botID string, version int SnapshotID: activeSnapshotName, Snapshotter: info.Snapshotter, Labels: info.Labels, - SpecOpts: specOpts, + Spec: spec, }) if err != nil { return err @@ -355,8 +289,43 @@ func (m *Manager) VersionSnapshotName(ctx context.Context, botID string, version }) } +func (m *Manager) buildVersionSpec(botID string) (ctr.ContainerSpec, error) { + dataDir, err := m.ensureBotDir(botID) + if err != nil { + return ctr.ContainerSpec{}, err + } + dataMount := m.cfg.DataMount + if dataMount == "" { + dataMount = config.DefaultDataMount + } + resolvPath, err := ctr.ResolveConfSource(dataDir) + if err != nil { + return ctr.ContainerSpec{}, err + } + mounts := []ctr.MountSpec{ + { + Destination: dataMount, + Type: "bind", + Source: dataDir, + Options: []string{"rbind", "rw"}, + }, + { + Destination: "/etc/resolv.conf", + Type: "bind", + Source: resolvPath, + Options: []string{"rbind", "ro"}, + }, + } + tzMounts, tzEnv := ctr.TimezoneSpec() + mounts = append(mounts, tzMounts...) + return ctr.ContainerSpec{ + Mounts: mounts, + Env: tzEnv, + }, nil +} + func (m *Manager) safeStopTask(ctx context.Context, containerID string) error { - err := m.service.StopTask(ctx, containerID, &ctr.StopTaskOptions{ + err := m.service.StopContainer(ctx, containerID, &ctr.StopTaskOptions{ Timeout: 10 * time.Second, Force: true, }) diff --git a/mise.toml b/mise.toml index f1e5981e..07b9e40a 100644 --- a/mise.toml +++ b/mise.toml @@ -77,9 +77,9 @@ description = "Install CLI" depends = ["//:pnpm-install"] run = "cd packages/cli && npm install -g" -[tasks.compile-mcp] -description = "Build MCP binary into /app and signal container" -run = "scripts/compile-mcp.sh" +[task.install-socktainer] +description = "Install socktainer" +run = "brew tap socktainer/tap && brew install socktainer" [tasks.dev] description = "Start development environment" diff --git a/packages/sdk/src/@pinia/colada.gen.ts b/packages/sdk/src/@pinia/colada.gen.ts index 17658c74..fcc097c8 100644 --- a/packages/sdk/src/@pinia/colada.gen.ts +++ b/packages/sdk/src/@pinia/colada.gen.ts @@ -4,8 +4,8 @@ import { type _JSONValue, defineQueryOptions, type UseMutationOptions } from '@p import { serializeQueryKeyValue } from '../client'; import { client } from '../client.gen'; -import { deleteBotsByBotIdContainer, deleteBotsByBotIdContainerSkills, deleteBotsByBotIdInboxById, deleteBotsByBotIdMcpById, deleteBotsByBotIdMemory, deleteBotsByBotIdMemoryById, deleteBotsByBotIdMessages, deleteBotsByBotIdScheduleById, deleteBotsByBotIdSettings, deleteBotsByBotIdSubagentsById, deleteBotsById, deleteBotsByIdChannelByPlatform, deleteBotsByIdMembersByUserId, deleteModelsById, deleteModelsModelByModelId, deleteProvidersById, deleteSearchProvidersById, getBots, getBotsByBotIdContainer, getBotsByBotIdContainerFs, getBotsByBotIdContainerFsDownload, getBotsByBotIdContainerFsList, getBotsByBotIdContainerFsRead, getBotsByBotIdContainerSkills, getBotsByBotIdContainerSnapshots, getBotsByBotIdInbox, getBotsByBotIdInboxById, getBotsByBotIdInboxCount, getBotsByBotIdMcp, getBotsByBotIdMcpById, getBotsByBotIdMcpExport, getBotsByBotIdMemory, getBotsByBotIdMemoryUsage, getBotsByBotIdMessages, getBotsByBotIdSchedule, getBotsByBotIdScheduleById, getBotsByBotIdSettings, getBotsByBotIdSubagents, getBotsByBotIdSubagentsById, getBotsByBotIdSubagentsByIdContext, getBotsByBotIdSubagentsByIdSkills, getBotsById, getBotsByIdChannelByPlatform, getBotsByIdChecks, getBotsByIdMembers, getChannels, getChannelsByPlatform, getModels, getModelsById, getModelsCount, getModelsModelByModelId, getProviders, getProvidersById, getProvidersByIdModels, getProvidersCount, getProvidersNameByName, getSearchProviders, getSearchProvidersById, getSearchProvidersMeta, getUsers, getUsersById, getUsersMe, getUsersMeChannelsByPlatform, getUsersMeIdentities, type Options, patchBotsByIdChannelByPlatformStatus, postAuthLogin, postBots, postBotsByBotIdCliMessages, postBotsByBotIdContainer, postBotsByBotIdContainerFsDelete, postBotsByBotIdContainerFsMkdir, postBotsByBotIdContainerFsRename, postBotsByBotIdContainerFsUpload, postBotsByBotIdContainerFsWrite, postBotsByBotIdContainerSkills, postBotsByBotIdContainerSnapshots, postBotsByBotIdContainerStart, postBotsByBotIdContainerStop, postBotsByBotIdInbox, postBotsByBotIdInboxMarkRead, postBotsByBotIdMcp, postBotsByBotIdMcpOpsBatchDelete, postBotsByBotIdMcpStdio, postBotsByBotIdMcpStdioByConnectionId, postBotsByBotIdMemory, postBotsByBotIdMemoryCompact, postBotsByBotIdMemoryRebuild, postBotsByBotIdMemorySearch, postBotsByBotIdSchedule, postBotsByBotIdSettings, postBotsByBotIdSubagents, postBotsByBotIdSubagentsByIdSkills, postBotsByBotIdTools, postBotsByBotIdWebMessages, postBotsByIdChannelByPlatformSend, postBotsByIdChannelByPlatformSendChat, postEmbeddings, postModels, postProviders, postProvidersByIdTest, postSearchProviders, postUsers, putBotsByBotIdMcpById, putBotsByBotIdMcpImport, putBotsByBotIdScheduleById, putBotsByBotIdSettings, putBotsByBotIdSubagentsById, putBotsByBotIdSubagentsByIdContext, putBotsByBotIdSubagentsByIdSkills, putBotsById, putBotsByIdChannelByPlatform, putBotsByIdMembers, putBotsByIdOwner, putModelsById, putModelsModelByModelId, putProvidersById, putSearchProvidersById, putUsersById, putUsersByIdPassword, putUsersMe, putUsersMeChannelsByPlatform, putUsersMePassword } from '../sdk.gen'; -import type { DeleteBotsByBotIdContainerData, DeleteBotsByBotIdContainerError, DeleteBotsByBotIdContainerSkillsData, DeleteBotsByBotIdContainerSkillsError, DeleteBotsByBotIdContainerSkillsResponse, DeleteBotsByBotIdInboxByIdData, DeleteBotsByBotIdInboxByIdError, DeleteBotsByBotIdMcpByIdData, DeleteBotsByBotIdMcpByIdError, DeleteBotsByBotIdMemoryByIdData, DeleteBotsByBotIdMemoryByIdError, DeleteBotsByBotIdMemoryByIdResponse, DeleteBotsByBotIdMemoryData, DeleteBotsByBotIdMemoryError, DeleteBotsByBotIdMemoryResponse, DeleteBotsByBotIdMessagesData, DeleteBotsByBotIdMessagesError, DeleteBotsByBotIdScheduleByIdData, DeleteBotsByBotIdScheduleByIdError, DeleteBotsByBotIdSettingsData, DeleteBotsByBotIdSettingsError, DeleteBotsByBotIdSubagentsByIdData, DeleteBotsByBotIdSubagentsByIdError, DeleteBotsByIdChannelByPlatformData, DeleteBotsByIdChannelByPlatformError, DeleteBotsByIdData, DeleteBotsByIdError, DeleteBotsByIdMembersByUserIdData, DeleteBotsByIdMembersByUserIdError, DeleteBotsByIdResponse, DeleteModelsByIdData, DeleteModelsByIdError, DeleteModelsModelByModelIdData, DeleteModelsModelByModelIdError, DeleteProvidersByIdData, DeleteProvidersByIdError, DeleteSearchProvidersByIdData, DeleteSearchProvidersByIdError, GetBotsByBotIdContainerData, GetBotsByBotIdContainerFsData, GetBotsByBotIdContainerFsDownloadData, GetBotsByBotIdContainerFsListData, GetBotsByBotIdContainerFsReadData, GetBotsByBotIdContainerSkillsData, GetBotsByBotIdContainerSnapshotsData, GetBotsByBotIdInboxByIdData, GetBotsByBotIdInboxCountData, GetBotsByBotIdInboxData, GetBotsByBotIdMcpByIdData, GetBotsByBotIdMcpData, GetBotsByBotIdMcpExportData, GetBotsByBotIdMemoryData, GetBotsByBotIdMemoryUsageData, GetBotsByBotIdMessagesData, GetBotsByBotIdScheduleByIdData, GetBotsByBotIdScheduleData, GetBotsByBotIdSettingsData, GetBotsByBotIdSubagentsByIdContextData, GetBotsByBotIdSubagentsByIdData, GetBotsByBotIdSubagentsByIdSkillsData, GetBotsByBotIdSubagentsData, GetBotsByIdChannelByPlatformData, GetBotsByIdChecksData, GetBotsByIdData, GetBotsByIdMembersData, GetBotsData, GetChannelsByPlatformData, GetChannelsData, GetModelsByIdData, GetModelsCountData, GetModelsData, GetModelsModelByModelIdData, GetProvidersByIdData, GetProvidersByIdModelsData, GetProvidersCountData, GetProvidersData, GetProvidersNameByNameData, GetSearchProvidersByIdData, GetSearchProvidersData, GetSearchProvidersMetaData, GetUsersByIdData, GetUsersData, GetUsersMeChannelsByPlatformData, GetUsersMeData, GetUsersMeIdentitiesData, PatchBotsByIdChannelByPlatformStatusData, PatchBotsByIdChannelByPlatformStatusError, PatchBotsByIdChannelByPlatformStatusResponse, PostAuthLoginData, PostAuthLoginError, PostAuthLoginResponse, PostBotsByBotIdCliMessagesData, PostBotsByBotIdCliMessagesError, PostBotsByBotIdCliMessagesResponse, PostBotsByBotIdContainerData, PostBotsByBotIdContainerError, PostBotsByBotIdContainerFsDeleteData, PostBotsByBotIdContainerFsDeleteError, PostBotsByBotIdContainerFsDeleteResponse, PostBotsByBotIdContainerFsMkdirData, PostBotsByBotIdContainerFsMkdirError, PostBotsByBotIdContainerFsMkdirResponse, PostBotsByBotIdContainerFsRenameData, PostBotsByBotIdContainerFsRenameError, PostBotsByBotIdContainerFsRenameResponse, PostBotsByBotIdContainerFsUploadData, PostBotsByBotIdContainerFsUploadError, PostBotsByBotIdContainerFsUploadResponse, PostBotsByBotIdContainerFsWriteData, PostBotsByBotIdContainerFsWriteError, PostBotsByBotIdContainerFsWriteResponse, PostBotsByBotIdContainerResponse, PostBotsByBotIdContainerSkillsData, PostBotsByBotIdContainerSkillsError, PostBotsByBotIdContainerSkillsResponse, PostBotsByBotIdContainerSnapshotsData, PostBotsByBotIdContainerSnapshotsError, PostBotsByBotIdContainerSnapshotsResponse, PostBotsByBotIdContainerStartData, PostBotsByBotIdContainerStartError, PostBotsByBotIdContainerStartResponse, PostBotsByBotIdContainerStopData, PostBotsByBotIdContainerStopError, PostBotsByBotIdContainerStopResponse, PostBotsByBotIdInboxData, PostBotsByBotIdInboxError, PostBotsByBotIdInboxMarkReadData, PostBotsByBotIdInboxMarkReadError, PostBotsByBotIdInboxResponse, PostBotsByBotIdMcpData, PostBotsByBotIdMcpError, PostBotsByBotIdMcpOpsBatchDeleteData, PostBotsByBotIdMcpOpsBatchDeleteError, PostBotsByBotIdMcpResponse, PostBotsByBotIdMcpStdioByConnectionIdData, PostBotsByBotIdMcpStdioByConnectionIdError, PostBotsByBotIdMcpStdioByConnectionIdResponse, PostBotsByBotIdMcpStdioData, PostBotsByBotIdMcpStdioError, PostBotsByBotIdMcpStdioResponse, PostBotsByBotIdMemoryCompactData, PostBotsByBotIdMemoryCompactError, PostBotsByBotIdMemoryCompactResponse, PostBotsByBotIdMemoryData, PostBotsByBotIdMemoryError, PostBotsByBotIdMemoryRebuildData, PostBotsByBotIdMemoryRebuildError, PostBotsByBotIdMemoryRebuildResponse, PostBotsByBotIdMemoryResponse, PostBotsByBotIdMemorySearchData, PostBotsByBotIdMemorySearchError, PostBotsByBotIdMemorySearchResponse, PostBotsByBotIdScheduleData, PostBotsByBotIdScheduleError, PostBotsByBotIdScheduleResponse, PostBotsByBotIdSettingsData, PostBotsByBotIdSettingsError, PostBotsByBotIdSettingsResponse, PostBotsByBotIdSubagentsByIdSkillsData, PostBotsByBotIdSubagentsByIdSkillsError, PostBotsByBotIdSubagentsByIdSkillsResponse, PostBotsByBotIdSubagentsData, PostBotsByBotIdSubagentsError, PostBotsByBotIdSubagentsResponse, PostBotsByBotIdToolsData, PostBotsByBotIdToolsError, PostBotsByBotIdToolsResponse, PostBotsByBotIdWebMessagesData, PostBotsByBotIdWebMessagesError, PostBotsByBotIdWebMessagesResponse, PostBotsByIdChannelByPlatformSendChatData, PostBotsByIdChannelByPlatformSendChatError, PostBotsByIdChannelByPlatformSendChatResponse, PostBotsByIdChannelByPlatformSendData, PostBotsByIdChannelByPlatformSendError, PostBotsByIdChannelByPlatformSendResponse, PostBotsData, PostBotsError, PostBotsResponse, PostEmbeddingsData, PostEmbeddingsError, PostEmbeddingsResponse, PostModelsData, PostModelsError, PostModelsResponse, PostProvidersByIdTestData, PostProvidersByIdTestError, PostProvidersByIdTestResponse, PostProvidersData, PostProvidersError, PostProvidersResponse, PostSearchProvidersData, PostSearchProvidersError, PostSearchProvidersResponse, PostUsersData, PostUsersError, PostUsersResponse, PutBotsByBotIdMcpByIdData, PutBotsByBotIdMcpByIdError, PutBotsByBotIdMcpByIdResponse, PutBotsByBotIdMcpImportData, PutBotsByBotIdMcpImportError, PutBotsByBotIdMcpImportResponse, PutBotsByBotIdScheduleByIdData, PutBotsByBotIdScheduleByIdError, PutBotsByBotIdScheduleByIdResponse, PutBotsByBotIdSettingsData, PutBotsByBotIdSettingsError, PutBotsByBotIdSettingsResponse, PutBotsByBotIdSubagentsByIdContextData, PutBotsByBotIdSubagentsByIdContextError, PutBotsByBotIdSubagentsByIdContextResponse, PutBotsByBotIdSubagentsByIdData, PutBotsByBotIdSubagentsByIdError, PutBotsByBotIdSubagentsByIdResponse, PutBotsByBotIdSubagentsByIdSkillsData, PutBotsByBotIdSubagentsByIdSkillsError, PutBotsByBotIdSubagentsByIdSkillsResponse, PutBotsByIdChannelByPlatformData, PutBotsByIdChannelByPlatformError, PutBotsByIdChannelByPlatformResponse, PutBotsByIdData, PutBotsByIdError, PutBotsByIdMembersData, PutBotsByIdMembersError, PutBotsByIdMembersResponse, PutBotsByIdOwnerData, PutBotsByIdOwnerError, PutBotsByIdOwnerResponse, PutBotsByIdResponse, PutModelsByIdData, PutModelsByIdError, PutModelsByIdResponse, PutModelsModelByModelIdData, PutModelsModelByModelIdError, PutModelsModelByModelIdResponse, PutProvidersByIdData, PutProvidersByIdError, PutProvidersByIdResponse, PutSearchProvidersByIdData, PutSearchProvidersByIdError, PutSearchProvidersByIdResponse, PutUsersByIdData, PutUsersByIdError, PutUsersByIdPasswordData, PutUsersByIdPasswordError, PutUsersByIdResponse, PutUsersMeChannelsByPlatformData, PutUsersMeChannelsByPlatformError, PutUsersMeChannelsByPlatformResponse, PutUsersMeData, PutUsersMeError, PutUsersMePasswordData, PutUsersMePasswordError, PutUsersMeResponse } from '../types.gen'; +import { deleteBotsByBotIdContainer, deleteBotsByBotIdContainerSkills, deleteBotsByBotIdInboxById, deleteBotsByBotIdMcpById, deleteBotsByBotIdMemory, deleteBotsByBotIdMemoryById, deleteBotsByBotIdMessages, deleteBotsByBotIdScheduleById, deleteBotsByBotIdSettings, deleteBotsByBotIdSubagentsById, deleteBotsById, deleteBotsByIdChannelByPlatform, deleteBotsByIdMembersByUserId, deleteModelsById, deleteModelsModelByModelId, deleteProvidersById, deleteSearchProvidersById, getBots, getBotsByBotIdContainer, getBotsByBotIdContainerFs, getBotsByBotIdContainerFsDownload, getBotsByBotIdContainerFsList, getBotsByBotIdContainerFsRead, getBotsByBotIdContainerSkills, getBotsByBotIdContainerSnapshots, getBotsByBotIdInbox, getBotsByBotIdInboxById, getBotsByBotIdInboxCount, getBotsByBotIdMcp, getBotsByBotIdMcpById, getBotsByBotIdMcpExport, getBotsByBotIdMemory, getBotsByBotIdMemoryUsage, getBotsByBotIdMessages, getBotsByBotIdSchedule, getBotsByBotIdScheduleById, getBotsByBotIdSettings, getBotsByBotIdSubagents, getBotsByBotIdSubagentsById, getBotsByBotIdSubagentsByIdContext, getBotsByBotIdSubagentsByIdSkills, getBotsById, getBotsByIdChannelByPlatform, getBotsByIdChecks, getBotsByIdMembers, getChannels, getChannelsByPlatform, getModels, getModelsById, getModelsCount, getModelsModelByModelId, getPing, getProviders, getProvidersById, getProvidersByIdModels, getProvidersCount, getProvidersNameByName, getSearchProviders, getSearchProvidersById, getSearchProvidersMeta, getUsers, getUsersById, getUsersMe, getUsersMeChannelsByPlatform, getUsersMeIdentities, type Options, patchBotsByIdChannelByPlatformStatus, postAuthLogin, postBots, postBotsByBotIdCliMessages, postBotsByBotIdContainer, postBotsByBotIdContainerFsDelete, postBotsByBotIdContainerFsMkdir, postBotsByBotIdContainerFsRename, postBotsByBotIdContainerFsUpload, postBotsByBotIdContainerFsWrite, postBotsByBotIdContainerSkills, postBotsByBotIdContainerSnapshots, postBotsByBotIdContainerStart, postBotsByBotIdContainerStop, postBotsByBotIdInbox, postBotsByBotIdInboxMarkRead, postBotsByBotIdMcp, postBotsByBotIdMcpOpsBatchDelete, postBotsByBotIdMcpStdio, postBotsByBotIdMcpStdioByConnectionId, postBotsByBotIdMemory, postBotsByBotIdMemoryCompact, postBotsByBotIdMemoryRebuild, postBotsByBotIdMemorySearch, postBotsByBotIdSchedule, postBotsByBotIdSettings, postBotsByBotIdSubagents, postBotsByBotIdSubagentsByIdSkills, postBotsByBotIdTools, postBotsByBotIdWebMessages, postBotsByIdChannelByPlatformSend, postBotsByIdChannelByPlatformSendChat, postEmbeddings, postModels, postProviders, postProvidersByIdTest, postSearchProviders, postUsers, putBotsByBotIdMcpById, putBotsByBotIdMcpImport, putBotsByBotIdScheduleById, putBotsByBotIdSettings, putBotsByBotIdSubagentsById, putBotsByBotIdSubagentsByIdContext, putBotsByBotIdSubagentsByIdSkills, putBotsById, putBotsByIdChannelByPlatform, putBotsByIdMembers, putBotsByIdOwner, putModelsById, putModelsModelByModelId, putProvidersById, putSearchProvidersById, putUsersById, putUsersByIdPassword, putUsersMe, putUsersMeChannelsByPlatform, putUsersMePassword } from '../sdk.gen'; +import type { DeleteBotsByBotIdContainerData, DeleteBotsByBotIdContainerError, DeleteBotsByBotIdContainerSkillsData, DeleteBotsByBotIdContainerSkillsError, DeleteBotsByBotIdContainerSkillsResponse, DeleteBotsByBotIdInboxByIdData, DeleteBotsByBotIdInboxByIdError, DeleteBotsByBotIdMcpByIdData, DeleteBotsByBotIdMcpByIdError, DeleteBotsByBotIdMemoryByIdData, DeleteBotsByBotIdMemoryByIdError, DeleteBotsByBotIdMemoryByIdResponse, DeleteBotsByBotIdMemoryData, DeleteBotsByBotIdMemoryError, DeleteBotsByBotIdMemoryResponse, DeleteBotsByBotIdMessagesData, DeleteBotsByBotIdMessagesError, DeleteBotsByBotIdScheduleByIdData, DeleteBotsByBotIdScheduleByIdError, DeleteBotsByBotIdSettingsData, DeleteBotsByBotIdSettingsError, DeleteBotsByBotIdSubagentsByIdData, DeleteBotsByBotIdSubagentsByIdError, DeleteBotsByIdChannelByPlatformData, DeleteBotsByIdChannelByPlatformError, DeleteBotsByIdData, DeleteBotsByIdError, DeleteBotsByIdMembersByUserIdData, DeleteBotsByIdMembersByUserIdError, DeleteBotsByIdResponse, DeleteModelsByIdData, DeleteModelsByIdError, DeleteModelsModelByModelIdData, DeleteModelsModelByModelIdError, DeleteProvidersByIdData, DeleteProvidersByIdError, DeleteSearchProvidersByIdData, DeleteSearchProvidersByIdError, GetBotsByBotIdContainerData, GetBotsByBotIdContainerFsData, GetBotsByBotIdContainerFsDownloadData, GetBotsByBotIdContainerFsListData, GetBotsByBotIdContainerFsReadData, GetBotsByBotIdContainerSkillsData, GetBotsByBotIdContainerSnapshotsData, GetBotsByBotIdInboxByIdData, GetBotsByBotIdInboxCountData, GetBotsByBotIdInboxData, GetBotsByBotIdMcpByIdData, GetBotsByBotIdMcpData, GetBotsByBotIdMcpExportData, GetBotsByBotIdMemoryData, GetBotsByBotIdMemoryUsageData, GetBotsByBotIdMessagesData, GetBotsByBotIdScheduleByIdData, GetBotsByBotIdScheduleData, GetBotsByBotIdSettingsData, GetBotsByBotIdSubagentsByIdContextData, GetBotsByBotIdSubagentsByIdData, GetBotsByBotIdSubagentsByIdSkillsData, GetBotsByBotIdSubagentsData, GetBotsByIdChannelByPlatformData, GetBotsByIdChecksData, GetBotsByIdData, GetBotsByIdMembersData, GetBotsData, GetChannelsByPlatformData, GetChannelsData, GetModelsByIdData, GetModelsCountData, GetModelsData, GetModelsModelByModelIdData, GetPingData, GetProvidersByIdData, GetProvidersByIdModelsData, GetProvidersCountData, GetProvidersData, GetProvidersNameByNameData, GetSearchProvidersByIdData, GetSearchProvidersData, GetSearchProvidersMetaData, GetUsersByIdData, GetUsersData, GetUsersMeChannelsByPlatformData, GetUsersMeData, GetUsersMeIdentitiesData, PatchBotsByIdChannelByPlatformStatusData, PatchBotsByIdChannelByPlatformStatusError, PatchBotsByIdChannelByPlatformStatusResponse, PostAuthLoginData, PostAuthLoginError, PostAuthLoginResponse, PostBotsByBotIdCliMessagesData, PostBotsByBotIdCliMessagesError, PostBotsByBotIdCliMessagesResponse, PostBotsByBotIdContainerData, PostBotsByBotIdContainerError, PostBotsByBotIdContainerFsDeleteData, PostBotsByBotIdContainerFsDeleteError, PostBotsByBotIdContainerFsDeleteResponse, PostBotsByBotIdContainerFsMkdirData, PostBotsByBotIdContainerFsMkdirError, PostBotsByBotIdContainerFsMkdirResponse, PostBotsByBotIdContainerFsRenameData, PostBotsByBotIdContainerFsRenameError, PostBotsByBotIdContainerFsRenameResponse, PostBotsByBotIdContainerFsUploadData, PostBotsByBotIdContainerFsUploadError, PostBotsByBotIdContainerFsUploadResponse, PostBotsByBotIdContainerFsWriteData, PostBotsByBotIdContainerFsWriteError, PostBotsByBotIdContainerFsWriteResponse, PostBotsByBotIdContainerResponse, PostBotsByBotIdContainerSkillsData, PostBotsByBotIdContainerSkillsError, PostBotsByBotIdContainerSkillsResponse, PostBotsByBotIdContainerSnapshotsData, PostBotsByBotIdContainerSnapshotsError, PostBotsByBotIdContainerSnapshotsResponse, PostBotsByBotIdContainerStartData, PostBotsByBotIdContainerStartError, PostBotsByBotIdContainerStartResponse, PostBotsByBotIdContainerStopData, PostBotsByBotIdContainerStopError, PostBotsByBotIdContainerStopResponse, PostBotsByBotIdInboxData, PostBotsByBotIdInboxError, PostBotsByBotIdInboxMarkReadData, PostBotsByBotIdInboxMarkReadError, PostBotsByBotIdInboxResponse, PostBotsByBotIdMcpData, PostBotsByBotIdMcpError, PostBotsByBotIdMcpOpsBatchDeleteData, PostBotsByBotIdMcpOpsBatchDeleteError, PostBotsByBotIdMcpResponse, PostBotsByBotIdMcpStdioByConnectionIdData, PostBotsByBotIdMcpStdioByConnectionIdError, PostBotsByBotIdMcpStdioByConnectionIdResponse, PostBotsByBotIdMcpStdioData, PostBotsByBotIdMcpStdioError, PostBotsByBotIdMcpStdioResponse, PostBotsByBotIdMemoryCompactData, PostBotsByBotIdMemoryCompactError, PostBotsByBotIdMemoryCompactResponse, PostBotsByBotIdMemoryData, PostBotsByBotIdMemoryError, PostBotsByBotIdMemoryRebuildData, PostBotsByBotIdMemoryRebuildError, PostBotsByBotIdMemoryRebuildResponse, PostBotsByBotIdMemoryResponse, PostBotsByBotIdMemorySearchData, PostBotsByBotIdMemorySearchError, PostBotsByBotIdMemorySearchResponse, PostBotsByBotIdScheduleData, PostBotsByBotIdScheduleError, PostBotsByBotIdScheduleResponse, PostBotsByBotIdSettingsData, PostBotsByBotIdSettingsError, PostBotsByBotIdSettingsResponse, PostBotsByBotIdSubagentsByIdSkillsData, PostBotsByBotIdSubagentsByIdSkillsError, PostBotsByBotIdSubagentsByIdSkillsResponse, PostBotsByBotIdSubagentsData, PostBotsByBotIdSubagentsError, PostBotsByBotIdSubagentsResponse, PostBotsByBotIdToolsData, PostBotsByBotIdToolsError, PostBotsByBotIdToolsResponse, PostBotsByBotIdWebMessagesData, PostBotsByBotIdWebMessagesError, PostBotsByBotIdWebMessagesResponse, PostBotsByIdChannelByPlatformSendChatData, PostBotsByIdChannelByPlatformSendChatError, PostBotsByIdChannelByPlatformSendChatResponse, PostBotsByIdChannelByPlatformSendData, PostBotsByIdChannelByPlatformSendError, PostBotsByIdChannelByPlatformSendResponse, PostBotsData, PostBotsError, PostBotsResponse, PostEmbeddingsData, PostEmbeddingsError, PostEmbeddingsResponse, PostModelsData, PostModelsError, PostModelsResponse, PostProvidersByIdTestData, PostProvidersByIdTestError, PostProvidersByIdTestResponse, PostProvidersData, PostProvidersError, PostProvidersResponse, PostSearchProvidersData, PostSearchProvidersError, PostSearchProvidersResponse, PostUsersData, PostUsersError, PostUsersResponse, PutBotsByBotIdMcpByIdData, PutBotsByBotIdMcpByIdError, PutBotsByBotIdMcpByIdResponse, PutBotsByBotIdMcpImportData, PutBotsByBotIdMcpImportError, PutBotsByBotIdMcpImportResponse, PutBotsByBotIdScheduleByIdData, PutBotsByBotIdScheduleByIdError, PutBotsByBotIdScheduleByIdResponse, PutBotsByBotIdSettingsData, PutBotsByBotIdSettingsError, PutBotsByBotIdSettingsResponse, PutBotsByBotIdSubagentsByIdContextData, PutBotsByBotIdSubagentsByIdContextError, PutBotsByBotIdSubagentsByIdContextResponse, PutBotsByBotIdSubagentsByIdData, PutBotsByBotIdSubagentsByIdError, PutBotsByBotIdSubagentsByIdResponse, PutBotsByBotIdSubagentsByIdSkillsData, PutBotsByBotIdSubagentsByIdSkillsError, PutBotsByBotIdSubagentsByIdSkillsResponse, PutBotsByIdChannelByPlatformData, PutBotsByIdChannelByPlatformError, PutBotsByIdChannelByPlatformResponse, PutBotsByIdData, PutBotsByIdError, PutBotsByIdMembersData, PutBotsByIdMembersError, PutBotsByIdMembersResponse, PutBotsByIdOwnerData, PutBotsByIdOwnerError, PutBotsByIdOwnerResponse, PutBotsByIdResponse, PutModelsByIdData, PutModelsByIdError, PutModelsByIdResponse, PutModelsModelByModelIdData, PutModelsModelByModelIdError, PutModelsModelByModelIdResponse, PutProvidersByIdData, PutProvidersByIdError, PutProvidersByIdResponse, PutSearchProvidersByIdData, PutSearchProvidersByIdError, PutSearchProvidersByIdResponse, PutUsersByIdData, PutUsersByIdError, PutUsersByIdPasswordData, PutUsersByIdPasswordError, PutUsersByIdResponse, PutUsersMeChannelsByPlatformData, PutUsersMeChannelsByPlatformError, PutUsersMeChannelsByPlatformResponse, PutUsersMeData, PutUsersMeError, PutUsersMePasswordData, PutUsersMePasswordError, PutUsersMeResponse } from '../types.gen'; /** * Login @@ -1667,6 +1667,23 @@ export const putModelsByIdMutation = (options?: Partial) => createQueryKey('getPing', options); + +/** + * Health check with server capabilities + */ +export const getPingQuery = defineQueryOptions((options?: Options) => ({ + key: getPingQueryKey(options), + query: async (context) => { + const { data } = await getPing({ + ...options, + ...context, + throwOnError: true + }); + return data; + } +})); + export const getProvidersQueryKey = (options?: Options) => createQueryKey('getProviders', options); /** diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts index d3e33060..785e9d2c 100644 --- a/packages/sdk/src/index.ts +++ b/packages/sdk/src/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { deleteBotsByBotIdContainer, deleteBotsByBotIdContainerSkills, deleteBotsByBotIdInboxById, deleteBotsByBotIdMcpById, deleteBotsByBotIdMemory, deleteBotsByBotIdMemoryById, deleteBotsByBotIdMessages, deleteBotsByBotIdScheduleById, deleteBotsByBotIdSettings, deleteBotsByBotIdSubagentsById, deleteBotsById, deleteBotsByIdChannelByPlatform, deleteBotsByIdMembersByUserId, deleteModelsById, deleteModelsModelByModelId, deleteProvidersById, deleteSearchProvidersById, getBots, getBotsByBotIdCliStream, getBotsByBotIdContainer, getBotsByBotIdContainerFs, getBotsByBotIdContainerFsDownload, getBotsByBotIdContainerFsList, getBotsByBotIdContainerFsRead, getBotsByBotIdContainerSkills, getBotsByBotIdContainerSnapshots, getBotsByBotIdInbox, getBotsByBotIdInboxById, getBotsByBotIdInboxCount, getBotsByBotIdMcp, getBotsByBotIdMcpById, getBotsByBotIdMcpExport, getBotsByBotIdMemory, getBotsByBotIdMemoryUsage, getBotsByBotIdMessages, getBotsByBotIdSchedule, getBotsByBotIdScheduleById, getBotsByBotIdSettings, getBotsByBotIdSubagents, getBotsByBotIdSubagentsById, getBotsByBotIdSubagentsByIdContext, getBotsByBotIdSubagentsByIdSkills, getBotsByBotIdWebStream, getBotsById, getBotsByIdChannelByPlatform, getBotsByIdChecks, getBotsByIdMembers, getChannels, getChannelsByPlatform, getModels, getModelsById, getModelsCount, getModelsModelByModelId, getProviders, getProvidersById, getProvidersByIdModels, getProvidersCount, getProvidersNameByName, getSearchProviders, getSearchProvidersById, getSearchProvidersMeta, getUsers, getUsersById, getUsersMe, getUsersMeChannelsByPlatform, getUsersMeIdentities, type Options, patchBotsByIdChannelByPlatformStatus, postAuthLogin, postBots, postBotsByBotIdCliMessages, postBotsByBotIdContainer, postBotsByBotIdContainerFsDelete, postBotsByBotIdContainerFsMkdir, postBotsByBotIdContainerFsRename, postBotsByBotIdContainerFsUpload, postBotsByBotIdContainerFsWrite, postBotsByBotIdContainerSkills, postBotsByBotIdContainerSnapshots, postBotsByBotIdContainerStart, postBotsByBotIdContainerStop, postBotsByBotIdInbox, postBotsByBotIdInboxMarkRead, postBotsByBotIdMcp, postBotsByBotIdMcpOpsBatchDelete, postBotsByBotIdMcpStdio, postBotsByBotIdMcpStdioByConnectionId, postBotsByBotIdMemory, postBotsByBotIdMemoryCompact, postBotsByBotIdMemoryRebuild, postBotsByBotIdMemorySearch, postBotsByBotIdSchedule, postBotsByBotIdSettings, postBotsByBotIdSubagents, postBotsByBotIdSubagentsByIdSkills, postBotsByBotIdTools, postBotsByBotIdWebMessages, postBotsByIdChannelByPlatformSend, postBotsByIdChannelByPlatformSendChat, postEmbeddings, postModels, postProviders, postProvidersByIdTest, postSearchProviders, postUsers, putBotsByBotIdMcpById, putBotsByBotIdMcpImport, putBotsByBotIdScheduleById, putBotsByBotIdSettings, putBotsByBotIdSubagentsById, putBotsByBotIdSubagentsByIdContext, putBotsByBotIdSubagentsByIdSkills, putBotsById, putBotsByIdChannelByPlatform, putBotsByIdMembers, putBotsByIdOwner, putModelsById, putModelsModelByModelId, putProvidersById, putSearchProvidersById, putUsersById, putUsersByIdPassword, putUsersMe, putUsersMeChannelsByPlatform, putUsersMePassword } from './sdk.gen'; -export type { AccountsAccount, AccountsCreateAccountRequest, AccountsListAccountsResponse, AccountsResetPasswordRequest, AccountsUpdateAccountRequest, AccountsUpdatePasswordRequest, AccountsUpdateProfileRequest, BotsBot, BotsBotCheck, BotsBotMember, BotsCreateBotRequest, BotsListBotsResponse, BotsListChecksResponse, BotsListMembersResponse, BotsTransferBotRequest, BotsUpdateBotRequest, BotsUpsertMemberRequest, ChannelAction, ChannelAttachment, ChannelAttachmentType, ChannelChannelCapabilities, ChannelChannelConfig, ChannelChannelIdentityBinding, ChannelConfigSchema, ChannelFieldSchema, ChannelFieldType, ChannelMessage, ChannelMessageFormat, ChannelMessagePart, ChannelMessagePartType, ChannelMessageTextStyle, ChannelReplyRef, ChannelSendRequest, ChannelTargetHint, ChannelTargetSpec, ChannelThreadRef, ChannelUpdateChannelStatusRequest, ChannelUpsertChannelIdentityConfigRequest, ChannelUpsertConfigRequest, ClientOptions, DeleteBotsByBotIdContainerData, DeleteBotsByBotIdContainerError, DeleteBotsByBotIdContainerErrors, DeleteBotsByBotIdContainerResponses, DeleteBotsByBotIdContainerSkillsData, DeleteBotsByBotIdContainerSkillsError, DeleteBotsByBotIdContainerSkillsErrors, DeleteBotsByBotIdContainerSkillsResponse, DeleteBotsByBotIdContainerSkillsResponses, DeleteBotsByBotIdInboxByIdData, DeleteBotsByBotIdInboxByIdError, DeleteBotsByBotIdInboxByIdErrors, DeleteBotsByBotIdInboxByIdResponses, DeleteBotsByBotIdMcpByIdData, DeleteBotsByBotIdMcpByIdError, DeleteBotsByBotIdMcpByIdErrors, DeleteBotsByBotIdMcpByIdResponses, DeleteBotsByBotIdMemoryByIdData, DeleteBotsByBotIdMemoryByIdError, DeleteBotsByBotIdMemoryByIdErrors, DeleteBotsByBotIdMemoryByIdResponse, DeleteBotsByBotIdMemoryByIdResponses, DeleteBotsByBotIdMemoryData, DeleteBotsByBotIdMemoryError, DeleteBotsByBotIdMemoryErrors, DeleteBotsByBotIdMemoryResponse, DeleteBotsByBotIdMemoryResponses, DeleteBotsByBotIdMessagesData, DeleteBotsByBotIdMessagesError, DeleteBotsByBotIdMessagesErrors, DeleteBotsByBotIdMessagesResponses, DeleteBotsByBotIdScheduleByIdData, DeleteBotsByBotIdScheduleByIdError, DeleteBotsByBotIdScheduleByIdErrors, DeleteBotsByBotIdScheduleByIdResponses, DeleteBotsByBotIdSettingsData, DeleteBotsByBotIdSettingsError, DeleteBotsByBotIdSettingsErrors, DeleteBotsByBotIdSettingsResponses, DeleteBotsByBotIdSubagentsByIdData, DeleteBotsByBotIdSubagentsByIdError, DeleteBotsByBotIdSubagentsByIdErrors, DeleteBotsByBotIdSubagentsByIdResponses, DeleteBotsByIdChannelByPlatformData, DeleteBotsByIdChannelByPlatformError, DeleteBotsByIdChannelByPlatformErrors, DeleteBotsByIdChannelByPlatformResponses, DeleteBotsByIdData, DeleteBotsByIdError, DeleteBotsByIdErrors, DeleteBotsByIdMembersByUserIdData, DeleteBotsByIdMembersByUserIdError, DeleteBotsByIdMembersByUserIdErrors, DeleteBotsByIdMembersByUserIdResponses, DeleteBotsByIdResponse, DeleteBotsByIdResponses, DeleteModelsByIdData, DeleteModelsByIdError, DeleteModelsByIdErrors, DeleteModelsByIdResponses, DeleteModelsModelByModelIdData, DeleteModelsModelByModelIdError, DeleteModelsModelByModelIdErrors, DeleteModelsModelByModelIdResponses, DeleteProvidersByIdData, DeleteProvidersByIdError, DeleteProvidersByIdErrors, DeleteProvidersByIdResponses, DeleteSearchProvidersByIdData, DeleteSearchProvidersByIdError, DeleteSearchProvidersByIdErrors, DeleteSearchProvidersByIdResponses, GetBotsByBotIdCliStreamData, GetBotsByBotIdCliStreamError, GetBotsByBotIdCliStreamErrors, GetBotsByBotIdCliStreamResponse, GetBotsByBotIdCliStreamResponses, GetBotsByBotIdContainerData, GetBotsByBotIdContainerError, GetBotsByBotIdContainerErrors, GetBotsByBotIdContainerFsData, GetBotsByBotIdContainerFsDownloadData, GetBotsByBotIdContainerFsDownloadError, GetBotsByBotIdContainerFsDownloadErrors, GetBotsByBotIdContainerFsDownloadResponses, GetBotsByBotIdContainerFsError, GetBotsByBotIdContainerFsErrors, GetBotsByBotIdContainerFsListData, GetBotsByBotIdContainerFsListError, GetBotsByBotIdContainerFsListErrors, GetBotsByBotIdContainerFsListResponse, GetBotsByBotIdContainerFsListResponses, GetBotsByBotIdContainerFsReadData, GetBotsByBotIdContainerFsReadError, GetBotsByBotIdContainerFsReadErrors, GetBotsByBotIdContainerFsReadResponse, GetBotsByBotIdContainerFsReadResponses, GetBotsByBotIdContainerFsResponse, GetBotsByBotIdContainerFsResponses, GetBotsByBotIdContainerResponse, GetBotsByBotIdContainerResponses, GetBotsByBotIdContainerSkillsData, GetBotsByBotIdContainerSkillsError, GetBotsByBotIdContainerSkillsErrors, GetBotsByBotIdContainerSkillsResponse, GetBotsByBotIdContainerSkillsResponses, GetBotsByBotIdContainerSnapshotsData, GetBotsByBotIdContainerSnapshotsResponse, GetBotsByBotIdContainerSnapshotsResponses, GetBotsByBotIdInboxByIdData, GetBotsByBotIdInboxByIdError, GetBotsByBotIdInboxByIdErrors, GetBotsByBotIdInboxByIdResponse, GetBotsByBotIdInboxByIdResponses, GetBotsByBotIdInboxCountData, GetBotsByBotIdInboxCountError, GetBotsByBotIdInboxCountErrors, GetBotsByBotIdInboxCountResponse, GetBotsByBotIdInboxCountResponses, GetBotsByBotIdInboxData, GetBotsByBotIdInboxError, GetBotsByBotIdInboxErrors, GetBotsByBotIdInboxResponse, GetBotsByBotIdInboxResponses, GetBotsByBotIdMcpByIdData, GetBotsByBotIdMcpByIdError, GetBotsByBotIdMcpByIdErrors, GetBotsByBotIdMcpByIdResponse, GetBotsByBotIdMcpByIdResponses, GetBotsByBotIdMcpData, GetBotsByBotIdMcpError, GetBotsByBotIdMcpErrors, GetBotsByBotIdMcpExportData, GetBotsByBotIdMcpExportError, GetBotsByBotIdMcpExportErrors, GetBotsByBotIdMcpExportResponse, GetBotsByBotIdMcpExportResponses, GetBotsByBotIdMcpResponse, GetBotsByBotIdMcpResponses, GetBotsByBotIdMemoryData, GetBotsByBotIdMemoryError, GetBotsByBotIdMemoryErrors, GetBotsByBotIdMemoryResponse, GetBotsByBotIdMemoryResponses, GetBotsByBotIdMemoryUsageData, GetBotsByBotIdMemoryUsageError, GetBotsByBotIdMemoryUsageErrors, GetBotsByBotIdMemoryUsageResponse, GetBotsByBotIdMemoryUsageResponses, GetBotsByBotIdMessagesData, GetBotsByBotIdMessagesError, GetBotsByBotIdMessagesErrors, GetBotsByBotIdMessagesResponse, GetBotsByBotIdMessagesResponses, GetBotsByBotIdScheduleByIdData, GetBotsByBotIdScheduleByIdError, GetBotsByBotIdScheduleByIdErrors, GetBotsByBotIdScheduleByIdResponse, GetBotsByBotIdScheduleByIdResponses, GetBotsByBotIdScheduleData, GetBotsByBotIdScheduleError, GetBotsByBotIdScheduleErrors, GetBotsByBotIdScheduleResponse, GetBotsByBotIdScheduleResponses, GetBotsByBotIdSettingsData, GetBotsByBotIdSettingsError, GetBotsByBotIdSettingsErrors, GetBotsByBotIdSettingsResponse, GetBotsByBotIdSettingsResponses, GetBotsByBotIdSubagentsByIdContextData, GetBotsByBotIdSubagentsByIdContextError, GetBotsByBotIdSubagentsByIdContextErrors, GetBotsByBotIdSubagentsByIdContextResponse, GetBotsByBotIdSubagentsByIdContextResponses, GetBotsByBotIdSubagentsByIdData, GetBotsByBotIdSubagentsByIdError, GetBotsByBotIdSubagentsByIdErrors, GetBotsByBotIdSubagentsByIdResponse, GetBotsByBotIdSubagentsByIdResponses, GetBotsByBotIdSubagentsByIdSkillsData, GetBotsByBotIdSubagentsByIdSkillsError, GetBotsByBotIdSubagentsByIdSkillsErrors, GetBotsByBotIdSubagentsByIdSkillsResponse, GetBotsByBotIdSubagentsByIdSkillsResponses, GetBotsByBotIdSubagentsData, GetBotsByBotIdSubagentsError, GetBotsByBotIdSubagentsErrors, GetBotsByBotIdSubagentsResponse, GetBotsByBotIdSubagentsResponses, GetBotsByBotIdWebStreamData, GetBotsByBotIdWebStreamError, GetBotsByBotIdWebStreamErrors, GetBotsByBotIdWebStreamResponse, GetBotsByBotIdWebStreamResponses, GetBotsByIdChannelByPlatformData, GetBotsByIdChannelByPlatformError, GetBotsByIdChannelByPlatformErrors, GetBotsByIdChannelByPlatformResponse, GetBotsByIdChannelByPlatformResponses, GetBotsByIdChecksData, GetBotsByIdChecksError, GetBotsByIdChecksErrors, GetBotsByIdChecksResponse, GetBotsByIdChecksResponses, GetBotsByIdData, GetBotsByIdError, GetBotsByIdErrors, GetBotsByIdMembersData, GetBotsByIdMembersError, GetBotsByIdMembersErrors, GetBotsByIdMembersResponse, GetBotsByIdMembersResponses, GetBotsByIdResponse, GetBotsByIdResponses, GetBotsData, GetBotsError, GetBotsErrors, GetBotsResponse, GetBotsResponses, GetChannelsByPlatformData, GetChannelsByPlatformError, GetChannelsByPlatformErrors, GetChannelsByPlatformResponse, GetChannelsByPlatformResponses, GetChannelsData, GetChannelsError, GetChannelsErrors, GetChannelsResponse, GetChannelsResponses, GetModelsByIdData, GetModelsByIdError, GetModelsByIdErrors, GetModelsByIdResponse, GetModelsByIdResponses, GetModelsCountData, GetModelsCountError, GetModelsCountErrors, GetModelsCountResponse, GetModelsCountResponses, GetModelsData, GetModelsError, GetModelsErrors, GetModelsModelByModelIdData, GetModelsModelByModelIdError, GetModelsModelByModelIdErrors, GetModelsModelByModelIdResponse, GetModelsModelByModelIdResponses, GetModelsResponse, GetModelsResponses, GetProvidersByIdData, GetProvidersByIdError, GetProvidersByIdErrors, GetProvidersByIdModelsData, GetProvidersByIdModelsError, GetProvidersByIdModelsErrors, GetProvidersByIdModelsResponse, GetProvidersByIdModelsResponses, GetProvidersByIdResponse, GetProvidersByIdResponses, GetProvidersCountData, GetProvidersCountError, GetProvidersCountErrors, GetProvidersCountResponse, GetProvidersCountResponses, GetProvidersData, GetProvidersError, GetProvidersErrors, GetProvidersNameByNameData, GetProvidersNameByNameError, GetProvidersNameByNameErrors, GetProvidersNameByNameResponse, GetProvidersNameByNameResponses, GetProvidersResponse, GetProvidersResponses, GetSearchProvidersByIdData, GetSearchProvidersByIdError, GetSearchProvidersByIdErrors, GetSearchProvidersByIdResponse, GetSearchProvidersByIdResponses, GetSearchProvidersData, GetSearchProvidersError, GetSearchProvidersErrors, GetSearchProvidersMetaData, GetSearchProvidersMetaResponse, GetSearchProvidersMetaResponses, GetSearchProvidersResponse, GetSearchProvidersResponses, GetUsersByIdData, GetUsersByIdError, GetUsersByIdErrors, GetUsersByIdResponse, GetUsersByIdResponses, GetUsersData, GetUsersError, GetUsersErrors, GetUsersMeChannelsByPlatformData, GetUsersMeChannelsByPlatformError, GetUsersMeChannelsByPlatformErrors, GetUsersMeChannelsByPlatformResponse, GetUsersMeChannelsByPlatformResponses, GetUsersMeData, GetUsersMeError, GetUsersMeErrors, GetUsersMeIdentitiesData, GetUsersMeIdentitiesError, GetUsersMeIdentitiesErrors, GetUsersMeIdentitiesResponse, GetUsersMeIdentitiesResponses, GetUsersMeResponse, GetUsersMeResponses, GetUsersResponse, GetUsersResponses, GithubComMemohaiMemohInternalMcpConnection, HandlersBatchDeleteRequest, HandlersChannelMeta, HandlersCreateContainerRequest, HandlersCreateContainerResponse, HandlersCreateSnapshotRequest, HandlersCreateSnapshotResponse, HandlersEmbeddingsInput, HandlersEmbeddingsRequest, HandlersEmbeddingsResponse, HandlersEmbeddingsUsage, HandlersErrorResponse, HandlersFsDeleteRequest, HandlersFsFileInfo, HandlersFsListResponse, HandlersFsMkdirRequest, HandlersFsOpResponse, HandlersFsReadResponse, HandlersFsRenameRequest, HandlersFsUploadResponse, HandlersFsWriteRequest, HandlersGetContainerResponse, HandlersListMyIdentitiesResponse, HandlersListSnapshotsResponse, HandlersLocalChannelMessageRequest, HandlersLoginRequest, HandlersLoginResponse, HandlersMarkReadRequest, HandlersMcpStdioRequest, HandlersMcpStdioResponse, HandlersMemoryAddPayload, HandlersMemoryCompactPayload, HandlersMemoryDeletePayload, HandlersMemorySearchPayload, HandlersSkillItem, HandlersSkillsDeleteRequest, HandlersSkillsOpResponse, HandlersSkillsResponse, HandlersSkillsUpsertRequest, HandlersSnapshotInfo, IdentitiesChannelIdentity, InboxCountResult, InboxCreateRequest, InboxItem, McpExportResponse, McpImportRequest, McpListResponse, McpMcpServerEntry, McpUpsertRequest, MemoryCdfPoint, MemoryCompactResult, MemoryDeleteResponse, MemoryMemoryItem, MemoryMessage, MemoryRebuildResult, MemorySearchResponse, MemoryTopKBucket, MemoryUsageResponse, MessageMessage, MessageMessageAsset, ModelsAddRequest, ModelsAddResponse, ModelsClientType, ModelsCountResponse, ModelsGetResponse, ModelsModelType, ModelsUpdateRequest, PatchBotsByIdChannelByPlatformStatusData, PatchBotsByIdChannelByPlatformStatusError, PatchBotsByIdChannelByPlatformStatusErrors, PatchBotsByIdChannelByPlatformStatusResponse, PatchBotsByIdChannelByPlatformStatusResponses, PostAuthLoginData, PostAuthLoginError, PostAuthLoginErrors, PostAuthLoginResponse, PostAuthLoginResponses, PostBotsByBotIdCliMessagesData, PostBotsByBotIdCliMessagesError, PostBotsByBotIdCliMessagesErrors, PostBotsByBotIdCliMessagesResponse, PostBotsByBotIdCliMessagesResponses, PostBotsByBotIdContainerData, PostBotsByBotIdContainerError, PostBotsByBotIdContainerErrors, PostBotsByBotIdContainerFsDeleteData, PostBotsByBotIdContainerFsDeleteError, PostBotsByBotIdContainerFsDeleteErrors, PostBotsByBotIdContainerFsDeleteResponse, PostBotsByBotIdContainerFsDeleteResponses, PostBotsByBotIdContainerFsMkdirData, PostBotsByBotIdContainerFsMkdirError, PostBotsByBotIdContainerFsMkdirErrors, PostBotsByBotIdContainerFsMkdirResponse, PostBotsByBotIdContainerFsMkdirResponses, PostBotsByBotIdContainerFsRenameData, PostBotsByBotIdContainerFsRenameError, PostBotsByBotIdContainerFsRenameErrors, PostBotsByBotIdContainerFsRenameResponse, PostBotsByBotIdContainerFsRenameResponses, PostBotsByBotIdContainerFsUploadData, PostBotsByBotIdContainerFsUploadError, PostBotsByBotIdContainerFsUploadErrors, PostBotsByBotIdContainerFsUploadResponse, PostBotsByBotIdContainerFsUploadResponses, PostBotsByBotIdContainerFsWriteData, PostBotsByBotIdContainerFsWriteError, PostBotsByBotIdContainerFsWriteErrors, PostBotsByBotIdContainerFsWriteResponse, PostBotsByBotIdContainerFsWriteResponses, PostBotsByBotIdContainerResponse, PostBotsByBotIdContainerResponses, PostBotsByBotIdContainerSkillsData, PostBotsByBotIdContainerSkillsError, PostBotsByBotIdContainerSkillsErrors, PostBotsByBotIdContainerSkillsResponse, PostBotsByBotIdContainerSkillsResponses, PostBotsByBotIdContainerSnapshotsData, PostBotsByBotIdContainerSnapshotsError, PostBotsByBotIdContainerSnapshotsErrors, PostBotsByBotIdContainerSnapshotsResponse, PostBotsByBotIdContainerSnapshotsResponses, PostBotsByBotIdContainerStartData, PostBotsByBotIdContainerStartError, PostBotsByBotIdContainerStartErrors, PostBotsByBotIdContainerStartResponse, PostBotsByBotIdContainerStartResponses, PostBotsByBotIdContainerStopData, PostBotsByBotIdContainerStopError, PostBotsByBotIdContainerStopErrors, PostBotsByBotIdContainerStopResponse, PostBotsByBotIdContainerStopResponses, PostBotsByBotIdInboxData, PostBotsByBotIdInboxError, PostBotsByBotIdInboxErrors, PostBotsByBotIdInboxMarkReadData, PostBotsByBotIdInboxMarkReadError, PostBotsByBotIdInboxMarkReadErrors, PostBotsByBotIdInboxMarkReadResponses, PostBotsByBotIdInboxResponse, PostBotsByBotIdInboxResponses, PostBotsByBotIdMcpData, PostBotsByBotIdMcpError, PostBotsByBotIdMcpErrors, PostBotsByBotIdMcpOpsBatchDeleteData, PostBotsByBotIdMcpOpsBatchDeleteError, PostBotsByBotIdMcpOpsBatchDeleteErrors, PostBotsByBotIdMcpOpsBatchDeleteResponses, PostBotsByBotIdMcpResponse, PostBotsByBotIdMcpResponses, PostBotsByBotIdMcpStdioByConnectionIdData, PostBotsByBotIdMcpStdioByConnectionIdError, PostBotsByBotIdMcpStdioByConnectionIdErrors, PostBotsByBotIdMcpStdioByConnectionIdResponse, PostBotsByBotIdMcpStdioByConnectionIdResponses, PostBotsByBotIdMcpStdioData, PostBotsByBotIdMcpStdioError, PostBotsByBotIdMcpStdioErrors, PostBotsByBotIdMcpStdioResponse, PostBotsByBotIdMcpStdioResponses, PostBotsByBotIdMemoryCompactData, PostBotsByBotIdMemoryCompactError, PostBotsByBotIdMemoryCompactErrors, PostBotsByBotIdMemoryCompactResponse, PostBotsByBotIdMemoryCompactResponses, PostBotsByBotIdMemoryData, PostBotsByBotIdMemoryError, PostBotsByBotIdMemoryErrors, PostBotsByBotIdMemoryRebuildData, PostBotsByBotIdMemoryRebuildError, PostBotsByBotIdMemoryRebuildErrors, PostBotsByBotIdMemoryRebuildResponse, PostBotsByBotIdMemoryRebuildResponses, PostBotsByBotIdMemoryResponse, PostBotsByBotIdMemoryResponses, PostBotsByBotIdMemorySearchData, PostBotsByBotIdMemorySearchError, PostBotsByBotIdMemorySearchErrors, PostBotsByBotIdMemorySearchResponse, PostBotsByBotIdMemorySearchResponses, PostBotsByBotIdScheduleData, PostBotsByBotIdScheduleError, PostBotsByBotIdScheduleErrors, PostBotsByBotIdScheduleResponse, PostBotsByBotIdScheduleResponses, PostBotsByBotIdSettingsData, PostBotsByBotIdSettingsError, PostBotsByBotIdSettingsErrors, PostBotsByBotIdSettingsResponse, PostBotsByBotIdSettingsResponses, PostBotsByBotIdSubagentsByIdSkillsData, PostBotsByBotIdSubagentsByIdSkillsError, PostBotsByBotIdSubagentsByIdSkillsErrors, PostBotsByBotIdSubagentsByIdSkillsResponse, PostBotsByBotIdSubagentsByIdSkillsResponses, PostBotsByBotIdSubagentsData, PostBotsByBotIdSubagentsError, PostBotsByBotIdSubagentsErrors, PostBotsByBotIdSubagentsResponse, PostBotsByBotIdSubagentsResponses, PostBotsByBotIdToolsData, PostBotsByBotIdToolsError, PostBotsByBotIdToolsErrors, PostBotsByBotIdToolsResponse, PostBotsByBotIdToolsResponses, PostBotsByBotIdWebMessagesData, PostBotsByBotIdWebMessagesError, PostBotsByBotIdWebMessagesErrors, PostBotsByBotIdWebMessagesResponse, PostBotsByBotIdWebMessagesResponses, PostBotsByIdChannelByPlatformSendChatData, PostBotsByIdChannelByPlatformSendChatError, PostBotsByIdChannelByPlatformSendChatErrors, PostBotsByIdChannelByPlatformSendChatResponse, PostBotsByIdChannelByPlatformSendChatResponses, PostBotsByIdChannelByPlatformSendData, PostBotsByIdChannelByPlatformSendError, PostBotsByIdChannelByPlatformSendErrors, PostBotsByIdChannelByPlatformSendResponse, PostBotsByIdChannelByPlatformSendResponses, PostBotsData, PostBotsError, PostBotsErrors, PostBotsResponse, PostBotsResponses, PostEmbeddingsData, PostEmbeddingsError, PostEmbeddingsErrors, PostEmbeddingsResponse, PostEmbeddingsResponses, PostModelsData, PostModelsError, PostModelsErrors, PostModelsResponse, PostModelsResponses, PostProvidersByIdTestData, PostProvidersByIdTestError, PostProvidersByIdTestErrors, PostProvidersByIdTestResponse, PostProvidersByIdTestResponses, PostProvidersData, PostProvidersError, PostProvidersErrors, PostProvidersResponse, PostProvidersResponses, PostSearchProvidersData, PostSearchProvidersError, PostSearchProvidersErrors, PostSearchProvidersResponse, PostSearchProvidersResponses, PostUsersData, PostUsersError, PostUsersErrors, PostUsersResponse, PostUsersResponses, ProvidersCheckResult, ProvidersCheckStatus, ProvidersCountResponse, ProvidersCreateRequest, ProvidersGetResponse, ProvidersTestResponse, ProvidersUpdateRequest, PutBotsByBotIdMcpByIdData, PutBotsByBotIdMcpByIdError, PutBotsByBotIdMcpByIdErrors, PutBotsByBotIdMcpByIdResponse, PutBotsByBotIdMcpByIdResponses, PutBotsByBotIdMcpImportData, PutBotsByBotIdMcpImportError, PutBotsByBotIdMcpImportErrors, PutBotsByBotIdMcpImportResponse, PutBotsByBotIdMcpImportResponses, PutBotsByBotIdScheduleByIdData, PutBotsByBotIdScheduleByIdError, PutBotsByBotIdScheduleByIdErrors, PutBotsByBotIdScheduleByIdResponse, PutBotsByBotIdScheduleByIdResponses, PutBotsByBotIdSettingsData, PutBotsByBotIdSettingsError, PutBotsByBotIdSettingsErrors, PutBotsByBotIdSettingsResponse, PutBotsByBotIdSettingsResponses, PutBotsByBotIdSubagentsByIdContextData, PutBotsByBotIdSubagentsByIdContextError, PutBotsByBotIdSubagentsByIdContextErrors, PutBotsByBotIdSubagentsByIdContextResponse, PutBotsByBotIdSubagentsByIdContextResponses, PutBotsByBotIdSubagentsByIdData, PutBotsByBotIdSubagentsByIdError, PutBotsByBotIdSubagentsByIdErrors, PutBotsByBotIdSubagentsByIdResponse, PutBotsByBotIdSubagentsByIdResponses, PutBotsByBotIdSubagentsByIdSkillsData, PutBotsByBotIdSubagentsByIdSkillsError, PutBotsByBotIdSubagentsByIdSkillsErrors, PutBotsByBotIdSubagentsByIdSkillsResponse, PutBotsByBotIdSubagentsByIdSkillsResponses, PutBotsByIdChannelByPlatformData, PutBotsByIdChannelByPlatformError, PutBotsByIdChannelByPlatformErrors, PutBotsByIdChannelByPlatformResponse, PutBotsByIdChannelByPlatformResponses, PutBotsByIdData, PutBotsByIdError, PutBotsByIdErrors, PutBotsByIdMembersData, PutBotsByIdMembersError, PutBotsByIdMembersErrors, PutBotsByIdMembersResponse, PutBotsByIdMembersResponses, PutBotsByIdOwnerData, PutBotsByIdOwnerError, PutBotsByIdOwnerErrors, PutBotsByIdOwnerResponse, PutBotsByIdOwnerResponses, PutBotsByIdResponse, PutBotsByIdResponses, PutModelsByIdData, PutModelsByIdError, PutModelsByIdErrors, PutModelsByIdResponse, PutModelsByIdResponses, PutModelsModelByModelIdData, PutModelsModelByModelIdError, PutModelsModelByModelIdErrors, PutModelsModelByModelIdResponse, PutModelsModelByModelIdResponses, PutProvidersByIdData, PutProvidersByIdError, PutProvidersByIdErrors, PutProvidersByIdResponse, PutProvidersByIdResponses, PutSearchProvidersByIdData, PutSearchProvidersByIdError, PutSearchProvidersByIdErrors, PutSearchProvidersByIdResponse, PutSearchProvidersByIdResponses, PutUsersByIdData, PutUsersByIdError, PutUsersByIdErrors, PutUsersByIdPasswordData, PutUsersByIdPasswordError, PutUsersByIdPasswordErrors, PutUsersByIdPasswordResponses, PutUsersByIdResponse, PutUsersByIdResponses, PutUsersMeChannelsByPlatformData, PutUsersMeChannelsByPlatformError, PutUsersMeChannelsByPlatformErrors, PutUsersMeChannelsByPlatformResponse, PutUsersMeChannelsByPlatformResponses, PutUsersMeData, PutUsersMeError, PutUsersMeErrors, PutUsersMePasswordData, PutUsersMePasswordError, PutUsersMePasswordErrors, PutUsersMePasswordResponses, PutUsersMeResponse, PutUsersMeResponses, ScheduleCreateRequest, ScheduleListResponse, ScheduleNullableInt, ScheduleSchedule, ScheduleUpdateRequest, SearchprovidersCreateRequest, SearchprovidersGetResponse, SearchprovidersProviderConfigSchema, SearchprovidersProviderFieldSchema, SearchprovidersProviderMeta, SearchprovidersProviderName, SearchprovidersUpdateRequest, SettingsSettings, SettingsUpsertRequest, SubagentAddSkillsRequest, SubagentContextResponse, SubagentCreateRequest, SubagentListResponse, SubagentSkillsResponse, SubagentSubagent, SubagentUpdateContextRequest, SubagentUpdateRequest, SubagentUpdateSkillsRequest } from './types.gen'; +export { deleteBotsByBotIdContainer, deleteBotsByBotIdContainerSkills, deleteBotsByBotIdInboxById, deleteBotsByBotIdMcpById, deleteBotsByBotIdMemory, deleteBotsByBotIdMemoryById, deleteBotsByBotIdMessages, deleteBotsByBotIdScheduleById, deleteBotsByBotIdSettings, deleteBotsByBotIdSubagentsById, deleteBotsById, deleteBotsByIdChannelByPlatform, deleteBotsByIdMembersByUserId, deleteModelsById, deleteModelsModelByModelId, deleteProvidersById, deleteSearchProvidersById, getBots, getBotsByBotIdCliStream, getBotsByBotIdContainer, getBotsByBotIdContainerFs, getBotsByBotIdContainerFsDownload, getBotsByBotIdContainerFsList, getBotsByBotIdContainerFsRead, getBotsByBotIdContainerSkills, getBotsByBotIdContainerSnapshots, getBotsByBotIdInbox, getBotsByBotIdInboxById, getBotsByBotIdInboxCount, getBotsByBotIdMcp, getBotsByBotIdMcpById, getBotsByBotIdMcpExport, getBotsByBotIdMemory, getBotsByBotIdMemoryUsage, getBotsByBotIdMessages, getBotsByBotIdSchedule, getBotsByBotIdScheduleById, getBotsByBotIdSettings, getBotsByBotIdSubagents, getBotsByBotIdSubagentsById, getBotsByBotIdSubagentsByIdContext, getBotsByBotIdSubagentsByIdSkills, getBotsByBotIdWebStream, getBotsById, getBotsByIdChannelByPlatform, getBotsByIdChecks, getBotsByIdMembers, getChannels, getChannelsByPlatform, getModels, getModelsById, getModelsCount, getModelsModelByModelId, getPing, getProviders, getProvidersById, getProvidersByIdModels, getProvidersCount, getProvidersNameByName, getSearchProviders, getSearchProvidersById, getSearchProvidersMeta, getUsers, getUsersById, getUsersMe, getUsersMeChannelsByPlatform, getUsersMeIdentities, type Options, patchBotsByIdChannelByPlatformStatus, postAuthLogin, postBots, postBotsByBotIdCliMessages, postBotsByBotIdContainer, postBotsByBotIdContainerFsDelete, postBotsByBotIdContainerFsMkdir, postBotsByBotIdContainerFsRename, postBotsByBotIdContainerFsUpload, postBotsByBotIdContainerFsWrite, postBotsByBotIdContainerSkills, postBotsByBotIdContainerSnapshots, postBotsByBotIdContainerStart, postBotsByBotIdContainerStop, postBotsByBotIdInbox, postBotsByBotIdInboxMarkRead, postBotsByBotIdMcp, postBotsByBotIdMcpOpsBatchDelete, postBotsByBotIdMcpStdio, postBotsByBotIdMcpStdioByConnectionId, postBotsByBotIdMemory, postBotsByBotIdMemoryCompact, postBotsByBotIdMemoryRebuild, postBotsByBotIdMemorySearch, postBotsByBotIdSchedule, postBotsByBotIdSettings, postBotsByBotIdSubagents, postBotsByBotIdSubagentsByIdSkills, postBotsByBotIdTools, postBotsByBotIdWebMessages, postBotsByIdChannelByPlatformSend, postBotsByIdChannelByPlatformSendChat, postEmbeddings, postModels, postProviders, postProvidersByIdTest, postSearchProviders, postUsers, putBotsByBotIdMcpById, putBotsByBotIdMcpImport, putBotsByBotIdScheduleById, putBotsByBotIdSettings, putBotsByBotIdSubagentsById, putBotsByBotIdSubagentsByIdContext, putBotsByBotIdSubagentsByIdSkills, putBotsById, putBotsByIdChannelByPlatform, putBotsByIdMembers, putBotsByIdOwner, putModelsById, putModelsModelByModelId, putProvidersById, putSearchProvidersById, putUsersById, putUsersByIdPassword, putUsersMe, putUsersMeChannelsByPlatform, putUsersMePassword } from './sdk.gen'; +export type { AccountsAccount, AccountsCreateAccountRequest, AccountsListAccountsResponse, AccountsResetPasswordRequest, AccountsUpdateAccountRequest, AccountsUpdatePasswordRequest, AccountsUpdateProfileRequest, BotsBot, BotsBotCheck, BotsBotMember, BotsCreateBotRequest, BotsListBotsResponse, BotsListChecksResponse, BotsListMembersResponse, BotsTransferBotRequest, BotsUpdateBotRequest, BotsUpsertMemberRequest, ChannelAction, ChannelAttachment, ChannelAttachmentType, ChannelChannelCapabilities, ChannelChannelConfig, ChannelChannelIdentityBinding, ChannelConfigSchema, ChannelFieldSchema, ChannelFieldType, ChannelMessage, ChannelMessageFormat, ChannelMessagePart, ChannelMessagePartType, ChannelMessageTextStyle, ChannelReplyRef, ChannelSendRequest, ChannelTargetHint, ChannelTargetSpec, ChannelThreadRef, ChannelUpdateChannelStatusRequest, ChannelUpsertChannelIdentityConfigRequest, ChannelUpsertConfigRequest, ClientOptions, DeleteBotsByBotIdContainerData, DeleteBotsByBotIdContainerError, DeleteBotsByBotIdContainerErrors, DeleteBotsByBotIdContainerResponses, DeleteBotsByBotIdContainerSkillsData, DeleteBotsByBotIdContainerSkillsError, DeleteBotsByBotIdContainerSkillsErrors, DeleteBotsByBotIdContainerSkillsResponse, DeleteBotsByBotIdContainerSkillsResponses, DeleteBotsByBotIdInboxByIdData, DeleteBotsByBotIdInboxByIdError, DeleteBotsByBotIdInboxByIdErrors, DeleteBotsByBotIdInboxByIdResponses, DeleteBotsByBotIdMcpByIdData, DeleteBotsByBotIdMcpByIdError, DeleteBotsByBotIdMcpByIdErrors, DeleteBotsByBotIdMcpByIdResponses, DeleteBotsByBotIdMemoryByIdData, DeleteBotsByBotIdMemoryByIdError, DeleteBotsByBotIdMemoryByIdErrors, DeleteBotsByBotIdMemoryByIdResponse, DeleteBotsByBotIdMemoryByIdResponses, DeleteBotsByBotIdMemoryData, DeleteBotsByBotIdMemoryError, DeleteBotsByBotIdMemoryErrors, DeleteBotsByBotIdMemoryResponse, DeleteBotsByBotIdMemoryResponses, DeleteBotsByBotIdMessagesData, DeleteBotsByBotIdMessagesError, DeleteBotsByBotIdMessagesErrors, DeleteBotsByBotIdMessagesResponses, DeleteBotsByBotIdScheduleByIdData, DeleteBotsByBotIdScheduleByIdError, DeleteBotsByBotIdScheduleByIdErrors, DeleteBotsByBotIdScheduleByIdResponses, DeleteBotsByBotIdSettingsData, DeleteBotsByBotIdSettingsError, DeleteBotsByBotIdSettingsErrors, DeleteBotsByBotIdSettingsResponses, DeleteBotsByBotIdSubagentsByIdData, DeleteBotsByBotIdSubagentsByIdError, DeleteBotsByBotIdSubagentsByIdErrors, DeleteBotsByBotIdSubagentsByIdResponses, DeleteBotsByIdChannelByPlatformData, DeleteBotsByIdChannelByPlatformError, DeleteBotsByIdChannelByPlatformErrors, DeleteBotsByIdChannelByPlatformResponses, DeleteBotsByIdData, DeleteBotsByIdError, DeleteBotsByIdErrors, DeleteBotsByIdMembersByUserIdData, DeleteBotsByIdMembersByUserIdError, DeleteBotsByIdMembersByUserIdErrors, DeleteBotsByIdMembersByUserIdResponses, DeleteBotsByIdResponse, DeleteBotsByIdResponses, DeleteModelsByIdData, DeleteModelsByIdError, DeleteModelsByIdErrors, DeleteModelsByIdResponses, DeleteModelsModelByModelIdData, DeleteModelsModelByModelIdError, DeleteModelsModelByModelIdErrors, DeleteModelsModelByModelIdResponses, DeleteProvidersByIdData, DeleteProvidersByIdError, DeleteProvidersByIdErrors, DeleteProvidersByIdResponses, DeleteSearchProvidersByIdData, DeleteSearchProvidersByIdError, DeleteSearchProvidersByIdErrors, DeleteSearchProvidersByIdResponses, GetBotsByBotIdCliStreamData, GetBotsByBotIdCliStreamError, GetBotsByBotIdCliStreamErrors, GetBotsByBotIdCliStreamResponse, GetBotsByBotIdCliStreamResponses, GetBotsByBotIdContainerData, GetBotsByBotIdContainerError, GetBotsByBotIdContainerErrors, GetBotsByBotIdContainerFsData, GetBotsByBotIdContainerFsDownloadData, GetBotsByBotIdContainerFsDownloadError, GetBotsByBotIdContainerFsDownloadErrors, GetBotsByBotIdContainerFsDownloadResponses, GetBotsByBotIdContainerFsError, GetBotsByBotIdContainerFsErrors, GetBotsByBotIdContainerFsListData, GetBotsByBotIdContainerFsListError, GetBotsByBotIdContainerFsListErrors, GetBotsByBotIdContainerFsListResponse, GetBotsByBotIdContainerFsListResponses, GetBotsByBotIdContainerFsReadData, GetBotsByBotIdContainerFsReadError, GetBotsByBotIdContainerFsReadErrors, GetBotsByBotIdContainerFsReadResponse, GetBotsByBotIdContainerFsReadResponses, GetBotsByBotIdContainerFsResponse, GetBotsByBotIdContainerFsResponses, GetBotsByBotIdContainerResponse, GetBotsByBotIdContainerResponses, GetBotsByBotIdContainerSkillsData, GetBotsByBotIdContainerSkillsError, GetBotsByBotIdContainerSkillsErrors, GetBotsByBotIdContainerSkillsResponse, GetBotsByBotIdContainerSkillsResponses, GetBotsByBotIdContainerSnapshotsData, GetBotsByBotIdContainerSnapshotsError, GetBotsByBotIdContainerSnapshotsErrors, GetBotsByBotIdContainerSnapshotsResponse, GetBotsByBotIdContainerSnapshotsResponses, GetBotsByBotIdInboxByIdData, GetBotsByBotIdInboxByIdError, GetBotsByBotIdInboxByIdErrors, GetBotsByBotIdInboxByIdResponse, GetBotsByBotIdInboxByIdResponses, GetBotsByBotIdInboxCountData, GetBotsByBotIdInboxCountError, GetBotsByBotIdInboxCountErrors, GetBotsByBotIdInboxCountResponse, GetBotsByBotIdInboxCountResponses, GetBotsByBotIdInboxData, GetBotsByBotIdInboxError, GetBotsByBotIdInboxErrors, GetBotsByBotIdInboxResponse, GetBotsByBotIdInboxResponses, GetBotsByBotIdMcpByIdData, GetBotsByBotIdMcpByIdError, GetBotsByBotIdMcpByIdErrors, GetBotsByBotIdMcpByIdResponse, GetBotsByBotIdMcpByIdResponses, GetBotsByBotIdMcpData, GetBotsByBotIdMcpError, GetBotsByBotIdMcpErrors, GetBotsByBotIdMcpExportData, GetBotsByBotIdMcpExportError, GetBotsByBotIdMcpExportErrors, GetBotsByBotIdMcpExportResponse, GetBotsByBotIdMcpExportResponses, GetBotsByBotIdMcpResponse, GetBotsByBotIdMcpResponses, GetBotsByBotIdMemoryData, GetBotsByBotIdMemoryError, GetBotsByBotIdMemoryErrors, GetBotsByBotIdMemoryResponse, GetBotsByBotIdMemoryResponses, GetBotsByBotIdMemoryUsageData, GetBotsByBotIdMemoryUsageError, GetBotsByBotIdMemoryUsageErrors, GetBotsByBotIdMemoryUsageResponse, GetBotsByBotIdMemoryUsageResponses, GetBotsByBotIdMessagesData, GetBotsByBotIdMessagesError, GetBotsByBotIdMessagesErrors, GetBotsByBotIdMessagesResponse, GetBotsByBotIdMessagesResponses, GetBotsByBotIdScheduleByIdData, GetBotsByBotIdScheduleByIdError, GetBotsByBotIdScheduleByIdErrors, GetBotsByBotIdScheduleByIdResponse, GetBotsByBotIdScheduleByIdResponses, GetBotsByBotIdScheduleData, GetBotsByBotIdScheduleError, GetBotsByBotIdScheduleErrors, GetBotsByBotIdScheduleResponse, GetBotsByBotIdScheduleResponses, GetBotsByBotIdSettingsData, GetBotsByBotIdSettingsError, GetBotsByBotIdSettingsErrors, GetBotsByBotIdSettingsResponse, GetBotsByBotIdSettingsResponses, GetBotsByBotIdSubagentsByIdContextData, GetBotsByBotIdSubagentsByIdContextError, GetBotsByBotIdSubagentsByIdContextErrors, GetBotsByBotIdSubagentsByIdContextResponse, GetBotsByBotIdSubagentsByIdContextResponses, GetBotsByBotIdSubagentsByIdData, GetBotsByBotIdSubagentsByIdError, GetBotsByBotIdSubagentsByIdErrors, GetBotsByBotIdSubagentsByIdResponse, GetBotsByBotIdSubagentsByIdResponses, GetBotsByBotIdSubagentsByIdSkillsData, GetBotsByBotIdSubagentsByIdSkillsError, GetBotsByBotIdSubagentsByIdSkillsErrors, GetBotsByBotIdSubagentsByIdSkillsResponse, GetBotsByBotIdSubagentsByIdSkillsResponses, GetBotsByBotIdSubagentsData, GetBotsByBotIdSubagentsError, GetBotsByBotIdSubagentsErrors, GetBotsByBotIdSubagentsResponse, GetBotsByBotIdSubagentsResponses, GetBotsByBotIdWebStreamData, GetBotsByBotIdWebStreamError, GetBotsByBotIdWebStreamErrors, GetBotsByBotIdWebStreamResponse, GetBotsByBotIdWebStreamResponses, GetBotsByIdChannelByPlatformData, GetBotsByIdChannelByPlatformError, GetBotsByIdChannelByPlatformErrors, GetBotsByIdChannelByPlatformResponse, GetBotsByIdChannelByPlatformResponses, GetBotsByIdChecksData, GetBotsByIdChecksError, GetBotsByIdChecksErrors, GetBotsByIdChecksResponse, GetBotsByIdChecksResponses, GetBotsByIdData, GetBotsByIdError, GetBotsByIdErrors, GetBotsByIdMembersData, GetBotsByIdMembersError, GetBotsByIdMembersErrors, GetBotsByIdMembersResponse, GetBotsByIdMembersResponses, GetBotsByIdResponse, GetBotsByIdResponses, GetBotsData, GetBotsError, GetBotsErrors, GetBotsResponse, GetBotsResponses, GetChannelsByPlatformData, GetChannelsByPlatformError, GetChannelsByPlatformErrors, GetChannelsByPlatformResponse, GetChannelsByPlatformResponses, GetChannelsData, GetChannelsError, GetChannelsErrors, GetChannelsResponse, GetChannelsResponses, GetModelsByIdData, GetModelsByIdError, GetModelsByIdErrors, GetModelsByIdResponse, GetModelsByIdResponses, GetModelsCountData, GetModelsCountError, GetModelsCountErrors, GetModelsCountResponse, GetModelsCountResponses, GetModelsData, GetModelsError, GetModelsErrors, GetModelsModelByModelIdData, GetModelsModelByModelIdError, GetModelsModelByModelIdErrors, GetModelsModelByModelIdResponse, GetModelsModelByModelIdResponses, GetModelsResponse, GetModelsResponses, GetPingData, GetPingResponse, GetPingResponses, GetProvidersByIdData, GetProvidersByIdError, GetProvidersByIdErrors, GetProvidersByIdModelsData, GetProvidersByIdModelsError, GetProvidersByIdModelsErrors, GetProvidersByIdModelsResponse, GetProvidersByIdModelsResponses, GetProvidersByIdResponse, GetProvidersByIdResponses, GetProvidersCountData, GetProvidersCountError, GetProvidersCountErrors, GetProvidersCountResponse, GetProvidersCountResponses, GetProvidersData, GetProvidersError, GetProvidersErrors, GetProvidersNameByNameData, GetProvidersNameByNameError, GetProvidersNameByNameErrors, GetProvidersNameByNameResponse, GetProvidersNameByNameResponses, GetProvidersResponse, GetProvidersResponses, GetSearchProvidersByIdData, GetSearchProvidersByIdError, GetSearchProvidersByIdErrors, GetSearchProvidersByIdResponse, GetSearchProvidersByIdResponses, GetSearchProvidersData, GetSearchProvidersError, GetSearchProvidersErrors, GetSearchProvidersMetaData, GetSearchProvidersMetaResponse, GetSearchProvidersMetaResponses, GetSearchProvidersResponse, GetSearchProvidersResponses, GetUsersByIdData, GetUsersByIdError, GetUsersByIdErrors, GetUsersByIdResponse, GetUsersByIdResponses, GetUsersData, GetUsersError, GetUsersErrors, GetUsersMeChannelsByPlatformData, GetUsersMeChannelsByPlatformError, GetUsersMeChannelsByPlatformErrors, GetUsersMeChannelsByPlatformResponse, GetUsersMeChannelsByPlatformResponses, GetUsersMeData, GetUsersMeError, GetUsersMeErrors, GetUsersMeIdentitiesData, GetUsersMeIdentitiesError, GetUsersMeIdentitiesErrors, GetUsersMeIdentitiesResponse, GetUsersMeIdentitiesResponses, GetUsersMeResponse, GetUsersMeResponses, GetUsersResponse, GetUsersResponses, GithubComMemohaiMemohInternalMcpConnection, HandlersBatchDeleteRequest, HandlersChannelMeta, HandlersCreateContainerRequest, HandlersCreateContainerResponse, HandlersCreateSnapshotRequest, HandlersCreateSnapshotResponse, HandlersEmbeddingsInput, HandlersEmbeddingsRequest, HandlersEmbeddingsResponse, HandlersEmbeddingsUsage, HandlersErrorResponse, HandlersFsDeleteRequest, HandlersFsFileInfo, HandlersFsListResponse, HandlersFsMkdirRequest, HandlersFsOpResponse, HandlersFsReadResponse, HandlersFsRenameRequest, HandlersFsUploadResponse, HandlersFsWriteRequest, HandlersGetContainerResponse, HandlersListMyIdentitiesResponse, HandlersListSnapshotsResponse, HandlersLocalChannelMessageRequest, HandlersLoginRequest, HandlersLoginResponse, HandlersMarkReadRequest, HandlersMcpStdioRequest, HandlersMcpStdioResponse, HandlersMemoryAddPayload, HandlersMemoryCompactPayload, HandlersMemoryDeletePayload, HandlersMemorySearchPayload, HandlersPingResponse, HandlersSkillItem, HandlersSkillsDeleteRequest, HandlersSkillsOpResponse, HandlersSkillsResponse, HandlersSkillsUpsertRequest, HandlersSnapshotInfo, IdentitiesChannelIdentity, InboxCountResult, InboxCreateRequest, InboxItem, McpExportResponse, McpImportRequest, McpListResponse, McpMcpServerEntry, McpUpsertRequest, MemoryCdfPoint, MemoryCompactResult, MemoryDeleteResponse, MemoryMemoryItem, MemoryMessage, MemoryRebuildResult, MemorySearchResponse, MemoryTopKBucket, MemoryUsageResponse, MessageMessage, MessageMessageAsset, ModelsAddRequest, ModelsAddResponse, ModelsClientType, ModelsCountResponse, ModelsGetResponse, ModelsModelType, ModelsUpdateRequest, PatchBotsByIdChannelByPlatformStatusData, PatchBotsByIdChannelByPlatformStatusError, PatchBotsByIdChannelByPlatformStatusErrors, PatchBotsByIdChannelByPlatformStatusResponse, PatchBotsByIdChannelByPlatformStatusResponses, PostAuthLoginData, PostAuthLoginError, PostAuthLoginErrors, PostAuthLoginResponse, PostAuthLoginResponses, PostBotsByBotIdCliMessagesData, PostBotsByBotIdCliMessagesError, PostBotsByBotIdCliMessagesErrors, PostBotsByBotIdCliMessagesResponse, PostBotsByBotIdCliMessagesResponses, PostBotsByBotIdContainerData, PostBotsByBotIdContainerError, PostBotsByBotIdContainerErrors, PostBotsByBotIdContainerFsDeleteData, PostBotsByBotIdContainerFsDeleteError, PostBotsByBotIdContainerFsDeleteErrors, PostBotsByBotIdContainerFsDeleteResponse, PostBotsByBotIdContainerFsDeleteResponses, PostBotsByBotIdContainerFsMkdirData, PostBotsByBotIdContainerFsMkdirError, PostBotsByBotIdContainerFsMkdirErrors, PostBotsByBotIdContainerFsMkdirResponse, PostBotsByBotIdContainerFsMkdirResponses, PostBotsByBotIdContainerFsRenameData, PostBotsByBotIdContainerFsRenameError, PostBotsByBotIdContainerFsRenameErrors, PostBotsByBotIdContainerFsRenameResponse, PostBotsByBotIdContainerFsRenameResponses, PostBotsByBotIdContainerFsUploadData, PostBotsByBotIdContainerFsUploadError, PostBotsByBotIdContainerFsUploadErrors, PostBotsByBotIdContainerFsUploadResponse, PostBotsByBotIdContainerFsUploadResponses, PostBotsByBotIdContainerFsWriteData, PostBotsByBotIdContainerFsWriteError, PostBotsByBotIdContainerFsWriteErrors, PostBotsByBotIdContainerFsWriteResponse, PostBotsByBotIdContainerFsWriteResponses, PostBotsByBotIdContainerResponse, PostBotsByBotIdContainerResponses, PostBotsByBotIdContainerSkillsData, PostBotsByBotIdContainerSkillsError, PostBotsByBotIdContainerSkillsErrors, PostBotsByBotIdContainerSkillsResponse, PostBotsByBotIdContainerSkillsResponses, PostBotsByBotIdContainerSnapshotsData, PostBotsByBotIdContainerSnapshotsError, PostBotsByBotIdContainerSnapshotsErrors, PostBotsByBotIdContainerSnapshotsResponse, PostBotsByBotIdContainerSnapshotsResponses, PostBotsByBotIdContainerStartData, PostBotsByBotIdContainerStartError, PostBotsByBotIdContainerStartErrors, PostBotsByBotIdContainerStartResponse, PostBotsByBotIdContainerStartResponses, PostBotsByBotIdContainerStopData, PostBotsByBotIdContainerStopError, PostBotsByBotIdContainerStopErrors, PostBotsByBotIdContainerStopResponse, PostBotsByBotIdContainerStopResponses, PostBotsByBotIdInboxData, PostBotsByBotIdInboxError, PostBotsByBotIdInboxErrors, PostBotsByBotIdInboxMarkReadData, PostBotsByBotIdInboxMarkReadError, PostBotsByBotIdInboxMarkReadErrors, PostBotsByBotIdInboxMarkReadResponses, PostBotsByBotIdInboxResponse, PostBotsByBotIdInboxResponses, PostBotsByBotIdMcpData, PostBotsByBotIdMcpError, PostBotsByBotIdMcpErrors, PostBotsByBotIdMcpOpsBatchDeleteData, PostBotsByBotIdMcpOpsBatchDeleteError, PostBotsByBotIdMcpOpsBatchDeleteErrors, PostBotsByBotIdMcpOpsBatchDeleteResponses, PostBotsByBotIdMcpResponse, PostBotsByBotIdMcpResponses, PostBotsByBotIdMcpStdioByConnectionIdData, PostBotsByBotIdMcpStdioByConnectionIdError, PostBotsByBotIdMcpStdioByConnectionIdErrors, PostBotsByBotIdMcpStdioByConnectionIdResponse, PostBotsByBotIdMcpStdioByConnectionIdResponses, PostBotsByBotIdMcpStdioData, PostBotsByBotIdMcpStdioError, PostBotsByBotIdMcpStdioErrors, PostBotsByBotIdMcpStdioResponse, PostBotsByBotIdMcpStdioResponses, PostBotsByBotIdMemoryCompactData, PostBotsByBotIdMemoryCompactError, PostBotsByBotIdMemoryCompactErrors, PostBotsByBotIdMemoryCompactResponse, PostBotsByBotIdMemoryCompactResponses, PostBotsByBotIdMemoryData, PostBotsByBotIdMemoryError, PostBotsByBotIdMemoryErrors, PostBotsByBotIdMemoryRebuildData, PostBotsByBotIdMemoryRebuildError, PostBotsByBotIdMemoryRebuildErrors, PostBotsByBotIdMemoryRebuildResponse, PostBotsByBotIdMemoryRebuildResponses, PostBotsByBotIdMemoryResponse, PostBotsByBotIdMemoryResponses, PostBotsByBotIdMemorySearchData, PostBotsByBotIdMemorySearchError, PostBotsByBotIdMemorySearchErrors, PostBotsByBotIdMemorySearchResponse, PostBotsByBotIdMemorySearchResponses, PostBotsByBotIdScheduleData, PostBotsByBotIdScheduleError, PostBotsByBotIdScheduleErrors, PostBotsByBotIdScheduleResponse, PostBotsByBotIdScheduleResponses, PostBotsByBotIdSettingsData, PostBotsByBotIdSettingsError, PostBotsByBotIdSettingsErrors, PostBotsByBotIdSettingsResponse, PostBotsByBotIdSettingsResponses, PostBotsByBotIdSubagentsByIdSkillsData, PostBotsByBotIdSubagentsByIdSkillsError, PostBotsByBotIdSubagentsByIdSkillsErrors, PostBotsByBotIdSubagentsByIdSkillsResponse, PostBotsByBotIdSubagentsByIdSkillsResponses, PostBotsByBotIdSubagentsData, PostBotsByBotIdSubagentsError, PostBotsByBotIdSubagentsErrors, PostBotsByBotIdSubagentsResponse, PostBotsByBotIdSubagentsResponses, PostBotsByBotIdToolsData, PostBotsByBotIdToolsError, PostBotsByBotIdToolsErrors, PostBotsByBotIdToolsResponse, PostBotsByBotIdToolsResponses, PostBotsByBotIdWebMessagesData, PostBotsByBotIdWebMessagesError, PostBotsByBotIdWebMessagesErrors, PostBotsByBotIdWebMessagesResponse, PostBotsByBotIdWebMessagesResponses, PostBotsByIdChannelByPlatformSendChatData, PostBotsByIdChannelByPlatformSendChatError, PostBotsByIdChannelByPlatformSendChatErrors, PostBotsByIdChannelByPlatformSendChatResponse, PostBotsByIdChannelByPlatformSendChatResponses, PostBotsByIdChannelByPlatformSendData, PostBotsByIdChannelByPlatformSendError, PostBotsByIdChannelByPlatformSendErrors, PostBotsByIdChannelByPlatformSendResponse, PostBotsByIdChannelByPlatformSendResponses, PostBotsData, PostBotsError, PostBotsErrors, PostBotsResponse, PostBotsResponses, PostEmbeddingsData, PostEmbeddingsError, PostEmbeddingsErrors, PostEmbeddingsResponse, PostEmbeddingsResponses, PostModelsData, PostModelsError, PostModelsErrors, PostModelsResponse, PostModelsResponses, PostProvidersByIdTestData, PostProvidersByIdTestError, PostProvidersByIdTestErrors, PostProvidersByIdTestResponse, PostProvidersByIdTestResponses, PostProvidersData, PostProvidersError, PostProvidersErrors, PostProvidersResponse, PostProvidersResponses, PostSearchProvidersData, PostSearchProvidersError, PostSearchProvidersErrors, PostSearchProvidersResponse, PostSearchProvidersResponses, PostUsersData, PostUsersError, PostUsersErrors, PostUsersResponse, PostUsersResponses, ProvidersCheckResult, ProvidersCheckStatus, ProvidersCountResponse, ProvidersCreateRequest, ProvidersGetResponse, ProvidersTestResponse, ProvidersUpdateRequest, PutBotsByBotIdMcpByIdData, PutBotsByBotIdMcpByIdError, PutBotsByBotIdMcpByIdErrors, PutBotsByBotIdMcpByIdResponse, PutBotsByBotIdMcpByIdResponses, PutBotsByBotIdMcpImportData, PutBotsByBotIdMcpImportError, PutBotsByBotIdMcpImportErrors, PutBotsByBotIdMcpImportResponse, PutBotsByBotIdMcpImportResponses, PutBotsByBotIdScheduleByIdData, PutBotsByBotIdScheduleByIdError, PutBotsByBotIdScheduleByIdErrors, PutBotsByBotIdScheduleByIdResponse, PutBotsByBotIdScheduleByIdResponses, PutBotsByBotIdSettingsData, PutBotsByBotIdSettingsError, PutBotsByBotIdSettingsErrors, PutBotsByBotIdSettingsResponse, PutBotsByBotIdSettingsResponses, PutBotsByBotIdSubagentsByIdContextData, PutBotsByBotIdSubagentsByIdContextError, PutBotsByBotIdSubagentsByIdContextErrors, PutBotsByBotIdSubagentsByIdContextResponse, PutBotsByBotIdSubagentsByIdContextResponses, PutBotsByBotIdSubagentsByIdData, PutBotsByBotIdSubagentsByIdError, PutBotsByBotIdSubagentsByIdErrors, PutBotsByBotIdSubagentsByIdResponse, PutBotsByBotIdSubagentsByIdResponses, PutBotsByBotIdSubagentsByIdSkillsData, PutBotsByBotIdSubagentsByIdSkillsError, PutBotsByBotIdSubagentsByIdSkillsErrors, PutBotsByBotIdSubagentsByIdSkillsResponse, PutBotsByBotIdSubagentsByIdSkillsResponses, PutBotsByIdChannelByPlatformData, PutBotsByIdChannelByPlatformError, PutBotsByIdChannelByPlatformErrors, PutBotsByIdChannelByPlatformResponse, PutBotsByIdChannelByPlatformResponses, PutBotsByIdData, PutBotsByIdError, PutBotsByIdErrors, PutBotsByIdMembersData, PutBotsByIdMembersError, PutBotsByIdMembersErrors, PutBotsByIdMembersResponse, PutBotsByIdMembersResponses, PutBotsByIdOwnerData, PutBotsByIdOwnerError, PutBotsByIdOwnerErrors, PutBotsByIdOwnerResponse, PutBotsByIdOwnerResponses, PutBotsByIdResponse, PutBotsByIdResponses, PutModelsByIdData, PutModelsByIdError, PutModelsByIdErrors, PutModelsByIdResponse, PutModelsByIdResponses, PutModelsModelByModelIdData, PutModelsModelByModelIdError, PutModelsModelByModelIdErrors, PutModelsModelByModelIdResponse, PutModelsModelByModelIdResponses, PutProvidersByIdData, PutProvidersByIdError, PutProvidersByIdErrors, PutProvidersByIdResponse, PutProvidersByIdResponses, PutSearchProvidersByIdData, PutSearchProvidersByIdError, PutSearchProvidersByIdErrors, PutSearchProvidersByIdResponse, PutSearchProvidersByIdResponses, PutUsersByIdData, PutUsersByIdError, PutUsersByIdErrors, PutUsersByIdPasswordData, PutUsersByIdPasswordError, PutUsersByIdPasswordErrors, PutUsersByIdPasswordResponses, PutUsersByIdResponse, PutUsersByIdResponses, PutUsersMeChannelsByPlatformData, PutUsersMeChannelsByPlatformError, PutUsersMeChannelsByPlatformErrors, PutUsersMeChannelsByPlatformResponse, PutUsersMeChannelsByPlatformResponses, PutUsersMeData, PutUsersMeError, PutUsersMeErrors, PutUsersMePasswordData, PutUsersMePasswordError, PutUsersMePasswordErrors, PutUsersMePasswordResponses, PutUsersMeResponse, PutUsersMeResponses, ScheduleCreateRequest, ScheduleListResponse, ScheduleNullableInt, ScheduleSchedule, ScheduleUpdateRequest, SearchprovidersCreateRequest, SearchprovidersGetResponse, SearchprovidersProviderConfigSchema, SearchprovidersProviderFieldSchema, SearchprovidersProviderMeta, SearchprovidersProviderName, SearchprovidersUpdateRequest, SettingsSettings, SettingsUpsertRequest, SubagentAddSkillsRequest, SubagentContextResponse, SubagentCreateRequest, SubagentListResponse, SubagentSkillsResponse, SubagentSubagent, SubagentUpdateContextRequest, SubagentUpdateRequest, SubagentUpdateSkillsRequest } from './types.gen'; diff --git a/packages/sdk/src/sdk.gen.ts b/packages/sdk/src/sdk.gen.ts index 45b2731d..097eb590 100644 --- a/packages/sdk/src/sdk.gen.ts +++ b/packages/sdk/src/sdk.gen.ts @@ -2,7 +2,7 @@ import { type Client, formDataBodySerializer, type Options as Options2, type TDataShape } from './client'; import { client } from './client.gen'; -import type { DeleteBotsByBotIdContainerData, DeleteBotsByBotIdContainerErrors, DeleteBotsByBotIdContainerResponses, DeleteBotsByBotIdContainerSkillsData, DeleteBotsByBotIdContainerSkillsErrors, DeleteBotsByBotIdContainerSkillsResponses, DeleteBotsByBotIdInboxByIdData, DeleteBotsByBotIdInboxByIdErrors, DeleteBotsByBotIdInboxByIdResponses, DeleteBotsByBotIdMcpByIdData, DeleteBotsByBotIdMcpByIdErrors, DeleteBotsByBotIdMcpByIdResponses, DeleteBotsByBotIdMemoryByIdData, DeleteBotsByBotIdMemoryByIdErrors, DeleteBotsByBotIdMemoryByIdResponses, DeleteBotsByBotIdMemoryData, DeleteBotsByBotIdMemoryErrors, DeleteBotsByBotIdMemoryResponses, DeleteBotsByBotIdMessagesData, DeleteBotsByBotIdMessagesErrors, DeleteBotsByBotIdMessagesResponses, DeleteBotsByBotIdScheduleByIdData, DeleteBotsByBotIdScheduleByIdErrors, DeleteBotsByBotIdScheduleByIdResponses, DeleteBotsByBotIdSettingsData, DeleteBotsByBotIdSettingsErrors, DeleteBotsByBotIdSettingsResponses, DeleteBotsByBotIdSubagentsByIdData, DeleteBotsByBotIdSubagentsByIdErrors, DeleteBotsByBotIdSubagentsByIdResponses, DeleteBotsByIdChannelByPlatformData, DeleteBotsByIdChannelByPlatformErrors, DeleteBotsByIdChannelByPlatformResponses, DeleteBotsByIdData, DeleteBotsByIdErrors, DeleteBotsByIdMembersByUserIdData, DeleteBotsByIdMembersByUserIdErrors, DeleteBotsByIdMembersByUserIdResponses, DeleteBotsByIdResponses, DeleteModelsByIdData, DeleteModelsByIdErrors, DeleteModelsByIdResponses, DeleteModelsModelByModelIdData, DeleteModelsModelByModelIdErrors, DeleteModelsModelByModelIdResponses, DeleteProvidersByIdData, DeleteProvidersByIdErrors, DeleteProvidersByIdResponses, DeleteSearchProvidersByIdData, DeleteSearchProvidersByIdErrors, DeleteSearchProvidersByIdResponses, GetBotsByBotIdCliStreamData, GetBotsByBotIdCliStreamErrors, GetBotsByBotIdCliStreamResponses, GetBotsByBotIdContainerData, GetBotsByBotIdContainerErrors, GetBotsByBotIdContainerFsData, GetBotsByBotIdContainerFsDownloadData, GetBotsByBotIdContainerFsDownloadErrors, GetBotsByBotIdContainerFsDownloadResponses, GetBotsByBotIdContainerFsErrors, GetBotsByBotIdContainerFsListData, GetBotsByBotIdContainerFsListErrors, GetBotsByBotIdContainerFsListResponses, GetBotsByBotIdContainerFsReadData, GetBotsByBotIdContainerFsReadErrors, GetBotsByBotIdContainerFsReadResponses, GetBotsByBotIdContainerFsResponses, GetBotsByBotIdContainerResponses, GetBotsByBotIdContainerSkillsData, GetBotsByBotIdContainerSkillsErrors, GetBotsByBotIdContainerSkillsResponses, GetBotsByBotIdContainerSnapshotsData, GetBotsByBotIdContainerSnapshotsResponses, GetBotsByBotIdInboxByIdData, GetBotsByBotIdInboxByIdErrors, GetBotsByBotIdInboxByIdResponses, GetBotsByBotIdInboxCountData, GetBotsByBotIdInboxCountErrors, GetBotsByBotIdInboxCountResponses, GetBotsByBotIdInboxData, GetBotsByBotIdInboxErrors, GetBotsByBotIdInboxResponses, GetBotsByBotIdMcpByIdData, GetBotsByBotIdMcpByIdErrors, GetBotsByBotIdMcpByIdResponses, GetBotsByBotIdMcpData, GetBotsByBotIdMcpErrors, GetBotsByBotIdMcpExportData, GetBotsByBotIdMcpExportErrors, GetBotsByBotIdMcpExportResponses, GetBotsByBotIdMcpResponses, GetBotsByBotIdMemoryData, GetBotsByBotIdMemoryErrors, GetBotsByBotIdMemoryResponses, GetBotsByBotIdMemoryUsageData, GetBotsByBotIdMemoryUsageErrors, GetBotsByBotIdMemoryUsageResponses, GetBotsByBotIdMessagesData, GetBotsByBotIdMessagesErrors, GetBotsByBotIdMessagesResponses, GetBotsByBotIdScheduleByIdData, GetBotsByBotIdScheduleByIdErrors, GetBotsByBotIdScheduleByIdResponses, GetBotsByBotIdScheduleData, GetBotsByBotIdScheduleErrors, GetBotsByBotIdScheduleResponses, GetBotsByBotIdSettingsData, GetBotsByBotIdSettingsErrors, GetBotsByBotIdSettingsResponses, GetBotsByBotIdSubagentsByIdContextData, GetBotsByBotIdSubagentsByIdContextErrors, GetBotsByBotIdSubagentsByIdContextResponses, GetBotsByBotIdSubagentsByIdData, GetBotsByBotIdSubagentsByIdErrors, GetBotsByBotIdSubagentsByIdResponses, GetBotsByBotIdSubagentsByIdSkillsData, GetBotsByBotIdSubagentsByIdSkillsErrors, GetBotsByBotIdSubagentsByIdSkillsResponses, GetBotsByBotIdSubagentsData, GetBotsByBotIdSubagentsErrors, GetBotsByBotIdSubagentsResponses, GetBotsByBotIdWebStreamData, GetBotsByBotIdWebStreamErrors, GetBotsByBotIdWebStreamResponses, GetBotsByIdChannelByPlatformData, GetBotsByIdChannelByPlatformErrors, GetBotsByIdChannelByPlatformResponses, GetBotsByIdChecksData, GetBotsByIdChecksErrors, GetBotsByIdChecksResponses, GetBotsByIdData, GetBotsByIdErrors, GetBotsByIdMembersData, GetBotsByIdMembersErrors, GetBotsByIdMembersResponses, GetBotsByIdResponses, GetBotsData, GetBotsErrors, GetBotsResponses, GetChannelsByPlatformData, GetChannelsByPlatformErrors, GetChannelsByPlatformResponses, GetChannelsData, GetChannelsErrors, GetChannelsResponses, GetModelsByIdData, GetModelsByIdErrors, GetModelsByIdResponses, GetModelsCountData, GetModelsCountErrors, GetModelsCountResponses, GetModelsData, GetModelsErrors, GetModelsModelByModelIdData, GetModelsModelByModelIdErrors, GetModelsModelByModelIdResponses, GetModelsResponses, GetProvidersByIdData, GetProvidersByIdErrors, GetProvidersByIdModelsData, GetProvidersByIdModelsErrors, GetProvidersByIdModelsResponses, GetProvidersByIdResponses, GetProvidersCountData, GetProvidersCountErrors, GetProvidersCountResponses, GetProvidersData, GetProvidersErrors, GetProvidersNameByNameData, GetProvidersNameByNameErrors, GetProvidersNameByNameResponses, GetProvidersResponses, GetSearchProvidersByIdData, GetSearchProvidersByIdErrors, GetSearchProvidersByIdResponses, GetSearchProvidersData, GetSearchProvidersErrors, GetSearchProvidersMetaData, GetSearchProvidersMetaResponses, GetSearchProvidersResponses, GetUsersByIdData, GetUsersByIdErrors, GetUsersByIdResponses, GetUsersData, GetUsersErrors, GetUsersMeChannelsByPlatformData, GetUsersMeChannelsByPlatformErrors, GetUsersMeChannelsByPlatformResponses, GetUsersMeData, GetUsersMeErrors, GetUsersMeIdentitiesData, GetUsersMeIdentitiesErrors, GetUsersMeIdentitiesResponses, GetUsersMeResponses, GetUsersResponses, PatchBotsByIdChannelByPlatformStatusData, PatchBotsByIdChannelByPlatformStatusErrors, PatchBotsByIdChannelByPlatformStatusResponses, PostAuthLoginData, PostAuthLoginErrors, PostAuthLoginResponses, PostBotsByBotIdCliMessagesData, PostBotsByBotIdCliMessagesErrors, PostBotsByBotIdCliMessagesResponses, PostBotsByBotIdContainerData, PostBotsByBotIdContainerErrors, PostBotsByBotIdContainerFsDeleteData, PostBotsByBotIdContainerFsDeleteErrors, PostBotsByBotIdContainerFsDeleteResponses, PostBotsByBotIdContainerFsMkdirData, PostBotsByBotIdContainerFsMkdirErrors, PostBotsByBotIdContainerFsMkdirResponses, PostBotsByBotIdContainerFsRenameData, PostBotsByBotIdContainerFsRenameErrors, PostBotsByBotIdContainerFsRenameResponses, PostBotsByBotIdContainerFsUploadData, PostBotsByBotIdContainerFsUploadErrors, PostBotsByBotIdContainerFsUploadResponses, PostBotsByBotIdContainerFsWriteData, PostBotsByBotIdContainerFsWriteErrors, PostBotsByBotIdContainerFsWriteResponses, PostBotsByBotIdContainerResponses, PostBotsByBotIdContainerSkillsData, PostBotsByBotIdContainerSkillsErrors, PostBotsByBotIdContainerSkillsResponses, PostBotsByBotIdContainerSnapshotsData, PostBotsByBotIdContainerSnapshotsErrors, PostBotsByBotIdContainerSnapshotsResponses, PostBotsByBotIdContainerStartData, PostBotsByBotIdContainerStartErrors, PostBotsByBotIdContainerStartResponses, PostBotsByBotIdContainerStopData, PostBotsByBotIdContainerStopErrors, PostBotsByBotIdContainerStopResponses, PostBotsByBotIdInboxData, PostBotsByBotIdInboxErrors, PostBotsByBotIdInboxMarkReadData, PostBotsByBotIdInboxMarkReadErrors, PostBotsByBotIdInboxMarkReadResponses, PostBotsByBotIdInboxResponses, PostBotsByBotIdMcpData, PostBotsByBotIdMcpErrors, PostBotsByBotIdMcpOpsBatchDeleteData, PostBotsByBotIdMcpOpsBatchDeleteErrors, PostBotsByBotIdMcpOpsBatchDeleteResponses, PostBotsByBotIdMcpResponses, PostBotsByBotIdMcpStdioByConnectionIdData, PostBotsByBotIdMcpStdioByConnectionIdErrors, PostBotsByBotIdMcpStdioByConnectionIdResponses, PostBotsByBotIdMcpStdioData, PostBotsByBotIdMcpStdioErrors, PostBotsByBotIdMcpStdioResponses, PostBotsByBotIdMemoryCompactData, PostBotsByBotIdMemoryCompactErrors, PostBotsByBotIdMemoryCompactResponses, PostBotsByBotIdMemoryData, PostBotsByBotIdMemoryErrors, PostBotsByBotIdMemoryRebuildData, PostBotsByBotIdMemoryRebuildErrors, PostBotsByBotIdMemoryRebuildResponses, PostBotsByBotIdMemoryResponses, PostBotsByBotIdMemorySearchData, PostBotsByBotIdMemorySearchErrors, PostBotsByBotIdMemorySearchResponses, PostBotsByBotIdScheduleData, PostBotsByBotIdScheduleErrors, PostBotsByBotIdScheduleResponses, PostBotsByBotIdSettingsData, PostBotsByBotIdSettingsErrors, PostBotsByBotIdSettingsResponses, PostBotsByBotIdSubagentsByIdSkillsData, PostBotsByBotIdSubagentsByIdSkillsErrors, PostBotsByBotIdSubagentsByIdSkillsResponses, PostBotsByBotIdSubagentsData, PostBotsByBotIdSubagentsErrors, PostBotsByBotIdSubagentsResponses, PostBotsByBotIdToolsData, PostBotsByBotIdToolsErrors, PostBotsByBotIdToolsResponses, PostBotsByBotIdWebMessagesData, PostBotsByBotIdWebMessagesErrors, PostBotsByBotIdWebMessagesResponses, PostBotsByIdChannelByPlatformSendChatData, PostBotsByIdChannelByPlatformSendChatErrors, PostBotsByIdChannelByPlatformSendChatResponses, PostBotsByIdChannelByPlatformSendData, PostBotsByIdChannelByPlatformSendErrors, PostBotsByIdChannelByPlatformSendResponses, PostBotsData, PostBotsErrors, PostBotsResponses, PostEmbeddingsData, PostEmbeddingsErrors, PostEmbeddingsResponses, PostModelsData, PostModelsErrors, PostModelsResponses, PostProvidersByIdTestData, PostProvidersByIdTestErrors, PostProvidersByIdTestResponses, PostProvidersData, PostProvidersErrors, PostProvidersResponses, PostSearchProvidersData, PostSearchProvidersErrors, PostSearchProvidersResponses, PostUsersData, PostUsersErrors, PostUsersResponses, PutBotsByBotIdMcpByIdData, PutBotsByBotIdMcpByIdErrors, PutBotsByBotIdMcpByIdResponses, PutBotsByBotIdMcpImportData, PutBotsByBotIdMcpImportErrors, PutBotsByBotIdMcpImportResponses, PutBotsByBotIdScheduleByIdData, PutBotsByBotIdScheduleByIdErrors, PutBotsByBotIdScheduleByIdResponses, PutBotsByBotIdSettingsData, PutBotsByBotIdSettingsErrors, PutBotsByBotIdSettingsResponses, PutBotsByBotIdSubagentsByIdContextData, PutBotsByBotIdSubagentsByIdContextErrors, PutBotsByBotIdSubagentsByIdContextResponses, PutBotsByBotIdSubagentsByIdData, PutBotsByBotIdSubagentsByIdErrors, PutBotsByBotIdSubagentsByIdResponses, PutBotsByBotIdSubagentsByIdSkillsData, PutBotsByBotIdSubagentsByIdSkillsErrors, PutBotsByBotIdSubagentsByIdSkillsResponses, PutBotsByIdChannelByPlatformData, PutBotsByIdChannelByPlatformErrors, PutBotsByIdChannelByPlatformResponses, PutBotsByIdData, PutBotsByIdErrors, PutBotsByIdMembersData, PutBotsByIdMembersErrors, PutBotsByIdMembersResponses, PutBotsByIdOwnerData, PutBotsByIdOwnerErrors, PutBotsByIdOwnerResponses, PutBotsByIdResponses, PutModelsByIdData, PutModelsByIdErrors, PutModelsByIdResponses, PutModelsModelByModelIdData, PutModelsModelByModelIdErrors, PutModelsModelByModelIdResponses, PutProvidersByIdData, PutProvidersByIdErrors, PutProvidersByIdResponses, PutSearchProvidersByIdData, PutSearchProvidersByIdErrors, PutSearchProvidersByIdResponses, PutUsersByIdData, PutUsersByIdErrors, PutUsersByIdPasswordData, PutUsersByIdPasswordErrors, PutUsersByIdPasswordResponses, PutUsersByIdResponses, PutUsersMeChannelsByPlatformData, PutUsersMeChannelsByPlatformErrors, PutUsersMeChannelsByPlatformResponses, PutUsersMeData, PutUsersMeErrors, PutUsersMePasswordData, PutUsersMePasswordErrors, PutUsersMePasswordResponses, PutUsersMeResponses } from './types.gen'; +import type { DeleteBotsByBotIdContainerData, DeleteBotsByBotIdContainerErrors, DeleteBotsByBotIdContainerResponses, DeleteBotsByBotIdContainerSkillsData, DeleteBotsByBotIdContainerSkillsErrors, DeleteBotsByBotIdContainerSkillsResponses, DeleteBotsByBotIdInboxByIdData, DeleteBotsByBotIdInboxByIdErrors, DeleteBotsByBotIdInboxByIdResponses, DeleteBotsByBotIdMcpByIdData, DeleteBotsByBotIdMcpByIdErrors, DeleteBotsByBotIdMcpByIdResponses, DeleteBotsByBotIdMemoryByIdData, DeleteBotsByBotIdMemoryByIdErrors, DeleteBotsByBotIdMemoryByIdResponses, DeleteBotsByBotIdMemoryData, DeleteBotsByBotIdMemoryErrors, DeleteBotsByBotIdMemoryResponses, DeleteBotsByBotIdMessagesData, DeleteBotsByBotIdMessagesErrors, DeleteBotsByBotIdMessagesResponses, DeleteBotsByBotIdScheduleByIdData, DeleteBotsByBotIdScheduleByIdErrors, DeleteBotsByBotIdScheduleByIdResponses, DeleteBotsByBotIdSettingsData, DeleteBotsByBotIdSettingsErrors, DeleteBotsByBotIdSettingsResponses, DeleteBotsByBotIdSubagentsByIdData, DeleteBotsByBotIdSubagentsByIdErrors, DeleteBotsByBotIdSubagentsByIdResponses, DeleteBotsByIdChannelByPlatformData, DeleteBotsByIdChannelByPlatformErrors, DeleteBotsByIdChannelByPlatformResponses, DeleteBotsByIdData, DeleteBotsByIdErrors, DeleteBotsByIdMembersByUserIdData, DeleteBotsByIdMembersByUserIdErrors, DeleteBotsByIdMembersByUserIdResponses, DeleteBotsByIdResponses, DeleteModelsByIdData, DeleteModelsByIdErrors, DeleteModelsByIdResponses, DeleteModelsModelByModelIdData, DeleteModelsModelByModelIdErrors, DeleteModelsModelByModelIdResponses, DeleteProvidersByIdData, DeleteProvidersByIdErrors, DeleteProvidersByIdResponses, DeleteSearchProvidersByIdData, DeleteSearchProvidersByIdErrors, DeleteSearchProvidersByIdResponses, GetBotsByBotIdCliStreamData, GetBotsByBotIdCliStreamErrors, GetBotsByBotIdCliStreamResponses, GetBotsByBotIdContainerData, GetBotsByBotIdContainerErrors, GetBotsByBotIdContainerFsData, GetBotsByBotIdContainerFsDownloadData, GetBotsByBotIdContainerFsDownloadErrors, GetBotsByBotIdContainerFsDownloadResponses, GetBotsByBotIdContainerFsErrors, GetBotsByBotIdContainerFsListData, GetBotsByBotIdContainerFsListErrors, GetBotsByBotIdContainerFsListResponses, GetBotsByBotIdContainerFsReadData, GetBotsByBotIdContainerFsReadErrors, GetBotsByBotIdContainerFsReadResponses, GetBotsByBotIdContainerFsResponses, GetBotsByBotIdContainerResponses, GetBotsByBotIdContainerSkillsData, GetBotsByBotIdContainerSkillsErrors, GetBotsByBotIdContainerSkillsResponses, GetBotsByBotIdContainerSnapshotsData, GetBotsByBotIdContainerSnapshotsErrors, GetBotsByBotIdContainerSnapshotsResponses, GetBotsByBotIdInboxByIdData, GetBotsByBotIdInboxByIdErrors, GetBotsByBotIdInboxByIdResponses, GetBotsByBotIdInboxCountData, GetBotsByBotIdInboxCountErrors, GetBotsByBotIdInboxCountResponses, GetBotsByBotIdInboxData, GetBotsByBotIdInboxErrors, GetBotsByBotIdInboxResponses, GetBotsByBotIdMcpByIdData, GetBotsByBotIdMcpByIdErrors, GetBotsByBotIdMcpByIdResponses, GetBotsByBotIdMcpData, GetBotsByBotIdMcpErrors, GetBotsByBotIdMcpExportData, GetBotsByBotIdMcpExportErrors, GetBotsByBotIdMcpExportResponses, GetBotsByBotIdMcpResponses, GetBotsByBotIdMemoryData, GetBotsByBotIdMemoryErrors, GetBotsByBotIdMemoryResponses, GetBotsByBotIdMemoryUsageData, GetBotsByBotIdMemoryUsageErrors, GetBotsByBotIdMemoryUsageResponses, GetBotsByBotIdMessagesData, GetBotsByBotIdMessagesErrors, GetBotsByBotIdMessagesResponses, GetBotsByBotIdScheduleByIdData, GetBotsByBotIdScheduleByIdErrors, GetBotsByBotIdScheduleByIdResponses, GetBotsByBotIdScheduleData, GetBotsByBotIdScheduleErrors, GetBotsByBotIdScheduleResponses, GetBotsByBotIdSettingsData, GetBotsByBotIdSettingsErrors, GetBotsByBotIdSettingsResponses, GetBotsByBotIdSubagentsByIdContextData, GetBotsByBotIdSubagentsByIdContextErrors, GetBotsByBotIdSubagentsByIdContextResponses, GetBotsByBotIdSubagentsByIdData, GetBotsByBotIdSubagentsByIdErrors, GetBotsByBotIdSubagentsByIdResponses, GetBotsByBotIdSubagentsByIdSkillsData, GetBotsByBotIdSubagentsByIdSkillsErrors, GetBotsByBotIdSubagentsByIdSkillsResponses, GetBotsByBotIdSubagentsData, GetBotsByBotIdSubagentsErrors, GetBotsByBotIdSubagentsResponses, GetBotsByBotIdWebStreamData, GetBotsByBotIdWebStreamErrors, GetBotsByBotIdWebStreamResponses, GetBotsByIdChannelByPlatformData, GetBotsByIdChannelByPlatformErrors, GetBotsByIdChannelByPlatformResponses, GetBotsByIdChecksData, GetBotsByIdChecksErrors, GetBotsByIdChecksResponses, GetBotsByIdData, GetBotsByIdErrors, GetBotsByIdMembersData, GetBotsByIdMembersErrors, GetBotsByIdMembersResponses, GetBotsByIdResponses, GetBotsData, GetBotsErrors, GetBotsResponses, GetChannelsByPlatformData, GetChannelsByPlatformErrors, GetChannelsByPlatformResponses, GetChannelsData, GetChannelsErrors, GetChannelsResponses, GetModelsByIdData, GetModelsByIdErrors, GetModelsByIdResponses, GetModelsCountData, GetModelsCountErrors, GetModelsCountResponses, GetModelsData, GetModelsErrors, GetModelsModelByModelIdData, GetModelsModelByModelIdErrors, GetModelsModelByModelIdResponses, GetModelsResponses, GetPingData, GetPingResponses, GetProvidersByIdData, GetProvidersByIdErrors, GetProvidersByIdModelsData, GetProvidersByIdModelsErrors, GetProvidersByIdModelsResponses, GetProvidersByIdResponses, GetProvidersCountData, GetProvidersCountErrors, GetProvidersCountResponses, GetProvidersData, GetProvidersErrors, GetProvidersNameByNameData, GetProvidersNameByNameErrors, GetProvidersNameByNameResponses, GetProvidersResponses, GetSearchProvidersByIdData, GetSearchProvidersByIdErrors, GetSearchProvidersByIdResponses, GetSearchProvidersData, GetSearchProvidersErrors, GetSearchProvidersMetaData, GetSearchProvidersMetaResponses, GetSearchProvidersResponses, GetUsersByIdData, GetUsersByIdErrors, GetUsersByIdResponses, GetUsersData, GetUsersErrors, GetUsersMeChannelsByPlatformData, GetUsersMeChannelsByPlatformErrors, GetUsersMeChannelsByPlatformResponses, GetUsersMeData, GetUsersMeErrors, GetUsersMeIdentitiesData, GetUsersMeIdentitiesErrors, GetUsersMeIdentitiesResponses, GetUsersMeResponses, GetUsersResponses, PatchBotsByIdChannelByPlatformStatusData, PatchBotsByIdChannelByPlatformStatusErrors, PatchBotsByIdChannelByPlatformStatusResponses, PostAuthLoginData, PostAuthLoginErrors, PostAuthLoginResponses, PostBotsByBotIdCliMessagesData, PostBotsByBotIdCliMessagesErrors, PostBotsByBotIdCliMessagesResponses, PostBotsByBotIdContainerData, PostBotsByBotIdContainerErrors, PostBotsByBotIdContainerFsDeleteData, PostBotsByBotIdContainerFsDeleteErrors, PostBotsByBotIdContainerFsDeleteResponses, PostBotsByBotIdContainerFsMkdirData, PostBotsByBotIdContainerFsMkdirErrors, PostBotsByBotIdContainerFsMkdirResponses, PostBotsByBotIdContainerFsRenameData, PostBotsByBotIdContainerFsRenameErrors, PostBotsByBotIdContainerFsRenameResponses, PostBotsByBotIdContainerFsUploadData, PostBotsByBotIdContainerFsUploadErrors, PostBotsByBotIdContainerFsUploadResponses, PostBotsByBotIdContainerFsWriteData, PostBotsByBotIdContainerFsWriteErrors, PostBotsByBotIdContainerFsWriteResponses, PostBotsByBotIdContainerResponses, PostBotsByBotIdContainerSkillsData, PostBotsByBotIdContainerSkillsErrors, PostBotsByBotIdContainerSkillsResponses, PostBotsByBotIdContainerSnapshotsData, PostBotsByBotIdContainerSnapshotsErrors, PostBotsByBotIdContainerSnapshotsResponses, PostBotsByBotIdContainerStartData, PostBotsByBotIdContainerStartErrors, PostBotsByBotIdContainerStartResponses, PostBotsByBotIdContainerStopData, PostBotsByBotIdContainerStopErrors, PostBotsByBotIdContainerStopResponses, PostBotsByBotIdInboxData, PostBotsByBotIdInboxErrors, PostBotsByBotIdInboxMarkReadData, PostBotsByBotIdInboxMarkReadErrors, PostBotsByBotIdInboxMarkReadResponses, PostBotsByBotIdInboxResponses, PostBotsByBotIdMcpData, PostBotsByBotIdMcpErrors, PostBotsByBotIdMcpOpsBatchDeleteData, PostBotsByBotIdMcpOpsBatchDeleteErrors, PostBotsByBotIdMcpOpsBatchDeleteResponses, PostBotsByBotIdMcpResponses, PostBotsByBotIdMcpStdioByConnectionIdData, PostBotsByBotIdMcpStdioByConnectionIdErrors, PostBotsByBotIdMcpStdioByConnectionIdResponses, PostBotsByBotIdMcpStdioData, PostBotsByBotIdMcpStdioErrors, PostBotsByBotIdMcpStdioResponses, PostBotsByBotIdMemoryCompactData, PostBotsByBotIdMemoryCompactErrors, PostBotsByBotIdMemoryCompactResponses, PostBotsByBotIdMemoryData, PostBotsByBotIdMemoryErrors, PostBotsByBotIdMemoryRebuildData, PostBotsByBotIdMemoryRebuildErrors, PostBotsByBotIdMemoryRebuildResponses, PostBotsByBotIdMemoryResponses, PostBotsByBotIdMemorySearchData, PostBotsByBotIdMemorySearchErrors, PostBotsByBotIdMemorySearchResponses, PostBotsByBotIdScheduleData, PostBotsByBotIdScheduleErrors, PostBotsByBotIdScheduleResponses, PostBotsByBotIdSettingsData, PostBotsByBotIdSettingsErrors, PostBotsByBotIdSettingsResponses, PostBotsByBotIdSubagentsByIdSkillsData, PostBotsByBotIdSubagentsByIdSkillsErrors, PostBotsByBotIdSubagentsByIdSkillsResponses, PostBotsByBotIdSubagentsData, PostBotsByBotIdSubagentsErrors, PostBotsByBotIdSubagentsResponses, PostBotsByBotIdToolsData, PostBotsByBotIdToolsErrors, PostBotsByBotIdToolsResponses, PostBotsByBotIdWebMessagesData, PostBotsByBotIdWebMessagesErrors, PostBotsByBotIdWebMessagesResponses, PostBotsByIdChannelByPlatformSendChatData, PostBotsByIdChannelByPlatformSendChatErrors, PostBotsByIdChannelByPlatformSendChatResponses, PostBotsByIdChannelByPlatformSendData, PostBotsByIdChannelByPlatformSendErrors, PostBotsByIdChannelByPlatformSendResponses, PostBotsData, PostBotsErrors, PostBotsResponses, PostEmbeddingsData, PostEmbeddingsErrors, PostEmbeddingsResponses, PostModelsData, PostModelsErrors, PostModelsResponses, PostProvidersByIdTestData, PostProvidersByIdTestErrors, PostProvidersByIdTestResponses, PostProvidersData, PostProvidersErrors, PostProvidersResponses, PostSearchProvidersData, PostSearchProvidersErrors, PostSearchProvidersResponses, PostUsersData, PostUsersErrors, PostUsersResponses, PutBotsByBotIdMcpByIdData, PutBotsByBotIdMcpByIdErrors, PutBotsByBotIdMcpByIdResponses, PutBotsByBotIdMcpImportData, PutBotsByBotIdMcpImportErrors, PutBotsByBotIdMcpImportResponses, PutBotsByBotIdScheduleByIdData, PutBotsByBotIdScheduleByIdErrors, PutBotsByBotIdScheduleByIdResponses, PutBotsByBotIdSettingsData, PutBotsByBotIdSettingsErrors, PutBotsByBotIdSettingsResponses, PutBotsByBotIdSubagentsByIdContextData, PutBotsByBotIdSubagentsByIdContextErrors, PutBotsByBotIdSubagentsByIdContextResponses, PutBotsByBotIdSubagentsByIdData, PutBotsByBotIdSubagentsByIdErrors, PutBotsByBotIdSubagentsByIdResponses, PutBotsByBotIdSubagentsByIdSkillsData, PutBotsByBotIdSubagentsByIdSkillsErrors, PutBotsByBotIdSubagentsByIdSkillsResponses, PutBotsByIdChannelByPlatformData, PutBotsByIdChannelByPlatformErrors, PutBotsByIdChannelByPlatformResponses, PutBotsByIdData, PutBotsByIdErrors, PutBotsByIdMembersData, PutBotsByIdMembersErrors, PutBotsByIdMembersResponses, PutBotsByIdOwnerData, PutBotsByIdOwnerErrors, PutBotsByIdOwnerResponses, PutBotsByIdResponses, PutModelsByIdData, PutModelsByIdErrors, PutModelsByIdResponses, PutModelsModelByModelIdData, PutModelsModelByModelIdErrors, PutModelsModelByModelIdResponses, PutProvidersByIdData, PutProvidersByIdErrors, PutProvidersByIdResponses, PutSearchProvidersByIdData, PutSearchProvidersByIdErrors, PutSearchProvidersByIdResponses, PutUsersByIdData, PutUsersByIdErrors, PutUsersByIdPasswordData, PutUsersByIdPasswordErrors, PutUsersByIdPasswordResponses, PutUsersByIdResponses, PutUsersMeChannelsByPlatformData, PutUsersMeChannelsByPlatformErrors, PutUsersMeChannelsByPlatformResponses, PutUsersMeData, PutUsersMeErrors, PutUsersMePasswordData, PutUsersMePasswordErrors, PutUsersMePasswordResponses, PutUsersMeResponses } from './types.gen'; export type Options = Options2 & { /** @@ -227,7 +227,7 @@ export const postBotsByBotIdContainerSkills = (options: Options) => (options.client ?? client).get({ url: '/bots/{bot_id}/container/snapshots', ...options }); +export const getBotsByBotIdContainerSnapshots = (options: Options) => (options.client ?? client).get({ url: '/bots/{bot_id}/container/snapshots', ...options }); /** * Create container snapshot for bot @@ -1014,6 +1014,11 @@ export const putModelsById = (options: Opt } }); +/** + * Health check with server capabilities + */ +export const getPing = (options?: Options) => (options?.client ?? client).get({ url: '/ping', ...options }); + /** * List all LLM providers * diff --git a/packages/sdk/src/types.gen.ts b/packages/sdk/src/types.gen.ts index a4660196..ef6013bc 100644 --- a/packages/sdk/src/types.gen.ts +++ b/packages/sdk/src/types.gen.ts @@ -493,6 +493,12 @@ export type HandlersMcpStdioResponse = { url?: string; }; +export type HandlersPingResponse = { + container_backend?: string; + snapshot_supported?: boolean; + status?: string; +}; + export type HandlersSkillItem = { content?: string; description?: string; @@ -1891,6 +1897,15 @@ export type GetBotsByBotIdContainerSnapshotsData = { url: '/bots/{bot_id}/container/snapshots'; }; +export type GetBotsByBotIdContainerSnapshotsErrors = { + /** + * Snapshots currently not supported on this backend + */ + 501: HandlersErrorResponse; +}; + +export type GetBotsByBotIdContainerSnapshotsError = GetBotsByBotIdContainerSnapshotsErrors[keyof GetBotsByBotIdContainerSnapshotsErrors]; + export type GetBotsByBotIdContainerSnapshotsResponses = { /** * OK @@ -1924,6 +1939,10 @@ export type PostBotsByBotIdContainerSnapshotsErrors = { * Internal Server Error */ 500: HandlersErrorResponse; + /** + * Snapshots currently not supported on this backend + */ + 501: HandlersErrorResponse; }; export type PostBotsByBotIdContainerSnapshotsError = PostBotsByBotIdContainerSnapshotsErrors[keyof PostBotsByBotIdContainerSnapshotsErrors]; @@ -4940,6 +4959,22 @@ export type PutModelsByIdResponses = { export type PutModelsByIdResponse = PutModelsByIdResponses[keyof PutModelsByIdResponses]; +export type GetPingData = { + body?: never; + path?: never; + query?: never; + url: '/ping'; +}; + +export type GetPingResponses = { + /** + * OK + */ + 200: HandlersPingResponse; +}; + +export type GetPingResponse = GetPingResponses[keyof GetPingResponses]; + export type GetProvidersData = { body?: never; path?: never; diff --git a/packages/web/src/pages/bots/detail.vue b/packages/web/src/pages/bots/detail.vue index c2704b2b..530badbf 100644 --- a/packages/web/src/pages/bots/detail.vue +++ b/packages/web/src/pages/bots/detail.vue @@ -411,9 +411,12 @@ - + -
+
route.params.botId as string) +const capabilitiesStore = useCapabilitiesStore() +onMounted(() => { + void capabilitiesStore.load() +}) + const { data: bot } = useQuery({ key: () => ['bot', botId.value], query: async () => { @@ -898,6 +907,7 @@ async function handleRefreshChecks() { } async function loadContainerData(showLoadingToast: boolean) { + await capabilitiesStore.load() containerLoading.value = true try { const result = await getBotsByBotIdContainer({ path: { bot_id: botId.value } }) @@ -912,7 +922,9 @@ async function loadContainerData(showLoadingToast: boolean) { } containerInfo.value = result.data containerMissing.value = false - await loadSnapshots() + if (capabilitiesStore.snapshotSupported) { + await loadSnapshots() + } } catch (error) { if (showLoadingToast) { toast.error(resolveErrorMessage(error, t('bots.container.loadFailed'))) @@ -923,7 +935,7 @@ async function loadContainerData(showLoadingToast: boolean) { } async function loadSnapshots() { - if (!containerInfo.value) { + if (!containerInfo.value || !capabilitiesStore.snapshotSupported) { snapshots.value = [] return } @@ -1018,7 +1030,7 @@ async function handleDeleteContainer() { } async function handleCreateSnapshot() { - if (botLifecyclePending.value || !containerInfo.value) return + if (botLifecyclePending.value || !containerInfo.value || !capabilitiesStore.snapshotSupported) return await runContainerAction( 'snapshot', async () => { @@ -1033,4 +1045,4 @@ async function handleCreateSnapshot() { t('bots.container.snapshotSuccess'), ) } - + \ No newline at end of file diff --git a/packages/web/src/store/capabilities.ts b/packages/web/src/store/capabilities.ts new file mode 100644 index 00000000..366d2004 --- /dev/null +++ b/packages/web/src/store/capabilities.ts @@ -0,0 +1,25 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { getPing } from '@memoh/sdk' + +export const useCapabilitiesStore = defineStore('capabilities', () => { + const containerBackend = ref('containerd') + const snapshotSupported = ref(true) + const loaded = ref(false) + + async function load() { + if (loaded.value) return + try { + const { data } = await getPing() + if (data) { + containerBackend.value = data.container_backend ?? 'containerd' + snapshotSupported.value = data.snapshot_supported !== false + } + } catch { + // fallback: assume containerd + } + loaded.value = true + } + + return { containerBackend, snapshotSupported, loaded, load } +}) diff --git a/scripts/compile-mcp.sh b/scripts/compile-mcp.sh deleted file mode 100755 index a6ea037c..00000000 --- a/scripts/compile-mcp.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env sh -set -e - -APP_DIR=${APP_DIR:-/app} -BIN_NAME=${BIN_NAME:-mcp} -STOP_SIGNAL=${STOP_SIGNAL:-TERM} -CONTAINER_NAME=${CONTAINER_NAME:-} -TARGET_OS=${TARGET_OS:-linux} -TARGET_ARCH=${TARGET_ARCH:-} - -if [ -z "$TARGET_ARCH" ]; then - case "$(uname -m)" in - arm64|aarch64) - TARGET_ARCH=arm64 - ;; - x86_64|amd64) - TARGET_ARCH=amd64 - ;; - *) - TARGET_ARCH=amd64 - ;; - esac -fi - -mkdir -p "$APP_DIR" - -GOOS="$TARGET_OS" GOARCH="$TARGET_ARCH" go build -trimpath -ldflags "-s -w" -o "${APP_DIR}/${BIN_NAME}.new" ./cmd/mcp -mv -f "${APP_DIR}/${BIN_NAME}.new" "${APP_DIR}/${BIN_NAME}" - -if [ -n "$CONTAINER_NAME" ]; then - nerdctl kill -s "$STOP_SIGNAL" "$CONTAINER_NAME" -else - echo "CONTAINER_NAME is empty; skip sending stop signal." -fi diff --git a/spec/docs.go b/spec/docs.go index 07b02bc9..b4f6d3dc 100644 --- a/spec/docs.go +++ b/spec/docs.go @@ -1038,6 +1038,12 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/handlers.ListSnapshotsResponse" } + }, + "501": { + "description": "Snapshots currently not supported on this backend", + "schema": { + "$ref": "#/definitions/handlers.ErrorResponse" + } } } }, @@ -1082,6 +1088,12 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/handlers.ErrorResponse" } + }, + "501": { + "description": "Snapshots currently not supported on this backend", + "schema": { + "$ref": "#/definitions/handlers.ErrorResponse" + } } } } @@ -4738,6 +4750,22 @@ const docTemplate = `{ } } }, + "/ping": { + "get": { + "tags": [ + "system" + ], + "summary": "Health check with server capabilities", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handlers.PingResponse" + } + } + } + } + }, "/providers": { "get": { "description": "Get a list of all configured LLM providers", @@ -7087,6 +7115,20 @@ const docTemplate = `{ } } }, + "handlers.PingResponse": { + "type": "object", + "properties": { + "container_backend": { + "type": "string" + }, + "snapshot_supported": { + "type": "boolean" + }, + "status": { + "type": "string" + } + } + }, "handlers.SkillItem": { "type": "object", "properties": { diff --git a/spec/swagger.json b/spec/swagger.json index f08fe6b1..f51c41ec 100644 --- a/spec/swagger.json +++ b/spec/swagger.json @@ -1029,6 +1029,12 @@ "schema": { "$ref": "#/definitions/handlers.ListSnapshotsResponse" } + }, + "501": { + "description": "Snapshots currently not supported on this backend", + "schema": { + "$ref": "#/definitions/handlers.ErrorResponse" + } } } }, @@ -1073,6 +1079,12 @@ "schema": { "$ref": "#/definitions/handlers.ErrorResponse" } + }, + "501": { + "description": "Snapshots currently not supported on this backend", + "schema": { + "$ref": "#/definitions/handlers.ErrorResponse" + } } } } @@ -4729,6 +4741,22 @@ } } }, + "/ping": { + "get": { + "tags": [ + "system" + ], + "summary": "Health check with server capabilities", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/handlers.PingResponse" + } + } + } + } + }, "/providers": { "get": { "description": "Get a list of all configured LLM providers", @@ -7078,6 +7106,20 @@ } } }, + "handlers.PingResponse": { + "type": "object", + "properties": { + "container_backend": { + "type": "string" + }, + "snapshot_supported": { + "type": "boolean" + }, + "status": { + "type": "string" + } + } + }, "handlers.SkillItem": { "type": "object", "properties": { diff --git a/spec/swagger.yaml b/spec/swagger.yaml index cef6608e..104418fb 100644 --- a/spec/swagger.yaml +++ b/spec/swagger.yaml @@ -816,6 +816,15 @@ definitions: url: type: string type: object + handlers.PingResponse: + properties: + container_backend: + type: string + snapshot_supported: + type: boolean + status: + type: string + type: object handlers.SkillItem: properties: content: @@ -2426,6 +2435,10 @@ paths: description: OK schema: $ref: '#/definitions/handlers.ListSnapshotsResponse' + "501": + description: Snapshots currently not supported on this backend + schema: + $ref: '#/definitions/handlers.ErrorResponse' summary: List snapshots tags: - containerd @@ -2455,6 +2468,10 @@ paths: description: Internal Server Error schema: $ref: '#/definitions/handlers.ErrorResponse' + "501": + description: Snapshots currently not supported on this backend + schema: + $ref: '#/definitions/handlers.ErrorResponse' summary: Create container snapshot for bot tags: - containerd @@ -4896,6 +4913,16 @@ paths: summary: Update model by model ID tags: - models + /ping: + get: + responses: + "200": + description: OK + schema: + $ref: '#/definitions/handlers.PingResponse' + summary: Health check with server capabilities + tags: + - system /providers: get: consumes: