botbackup

package
v0.20.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 15, 2026 License: AGPL-3.0 Imports: 42 Imported by: 0

Documentation

Index

Constants

View Source
const (
	BackupSchemaVersion = 1
	ManifestPath        = "manifest.json"
)

Variables

AllExportSections lists the sections a backup can contain, in display order. profile is always exported (it identifies the bot) and is not user-toggleable.

View Source
var ErrHistoryResetUnavailable = errors.New("bot backup: ACP history reset coordination is unavailable")

ErrHistoryResetUnavailable means an overwrite that can invalidate ACP state could not acquire the mandatory distributed runtime-reset boundary.

Functions

This section is empty.

Types

type ACPRuntimeCloser

type ACPRuntimeCloser interface {
	BeginBotHistoryReset(ctx context.Context, botID string) (resetCtx context.Context, release func(), err error)
}

type ExportOptions

type ExportOptions struct {
	// Sections lists which sections to include. nil/empty ⇒ all sections.
	// profile is always exported regardless.
	Sections []Section `json:"sections,omitempty"`
}

func NormalizeExportOptions

func NormalizeExportOptions(opts ExportOptions) ExportOptions

type ExportRequest

type ExportRequest struct {
	Sections   []Section `json:"sections,omitempty"`
	Passphrase string    `json:"passphrase,omitempty"`
}

ExportRequest is the export endpoint body. Passphrase is kept out of ExportOptions on purpose so it can never leak into the bundle manifest: when set, the resulting bundle is encrypted with it.

type ImportMode

type ImportMode string
const (
	ImportModeCreate    ImportMode = "create"
	ImportModeOverwrite ImportMode = "overwrite"
)

type ImportOptions

type ImportOptions struct {
	Mode        ImportMode `json:"mode,omitempty"`
	TargetBotID string     `json:"target_bot_id,omitempty"`
	// Sections maps a section to its import strategy (skip|merge|replace).
	// nil ⇒ every section imported with the default (merge). A section absent
	// from a non-nil map, or mapped to "skip", is not imported.
	Sections map[Section]ImportStrategy `json:"sections,omitempty"`
}

type ImportResult

type ImportResult struct {
	BotID    string   `json:"bot_id"`
	Created  bool     `json:"created"`
	Warnings []string `json:"warnings,omitempty"`
	// Imported reports how many items were restored per section, powering the
	// post-import summary in the UI.
	Imported map[Section]int `json:"imported,omitempty"`
}

type ImportStrategy

type ImportStrategy string

ImportStrategy controls how a section is applied to the target bot on import.

const (
	StrategySkip    ImportStrategy = "skip"
	StrategyMerge   ImportStrategy = "merge"
	StrategyReplace ImportStrategy = "replace"
)

type Manifest

type Manifest struct {
	SchemaVersion int               `json:"schema_version"`
	App           string            `json:"app"`
	ExportedAt    time.Time         `json:"exported_at"`
	SourceBotID   string            `json:"source_bot_id"`
	SourceBotName string            `json:"source_bot_name"`
	Options       ManifestOptions   `json:"options"`
	Entries       []ManifestEntry   `json:"entries"`
	Warnings      []string          `json:"warnings,omitempty"`
	Checksums     map[string]string `json:"checksums,omitempty"`
}

type ManifestEntry

type ManifestEntry struct {
	Path string `json:"path"`
	Type string `json:"type"`
}

type ManifestOptions

type ManifestOptions struct {
	Sections []Section `json:"sections,omitempty"`
}

type Params

type Params struct {
	Logger          *slog.Logger
	DB              *pgxpool.Pool
	Queries         dbstore.Queries
	Bots            *bots.Service
	Settings        *settings.Service
	ACL             *acl.Service
	Channels        *channel.Store
	MCP             *mcp.ConnectionService
	Schedules       *schedule.Service
	Email           *emailpkg.Service
	Providers       *providerpkg.Service
	Models          *modelpkg.Service
	SearchProviders *searchpkg.Service
	FetchProviders  *fetchpkg.Service
	MemoryProviders *memprovider.Service
	Workspace       WorkspaceData
	ACPRuntimes     ACPRuntimeCloser
	Workdirs        dbstore.BotWorkdirStore
}

type PreviewResult

