/** * Custom tools: Company, filings, and earnings data access */ import { Type } from "typebox"; import { defineTool } from "@earendil-works/pi-coding-agent"; import type { Db } from "../db/database.js"; import { getCompany, getCompanyByTicker, resolveCompany, listFilings, getEarningsSchedule, listCatalysts, listRisks, listAlerts, } from "../db/queries.js"; export function createCompanyTools(db: Db) { const getCompanyInfo = defineTool({ name: "get_company_info", label: "Get Company Info", description: "Get company details including name, ticker, sector, price, thesis, and metadata. Accepts either a company ID or ticker symbol.", parameters: Type.Object({ companyIdOrTicker: Type.String({ description: "Company ID or ticker symbol (e.g. 'AAPL' or 'company-123')", }), }), execute: async (_, params) => { const company = resolveCompany(db, params.companyIdOrTicker); if (!company) { return { content: [ { type: "text" as const, text: `Company "${params.companyIdOrTicker}" not found.`, }, ], isError: true, details: {}, }; } return { content: [ { type: "text" as const, text: JSON.stringify(company, null, 2), }, ], details: {}, }; }, }); const getFilingsTool = defineTool({ name: "get_filings", label: "Get SEC Filings", description: "List SEC filings for a company (10-K, 10-Q, 8-K, DEF 14A, etc.). Returns form type, title, filed date, and key changes.", parameters: Type.Object({ companyIdOrTicker: Type.String({ description: "Company ID or ticker symbol", }), limit: Type.Optional( Type.Number({ description: "Max filings to return (default 20)", default: 20 }), ), since: Type.Optional( Type.String({ description: "Only filings after this date (YYYY-MM-DD)" }), ), }), execute: async (_, params) => { const company = resolveCompany(db, params.companyIdOrTicker); if (!company) { return { content: [{ type: "text" as const, text: `Company "${params.companyIdOrTicker}" not found.` }], isError: true, details: {}, }; } const filings = listFilings(db, company.id, params.since); const limited = filings.slice(0, params.limit ?? 20); return { content: [ { type: "text" as const, text: JSON.stringify( { companyId: company.id, ticker: company.ticker, count: limited.length, filings: limited }, null, 2, ), }, ], details: {}, }; }, }); const getEarningsTool = defineTool({ name: "get_earnings", label: "Get Earnings Schedule", description: "Get upcoming and historical earnings dates, actual vs expected revenue and EPS.", parameters: Type.Object({ companyIdOrTicker: Type.String({ description: "Company ID or ticker symbol", }), }), execute: async (_, params) => { const company = resolveCompany(db, params.companyIdOrTicker); if (!company) { return { content: [{ type: "text" as const, text: `Company "${params.companyIdOrTicker}" not found.` }], isError: true, details: {}, }; } const schedule = getEarningsSchedule(db, company.id); return { content: [ { type: "text" as const, text: JSON.stringify(schedule, null, 2), }, ], details: {}, }; }, }); const getCatalystsTool = defineTool({ name: "get_catalysts", label: "Get Catalysts", description: "List catalysts (upcoming events) for a company with impact assessment and thesis relevance.", parameters: Type.Object({ companyIdOrTicker: Type.String({ description: "Company ID or ticker symbol", }), }), execute: async (_, params) => { const company = resolveCompany(db, params.companyIdOrTicker); if (!company) { return { content: [{ type: "text" as const, text: `Company "${params.companyIdOrTicker}" not found.` }], isError: true, details: {}, }; } const catalysts = listCatalysts(db, company.id); return { content: [{ type: "text" as const, text: JSON.stringify(catalysts, null, 2) }], details: {}, }; }, }); const getRisksTool = defineTool({ name: "get_risks", label: "Get Risks", description: "List identified risks for a company, categorized by type with severity and likelihood.", parameters: Type.Object({ companyIdOrTicker: Type.String({ description: "Company ID or ticker symbol", }), }), execute: async (_, params) => { const company = resolveCompany(db, params.companyIdOrTicker); if (!company) { return { content: [{ type: "text" as const, text: `Company "${params.companyIdOrTicker}" not found.` }], isError: true, details: {}, }; } const risks = listRisks(db, company.id); return { content: [{ type: "text" as const, text: JSON.stringify(risks, null, 2) }], details: {}, }; }, }); const getAlertsTool = defineTool({ name: "get_alerts", label: "Get Alerts", description: "List recent alerts (filing, price move, earnings surprise, peer event) for a company.", parameters: Type.Object({ companyIdOrTicker: Type.Optional( Type.String({ description: "Company ID or ticker symbol (omit for all companies)" }), ), since: Type.Optional( Type.String({ description: "Only alerts after this timestamp" }), ), }), execute: async (_, params) => { const company = params.companyIdOrTicker ? resolveCompany(db, params.companyIdOrTicker) : undefined; const alerts = listAlerts(db, company?.id, params.since); return { content: [{ type: "text" as const, text: JSON.stringify(alerts, null, 2) }], details: {}, }; }, }); return [getCompanyInfo, getFilingsTool, getEarningsTool, getCatalystsTool, getRisksTool, getAlertsTool]; }