import type { BackendContext } from '@jaspers-ai/sdk' import { openTickers } from './chats.ts' import { publishDocs } from './doc-files.ts' import { errorText } from './errors.ts' import { SERVER } from './research.ts' import { companies } from './sec-files.ts' import { companyStatuses } from './sec.ts' // What the view shows of the research store, published while the plugin runs: whether the Terminal // is signed in to it (the connection is ready), and each company the open conversations touch, with // how far its reading and embedding are. Polled every two seconds while anything is moving, every // ten while nothing is. const BUSY_MS = 2_000 const IDLE_MS = 10_000 /** What the view gates on: the store is reached as the account. */ export interface Setup { signedIn: boolean /** The connection's status when it is not ready: needs-sign-in, error, starting. */ status: string error: string | null } let watching = false /** Whether the account's documents have been listed since the store last answered: once, at the first ready. */ let docsListed = false export function watchStatus(ctx: BackendContext): void { if (watching) return watching = true const tick = async (): Promise => { let busy = true try { busy = await publishStatus(ctx) } catch (err) { console.warn(`status: ${errorText(err, 'failed')}`) } setTimeout(() => void tick(), busy ? BUSY_MS : IDLE_MS) } void tick() } /** Publishes the setup and the companies; true while anything is still moving. */ export async function publishStatus(ctx: BackendContext): Promise { const [connection] = await ctx.tools.connections({ connections: [SERVER] }) const status = connection?.status ?? 'starting' if (status !== 'ready') { docsListed = false ctx.live.set('setup', { signedIn: false, status, error: null } satisfies Setup) ctx.live.set('sec', []) return status === 'starting' } ctx.live.set('setup', { signedIn: true, status, error: null } satisfies Setup) if (!docsListed) { // The account's documents live in the store: listed as soon as it answers, then after each change. await publishDocs(ctx) docsListed = true } const held = await companies(ctx, openTickers()) ctx.live.set('sec', companyStatuses(held)) return held.some( (c) => c.unembedded > 0 || (c.job !== null && ['queued', 'listing', 'reading'].includes(c.job.state)), ) }