import type { BackendContext } from '@jaspers-ai/sdk' import type { Reads } from './sec.ts' // The research store (JaspersAI/research-store), reached as the plugin's connection agents/research: // SEC filings for everyone, the account's own documents, Vertex AI's embeddings and ranking, and SEC // EDGAR. The Terminal signs in to it as the Jaspers account. Every call goes through here, and a // refusal comes back as the error the store said. export const SERVER = 'agents/research' /** A passage a search answered, as the store says it. */ export interface Hit { id: string doc: string /** Where it is from, in one line: `FLWS 10-K FY2024 · Item 1A Risk Factors · filed 2024-09-06`. */ label: string section: string /** The reranker's relevance, 0 to 1, already over the store's floor. */ score: number url: string | null text: string } /** An ingest job: a company's kinds of filing and years being read into the store, for everyone. */ export interface JobStatus { id: number ticker: string | null state: 'queued' | 'listing' | 'reading' | 'done' | 'failed' | 'unknown' total: number done: number failed: number error: string | null } export interface StoredCompany { ticker: string company: string | null cik: number | null filings: number chunks: number unembedded: number /** When SEC last listed its filings, ISO; null before a listing was kept. */ recently_as_of: string | null /** The kinds of its filings ever asked for, by anyone, and their years. */ reads: Reads /** The job reading it now, if one is. */ job: JobStatus | null } export interface ServerStatus { companies: StoredCompany[] } /** One of the account's own documents, or a page its agents read. */ export interface StoredDoc { id: string origin: 'upload' | 'web' title: string url: string | null chars: number /** ISO. */ added_at: string } export async function research( ctx: BackendContext, tool: string, args: Record, signal?: AbortSignal, ): Promise { const { text, isError } = await ctx.tools.call(`${SERVER}/${tool}`, args, signal ? { signal } : undefined) if (isError) throw new Error(text) return JSON.parse(text) as T } /** A document as its window opens it. */ export interface Outline { doc: { id: string origin: string title: string | null url: string | null ticker: string | null form: string | null filing_date: string | null } sections: { seq: number; section: string; title: string; chars: number }[] /** Where the cited chunk sits: its section and its span in that section's text. */ chunk: { section: number; start: number; end: number; label: string } | null } /** One section's whole text, read window by window. */ export async function sectionText(ctx: BackendContext, doc: string, seq: number): Promise { let text = '' let offset: number | null = 0 while (offset !== null) { const page: { text: string; next: number | null } = await research(ctx, 'document_section', { doc_id: doc, seq, offset, }) text += page.text offset = page.next } return text }