@essentialai/cogent-bridge
Version:
Cogent Bridge — cross-agent comms for Claude Code, OpenAI Codex and Slack. Codex users: install with `curl -fsSL https://cogent.tools/install.sh | sh`, then start with `cogent-codex` for real-time peer wake.
112 lines • 4.07 kB
TypeScript
import type { PersistedMailCredentials } from "../cloud/mail-credential-store.js";
/**
* Inbound-mail port (Cogent Mail M2.3). Symmetric to the outbound {@link MailSender}:
* the fetch tool depends on THIS interface, not on imapflow, so it is unit-testable with a
* fake IMAP session and the IMAP library is swappable + loaded lazily (off the cold-start
* path). Following RemoteDataSource / Dependency_Injection
* (typescript-master-vault/concepts/RemoteDataSource.md, Dependency_Injection.md).
*/
export interface MailSummary {
uid: number;
from: string;
subject: string;
date: string;
unread: boolean;
}
export interface SavedAttachment {
filename: string;
savedPath: string;
size: number;
}
export interface FetchedMail {
uid: number;
from: string;
subject: string;
date: string;
text: string;
attachments: SavedAttachment[];
}
export interface MailFetcher {
/** List messages (most recent first) as lightweight summaries — no bodies downloaded. */
list(opts?: {
unreadOnly?: boolean;
limit?: number;
}): Promise<MailSummary[]>;
/** Fetch one message by UID: text body + attachments saved to `downloadDir`. */
fetchOne(uid: number, downloadDir: string): Promise<FetchedMail>;
}
/** Raw envelope row as produced by the IMAP session (already parsed to plain data). */
export interface RawMessage {
uid: number;
from: string;
subject: string;
date: string;
unread: boolean;
}
/** Decoded message content as produced by the IMAP session (attachments in memory). */
export interface RawContent {
from: string;
subject: string;
date: string;
text: string;
attachments: {
filename: string;
content: Buffer;
}[];
}
/**
* The minimal IMAP surface the fetcher needs. Returning already-parsed plain data keeps the
* imapflow specifics behind {@link defaultImapSessionFactory}, so ImapflowMailFetcher's
* disk-saving + summary logic is unit-tested against a fake session.
*/
export interface ImapSession {
list(unreadOnly: boolean): Promise<RawMessage[]>;
fetch(uid: number): Promise<RawContent>;
close(): Promise<void>;
}
export type ImapSessionFactory = (creds: PersistedMailCredentials) => Promise<ImapSession>;
/** In-memory fetcher: a fixed inbox. The test double the tool drives. */
export declare class InMemoryMailFetcher implements MailFetcher {
private readonly inbox;
constructor(inbox?: (RawMessage & {
text: string;
attachments: {
filename: string;
content: Buffer;
}[];
})[]);
list(opts?: {
unreadOnly?: boolean;
limit?: number;
}): Promise<MailSummary[]>;
fetchOne(uid: number, downloadDir: string): Promise<FetchedMail>;
}
/**
* Real IMAP fetcher. The imapflow session is created LAZILY (dynamic import) so imapflow never
* loads on the cold-start path — only when the agent actually fetches mail. `sessionFactory` is
* the injection seam for tests (default connects a real imapflow session).
*/
export declare class ImapflowMailFetcher implements MailFetcher {
private readonly creds;
private readonly sessionFactory;
constructor(creds: PersistedMailCredentials, sessionFactory?: ImapSessionFactory);
list(opts?: {
unreadOnly?: boolean;
limit?: number;
}): Promise<MailSummary[]>;
fetchOne(uid: number, downloadDir: string): Promise<FetchedMail>;
}
/** A leaf MIME part reference extracted from an imapflow bodyStructure tree. */
export interface MimePartRef {
part: string;
type: string;
isText: boolean;
filename?: string;
}
/**
* Flatten an imapflow bodyStructure into its leaf parts. Attachment leaves carry a `filename`
* (from disposition or content-type params); text/plain leaves are marked `isText`. Multipart
* container nodes (those with `childNodes`) are recursed, not emitted.
*/
export declare function flattenBodyStructure(node: unknown, acc?: MimePartRef[]): MimePartRef[];
//# sourceMappingURL=mail-fetcher.d.ts.map