courtmitra / packages /ports /src /index.ts
Hetansh Waghela
module 4-8 done, bugs fixed
7aa8d9d
Raw
History Blame
9.54 kB
/**
* Ports = interfaces only (CLAUDE.md #1). Adapters implement these; apps wire
* them. NO framework/SDK imports allowed here (enforced by eslint boundary).
*/
import type {
AdapterCapability,
Channel,
ProofState,
LegalSupportLevel,
} from "@courtmitra/contracts";
/** Anything an adapter can do, plus what it can do *right now* in this env. */
export interface CapabilityAware {
capabilities(): AdapterCapability[];
}
// --- LLM ---------------------------------------------------------------------
/** Minimal schema carrier (a Zod schema satisfies this) — keeps ports SDK-free. */
export interface OutputSchema<T> {
parse(input: unknown): T;
}
export interface LlmStructuredRequest<T> {
/** Versioned prompt id from packages/prompts — never an inline prompt. */
promptId: string;
/** Variables interpolated into the prompt template. */
variables: Record<string, unknown>;
/** Schema the adapter validates the model output against (CLAUDE.md: never pass through). */
schema: OutputSchema<T>;
/** Optional images (data URLs / storage refs) for vision parsing. */
images?: string[];
model?: string;
temperature?: number;
}
export interface LlmStructuredResult<T> {
output: T;
raw: string;
model: string;
usage?: { inputTokens: number; outputTokens: number };
}
export interface LlmPort {
generateStructured<T>(req: LlmStructuredRequest<T>): Promise<LlmStructuredResult<T>>;
}
// --- Embedding ---------------------------------------------------------------
export interface EmbeddingPort {
embed(texts: string[]): Promise<number[][]>;
dimensions: number;
}
// --- Legal retrieval / verification -----------------------------------------
export interface LegalQuery {
missionId: string;
issueDomain: string;
query: string;
topK?: number;
}
export interface RetrievedLegalSource {
chunkId: string;
sourceId: string;
actName: string | null;
sectionNo: string | null;
heading: string | null;
text: string;
score: number;
}
export interface ClaimSupportCheck {
/** Unique mission identifier — required to persist legal_claim_verifications. */
missionId: string;
claim: string;
quoteSpans: string[];
chunkIds: string[];
}
export interface ClaimSupportResult {
supported: boolean;
supportLevel: LegalSupportLevel;
citedChunkIds: string[];
failureReason: string | null;
}
export interface LegalRetrievalPort {
retrieve(q: LegalQuery): Promise<RetrievedLegalSource[]>;
/** Verify = literal quote-span substring match against chunk.text (CLAUDE.md #4). */
verifyClaimSupport(i: ClaimSupportCheck): Promise<ClaimSupportResult>;
}
// --- Evidence parsing (Phase 1 = vision-LLM) --------------------------------
export interface EvidenceFile {
evidenceItemId: string;
storageKey: string;
mimeType: string;
}
export interface ParsedEvidence {
rawText: string;
entities: Record<string, unknown>;
dates: string[];
money: { amount: number; currency: string; original: string }[];
parties: string[];
confidence: number;
}
export interface EvidenceParserPort {
parse(file: EvidenceFile): Promise<ParsedEvidence>;
}
// --- ASR / Transcription (Phase 2 Module 2) --------------------------------
export interface AsrTranscribeRequest {
audioBytes: Uint8Array;
mimeType: string;
languageHint?: string;
}
export interface AsrTranscribeResult {
text: string;
language: string;
confidence: number;
durationMs: number;
}
export interface AsrPort {
transcribe(request: AsrTranscribeRequest): Promise<AsrTranscribeResult>;
}
// --- Translation (Phase 2 Module 3) ----------------------------------------
export interface TranslationDetectRequest {
text: string;
}
export interface TranslationDetectResult {
language: string;
confidence: number;
}
export interface TranslationTranslateRequest {
text: string;
sourceLang?: string;
targetLang: string;
}
export interface TranslationTranslateResult {
originalText: string;
translatedText: string;
sourceLang: string;
targetLang: string;
confidence: number;
model: string;
}
export interface TranslationPort {
detectLanguage(text: string): Promise<TranslationDetectResult>;
translate(request: TranslationTranslateRequest): Promise<TranslationTranslateResult>;
}
// --- Portal Assist (Phase 2 Module 5) -------------------------------------
export interface PortalAssistSessionState {
sessionId: string;
state: string;
portalUrl: string;
formFields: { selector: string; label: string; value: string | null; filled: boolean }[];
screenshotStorageKey: string | null;
receiptStorageKey: string | null;
errorMessage: string | null;
}
export interface PortalAssistPort {
init(): Promise<void>;
fillFields(sessionId: string, url: string, fields: FormField[]): Promise<void>;
captureScreenshot(sessionId: string): Promise<Uint8Array>;
waitForUserAction(state: string): Promise<void>;
captureScreenshotAfterSubmit(sessionId: string): Promise<{ bytes: Uint8Array; url: string }>;
close(): Promise<void>;
}
export interface FormField {
label: string;
value: string;
}
// --- Social Publishing (Phase 2 Module 7) ----------------------------------
export interface SocialPublishRequest {
text: string;
platform: string;
cardBytes?: Uint8Array;
cardMimeType?: string;
consentGrantId: string;
missionId: string;
actionId: string;
}
export interface SocialPublishResult {
published: boolean;
proofState: string;
externalPostId: string | null;
postUrl: string | null;
failureReason: string | null;
}
export interface SocialPublisherPort extends CapabilityAware {
publish(request: SocialPublishRequest): Promise<SocialPublishResult>;
}
// --- Case Lookup / eCourts (Phase 2 Module 8) -----------------------------
export interface CaseLookupRequest {
cnrNumber: string;
}
export interface CaseLookupResponse {
cnrNumber: string;
caseNumber: string | null;
courtName: string | null;
petitioner: string | null;
respondent: string | null;
caseStatus: string | null;
nextHearingDate: string | null;
lastOrderDate: string | null;
lastOrderSummary: string | null;
rawData: Record<string, unknown> | null;
}
export interface CaseLookupPort extends CapabilityAware {
lookup(request: CaseLookupRequest): Promise<CaseLookupResponse>;
}
// --- Channels ----------------------------------------------------------------
export interface ChannelMessage {
channel: Channel;
to: string;
body: string;
}
export interface InteractiveMessage extends ChannelMessage {
buttons: { id: string; label: string }[];
}
export interface ChannelSendResult {
providerMessageId: string | null;
proofState: ProofState;
}
export interface ChannelPort extends CapabilityAware {
sendMessage(m: ChannelMessage): Promise<ChannelSendResult>;
sendInteractive(m: InteractiveMessage): Promise<ChannelSendResult>;
}
// --- Submission (email / portal packet) -------------------------------------
export interface SubmissionRequest {
missionId: string;
actionId: string;
destination: string;
subject?: string;
body: string;
attachments: { id: string; storageKey: string; filename: string }[];
idempotencyKey: string;
}
export interface SubmissionResult {
proofState: ProofState;
externalReference: string | null;
proofRef: Record<string, unknown>;
}
export interface SubmissionPort extends CapabilityAware {
submit(r: SubmissionRequest): Promise<SubmissionResult>;
}
// --- Email (dedicated port, separate from generic SubmissionPort) -----------
export interface EmailSendRequest {
to: string;
subject: string;
body: string;
replyTo?: string;
/** Attachments as base64-encoded content (referenced by storage key). */
attachments?: { filename: string; storageKey: string; contentType?: string }[];
}
export interface EmailSendResult {
proofState: ProofState;
providerMessageId: string | null;
proofRef: Record<string, unknown>;
}
export interface EmailPort extends CapabilityAware {
send(req: EmailSendRequest): Promise<EmailSendResult>;
}
// --- Redaction ---------------------------------------------------------------
export type RedactionMode = "mask" | "remove" | "tag";
export interface RedactionSpan {
start: number;
end: number;
piiType: string;
replacement: string;
}
export interface RedactionPort {
detect(text: string): Promise<RedactionSpan[]> | RedactionSpan[];
redact(text: string, mode: RedactionMode): Promise<string> | string;
}
// --- Workflow / audit --------------------------------------------------------
export interface WorkflowEvent {
name: string;
data: Record<string, unknown>;
}
export interface WorkflowPort {
send(event: WorkflowEvent): Promise<void>;
sleepUntil(date: Date): Promise<void>;
}
export interface AuditEvent {
actorType: string;
actorId: string;
action: string;
resourceType: string;
resourceId: string;
before?: Record<string, unknown>;
after?: Record<string, unknown>;
}
export interface AuditPort {
append(e: AuditEvent): Promise<void>;
}
// --- Storage -----------------------------------------------------------------
export interface StoredObject {
storageKey: string;
sha256: string;
sizeBytes: number;
mimeType: string | null;
}
export interface StoragePort {
put(input: { key: string; bytes: Uint8Array; mimeType?: string }): Promise<StoredObject>;
getBytes(key: string): Promise<Uint8Array>;
/** Returns a URL the web app can fetch. In dev this may be a local served path. */
publicUrl(key: string): string;
}