源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
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
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
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
package workspace
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
workspaceissues "github.com/tutti-os/tutti/packages/workspace/issues"
|
||||
)
|
||||
|
||||
// SearchRunOutputs matches output files by display name across one workspace,
|
||||
// joining the owning issue for its title (and for topic scoping). Results are
|
||||
// recency-ordered and deduplicated by path, mirroring GetIssueDetail outputs.
|
||||
func (s *SQLiteStore) SearchRunOutputs(ctx context.Context, params workspaceissues.RunOutputSearchParams) ([]workspaceissues.RunOutputSearchHit, error) {
|
||||
if err := s.ensureIssueDatabase(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.ensureIssueWorkspace(ctx, params.WorkspaceID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// query 为空时 LIKE '%%' 匹配全部 —— 即「仅按类型筛选」的 list-all(由下方 filters 收窄)。
|
||||
where := []string{"o.workspace_id = ?", "LOWER(o.display_name) LIKE ?"}
|
||||
args := []any{params.WorkspaceID, "%" + strings.ToLower(params.Query) + "%"}
|
||||
if params.IssueID != "" {
|
||||
where = append(where, "o.issue_id = ?")
|
||||
args = append(args, params.IssueID)
|
||||
} else if params.TopicID != "" {
|
||||
where = append(where, "i.topic_id = ?")
|
||||
args = append(args, params.TopicID)
|
||||
}
|
||||
// 文件类型筛选(全局统一口径):按 display_name 扩展名收窄,见 reference_filter_categories.go。
|
||||
if clause, clauseArgs := referenceFilterDisplayNameClause("o.display_name", params.Filters); clause != "" {
|
||||
where = append(where, clause)
|
||||
args = append(args, clauseArgs...)
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`
|
||||
SELECT o.id, o.output_id, o.run_id, o.task_id, o.issue_id, o.workspace_id,
|
||||
o.path, o.display_name, o.media_type, o.size_bytes, o.created_at_unix_ms,
|
||||
i.title
|
||||
FROM workspace_issue_run_outputs o
|
||||
JOIN workspace_issues i
|
||||
ON i.workspace_id = o.workspace_id AND i.issue_id = o.issue_id
|
||||
WHERE %s
|
||||
ORDER BY o.created_at_unix_ms DESC, o.id DESC
|
||||
LIMIT ?
|
||||
`, strings.Join(where, " AND "))
|
||||
args = append(args, params.Limit)
|
||||
|
||||
rows, err := s.readDB.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("search workspace issue run outputs: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
hits := make([]workspaceissues.RunOutputSearchHit, 0)
|
||||
seenPaths := map[string]struct{}{}
|
||||
for rows.Next() {
|
||||
hit, err := scanWorkspaceIssueRunOutputSearchHit(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dedupKey := strings.TrimSpace(hit.Output.Path)
|
||||
if _, exists := seenPaths[dedupKey]; exists {
|
||||
continue
|
||||
}
|
||||
seenPaths[dedupKey] = struct{}{}
|
||||
hits = append(hits, hit)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("iterate workspace issue run output search: %w", err)
|
||||
}
|
||||
return hits, nil
|
||||
}
|
||||
Reference in New Issue
Block a user