Help us shape the future of Go! Take the 2026 Go Developer Survey

repository

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrGraphWorkflowVersionConflict = errors.New("graph workflow version conflict")
View Source
var ErrMessagePageChanged = errors.New("message history changed while paging")
View Source
var ErrMessagePresetConflict = errors.New("message preset configuration conflict")

Functions

func AtomicWriteFile

func AtomicWriteFile(path string, data []byte, mode os.FileMode) error

AtomicWriteFile writes data to path using the canonical temp-file + rename dance so a concurrent reader never observes a half-written file and a crash cannot leave a truncated file behind.

Algorithm:

  1. mkdir -p the parent directory (matching the previous sandbox behaviour).
  2. Create a temp file in the same directory (so the final rename is atomic on POSIX — rename(2) across directories may not be).
  3. Write, fsync the file, and close it.
  4. Rename the temp file over the destination.
  5. Best-effort fsync of the parent directory so the rename itself is durable.

The signature matches the standard library's WriteFile to make callers interchangeable; `mode` is applied to the final file.

func SortRoles

func SortRoles(roles []*model.Role)

func SortUsers

func SortUsers(users []*model.User)

Types

type ACPProbeCacheRepo

type ACPProbeCacheRepo interface {
	Load(ctx context.Context) (*model.ACPProbeCacheSnapshot, error)
	Save(ctx context.Context, snapshot *model.ACPProbeCacheSnapshot) error
}

func NewACPProbeCacheRepo

func NewACPProbeCacheRepo() (ACPProbeCacheRepo, error)

type AgentCatalogRepo

type AgentCatalogRepo interface {
	Load(ctx context.Context) (*model.AgentCatalogSnapshot, error)
	Save(ctx context.Context, snapshot *model.AgentCatalogSnapshot) error
}

func NewAgentCatalogRepo

func NewAgentCatalogRepo() (AgentCatalogRepo, error)

type AuthRepo

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

func NewAuthRepo

func NewAuthRepo() (*AuthRepo, error)

func (*AuthRepo) ConfigEntriesExist

func (r *AuthRepo) ConfigEntriesExist() (bool, error)

func (*AuthRepo) DeleteRole

func (r *AuthRepo) DeleteRole(id string) error

func (*AuthRepo) DeleteSession

func (r *AuthRepo) DeleteSession(hash string) error

func (*AuthRepo) ListRoles

func (r *AuthRepo) ListRoles() ([]*model.Role, error)

func (*AuthRepo) ListSessions

func (r *AuthRepo) ListSessions() ([]*model.AuthSession, error)

func (*AuthRepo) ListUsers

func (r *AuthRepo) ListUsers() ([]*model.User, error)

func (*AuthRepo) LoadSession

func (r *AuthRepo) LoadSession(hash string) (*model.AuthSession, error)

func (*AuthRepo) LoadSystem

func (r *AuthRepo) LoadSystem() (*model.AuthSystem, error)

func (*AuthRepo) SaveRole

func (r *AuthRepo) SaveRole(value *model.Role) error

func (*AuthRepo) SaveSession

func (r *AuthRepo) SaveSession(value *model.AuthSession) error

func (*AuthRepo) SaveSystem

func (r *AuthRepo) SaveSystem(value *model.AuthSystem) error

func (*AuthRepo) SaveUser

func (r *AuthRepo) SaveUser(value *model.User) error

type ChatContextRepo

type ChatContextRepo interface {
	LoadAllMessages(ctx context.Context) ([]*schema.Message, error)
	CountMessage(ctx context.Context) (int, error)
	// MessagesFingerprint returns a content-aware identifier for the
	// current state of messages.jsonl. Used by the ACP drift check to
	// detect cross-path mutations that count alone misses (in-place row
	// rewrites — e.g. ReplacePlaceholderToolResult — or hand edits that
	// keep the row count stable but change content). The returned hash
	// is FNV-64 over the on-disk file contents, which is reproducible
	// when nothing has changed and changes whenever any byte does. Empty
	// / missing file yields a zero-valued fingerprint.
	MessagesFingerprint(ctx context.Context) (MessagesFingerprint, error)
	// AppendMessages appends the chat messages to the file.
	AppendMessages(ctx context.Context, msgs []*schema.Message) error
	// ReplaceMessages rewrites the full message history.
	ReplaceMessages(ctx context.Context, msgs []*schema.Message) error
	// ReplacePlaceholderToolResult swaps a previously-persisted placeholder
	// tool_result (matching toolCallID and carrying the placeholder flag)
	// with the real tool result. Used by the round builder when a terminal
	// event arrives AFTER an eager-flush already wrote a [placeholder]
	// superseded row: without this stitch, the placeholder would stay on
	// disk forever and pollute both the history view and the next round's
	// LLM context.
	//
	// Returns stitched=true iff a matching placeholder row was found and
	// replaced. Returns stitched=false (no error) when the placeholder is
	// gone — e.g. a concurrent orphan-tail truncate already cut the row.
	// Errors surface I/O failures only.
	ReplacePlaceholderToolResult(ctx context.Context, toolCallID string, real *schema.Message) (bool, error)
	// WithLock acquires the per-session write lock and runs fn with a
	// LockedRepo handle whose methods bypass the per-call locking. Used
	// by callers that need a multi-step compound operation (e.g.
	// BeginRun's truncate-then-append) to be atomic across other
	// ChatContextRepo instances pointed at the same session directory.
	// Calling the regular ChatContextRepo methods inside fn would
	// deadlock — use the LockedRepo handle.
	//
	// ctx gates the lock acquisition: a Run whose persist deadline has
	// already expired observes ctx.Err() instead of blocking on a
	// contended lock. Once fn starts running, ctx cancellation no
	// longer interrupts the in-flight critical section — fn is
	// expected to honour ctx itself for its own per-step IO.
	WithLock(ctx context.Context, fn func(tx LockedRepo) error) error
}

type CodexAccountBackup

type CodexAccountBackup struct {
	Files         CodexAccountFiles `json:"files"`
	ManagedID     string            `json:"managed_id"`
	ConfigApplied bool              `json:"config_applied"`
}

type CodexAccountFiles

type CodexAccountFiles struct {
	Home   string  `json:"home"`
	Auth   *string `json:"auth"`
	Config *string `json:"config"`
}

func (CodexAccountFiles) Revision

func (f CodexAccountFiles) Revision() string

type CodexAccountRepo

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

func NewCodexAccountRepo

func NewCodexAccountRepo() (*CodexAccountRepo, error)

func (*CodexAccountRepo) Load

func (*CodexAccountRepo) PrepareLoginHome

func (r *CodexAccountRepo) PrepareLoginHome(id string) (string, error)

func (*CodexAccountRepo) ReadFiles

func (r *CodexAccountRepo) ReadFiles(home string) (CodexAccountFiles, error)

func (*CodexAccountRepo) RemoveLoginHome

func (r *CodexAccountRepo) RemoveLoginHome(id string) error

func (*CodexAccountRepo) ReplaceFiles

func (r *CodexAccountRepo) ReplaceFiles(before, after CodexAccountFiles) error

ReplaceFiles compares each file immediately before replacement. Restoration accepts either side of an interrupted transaction and refuses external edits.

func (*CodexAccountRepo) Rollback

func (r *CodexAccountRepo) Rollback(transaction *CodexAccountTransaction) error

func (*CodexAccountRepo) Save

func (r *CodexAccountRepo) Save(state *CodexAccountStore) error

type CodexAccountStore

type CodexAccountStore struct {
	Version         int                           `json:"version"`
	Revision        uint64                        `json:"revision"`
	Accounts        []StoredCodexAccount          `json:"accounts"`
	ActiveID        string                        `json:"active_id"`
	ActiveHome      string                        `json:"active_home"`
	ConfigApplied   bool                          `json:"config_applied"`
	Backup          *CodexAccountBackup           `json:"backup,omitempty"`
	Pending         *CodexAccountTransaction      `json:"pending,omitempty"`
	Operations      []model.CodexAccountOperation `json:"operations"`
	OperationHashes map[string]string             `json:"operation_hashes,omitempty"`
}

type CodexAccountTransaction

type CodexAccountTransaction struct {
	Before    CodexAccountBackup          `json:"before"`
	After     CodexAccountFiles           `json:"after"`
	Operation model.CodexAccountOperation `json:"operation"`
}

type FileShareRepo

type FileShareRepo interface {
	Create(filePath string) (*model.FileShare, error)
	Get(token string) (*model.FileShare, bool)
	GetByPath(filePath string) (*model.FileShare, bool)
	Delete(token string) error
}

func GetFileShareRepo

func GetFileShareRepo() FileShareRepo

type GraphRunRepo

type GraphRunRepo interface {
	RegisterRun(ctx context.Context, run *model.GraphRun) error
	RegisterRunLocation(ctx context.Context, runID, workspaceID, jobID string) error
	SaveRun(ctx context.Context, run *model.GraphRun) error
	GetRun(ctx context.Context, runID string) (*model.GraphRun, error)

	SaveInstances(ctx context.Context, runID string, instances map[string]model.GraphInstanceState) error
	GetInstances(ctx context.Context, runID string) (map[string]model.GraphInstanceState, error)

	SaveEdges(ctx context.Context, runID string, edges map[string]model.GraphEdgeState) error
	GetEdges(ctx context.Context, runID string) (map[string]model.GraphEdgeState, error)

	SaveVariables(ctx context.Context, runID string, variables map[string]map[string]string) error
	GetVariables(ctx context.Context, runID string) (map[string]map[string]string, error)

	SaveSessionLineage(ctx context.Context, runID string, lineage map[string]model.GraphSessionLineage) error
	GetSessionLineage(ctx context.Context, runID string) (map[string]model.GraphSessionLineage, error)

	SaveProgress(ctx context.Context, runID string, progress *model.GraphProgress) error
	GetProgress(ctx context.Context, runID string) (*model.GraphProgress, error)

	SaveResume(ctx context.Context, runID string, resume *model.GraphResumeState) error
	GetResume(ctx context.Context, runID string) (*model.GraphResumeState, error)

	AppendEvent(ctx context.Context, runID string, event *model.GraphEvent) error
	ListEvents(ctx context.Context, runID string, startLine int, count *int) ([]model.GraphEvent, error)
	// CountEvents returns the number of persisted event lines without reading
	// their content. Used by GetRunStatus to expose an event count (the SSE
	// resume cursor seed) without serialising the whole event log into the
	// status response. A missing events file yields (0, nil).
	CountEvents(ctx context.Context, runID string) (int, error)

	DeleteRun(ctx context.Context, runID string) error
}

GraphRunRepo owns GraphRun runtime artifacts. A run is stored as a directory under its bound Job directory so deleting a Job can keep its graph runtime artifacts colocated with sessions and metadata.

func NewGraphRunRepo

func NewGraphRunRepo() (GraphRunRepo, error)

type GraphWorkflowRepo

type GraphWorkflowRepo interface {
	Save(ctx context.Context, wf *model.GraphWorkflow) error
	Get(ctx context.Context, id string) (*model.GraphWorkflow, error)
	List(ctx context.Context) ([]*model.GraphWorkflow, []model.GraphWorkflowWarning, error)
	Update(ctx context.Context, id string, wf *model.GraphWorkflow) error
	UpdateIfUnchanged(ctx context.Context, id string, wf *model.GraphWorkflow, expectedUpdatedAt *time.Time) error
	Delete(ctx context.Context, id string, expectedUpdatedAt *time.Time) error
}

GraphWorkflowRepo persists editable/saved Graph workflow configs, one JSON file per workflow keyed by ID.

func NewGraphWorkflowRepo

func NewGraphWorkflowRepo() (GraphWorkflowRepo, error)

type IMJobMappingRepo

type IMJobMappingRepo interface {
	Get(platform, chatID string) (*model.IMJobMapping, error)
	Save(m *model.IMJobMapping) error
}

func NewIMJobMappingRepo

func NewIMJobMappingRepo() (IMJobMappingRepo, error)

type IMMessageRepo

type IMMessageRepo interface {
	Append(ctx context.Context, msg *model.IMMessage) error
}

func NewIMMessageRepo

func NewIMMessageRepo() IMMessageRepo

type JobRepo

type JobRepo interface {
	Save(jobID string, job *model.Job) error
	Load(jobID string) (*model.Job, error)
	ListIDs() ([]string, error)
	LoadAll() ([]*model.Job, error)
	// SweepDeleted removes complete on-disk job directories whose durable job
	// metadata is marked Deleted. It is the startup recovery half of the
	// two-phase Job deletion protocol.
	SweepDeleted() error
}

func NewJobRepo

func NewJobRepo(wsID string) (JobRepo, error)

NewJobRepo creates a JobRepo. Root dir: {LOCAL_MEMORY}/quartet/data/workspaces/{wsID}/jobs/.

type LockedRepo

type LockedRepo interface {
	LoadAllMessages(ctx context.Context) ([]*schema.Message, error)
	AppendMessages(ctx context.Context, msgs []*schema.Message) error
	ReplaceMessages(ctx context.Context, msgs []*schema.Message) error
}

LockedRepo exposes the unlocked variants of the repo's read/write methods. Returned exclusively through ChatContextRepo.WithLock so the caller already holds the per-session write lock; the methods here must NEVER take the lock themselves or the WithLock holder would deadlock against itself.

ctx is threaded for parity with ChatContextRepo so an inner operation can cooperate with cancellation (e.g. log breadcrumbs, future ctx-aware fileserver calls). The lock itself stays held for the full WithLock body — fn is the natural cancellation boundary.

type MessagePage

type MessagePage struct {
	Messages []*schema.Message
	Offsets  []int64
	// StartOffset is the cursor for the next older page. Boundary* identifies
	// the first raw row in this page so the next request can detect a rewrite.
	StartOffset       int64
	BoundaryEndOffset int64
	BoundaryHash      string
	HasMore           bool
}

type MessagePresetRepo

type MessagePresetRepo interface {
	GetGlobal() (*StoredMessagePresetConfig, error)
	GetWorkspace(workspaceID string) (*StoredMessagePresetConfig, error)
	ListWorkspaceFiles() ([]string, error)
	SaveGlobal(expectedRevision string, config *model.MessagePresetConfig) (*StoredMessagePresetConfig, error)
	SaveWorkspace(workspaceID, expectedRevision string, config *model.MessagePresetConfig) (*StoredMessagePresetConfig, error)
	DeleteWorkspace(workspaceID, expectedRevision string) error
	RebindWorkspace(sourceID, targetID, expectedRevision string, config *model.MessagePresetConfig) error
}

func NewMessagePresetRepo

func NewMessagePresetRepo() (MessagePresetRepo, error)

type MessagesFingerprint

type MessagesFingerprint struct {
	Count int    `json:"count,omitempty"`
	Hash  string `json:"hash,omitempty"`
}

MessagesFingerprint identifies the state of messages.jsonl for drift detection. Count alone is insufficient — ReplacePlaceholderToolResult rewrites a row in place without changing the count, so two distinct on-disk states can share the same Count. The Hash captures the full byte content so any mutation (in-place rewrite, hand edit, append + truncate that nets to the same count) trips the drift check.

The zero value (Count=0, Hash="") represents "no messages on disk" and is returned for missing or empty files. Two zero values compare equal, so an empty session is correctly diagnosed as "no drift".

func (MessagesFingerprint) Equal

Equal reports whether two fingerprints describe the same on-disk state. Used by the ACP drift check.

type PagedChatContextRepo

type PagedChatContextRepo interface {
	ChatContextRepo
	// LoadMessagePage reads a reverse page ending immediately before
	// beforeOffset. A zero beforeOffset starts at the current end of file.
	// boundaryEndOffset and boundaryHash validate the first row of the page
	// already returned to the client while still allowing tail appends.
	LoadMessagePage(ctx context.Context, beforeOffset, boundaryEndOffset int64, boundaryHash string, limit int) (*MessagePage, error)
}

PagedChatContextRepo adds UI-oriented reverse paging without forcing Agent context test doubles, which only need the full-history contract, to implement presentation-specific reads.

func NewChatContextRepo

func NewChatContextRepo(wsID, jobID, sessionID string) (PagedChatContextRepo, error)

NewChatContextRepo creates a ChatContextRepo. Root dir: {LOCAL_MEMORY}/quartet/data/workspaces/{wsID}/jobs/{jobID}/sessions/{sessionID}/.

