/** * Shared `docs.fetch` / `docs view --json` result builder — T13352. * * Previously both call sites hand-built the envelope: they re-encoded the * already-decoded UTF-8 body to base64, hard-coded `refCount: 0`, and * reported a storage path inside the legacy `.cleo/attachments` tree even * for docs whose bytes live in the blob manifest store (where the reported * path does not exist). * * This builder is the single source of truth for the fetch envelope: * * - **Text docs carry `content`** (decoded UTF-8) directly in the envelope — * no base64 round-trip for the overwhelmingly common markdown case. * Binary docs keep `bytesBase64` (≤ 1 MB inline cap). * - **`refCount` is the real value** from the read model * (`attachments.ref_count`; 0 for manifest-only blobs). * - **`path` always resolves against the blob store** * (`.cleo/blobs/blobs/`) — the canonical byte location since the * legacy `.cleo/attachments/sha256/` tree was retired as a read surface * (T13362). `fetchContent` reads the same location, so the reported path * always matches where the envelope's bytes came from. * - **mime/type come from the record**, never literals. * - **Recorded CRDT head conflicts surface** as `headConflict` (T13604): the * fetched content is the winning projection; losing edits survive in the * append-only version history. Absent on a clean head — the no-conflict * envelope is unchanged. * * @task T13352 (envelope shape) · T13604 (head-conflict surfacing) * @see ResolvedDoc — packages/core/src/docs/docs-read-model.ts * @see readDoc — sibling read API with the same utf-8-vs-base64 body rule */ import type { DocsFetchResult } from '@cleocode/contracts/operations/docs.js'; import type { ResolvedDoc } from './docs-read-model.js'; /** * Whether a MIME type denotes UTF-8 text. An absent MIME defaults to text: * docs blobs are overwhelmingly markdown, and the read model has already * decoded the body to a string by the time this predicate runs. * * @param mime - IANA MIME type, or null when unknown. * @returns True when the body should be surfaced as decoded `content`. * @task T13352 */ export declare function isTextMime(mime: string | null): boolean; /** * Resolve the on-disk storage path for a doc. * * The blob store (`.cleo/blobs/blobs/`) is the canonical byte * location for every doc — `DocsReadModel.fetchContent` reads bytes by * content address since the legacy `.cleo/attachments/sha256/` tree was * retired as a read surface (T13362), so the envelope reports that same * location regardless of which registry the doc's metadata resolved from. * Returns undefined for docs without a content hash. * * @param doc - The resolved doc record. * @param cleoDir - The project's `.cleo` directory. * @returns Absolute storage path, or undefined. * @task T13352 */ export declare function docsStoragePath(doc: ResolvedDoc, cleoDir: string): string | undefined; /** * Build the canonical `docs.fetch` result from a resolved doc and its * decoded body. Used by both the dispatch `docs.fetch` handler and the * `docs view --json` renderer, so the envelope shape can never drift * between the two again. * * @param opts.doc - The resolved doc record (metadata source of truth). * @param opts.content - The decoded UTF-8 body from `fetchContent`. * @param opts.projectRoot - Project root (resolves `.cleo` for the path). * @param opts.attachmentBackend - Current backend, echoed into the envelope. * @returns The typed {@link DocsFetchResult}. * @task T13352 */ export declare function buildDocsFetchResult(opts: { doc: ResolvedDoc; content: string; projectRoot: string; /** * Current backend label, echoed into the envelope. Typed as `string` * because core-internal `AttachmentBackend` (`'llmtxt'`) and the contracts * `AttachmentBackend` (`'legacy' | 'llmstxt-v2'`) are two divergent types * (pre-existing debt) — the historical fetch handler passed the internal * value through with a cast, and this builder preserves that behaviour. */ attachmentBackend?: string; /** * `D####` decisions linked to this doc (T13359) — looked up by the caller * (the dispatch handler owns the store access) and echoed here so the * `docs.fetch` envelope and `docs view --json` can never drift on the * field. Omitted when the doc has no live links. */ linkedDecisions?: string[]; }): Promise; /** * Resolve the conduit head version uid for a slug (T13674) — the version the * fetched body was projected from. Returns undefined for slug-less docs, * docs outside the conduit family, and any store read failure (the base * parameter stays opt-in; a degraded store must not break fetch). * * @param projectRoot - Project root. * @param slug - The doc's slug (`ResolvedDoc.slug`), or null. * @returns The head version uid, or undefined when not applicable. */ export declare function readDocHeadVersionUid(projectRoot: string, slug: string | null): Promise; //# sourceMappingURL=fetch-result.d.ts.map