Files
wehub-resource-sync f99010fae1
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Linux) (push) Has been cancelled
Desktop Artifacts / Desktop Build (Windows) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Has been cancelled
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:36 +08:00

969 lines
26 KiB
Go

package db
import (
"bufio"
"context"
"database/sql"
"encoding/json"
"fmt"
"io"
"slices"
"strings"
"time"
"unicode"
corerecall "go.kenn.io/agentsview/internal/recall"
)
type RecallImportResult struct {
Imported int `json:"imported"`
Skipped int `json:"skipped"`
WouldImport int `json:"would_import,omitempty"`
ImportedEntries []RecallImportItem `json:"imported_entries,omitempty"`
WouldImportEntries []RecallImportItem `json:"would_import_entries,omitempty"`
SkippedEntries []RecallImportItem `json:"skipped_entries,omitempty"`
}
type RecallImportItem struct {
CandidateID string `json:"candidate_id"`
Title string `json:"title,omitempty"`
SourceSessionID string `json:"source_session_id,omitempty"`
SupersedesEntryID string `json:"supersedes_entry_id,omitempty"`
Label string `json:"label,omitempty"`
Reason string `json:"reason,omitempty"`
}
type RecallImportOptions struct {
DryRun bool
RequireExistingSessions bool
AllowProductionImport bool
}
type recallImportQueryer interface {
recallEvidenceQueryer
recallQueryRower
}
type probeAcceptedRecallEntry struct {
CandidateID string `json:"candidate_id"`
RunID string `json:"run_id"`
SessionID string `json:"session_id"`
EpisodeID string `json:"episode_id"`
Type string `json:"type"`
Scope string `json:"scope"`
Title string `json:"title"`
Body string `json:"body"`
Trigger string `json:"trigger"`
Confidence *float64 `json:"confidence"`
Uncertainty string `json:"uncertainty"`
Project string `json:"project"`
CWD string `json:"cwd"`
GitBranch string `json:"git_branch"`
Agent string `json:"agent"`
ExtractorMethod string `json:"extractor_method"`
Model string `json:"model"`
Label string `json:"label"`
SupersedesEntryID string `json:"supersedes_entry_id"`
Transferable bool `json:"transferable"`
ProvenanceOK bool `json:"provenance_ok"`
Evidence probeRecallEvidence `json:"evidence"`
}
type probeRecallEvidence struct {
OrdinalStart *int `json:"ordinal_start"`
OrdinalEnd *int `json:"ordinal_end"`
ToolUseIDs []string `json:"tool_use_ids"`
Snippets []string `json:"snippets"`
}
func (db *DB) ImportAcceptedRecallEntriesJSONL(
ctx context.Context, r io.Reader,
) (RecallImportResult, error) {
return db.ImportAcceptedRecallEntriesJSONLWithOptions(
ctx, r, RecallImportOptions{},
)
}
func (db *DB) ImportAcceptedRecallEntriesJSONLWithOptions(
ctx context.Context, r io.Reader, opts RecallImportOptions,
) (RecallImportResult, error) {
var result RecallImportResult
scanner := bufio.NewScanner(r)
scanner.Buffer(make([]byte, 0, 64*1024), 4*1024*1024)
lineNo := 0
seen := make(map[string]struct{})
dryRunProjection := newRecallImportDryRunProjection()
for scanner.Scan() {
lineNo++
line := strings.TrimSpace(scanner.Text())
if line == "" {
continue
}
var fields map[string]json.RawMessage
if err := json.Unmarshal([]byte(line), &fields); err != nil {
return result, fmt.Errorf(
"importing recall line %d: invalid JSON: %w",
lineNo, err,
)
}
if field, ok, err := hostControlledRecallImportField(fields); err != nil {
return result, fmt.Errorf(
"importing recall line %d: %w",
lineNo,
err,
)
} else if ok {
return result, fmt.Errorf(
"importing recall line %d: %s is host-controlled",
lineNo,
field,
)
}
var item probeAcceptedRecallEntry
if err := json.Unmarshal([]byte(line), &item); err != nil {
return result, fmt.Errorf(
"importing recall line %d: invalid JSON: %w",
lineNo, err,
)
}
item = normalizeProbeAcceptedRecallEntry(item)
if reason := probeRecallEntrySkipReason(item); reason != "" {
result.Skipped++
result.SkippedEntries = append(
result.SkippedEntries,
probeRecallImportItem(item, reason),
)
continue
}
recall, err := probeRecallEntryToDB(item)
if err != nil {
return result, fmt.Errorf(
"importing recall line %d: %w", lineNo, err,
)
}
if _, dup := seen[recall.ID]; dup {
// A duplicate candidate_id earlier in this stream: a real
// import inserts the first and skips the rest, so the dry-run
// must skip it too instead of double-counting WouldImport.
result.Skipped++
result.SkippedEntries = append(
result.SkippedEntries,
probeRecallImportItem(item, "duplicate"),
)
continue
}
seen[recall.ID] = struct{}{}
if opts.DryRun {
duplicate, err := db.validateRecallImportDryRun(
ctx, item, &recall, opts, dryRunProjection,
)
if err != nil {
return result, fmt.Errorf(
"importing recall line %d: %w", lineNo, err,
)
}
if duplicate {
result.Skipped++
result.SkippedEntries = append(
result.SkippedEntries,
probeRecallImportItem(item, "duplicate"),
)
continue
}
dryRunProjection.add(recall)
result.WouldImport++
result.WouldImportEntries = append(
result.WouldImportEntries,
probeRecallImportItem(item, ""),
)
continue
}
inserted, err := db.importAcceptedRecallEntry(
ctx, item, recall, opts,
)
if err != nil {
return result, fmt.Errorf(
"importing recall line %d: %w", lineNo, err,
)
}
if !inserted {
result.Skipped++
result.SkippedEntries = append(
result.SkippedEntries,
probeRecallImportItem(item, "duplicate"),
)
continue
}
result.Imported++
result.ImportedEntries = append(
result.ImportedEntries,
probeRecallImportItem(item, ""),
)
}
if err := scanner.Err(); err != nil {
return result, fmt.Errorf("reading entries JSONL: %w", err)
}
if err := ctx.Err(); err != nil {
return result, err
}
return result, nil
}
func (db *DB) validateRecallImportDryRun(
ctx context.Context,
item probeAcceptedRecallEntry,
recall *RecallEntry,
opts RecallImportOptions,
projection *recallImportDryRunProjection,
) (bool, error) {
tx, err := db.getReader().BeginTx(ctx, &sql.TxOptions{ReadOnly: true})
if err != nil {
return false, fmt.Errorf("begin recall import dry-run: %w", err)
}
defer func() { _ = tx.Rollback() }()
duplicate, err := recallImportEntryExistsWithQueryer(
ctx, tx, recall.ID,
)
if err != nil {
return false, err
}
if duplicate {
return true, nil
}
if opts.RequireExistingSessions {
if err := requireRecallImportSessionWithQueryer(ctx, tx, item); err != nil {
return false, err
}
if err := requireRecallImportEvidenceWithQueryer(ctx, tx, *recall); err != nil {
return false, err
}
if err := bindVerifiedRecallImportEvidenceWithQueryer(
ctx, tx, recall,
); err != nil {
return false, err
}
} else {
if err := validateRecallImportPlaceholderSessionStateWithQueryer(
ctx, tx, recall.SourceSessionID,
); err != nil {
return false, err
}
recall.ProvenanceOK = false
}
if !opts.RequireExistingSessions {
projected := false
if recall.SupersedesEntryID != "" {
_, projected = projection.activeEntries[recall.SupersedesEntryID]
}
if !projected {
if err := rejectUnverifiedRecallImportTrustedSupersession(
ctx, tx, *recall,
); err != nil {
return false, err
}
}
}
if err := projection.validateSupersession(ctx, tx, *recall); err != nil {
return false, err
}
if err := tx.Commit(); err != nil {
return false, fmt.Errorf("commit recall import dry-run: %w", err)
}
return false, nil
}
type recallImportDryRunProjection struct {
activeEntries map[string]struct{}
consumedEntryIDs map[string]struct{}
}
func newRecallImportDryRunProjection() *recallImportDryRunProjection {
return &recallImportDryRunProjection{
activeEntries: make(map[string]struct{}),
consumedEntryIDs: make(map[string]struct{}),
}
}
func (p *recallImportDryRunProjection) validateSupersession(
ctx context.Context,
queryer recallImportQueryer,
recall RecallEntry,
) error {
targetID := recall.SupersedesEntryID
if targetID == "" {
return nil
}
if _, consumed := p.consumedEntryIDs[targetID]; consumed {
return fmt.Errorf("superseded entry %s is not active", targetID)
}
if _, projected := p.activeEntries[targetID]; projected {
return nil
}
return requireActiveRecallSupersessionTarget(ctx, queryer, targetID)
}
func (p *recallImportDryRunProjection) add(recall RecallEntry) {
p.activeEntries[recall.ID] = struct{}{}
if recall.SupersedesEntryID != "" {
p.consumedEntryIDs[recall.SupersedesEntryID] = struct{}{}
}
}
func recallImportEntryExistsWithQueryer(
ctx context.Context,
queryer recallImportQueryer,
id string,
) (bool, error) {
var duplicate bool
if err := queryer.QueryRowContext(ctx, `
SELECT EXISTS (SELECT 1 FROM recall_entries WHERE id = ?)
`, id).Scan(&duplicate); err != nil {
return false, fmt.Errorf("checking duplicate: %w", err)
}
return duplicate, nil
}
func validateRecallImportSupersessionWithQueryer(
ctx context.Context,
queryer recallImportQueryer,
recall RecallEntry,
) error {
if recall.SupersedesEntryID == "" {
return nil
}
return requireActiveRecallSupersessionTarget(
ctx, queryer, recall.SupersedesEntryID,
)
}
func rejectUnverifiedRecallImportTrustedSupersession(
ctx context.Context,
queryer recallImportQueryer,
recall RecallEntry,
) error {
if recall.SupersedesEntryID == "" {
return nil
}
var provenanceOK bool
err := queryer.QueryRowContext(ctx, `
SELECT provenance_ok
FROM recall_entries
WHERE id = ?
`, recall.SupersedesEntryID).Scan(&provenanceOK)
if err == sql.ErrNoRows {
return nil
}
if err != nil {
return fmt.Errorf(
"checking superseded entry %s provenance: %w",
recall.SupersedesEntryID, err,
)
}
if provenanceOK {
return fmt.Errorf(
"unverified recall import cannot supersede provenance-valid entry %s",
recall.SupersedesEntryID,
)
}
return nil
}
// importAcceptedRecallEntry verifies and binds evidence in the same serialized
// writer transaction that inserts the entry. A concurrent transcript rewrite
// can therefore either precede validation or reconcile the committed row; it
// cannot land in the gap between a reader snapshot and insertion.
func (db *DB) importAcceptedRecallEntry(
ctx context.Context,
item probeAcceptedRecallEntry,
recall RecallEntry,
opts RecallImportOptions,
) (bool, error) {
if err := normalizeRecallEntryReviewState(&recall); err != nil {
return false, err
}
if recall.Status == "" {
recall.Status = corerecall.StatusAccepted
}
db.mu.Lock()
defer db.mu.Unlock()
tx, err := db.getWriter().BeginTx(ctx, nil)
if err != nil {
return false, fmt.Errorf("begin recall import: %w", err)
}
defer func() { _ = tx.Rollback() }()
duplicate, err := recallImportEntryExistsWithQueryer(ctx, tx, recall.ID)
if err != nil {
return false, err
}
if duplicate {
return false, nil
}
if opts.RequireExistingSessions {
if err := requireRecallImportSessionWithQueryer(ctx, tx, item); err != nil {
return false, err
}
if err := requireRecallImportEvidenceWithQueryer(ctx, tx, recall); err != nil {
return false, err
}
if err := bindVerifiedRecallImportEvidenceWithQueryer(
ctx, tx, &recall,
); err != nil {
return false, err
}
}
if !opts.RequireExistingSessions {
if err := rejectUnverifiedRecallImportTrustedSupersession(
ctx, tx, recall,
); err != nil {
return false, err
}
}
if err := validateRecallImportSupersessionWithQueryer(
ctx, tx, recall,
); err != nil {
return false, err
}
if !opts.RequireExistingSessions {
recall.ProvenanceOK = false
if err := ensureRecallImportSessionTx(ctx, tx, item); err != nil {
return false, fmt.Errorf("preparing source session: %w", err)
}
}
if recall.SupersedesEntryID != "" {
if recall.SupersedesEntryID == recall.ID {
return false, fmt.Errorf(
"replacement entry id must differ from superseded entry id",
)
}
recall.SupersededByEntryID = ""
if err := supersedeRecallEntryTx(
ctx, tx, recall.SupersedesEntryID, recall,
); err != nil {
return false, err
}
} else if err := insertRecallEntryTx(tx, recall); err != nil {
return false, err
}
if err := tx.Commit(); err != nil {
return false, fmt.Errorf("commit recall import: %w", err)
}
return true, nil
}
func hostControlledRecallImportField(
fields map[string]json.RawMessage,
) (string, bool, error) {
hostControlledFields := []string{
"review_state",
"message_start_source_uuid",
"message_end_source_uuid",
"content_digest",
}
for _, field := range hostControlledFields {
if _, ok := fields[field]; ok {
return field, true, nil
}
}
rawEvidence, ok := fields["evidence"]
if !ok {
return "", false, nil
}
var evidenceFields map[string]json.RawMessage
if err := json.Unmarshal(rawEvidence, &evidenceFields); err != nil {
return "", false, fmt.Errorf("invalid evidence JSON: %w", err)
}
for _, field := range hostControlledFields[1:] {
if _, ok := evidenceFields[field]; ok {
return "evidence." + field, true, nil
}
}
return "", false, nil
}
func normalizeProbeAcceptedRecallEntry(m probeAcceptedRecallEntry) probeAcceptedRecallEntry {
m.CandidateID = strings.TrimSpace(m.CandidateID)
m.RunID = strings.TrimSpace(m.RunID)
m.SessionID = strings.TrimSpace(m.SessionID)
m.EpisodeID = strings.TrimSpace(m.EpisodeID)
m.Type = strings.TrimSpace(m.Type)
m.Scope = strings.TrimSpace(m.Scope)
m.Title = strings.TrimSpace(m.Title)
m.Body = strings.TrimSpace(m.Body)
m.Trigger = strings.TrimSpace(m.Trigger)
m.Uncertainty = strings.TrimSpace(m.Uncertainty)
m.Project = strings.TrimSpace(m.Project)
m.CWD = strings.TrimSpace(m.CWD)
m.GitBranch = strings.TrimSpace(m.GitBranch)
m.Agent = strings.TrimSpace(m.Agent)
m.ExtractorMethod = strings.TrimSpace(m.ExtractorMethod)
m.Model = strings.TrimSpace(m.Model)
m.Label = strings.TrimSpace(m.Label)
m.SupersedesEntryID = strings.TrimSpace(m.SupersedesEntryID)
m.Evidence.ToolUseIDs = normalizeProbeToolUseIDs(m.Evidence.ToolUseIDs)
return m
}
func normalizeProbeToolUseIDs(ids []string) []string {
if len(ids) == 0 {
return nil
}
out := make([]string, 0, len(ids))
seen := make(map[string]struct{}, len(ids))
for _, id := range ids {
id = strings.TrimSpace(id)
if id == "" {
continue
}
if _, ok := seen[id]; ok {
continue
}
seen[id] = struct{}{}
out = append(out, id)
}
return out
}
func requireRecallImportSessionWithQueryer(
ctx context.Context,
queryer recallImportQueryer,
m probeAcceptedRecallEntry,
) error {
var exists bool
if err := queryer.QueryRowContext(ctx, `
SELECT EXISTS (
SELECT 1 FROM sessions
WHERE id = ? AND deleted_at IS NULL
)
`, m.SessionID).Scan(&exists); err != nil {
return fmt.Errorf("checking source session %s: %w", m.SessionID, err)
}
if !exists {
return fmt.Errorf("source session %s not found", m.SessionID)
}
return nil
}
func requireRecallImportEvidenceWithQueryer(
ctx context.Context,
queryer recallImportQueryer,
recall RecallEntry,
) error {
if len(recall.Evidence) == 0 {
return fmt.Errorf("missing recall evidence")
}
rangesChecked := map[string]struct{}{}
toolUsesChecked := map[string]struct{}{}
for _, evidence := range recall.Evidence {
rangeKey := fmt.Sprintf(
"%s:%d-%d",
evidence.SessionID,
evidence.MessageStartOrdinal,
evidence.MessageEndOrdinal,
)
if _, ok := rangesChecked[rangeKey]; !ok {
if err := requireRecallEvidenceRangeWithQueryer(
ctx, queryer, evidence,
); err != nil {
return err
}
rangesChecked[rangeKey] = struct{}{}
}
toolUseID := strings.TrimSpace(evidence.ToolUseID)
if toolUseID == "" {
continue
}
toolKey := rangeKey + ":" + toolUseID
if _, ok := toolUsesChecked[toolKey]; ok {
continue
}
if err := requireRecallEvidenceToolUseWithQueryer(
ctx, queryer, evidence,
); err != nil {
return err
}
toolUsesChecked[toolKey] = struct{}{}
}
return nil
}
func bindVerifiedRecallImportEvidenceWithQueryer(
ctx context.Context,
queryer recallImportQueryer,
recall *RecallEntry,
) error {
if len(recall.Evidence) == 0 {
return fmt.Errorf("missing recall evidence")
}
first := recall.Evidence[0]
toolUseIDs := make([]string, 0, len(recall.Evidence))
for _, evidence := range recall.Evidence {
if evidence.SessionID != first.SessionID ||
evidence.MessageStartOrdinal != first.MessageStartOrdinal ||
evidence.MessageEndOrdinal != first.MessageEndOrdinal {
return fmt.Errorf("recall evidence spans multiple windows")
}
if evidence.ToolUseID != "" {
toolUseIDs = append(toolUseIDs, evidence.ToolUseID)
}
}
window, err := buildRecallEvidenceWindow(
ctx,
queryer,
first.SessionID,
first.MessageStartOrdinal,
first.MessageEndOrdinal,
)
if err != nil {
return err
}
metadata, err := window.BindSelection(RecallEvidenceSelection{
MessageStartOrdinal: first.MessageStartOrdinal,
MessageEndOrdinal: first.MessageEndOrdinal,
ToolUseIDs: toolUseIDs,
})
if err != nil {
return err
}
for i := range recall.Evidence {
recall.Evidence[i].MessageStartSourceUUID =
metadata.MessageStartSourceUUID
recall.Evidence[i].MessageEndSourceUUID =
metadata.MessageEndSourceUUID
recall.Evidence[i].ContentDigest = metadata.ContentDigest
}
return nil
}
func requireRecallEvidenceRangeWithQueryer(
ctx context.Context,
queryer recallImportQueryer,
evidence RecallEvidence,
) error {
want := evidence.MessageEndOrdinal - evidence.MessageStartOrdinal + 1
var got int
err := queryer.QueryRowContext(ctx, `
SELECT COUNT(*)
FROM messages
WHERE session_id = ?
AND ordinal BETWEEN ? AND ?`,
evidence.SessionID,
evidence.MessageStartOrdinal,
evidence.MessageEndOrdinal,
).Scan(&got)
if err != nil {
return fmt.Errorf("checking source evidence: %w", err)
}
if got != want {
return fmt.Errorf(
"source evidence %s:%d-%d not found",
evidence.SessionID,
evidence.MessageStartOrdinal,
evidence.MessageEndOrdinal,
)
}
return nil
}
func requireRecallEvidenceToolUseWithQueryer(
ctx context.Context,
queryer recallImportQueryer,
evidence RecallEvidence,
) error {
var got int
err := queryer.QueryRowContext(ctx, `
SELECT COUNT(*)
FROM tool_calls tc
JOIN messages m ON m.id = tc.message_id
WHERE tc.session_id = ?
AND tc.tool_use_id = ?
AND m.ordinal BETWEEN ? AND ?`,
evidence.SessionID,
evidence.ToolUseID,
evidence.MessageStartOrdinal,
evidence.MessageEndOrdinal,
).Scan(&got)
if err != nil {
return fmt.Errorf("checking source tool use: %w", err)
}
if got == 0 {
return fmt.Errorf(
"source tool use %s not found in %s:%d-%d",
evidence.ToolUseID,
evidence.SessionID,
evidence.MessageStartOrdinal,
evidence.MessageEndOrdinal,
)
}
return nil
}
func recallImportPlaceholderSession(m probeAcceptedRecallEntry) Session {
// Insert the placeholder only when the session is absent. A plain upsert
// would clobber a real session with placeholder metadata.
now := time.Now().UTC().Format(time.RFC3339Nano)
firstMessage := "Recall import placeholder for " + m.SessionID
displayName := firstMessage
return Session{
ID: m.SessionID,
Project: m.Project,
Machine: "recall-import",
Agent: m.Agent,
FirstMessage: &firstMessage,
DisplayName: &displayName,
StartedAt: &now,
EndedAt: &now,
MessageCount: 0,
UserMessageCount: 0,
Outcome: "unknown",
OutcomeConfidence: "low",
Cwd: m.CWD,
GitBranch: m.GitBranch,
SourceVersion: "recall-import-placeholder",
}
}
func ensureRecallImportSessionTx(
ctx context.Context,
tx *sql.Tx,
m probeAcceptedRecallEntry,
) error {
session := recallImportPlaceholderSession(m)
if err := validateRecallImportPlaceholderSessionStateWithQueryer(
ctx, tx, session.ID,
); err != nil {
return err
}
if _, err := tx.ExecContext(
ctx, insertSessionIfAbsentSQL, upsertSessionArgs(session)...,
); err != nil {
return fmt.Errorf("inserting session %s if absent: %w", session.ID, err)
}
return nil
}
func validateRecallImportPlaceholderSessionStateWithQueryer(
ctx context.Context,
queryer recallImportQueryer,
sessionID string,
) error {
var excluded bool
if err := queryer.QueryRowContext(ctx, `
SELECT EXISTS (SELECT 1 FROM excluded_sessions WHERE id = ?)
`, sessionID).Scan(&excluded); err != nil {
return fmt.Errorf("checking excluded session %s: %w", sessionID, err)
}
if excluded {
return ErrSessionExcluded
}
var trashed bool
if err := queryer.QueryRowContext(ctx, `
SELECT EXISTS (
SELECT 1 FROM sessions
WHERE id = ? AND deleted_at IS NOT NULL
)
`, sessionID).Scan(&trashed); err != nil {
return fmt.Errorf("checking trashed session %s: %w", sessionID, err)
}
if trashed {
return ErrSessionTrashed
}
return nil
}
func probeRecallEntrySkipReason(m probeAcceptedRecallEntry) string {
if !m.Transferable {
return "not_transferable"
}
if !m.ProvenanceOK {
return "provenance_not_ok"
}
switch m.Label {
case "correct", "useful-but-uncertain", "genuine-tradeoff":
return ""
default:
return "label_not_keeper"
}
}
func probeRecallImportItem(m probeAcceptedRecallEntry, reason string) RecallImportItem {
return RecallImportItem{
CandidateID: m.CandidateID,
Title: m.Title,
SourceSessionID: m.SessionID,
SupersedesEntryID: m.SupersedesEntryID,
Label: m.Label,
Reason: reason,
}
}
func probeRecallEntryToDB(m probeAcceptedRecallEntry) (RecallEntry, error) {
if m.CandidateID == "" {
return RecallEntry{}, fmt.Errorf("missing candidate_id")
}
if m.SessionID == "" {
return RecallEntry{}, fmt.Errorf("missing session_id")
}
if err := validateImportedRecallEntryIdentities(m); err != nil {
return RecallEntry{}, err
}
if m.Title == "" || m.Body == "" {
return RecallEntry{}, fmt.Errorf("missing title or body")
}
if !validImportedRecallEntryType(m.Type) {
return RecallEntry{}, fmt.Errorf("invalid recall type %q", m.Type)
}
if !validImportedRecallEntryScope(m.Scope) {
return RecallEntry{}, fmt.Errorf("invalid recall scope %q", m.Scope)
}
if !validImportedConfidence(m.Confidence) {
return RecallEntry{}, fmt.Errorf(
"invalid confidence %g; must be between 0 and 1",
*m.Confidence,
)
}
if m.Evidence.OrdinalStart == nil || m.Evidence.OrdinalEnd == nil {
return RecallEntry{}, fmt.Errorf("missing evidence ordinal range")
}
if *m.Evidence.OrdinalStart < 0 ||
*m.Evidence.OrdinalEnd < *m.Evidence.OrdinalStart {
return RecallEntry{}, fmt.Errorf("invalid evidence ordinal range")
}
evidence := probeEvidenceToDB(m.CandidateID, m.SessionID, m.Evidence)
return RecallEntry{
ID: m.CandidateID,
Type: m.Type,
Scope: m.Scope,
Status: "accepted",
ReviewState: corerecall.ReviewStateHumanReviewed,
Title: m.Title,
Body: m.Body,
Trigger: m.Trigger,
Confidence: m.Confidence,
Uncertainty: m.Uncertainty,
Project: m.Project,
CWD: m.CWD,
GitBranch: m.GitBranch,
Agent: m.Agent,
SourceSessionID: m.SessionID,
SourceEpisodeID: m.EpisodeID,
SourceRunID: m.RunID,
ExtractorMethod: m.ExtractorMethod,
Model: m.Model,
SupersedesEntryID: strings.TrimSpace(m.SupersedesEntryID),
Transferable: true,
ProvenanceOK: true,
Evidence: evidence,
}, nil
}
func validateImportedRecallEntryIdentities(m probeAcceptedRecallEntry) error {
for _, field := range []struct {
name string
value string
}{
{name: "candidate_id", value: m.CandidateID},
{name: "session_id", value: m.SessionID},
{name: "run_id", value: m.RunID},
{name: "episode_id", value: m.EpisodeID},
{name: "supersedes_entry_id", value: m.SupersedesEntryID},
} {
if containsImportedControlCharacter(field.value) {
return fmt.Errorf(
"%s must not contain control characters",
field.name,
)
}
}
if slices.ContainsFunc(m.Evidence.ToolUseIDs, containsImportedControlCharacter) {
return fmt.Errorf(
"tool_use_id must not contain control characters",
)
}
return nil
}
func containsImportedControlCharacter(value string) bool {
for _, r := range value {
if unicode.IsControl(r) {
return true
}
}
return false
}
func validImportedRecallEntryType(value string) bool {
switch value {
case corerecall.TypeFact,
corerecall.TypeDecision,
corerecall.TypeProcedure,
corerecall.TypeDebuggingMethod,
corerecall.TypeWarning,
corerecall.TypePreference,
corerecall.TypeOpenQuestion:
return true
default:
return false
}
}
func validImportedRecallEntryScope(value string) bool {
switch value {
case corerecall.ScopeGlobal,
corerecall.ScopeProject,
corerecall.ScopeRepository,
corerecall.ScopeBranch,
corerecall.ScopeFile,
corerecall.ScopeTool,
corerecall.ScopeAgent:
return true
default:
return false
}
}
func validImportedConfidence(value *float64) bool {
if value == nil {
return true
}
return *value >= 0 && *value <= 1
}
func probeEvidenceToDB(
recallID, sessionID string, e probeRecallEvidence,
) []RecallEvidence {
if len(e.ToolUseIDs) == 0 {
return []RecallEvidence{
probeEvidenceItem(recallID, sessionID, e, ""),
}
}
items := make([]RecallEvidence, 0, len(e.ToolUseIDs))
for _, toolUseID := range e.ToolUseIDs {
item := probeEvidenceItem(recallID, sessionID, e, toolUseID)
if len(items) > 0 {
item.Snippet = ""
}
items = append(items, item)
}
return items
}
func probeEvidenceItem(
recallID, sessionID string, e probeRecallEvidence, toolUseID string,
) RecallEvidence {
return RecallEvidence{
EntryID: recallID,
SessionID: sessionID,
MessageStartOrdinal: *e.OrdinalStart,
MessageEndOrdinal: *e.OrdinalEnd,
ToolUseID: toolUseID,
Snippet: strings.Join(e.Snippets, "\n"),
}
}