Class: Pikuri::Thunderbird::ContactSearch
- Inherits:
-
Pikuri::Tool
- Object
- Pikuri::Tool
- Pikuri::Thunderbird::ContactSearch
- Defined in:
- lib/pikuri/thunderbird/contact_search.rb
Overview
The thunderbird_contact_search tool — resolve a person's name (or a
partial address) to the email address(es) the user has actually
corresponded with, ranked by familiarity. Inbound-only (a pure read,
no egress leg), registered whenever Gloda is present — like mail
search, and independently useful ("what's Jon's address?").
Its reason to exist is MailCompose: the user says "email Jon Snow a summary," the model has a name and compose needs an address. Rather than invent one (a mis-send / exfil risk) or stop to ask, resolve it against the user's own correspondence graph via Gloda::Contacts#resolve. It returns ranked candidates and never auto-picks — a look-alike sender of received mail can surface, so the human reviewing the To field stays the last line (same posture as ComposeGuard).
Sharing: P_shared_locked — no state of its own, and the Gloda
backend it queries locks; see that class's == Sharing.
Constant Summary collapse
- DEFAULT_LIMIT =
Returns default / max candidates returned (a short disambiguation list, not a mailbox scan).
5- MAX_LIMIT =
15- DESCRIPTION =
Returns opencode-shape description.
<<~DESC Resolve a person's name (or a partial address) to their email address(es), drawn from the user's own Thunderbird correspondence history. Usage: - Give a name ("Jon Snow") or a fragment ("jon", "acme.com") to find who the user has actually mailed or received mail from. - Returns ranked candidates as Name <address> with a familiarity signal — addresses the user has sent mail to rank highest — and never picks one for you. - Use it to fill a recipient before drafting mail, then confirm the address with the user: a look-alike sender can appear in received mail, so resolution alone is not proof. - Reads Thunderbird's own local index only; it never connects to any server. DESC
Class Method Summary collapse
-
.run_search(backend:, query:, limit:) ⇒ String
Formatted ranked candidates or a no-match line.
Instance Method Summary collapse
- #initialize(backend:) ⇒ ContactSearch constructor
Constructor Details
#initialize(backend:) ⇒ ContactSearch
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/pikuri/thunderbird/contact_search.rb', line 40 def initialize(backend:) @backend = backend super( name: 'thunderbird_contact_search', description: DESCRIPTION, parameters: Parameters.build { |p| p.required_string :query, 'A name or partial address to resolve, e.g. "Jon Snow".' p.optional_integer :limit, "Max candidates (default #{DEFAULT_LIMIT}, max #{MAX_LIMIT}), e.g. 5." }, execute: lambda { |query:, limit: DEFAULT_LIMIT| ContactSearch.run_search(backend: @backend, query:, limit:) }, trifecta_legs: Pikuri::Thunderbird::INBOUND_LEGS ) end |
Class Method Details
.run_search(backend:, query:, limit:) ⇒ String
Returns formatted ranked candidates or a no-match line.
57 58 59 60 61 62 63 64 |
# File 'lib/pikuri/thunderbird/contact_search.rb', line 57 def self.run_search(backend:, query:, limit:) limit = limit.to_i.clamp(1, MAX_LIMIT) candidates = backend.resolve(query:, limit:) return "No contacts found matching #{query.inspect}." if candidates.empty? header = "#{candidates.size} contact#{candidates.size == 1 ? '' : 's'} (best first):" [header, *candidates.map { |c| render(c) }].join("\n\n") end |