d25d482dc2
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
275 lines
7.7 KiB
TypeScript
275 lines
7.7 KiB
TypeScript
import type {
|
|
QuartrAudio,
|
|
QuartrAudioDto,
|
|
QuartrCompany,
|
|
QuartrCompanyDto,
|
|
QuartrCompanyFilterParams,
|
|
QuartrDocument,
|
|
QuartrDocumentDto,
|
|
QuartrDocumentType,
|
|
QuartrDocumentTypeDto,
|
|
QuartrEvent,
|
|
QuartrEventDto,
|
|
QuartrEventType,
|
|
QuartrEventTypeDto,
|
|
QuartrExpandedEvent,
|
|
QuartrExpandedEventDto,
|
|
QuartrListDocumentsParams,
|
|
QuartrLiveEvent,
|
|
QuartrLiveEventDto,
|
|
QuartrPaginationParams,
|
|
QuartrSummarySource,
|
|
QuartrSummarySourceDto,
|
|
QuartrUpdatedRangeParams,
|
|
} from '@/tools/quartr/types'
|
|
|
|
export const QUARTR_API_BASE_URL = 'https://api.quartr.com/public/v3'
|
|
|
|
/**
|
|
* Normalizes a comma-separated list value by trimming whitespace around each
|
|
* entry, since the Quartr API expects lists without blank spaces.
|
|
*/
|
|
export function normalizeQuartrCommaList(
|
|
value: string | number | null | undefined
|
|
): string | undefined {
|
|
if (value == null || value === '') return undefined
|
|
const normalized = String(value)
|
|
.split(',')
|
|
.map((entry) => entry.trim())
|
|
.filter(Boolean)
|
|
.join(',')
|
|
return normalized || undefined
|
|
}
|
|
|
|
/**
|
|
* Interprets a boolean-ish tool param, accepting boolean true or the string
|
|
* "true" (agent tool configuration serializes switch values as strings).
|
|
*/
|
|
export function isQuartrToggleEnabled(value: boolean | string | null | undefined): boolean {
|
|
return value === true || value === 'true'
|
|
}
|
|
|
|
/**
|
|
* Builds a Quartr API URL, appending only query parameters that have a value.
|
|
*/
|
|
export function buildQuartrUrl(
|
|
path: string,
|
|
query?: Record<string, string | number | boolean | null | undefined>
|
|
): string {
|
|
const url = new URL(`${QUARTR_API_BASE_URL}${path}`)
|
|
if (query) {
|
|
for (const [key, value] of Object.entries(query)) {
|
|
if (value == null || value === '') continue
|
|
url.searchParams.set(key, String(value))
|
|
}
|
|
}
|
|
return url.toString()
|
|
}
|
|
|
|
/**
|
|
* Builds the query parameters shared by all Quartr list tools: company
|
|
* identifier filters, pagination, and updatedAt range filters.
|
|
*/
|
|
export function buildQuartrListQuery(
|
|
params: QuartrCompanyFilterParams & QuartrPaginationParams & QuartrUpdatedRangeParams
|
|
): Record<string, string | number | boolean | undefined> {
|
|
return {
|
|
tickers: normalizeQuartrCommaList(params.tickers),
|
|
isins: normalizeQuartrCommaList(params.isins),
|
|
ciks: normalizeQuartrCommaList(params.ciks),
|
|
countries: normalizeQuartrCommaList(params.countries),
|
|
exchanges: normalizeQuartrCommaList(params.exchanges),
|
|
limit: params.limit,
|
|
cursor: params.cursor,
|
|
direction: params.direction,
|
|
updatedAfter: params.updatedAfter,
|
|
updatedBefore: params.updatedBefore,
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Builds the query parameters shared by the documents, reports, slide decks,
|
|
* and transcripts list tools.
|
|
*/
|
|
export function buildQuartrDocumentListQuery(
|
|
params: QuartrListDocumentsParams
|
|
): Record<string, string | number | boolean | undefined> {
|
|
return {
|
|
...buildQuartrListQuery(params),
|
|
companyIds: normalizeQuartrCommaList(params.companyIds),
|
|
eventIds: normalizeQuartrCommaList(params.eventIds),
|
|
typeIds: normalizeQuartrCommaList(params.documentTypeIds),
|
|
documentGroupIds: normalizeQuartrCommaList(params.documentGroupIds),
|
|
startDate: params.startDate,
|
|
endDate: params.endDate,
|
|
expand: isQuartrToggleEnabled(params.expandEvent) ? 'event' : undefined,
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parses a Quartr API response, throwing a descriptive error for failures.
|
|
*/
|
|
export async function parseQuartrResponse<T>(response: Response, operation: string): Promise<T> {
|
|
const text = await response.text()
|
|
let data: unknown
|
|
try {
|
|
data = JSON.parse(text)
|
|
} catch {
|
|
data = undefined
|
|
}
|
|
|
|
if (!response.ok) {
|
|
const body = data as
|
|
| { message?: string | Array<string | { field?: string; message?: string }>; error?: string }
|
|
| undefined
|
|
const rawMessage = body?.message ?? body?.error ?? `HTTP ${response.status}`
|
|
const message = Array.isArray(rawMessage)
|
|
? rawMessage
|
|
.map((entry) => {
|
|
if (typeof entry === 'string') return entry
|
|
if (typeof entry?.message === 'string') {
|
|
return entry.field ? `${entry.field}: ${entry.message}` : entry.message
|
|
}
|
|
return JSON.stringify(entry)
|
|
})
|
|
.join('; ')
|
|
: rawMessage
|
|
throw new Error(`Quartr ${operation} failed (${response.status}): ${message}`)
|
|
}
|
|
|
|
if (data === undefined) {
|
|
throw new Error(`Quartr ${operation} returned an invalid JSON response`)
|
|
}
|
|
|
|
return data as T
|
|
}
|
|
|
|
export function mapQuartrCompany(dto: QuartrCompanyDto): QuartrCompany {
|
|
return {
|
|
id: dto.id,
|
|
name: dto.name,
|
|
displayName: dto.displayName ?? null,
|
|
country: dto.country,
|
|
tickers: dto.tickers ?? [],
|
|
isins: dto.isins ?? [],
|
|
cik: dto.cik ?? null,
|
|
openfigi: dto.openfigi ?? [],
|
|
backlinkUrl: dto.backlinkUrl,
|
|
createdAt: dto.createdAt,
|
|
updatedAt: dto.updatedAt,
|
|
}
|
|
}
|
|
|
|
export function mapQuartrEvent(dto: QuartrEventDto): QuartrEvent {
|
|
return {
|
|
id: dto.id,
|
|
companyId: dto.companyId,
|
|
title: dto.title,
|
|
date: dto.date,
|
|
typeId: dto.typeId,
|
|
fiscalYear: dto.fiscalYear ?? null,
|
|
fiscalPeriod: dto.fiscalPeriod ?? null,
|
|
language: dto.language,
|
|
backlinkUrl: dto.backlinkUrl,
|
|
createdAt: dto.createdAt,
|
|
updatedAt: dto.updatedAt,
|
|
}
|
|
}
|
|
|
|
export function mapQuartrExpandedEvent(
|
|
dto: QuartrExpandedEventDto | undefined
|
|
): QuartrExpandedEvent | null {
|
|
if (!dto) return null
|
|
return {
|
|
title: dto.title ?? null,
|
|
typeId: dto.typeId ?? null,
|
|
fiscalYear: dto.fiscalYear ?? null,
|
|
fiscalPeriod: dto.fiscalPeriod ?? null,
|
|
language: dto.language ?? null,
|
|
date: dto.date ?? null,
|
|
}
|
|
}
|
|
|
|
export function mapQuartrDocument(dto: QuartrDocumentDto): QuartrDocument {
|
|
return {
|
|
id: dto.id,
|
|
companyId: dto.companyId ?? null,
|
|
eventId: dto.eventId ?? null,
|
|
typeId: dto.typeId,
|
|
fileUrl: dto.fileUrl,
|
|
createdAt: dto.createdAt,
|
|
updatedAt: dto.updatedAt,
|
|
event: mapQuartrExpandedEvent(dto.event),
|
|
}
|
|
}
|
|
|
|
export function mapQuartrSummarySource(dto: QuartrSummarySourceDto): QuartrSummarySource {
|
|
return {
|
|
sourceId: dto.sourceId ?? null,
|
|
documentId: dto.documentId,
|
|
page: dto.page ?? null,
|
|
timestamp: dto.timestamp ?? null,
|
|
typeId: dto.typeId,
|
|
}
|
|
}
|
|
|
|
export function mapQuartrAudio(dto: QuartrAudioDto): QuartrAudio {
|
|
return {
|
|
id: dto.id,
|
|
companyId: dto.companyId,
|
|
eventId: dto.eventId,
|
|
fileUrl: dto.fileUrl ?? null,
|
|
streamUrl: dto.streamUrl ?? null,
|
|
qna: dto.qna ?? null,
|
|
audioMetadata: dto.audioMetadata
|
|
? {
|
|
size: dto.audioMetadata.size ?? null,
|
|
duration: dto.audioMetadata.duration ?? null,
|
|
encoding: dto.audioMetadata.encoding ?? null,
|
|
mimetype: dto.audioMetadata.mimetype ?? null,
|
|
}
|
|
: null,
|
|
createdAt: dto.createdAt,
|
|
updatedAt: dto.updatedAt,
|
|
event: mapQuartrExpandedEvent(dto.event),
|
|
}
|
|
}
|
|
|
|
export function mapQuartrLiveEvent(dto: QuartrLiveEventDto): QuartrLiveEvent {
|
|
return {
|
|
id: dto.id,
|
|
eventId: dto.eventId,
|
|
companyId: dto.companyId,
|
|
date: dto.date,
|
|
wentLiveAt: dto.wentLiveAt ?? null,
|
|
state: dto.state ?? null,
|
|
audio: dto.audio ?? null,
|
|
transcript: dto.transcript ?? null,
|
|
createdAt: dto.createdAt,
|
|
updatedAt: dto.updatedAt,
|
|
}
|
|
}
|
|
|
|
export function mapQuartrEventType(dto: QuartrEventTypeDto): QuartrEventType {
|
|
return {
|
|
id: dto.id,
|
|
name: dto.name ?? null,
|
|
parent: dto.parent ?? null,
|
|
createdAt: dto.createdAt,
|
|
updatedAt: dto.updatedAt,
|
|
}
|
|
}
|
|
|
|
export function mapQuartrDocumentType(dto: QuartrDocumentTypeDto): QuartrDocumentType {
|
|
return {
|
|
id: dto.id,
|
|
name: dto.name,
|
|
description: dto.description ?? null,
|
|
form: dto.form ?? null,
|
|
category: dto.category,
|
|
documentGroupId: dto.documentGroupId ?? null,
|
|
createdAt: dto.createdAt,
|
|
updatedAt: dto.updatedAt,
|
|
}
|
|
}
|