UNPKG

@phren/cli

Version:

Knowledge layer for AI agents - CLI, MCP server, and data layer

144 lines (143 loc) • 6.54 kB
export declare const NOW_START = "<!-- phren:now:start -->"; export declare const NOW_END = "<!-- phren:now:end -->"; export declare const KNOWS_START = "<!-- phren:knows:start -->"; export declare const KNOWS_END = "<!-- phren:knows:end -->"; /** Bullets a topic file may hold before the oldest sections move to <topic>.older.md. */ export declare const TOPIC_SPLIT_AT = 400; export interface ArchivedBullet { date: string; tag: string; text: string; } export interface TopicDigest { slug: string; file: string; bullets: number; tags: Record<string, number>; first: string; last: string; mentioned: string[]; headlines: string[]; } /** Every "- " bullet under an "## Archived <date>" heading (or before any heading, for legacy files). */ export declare function parseTopicBullets(content: string): ArchivedBullet[]; /** Names the bullets keep coming back to: backticked identifiers and CamelCase words. ALLCAPS is emphasis, not a name. */ export declare function mostMentioned(bullets: ArchivedBullet[], limit?: number): string[]; export declare function digestTopic(slug: string, file: string, bullets: ArchivedBullet[]): TopicDigest; /** The paragraph that can always be written, no model required. */ export declare function structuralNow(d: TopicDigest): string; /** * Identifiers a paragraph names that none of the bullets do. A small local * model asked to summarise engineering notes will happily invent the stack * ("built on argparse" for a TypeScript project); a summary that adds facts * is worse than no summary, so any invented identifier fails the paragraph. */ export declare function inventedIdentifiers(prose: string, bullets: ArchivedBullet[]): string[]; /** * A prose paragraph over the newest bullets, when a model is configured; "" * otherwise, and "" when the paragraph names things the bullets do not. */ export declare function proseNow(d: TopicDigest, bullets: ArchivedBullet[], signal?: AbortSignal): Promise<string>; /** Fingerprint of everything in a topic file except its own Now block. */ export declare function contentFingerprint(content: string, start: string, end: string): string; /** * Where a marked block sits: from its first start marker to its last end * marker, and where its body begins (after the last start marker line). The * store syncs with git's union merge for markdown, so two computers that both * rewrote a block leave both start lines (and possibly both bodies); reading * past every marker and replacing the whole span heals the file on the next write. */ export declare function blockSpan(content: string, start: string, end: string): { start: number; end: number; pick: number; body: number; bodyEnd: number; } | null; /** The block rebuilt as one copy: the newest start marker, its body and the end marker. */ export declare function cleanBlock(content: string, start: string, end: string): { rest: string; block: string; } | null; /** A block's text without its markers and heading line ("## Now"). */ export declare function blockBody(content: string, start: string, end: string): string | null; /** Insert or replace a marked block. Topic files: before the first section; summary: at the end. */ export declare function upsertBlock(content: string, start: string, end: string, rendered: string, where: "top" | "bottom"): string; /** The stamp and fingerprint inside an existing block, so unchanged files are not rewritten. */ export declare function blockMeta(content: string, start: string): { at: string; hash: string | null; } | null; export interface SummarizeOptions { /** Ask a configured model for prose; falls back to structural when none answers. */ llm?: boolean; /** Re-summarize even when the file has not changed since the last block. */ force?: boolean; now?: () => Date; } export interface TopicResult { slug: string; file: string; bullets: number; updated: boolean; split?: string; now: string; } /** * Move whole "## Archived <date>" sections, oldest first, into <topic>.older.md * until the file is under the cap. Returns the older file's path if anything moved. */ export declare function splitTopicFile(filePath: string, maxBullets?: number): string | null; export declare function summarizeTopicFile(filePath: string, slug: string, opts?: SummarizeOptions): Promise<TopicResult>; export interface ProjectSummary { project: string; topics: TopicResult[]; summaryPath: string | null; summaryUpdated: boolean; } export declare function countActiveFindingsIn(findingsPath: string): number; export declare function countOpenTasks(tasksPath: string): number; /** What a project holds, counted the same way everywhere a count is shown: * live findings, team journal findings, everything archived into topic files * (older halves included), and open tasks. Every graph and project list reads * this so no surface shows only the slice it happened to draw. */ export interface ProjectMemoryCounts { active: number; journal: number; archived: number; findings: number; openTasks: number; } export declare function projectMemoryCounts(phrenPath: string, project: string): ProjectMemoryCounts; /** Summarize every topic file of a project and refresh the "What phren knows" block in summary.md. */ export declare function summarizeProject(phrenPath: string, project: string, opts?: SummarizeOptions): Promise<ProjectSummary>; export interface TopicFile { slug: string; file: string; } /** Every markdown file under a project's reference/topics, minus the .older.md spill-over files. */ export declare function listTopicFiles(phrenPath: string, project: string): TopicFile[]; /** The current Now text of a topic file and whether it is structural or prose. */ export declare function readNowBlock(content: string): { text: string; structural: boolean; } | null; /** * Store a paragraph an agent wrote for a topic, under the same rule a model's * paragraph gets: every identifier it names must appear in the bullets. * Returns the invented names on refusal. */ export declare function setTopicSummary(filePath: string, text: string, now?: () => Date): { ok: true; } | { ok: false; invented: string[]; } | { ok: false; error: string; }; /** The "What phren knows" block of a project, for the hook to inject; null when absent. */ export declare function readKnowsBlock(phrenPath: string, project: string): { path: string; text: string; } | null;