/** * Transport-agnostic type definitions shared by all `src/runtime-api/handlers/` * modules and the route layer that consumes them. * * No Fastify imports. No side-effects. */ import type { ExternalScannerIngestSignalItem, ExternalScannerIngestErrorCode } from "../../scanners/external-scanner-receiver.js"; import type { Signal } from "../../scanners/types.js"; /** * Per-item shape accepted by `POST /signals`. * * Mirrors {@link ExternalScannerIngestRequest} with `address` lifted to the * item level so a single request body can target multiple wallets. * * Only one of `data` (single-signal shortcut) or `signals[]` (batch within * one address+scanner) may be present — the handler enforces mutual exclusion * at runtime in addition to the TypeBox schema check. */ export interface SignalItem { /** Wallet address of the target runtime. Lowercased server-side. */ address: string; /** Configured scanner id. */ scanner: string; /** Asset for a single ingested signal. */ asset?: string; /** Direction for a single ingested signal. */ direction?: Signal["direction"]; /** Confidence score for a single ingested signal (0–1). */ score?: number; /** Signal classification override for a single ingested signal. */ signal_type?: string; /** * Producer-minted id of the scan that produced this signal. Absent when the * producer sends none — the ingest never mints one. */ tick_id?: string; /** * Single ingest payload for signal-producing or context-producing scanners. * Mutually exclusive with `signals[]`. */ data?: Record; /** * Batch signal payloads for signal-producing external scanners. * Mutually exclusive with `data`. * Prefer this over multiple top-level items for the same address+scanner * to avoid the per-(address, scanner) ingest lock. */ signals?: ExternalScannerIngestSignalItem[]; } /** * Per-item result returned by {@link ingestSignalsHandler}. * * INTERNAL handler shape — kept flat so the gateway shim * (`senpi.ingestExternalScannerData` in `src/plugin.ts`) can read fields * directly without a transform. The HTTP route layer * (`routes/signals.ts`) reshapes this into the senpi-stack wire format * `{ success, address, scanner, data | error }` before sending on the wire. * * Discriminator is `success` (matching MCP and the rest of the runtime-api * surface). * * Error codes reuse the existing * {@link ExternalScannerIngestErrorCode} taxonomy: * `INVALID_REQUEST | NOT_FOUND | UNAVAILABLE`. No `INTERNAL` code is added — * unexpected throws map to `UNAVAILABLE`. */ export type SignalResult = { success: true; /** Lowercased wallet address. */ address: string; /** Configured scanner id. */ scanner: string; /** Unix epoch ms timestamp from the ingest result. */ timestamp: number; /** Number of committed signals; `0` for context-only ingests. */ signalCount: number; /** Whether retained context was updated. */ contextUpdated: boolean; } | { success: false; /** Lowercased wallet address. */ address: string; /** Configured scanner id. */ scanner: string; /** Machine-readable failure code. */ code: ExternalScannerIngestErrorCode; /** Human-readable failure detail. */ message: string; }; //# sourceMappingURL=types.d.ts.map