type PreviewResult struct {
	Manifest    Manifest         `json:"manifest"`
	Profile     *ProfilePreview  `json:"profile,omitempty"`
	Conflicts   []string         `json:"conflicts"`
	Missing     []string         `json:"missing"`
	Warnings    []string         `json:"warnings"`
	Sections    []SectionSummary `json:"sections"`
	RestorePlan RestorePlan      `json:"restore_plan"`
	// Encrypted reports that the uploaded bundle is passphrase-encrypted. When
	// true and no (or a wrong) passphrase was supplied, the other fields are
	// empty and the UI should prompt for the passphrase. RequiresPassphrase
	// distinguishes "needs a passphrase" from "passphrase was wrong".
	Encrypted          bool `json:"encrypted"`
	RequiresPassphrase bool `json:"requires_passphrase"`
}

type ProfilePreview

type ProfilePreview struct {
	DisplayName string `json:"display_name"`
	AvatarURL   string `json:"avatar_url"`
	Timezone    string `json:"timezone"`
	IsActive    bool   `json:"is_active"`
}

ProfilePreview surfaces the backup's bot identity so the UI can show an avatar + name card before importing.

type RestorePlan

type RestorePlan struct {
	Mode                 ImportMode     `json:"mode"`
	TargetBotID          string         `json:"target_bot_id,omitempty"`
	WillCreateBot        bool           `json:"will_create_bot"`
	WillRestoreWorkspace bool           `json:"will_restore_workspace"`
	DependencyMatches    map[string]int `json:"dependency_matches,omitempty"`
}

type Section

type Section string

Section identifies a selectable group of data within a backup. On import, each section can be individually included or skipped. The bot profile is always imported (it creates or updates the bot itself) and is not a section.

const (
	SectionProfile   Section = "profile"
	SectionSettings  Section = "settings"
	SectionModels    Section = "models"
	SectionACL       Section = "acl"
	SectionChannels  Section = "channels"
	SectionMCP       Section = "mcp"
	SectionSchedules Section = "schedules"
	SectionEmail     Section = "email"
	SectionHistory   Section = "history"
	SectionAssets    Section = "assets"
	SectionWorkspace Section = "workspace"
)

type SectionSummary

type SectionSummary struct {
	Key         Section  `json:"key"`
	Count       int      `json:"count"`
	TargetCount int      `json:"target_count"`
	Conflict    bool     `json:"conflict"`
	Sensitive   bool     `json:"sensitive"`
	Items       []string `json:"items,omitempty"`
}

SectionSummary reports a restorable section, how many items it holds, and (in overwrite mode) how many the target already has. Items lists a sample of the contained item labels for an expandable detail view.

type Service

type Service struct {
	// contains filtered or unexported fields
}

func New

func New(params Params) *Service

func (*Service) Export

func (s *Service) Export(ctx context.Context, botID string, opts ExportOptions, dst io.Writer) error

func (*Service) Import

func (s *Service) Import(ctx context.Context, actorUserID string, raw []byte, opts ImportOptions, passphrase string) (ImportResult, error)

func (*Service) Preview

func (s *Service) Preview(ctx context.Context, raw []byte, opts ImportOptions, passphrase string) (PreviewResult, error)

func (*Service) Summary

func (s *Service) Summary(ctx context.Context, botID string) (SummaryResult, error)

Summary reports what a live bot would export: per-section item counts and a sample of item labels. It powers the export dialog so users see counts and details (and skip empty sections) before exporting. Unlike Export it does not pause the bot or stream the workspace, and it counts history/assets/workspace without loading them in full.

type SummaryResult

type SummaryResult struct {
	Profile  *ProfilePreview  `json:"profile,omitempty"`
	Sections []SectionSummary `json:"sections"`
}

SummaryResult describes what a live bot would export, for the export dialog.

type WorkspaceData

type WorkspaceData interface {
	ExportData(ctx context.Context, botID string) (io.ReadCloser, error)
	ImportData(ctx context.Context, botID string, r io.Reader) error
	// CountData returns the number of files in the bot's workspace /data. It is
	// best-effort context for the export dialog; an error means "unknown".
	CountData(ctx context.Context, botID string) (int, error)
}

Directories

Path Synopsis
Package secure provides passphrase-based authenticated encryption for bot backup bundles.
Package secure provides passphrase-based authenticated encryption for bot backup bundles.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL