Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

698 lines
34 KiB
Go

package workspace
import (
"context"
"database/sql"
"errors"
"fmt"
"strings"
"github.com/tutti-os/tutti/packages/agent/daemon/providerregistry"
agentactivitybiz "github.com/tutti-os/tutti/packages/agent/store-sqlite"
agenttargetbiz "github.com/tutti-os/tutti/services/tuttid/biz/agenttarget"
)
var _ agentactivitybiz.Repository = (*SQLiteStore)(nil)
var _ AgentActivityStore = (*SQLiteStore)(nil)
// Agent activity and agent target persistence is delegated to the
// embeddable packages/agent/store-sqlite module, sharing this store's
// database handle. The delegation below keeps tuttid's persistence seams thin
// while store-sqlite owns canonical query and migration behavior.
var _ AgentActivityStore = (*SQLiteStore)(nil)
const legacyIDLocalCodex = "local-codex"
const legacyIDLocalClaudeCode = "local-claude-code"
func newAgentStore(db *sql.DB) *agentactivitybiz.Store {
return agentactivitybiz.New(db, agentactivitybiz.Options{
WorkspaceExists: func(ctx context.Context, workspaceID string) error {
return ensureWorkspaceExistsOn(ctx, db, workspaceID)
},
ProjectPaths: userProjectPathsQuerier{},
NormalizeTarget: normalizeStoreAgentTarget,
IsSkippableTargetError: isSkippableAgentTargetRowError,
SeedSystemTargets: defaultSystemStoreAgentTargets,
LegacySystemTargetIDRenames: map[string]string{
legacyIDLocalCodex: agenttargetbiz.IDLocalCodex,
legacyIDLocalClaudeCode: agenttargetbiz.IDLocalClaudeCode,
},
TargetIDBackfillByProvider: defaultTargetIDBackfillByProvider(),
TransactionParticipant: agentTransactionParticipants{
tuttiModeSourceActivityParticipant{},
agentTurnTerminalAnalyticsParticipant{},
},
})
}
func defaultTargetIDBackfillByProvider() map[string]string {
result := map[string]string{
"claude-code": agenttargetbiz.IDLocalClaudeCode,
"cursor": agenttargetbiz.IDLocalCursor,
}
for _, descriptor := range providerregistry.Migrated() {
result[descriptor.Identity.ID] = descriptor.Target.ID
}
return result
}
func (s *SQLiteStore) agentStore() *agentactivitybiz.Store {
if s == nil {
return nil
}
return s.agentWriter
}
// AgentCanonicalStore exposes the official canonical agent store for Host
// composition. Product services must not wrap its lifecycle mutations.
func (s *SQLiteStore) AgentCanonicalStore() *agentactivitybiz.Store {
return s.agentStore()
}
func (s *SQLiteStore) agentReadStore() *agentactivitybiz.Store {
if s == nil {
return nil
}
if s.agentReader != nil {
return s.agentReader
}
return s.agentWriter
}
// userProjectPathsQuerier feeds the user_projects table into the agent
// store's rail section classification, using whatever querier (transaction
// or database) the store is currently running on.
type userProjectPathsQuerier struct{}
func (userProjectPathsQuerier) ProjectPaths(ctx context.Context, q agentactivitybiz.Querier) ([]string, error) {
rows, err := q.QueryContext(ctx, `
SELECT path
FROM user_projects
WHERE TRIM(path) != ''
ORDER BY length(path) DESC, path ASC
`)
if err != nil {
return nil, fmt.Errorf("list user projects for workspace agent session rail classification: %w", err)
}
defer rows.Close()
paths := make([]string, 0)
for rows.Next() {
var path string
if err := rows.Scan(&path); err != nil {
return nil, fmt.Errorf("scan user project for workspace agent session rail classification: %w", err)
}
path = strings.TrimSpace(path)
if path != "" {
paths = append(paths, path)
}
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate user projects for workspace agent session rail classification: %w", err)
}
return paths, nil
}
func (s *SQLiteStore) ReportSessionState(ctx context.Context, input agentactivitybiz.SessionStateReport) (agentactivitybiz.StateReportResult, error) {
return s.agentStore().ReportSessionState(ctx, input)
}
func (s *SQLiteStore) BindGoalProvenance(ctx context.Context, input agentactivitybiz.BindGoalProvenanceInput) (agentactivitybiz.GoalProvenanceBinding, error) {
return s.agentStore().BindGoalProvenance(ctx, input)
}
func (s *SQLiteStore) LookupGoalProvenance(ctx context.Context, input agentactivitybiz.LookupGoalProvenanceInput) (agentactivitybiz.GoalProvenanceBinding, bool, error) {
return s.agentReadStore().LookupGoalProvenance(ctx, input)
}
func (s *SQLiteStore) ReportActivityState(ctx context.Context, input agentactivitybiz.ActivityStateReport) (agentactivitybiz.ActivityStateReportResult, error) {
return s.agentStore().ReportActivityState(ctx, input)
}
func (s *SQLiteStore) ReportSessionMessages(ctx context.Context, input agentactivitybiz.SessionMessageReport) (agentactivitybiz.MessageReportResult, error) {
return s.agentStore().ReportSessionMessages(ctx, input)
}
func (s *SQLiteStore) PutGoalReconcileInbox(ctx context.Context, input agentactivitybiz.GoalReconcileInboxItem) (bool, error) {
return s.agentStore().PutGoalReconcileInbox(ctx, input)
}
func (s *SQLiteStore) ListClaimableGoalReconcileInbox(ctx context.Context, now int64, limit int) ([]agentactivitybiz.GoalReconcileInboxItem, error) {
return s.agentReadStore().ListClaimableGoalReconcileInbox(ctx, now, limit)
}
func (s *SQLiteStore) ClaimGoalReconcileInbox(ctx context.Context, input agentactivitybiz.ClaimGoalReconcileInboxInput) (agentactivitybiz.GoalReconcileInboxItem, bool, error) {
return s.agentStore().ClaimGoalReconcileInbox(ctx, input)
}
func (s *SQLiteStore) CompleteGoalReconcileInbox(ctx context.Context, requestID, owner string, now int64) (bool, error) {
return s.agentStore().CompleteGoalReconcileInbox(ctx, requestID, owner, now)
}
func (s *SQLiteStore) ReleaseGoalReconcileInbox(ctx context.Context, input agentactivitybiz.ReleaseGoalReconcileInboxInput) (bool, error) {
return s.agentStore().ReleaseGoalReconcileInbox(ctx, input)
}
func (s *SQLiteStore) RequeueLeasedGoalReconcileInboxOnStartup(ctx context.Context, now int64) (int64, error) {
return s.agentStore().RequeueLeasedGoalReconcileInboxOnStartup(ctx, now)
}
func (s *SQLiteStore) GetSession(ctx context.Context, workspaceID string, agentSessionID string) (agentactivitybiz.Session, bool, error) {
return s.agentReadStore().GetSession(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) ListChildSessions(ctx context.Context, workspaceID string, agentSessionID string) ([]agentactivitybiz.Session, error) {
return s.agentReadStore().ListChildSessions(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) SessionDeleted(ctx context.Context, workspaceID string, agentSessionID string) (bool, error) {
return s.agentReadStore().SessionDeleted(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) ListDeletedSessions(ctx context.Context, input agentactivitybiz.ListDeletedSessionsInput) (agentactivitybiz.DeletedSessionPage, error) {
return s.agentReadStore().ListDeletedSessions(ctx, input)
}
func (s *SQLiteStore) RestoreDeletedSession(ctx context.Context, input agentactivitybiz.RestoreDeletedSessionInput) (agentactivitybiz.RestoreDeletedSessionResult, error) {
return s.agentStore().RestoreDeletedSession(ctx, input)
}
func (s *SQLiteStore) PurgeDeletedSessionTrees(ctx context.Context, input agentactivitybiz.PurgeDeletedSessionTreesInput) (agentactivitybiz.PurgeDeletedSessionTreesResult, error) {
if s == nil || s.writeDB == nil {
return agentactivitybiz.PurgeDeletedSessionTreesResult{}, errors.New("workspace database is not initialized")
}
tx, err := s.writeDB.BeginTx(ctx, nil)
if err != nil {
return agentactivitybiz.PurgeDeletedSessionTreesResult{}, fmt.Errorf("begin purge deleted agent and Tutti mode sessions: %w", err)
}
defer func() { _ = tx.Rollback() }()
result, err := s.agentStore().PurgeDeletedSessionTreesTx(ctx, tx, input)
if err != nil {
return agentactivitybiz.PurgeDeletedSessionTreesResult{}, err
}
if err := deleteTuttiModeSessionStatesTx(ctx, tx, strings.TrimSpace(input.WorkspaceID), result.PurgedSessionIDs); err != nil {
return agentactivitybiz.PurgeDeletedSessionTreesResult{}, err
}
cleanupItems := make([]AgentSessionResourceCleanup, 0, len(result.PurgedSessionIDs))
for _, sessionID := range result.PurgedSessionIDs {
cleanupItems = append(cleanupItems, AgentSessionResourceCleanup{
WorkspaceID: strings.TrimSpace(input.WorkspaceID), AgentSessionID: sessionID,
})
}
if err := enqueueAgentSessionResourceCleanupTx(ctx, tx, cleanupItems); err != nil {
return agentactivitybiz.PurgeDeletedSessionTreesResult{}, err
}
if err := tx.Commit(); err != nil {
return agentactivitybiz.PurgeDeletedSessionTreesResult{}, fmt.Errorf("commit purge deleted agent and Tutti mode sessions: %w", err)
}
return result, nil
}
func (s *SQLiteStore) ListRecoverableDeletedSessionResources(ctx context.Context) ([]agentactivitybiz.DeletedSessionResource, error) {
return s.agentReadStore().ListRecoverableDeletedSessionResources(ctx)
}
func (s *SQLiteStore) RollbackRuntimeSessionInitialization(ctx context.Context, workspaceID string, agentSessionID string) (bool, error) {
return s.agentStore().RollbackRuntimeSessionInitialization(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) ListSessions(ctx context.Context, workspaceID string) ([]agentactivitybiz.Session, bool, error) {
return s.agentReadStore().ListSessions(ctx, workspaceID)
}
func (s *SQLiteStore) ListSessionsPage(ctx context.Context, input agentactivitybiz.ListSessionsPageInput) (agentactivitybiz.SessionListPage, bool, error) {
return s.agentReadStore().ListSessionsPage(ctx, input)
}
func (s *SQLiteStore) ListSessionSection(ctx context.Context, input agentactivitybiz.ListSessionSectionInput) (agentactivitybiz.SessionSectionPage, bool, error) {
return s.agentReadStore().ListSessionSection(ctx, input)
}
func (s *SQLiteStore) ListSessionSections(ctx context.Context, input agentactivitybiz.ListSessionSectionsInput) (agentactivitybiz.SessionSectionsPage, bool, error) {
return s.agentReadStore().ListSessionSections(ctx, input)
}
func (s *SQLiteStore) ListSessionSectionDeletionCandidates(ctx context.Context, input agentactivitybiz.ListSessionSectionDeletionCandidatesInput) (agentactivitybiz.SessionSectionDeletionCandidates, bool, error) {
return s.agentReadStore().ListSessionSectionDeletionCandidates(ctx, input)
}
func (s *SQLiteStore) ListSessionMessages(ctx context.Context, input agentactivitybiz.ListSessionMessagesInput) (agentactivitybiz.MessagePage, bool, error) {
return s.agentReadStore().ListSessionMessages(ctx, input)
}
func (s *SQLiteStore) ListWorkspaceGeneratedFileTurns(ctx context.Context, input agentactivitybiz.ListWorkspaceGeneratedFileTurnsInput) (agentactivitybiz.GeneratedFileTurnList, bool, error) {
return s.agentReadStore().ListWorkspaceGeneratedFileTurns(ctx, input)
}
func (s *SQLiteStore) DeleteSession(ctx context.Context, workspaceID string, agentSessionID string) (bool, error) {
return s.agentStore().DeleteSession(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) DeleteSessionWithCommit(ctx context.Context, workspaceID string, agentSessionID string) (agentactivitybiz.DeleteSessionResult, error) {
return s.agentStore().DeleteSessionWithCommit(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) DeleteSessionsBatch(ctx context.Context, input agentactivitybiz.DeleteSessionsBatchInput) (agentactivitybiz.DeleteSessionsBatchResult, error) {
return s.agentStore().DeleteSessionsBatch(ctx, input)
}
func (s *SQLiteStore) PlanDeleteSessions(ctx context.Context, input agentactivitybiz.DeleteSessionsBatchInput) (agentactivitybiz.DeleteSessionsPlan, error) {
return s.agentReadStore().PlanDeleteSessions(ctx, input)
}
func (s *SQLiteStore) PlanClearSessions(ctx context.Context, workspaceID string) (agentactivitybiz.DeleteSessionsPlan, error) {
return s.agentReadStore().PlanClearSessions(ctx, workspaceID)
}
func (s *SQLiteStore) ClearSessions(ctx context.Context, workspaceID string) (agentactivitybiz.ClearSessionsResult, error) {
if s == nil || s.writeDB == nil {
return agentactivitybiz.ClearSessionsResult{}, errors.New("workspace database is not initialized")
}
workspaceID = strings.TrimSpace(workspaceID)
if workspaceID == "" {
return agentactivitybiz.ClearSessionsResult{}, nil
}
tx, err := s.writeDB.BeginTx(ctx, nil)
if err != nil {
return agentactivitybiz.ClearSessionsResult{}, fmt.Errorf("begin clear agent and Tutti mode sessions: %w", err)
}
defer func() { _ = tx.Rollback() }()
result, err := s.agentStore().ClearSessionsTx(ctx, tx, workspaceID)
if err != nil {
return agentactivitybiz.ClearSessionsResult{}, err
}
if err := deleteTuttiModeWorkspaceSessionStateTx(ctx, tx, workspaceID); err != nil {
return agentactivitybiz.ClearSessionsResult{}, err
}
if err := tx.Commit(); err != nil {
return agentactivitybiz.ClearSessionsResult{}, fmt.Errorf("commit clear agent and Tutti mode sessions: %w", err)
}
return result, nil
}
func deleteTuttiModeSessionStatesTx(ctx context.Context, tx *sql.Tx, workspaceID string, sessionIDs []string) error {
for _, sessionID := range sessionIDs {
sessionID = strings.TrimSpace(sessionID)
if sessionID == "" {
continue
}
if _, err := tx.ExecContext(ctx, `DELETE FROM tutti_mode_turn_snapshots WHERE workspace_id = ? AND agent_session_id = ?`, workspaceID, sessionID); err != nil {
return fmt.Errorf("delete Tutti mode turn snapshots with agent session: %w", err)
}
if _, err := tx.ExecContext(ctx, `DELETE FROM tutti_mode_activations WHERE workspace_id = ? AND agent_session_id = ?`, workspaceID, sessionID); err != nil {
return fmt.Errorf("delete Tutti mode activation with agent session: %w", err)
}
}
return nil
}
func deleteTuttiModeWorkspaceSessionStateTx(ctx context.Context, tx *sql.Tx, workspaceID string) error {
if _, err := tx.ExecContext(ctx, `DELETE FROM tutti_mode_turn_snapshots WHERE workspace_id = ?`, workspaceID); err != nil {
return fmt.Errorf("clear Tutti mode turn snapshots with agent sessions: %w", err)
}
if _, err := tx.ExecContext(ctx, `DELETE FROM tutti_mode_activations WHERE workspace_id = ?`, workspaceID); err != nil {
return fmt.Errorf("clear Tutti mode activations with agent sessions: %w", err)
}
return nil
}
func (s *SQLiteStore) PurgeDeletedSessions(ctx context.Context, input agentactivitybiz.PurgeDeletedSessionsInput) (agentactivitybiz.PurgeDeletedSessionsResult, error) {
if s == nil || s.writeDB == nil {
return agentactivitybiz.PurgeDeletedSessionsResult{}, errors.New("workspace database is not initialized")
}
tx, err := s.writeDB.BeginTx(ctx, nil)
if err != nil {
return agentactivitybiz.PurgeDeletedSessionsResult{}, fmt.Errorf("begin purge deleted agent and Tutti mode sessions: %w", err)
}
defer func() { _ = tx.Rollback() }()
result, err := s.agentStore().PurgeDeletedSessionsTx(ctx, tx, input)
if err != nil {
return agentactivitybiz.PurgeDeletedSessionsResult{}, err
}
sessionIDsByWorkspace := make(map[string][]string)
cleanupItems := make([]AgentSessionResourceCleanup, 0, len(result.Sessions))
for _, session := range result.Sessions {
workspaceID := strings.TrimSpace(session.WorkspaceID)
sessionIDsByWorkspace[workspaceID] = append(sessionIDsByWorkspace[workspaceID], session.AgentSessionID)
cleanupItems = append(cleanupItems, AgentSessionResourceCleanup{
WorkspaceID: workspaceID, AgentSessionID: session.AgentSessionID,
})
}
for workspaceID, sessionIDs := range sessionIDsByWorkspace {
if err := deleteTuttiModeSessionStatesTx(ctx, tx, workspaceID, sessionIDs); err != nil {
return agentactivitybiz.PurgeDeletedSessionsResult{}, err
}
}
if err := enqueueAgentSessionResourceCleanupTx(ctx, tx, cleanupItems); err != nil {
return agentactivitybiz.PurgeDeletedSessionsResult{}, err
}
if err := tx.Commit(); err != nil {
return agentactivitybiz.PurgeDeletedSessionsResult{}, fmt.Errorf("commit purge deleted agent and Tutti mode sessions: %w", err)
}
return result, nil
}
func (s *SQLiteStore) UpdateSessionPinned(ctx context.Context, workspaceID string, agentSessionID string, pinned bool) (agentactivitybiz.Session, bool, error) {
return s.agentStore().UpdateSessionPinned(ctx, workspaceID, agentSessionID, pinned)
}
func (s *SQLiteStore) UpdateSessionSettings(ctx context.Context, workspaceID string, agentSessionID string, model string, settings map[string]any) (agentactivitybiz.Session, bool, error) {
return s.agentStore().UpdateSessionSettings(ctx, workspaceID, agentSessionID, model, settings)
}
func (s *SQLiteStore) UpdateSessionTitle(ctx context.Context, workspaceID string, agentSessionID string, title string) (agentactivitybiz.Session, bool, error) {
return s.agentStore().UpdateSessionTitle(ctx, workspaceID, agentSessionID, title)
}
func (s *SQLiteStore) GetTurn(ctx context.Context, workspaceID string, agentSessionID string, turnID string) (agentactivitybiz.Turn, bool, error) {
return s.agentReadStore().GetTurn(ctx, workspaceID, agentSessionID, turnID)
}
func (s *SQLiteStore) GetTurnSubmission(ctx context.Context, workspaceID string, agentSessionID string, turnID string) (agentactivitybiz.TurnSubmission, bool, error) {
return s.agentReadStore().GetTurnSubmission(ctx, workspaceID, agentSessionID, turnID)
}
func (s *SQLiteStore) GetLatestTurn(ctx context.Context, workspaceID string, agentSessionID string) (agentactivitybiz.Turn, bool, error) {
return s.agentReadStore().GetLatestTurn(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) ListLatestTurns(ctx context.Context, workspaceID string, agentSessionIDs []string) (map[string]agentactivitybiz.Turn, error) {
return s.agentReadStore().ListLatestTurns(ctx, workspaceID, agentSessionIDs)
}
func (s *SQLiteStore) ListLatestTurnInteractions(ctx context.Context, workspaceID string, agentSessionIDs []string) (map[string][]agentactivitybiz.Interaction, error) {
return s.agentReadStore().ListLatestTurnInteractions(ctx, workspaceID, agentSessionIDs)
}
func (s *SQLiteStore) ListTurnsBySession(ctx context.Context, workspaceID string, turnIDBySessionID map[string]string) (map[string]agentactivitybiz.Turn, error) {
return s.agentReadStore().ListTurnsBySession(ctx, workspaceID, turnIDBySessionID)
}
func (s *SQLiteStore) ListPendingInteractionsBySession(ctx context.Context, workspaceID string, agentSessionIDs []string) (map[string][]agentactivitybiz.Interaction, error) {
return s.agentReadStore().ListPendingInteractionsBySession(ctx, workspaceID, agentSessionIDs)
}
func (s *SQLiteStore) ListSessionTurns(ctx context.Context, workspaceID string, agentSessionID string) ([]agentactivitybiz.Turn, error) {
return s.agentReadStore().ListSessionTurns(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) ListEffectiveSessionTurns(ctx context.Context, workspaceID string, agentSessionID string) ([]agentactivitybiz.Turn, error) {
return s.agentReadStore().ListEffectiveSessionTurns(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) ListSessionTurnSummaries(ctx context.Context, input agentactivitybiz.ListSessionTurnSummariesInput) (agentactivitybiz.SessionTurnSummaryPage, error) {
return s.agentReadStore().ListSessionTurnSummaries(ctx, input)
}
func (s *SQLiteStore) SettleStaleTurns(ctx context.Context) ([]agentactivitybiz.StaleTurnSettlement, error) {
return s.agentStore().SettleStaleTurns(ctx)
}
func (s *SQLiteStore) ListSessionInteractions(ctx context.Context, input agentactivitybiz.ListSessionInteractionsInput) ([]agentactivitybiz.Interaction, error) {
return s.agentReadStore().ListSessionInteractions(ctx, input)
}
func (s *SQLiteStore) PrepareRuntimeOperation(ctx context.Context, input agentactivitybiz.RuntimeOperationPrepare) (agentactivitybiz.RuntimeOperation, bool, error) {
return s.agentStore().PrepareRuntimeOperation(ctx, input)
}
func (s *SQLiteStore) PrepareInteractiveRuntimeOperation(ctx context.Context, input agentactivitybiz.RuntimeOperationPrepare) (agentactivitybiz.RuntimeOperation, agentactivitybiz.Interaction, agentactivitybiz.InteractionTransitionResult, error) {
return s.agentStore().PrepareInteractiveRuntimeOperation(ctx, input)
}
func (s *SQLiteStore) PrepareGoalControlOperation(ctx context.Context, input agentactivitybiz.GoalControlOperationPrepare) (agentactivitybiz.GoalControlOperation, agentactivitybiz.SessionGoalState, bool, error) {
return s.agentStore().PrepareGoalControlOperation(ctx, input)
}
func (s *SQLiteStore) AdoptProviderGoalOperation(ctx context.Context, input agentactivitybiz.ProviderGoalAdoption) (agentactivitybiz.GoalControlOperation, agentactivitybiz.SessionGoalState, bool, error) {
return s.agentStore().AdoptProviderGoalOperation(ctx, input)
}
func (s *SQLiteStore) GetGoalControlAudit(ctx context.Context, workspaceID string, agentSessionID string, operationID string) (agentactivitybiz.Message, bool, error) {
return s.agentReadStore().GetGoalControlAudit(ctx, workspaceID, agentSessionID, operationID)
}
func (s *SQLiteStore) MarkGoalControlOperationDispatched(ctx context.Context, workspaceID, operationID string, occurredAtUnixMS int64) (agentactivitybiz.GoalControlOperation, bool, error) {
return s.agentStore().MarkGoalControlOperationDispatched(ctx, workspaceID, operationID, occurredAtUnixMS)
}
func (s *SQLiteStore) AcknowledgeGoalControlOperation(ctx context.Context, input agentactivitybiz.GoalControlOperationAcknowledge) (agentactivitybiz.GoalControlOperation, agentactivitybiz.SessionGoalState, bool, error) {
return s.agentStore().AcknowledgeGoalControlOperation(ctx, input)
}
func (s *SQLiteStore) CompleteGoalControlOperation(ctx context.Context, input agentactivitybiz.GoalControlOperationComplete) (agentactivitybiz.GoalControlOperation, agentactivitybiz.SessionGoalState, bool, error) {
return s.agentStore().CompleteGoalControlOperation(ctx, input)
}
func (s *SQLiteStore) GetSessionGoalState(ctx context.Context, workspaceID, agentSessionID string) (agentactivitybiz.SessionGoalState, bool, error) {
return s.agentReadStore().GetSessionGoalState(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) ListSessionGoalStates(ctx context.Context, workspaceID string, agentSessionIDs []string) (map[string]agentactivitybiz.SessionGoalState, error) {
return s.agentReadStore().ListSessionGoalStates(ctx, workspaceID, agentSessionIDs)
}
func (s *SQLiteStore) ReconcileSessionGoalObservation(ctx context.Context, input agentactivitybiz.GoalObservationReconcile) (agentactivitybiz.SessionGoalState, error) {
return s.agentStore().ReconcileSessionGoalObservation(ctx, input)
}
func (s *SQLiteStore) GetGoalControlOperation(ctx context.Context, workspaceID, operationID string) (agentactivitybiz.GoalControlOperation, bool, error) {
return s.agentReadStore().GetGoalControlOperation(ctx, workspaceID, operationID)
}
func (s *SQLiteStore) ListClaimableGoalControlOperations(ctx context.Context, input agentactivitybiz.ListClaimableGoalControlOperationsInput) ([]agentactivitybiz.GoalControlOperation, error) {
return s.agentReadStore().ListClaimableGoalControlOperations(ctx, input)
}
func (s *SQLiteStore) ClaimGoalControlOperation(ctx context.Context, input agentactivitybiz.ClaimGoalControlOperationInput) (agentactivitybiz.GoalControlOperation, bool, error) {
return s.agentStore().ClaimGoalControlOperation(ctx, input)
}
func (s *SQLiteStore) ReleaseGoalControlOperation(ctx context.Context, input agentactivitybiz.ReleaseGoalControlOperationInput) (agentactivitybiz.GoalControlOperation, bool, error) {
return s.agentStore().ReleaseGoalControlOperation(ctx, input)
}
func (s *SQLiteStore) RecordGoalControlOperationEvidence(ctx context.Context, input agentactivitybiz.GoalControlOperationEvidence) (agentactivitybiz.GoalControlOperation, bool, error) {
return s.agentStore().RecordGoalControlOperationEvidence(ctx, input)
}
func (s *SQLiteStore) EnsureOrWakeGoalRepairOperation(ctx context.Context, input agentactivitybiz.EnsureGoalRepairOperationInput) (agentactivitybiz.GoalControlOperation, agentactivitybiz.SessionGoalState, bool, error) {
return s.agentStore().EnsureOrWakeGoalRepairOperation(ctx, input)
}
func (s *SQLiteStore) MarkGoalRevisionTerminalIncident(ctx context.Context, input agentactivitybiz.GoalTerminalIncidentInput) (agentactivitybiz.SessionGoalState, error) {
return s.agentStore().MarkGoalRevisionTerminalIncident(ctx, input)
}
func (s *SQLiteStore) RequeueLeasedGoalControlOperationsOnStartup(ctx context.Context, now int64) (int64, error) {
return s.agentStore().RequeueLeasedGoalControlOperationsOnStartup(ctx, now)
}
func (s *SQLiteStore) PrepareGoalGenerationFence(ctx context.Context, input agentactivitybiz.GoalGenerationFencePrepare) (agentactivitybiz.GoalGenerationFence, bool, error) {
return s.agentStore().PrepareGoalGenerationFence(ctx, input)
}
func (s *SQLiteStore) GetGoalGenerationFence(ctx context.Context, workspaceID, fenceID string) (agentactivitybiz.GoalGenerationFence, bool, error) {
return s.agentReadStore().GetGoalGenerationFence(ctx, workspaceID, fenceID)
}
func (s *SQLiteStore) ListGoalGenerationFencesForSession(ctx context.Context, workspaceID, agentSessionID string) ([]agentactivitybiz.GoalGenerationFence, error) {
return s.agentReadStore().ListGoalGenerationFencesForSession(ctx, workspaceID, agentSessionID)
}
func (s *SQLiteStore) ListClaimableGoalGenerationFences(ctx context.Context, input agentactivitybiz.ListClaimableGoalGenerationFencesInput) ([]agentactivitybiz.GoalGenerationFence, error) {
return s.agentReadStore().ListClaimableGoalGenerationFences(ctx, input)
}
func (s *SQLiteStore) ClaimGoalGenerationFence(ctx context.Context, input agentactivitybiz.ClaimGoalGenerationFenceInput) (agentactivitybiz.GoalGenerationFence, bool, error) {
return s.agentStore().ClaimGoalGenerationFence(ctx, input)
}
func (s *SQLiteStore) ReleaseGoalGenerationFence(ctx context.Context, input agentactivitybiz.ReleaseGoalGenerationFenceInput) (agentactivitybiz.GoalGenerationFence, bool, error) {
return s.agentStore().ReleaseGoalGenerationFence(ctx, input)
}
func (s *SQLiteStore) CompleteGoalGenerationFence(ctx context.Context, input agentactivitybiz.CompleteGoalGenerationFenceInput) (agentactivitybiz.GoalGenerationFence, bool, error) {
return s.agentStore().CompleteGoalGenerationFence(ctx, input)
}
func (s *SQLiteStore) RequeueLeasedGoalGenerationFencesOnStartup(ctx context.Context, now int64) (int64, error) {
return s.agentStore().RequeueLeasedGoalGenerationFencesOnStartup(ctx, now)
}
func (s *SQLiteStore) PrepareSubmitClaim(ctx context.Context, input agentactivitybiz.SubmitClaimPrepare) (agentactivitybiz.SubmitClaim, bool, error) {
return s.agentStore().PrepareSubmitClaim(ctx, input)
}
func (s *SQLiteStore) GetSubmitClaim(ctx context.Context, workspaceID, agentSessionID, clientSubmitID string) (agentactivitybiz.SubmitClaim, bool, error) {
return s.agentStore().GetSubmitClaim(ctx, workspaceID, agentSessionID, clientSubmitID)
}
func (s *SQLiteStore) AcceptSubmitClaim(ctx context.Context, workspaceID, agentSessionID, clientSubmitID, turnID string, nowUnixMS int64) (agentactivitybiz.SubmitClaim, bool, error) {
return s.agentStore().AcceptSubmitClaim(ctx, workspaceID, agentSessionID, clientSubmitID, turnID, nowUnixMS)
}
func (s *SQLiteStore) RejectSubmitClaim(ctx context.Context, workspaceID, agentSessionID, clientSubmitID, turnID string, nowUnixMS int64) (agentactivitybiz.SubmitClaim, bool, error) {
return s.agentStore().RejectSubmitClaim(ctx, workspaceID, agentSessionID, clientSubmitID, turnID, nowUnixMS)
}
func (s *SQLiteStore) DeleteSubmitClaim(ctx context.Context, workspaceID, agentSessionID, clientSubmitID string) (bool, error) {
return s.agentStore().DeleteSubmitClaim(ctx, workspaceID, agentSessionID, clientSubmitID)
}
func (s *SQLiteStore) GetRuntimeOperation(ctx context.Context, workspaceID string, operationID string) (agentactivitybiz.RuntimeOperation, bool, error) {
return s.agentReadStore().GetRuntimeOperation(ctx, workspaceID, operationID)
}
func (s *SQLiteStore) ListClaimableRuntimeOperations(ctx context.Context, input agentactivitybiz.ListClaimableRuntimeOperationsInput) ([]agentactivitybiz.RuntimeOperation, error) {
return s.agentReadStore().ListClaimableRuntimeOperations(ctx, input)
}
func (s *SQLiteStore) ClaimRuntimeOperationLease(ctx context.Context, input agentactivitybiz.ClaimRuntimeOperationLeaseInput) (agentactivitybiz.RuntimeOperation, bool, error) {
return s.agentStore().ClaimRuntimeOperationLease(ctx, input)
}
func (s *SQLiteStore) ReleaseOrFailRuntimeOperation(ctx context.Context, input agentactivitybiz.ReleaseOrFailRuntimeOperationInput) (agentactivitybiz.RuntimeOperation, bool, error) {
return s.agentStore().ReleaseOrFailRuntimeOperation(ctx, input)
}
func (s *SQLiteStore) CheckpointRuntimeOperation(ctx context.Context, input agentactivitybiz.CheckpointRuntimeOperationInput) (agentactivitybiz.RuntimeOperation, bool, error) {
return s.agentStore().CheckpointRuntimeOperation(ctx, input)
}
func (s *SQLiteStore) RequeueLeasedRuntimeOperationsOnStartup(ctx context.Context, nowUnixMS int64) (int64, error) {
return s.agentStore().RequeueLeasedRuntimeOperationsOnStartup(ctx, nowUnixMS)
}
func (s *SQLiteStore) CompleteInteractiveRuntimeOperation(ctx context.Context, input agentactivitybiz.CompleteInteractiveRuntimeOperationInput) (agentactivitybiz.RuntimeOperationCompletion, bool, error) {
return s.agentStore().CompleteInteractiveRuntimeOperation(ctx, input)
}
func (s *SQLiteStore) CompleteCancelRuntimeOperation(ctx context.Context, input agentactivitybiz.CompleteCancelRuntimeOperationInput) (agentactivitybiz.RuntimeOperationCompletion, bool, error) {
return s.agentStore().CompleteCancelRuntimeOperation(ctx, input)
}
func (s *SQLiteStore) CompletePlanDecisionRuntimeOperation(ctx context.Context, input agentactivitybiz.CompletePlanDecisionRuntimeOperationInput) (agentactivitybiz.RuntimeOperationCompletion, bool, error) {
return s.agentStore().CompletePlanDecisionRuntimeOperation(ctx, input)
}
func (s *SQLiteStore) FindTurnByClientSubmitID(ctx context.Context, workspaceID string, agentSessionID string, clientSubmitID string) (string, bool, error) {
return s.agentReadStore().FindTurnByClientSubmitID(ctx, workspaceID, agentSessionID, clientSubmitID)
}
func (s *SQLiteStore) ListPendingRuntimeOperationEvents(ctx context.Context, workspaceID string, limit int) ([]agentactivitybiz.RuntimeOperationEvent, error) {
return s.agentReadStore().ListPendingRuntimeOperationEvents(ctx, workspaceID, limit)
}
func (s *SQLiteStore) MarkRuntimeOperationEventPublished(ctx context.Context, workspaceID string, eventID int64, publishedAtUnixMS int64) (bool, error) {
return s.agentStore().MarkRuntimeOperationEventPublished(ctx, workspaceID, eventID, publishedAtUnixMS)
}
func (s *SQLiteStore) ListAgentTargets(ctx context.Context) ([]agenttargetbiz.Target, error) {
targets, err := s.agentReadStore().ListAgentTargets(ctx)
if err != nil {
return nil, err
}
var result []agenttargetbiz.Target
for _, target := range targets {
result = append(result, agentTargetFromStore(target))
}
return result, nil
}
func (s *SQLiteStore) GetAgentTarget(ctx context.Context, id string) (agenttargetbiz.Target, error) {
target, err := s.agentReadStore().GetAgentTarget(ctx, id)
if err != nil {
return agenttargetbiz.Target{}, err
}
return agentTargetFromStore(target), nil
}
func (s *SQLiteStore) PutAgentTarget(ctx context.Context, target agenttargetbiz.Target) (agenttargetbiz.Target, error) {
stored, err := s.agentStore().PutAgentTarget(ctx, agentTargetToStore(target))
if err != nil {
return agenttargetbiz.Target{}, err
}
return agentTargetFromStore(stored), nil
}
func (s *SQLiteStore) DeleteAgentTarget(ctx context.Context, id string) error {
return s.agentStore().DeleteAgentTarget(ctx, id)
}
// ResolveAgentTargetAlias reverse-looks-up which registered agent target
// claims the given id as an alias, returning that target's primary id.
//
// Contract: cross-domain id translation is owned by the host projection layer
// (tsh/tutti-os rewrites a shared session's owner-domain agentTargetId to the
// caller-local `shared-agent:{sharedAgentId}` id at its sync boundary), so
// owner-domain ids are never expected to reach this store and no alias column
// is planned. This hook exists purely as defense in depth for the ingestion
// boundary in services/tuttid/service/agent: a hit means an upstream missed
// its translation. The store-backed implementation therefore resolves
// nothing.
func (*SQLiteStore) ResolveAgentTargetAlias(context.Context, string) (string, bool) {
return "", false
}
func agentTargetToStore(target agenttargetbiz.Target) agentactivitybiz.Target {
return agentactivitybiz.Target{
ID: target.ID,
Provider: target.Provider,
LaunchRefJSON: target.LaunchRefJSON,
Name: target.Name,
IconKey: target.IconKey,
IconURL: target.IconURL,
MaskIconURL: target.MaskIconURL,
HeroImageURL: target.HeroImageURL,
Enabled: target.Enabled,
Source: target.Source,
SortOrder: target.SortOrder,
CreatedAtUnixMS: target.CreatedAtUnixMS,
UpdatedAtUnixMS: target.UpdatedAtUnixMS,
}
}
func agentTargetFromStore(target agentactivitybiz.Target) agenttargetbiz.Target {
return agenttargetbiz.Target{
ID: target.ID,
Provider: target.Provider,
LaunchRefJSON: target.LaunchRefJSON,
Name: target.Name,
IconKey: target.IconKey,
IconURL: target.IconURL,
MaskIconURL: target.MaskIconURL,
HeroImageURL: target.HeroImageURL,
Enabled: target.Enabled,
Source: target.Source,
SortOrder: target.SortOrder,
CreatedAtUnixMS: target.CreatedAtUnixMS,
UpdatedAtUnixMS: target.UpdatedAtUnixMS,
}
}
func normalizeStoreAgentTarget(target agentactivitybiz.Target) (agentactivitybiz.Target, error) {
normalized, err := agenttargetbiz.NormalizeTarget(agentTargetFromStore(target))
if err != nil {
return agentactivitybiz.Target{}, err
}
return agentTargetToStore(normalized), nil
}
func isSkippableAgentTargetRowError(err error) bool {
return errors.Is(err, agenttargetbiz.ErrInvalidTarget) ||
errors.Is(err, agenttargetbiz.ErrInvalidLaunchRef)
}
func defaultSystemStoreAgentTargets(nowUnixMS int64) []agentactivitybiz.Target {
defaults := agenttargetbiz.DefaultSystemTargets(nowUnixMS)
targets := make([]agentactivitybiz.Target, 0, len(defaults))
for _, target := range defaults {
targets = append(targets, agentTargetToStore(target))
}
return targets
}