| 586 | } |
| 587 | |
| 588 | func (e *forkedMemoryExtractor) Extract( |
| 589 | ctx context.Context, |
| 590 | turn memcontract.TurnRecord, |
| 591 | ) ([]memcontract.Candidate, error) { |
| 592 | if e == nil || e.sessions == nil { |
| 593 | return nil, errors.New("daemon: memory extractor sessions are not configured") |
| 594 | } |
| 595 | runCtx := context.WithoutCancel(ctx) |
| 596 | if e.deadline > 0 { |
| 597 | var cancel context.CancelFunc |
| 598 | runCtx, cancel = context.WithTimeout(runCtx, e.deadline) |
| 599 | defer cancel() |
| 600 | } |
| 601 | prompt, err := renderMemoryExtractorPrompt(turn) |
| 602 | if err != nil { |
| 603 | return nil, err |
| 604 | } |
| 605 | child, err := e.sessions.Spawn(runCtx, session.SpawnOpts{ |
| 606 | ParentSessionID: turn.SessionID, |
| 607 | AgentName: firstNonEmptyString(turn.AgentID, e.defaultAgent), |
| 608 | Model: strings.TrimSpace(e.model), |
| 609 | Name: "Memory extractor", |
| 610 | PromptOverlay: memoryExtractorOverlay(), |
| 611 | SpawnRole: session.SpawnRoleMemoryExtractor, |
| 612 | TTL: e.extractorTTL(), |
| 613 | AllowStoppedParent: true, |
| 614 | }) |
| 615 | if err != nil { |
| 616 | return nil, fmt.Errorf("daemon: spawn memory extractor session: %w", err) |
| 617 | } |
| 618 | defer e.stopChild(ctx, child.ID) |
| 619 | |
| 620 | events, err := e.sessions.PromptSynthetic(runCtx, child.ID, session.SyntheticPromptOpts{ |
| 621 | Message: prompt, |
| 622 | Metadata: acp.PromptSyntheticMeta{ |
| 623 | TaskID: memoryExtractorSyntheticTaskID, |
| 624 | Reason: "memory_extractor", |
| 625 | Summary: "extract durable Memory v2 candidates", |
| 626 | }, |
| 627 | }) |
| 628 | if err != nil { |
| 629 | return nil, fmt.Errorf("daemon: prompt memory extractor session: %w", err) |
| 630 | } |
| 631 | output, err := collectMemoryExtractorOutput(runCtx, events) |
| 632 | if err != nil { |
| 633 | return nil, err |
| 634 | } |
| 635 | candidates, err := parseMemoryExtractorCandidates(output, turn, e.workspaceRoot(turn.SessionID), e.nowUTC()) |
| 636 | if err != nil { |
| 637 | return nil, err |
| 638 | } |
| 639 | return candidates, nil |
| 640 | } |
| 641 | |
| 642 | func (e *forkedMemoryExtractor) Drain(context.Context) error { |
| 643 | return nil |