Concurrency: every method serialises against other ChatContextRepo instances pointed at the same sessionDir via the process-wide lock registry in session_locks.go. Per-instance mutexes can't help here because acp / shell-persist / web-reload each construct their own instance for the same session.

type PromptRepo

type PromptRepo interface {
	Get(ctx context.Context, key string) (string, error)
	Save(ctx context.Context, key string, content string) error
}

func NewPromptRepo

func NewPromptRepo() (PromptRepo, error)

type RecentDirs

type RecentDirs struct {
	Dirs []string `json:"dirs"`
}

type RecentDirsRepo

type RecentDirsRepo interface {
	Get() (*RecentDirs, error)
	Add(ctx context.Context, dir string) error
}

func NewRecentDirsRepo

func NewRecentDirsRepo() (RecentDirsRepo, error)

type ScheduleRepo

type ScheduleRepo interface {
	Create(ctx context.Context, task *model.ScheduledTask) error
	SaveDefinition(ctx context.Context, task *model.ScheduledTask) error
	SaveState(ctx context.Context, task *model.ScheduledTask) error
	UpdateActivation(ctx context.Context, id string, enabled *bool, nextRunAt *time.Time) error
	ToggleEnabled(ctx context.Context, id string, nextRunAt *time.Time) error
	Get(ctx context.Context, id string) (*model.ScheduledTask, error)
	List(ctx context.Context) ([]*model.ScheduledTask, error)
	Delete(ctx context.Context, id string) error
}

func NewScheduleRepo

func NewScheduleRepo() (ScheduleRepo, error)

type SessionRepo

type SessionRepo interface {
	Save(sessionID string, meta *model.Session) error
	Load(sessionID string) (*model.Session, error)
	ListIDs() ([]string, error)
	LoadAll() ([]*model.Session, error)
}

func NewSessionRepo

func NewSessionRepo(wsID, jobID string) (SessionRepo, error)

NewSessionRepo creates a SessionRepo. Root dir: {LOCAL_MEMORY}/quartet/data/workspaces/{wsID}/jobs/{jobID}/sessions/.

type SettingsRepo

type SettingsRepo interface {
	Get() (*model.Settings, error)
	Save(s *model.Settings) error
}

func NewSettingsRepo

func NewSettingsRepo() (SettingsRepo, error)

type StoredCodexAccount

type StoredCodexAccount struct {
	Info     model.CodexAccount `json:"info"`
	Identity string             `json:"identity"`
	Auth     string             `json:"auth"`
	Config   *string            `json:"config,omitempty"`
}

type StoredMessagePresetConfig

type StoredMessagePresetConfig struct {
	Config   *model.MessagePresetConfig
	Revision string
	File     string
}

type UserInputRepo

type UserInputRepo interface {
	Append(ctx context.Context, input *model.UserInput) error
}

UserInputRepo appends "真实用户输入" entries — the narrow-spec stream that covers IM admin private chat + Web, flat-dated under {LOCAL_MEMORY}/quartet/data/user-input/YYYY-MM-DD.jsonl. Coexists with IMMessageRepo: the two feeds have different intakes and different consumers (see docs/feature-2026-05-03-user-input-logging.md §4).

func NewUserInputRepo

func NewUserInputRepo() UserInputRepo

type WeChatOutboxRepo

type WeChatOutboxRepo interface {
	Save(ctx context.Context, task *model.WeChatOutboxTask) error
	Get(ctx context.Context, id string) (*model.WeChatOutboxTask, error)
	List(ctx context.Context) ([]*model.WeChatOutboxTask, error)
}

func NewWeChatOutboxRepo

func NewWeChatOutboxRepo() (WeChatOutboxRepo, error)

type WorkspaceRepo

type WorkspaceRepo interface {
	Save(id string, ws *model.Workspace) error
	Load(id string) (*model.Workspace, error)
	ListIDs() ([]string, error)
	LoadAll() ([]*model.Workspace, error)
	// SweepDeleted removes on-disk directories for workspaces marked as
	// deleted. Split from LoadAll so the read path has no write side effects.
	SweepDeleted() error
	RemoveDir(id string) error
}

func NewWorkspaceRepo

func NewWorkspaceRepo() (WorkspaceRepo, error)

Jump to

Keyboard shortcuts

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