Files
tutti/services/tuttid/api/daemon_agent_session_list.go
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

251 lines
10 KiB
Go

package api
import (
"context"
"log/slog"
"strings"
tuttigenerated "github.com/tutti-os/tutti/services/tuttid/api/generated"
"github.com/tutti-os/tutti/services/tuttid/apierrors"
agentservice "github.com/tutti-os/tutti/services/tuttid/service/agent"
)
const listWorkspaceAgentSessionsLimitMax = 100
func agentSessionServiceUnavailableError() tuttigenerated.ServiceUnavailableErrorJSONResponse {
return serviceUnavailableError(
apierrors.WorkspaceAgentSessionServiceUnavailable(
apierrors.WithDeveloperMessage("workspace agent session service is unavailable"),
),
)
}
func (api DaemonAPI) ListWorkspaceAgentSessions(ctx context.Context, request tuttigenerated.ListWorkspaceAgentSessionsRequestObject) (tuttigenerated.ListWorkspaceAgentSessionsResponseObject, error) {
if api.AgentSessionService == nil {
return tuttigenerated.ListWorkspaceAgentSessions503JSONResponse{
ServiceUnavailableErrorJSONResponse: agentSessionServiceUnavailableError(),
}, nil
}
input := agentservice.ListSessionsInput{}
if request.Params.AgentTargetId != nil {
input.AgentTargetID = strings.TrimSpace(*request.Params.AgentTargetId)
}
if request.Params.Cursor != nil {
input.Cursor = strings.TrimSpace(*request.Params.Cursor)
}
if request.Params.SearchQuery != nil {
input.SearchQuery = strings.TrimSpace(*request.Params.SearchQuery)
}
if request.Params.Limit != nil {
if *request.Params.Limit <= 0 || *request.Params.Limit > listWorkspaceAgentSessionsLimitMax {
return writeListWorkspaceAgentSessionsError(agentservice.ErrInvalidArgument), nil
}
input.Limit = int(*request.Params.Limit)
}
workspaceID := string(request.WorkspaceID)
page, err := api.AgentSessionService.ListPage(ctx, workspaceID, input)
if err != nil {
return writeListWorkspaceAgentSessionsError(err), nil
}
generatedSessions, err := generatedAgentSessions(page.Sessions)
if err != nil {
return writeListWorkspaceAgentSessionsError(err), nil
}
slog.Info("workspace agent sessions list completed",
"event", "workspace.agent_session.api.list_completed",
"workspace_id", workspaceID,
"session_count", len(page.Sessions),
)
response := tuttigenerated.ListWorkspaceAgentSessions200JSONResponse{
HasMore: page.HasMore,
Sessions: generatedSessions,
WorkspaceId: workspaceID,
}
if page.NextCursor != "" {
response.NextCursor = &page.NextCursor
}
return response, nil
}
func (api DaemonAPI) ListWorkspaceAgentSessionSections(ctx context.Context, request tuttigenerated.ListWorkspaceAgentSessionSectionsRequestObject) (tuttigenerated.ListWorkspaceAgentSessionSectionsResponseObject, error) {
if api.AgentSessionService == nil {
return tuttigenerated.ListWorkspaceAgentSessionSections503JSONResponse{
ServiceUnavailableErrorJSONResponse: agentSessionServiceUnavailableError(),
}, nil
}
input := agentservice.ListSessionSectionsInput{LimitPerSection: 5}
if request.Params.AgentTargetId != nil {
input.AgentTargetID = strings.TrimSpace(*request.Params.AgentTargetId)
}
if request.Params.LimitPerSection != nil {
if *request.Params.LimitPerSection <= 0 || *request.Params.LimitPerSection > listWorkspaceAgentSessionsLimitMax {
return writeListWorkspaceAgentSessionSectionsError(agentservice.ErrInvalidArgument), nil
}
input.LimitPerSection = int(*request.Params.LimitPerSection)
}
page, err := api.AgentSessionService.ListSessionSections(ctx, string(request.WorkspaceID), input)
if err != nil {
return writeListWorkspaceAgentSessionSectionsError(err), nil
}
generatedPinned, err := generatedAgentSessionPage(page.Pinned)
if err != nil {
return writeListWorkspaceAgentSessionSectionsError(err), nil
}
generatedSections, err := generatedAgentSessionSections(page.Sections)
if err != nil {
return writeListWorkspaceAgentSessionSectionsError(err), nil
}
return tuttigenerated.ListWorkspaceAgentSessionSections200JSONResponse{
Pinned: generatedPinned,
Sections: generatedSections,
WorkspaceId: page.WorkspaceID,
}, nil
}
func (api DaemonAPI) ListWorkspaceAgentSessionSectionPage(ctx context.Context, request tuttigenerated.ListWorkspaceAgentSessionSectionPageRequestObject) (tuttigenerated.ListWorkspaceAgentSessionSectionPageResponseObject, error) {
if api.AgentSessionService == nil {
return tuttigenerated.ListWorkspaceAgentSessionSectionPage503JSONResponse{
ServiceUnavailableErrorJSONResponse: agentSessionServiceUnavailableError(),
}, nil
}
input := agentservice.ListSessionSectionPageInput{
Limit: 5,
SectionKey: strings.TrimSpace(request.Params.SectionKey),
}
if request.Params.AgentTargetId != nil {
input.AgentTargetID = strings.TrimSpace(*request.Params.AgentTargetId)
}
if request.Params.Cursor != nil {
input.Cursor = strings.TrimSpace(*request.Params.Cursor)
}
if request.Params.Limit != nil {
if *request.Params.Limit <= 0 || *request.Params.Limit > listWorkspaceAgentSessionsLimitMax {
return writeListWorkspaceAgentSessionSectionPageError(agentservice.ErrInvalidArgument), nil
}
input.Limit = int(*request.Params.Limit)
}
section, err := api.AgentSessionService.ListSessionSectionPage(ctx, string(request.WorkspaceID), input)
if err != nil {
return writeListWorkspaceAgentSessionSectionPageError(err), nil
}
generatedSection, err := generatedAgentSessionSection(section)
if err != nil {
return writeListWorkspaceAgentSessionSectionPageError(err), nil
}
return tuttigenerated.ListWorkspaceAgentSessionSectionPage200JSONResponse{
Section: generatedSection,
WorkspaceId: string(request.WorkspaceID),
}, nil
}
func (api DaemonAPI) ListWorkspaceAgentSessionSectionDeletionCandidates(ctx context.Context, request tuttigenerated.ListWorkspaceAgentSessionSectionDeletionCandidatesRequestObject) (tuttigenerated.ListWorkspaceAgentSessionSectionDeletionCandidatesResponseObject, error) {
if api.AgentSessionService == nil {
return tuttigenerated.ListWorkspaceAgentSessionSectionDeletionCandidates503JSONResponse{
ServiceUnavailableErrorJSONResponse: agentSessionServiceUnavailableError(),
}, nil
}
input := agentservice.ListSessionSectionDeletionCandidatesInput{
SectionKey: strings.TrimSpace(request.Params.SectionKey),
}
if request.Params.AgentTargetId != nil {
input.AgentTargetID = strings.TrimSpace(*request.Params.AgentTargetId)
}
if request.Params.ExcludePinned != nil {
input.ExcludePinned = *request.Params.ExcludePinned
}
candidates, err := api.AgentSessionService.ListSessionSectionDeletionCandidates(ctx, string(request.WorkspaceID), input)
if err != nil {
return writeListWorkspaceAgentSessionSectionDeletionCandidatesError(err), nil
}
response := tuttigenerated.ListWorkspaceAgentSessionSectionDeletionCandidates200JSONResponse{
ExcludePinned: candidates.ExcludePinned,
SectionKey: candidates.SectionKey,
SessionIds: candidates.SessionIDs,
WorkspaceId: candidates.WorkspaceID,
}
if strings.TrimSpace(candidates.AgentTargetID) != "" {
response.AgentTargetId = &candidates.AgentTargetID
}
return response, nil
}
func (api DaemonAPI) DeleteWorkspaceAgentSessionsBatch(ctx context.Context, request tuttigenerated.DeleteWorkspaceAgentSessionsBatchRequestObject) (tuttigenerated.DeleteWorkspaceAgentSessionsBatchResponseObject, error) {
if api.AgentSessionService == nil {
return tuttigenerated.DeleteWorkspaceAgentSessionsBatch503JSONResponse{
ServiceUnavailableErrorJSONResponse: agentSessionServiceUnavailableError(),
}, nil
}
if request.Body == nil {
return writeDeleteWorkspaceAgentSessionsBatchError(agentservice.ErrInvalidArgument), nil
}
sessionIDs, ok := normalizeBatchDeleteSessionIDs(request.Body.SessionIds)
if !ok {
return writeDeleteWorkspaceAgentSessionsBatchError(agentservice.ErrInvalidArgument), nil
}
result, err := api.AgentSessionService.DeleteSessionsBatch(ctx, string(request.WorkspaceID), agentservice.DeleteSessionsBatchInput{
SessionIDs: sessionIDs,
})
if err != nil {
return writeDeleteWorkspaceAgentSessionsBatchError(err), nil
}
return tuttigenerated.DeleteWorkspaceAgentSessionsBatch200JSONResponse{
RemovedMessages: result.RemovedMessages,
RemovedSessionIds: append([]string{}, result.RemovedSessionIDs...),
RemovedSessions: result.RemovedSessions,
CleanupFailedSessionIds: append([]string{}, result.CleanupFailedSessionIDs...),
}, nil
}
func normalizeBatchDeleteSessionIDs(input []string) ([]string, bool) {
if len(input) == 0 {
return nil, false
}
result := make([]string, 0, len(input))
seen := make(map[string]struct{}, len(input))
for _, value := range input {
sessionID := strings.TrimSpace(value)
if sessionID == "" {
return nil, false
}
if _, exists := seen[sessionID]; exists {
return nil, false
}
seen[sessionID] = struct{}{}
result = append(result, sessionID)
}
return result, true
}
func (api DaemonAPI) ListWorkspaceAgentPinnedSessionPage(ctx context.Context, request tuttigenerated.ListWorkspaceAgentPinnedSessionPageRequestObject) (tuttigenerated.ListWorkspaceAgentPinnedSessionPageResponseObject, error) {
if api.AgentSessionService == nil {
return tuttigenerated.ListWorkspaceAgentPinnedSessionPage503JSONResponse{
ServiceUnavailableErrorJSONResponse: agentSessionServiceUnavailableError(),
}, nil
}
input := agentservice.ListPinnedSessionPageInput{Limit: 5}
if request.Params.AgentTargetId != nil {
input.AgentTargetID = strings.TrimSpace(*request.Params.AgentTargetId)
}
if request.Params.Cursor != nil {
input.Cursor = strings.TrimSpace(*request.Params.Cursor)
}
if request.Params.Limit != nil {
if *request.Params.Limit <= 0 || *request.Params.Limit > listWorkspaceAgentSessionsLimitMax {
return writeListWorkspaceAgentPinnedSessionPageError(agentservice.ErrInvalidArgument), nil
}
input.Limit = int(*request.Params.Limit)
}
page, err := api.AgentSessionService.ListPinnedSessionPage(ctx, string(request.WorkspaceID), input)
if err != nil {
return writeListWorkspaceAgentPinnedSessionPageError(err), nil
}
generatedPage, err := generatedAgentSessionPage(page)
if err != nil {
return writeListWorkspaceAgentPinnedSessionPageError(err), nil
}
return tuttigenerated.ListWorkspaceAgentPinnedSessionPage200JSONResponse{
Page: generatedPage,
WorkspaceId: string(request.WorkspaceID),
}, nil
}