Research Agents: Lets you define research agents that chat and answer with citations from SEC filings, your documents, and the web, via Jaspers' research-store service.
| 1 | import type { BackendContext } from '@jaspers-ai/sdk' |
| 2 | import type { Reads } from './sec.ts' |
| 3 | |
| 4 | // The research store (JaspersAI/research-store), reached as the plugin's connection agents/research: |
| 5 | // SEC filings for everyone, the account's own documents, Vertex AI's embeddings and ranking, and SEC |
| 6 | // EDGAR. The Terminal signs in to it as the Jaspers account. Every call goes through here, and a |
| 7 | // refusal comes back as the error the store said. |
| 8 | |
| 9 | export const SERVER = 'agents/research' |
| 10 | |
| 11 | /** A passage a search answered, as the store says it. */ |
| 12 | export interface Hit { |
| 13 | id: string |
| 14 | doc: string |
| 15 | /** Where it is from, in one line: `FLWS 10-K FY2024 · Item 1A Risk Factors · filed 2024-09-06`. */ |
| 16 | label: string |
| 17 | section: string |
| 18 | /** The reranker's relevance, 0 to 1, already over the store's floor. */ |
| 19 | score: number |
| 20 | url: string | null |
| 21 | text: string |
| 22 | } |
| 23 | |
| 24 | /** An ingest job: a company's kinds of filing and years being read into the store, for everyone. */ |
| 25 | export interface JobStatus { |
| 26 | id: number |
| 27 | ticker: string | null |
| 28 | state: 'queued' | 'listing' | 'reading' | 'done' | 'failed' | 'unknown' |
| 29 | total: number |
| 30 | done: number |
| 31 | failed: number |
| 32 | error: string | null |
| 33 | } |
| 34 | |
| 35 | export interface StoredCompany { |
| 36 | ticker: string |
| 37 | company: string | null |
| 38 | cik: number | null |
| 39 | filings: number |
| 40 | chunks: number |
| 41 | unembedded: number |
| 42 | /** When SEC last listed its filings, ISO; null before a listing was kept. */ |
| 43 | recently_as_of: string | null |
| 44 | /** The kinds of its filings ever asked for, by anyone, and their years. */ |
| 45 | reads: Reads |
| 46 | /** The job reading it now, if one is. */ |
| 47 | job: JobStatus | null |
| 48 | } |
| 49 | |
| 50 | export interface ServerStatus { |
| 51 | companies: StoredCompany[] |
| 52 | } |
| 53 | |
| 54 | /** One of the account's own documents, or a page its agents read. */ |
| 55 | export interface StoredDoc { |
| 56 | id: string |
| 57 | origin: 'upload' | 'web' |
| 58 | title: string |
| 59 | url: string | null |
| 60 | chars: number |
| 61 | /** ISO. */ |
| 62 | added_at: string |
| 63 | } |
| 64 | |
| 65 | export async function research<T>( |
| 66 | ctx: BackendContext, |
| 67 | tool: string, |
| 68 | args: Record<string, unknown>, |
| 69 | signal?: AbortSignal, |
| 70 | ): Promise<T> { |
| 71 | const { text, isError } = await ctx.tools.call(`${SERVER}/${tool}`, args, signal ? { signal } : undefined) |
| 72 | if (isError) throw new Error(text) |
| 73 | return JSON.parse(text) as T |
| 74 | } |
| 75 | |
| 76 | /** A document as its window opens it. */ |
| 77 | export interface Outline { |
| 78 | doc: { |
| 79 | id: string |
| 80 | origin: string |
| 81 | title: string | null |
| 82 | url: string | null |
| 83 | ticker: string | null |
| 84 | form: string | null |
| 85 | filing_date: string | null |
| 86 | } |
| 87 | sections: { seq: number; section: string; title: string; chars: number }[] |
| 88 | /** Where the cited chunk sits: its section and its span in that section's text. */ |
| 89 | chunk: { section: number; start: number; end: number; label: string } | null |
| 90 | } |
| 91 | |
| 92 | /** One section's whole text, read window by window. */ |
| 93 | export async function sectionText(ctx: BackendContext, doc: string, seq: number): Promise<string> { |
| 94 | let text = '' |
| 95 | let offset: number | null = 0 |
| 96 | while (offset !== null) { |
| 97 | const page: { text: string; next: number | null } = await research(ctx, 'document_section', { |
| 98 | doc_id: doc, |
| 99 | seq, |
| 100 | offset, |
| 101 | }) |
| 102 | text += page.text |
| 103 | offset = page.next |
| 104 | } |
| 105 | return text |
| 106 | } |