@ai-matrx/agents 0.21.26 → 0.21.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../sources/runtime/index.ts","../../../sources/runtime/delivery.ts","../../../sources/runtime/partsSearch.ts","../../../sources/runtime/interrupted.ts","../../../sources/runtime/fileSource.ts","../../../sources/runtime/tokens.ts","../../../sources/index.ts","../../../sources/runtime/state.ts","../../../sources/runtime/plan.ts","../../../sources/runtime/client.ts","../../../sources/runtime/controller.ts","../../../sources/runtime/intake.ts","../../../sources/runtime/recovery.ts"],"sourcesContent":["/**\n * `@ai-matrx/agents/sources/runtime` — the UI-free core of the one Source\n * input: pure TypeScript, no React, no framework, no store library.\n *\n * - state the source-list state machine (reducers + selectors),\n * persistence helpers, display names;\n * - controller the imperative face over an injected store, draft storage,\n * client and host config (`createSourceSetController`);\n * - intake every landing door, with every dependency injected\n * (`createSourceIntake`);\n * - recovery re-land what a reload cut off, continue after an\n * organization is chosen, follow stored files' Sources;\n * - plan THE review planner shared by the preview and the run;\n * - client the manifest / resolve / parts-search doors over an\n * injected transport;\n * - delivery, partsSearch, interrupted, fileSource — the pure rules.\n *\n * Screens bind it through `@ai-matrx/agents/sources/react`.\n * Contract of record: common-docs `projects/unified-source-input/DESIGN.md`.\n */\n\nexport * from \"./types\";\nexport * from \"./delivery\";\nexport * from \"./partsSearch\";\nexport * from \"./interrupted\";\nexport * from \"./fileSource\";\nexport * from \"./tokens\";\nexport * from \"./plan\";\nexport * from \"./client\";\nexport * from \"./state\";\nexport * from \"./controller\";\nexport * from \"./intake\";\nexport * from \"./recovery\";\n","/**\n * How the AI gets a Source — THE one source of truth for delivery.\n *\n * The frozen contract (`SourceRef.delivery`, `@ai-matrx/agents/sources`) has\n * two values and a default: absent / \"direct\" = the text is handed to the AI\n * with the request; \"context\" = nothing is sent up front and the AI opens the\n * Source while it works. The server (aidream `source_resolution.py`) reads\n * exactly this field and nothing else — `promote` / `exclude` are NOT read on\n * the Source path.\n *\n * Every screen that shows or changes delivery (the Source card, \"Review what\n * goes in\", the planner) reads it through `sourceDelivery` and says it with\n * `DELIVERY_WORDS`, so a card can never say one thing while the review and the\n * request say another (V1-A: the card said \"Nothing is copied in\" — chat's\n * attachment editor's wording — while the review said \"Include the text\" and\n * the request carried the text).\n */\n\nimport type { SourceDelivery, SourceRef, SourceRefOptions } from \"../index\";\n\nexport type { SourceDelivery };\n\n/** The delivery a pointer asks for — absent means the contract default, \"direct\". */\nexport function sourceDelivery(ref: Pick<SourceRef, \"delivery\"> | null | undefined): SourceDelivery {\n return ref?.delivery === \"context\" ? \"context\" : \"direct\";\n}\n\n/**\n * The patch that sets a delivery. \"direct\" is the default, so it clears the\n * field (the wire stays minimal, exactly as the review has always written it).\n * Looking a Source up sends no text, so parts and a size limit no longer apply.\n */\nexport function deliveryPatch(\n delivery: SourceDelivery,\n): Pick<SourceRefOptions, \"delivery\" | \"include_segments\" | \"max_chars\"> {\n return delivery === \"context\"\n ? { delivery: \"context\", include_segments: undefined, max_chars: undefined }\n : { delivery: undefined };\n}\n\nexport interface DeliveryWords {\n /** The choice's name on a control. */\n label: string;\n /** Two or three words under the control: what happens (copy law R9). */\n hint: string;\n /** The short phrase a summary line uses. */\n summary: string;\n}\n\nexport const DELIVERY_WORDS: Record<SourceDelivery, DeliveryWords> = {\n direct: {\n label: \"Include the text\",\n hint: \"Sent in full\",\n summary: \"Text included\",\n },\n context: {\n label: \"Let the AI look it up\",\n hint: \"Read as needed\",\n summary: \"Looked up when needed\",\n },\n};\n\n/** The choices, in the order every control shows them. */\nexport const DELIVERY_CHOICES: ReadonlyArray<{ value: SourceDelivery } & DeliveryWords> = (\n [\"direct\", \"context\"] as const\n).map((value) => ({ value, ...DELIVERY_WORDS[value] }));\n\n/**\n * What a HOST can use. Not every host can take every delivery: a generator\n * that needs the text up front (flashcards' segmented generator reads the\n * resolved text and nothing else) gets NOTHING from a Source set to \"look it\n * up\" — V2 verifier shots 06/26: the request went out with `delivery:\n * \"context\"` and the page said \"None of the Sources had any text\", which was\n * false. So a host declares the deliveries it can use (`SourceInputProps.\n * deliveries`); the card and the review offer only those, and a Source already\n * set to something the host cannot use is switched back — with a note on it.\n * Omitted = both (a host whose AI can open Sources while it works).\n */\nexport function allowedDeliveries(\n deliveries: readonly SourceDelivery[] | undefined,\n): readonly SourceDelivery[] {\n const allowed = ([\"direct\", \"context\"] as const).filter((d) => !deliveries || deliveries.includes(d));\n // A host that lists nothing it can use still gets the contract default.\n return allowed.length > 0 ? allowed : [\"direct\"];\n}\n\n/** The choices one host offers, in the order every control shows them. */\nexport function deliveryChoicesFor(\n deliveries: readonly SourceDelivery[] | undefined,\n): ReadonlyArray<{ value: SourceDelivery } & DeliveryWords> {\n const allowed = allowedDeliveries(deliveries);\n return DELIVERY_CHOICES.filter((c) => allowed.includes(c.value));\n}\n\n/** The sentence a switched-back Source carries — every intervention announces itself. */\nexport function deliverySwitchedNote(to: SourceDelivery): string {\n return to === \"direct\"\n ? `This Source was set to \"${DELIVERY_WORDS.context.label}\", which this page cannot use — it needs the text up front — so it was switched back to \"${DELIVERY_WORDS.direct.label}\".`\n : `This Source was set to \"${DELIVERY_WORDS.direct.label}\", which this page cannot use, so it was switched to \"${DELIVERY_WORDS.context.label}\".`;\n}\n\n/**\n * Fit a pointer to what the host can use. Returns the patch to apply (null\n * when it already fits) and the delivery it lands on.\n */\nexport function fitDelivery(\n ref: Pick<SourceRef, \"delivery\"> | null | undefined,\n deliveries: readonly SourceDelivery[] | undefined,\n): { patch: ReturnType<typeof deliveryPatch>; to: SourceDelivery } | null {\n if (!ref) return null;\n const allowed = allowedDeliveries(deliveries);\n const current = sourceDelivery(ref);\n if (allowed.includes(current)) return null;\n const to = allowed[0]!;\n return { patch: deliveryPatch(to), to };\n}\n","/**\n * Finding a part of a Source — THE one matcher, used by the Source card's\n * \"Choose parts\" and by \"Review what goes in\".\n *\n * A query is one of:\n * - a page number (\"12\") — the part that covers that page;\n * - a page range (\"3-10\", \"3–10\", \"3 to 10\") — every part inside it;\n * - words — every word must appear in the part's label or its preview (the\n * opening words the manifest carries, contract amendment A5), matched here;\n * or the part is one the server found holding every word in its full text\n * (`POST /sources/parts/search`, via `useSourcePartsSearch`).\n *\n * A part spanning several pages (\"Pages 22–24\") covers each of them: the\n * manifest's numeric `page` is its first page and the label names the span.\n *\n * V1-A: the search promised \"words\" but matched only labels, so\n * \"photosynthesis\" found nothing in a biology course.\n */\n\nimport type { SourceManifestSegment } from \"../index\";\n\n/** A manifest part, with the A5 preview (optional on the wire). */\nexport type SourcePart = SourceManifestSegment & { preview?: string };\n\n/** The ids of parts the server found holding every word (`useSourcePartsSearch`). */\nexport type PartMatchIds = ReadonlySet<string>;\n\nconst RANGE_RE = /^(\\d+)\\s*(?:-|–|—|to)\\s*(\\d+)$/;\nconst SPAN_RE = /(\\d+)\\s*[–—-]\\s*(\\d+)/;\n\n/** The pages a part covers: its label's span (\"Pages 22–24\") or its one page. */\nexport function partPages(part: SourcePart): [number, number] | null {\n if (part.page === undefined || part.page === null) return null;\n const span = /^pages?\\s/i.test(part.label) ? SPAN_RE.exec(part.label) : null;\n if (span) return [Number(span[1]), Number(span[2])];\n return [part.page, part.page];\n}\n\n/** True when a query is words (not a page or a range) — only then is the text searched. */\nexport function isWordQuery(query: string): boolean {\n const q = query.trim().toLowerCase();\n return q.length > 0 && !/^\\d+$/.test(q) && !RANGE_RE.test(q);\n}\n\nfunction normalise(text: string): string {\n return text.toLowerCase().replace(/\\s+/g, \" \");\n}\n\nexport function matchesPart(part: SourcePart, query: string, serverMatches?: PartMatchIds): boolean {\n const q = query.trim().toLowerCase();\n if (!q) return true;\n const pages = partPages(part);\n const range = RANGE_RE.exec(q);\n if (range && pages) {\n const from = Math.min(Number(range[1]), Number(range[2]));\n const to = Math.max(Number(range[1]), Number(range[2]));\n return pages[0] <= to && pages[1] >= from;\n }\n if (/^\\d+$/.test(q) && pages) {\n const n = Number(q);\n return pages[0] <= n && n <= pages[1];\n }\n if (part.id.toLowerCase() === q) return true;\n if (serverMatches?.has(part.id)) return true;\n const haystack = normalise([part.label, part.preview ?? \"\"].join(\" \"));\n return q\n .split(/\\s+/)\n .filter(Boolean)\n .every((word) => haystack.includes(word));\n}\n\n/** The parts a query shows, in the Source's own order. */\nexport function findParts<T extends SourcePart>(\n parts: readonly T[],\n query: string,\n serverMatches?: PartMatchIds,\n): T[] {\n return parts.filter((p) => matchesPart(p, query, serverMatches));\n}\n","/**\n * What a Source that was still landing becomes when the page reloads.\n *\n * Never lose input (table stakes): the pasted text, the link, or an\n * already-uploaded recording is kept in the draft (`SourceDraft.input`), so\n * the input picks it up again by itself — the landing door dedupes by content\n * hash, so landing it a second time reuses the same Source, never a copy.\n * A file that was mid-upload cannot come back (its bytes lived only in the\n * browser tab); the card says so honestly and keeps the file's name so the\n * person can choose it again in one click.\n */\n\nimport type { SourceDraft, SourceIntakeInput } from \"./types\";\n\n/** Shown while a kept input is being landed again after a reload. */\nexport const RELOADED_RESUMING =\n \"The page reloaded while this was being added — picking it up again.\";\n\n/** A kept input exists but has not been re-landed (it will be, or the person can press Try again). */\nexport const RELOADED_WHILE_ADDING =\n \"This was still being added when the page reloaded, so it did not finish. Add it again.\";\n\n/** The kinds whose landing can be repeated from what the draft kept. */\nexport function resumableInput(draft: SourceDraft): SourceIntakeInput | null {\n const input = draft.input;\n if (!input) return null;\n switch (draft.kind) {\n case \"paste\":\n return input.text?.trim() ? input : null;\n case \"web\":\n case \"youtube\":\n return input.url?.trim() ? input : null;\n case \"audio\":\n // An uploaded recording re-transcribes from its file; one recorded in\n // place (the Voice Pad) is already text and lands again from it.\n return input.fileId || input.text?.trim() ? input : null;\n default:\n return null;\n }\n}\n\n/** The sentence for a file whose upload the reload cut off. */\nexport function uploadCutOffSentence(draft: SourceDraft): string {\n return `\"${draft.label}\" was still uploading when the page reloaded, so it did not arrive. Choose it again to add it.`;\n}\n\nexport interface ReloadedCard {\n /** \"resume\" = land the kept input again now; \"reoffer\" = the person must re-choose a file. */\n action: \"resume\" | \"reoffer\" | \"lost\";\n sentence: string;\n}\n\n/**\n * The one decision: a card that was `pending`/`resolving` when the page\n * unloaded. Cards in any other state are restored unchanged (returns null).\n */\nexport function reloadedCard(\n draft: SourceDraft,\n status: \"pending\" | \"resolving\" | \"ready\" | \"error\",\n): ReloadedCard | null {\n if (status !== \"pending\" && status !== \"resolving\") return null;\n if (resumableInput(draft)) return { action: \"resume\", sentence: RELOADED_RESUMING };\n if (draft.kind === \"upload\" || draft.kind === \"image\" || draft.kind === \"audio\")\n return { action: \"reoffer\", sentence: uploadCutOffSentence(draft) };\n return { action: \"lost\", sentence: RELOADED_WHILE_ADDING };\n}\n\n/**\n * The knob for the largest pasted text kept in the device draft (it would\n * crowd the draft store). Read by the intake; while unread nothing is kept and\n * the card says so.\n */\nexport const MAX_KEPT_TEXT_KNOB = { feature: \"sources\", key: \"max_kept_draft_chars\" } as const;\n\n/** Said on a pasted card whose text is too large (or the limit unreadable) to keep for a reload. */\nexport const NOT_KEPT_FOR_RELOAD =\n \"Too large to restore if the page reloads before it is added.\";\n\n/**\n * A landing stopped only because no organization is chosen yet. The card\n * waits; the moment one is set the intake lands every waiting card again from\n * what its draft kept (state, never an in-memory queue — it survives a reload).\n */\nexport const WAITING_FOR_ORGANIZATION =\n \"Waiting for an organization — choose one and this continues by itself.\";\n\n/** A read Source whose keep waits for an organization; kept again once one is set. */\nexport const KEEP_WAITING_FOR_ORGANIZATION =\n \"Read. Waiting for an organization to keep it — choose one and it is kept by itself.\";\n","/**\n * fileSource — how a stored file on a Source card becomes its Source, decided\n * from the SERVER's state alone (USI-3e). Pure: the one read\n * (`/files/{id}/rag-status`) and the file's own organization are INJECTED by\n * the host (`SourceFileState` below), never imported.\n *\n * The server owns reading a file: every upload's finalize already starts the\n * one processing run (the file adapters → a `processed_documents` row), and\n * `/files/{id}/rag-status` merges that run's lifecycle row with the Source it\n * made. So a card never starts its own run while one is live, a reload simply\n * reads the state again (re-attach, never a second job), and a file someone\n * already had (\"use the one you already have\", or picked from Files) is kept\n * the moment its existing Source is seen.\n */\n\nimport type { SourceCardModel } from \"./types\";\n\n/** The part of the server's `/files/{id}/rag-status` answer the decision reads. */\nexport interface FileSourceStatus {\n state: string;\n processed_document_id?: string | null | undefined;\n error?: { message?: string | null | undefined; [detail: string]: unknown } | null | undefined;\n}\n\nexport type FileSourceStep =\n /** The Source exists: keep it and file it against the thing being made. */\n | { do: \"keep\"; processedDocumentId: string }\n /** A run is reading it now (server-side or this tab's own). Look again soon. */\n | { do: \"wait\" }\n /** Nothing is reading it and it has no Source yet: start the one run. */\n | { do: \"start\" }\n /** It cannot become a Source; say why, and stop looking. */\n | { do: \"unreadable\"; reason: string };\n\nexport interface FileSourceContext {\n /** This card already started a run in this page's life. */\n started: boolean;\n /** This tab's processing runner has a live run for the file. */\n localRunning: boolean;\n}\n\nconst UNREADABLE = \"Can't read this file — add a PDF, Word or text copy.\";\n\n/** The one decision. `status` is the server's `/files/{id}/rag-status` answer. */\nexport function nextFileStep(\n status: FileSourceStatus | null,\n ctx: FileSourceContext,\n): FileSourceStep {\n const pdId = status?.processed_document_id ?? null;\n if (pdId) return { do: \"keep\", processedDocumentId: pdId };\n if (ctx.localRunning || status?.state === \"running\") return { do: \"wait\" };\n if (status?.state === \"failed\")\n return {\n do: \"unreadable\",\n reason: status.error?.message\n ? `Can't read this file: ${status.error.message}. Add it again.`\n : UNREADABLE,\n };\n if (!ctx.started) return { do: \"start\" };\n return { do: \"unreadable\", reason: UNREADABLE };\n}\n\n/** How long to wait before looking again: quick at first, then spaced out. */\nexport function fileSourcePollDelayMs(round: number): number {\n if (round < 5) return 3_000;\n if (round < 20) return 6_000;\n return 15_000;\n}\n\n/** A stored file on a card whose Source is not known yet — the recovery reads its state. */\nexport function isWaitingFileCard(card: SourceCardModel): boolean {\n return (\n card.status === \"ready\" &&\n card.draft.ref?.resource_type === \"file\" &&\n !!card.draft.fileId &&\n !card.draft.processedDocumentId\n );\n}\n\n/**\n * True while a waiting file card cannot be asked about yet: `/files/{id}/\n * rag-status` answers only with an organization (the file's own, when the\n * host knows it, or the one the person picked). Without one every read was a\n * refused 400 — every ~3 s, piling up as page errors (V2-F #3). So the card\n * is HELD: it says it is waiting for an organization, offers the one picker,\n * and nothing is asked until one is known.\n *\n * `fileOrganizationId` is the host's lookup of a file's own organization\n * (omitted = the host does not know it).\n */\nexport function fileCardHeldForOrganization(\n card: SourceCardModel,\n activeOrganizationId: string | null | undefined,\n fileOrganizationId?: (fileId: string) => string | null | undefined,\n): boolean {\n if (!isWaitingFileCard(card)) return false;\n if (activeOrganizationId) return false;\n return !fileOrganizationId?.(card.draft.fileId as string);\n}\n","/**\n * The token estimate the planner uses by default — the SAME measured ratios as\n * the web app's one estimator (matrx-frontend `lib/tokens/estimate.ts`) and the\n * server's `CHARS_PER_TOKEN_MEASURED` (aidream, 2026-09-28): 2.9 characters per\n * token for prose with markup, 2.4 for structured payloads. Measured, not\n * assumed — the textbook 4.0 under-counted a real run by 23%.\n *\n * A host that owns its own estimator passes it to `planSourceReview`\n * (`PlanInput.estimateTokens`) so a preview and a run never disagree.\n */\n\nexport const SOURCE_CHARS_PER_TOKEN = {\n prose: 2.9,\n structured: 2.4,\n} as const;\n\n/** Estimated tokens for `chars` characters of prose. */\nexport function estimateSourceTokens(chars: number): number {\n if (!Number.isFinite(chars) || chars <= 0) return 0;\n return Math.ceil(chars / SOURCE_CHARS_PER_TOKEN.prose);\n}\n","/**\n * `@ai-matrx/agents/sources` — THE ONE SOURCE PAYLOAD (contract v1, frozen 2026-09-27).\n *\n * Every request that is built from a person's Sources carries them as a\n * `SourceSet`: a list of `SourceRef` pointers (never blobs) plus how the model\n * should be grounded in them. The server answers with a `SourceManifest`\n * (sizes and states, never bodies — POST /sources/manifest) or a\n * `ResolvedSourceSet` (grounded text for generators — POST /sources/resolve).\n *\n * Contract of record: common-docs `projects/unified-source-input/DESIGN.md`\n * § \"Contract v1 — FROZEN\". A shape change here is an AMENDMENT there first,\n * with its Pydantic twin beside aidream's `parse_resource_reference`.\n *\n * `SourceRef` IS the existing `resource_ref` pointer already on the wire\n * (aidream `services/conversation_context/resource_context.py`), extended with\n * optional fields only — never coin a second pointer type.\n *\n * Pure module: no React, no I/O, no \"use client\".\n */\n\nexport const RESOURCE_REF_KIND = \"resource_ref\" as const;\nexport const SOURCE_SET_KIND = \"source_set\" as const;\nexport const SOURCE_MANIFEST_KIND = \"source_manifest\" as const;\nexport const RESOLVED_SOURCE_SET_KIND = \"resolved_source_set\" as const;\n\n/** The wire version every `SourceSet` carries. */\nexport const SOURCE_SET_VERSION = 1 as const;\n\n/** A bounded preview of one representation promoted into the prompt. */\nexport interface ResourcePromotion {\n representation: string;\n max_chars?: number;\n}\n\nexport type SourceDelivery = \"direct\" | \"context\";\nexport type SourceGrounding = \"whole\" | \"selected\" | \"retrieve\";\n\n/** The pointer — the existing `resource_ref` envelope, extended (all new fields optional). */\nexport interface SourceRef {\n __kind: typeof RESOURCE_REF_KIND;\n /** Server resource token: \"file\" (A2; \"cld_file\" is a server alias) | \"processed_document\" | \"note\" | \"fc_set\" | … */\n resource_type: string;\n resource_id: string;\n /** \"clean\" | \"raw\" | \"pdf\" | a family representation key. Omitted = server's Clean → Raw → original fallback. */\n representation?: string;\n /** Hand-picked Segment ids (rag.kg_chunks ids or \"<resource_id>:<n>\"). */\n include_segments?: string[];\n /** Include the text (default \"direct\") | the AI fetches it on demand (\"context\"). */\n delivery?: SourceDelivery;\n /** Per-Source cap chosen on the review page. */\n max_chars?: number;\n promote?: ResourcePromotion | ResourcePromotion[];\n exclude?: string[];\n}\n\nexport interface SourceSet {\n __kind: typeof SOURCE_SET_KIND;\n version: typeof SOURCE_SET_VERSION;\n sources: SourceRef[];\n /** Only for \"Just a topic\". */\n topic?: string;\n /** Default \"whole\". */\n grounding?: SourceGrounding;\n /** Required in spirit when grounding = \"retrieve\". */\n retrieve_query?: string;\n /** The model whose context window sets the budget. */\n target_model_id?: string;\n}\n\nexport type SourceState = \"ready\" | \"processing\" | \"failed\" | \"unavailable\";\n\nexport interface SourceManifestForm {\n form: string;\n label: string;\n chars: number;\n available: boolean;\n}\n\nexport interface SourceManifestSegment {\n id: string;\n /** \"Page 7\", \"Pages 22–24\" (a part spanning pages), \"0:04–2:31\", a heading path, \"Part 3\". */\n label: string;\n page?: number;\n chars: number;\n /**\n * Amendment A5: the part's opening words (about 160 characters, whitespace\n * collapsed) — never its body. Lets a person see what a part says and find\n * a part by its words.\n */\n preview?: string;\n}\n\nexport interface SourceManifestEntry {\n ref: SourceRef;\n label: string;\n resource_type: string;\n state: SourceState;\n state_detail?: string;\n forms: SourceManifestForm[];\n default_form: string;\n segments?: SourceManifestSegment[];\n}\n\n/** POST /sources/manifest { source_set } → sizes and states, never bodies. */\nexport interface SourceManifest {\n __kind: typeof SOURCE_MANIFEST_KIND;\n sources: SourceManifestEntry[];\n total_chars: number;\n estimated_tokens: number;\n /** null = unknown model; the UI says so. */\n model_context_tokens: number | null;\n}\n\nexport interface ResolvedSourceSegment {\n id: string;\n page?: number;\n chars: number;\n}\n\nexport interface ResolvedSource {\n ref: SourceRef;\n label: string;\n form_used: string;\n /** Grounded: \"### Chunk <id> (page N)\" blocks; never re-chunked. */\n text: string;\n segments: ResolvedSourceSegment[];\n file_id?: string;\n processed_document_id?: string;\n /** \"processing\" = the raw fallback was used. */\n state: \"ready\" | \"processing\";\n truncated: boolean;\n /** Every stand-in announces itself. */\n notes: string[];\n}\n\n/** A1 (2026-09-27): \"not_ready\" = a file not yet read. */\nexport type DroppedSourceReason =\n | \"no_access\"\n | \"missing\"\n | \"failed\"\n | \"over_budget\"\n | \"not_ready\";\n\nexport interface DroppedSource {\n ref: SourceRef;\n reason: DroppedSourceReason;\n /** A1: what happened and what to do. */\n detail?: string;\n}\n\n/** POST /sources/resolve { source_set } → grounded text for generators. */\nexport interface ResolvedSourceSet {\n __kind: typeof RESOLVED_SOURCE_SET_KIND;\n sources: ResolvedSource[];\n dropped: DroppedSource[];\n total_chars: number;\n}\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\n/** Builder options. `undefined` is accepted everywhere so callers can forward an existing ref's optional fields. */\nexport interface SourceRefOptions {\n representation?: string | undefined;\n include_segments?: readonly string[] | undefined;\n delivery?: SourceDelivery | undefined;\n max_chars?: number | undefined;\n promote?: ResourcePromotion | ResourcePromotion[] | undefined;\n exclude?: readonly string[] | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Build one pointer. Empty optional fields are omitted (so the wire stays\n * minimal and equal pointers serialise equally); `exclude` is trimmed,\n * lower-cased and de-duplicated exactly as the server normalises it;\n * `include_segments` is de-duplicated in order. Throws on an empty type or id —\n * a pointer to nothing is never built silently.\n */\nexport function createSourceRef(\n resourceType: string,\n resourceId: string,\n options: SourceRefOptions = {},\n): SourceRef {\n const resource_type = resourceType.trim();\n const resource_id = resourceId.trim();\n if (!resource_type) throw new Error(\"createSourceRef: resource_type is required\");\n if (!resource_id) throw new Error(\"createSourceRef: resource_id is required\");\n if (\n options.max_chars !== undefined &&\n (!Number.isInteger(options.max_chars) || options.max_chars <= 0)\n ) {\n throw new Error(\"createSourceRef: max_chars must be a positive integer\");\n }\n const exclude = Array.from(\n new Set(\n (options.exclude ?? [])\n .map((value) => value.trim().toLowerCase())\n .filter(Boolean),\n ),\n );\n const include_segments = Array.from(\n new Set((options.include_segments ?? []).map((id) => id.trim()).filter(Boolean)),\n );\n return {\n __kind: RESOURCE_REF_KIND,\n resource_type,\n resource_id,\n ...(options.representation ? { representation: options.representation } : {}),\n ...(include_segments.length ? { include_segments } : {}),\n ...(options.delivery ? { delivery: options.delivery } : {}),\n ...(options.max_chars !== undefined ? { max_chars: options.max_chars } : {}),\n ...(options.promote ? { promote: options.promote } : {}),\n ...(exclude.length ? { exclude } : {}),\n };\n}\n\nexport function isSourceRef(value: unknown): value is SourceRef {\n return (\n isRecord(value) &&\n value.__kind === RESOURCE_REF_KIND &&\n typeof value.resource_type === \"string\" &&\n value.resource_type.length > 0 &&\n typeof value.resource_id === \"string\" &&\n value.resource_id.length > 0\n );\n}\n\nexport interface SourceSetOptions {\n topic?: string | undefined;\n grounding?: SourceGrounding | undefined;\n retrieve_query?: string | undefined;\n target_model_id?: string | undefined;\n}\n\n/**\n * Build one envelope. Duplicate pointers (same type + id + representation) are\n * collapsed, keeping the first. `grounding: \"retrieve\"` without a query and\n * `grounding: \"selected\"` with no Source carrying `include_segments` throw —\n * both would otherwise resolve to something the person never asked for.\n */\nexport function createSourceSet(\n sources: readonly SourceRef[],\n options: SourceSetOptions = {},\n): SourceSet {\n const seen = new Set<string>();\n const unique: SourceRef[] = [];\n for (const ref of sources) {\n if (!isSourceRef(ref)) throw new Error(\"createSourceSet: every source must be a resource_ref\");\n const key = `${ref.resource_type}\\u0000${ref.resource_id}\\u0000${ref.representation ?? \"\"}`;\n if (seen.has(key)) continue;\n seen.add(key);\n unique.push(ref);\n }\n const topic = options.topic?.trim();\n const retrieve_query = options.retrieve_query?.trim();\n if (options.grounding === \"retrieve\" && !retrieve_query) {\n throw new Error('createSourceSet: grounding \"retrieve\" needs a retrieve_query');\n }\n if (\n options.grounding === \"selected\" &&\n !unique.some((ref) => (ref.include_segments?.length ?? 0) > 0)\n ) {\n throw new Error('createSourceSet: grounding \"selected\" needs at least one Source with include_segments');\n }\n return {\n __kind: SOURCE_SET_KIND,\n version: SOURCE_SET_VERSION,\n sources: unique,\n ...(topic ? { topic } : {}),\n ...(options.grounding ? { grounding: options.grounding } : {}),\n ...(retrieve_query ? { retrieve_query } : {}),\n ...(options.target_model_id ? { target_model_id: options.target_model_id } : {}),\n };\n}\n\n/** Structural guard for a wire value claiming to be a v1 `SourceSet`. */\nexport function isSourceSet(value: unknown): value is SourceSet {\n return (\n isRecord(value) &&\n value.__kind === SOURCE_SET_KIND &&\n value.version === SOURCE_SET_VERSION &&\n Array.isArray(value.sources) &&\n value.sources.every(isSourceRef)\n );\n}\n\nfunction manifestEntryChars(entry: SourceManifestEntry): number {\n const selected = entry.ref.include_segments;\n let chars: number;\n if (selected?.length && entry.segments?.length) {\n const wanted = new Set(selected);\n chars = entry.segments\n .filter((segment) => wanted.has(segment.id))\n .reduce((sum, segment) => sum + segment.chars, 0);\n } else {\n const formKey = entry.ref.representation ?? entry.default_form;\n const form =\n entry.forms.find((candidate) => candidate.form === formKey) ??\n entry.forms.find((candidate) => candidate.form === entry.default_form);\n chars = form?.chars ?? 0;\n }\n return entry.ref.max_chars !== undefined ? Math.min(chars, entry.ref.max_chars) : chars;\n}\n\n/**\n * Characters that will actually go in, computed from the Sources themselves\n * (never trusting a stale `total_chars`):\n * - `ResolvedSourceSet`: the sum of every resolved text's length.\n * - `SourceManifest`: per Source, the chosen form's size (the ref's\n * `representation`, else `default_form`), or the picked Segments' sizes when\n * `include_segments` is set, capped by the ref's `max_chars`. Sources whose\n * state is \"failed\" or \"unavailable\" contribute nothing — they cannot go in.\n */\nexport function totalChars(value: SourceManifest | ResolvedSourceSet): number {\n if (value.__kind === RESOLVED_SOURCE_SET_KIND) {\n return value.sources.reduce((sum, source) => sum + source.text.length, 0);\n }\n return value.sources\n .filter((entry) => entry.state === \"ready\" || entry.state === \"processing\")\n .reduce((sum, entry) => sum + manifestEntryChars(entry), 0);\n}\n","/**\n * The source-list state machine — pure reducers and selectors over\n * `SourceSetState`. Every function returns a NEW state (or the same one when\n * nothing changed) and never touches a store, a network or a clock; the\n * controller (`controller.ts`) applies them through the host's store adapter.\n *\n * The rules here are the ones the web app's Source input has always kept:\n * - landing the same Source twice keeps ONE card and says so on it;\n * - a settled card drops the input it kept for a reload;\n * - a card cut off mid-landing by a reload is restored as an error the\n * input resolves (`interrupted.ts`), never a spinner forever;\n * - a new Source starts on the host's default form.\n */\n\nimport {\n createSourceRef,\n createSourceSet,\n totalChars as sumChars,\n type ResolvedSourceSet,\n type SourceManifest,\n type SourceManifestEntry,\n type SourceRef,\n type SourceRefOptions,\n type SourceSet,\n} from \"../index\";\nimport { deliverySwitchedNote, fitDelivery, type SourceDelivery } from \"./delivery\";\nimport { reloadedCard, WAITING_FOR_ORGANIZATION } from \"./interrupted\";\nimport { partPages } from \"./partsSearch\";\nimport type {\n PersistedSourceCard,\n PersistedSourceInput,\n SourceCardModel,\n SourceDraft,\n SourcePickedPart,\n SourceSetState,\n} from \"./types\";\n\nexport const EMPTY_SOURCE_SET_STATE: SourceSetState = Object.freeze({ cards: Object.freeze([]), topic: \"\" }) as SourceSetState;\n\n/** Said when a Source's parts were re-read (the clean version landed) and the pick was carried over by page. */\nexport const PARTS_MATCHED_BY_PAGE = \"The clean version is ready — your parts were matched to it by page.\";\n\n/** Said when a pick could not be carried over to the Source's new parts: the whole Source goes in until parts are chosen again. */\nexport const PARTS_NOT_MATCHED =\n \"The clean version is ready, but your parts could not be matched to it — choose parts again. Until then the whole Source goes in.\";\n\n/** Said on the one card kept when the same Source lands twice. */\nexport const SAME_SOURCE_AGAIN = \"You added this again — it is the same Source, so it is listed once.\";\n\nexport function isSourceDraft(value: unknown): value is SourceDraft {\n return (\n !!value &&\n typeof value === \"object\" &&\n typeof (value as SourceDraft).kind === \"string\" &&\n typeof (value as SourceDraft).label === \"string\"\n );\n}\n\nexport function sameSourceRef(\n a: Pick<SourceRef, \"resource_type\" | \"resource_id\">,\n b: Pick<SourceRef, \"resource_type\" | \"resource_id\">,\n): boolean {\n return a.resource_type === b.resource_type && a.resource_id === b.resource_id;\n}\n\n/** \"<resource_type>:<resource_id>\" — how a Source is keyed across screens. */\nexport function sourceKey(ref: { resource_type: string; resource_id: string }): string {\n return `${ref.resource_type}:${ref.resource_id}`;\n}\n\n/** The draft kind a registry token is picked as. */\nexport function draftKindForToken(token: string): SourceDraft[\"kind\"] {\n if (token === \"file\") return \"files\";\n if (token === \"note\") return \"notes\";\n if (token === \"processed_document\") return \"your_sources\";\n return \"records\";\n}\n\n/** A new pointer starts on the host's default form (never over one already chosen). */\nexport function withDefaultForm(ref: SourceRef, defaultForm: string | undefined): SourceRef {\n return defaultForm && !ref.representation\n ? createSourceRef(ref.resource_type, ref.resource_id, { ...ref, representation: defaultForm })\n : ref;\n}\n\nfunction cardById(state: SourceSetState, id: string): SourceCardModel | undefined {\n return state.cards.find((c) => c.id === id);\n}\n\nfunction replaceCard(\n state: SourceSetState,\n id: string,\n patch: (card: SourceCardModel) => SourceCardModel,\n): SourceSetState {\n let changed = false;\n const cards = state.cards.map((c) => {\n if (c.id !== id) return c;\n const next = patch(c);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...state, cards } : state;\n}\n\n// ── Reducers ────────────────────────────────────────────────────────────────\n\n/** Add a Source that is already a pointer (a stored record, a landed Source). */\nexport function addReadyCard(\n state: SourceSetState,\n id: string,\n draft: SourceDraft,\n options: { defaultForm?: string | undefined } = {},\n): SourceSetState {\n const ref = draft.ref ? withDefaultForm(draft.ref, options.defaultForm) : null;\n return {\n ...state,\n cards: [...state.cards, { id, draft: { ...draft, ref }, status: \"ready\", error: null, manifest: null }],\n };\n}\n\n/** Add a Source that is still landing; finish it with `settleCard` or `failCard`. */\nexport function addPendingCard(\n state: SourceSetState,\n id: string,\n draft: Omit<SourceDraft, \"ref\">,\n): SourceSetState {\n return {\n ...state,\n cards: [...state.cards, { id, draft: { ...draft, ref: null }, status: \"resolving\", error: null, manifest: null }],\n };\n}\n\n/**\n * A landing answered. The door dedupes by content: landing the same thing\n * twice returns the Source already picked — keep ONE card and say so on it.\n */\nexport function settleCard(\n state: SourceSetState,\n id: string,\n patch: Partial<SourceDraft> & { ref: SourceRef },\n options: { defaultForm?: string | undefined } = {},\n): SourceSetState {\n const card = cardById(state, id);\n if (!card) return state; // removed while it was landing — nothing to finish\n const twin = state.cards.find((c) => c.id !== id && c.draft.ref && sameSourceRef(c.draft.ref, patch.ref));\n if (twin) {\n const without = { ...state, cards: state.cards.filter((c) => c.id !== id) };\n if (twin.draft.notes?.includes(SAME_SOURCE_AGAIN)) return without;\n return replaceCard(without, twin.id, (c) => ({\n ...c,\n draft: { ...c.draft, notes: [...(c.draft.notes ?? []), SAME_SOURCE_AGAIN] },\n }));\n }\n return replaceCard(state, id, (c) => ({\n ...c,\n // Landed: the kept input has done its job and leaves the draft.\n draft: { ...c.draft, ...patch, input: undefined, ref: withDefaultForm(patch.ref, options.defaultForm) },\n status: \"ready\",\n error: null,\n }));\n}\n\n/**\n * A card that failed has ONE state — failed. Its last measurement goes, so it\n * can never also say \"Still being read\" (verify-3: a stored PDF showed both).\n */\nexport function failCard(state: SourceSetState, id: string, sentence: string): SourceSetState {\n return replaceCard(state, id, (c) => ({ ...c, status: \"error\", error: sentence, manifest: null }));\n}\n\n/** Back to landing (after a reload or a failure). */\nexport function restartCard(state: SourceSetState, id: string): SourceSetState {\n return replaceCard(state, id, (c) => ({ ...c, status: \"resolving\", error: null }));\n}\n\n/** Change what a card says or keeps (label, input, fileId, notes, processedDocumentId). */\nexport function updateCardDraft(\n state: SourceSetState,\n id: string,\n patch: Partial<Omit<SourceDraft, \"ref\">>,\n): SourceSetState {\n return replaceCard(state, id, (c) => ({ ...c, draft: { ...c.draft, ...patch } }));\n}\n\nexport function removeCard(state: SourceSetState, id: string): SourceSetState {\n if (!cardById(state, id)) return state;\n return { ...state, cards: state.cards.filter((c) => c.id !== id) };\n}\n\n/** Change the pointer's choices (form, parts, cap, delivery). */\nexport function updateCardRef(state: SourceSetState, id: string, options: SourceRefOptions): SourceSetState {\n return replaceCard(state, id, (c) => {\n if (!c.draft.ref) return c;\n const ref = createSourceRef(c.draft.ref.resource_type, c.draft.ref.resource_id, { ...c.draft.ref, ...options });\n return rememberPickedParts({ ...c, draft: { ...c.draft, ref } });\n });\n}\n\n/**\n * Remember where the picked parts sit (label + pages) from the card's current\n * measurement, so a pick survives the Source being re-split (raw pages → clean\n * parts). No parts picked = nothing remembered.\n */\nexport function rememberPickedParts(card: SourceCardModel): SourceCardModel {\n const ids = card.draft.ref?.include_segments ?? [];\n if (ids.length === 0) {\n return card.draft.pickedParts === undefined ? card : { ...card, draft: { ...card.draft, pickedParts: undefined } };\n }\n const segments = card.manifest?.segments ?? [];\n const known = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));\n const picked: SourcePickedPart[] = [];\n for (const id of ids) {\n const segment = segments.find((s) => s.id === id);\n if (segment) {\n const pages = partPages(segment);\n picked.push({ id, label: segment.label, ...(pages ? { pages } : {}) });\n } else {\n const before = known.get(id);\n if (before) picked.push(before);\n }\n }\n return { ...card, draft: { ...card.draft, pickedParts: picked.length ? picked : undefined } };\n}\n\nfunction withNote(notes: readonly string[] | undefined, note: string, drop: readonly string[] = []): string[] {\n const kept = (notes ?? []).filter((n) => n !== note && !drop.includes(n));\n return [...kept, note];\n}\n\n/**\n * A fresh measurement listed NEW parts (the clean version landed, so the raw\n * pages the person picked no longer exist by id). Carry the pick over by page:\n * every new part that covers a page the old pick covered goes in. When the old\n * pick's pages are unknown, the pick is cleared and the card says so — never\n * \"0 characters · 4 of 21 parts\" with nothing ticked (verify-3, 11d/11e).\n */\nexport function carryPickedParts(card: SourceCardModel, entry: SourceManifestEntry): SourceCardModel {\n const ref = card.draft.ref;\n const picked = ref?.include_segments ?? [];\n const segments = entry.segments ?? [];\n if (!ref || picked.length === 0 || segments.length === 0) return card;\n const ids = new Set(segments.map((s) => s.id));\n const stale = picked.filter((id) => !ids.has(id));\n if (stale.length === 0) return card;\n const remembered = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));\n const oldSegments = card.manifest?.segments ?? [];\n const spans: Array<[number, number]> = [];\n let unknown = 0;\n for (const id of stale) {\n const old = oldSegments.find((s) => s.id === id);\n const pages = remembered.get(id)?.pages ?? (old ? partPages(old) : null);\n if (pages) spans.push(pages);\n else unknown += 1;\n }\n const keep = new Set(picked.filter((id) => ids.has(id)));\n for (const segment of segments) {\n const pages = partPages(segment);\n if (pages && spans.some(([from, to]) => pages[0] <= to && pages[1] >= from)) keep.add(segment.id);\n }\n const nextIds = segments.filter((s) => keep.has(s.id)).map((s) => s.id);\n const matched = unknown === 0 && nextIds.length > 0;\n const nextRef = createSourceRef(ref.resource_type, ref.resource_id, {\n ...ref,\n include_segments: matched ? nextIds : undefined,\n });\n const note = matched ? PARTS_MATCHED_BY_PAGE : PARTS_NOT_MATCHED;\n const other = matched ? PARTS_NOT_MATCHED : PARTS_MATCHED_BY_PAGE;\n return rememberPickedParts({\n ...card,\n manifest: entry,\n draft: { ...card.draft, ref: nextRef, notes: withNote(card.draft.notes, note, [other]) },\n });\n}\n\nexport function setCardWaitForClean(state: SourceSetState, id: string, wait: boolean): SourceSetState {\n return replaceCard(state, id, (c) => ({ ...c, draft: { ...c.draft, waitForClean: wait } }));\n}\n\nexport function setSourceTopic(state: SourceSetState, topic: string): SourceSetState {\n return state.topic === topic ? state : { ...state, topic };\n}\n\n/**\n * What the person removed in \"Review what goes in\": the Sources that went INTO\n * the review (`reviewed`) and did not come back in its answer — keyed by\n * `sourceKey`. A Source that landed while the review was open is never in\n * `reviewed`, so it is never removed by it (verify-4 V4-F #3).\n */\nexport function removedInReview(reviewed: SourceSet, answer: SourceSet): Set<string> {\n const kept = new Set(answer.sources.map(sourceKey));\n return new Set(reviewed.sources.map(sourceKey).filter((k) => !kept.has(k)));\n}\n\n/**\n * Apply a set the review returned (forms, parts, caps, delivery) — and its\n * topic. Pass `reviewed` (the set that was sent INTO the review) and every\n * Source removed there leaves the list, bound by its own card id.\n */\nexport function applyReviewedSourceSet(state: SourceSetState, set: SourceSet, reviewed?: SourceSet): SourceSetState {\n let next = state;\n if (reviewed) {\n const removed = removedInReview(reviewed, set);\n for (const card of state.cards) {\n if (card.draft.ref && removed.has(sourceKey(card.draft.ref))) next = removeCard(next, card.id);\n }\n }\n for (const card of next.cards) {\n const ref = card.draft.ref;\n if (!ref) continue;\n const match = set.sources.find((r) => sameSourceRef(r, ref));\n if (!match) continue;\n next = replaceCard(next, card.id, (c) => rememberPickedParts({ ...c, draft: { ...c.draft, ref: match } }));\n }\n return set.topic !== undefined ? setSourceTopic(next, set.topic) : next;\n}\n\n/** The server measured the ready Sources: each ready card takes its entry. */\nexport function applyManifest(state: SourceSetState, manifest: SourceManifest): SourceSetState {\n let next = state;\n for (const card of state.cards) {\n const ref = card.draft.ref;\n if (!ref || card.status !== \"ready\") continue;\n const entry = manifest.sources.find((e) => sameSourceRef(e.ref, ref));\n if (!entry) continue;\n next = replaceCard(next, card.id, (c) => {\n const carried = carryPickedParts(c, entry);\n if (carried !== c) return carried;\n const measured = { ...c, manifest: entry };\n // Parts picked before their pages were known are remembered now.\n return c.draft.ref?.include_segments?.length && !c.draft.pickedParts ? rememberPickedParts(measured) : measured;\n });\n }\n return next;\n}\n\n/**\n * Only what the host can use (V2-F #1): a Source set to a delivery this surface\n * cannot use (picked elsewhere, restored from a draft, handed in by a link) is\n * switched back, and its card says so. Never a choice that cannot work.\n */\nexport function fitCardDeliveries(\n state: SourceSetState,\n deliveries: readonly SourceDelivery[] | undefined,\n): SourceSetState {\n let next = state;\n for (const card of state.cards) {\n const fit = fitDelivery(card.draft.ref, deliveries);\n if (!fit) continue;\n next = updateCardRef(next, card.id, fit.patch);\n const note = deliverySwitchedNote(fit.to);\n if (!card.draft.notes?.includes(note))\n next = updateCardDraft(next, card.id, { notes: [...(card.draft.notes ?? []), note] });\n }\n return next;\n}\n\n// ── Persistence (a draft store keeps this for a reload) ─────────────────────\n\n/** Read whatever a draft store handed back; anything malformed is dropped. */\nexport function readPersistedSourceInput(data: unknown): PersistedSourceInput {\n const record = data && typeof data === \"object\" ? (data as Record<string, unknown>) : undefined;\n const sources = Array.isArray(record?.sources)\n ? (record.sources as PersistedSourceCard[]).filter(\n (c) => !!c && typeof c.id === \"string\" && isSourceDraft(c.draft),\n )\n : [];\n return { sources, topic: typeof record?.topic === \"string\" ? record.topic : \"\" };\n}\n\nexport function toPersistedSourceInput(state: SourceSetState): PersistedSourceInput {\n return {\n sources: state.cards.map((c) => ({ id: c.id, draft: c.draft, status: c.status, error: c.error })),\n topic: state.topic,\n };\n}\n\n/**\n * The cards a reload brings back. A card cut off mid-landing becomes an error\n * the input resolves (it re-lands the kept input, or asks for the file again)\n * — never a spinner forever. A landing held for an organization lost its hold\n * with the page: it is picked up again like one cut off mid-landing.\n */\nexport function restoredCards(persisted: PersistedSourceInput): SourceCardModel[] {\n return persisted.sources.map((card) => {\n const reloaded = reloadedCard(\n card.draft,\n card.status === \"error\" && card.error === WAITING_FOR_ORGANIZATION ? \"resolving\" : card.status,\n );\n return {\n id: card.id,\n draft: card.draft,\n status: reloaded ? \"error\" : card.status,\n error: reloaded ? reloaded.sentence : (card.error ?? null),\n manifest: null,\n };\n });\n}\n\n// ── Selectors ───────────────────────────────────────────────────────────────\n\nexport function readySourceRefs(state: SourceSetState): SourceRef[] {\n return state.cards.flatMap((c) => (c.status === \"ready\" && c.draft.ref ? [c.draft.ref] : []));\n}\n\nexport function hasSourceRef(state: SourceSetState, resourceType: string, resourceId: string): boolean {\n return state.cards.some(\n (c) => c.draft.ref?.resource_type === resourceType && c.draft.ref.resource_id === resourceId,\n );\n}\n\n/** The frozen v1 payload, built from the ready Sources. */\nexport function selectSourceSet(\n state: SourceSetState,\n options: { targetModelId?: string | undefined } = {},\n): SourceSet {\n const topic = state.topic.trim();\n return createSourceSet(readySourceRefs(state), {\n topic: topic || undefined,\n grounding: \"whole\",\n target_model_id: options.targetModelId,\n });\n}\n\n/**\n * THE one size rule (the contract's `totalChars`): the chosen form, or the\n * picked parts, capped — measured against each card's CURRENT pointer.\n */\nexport function selectTotalChars(state: SourceSetState): number {\n const measured: SourceManifestEntry[] = state.cards.flatMap((c) =>\n c.status === \"ready\" && c.manifest && c.draft.ref ? [{ ...c.manifest, ref: c.draft.ref }] : [],\n );\n if (!measured.length) return 0;\n return sumChars({\n __kind: \"source_manifest\",\n sources: measured,\n total_chars: 0,\n estimated_tokens: 0,\n model_context_tokens: null,\n });\n}\n\n/**\n * THE one size of one Source (verify-3: one Source read 109k, 115k, 108k and\n * 106k on four screens): the contract's rule — the chosen form, or the picked\n * parts, capped by `max_chars` — measured against the card's CURRENT pointer.\n * The card, the header total (`selectTotalChars`) and the review (`SourcePlanEntry.chars`)\n * all read this. Null when it is not measured or cannot go in.\n */\nexport function sourceEntryChars(entry: SourceManifestEntry, ref: SourceRef): number | null {\n if (entry.state !== \"ready\" && entry.state !== \"processing\") return null;\n return sumChars({\n __kind: \"source_manifest\",\n sources: [{ ...entry, ref }],\n total_chars: 0,\n estimated_tokens: 0,\n model_context_tokens: null,\n });\n}\n\nexport function sourceCardChars(card: Pick<SourceCardModel, \"draft\" | \"manifest\">): number | null {\n return card.manifest && card.draft.ref ? sourceEntryChars(card.manifest, card.draft.ref) : null;\n}\n\n/**\n * THE one state of one Source card, derived once: its own lifecycle wins\n * (adding, waiting for an organization, failed); only a card that landed takes\n * the server's measured state. Never two states at once.\n */\nexport type SourceCardState =\n | \"adding\"\n | \"waiting_for_organization\"\n | \"failed\"\n | \"unmeasured\"\n | SourceManifestEntry[\"state\"];\n\nexport function sourceCardState(card: Pick<SourceCardModel, \"status\" | \"error\" | \"manifest\">): SourceCardState {\n if (card.status === \"pending\" || card.status === \"resolving\") return \"adding\";\n if (card.status === \"error\") return card.error === WAITING_FOR_ORGANIZATION ? \"waiting_for_organization\" : \"failed\";\n return card.manifest?.state ?? \"unmeasured\";\n}\n\n/** The server's measured state to show on a card — only for a card that landed (null otherwise). */\nexport function sourceCardMeasuredState(\n card: Pick<SourceCardModel, \"status\" | \"error\" | \"manifest\">,\n): SourceManifestEntry[\"state\"] | null {\n return card.status === \"ready\" ? (card.manifest?.state ?? null) : null;\n}\n\n/** Every Source finished landing (nothing pending) and none failed. */\nexport function selectSettled(state: SourceSetState): boolean {\n return state.cards.every((c) => c.status === \"ready\");\n}\n\n/** How many more Sources fit under the host's max (Infinity when there is none). */\nexport function sourceRoomLeft(state: SourceSetState, max: number | undefined): number {\n return max === undefined ? Number.POSITIVE_INFINITY : Math.max(0, max - state.cards.length);\n}\n\n/**\n * Every generator names a Source the way the person saw it on its card — the\n * file name, the name they gave pasted text — never the stored document's own\n * title (V2-F #5). The server's label stays only for a Source the input does\n * not hold.\n */\nexport function withDisplayNames(\n resolved: ResolvedSourceSet,\n cards: readonly Pick<SourceCardModel, \"draft\">[],\n): ResolvedSourceSet {\n const names = new Map<string, string>();\n for (const c of cards) {\n const label = c.draft.label?.trim();\n if (c.draft.ref && label) names.set(sourceKey(c.draft.ref), label);\n }\n return {\n ...resolved,\n sources: resolved.sources.map((s) => {\n const name = names.get(sourceKey(s.ref));\n return name ? { ...s, label: name } : s;\n }),\n };\n}\n","/**\n * THE PLANNER — one pure function shared by the preview and the result.\n *\n * The research context builder's discipline, generalised: the review shows a\n * number only if the returned `SourceSet` will carry exactly that. So the\n * screen, the budget verdict and the output all come from `planSourceReview`,\n * and nothing else does arithmetic.\n *\n * It mirrors the ONE server handler (aidream\n * `services/conversation_context/source_resolution.py`) rule for rule:\n * - chosen form = the ref's `representation`, else the manifest's `default_form`;\n * - picked parts (`include_segments`) replace the whole form;\n * - `max_chars` keeps whole parts in order until the next one would overflow\n * (`_cap`), cutting only a first part that is bigger than the cap by itself;\n * - the resolved text is the parts rendered as `### Chunk <id> (page N)` blocks\n * joined by a blank line (`render_grounded_chunk` / `_render`), so the count\n * here INCLUDES those headers and matches `POST /sources/resolve` exactly\n * whenever the manifest lists the parts;\n * - \"let the AI look it up\" (`delivery: \"context\"`) sends no text at all;\n * - Sources are budgeted in order and one that would overflow is left out,\n * while later, smaller ones may still go in.\n *\n * Budget tokens use the host's ONE estimator (`PlanInput.estimateTokens`;\n * default `estimateSourceTokens`, the same measured 2.9 chars per token as the\n * web app's `lib/tokens/estimate.ts`). The server uses the SAME measured\n * ratios since 2026-09-28 (aidream `CHARS_PER_TOKEN_MEASURED`), so the two\n * sides agree on what fits — and Sources the planner\n * leaves out are REMOVED from the returned set (named on screen first), so\n * the server never drops something the review showed as going in.\n */\n\nimport type {\n SourceManifest,\n SourceManifestEntry,\n SourceManifestSegment,\n SourceRef,\n SourceSet,\n} from \"../index\";\nimport { createSourceRef, createSourceSet } from \"../index\";\nimport { sourceDelivery } from \"./delivery\";\nimport { sourceEntryChars } from \"./state\";\nimport { estimateSourceTokens } from \"./tokens\";\n\n/** How close to the window counts as \"Getting heavy\" (the champion's 70%). */\nexport const HEAVY_SHARE = 0.7;\n\nexport type SourcePlanStatus =\n /** Its text goes in. */\n | \"included\"\n /** The AI looks it up on demand — no text is sent up front. */\n | \"on_demand\"\n /** Does not fit in what is left of the window — removed from the result. */\n | \"left_out\"\n /** Cannot be used at all (no access, missing, failed). Kept so the host can show it. */\n | \"unusable\";\n\nexport interface SourcePlanEntry {\n index: number;\n ref: SourceRef;\n entry: SourceManifestEntry;\n status: SourcePlanStatus;\n /** Label of the form in use. */\n formLabel: string;\n /** Characters of the chosen form before parts/cap. */\n formChars: number;\n /**\n * THE one size of this Source — the same number its card and the header show\n * (`sourceEntryChars`: the chosen form or picked parts, capped). What a person\n * sees; `sentChars` is only the budget's exact wire length.\n */\n chars: number;\n /** Characters the model receives for this Source (grounding headers included) — the budget's measure. */\n sentChars: number;\n sentTokens: number;\n /** True when parts are known, so `sentChars` is exact; false = the text body only. */\n exact: boolean;\n /** Number of parts that go in, when parts are known. */\n partsSent: number | null;\n partsTotal: number | null;\n /** The per-Source cap cut something. */\n capped: boolean;\n}\n\nexport type BudgetVerdict = \"empty\" | \"fine\" | \"heavy\" | \"too_much\";\n\nexport interface SourcePlan {\n entries: SourcePlanEntry[];\n /** THE one size of what goes in (sum of `chars` of the Sources whose text goes in) — shown to the person. */\n chars: number;\n /** The exact wire length the budget is judged on (grounding headers included). */\n sentChars: number;\n sentTokens: number;\n /** Window the verdict is judged against. */\n windowTokens: number;\n /** True when the window is the labelled default, not the model's own. */\n windowIsFallback: boolean;\n verdict: BudgetVerdict;\n /** Share of the window used, 0..∞. */\n share: number;\n leftOut: SourcePlanEntry[];\n /** Exactly what the review returns. */\n sourceSet: SourceSet;\n}\n\n// ---------------------------------------------------------------------------\n\nconst PAGE_SUFFIX = (page: number | undefined) =>\n page !== undefined && page > 0 ? ` (page ${page})` : \"\";\n\n/** Length of one rendered grounding block: `### Chunk <id>[ (page N)]\\n<text>`. */\nexport function renderedPartChars(\n segment: { id: string; page?: number | undefined },\n chars: number,\n): number {\n return `### Chunk ${segment.id}${PAGE_SUFFIX(segment.page)}`.length + 1 + chars;\n}\n\n/** The server's `_cap`: whole parts in order; only a lone first part is cut. */\nfunction capParts(\n parts: SourceManifestSegment[],\n maxChars: number | undefined,\n): { kept: Array<{ seg: SourceManifestSegment; chars: number }>; capped: boolean } {\n if (!maxChars) return { kept: parts.map((seg) => ({ seg, chars: seg.chars })), capped: false };\n const kept: Array<{ seg: SourceManifestSegment; chars: number }> = [];\n let used = 0;\n for (const seg of parts) {\n if (used + seg.chars <= maxChars) {\n kept.push({ seg, chars: seg.chars });\n used += seg.chars;\n continue;\n }\n const room = maxChars - used;\n if (room > 0 && kept.length === 0) kept.push({ seg, chars: room });\n return { kept, capped: true };\n }\n return { kept, capped: false };\n}\n\nexport function chosenForm(entry: SourceManifestEntry, ref: SourceRef) {\n const key = ref.representation ?? entry.default_form;\n return (\n entry.forms.find((f) => f.form === key) ??\n entry.forms.find((f) => f.form === entry.default_form) ??\n null\n );\n}\n\nfunction isUsable(entry: SourceManifestEntry): boolean {\n return entry.state === \"ready\" || entry.state === \"processing\";\n}\n\nfunction measure(entry: SourceManifestEntry, ref: SourceRef) {\n const form = chosenForm(entry, ref);\n const formChars = form?.chars ?? 0;\n const formLabel = form?.label ?? \"Text\";\n const segments = entry.segments ?? null;\n if (segments && segments.length > 0) {\n const wanted = ref.include_segments?.length ? new Set(ref.include_segments) : null;\n const chosen = wanted ? segments.filter((s) => wanted.has(s.id)) : segments;\n const { kept, capped } = capParts(chosen, ref.max_chars);\n const body = kept.reduce((sum, k) => sum + renderedPartChars(k.seg, k.chars), 0);\n const sentChars = kept.length ? body + 2 * (kept.length - 1) : 0;\n return {\n formChars,\n formLabel,\n sentChars,\n exact: true,\n partsSent: kept.length,\n partsTotal: segments.length,\n capped,\n };\n }\n const capped = ref.max_chars !== undefined && formChars > ref.max_chars;\n return {\n formChars,\n formLabel,\n sentChars: capped ? (ref.max_chars ?? formChars) : formChars,\n exact: false,\n partsSent: null,\n partsTotal: null,\n capped,\n };\n}\n\nexport interface PlanInput {\n manifest: SourceManifest;\n /** The person's current choices, index-aligned with `manifest.sources`. */\n refs: SourceRef[];\n /** The original set — carries topic / grounding / retrieve_query. */\n base: SourceSet;\n /** The model's window, or null when unknown. */\n modelWindowTokens: number | null;\n /** The labelled default used when the model is unknown. */\n fallbackWindowTokens: number;\n targetModelId?: string | undefined;\n /** The host's one token estimator (default: the measured `estimateSourceTokens`). */\n estimateTokens?: ((chars: number) => number) | undefined;\n}\n\nexport function planSourceReview(input: PlanInput): SourcePlan {\n const estimateTokens = input.estimateTokens ?? estimateSourceTokens;\n const windowIsFallback = !input.modelWindowTokens || input.modelWindowTokens <= 0;\n const windowTokens = windowIsFallback\n ? input.fallbackWindowTokens\n : (input.modelWindowTokens as number);\n\n let sentChars = 0;\n const entries: SourcePlanEntry[] = input.manifest.sources.map((entry, index) => {\n const ref = input.refs[index] ?? entry.ref;\n const m = measure(entry, ref);\n const base = { index, ref, entry, ...m, chars: sourceEntryChars(entry, ref) ?? 0 };\n if (!isUsable(entry)) {\n return { ...base, status: \"unusable\" as const, sentChars: 0, sentTokens: 0 };\n }\n if (sourceDelivery(ref) === \"context\") {\n return { ...base, status: \"on_demand\" as const, sentChars: 0, sentTokens: 0 };\n }\n if (estimateTokens(sentChars + m.sentChars) > windowTokens) {\n return { ...base, status: \"left_out\" as const, sentTokens: estimateTokens(m.sentChars) };\n }\n sentChars += m.sentChars;\n return { ...base, status: \"included\" as const, sentTokens: estimateTokens(m.sentChars) };\n });\n\n const sentTokens = estimateTokens(sentChars);\n const leftOut = entries.filter((e) => e.status === \"left_out\");\n const share = windowTokens > 0 ? sentTokens / windowTokens : 0;\n const anythingGoesIn = entries.some((e) => e.status === \"included\" || e.status === \"on_demand\");\n const verdict: BudgetVerdict = !anythingGoesIn && leftOut.length === 0\n ? \"empty\"\n : leftOut.length > 0\n ? \"too_much\"\n : share >= HEAVY_SHARE\n ? \"heavy\"\n : \"fine\";\n\n const kept = entries\n .filter((e) => e.status !== \"left_out\")\n .map((e) =>\n createSourceRef(e.ref.resource_type, e.ref.resource_id, {\n representation: e.ref.representation,\n include_segments: e.ref.include_segments,\n delivery: e.ref.delivery,\n max_chars: e.ref.max_chars,\n promote: e.ref.promote,\n exclude: e.ref.exclude,\n }),\n );\n const grounding =\n input.base.grounding === \"selected\" && !kept.some((r) => r.include_segments?.length)\n ? undefined\n : input.base.grounding;\n const sourceSet = createSourceSet(kept, {\n topic: input.base.topic,\n grounding,\n retrieve_query: input.base.retrieve_query,\n target_model_id: input.targetModelId ?? input.base.target_model_id,\n });\n\n return {\n entries,\n chars: entries.filter((e) => e.status === \"included\").reduce((sum, e) => sum + e.chars, 0),\n sentChars,\n sentTokens,\n windowTokens,\n windowIsFallback,\n verdict,\n share,\n leftOut,\n sourceSet,\n };\n}\n","/**\n * THE one client for the Source doors on the server (aidream\n * `api/routers/source_sets.py`):\n *\n * - `POST /sources/manifest` — sizes, states, forms and parts (never bodies);\n * - `POST /sources/resolve` — the full grounded text a generator reads;\n * - `POST /sources/parts/search` — the ids of one Source's parts that hold\n * every word of a query (the manifest's own part ids; never a body).\n *\n * All three are READS decided by access, never by the selected organization:\n * the server names them in `BODY_CARRIED_READS` (aidream `api/read_by_access.py`),\n * so every call goes out marked `bodyCarriedRead` — with an organization it is\n * still named, with none it is sent naming none instead of being refused on\n * the client (V1-A: \"Select an organization before sending this request\" was a\n * dead end the server never asked for).\n *\n * The TRANSPORT is injected: auth, base URL and error shape belong to the\n * host. A web app binds its typed API client; any other client can use\n * `createFetchSourcesTransport` below.\n */\n\nimport type { ResolvedSourceSet, SourceManifest, SourceRef, SourceSet } from \"../index\";\n\n/** Options every Source door call carries. */\nexport interface SourceCallOptions {\n organizationId?: string | undefined;\n signal?: AbortSignal | undefined;\n}\n\n/** What the transport receives: the call options plus the read marker. */\nexport interface SourceTransportOptions extends SourceCallOptions {\n /** Always true for the Source doors — send without requiring an organization. */\n bodyCarriedRead: true;\n}\n\n/** The server's answer to a part search. */\nexport interface SourcePartsSearchResult {\n segment_ids?: string[] | null | undefined;\n truncated?: boolean | null | undefined;\n /** Set when the Source cannot be searched (\"no_access\", …). */\n unavailable?: string | null | undefined;\n /** What happened and what to do, in the server's words. */\n detail?: string | null | undefined;\n}\n\n/** The three door paths, typed by body and answer. */\nexport interface SourceDoorCalls {\n \"/sources/manifest\": { body: { source_set: SourceSet }; answer: SourceManifest };\n \"/sources/resolve\": { body: { source_set: SourceSet }; answer: ResolvedSourceSet };\n \"/sources/parts/search\": {\n body: { source_ref: SourceRef; query: string };\n answer: SourcePartsSearchResult;\n };\n}\n\nexport type SourceDoorPath = keyof SourceDoorCalls;\n\n/** The host's way to POST to the server (auth + base URL + error shape are its own). */\nexport interface SourcesTransport {\n post<P extends SourceDoorPath>(\n path: P,\n body: SourceDoorCalls[P][\"body\"],\n options: SourceTransportOptions,\n ): Promise<SourceDoorCalls[P][\"answer\"]>;\n}\n\nexport interface SourcesClient {\n manifest(sourceSet: SourceSet, options?: SourceCallOptions): Promise<SourceManifest>;\n resolve(sourceSet: SourceSet, options?: SourceCallOptions): Promise<ResolvedSourceSet>;\n /** The ids of `ref`'s parts whose label or text holds every word of `query`. */\n searchParts(\n ref: SourceRef,\n query: string,\n options?: SourceCallOptions,\n ): Promise<SourcePartsSearchResult>;\n}\n\nfunction marked(options: SourceCallOptions | undefined): SourceTransportOptions {\n return {\n bodyCarriedRead: true,\n ...(options?.organizationId ? { organizationId: options.organizationId } : {}),\n ...(options?.signal ? { signal: options.signal } : {}),\n };\n}\n\nexport function createSourcesClient(transport: SourcesTransport): SourcesClient {\n return {\n manifest: (sourceSet, options) =>\n transport.post(\"/sources/manifest\", { source_set: sourceSet }, marked(options)),\n resolve: (sourceSet, options) =>\n transport.post(\"/sources/resolve\", { source_set: sourceSet }, marked(options)),\n searchParts: (ref, query, options) =>\n transport.post(\"/sources/parts/search\", { source_ref: ref, query }, marked(options)),\n };\n}\n\n/** Thrown by the fetch transport for a non-2xx answer — carries the server's words. */\nexport class SourceDoorError extends Error {\n readonly status: number;\n readonly body: unknown;\n constructor(status: number, message: string, body: unknown) {\n super(message);\n this.name = \"SourceDoorError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport interface FetchSourcesTransportOptions {\n /** The server's base URL (\"https://server.app.matrxserver.com\"). */\n baseUrl: string;\n /** Headers for each call — the host's auth (a bearer token) goes here. */\n headers?: (() => Record<string, string> | Promise<Record<string, string>>) | undefined;\n /** The header that names the organization (default \"X-Organization-Id\"). */\n organizationHeader?: string | undefined;\n fetch?: typeof fetch | undefined;\n}\n\nfunction refusalMessage(status: number, body: unknown): string {\n if (body && typeof body === \"object\") {\n const record = body as Record<string, unknown>;\n const error = record.error;\n if (error && typeof error === \"object\") {\n const message = (error as Record<string, unknown>).user_message ?? (error as Record<string, unknown>).message;\n if (typeof message === \"string\" && message) return message;\n }\n if (typeof record.detail === \"string\" && record.detail) return record.detail;\n }\n return `The server answered ${status}.`;\n}\n\n/** A plain `fetch` transport for clients without their own API layer. */\nexport function createFetchSourcesTransport(options: FetchSourcesTransportOptions): SourcesTransport {\n const base = options.baseUrl.replace(/\\/+$/, \"\");\n return {\n async post(path, body, call) {\n const doFetch = options.fetch ?? fetch;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers ? await options.headers() : {}),\n };\n if (call.organizationId) headers[options.organizationHeader ?? \"X-Organization-Id\"] = call.organizationId;\n const response = await doFetch(`${base}${path}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n ...(call.signal ? { signal: call.signal } : {}),\n });\n const text = await response.text();\n let parsed: unknown = null;\n try {\n parsed = text ? JSON.parse(text) : null;\n } catch {\n parsed = text;\n }\n if (!response.ok) throw new SourceDoorError(response.status, refusalMessage(response.status, parsed), parsed);\n return parsed as SourceDoorCalls[typeof path][\"answer\"];\n },\n };\n}\n","/**\n * The Source-set controller — the imperative face of the state machine, with\n * every outside dependency injected through one adapter:\n *\n * - `store` where the cards live (a Redux slice, a Zustand store, the\n * in-memory store below — the host's choice);\n * - `persistence` the draft store a reload reads back (optional);\n * - `client` the Source doors (`createSourcesClient(transport)`);\n * - `config` the host's choices: default form, organization, the\n * deliveries it can use, the most Sources it takes.\n *\n * Every screen (the Studio grid, a compact strip, chat's \"+\", the review)\n * drives the SAME controller; `@ai-matrx/agents/sources/react` binds it to\n * React with `useSourceSet(adapter)`.\n */\n\nimport {\n createSourceSet,\n type ResolvedSourceSet,\n type SourceManifest,\n type SourceRef,\n type SourceRefOptions,\n type SourceSet,\n} from \"../index\";\nimport type { SourcesClient } from \"./client\";\nimport type { SourceDelivery } from \"./delivery\";\nimport {\n addPendingCard,\n addReadyCard,\n applyManifest,\n applyReviewedSourceSet,\n EMPTY_SOURCE_SET_STATE,\n failCard,\n fitCardDeliveries,\n hasSourceRef,\n readPersistedSourceInput,\n readySourceRefs,\n removeCard,\n restartCard,\n restoredCards,\n selectSettled,\n selectSourceSet,\n selectTotalChars,\n setCardWaitForClean,\n setSourceTopic,\n settleCard,\n sourceRoomLeft,\n toPersistedSourceInput,\n updateCardDraft,\n updateCardRef,\n withDisplayNames,\n} from \"./state\";\nimport type { PersistedSourceInput, SourceCardModel, SourceDraft, SourceSetState } from \"./types\";\n\n/** Where the cards live. `getState` must return the SAME object until something changes. */\nexport interface SourceSetStore {\n getState(): SourceSetState;\n setState(next: SourceSetState): void;\n subscribe(listener: () => void): () => void;\n /** Called once when a screen mounts (a store that registers entries lazily). */\n init?: (() => void) | undefined;\n}\n\n/** The draft store a reload reads back. `load` returns the raw saved value (stable until it changes). */\nexport interface SourceDraftStorage {\n load(): unknown;\n save(value: PersistedSourceInput): void;\n subscribe?: ((listener: () => void) => () => void) | undefined;\n}\n\nexport interface SourceSetConfig {\n /** The form each new Source starts on (\"clean\" | \"raw\"). Omitted = the server's choice. */\n defaultForm?: string | undefined;\n /** The organization named on the door calls (they answer without one too). */\n organizationId?: string | null | undefined;\n /** How the AI may get the Sources on this surface. Omitted = both. */\n deliveries?: readonly SourceDelivery[] | undefined;\n /** Most Sources the person may pick. Omitted = no limit. */\n max?: number | undefined;\n}\n\nexport interface SourceSetAdapter {\n store: SourceSetStore;\n persistence?: SourceDraftStorage | undefined;\n /** Needed for `manifest()` and `resolve()`. */\n client?: SourcesClient | undefined;\n config?: SourceSetConfig | undefined;\n /** A new card's id (default: a random UUID). */\n createId?: (() => string) | undefined;\n /** A failed call as one sentence with its remedy (default: the error's message). */\n describeError?: ((error: unknown) => string) | undefined;\n}\n\n/** The measurement's own state (not persisted, not shared across controllers). */\nexport interface SourceSetMeta {\n measuring: boolean;\n /** Why the measurement failed, with its remedy. */\n manifestError: string | null;\n}\n\n/** The mutations every intake and screen drives. */\nexport interface SourceSetActions {\n /** Add a Source that is already a pointer (a stored record, a landed Source). */\n addReady(draft: SourceDraft): string;\n /** Add a Source that is still landing; finish it with `settle` or `fail`. */\n addPending(draft: Omit<SourceDraft, \"ref\">): string;\n settle(id: string, patch: Partial<SourceDraft> & { ref: SourceRef }): void;\n fail(id: string, sentence: string): void;\n /** Back to landing. False when the card is gone (removed) — nothing to land. */\n restart(id: string): boolean;\n /** Change what a card that is still landing says or keeps (label, input, fileId, notes). */\n updateDraft(id: string, patch: Partial<Omit<SourceDraft, \"ref\">>): void;\n remove(id: string): void;\n /** Change the pointer's choices (form, parts, cap, delivery). */\n updateRef(id: string, options: SourceRefOptions): void;\n setWaitForClean(id: string, wait: boolean): void;\n setTopic(topic: string): void;\n /** True when this pointer is already picked. */\n hasRef(resourceType: string, resourceId: string): boolean;\n /** How many Sources are picked RIGHT NOW (read from the store, never a stale render). */\n liveCount(): number;\n /** POST /sources/manifest for the ready Sources; cards update with it. */\n manifest(): Promise<SourceManifest | null>;\n}\n\nexport interface SourceSetController extends SourceSetActions {\n getState(): SourceSetState;\n subscribe(listener: () => void): () => void;\n getMeta(): SourceSetMeta;\n subscribeMeta(listener: () => void): () => void;\n /** Replace the host's choices (called on every render by a React binding). */\n configure(config: SourceSetConfig): void;\n readonly config: SourceSetConfig;\n /** Bring back a saved draft once — only into an empty input. True when it restored. */\n restore(saved: unknown): boolean;\n /** The frozen v1 payload, built from the ready Sources. */\n toSourceSet(options?: { targetModelId?: string | undefined }): SourceSet;\n /**\n * Apply a set the review returned (forms, parts, caps, delivery). Pass\n * `reviewed` — the set sent INTO the review — and every Source removed there\n * leaves the list too (only those; one that landed meanwhile stays).\n */\n applySourceSet(set: SourceSet, options?: { reviewed?: SourceSet | undefined }): void;\n /** POST /sources/resolve — the grounded text for a generator, named as the cards name them. */\n resolve(options?: { targetModelId?: string | undefined }): Promise<ResolvedSourceSet>;\n /** Switch back any Source set to a delivery the host cannot use (with a note). */\n fitDeliveries(deliveries?: readonly SourceDelivery[]): void;\n /** How many more Sources fit under the host's max. */\n roomLeft(): number;\n totalChars(): number;\n settled(): boolean;\n}\n\nfunction randomId(): string {\n const cryptoApi = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (cryptoApi?.randomUUID) return cryptoApi.randomUUID();\n return `src-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** An in-memory store — for clients without their own, and for tests. */\nexport function createMemorySourceSetStore(initial: SourceSetState = EMPTY_SOURCE_SET_STATE): SourceSetStore {\n let state = initial;\n const listeners = new Set<() => void>();\n return {\n getState: () => state,\n setState(next) {\n if (next === state) return;\n state = next;\n for (const listener of [...listeners]) listener();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\n/** An in-memory draft store (a stand-in for device storage in tests and previews). */\nexport function createMemorySourceDraftStorage(initial: unknown = undefined): SourceDraftStorage & {\n current(): unknown;\n} {\n let saved: unknown = initial;\n const listeners = new Set<() => void>();\n return {\n load: () => saved,\n save(value) {\n saved = value;\n for (const listener of [...listeners]) listener();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n current: () => saved,\n };\n}\n\nexport function createSourceSetController(adapter: SourceSetAdapter): SourceSetController {\n const { store, persistence } = adapter;\n let config: SourceSetConfig = { ...(adapter.config ?? {}) };\n const createId = adapter.createId ?? randomId;\n const describe = adapter.describeError ?? errorText;\n let meta: SourceSetMeta = { measuring: false, manifestError: null };\n const metaListeners = new Set<() => void>();\n let hydrated = false;\n /** The newest measurement wins: an older answer never overwrites a newer one. */\n let measurement: AbortController | null = null;\n\n const setMeta = (patch: Partial<SourceSetMeta>) => {\n const next = { ...meta, ...patch };\n if (next.measuring === meta.measuring && next.manifestError === meta.manifestError) return;\n meta = next;\n for (const listener of [...metaListeners]) listener();\n };\n\n /** Apply a reducer's result and write the draft (explicit persistence). */\n const commit = (next: SourceSetState) => {\n hydrated = true;\n if (next !== store.getState()) store.setState(next);\n persistence?.save(toPersistedSourceInput(store.getState()));\n };\n\n const has = (id: string) => store.getState().cards.some((c) => c.id === id);\n\n const controller: SourceSetController = {\n getState: () => store.getState(),\n subscribe: (listener) => store.subscribe(listener),\n getMeta: () => meta,\n subscribeMeta(listener) {\n metaListeners.add(listener);\n return () => metaListeners.delete(listener);\n },\n configure(next) {\n config = { ...next };\n },\n get config() {\n return config;\n },\n\n restore(saved) {\n if (hydrated) return false;\n const live = store.getState();\n if (live.cards.length > 0) {\n hydrated = true;\n return false;\n }\n const persisted = readPersistedSourceInput(saved);\n if (persisted.sources.length === 0) return false;\n hydrated = true;\n store.setState({ cards: restoredCards(persisted), topic: live.topic || persisted.topic });\n return true;\n },\n\n addReady(draft) {\n const id = createId();\n commit(addReadyCard(store.getState(), id, draft, { defaultForm: config.defaultForm }));\n return id;\n },\n addPending(draft) {\n const id = createId();\n commit(addPendingCard(store.getState(), id, draft));\n return id;\n },\n settle(id, patch) {\n if (!has(id)) return;\n commit(settleCard(store.getState(), id, patch, { defaultForm: config.defaultForm }));\n },\n fail(id, sentence) {\n if (!has(id)) return;\n commit(failCard(store.getState(), id, sentence));\n },\n restart(id) {\n if (!has(id)) return false;\n commit(restartCard(store.getState(), id));\n return true;\n },\n updateDraft(id, patch) {\n if (!has(id)) return;\n commit(updateCardDraft(store.getState(), id, patch));\n },\n remove(id) {\n commit(removeCard(store.getState(), id));\n },\n updateRef(id, options) {\n if (!store.getState().cards.find((c) => c.id === id)?.draft.ref) return;\n commit(updateCardRef(store.getState(), id, options));\n },\n setWaitForClean(id, wait) {\n if (!has(id)) return;\n commit(setCardWaitForClean(store.getState(), id, wait));\n },\n setTopic(topic) {\n commit(setSourceTopic(store.getState(), topic));\n },\n hasRef: (resourceType, resourceId) => hasSourceRef(store.getState(), resourceType, resourceId),\n liveCount: () => store.getState().cards.length,\n\n toSourceSet: (options = {}) => selectSourceSet(store.getState(), options),\n applySourceSet(set, options = {}) {\n commit(applyReviewedSourceSet(store.getState(), set, options.reviewed));\n },\n\n async manifest() {\n const refs = readySourceRefs(store.getState());\n if (refs.length === 0) {\n setMeta({ manifestError: null });\n return null;\n }\n if (!adapter.client) throw new Error(\"createSourceSetController: manifest() needs a client in the adapter\");\n measurement?.abort();\n const controllerForThis = new AbortController();\n measurement = controllerForThis;\n setMeta({ measuring: true });\n try {\n const result = await adapter.client.manifest(createSourceSet(refs), {\n organizationId: config.organizationId ?? undefined,\n signal: controllerForThis.signal,\n });\n if (measurement !== controllerForThis) return null;\n const next = applyManifest(store.getState(), result);\n if (next !== store.getState()) store.setState(next);\n setMeta({ manifestError: null });\n return result;\n } catch (err) {\n // A superseded measurement was cancelled on purpose — not a failure.\n if (measurement !== controllerForThis) return null;\n setMeta({\n manifestError: `Sizes and parts could not be read: ${describe(err)} Your picks are kept — try again.`,\n });\n return null;\n } finally {\n if (measurement === controllerForThis) setMeta({ measuring: false });\n }\n },\n\n async resolve(options = {}) {\n if (!adapter.client) throw new Error(\"createSourceSetController: resolve() needs a client in the adapter\");\n const resolved = await adapter.client.resolve(controller.toSourceSet(options), {\n organizationId: config.organizationId ?? undefined,\n });\n return withDisplayNames(resolved, store.getState().cards as SourceCardModel[]);\n },\n\n fitDeliveries(deliveries = config.deliveries) {\n const next = fitCardDeliveries(store.getState(), deliveries);\n if (next !== store.getState()) commit(next);\n },\n roomLeft: () => sourceRoomLeft(store.getState(), config.max),\n totalChars: () => selectTotalChars(store.getState()),\n settled: () => selectSettled(store.getState()),\n };\n return controller;\n}\n","/**\n * Source intake — every way NEW material becomes a Source, through the doors\n * that already exist on the server (DESIGN.md amendment A3). Each call adds a\n * card at once (so the person sees it working), then settles it to a pointer\n * or fails it with a sentence and a remedy. Nothing is ever sent onward as a\n * blob.\n *\n * pasted text → `POST /sources/land`, kept.\n * a web page → the host's scraper lands it (`addScrapedPage`), or a link\n * typed before a reload is scraped again (`addWebPage`);\n * `POST /sources/{id}/keep` files it against the thing being made.\n * a file/image → the host's uploader hands over file ids (`addUploaded`); the\n * file is filed against `attachTo` in the direction the\n * association registry declares, and its Source is kept once\n * reading makes one (`fileLanded`, driven by the recovery).\n * existing → a registry item (`addExisting`).\n * YouTube/audio → the transcript comes from the host's readers and lands\n * through `POST /sources/land`.\n *\n * Never lose input: every landing keeps what the person handed over in the\n * draft (`SourceDraft.input` — text, link, uploaded recording; never bytes)\n * until it settles, so `resume` can land it again after a reload, a failure,\n * or once an organization is chosen (the recovery replays every card waiting\n * for one — from state, never an in-memory queue). Landing twice is safe: the\n * door dedupes by (organization, identity, content hash).\n *\n * Every outside dependency is INJECTED (`SourceIntakeDeps`): the doors, the\n * organization gate, the signed-in person, the failure wording.\n */\n\nimport { isAssociationTargetType, isRegisteredPair } from \"@ai-matrx/associations\";\nimport { createSourceRef } from \"../index\";\nimport type { SourceSetActions } from \"./controller\";\nimport {\n KEEP_WAITING_FOR_ORGANIZATION,\n NOT_KEPT_FOR_RELOAD,\n WAITING_FOR_ORGANIZATION,\n resumableInput,\n} from \"./interrupted\";\nimport { draftKindForToken } from \"./state\";\nimport type { SourceAttachTo, SourceCardModel, SourceIntakeInput, SourceKindId } from \"./types\";\n\nconst TRANSCRIPT_NAME_MAX = 120;\n\n/** A door's notice: a sentence, and sometimes a remedy code (\"save_it…\"). */\nexport interface SourceLandingNotice {\n message: string;\n remedy?: string | null | undefined;\n}\n\n/** The target a door files a Source against (`attach_to`). */\nexport interface SourceAttachTarget {\n entity_type: string;\n entity_id: string;\n label: string | null;\n signal: boolean;\n}\n\n/** The part of a landing body the intake reads or sets — the rest is the host's door shape. */\nexport interface SourceLandingBodyBase {\n name: string;\n canonical_identity?: string | null | undefined;\n provenance?: Record<string, unknown> | null | undefined;\n}\n\n/** A landed (or kept) Source's answer. */\nexport interface SourceLandingAnswer {\n processed_document_id: string;\n notices?: SourceLandingNotice[] | null | undefined;\n}\n\n/** What the host's web reader returns for a link. Null = the page could not be read. */\nexport interface ScrapedSourcePage {\n processedDocumentId: string | null | undefined;\n sourceNotices: SourceLandingNotice[];\n pageTitle?: string | null | undefined;\n}\n\n/** What the host's YouTube reader returns. `source` = the server landed a timed transcript Source. */\nexport interface YouTubeTranscriptResult {\n text: string | null | undefined;\n note?: string | null | undefined;\n source?: { processed_document_id: string; title?: string | null | undefined } | null | undefined;\n}\n\n/** One file the host's uploader already uploaded. */\nexport interface UploadedSourceFile {\n fileId: string;\n name: string;\n}\n\n/** The association write (the host's one chokepoint). */\nexport interface SourceAssociationEdge {\n sourceType: string;\n sourceId: string;\n targetType: string;\n targetId: string;\n orgId: string;\n}\n\nexport type SourceAssociationResult = { ok: true } | { ok: false; error: { message: string } };\n\nexport interface SourceIntakeDoors<Body extends SourceLandingBodyBase = SourceLandingBodyBase> {\n /** `POST /sources/land` with the body as given (keep + attach_to set by the intake). */\n land(body: Body & { keep: true; attach_to: SourceAttachTarget[] }): Promise<SourceLandingAnswer>;\n /** `POST /sources/{id}/keep`, filed against the targets. */\n keep(\n processedDocumentId: string,\n options: { attachTo: SourceAttachTarget[]; organizationId: string },\n ): Promise<{ notices?: SourceLandingNotice[] | null | undefined }>;\n /** Build the landing body for text the person handed over. */\n buildTextLanding(input: {\n text: string;\n name?: string | undefined;\n organizationId: string;\n userId: string;\n }): Promise<Body>;\n /** Read a web page (the scraper lands it). Null = it could not be read. */\n scrapeUrl(url: string): Promise<ScrapedSourcePage | null>;\n /** Read a YouTube video's transcript. */\n fetchYouTubeTranscript(url: string): Promise<YouTubeTranscriptResult>;\n /** Write out a recording that is already stored. */\n transcribeFile(input: { fileId: string; organizationId: string }): Promise<{ text?: string | null | undefined }>;\n /** File one edge through the host's association chokepoint. */\n associate(edge: SourceAssociationEdge): Promise<SourceAssociationResult>;\n}\n\nexport interface SourceIntakeDeps<Body extends SourceLandingBodyBase = SourceLandingBodyBase> {\n doors: SourceIntakeDoors<Body>;\n /** The organization to land in — asks the person when none is chosen (the host's gate). */\n ensureOrganization(): Promise<string>;\n /** Run a landing the person asked for so the gate can carry the click intent. Default: run it. */\n holdIntent?: (<T>(run: () => Promise<T>) => Promise<T | undefined>) | undefined;\n /** True when a landing stopped only because no organization is chosen yet. */\n waitsForOrganization(error: unknown): boolean;\n /** A failed landing as one sentence with its remedy. */\n failureSentence(error: unknown): string;\n /** The signed-in person (null while sign-in is still loading). */\n userId(): string | null | undefined;\n /** The YouTube video id in a link, or null. */\n youtubeId(url: string): string | null | undefined;\n /** The largest pasted text kept in the draft for a reload (null = unknown — nothing kept). */\n maxKeptChars(): number | null;\n /** The thing being made — new Sources are filed against it and kept. */\n attachTo?: SourceAttachTo | undefined;\n}\n\nexport interface SourceIntake {\n addPastedText(text: string, name?: string): Promise<void>;\n addWebPage(url: string): Promise<void>;\n /**\n * A page the host's web picker already read (and the scraper landed); null id\n * = land its text instead. `pendingId` = the card `beginWebPage` made when the\n * read started — it is settled instead of a new card being added.\n */\n addScrapedPage(\n page: { url: string; title: string; text: string; processedDocumentId: string | null },\n pendingId?: string | null,\n ): Promise<void>;\n /**\n * The host's web picker STARTED reading a link: a card with the link kept\n * appears at once, so a reload mid-read brings it back and lands it (verify-3\n * 12a/12b: a reload while a page was read lost it, link and all). Finish it\n * with `addScrapedPage(page, id)`; if the person drops the preview, remove it;\n * if the picker goes away mid-read, `resume(card)` lands it through the web door.\n */\n beginWebPage(url: string): string;\n /** Files the host's uploader already uploaded. */\n addUploaded(files: readonly UploadedSourceFile[], kind: SourceKindId): Promise<void>;\n /**\n * A recording made in place (the Voice Pad) that is already written out: it\n * lands as text, but it IS a recording — its card and review say \"Recording\",\n * never \"Pasted text\" — and it keeps its name (\"Recording 3:41 PM\").\n */\n addRecordedText(text: string, name?: string): Promise<void>;\n /** A recording already uploaded — written out, then landed. */\n addUploadedRecording(file: UploadedSourceFile): Promise<void>;\n /** Something the person already has (Use existing / search). Returns false when already picked. */\n addExisting(item: { token: string; id: string; title: string }): boolean;\n addYouTube(url: string): Promise<void>;\n /** Land a card's kept input again (after a reload or a failure). False when nothing was kept. */\n resume(card: SourceCardModel): boolean;\n /** The person chose the file again (uploaded) for a card whose upload was cut off. */\n retryFile(card: SourceCardModel, file: UploadedSourceFile): Promise<void>;\n /** Reading an uploaded file made its Source: keep it and file it against `attachTo`. */\n fileLanded(card: SourceCardModel, processedDocumentId: string): Promise<void>;\n}\n\nexport function sourceAttachTargets(attachTo: SourceAttachTo | undefined): SourceAttachTarget[] {\n return attachTo\n ? [\n {\n entity_type: attachTo.entityType,\n entity_id: attachTo.entityId,\n // The EDGE's label, which the registry names (a deck's Source is its\n // \"source\", a scope's is \"about\") — never the target's display name,\n // which the door refused as an unknown label (USI-3e).\n label: null,\n signal: true,\n },\n ]\n : [];\n}\n\nfunction hostOf(url: string): string {\n try {\n return new URL(url).hostname.replace(/^www\\./, \"\");\n } catch {\n return url;\n }\n}\n\n/** A notice that asks the person to save (keep) the Source — moot once it is kept. */\nfunction isSaveItNotice(remedy: string | null | undefined): boolean {\n return typeof remedy === \"string\" && remedy.startsWith(\"save_it\");\n}\n\nfunction landedNotes(notices: readonly SourceLandingNotice[] | null | undefined): string[] {\n return (notices ?? []).map((n) => n.message).filter(Boolean);\n}\n\n/**\n * Which way a file ↔ `targetType` edge is registered — read from the package's\n * generated association registry (`@ai-matrx/associations`) — or null when it\n * is not registered.\n */\nexport function registeredFileEdge(targetType: string): \"file_to_target\" | \"target_to_file\" | null {\n if (isRegisteredPair(\"file\", targetType)) return \"file_to_target\";\n if (isRegisteredPair(targetType, \"file\")) return \"target_to_file\";\n return null;\n}\n\nexport function createSourceIntake<Body extends SourceLandingBodyBase>(\n set: SourceSetActions,\n deps: SourceIntakeDeps<Body>,\n): SourceIntake {\n const { doors } = deps;\n const attachTo = sourceAttachTargets(deps.attachTo);\n const hold = <T>(run: () => Promise<T>): Promise<T | undefined> =>\n deps.holdIntent ? deps.holdIntent(run) : run();\n const notFiledSuffix = attachTo.length ? \" or filed with what you are making\" : \"\";\n\n /**\n * Fail the card — or, when only the organization is missing, say it is\n * waiting. The card's kept input is its replay: the recovery lands it again\n * the moment an organization is set (state, not a queue).\n */\n const failOrHold = (id: string, err: unknown) => {\n set.fail(id, deps.waitsForOrganization(err) ? WAITING_FOR_ORGANIZATION : deps.failureSentence(err));\n };\n\n const needUser = (): string => {\n const userId = deps.userId();\n if (!userId) throw new Error(\"Your sign-in is still loading, so nothing was added. Try again in a moment.\");\n return userId;\n };\n\n /** Land text through the door as a kept Source; returns the settle patch. */\n const landText = async (body: Body): Promise<{ id: string; notes: string[] }> => {\n const landed = await doors.land({ ...body, keep: true, attach_to: attachTo });\n return { id: landed.processed_document_id, notes: landedNotes(landed.notices) };\n };\n\n const landPaste = async (id: string, trimmed: string, name?: string) => {\n try {\n const organizationId = await deps.ensureOrganization();\n const body = await doors.buildTextLanding({ text: trimmed, name, organizationId, userId: needUser() });\n const landed = await landText(body);\n set.settle(id, {\n label: body.name,\n ref: createSourceRef(\"processed_document\", landed.id),\n processedDocumentId: landed.id,\n notes: landed.notes,\n });\n } catch (err) {\n failOrHold(id, err);\n }\n };\n\n const landWebPage = async (id: string, url: string) => {\n try {\n const organizationId = await deps.ensureOrganization();\n const result = await doors.scrapeUrl(url);\n if (!result) {\n set.fail(\n id,\n \"That page could not be read — it may need a sign-in or block robots. Try another link, or copy the text and use Paste text.\",\n );\n return;\n }\n if (!result.processedDocumentId) {\n set.fail(\n id,\n result.sourceNotices[0]?.message ??\n \"The page was read but did not become a Source, and the server did not say why. Try again.\",\n );\n return;\n }\n // A Source picked for real work is kept (A3): its clean → segment →\n // embed is queued, and it is filed against the thing being made. Once\n // kept, the capture's \"not saved — save it\" notices are no longer true;\n // the keep's own notices replace them.\n let notes: string[];\n try {\n const kept = await doors.keep(result.processedDocumentId, { attachTo, organizationId });\n notes = [\n ...landedNotes(result.sourceNotices.filter((n) => !isSaveItNotice(n.remedy))),\n ...landedNotes(kept.notices),\n ];\n } catch (err) {\n notes = [\n ...landedNotes(result.sourceNotices),\n `It is in your Sources, but it could not be kept for reuse${notFiledSuffix}: ${deps.failureSentence(err)}`,\n ];\n }\n set.settle(id, {\n label: result.pageTitle || hostOf(url),\n ref: createSourceRef(\"processed_document\", result.processedDocumentId),\n processedDocumentId: result.processedDocumentId,\n notes,\n });\n } catch (err) {\n failOrHold(id, err);\n }\n };\n\n const landYouTube = async (id: string, url: string, videoId: string) => {\n try {\n const organizationId = await deps.ensureOrganization();\n const { text, note, source } = await doors.fetchYouTubeTranscript(url);\n if (!text) {\n set.fail(\n id,\n note ??\n \"That video has no speech we could write out (no captions and no clear voice). Try another video, or paste a transcript.\",\n );\n return;\n }\n if (source) {\n // The server landed the timed transcript through the door: the card IS\n // that transcript Source, and \"Choose parts\" lists its timed segments.\n const label = `YouTube — ${source.title || videoId}`.slice(0, TRANSCRIPT_NAME_MAX);\n let notes: string[] = [];\n try {\n const kept = await doors.keep(source.processed_document_id, { attachTo, organizationId });\n notes = landedNotes(kept.notices);\n } catch (err) {\n notes = [\n `It was read, but its Source could not be kept for reuse${notFiledSuffix}: ${deps.failureSentence(err)}`,\n ];\n }\n set.settle(id, {\n label,\n ref: createSourceRef(\"processed_document\", source.processed_document_id),\n processedDocumentId: source.processed_document_id,\n notes,\n });\n return;\n }\n const name = `YouTube — ${text.split(/\\s+/).slice(0, 10).join(\" \")}…`.slice(0, TRANSCRIPT_NAME_MAX);\n const body = await doors.buildTextLanding({ text, name, organizationId, userId: needUser() });\n const landed = await landText({\n ...body,\n // Identity is the video, so the same video twice is one Source.\n canonical_identity: `youtube:${videoId}`,\n provenance: { ...(body.provenance ?? {}), origin_client: \"youtube\", capture_method: \"captions\", final_url: url },\n });\n set.settle(id, {\n label: name,\n ref: createSourceRef(\"processed_document\", landed.id),\n processedDocumentId: landed.id,\n // Untimed: say why it has no parts to choose (the server's own sentence).\n notes: note ? [...landed.notes, note] : landed.notes,\n });\n } catch (err) {\n failOrHold(id, err);\n }\n };\n\n /**\n * File the uploaded file against the thing being made — the ONE associations\n * chokepoint, in the direction the registry declares (`fc_set → file`, but\n * `file → task`); writing it backwards is refused (USI-3e). Returns a note\n * when it could not be filed; the upload itself stands.\n */\n const fileAgainstTarget = async (fileId: string, organizationId: string): Promise<string | null> => {\n const target = deps.attachTo;\n if (!target) return null;\n const what = target.label ? `\"${target.label}\"` : \"what you are making\";\n const direction = registeredFileEdge(target.entityType);\n const cannot = `It was uploaded, but a file cannot be filed with ${what} (a ${target.entityType.replace(/_/g, \" \")}), so it is not listed there.`;\n if (!direction) return cannot;\n if (direction === \"file_to_target\" && !isAssociationTargetType(target.entityType)) return cannot;\n const linked = await doors.associate(\n direction === \"file_to_target\"\n ? {\n sourceType: \"file\",\n sourceId: fileId,\n targetType: target.entityType,\n targetId: target.entityId,\n orgId: organizationId,\n }\n : {\n sourceType: target.entityType,\n sourceId: target.entityId,\n targetType: \"file\",\n targetId: fileId,\n orgId: organizationId,\n },\n );\n return linked.ok ? null : `It was uploaded, but it could not be filed with ${what}: ${linked.error.message}`;\n };\n\n const fileNotes = async (fileId: string): Promise<string[]> => {\n try {\n const organizationId = await deps.ensureOrganization();\n const filed = await fileAgainstTarget(fileId, organizationId);\n return filed ? [filed] : [];\n } catch (err) {\n return deps.waitsForOrganization(err)\n ? []\n : [`It was uploaded, but it could not be filed: ${deps.failureSentence(err)}`];\n }\n };\n\n const transcribeRecording = async (id: string, fileId: string, fileName: string) => {\n try {\n const organizationId = await deps.ensureOrganization();\n const transcription = await doors.transcribeFile({ fileId, organizationId });\n const text = (transcription.text ?? \"\").trim();\n if (text.length < 8) {\n set.fail(\n id,\n \"We couldn't hear enough speech in that recording to write it out. Try a recording with a clear voice.\",\n );\n return;\n }\n const name = `Recording — ${fileName}`.slice(0, TRANSCRIPT_NAME_MAX);\n const body = await doors.buildTextLanding({ text, name, organizationId, userId: needUser() });\n const landed = await landText({\n ...body,\n canonical_identity: `audio-transcript:${fileId}`,\n provenance: { ...(body.provenance ?? {}), origin_client: \"transcription\", capture_method: \"speech\" },\n });\n set.settle(id, {\n label: name,\n ref: createSourceRef(\"processed_document\", landed.id),\n processedDocumentId: landed.id,\n fileId,\n notes: landed.notes,\n });\n } catch (err) {\n failOrHold(id, err);\n }\n };\n\n const intake: SourceIntake = {\n async addPastedText(text, name) {\n const trimmed = text.trim();\n if (!trimmed) return;\n const max = deps.maxKeptChars();\n const kept = max !== null && trimmed.length <= max;\n const id = set.addPending({\n kind: \"paste\",\n label: name?.trim() || \"Pasted text\",\n input: kept ? { text: trimmed, name } : undefined,\n notes: kept ? undefined : [NOT_KEPT_FOR_RELOAD],\n });\n await hold(() => landPaste(id, trimmed, name));\n },\n\n async addRecordedText(text, name) {\n const trimmed = text.trim();\n if (!trimmed) return;\n const max = deps.maxKeptChars();\n const kept = max !== null && trimmed.length <= max;\n const id = set.addPending({\n kind: \"audio\",\n label: name?.trim() || \"Recording\",\n origin: \"Recording\",\n input: kept ? { text: trimmed, name } : undefined,\n notes: kept ? undefined : [NOT_KEPT_FOR_RELOAD],\n });\n await hold(() => landPaste(id, trimmed, name));\n },\n\n async addWebPage(raw) {\n const url = /^https?:\\/\\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;\n const id = set.addPending({ kind: \"web\", label: hostOf(url), origin: url, input: { url } });\n await hold(() => landWebPage(id, url));\n },\n\n beginWebPage(raw) {\n const url = /^https?:\\/\\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;\n return set.addPending({ kind: \"web\", label: hostOf(url), origin: url, input: { url } });\n },\n\n async addScrapedPage(page, pendingId) {\n const label = page.title || hostOf(page.url);\n const cardFor = () => {\n if (pendingId && set.restart(pendingId)) {\n set.updateDraft(pendingId, { label, origin: page.url, input: { url: page.url } });\n return pendingId;\n }\n return set.addPending({ kind: \"web\", label, origin: page.url, input: { url: page.url } });\n };\n if (!page.processedDocumentId) {\n // The scrape did not land a Source (or the person edited the text): land what they confirmed.\n const id = cardFor();\n await hold(() => landPaste(id, page.text, label));\n return;\n }\n const pdId = page.processedDocumentId;\n const id = cardFor();\n await hold(async () => {\n let notes: string[] = [];\n try {\n const organizationId = await deps.ensureOrganization();\n const kept = await doors.keep(pdId, { attachTo, organizationId });\n notes = landedNotes(kept.notices);\n } catch (err) {\n notes = deps.waitsForOrganization(err)\n ? [KEEP_WAITING_FOR_ORGANIZATION]\n : [`It is in your Sources, but it could not be kept for reuse${notFiledSuffix}: ${deps.failureSentence(err)}`];\n }\n set.settle(id, {\n label,\n ref: createSourceRef(\"processed_document\", pdId),\n processedDocumentId: pdId,\n notes,\n });\n });\n },\n\n async addUploaded(files, kind) {\n for (const file of files) {\n if (set.hasRef(\"file\", file.fileId)) continue;\n const id = set.addPending({ kind, label: file.name, origin: \"Uploaded file\", fileId: file.fileId });\n const notes = await fileNotes(file.fileId);\n // The Source itself is kept and filed by the recovery from the server's state.\n set.settle(id, { label: file.name, ref: createSourceRef(\"file\", file.fileId), fileId: file.fileId, notes });\n }\n },\n\n async addUploadedRecording(file) {\n const id = set.addPending({\n kind: \"audio\",\n label: file.name,\n origin: \"Recording\",\n fileId: file.fileId,\n input: { fileId: file.fileId },\n });\n await hold(() => transcribeRecording(id, file.fileId, file.name));\n },\n\n addExisting(item) {\n if (set.hasRef(item.token, item.id)) return false;\n set.addReady({\n kind: draftKindForToken(item.token),\n label: item.title,\n ref: createSourceRef(item.token, item.id),\n fileId: item.token === \"file\" ? item.id : undefined,\n processedDocumentId: item.token === \"processed_document\" ? item.id : undefined,\n });\n return true;\n },\n\n async addYouTube(raw) {\n const url = raw.trim();\n const videoId = deps.youtubeId(url);\n if (!videoId) return;\n const id = set.addPending({ kind: \"youtube\", label: \"YouTube video\", origin: url, input: { url } });\n await hold(() => landYouTube(id, url, videoId));\n },\n\n resume(card) {\n const input: SourceIntakeInput | null = resumableInput(card.draft);\n if (!input) return false;\n set.restart(card.id);\n switch (card.draft.kind) {\n case \"paste\":\n void landPaste(card.id, (input.text ?? \"\").trim(), input.name);\n return true;\n case \"web\":\n void landWebPage(card.id, input.url ?? \"\");\n return true;\n case \"youtube\": {\n const videoId = deps.youtubeId(input.url ?? \"\");\n if (!videoId) {\n set.fail(card.id, \"That link is not a YouTube video any more. Remove it and paste the link again.\");\n return true;\n }\n void landYouTube(card.id, input.url ?? \"\", videoId);\n return true;\n }\n case \"audio\":\n if (input.fileId) void transcribeRecording(card.id, input.fileId, card.draft.label);\n else void landPaste(card.id, (input.text ?? \"\").trim(), input.name);\n return true;\n default:\n return false;\n }\n },\n\n async retryFile(card, file) {\n set.restart(card.id);\n set.updateDraft(card.id, { label: file.name, fileId: file.fileId });\n if (card.draft.kind === \"audio\") {\n set.updateDraft(card.id, { input: { fileId: file.fileId } });\n await hold(() => transcribeRecording(card.id, file.fileId, file.name));\n return;\n }\n const notes = await fileNotes(file.fileId);\n set.settle(card.id, { label: file.name, ref: createSourceRef(\"file\", file.fileId), fileId: file.fileId, notes });\n },\n\n async fileLanded(card, processedDocumentId) {\n // Every card opens its Source from now on (and a held keep's waiting note goes).\n const notes = (card.draft.notes ?? []).filter((n) => n !== KEEP_WAITING_FOR_ORGANIZATION);\n set.updateDraft(card.id, { processedDocumentId, notes });\n try {\n const organizationId = await deps.ensureOrganization();\n await doors.keep(processedDocumentId, { attachTo, organizationId });\n } catch (err) {\n if (deps.waitsForOrganization(err)) {\n // Kept again by the recovery once an organization is set.\n set.updateDraft(card.id, { processedDocumentId, notes: [...notes, KEEP_WAITING_FOR_ORGANIZATION] });\n return;\n }\n set.updateDraft(card.id, {\n processedDocumentId,\n notes: [\n ...notes,\n `It was read, but its Source could not be kept for reuse${notFiledSuffix}: ${deps.failureSentence(err)}`,\n ],\n });\n }\n },\n };\n return intake;\n}\n","/**\n * Recovery — the UI-free half of \"never lose input\" (USI-3b), as decisions and\n * one step function. A React binding (`@ai-matrx/agents/sources/react`\n * `useSourceRecovery`) schedules them; any other client can call them itself.\n *\n * 1. A Source a reload cut off while it was landing, whose input the draft\n * kept (`interrupted.ts`), is handed back to the door once — the door\n * dedupes by content hash, so a second landing reuses the same Source.\n * 2. A landing that waited for an organization is landed again the moment one\n * is set — from the card's kept input, or, for a read Source whose keep\n * waited, by keeping it again. State, never an in-memory queue.\n * 3. A stored file's Source (new upload, reused copy, or picked file) is read\n * from the SERVER's state (`fileSource.ts`): kept and filed once it exists,\n * the one run started only when nothing is reading it, re-attached after a\n * reload — never a duplicate run.\n *\n * The once-per-card guards live on `globalThis` (one registry however many\n * loader graphs import this module), so two inputs on one surface, or a\n * re-mount, never land the same card twice.\n */\n\nimport type { SourceSetActions } from \"./controller\";\nimport {\n fileCardHeldForOrganization,\n isWaitingFileCard,\n nextFileStep,\n type FileSourceStatus,\n} from \"./fileSource\";\nimport type { SourceIntake } from \"./intake\";\nimport { KEEP_WAITING_FOR_ORGANIZATION, RELOADED_RESUMING, WAITING_FOR_ORGANIZATION } from \"./interrupted\";\nimport type { SourceCardModel } from \"./types\";\n\ninterface RecoveryGuards {\n resumedCards: Set<string>;\n keptFileSources: Set<string>;\n startedFileRuns: Set<string>;\n}\n\n// Module-level state is banned in our packages (dual ESM/CJS graphs would\n// split it): the guards live on globalThis under one registered symbol.\nconst GUARDS = Symbol.for(\"ai-matrx.agents.sources.recovery-guards\");\n\nexport function sourceRecoveryGuards(): RecoveryGuards {\n const slot = globalThis as unknown as Record<symbol, RecoveryGuards | undefined>;\n let guards = slot[GUARDS];\n if (!guards) {\n guards = { resumedCards: new Set(), keptFileSources: new Set(), startedFileRuns: new Set() };\n slot[GUARDS] = guards;\n }\n return guards;\n}\n\n/** Cards a reload cut off whose kept input lands again now. */\nexport function cardsToResume(cards: readonly SourceCardModel[]): SourceCardModel[] {\n return cards.filter((c) => c.status === \"error\" && c.error === RELOADED_RESUMING);\n}\n\n/** Resume each cut-off card once (per card id, across every input). */\nexport function resumeInterrupted(cards: readonly SourceCardModel[], intake: Pick<SourceIntake, \"resume\">): void {\n const { resumedCards } = sourceRecoveryGuards();\n for (const card of cardsToResume(cards)) {\n if (resumedCards.has(card.id)) continue;\n resumedCards.add(card.id);\n intake.resume(card);\n }\n}\n\n/** Cards that waited for an organization (a landing, or a read Source's keep). */\nexport function cardsWaitingForOrganization(cards: readonly SourceCardModel[]): SourceCardModel[] {\n return cards.filter(\n (s) =>\n (s.status === \"error\" && s.error === WAITING_FOR_ORGANIZATION) ||\n (!!s.draft.processedDocumentId && !!s.draft.notes?.includes(KEEP_WAITING_FOR_ORGANIZATION)),\n );\n}\n\n/** An organization is known now: land or keep every card that waited for one. */\nexport function continueAfterOrganization(\n cards: readonly SourceCardModel[],\n intake: Pick<SourceIntake, \"resume\" | \"fileLanded\">,\n): void {\n for (const card of cards) {\n if (card.status === \"error\" && card.error === WAITING_FOR_ORGANIZATION) {\n intake.resume(card);\n } else if (card.draft.processedDocumentId && card.draft.notes?.includes(KEEP_WAITING_FOR_ORGANIZATION)) {\n void intake.fileLanded(card, card.draft.processedDocumentId);\n }\n }\n}\n\n/** The host's processing runner, as far as the recovery needs it. */\nexport interface SourceFileRunner {\n jobs: ReadonlyArray<{ cldFileId?: string | null | undefined; status: string; processedDocumentId?: string | null | undefined }>;\n runForCldFile(fileId: string, label: string, reason: string): Promise<unknown>;\n}\n\nexport interface FileRecoveryDeps {\n /** The organization the person picked (null = none yet). */\n organizationId: string | null | undefined;\n /** The server's `/files/{id}/rag-status` read. */\n readFileState(fileId: string, signal?: AbortSignal): Promise<FileSourceStatus>;\n /** The host's lookup of a file's own organization (omitted = unknown). */\n fileOrganizationId?: ((fileId: string) => string | null | undefined) | undefined;\n}\n\n/** A file card the recovery may ask about now (waiting, and not held for an organization). */\nexport function isAskableFileCard(card: SourceCardModel, deps: Pick<FileRecoveryDeps, \"organizationId\" | \"fileOrganizationId\">): boolean {\n return isWaitingFileCard(card) && !fileCardHeldForOrganization(card, deps.organizationId, deps.fileOrganizationId);\n}\n\n/**\n * One look at every askable file card: a Source → keep and file it; a live run\n * → look again; nothing reading it → start the one run (once); unreadable →\n * say so. Returns true while any card still waits (look again later).\n */\nexport async function lookAtFileCards(\n cards: readonly SourceCardModel[],\n ctx: {\n set: Pick<SourceSetActions, \"fail\" | \"manifest\">;\n intake: Pick<SourceIntake, \"fileLanded\">;\n runner: SourceFileRunner;\n signal: AbortSignal;\n } & FileRecoveryDeps,\n): Promise<boolean> {\n const { keptFileSources, startedFileRuns } = sourceRecoveryGuards();\n let anyWaiting = false;\n for (const card of cards.filter((c) => isAskableFileCard(c, ctx))) {\n const fileId = card.draft.fileId as string;\n const guard = `${card.id}:${fileId}`;\n if (keptFileSources.has(guard)) continue;\n let status: FileSourceStatus | null = null;\n try {\n status = await ctx.readFileState(fileId, ctx.signal);\n } catch {\n // A missed read is not an answer — look again next round.\n if (ctx.signal.aborted) return false;\n anyWaiting = true;\n continue;\n }\n if (ctx.signal.aborted) return false;\n const localJob = ctx.runner.jobs.find((j) => j.cldFileId === fileId) ?? null;\n const step = nextFileStep(status, {\n started: startedFileRuns.has(guard),\n localRunning: localJob?.status === \"running\",\n });\n const localPdId = localJob?.processedDocumentId ?? null;\n if (step.do === \"keep\" || localPdId) {\n keptFileSources.add(guard);\n const pdId = step.do === \"keep\" ? step.processedDocumentId : (localPdId as string);\n await ctx.intake.fileLanded(card, pdId);\n // The pointer did not change, so nothing else re-measures: ask once now.\n void ctx.set.manifest();\n } else if (step.do === \"start\") {\n startedFileRuns.add(guard);\n anyWaiting = true;\n void ctx.runner.runForCldFile(fileId, card.draft.label, \"Reading it into a Source\").catch(() => undefined);\n } else if (step.do === \"unreadable\") {\n keptFileSources.add(guard);\n ctx.set.fail(card.id, step.reason);\n } else {\n anyWaiting = true;\n }\n }\n return anyWaiting;\n}\n"],"mappings":"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","names":["capped","id"]}
1
+ {"version":3,"sources":["../../../sources/runtime/index.ts","../../../sources/runtime/delivery.ts","../../../sources/runtime/partsSearch.ts","../../../sources/runtime/interrupted.ts","../../../sources/runtime/fileSource.ts","../../../sources/runtime/tokens.ts","../../../sources/index.ts","../../../sources/runtime/state.ts","../../../sources/runtime/plan.ts","../../../sources/runtime/client.ts","../../../sources/runtime/controller.ts","../../../sources/runtime/intake.ts","../../../sources/runtime/recovery.ts"],"sourcesContent":["/**\n * `@ai-matrx/agents/sources/runtime` — the UI-free core of the one Source\n * input: pure TypeScript, no React, no framework, no store library.\n *\n * - state the source-list state machine (reducers + selectors),\n * persistence helpers, display names;\n * - controller the imperative face over an injected store, draft storage,\n * client and host config (`createSourceSetController`);\n * - intake every landing door, with every dependency injected\n * (`createSourceIntake`);\n * - recovery re-land what a reload cut off, continue after an\n * organization is chosen, follow stored files' Sources;\n * - plan THE review planner shared by the preview and the run;\n * - client the manifest / resolve / parts-search doors over an\n * injected transport;\n * - delivery, partsSearch, interrupted, fileSource — the pure rules.\n *\n * Screens bind it through `@ai-matrx/agents/sources/react`.\n * Contract of record: common-docs `projects/unified-source-input/DESIGN.md`.\n */\n\nexport * from \"./types\";\nexport * from \"./delivery\";\nexport * from \"./partsSearch\";\nexport * from \"./interrupted\";\nexport * from \"./fileSource\";\nexport * from \"./tokens\";\nexport * from \"./plan\";\nexport * from \"./client\";\nexport * from \"./state\";\nexport * from \"./controller\";\nexport * from \"./intake\";\nexport * from \"./recovery\";\n","/**\n * How the AI gets a Source — THE one source of truth for delivery.\n *\n * The frozen contract (`SourceRef.delivery`, `@ai-matrx/agents/sources`) has\n * two values and a default: absent / \"direct\" = the text is handed to the AI\n * with the request; \"context\" = nothing is sent up front and the AI opens the\n * Source while it works. The server (aidream `source_resolution.py`) reads\n * exactly this field and nothing else — `promote` / `exclude` are NOT read on\n * the Source path.\n *\n * Every screen that shows or changes delivery (the Source card, \"Review what\n * goes in\", the planner) reads it through `sourceDelivery` and says it with\n * `DELIVERY_WORDS`, so a card can never say one thing while the review and the\n * request say another (V1-A: the card said \"Nothing is copied in\" — chat's\n * attachment editor's wording — while the review said \"Include the text\" and\n * the request carried the text).\n */\n\nimport type { SourceDelivery, SourceRef, SourceRefOptions } from \"../index\";\n\nexport type { SourceDelivery };\n\n/** The delivery a pointer asks for — absent means the contract default, \"direct\". */\nexport function sourceDelivery(ref: Pick<SourceRef, \"delivery\"> | null | undefined): SourceDelivery {\n return ref?.delivery === \"context\" ? \"context\" : \"direct\";\n}\n\n/**\n * The patch that sets a delivery. \"direct\" is the default, so it clears the\n * field (the wire stays minimal, exactly as the review has always written it).\n * Looking a Source up sends no text, so parts and a size limit no longer apply.\n */\nexport function deliveryPatch(\n delivery: SourceDelivery,\n): Pick<SourceRefOptions, \"delivery\" | \"include_segments\" | \"max_chars\"> {\n return delivery === \"context\"\n ? { delivery: \"context\", include_segments: undefined, max_chars: undefined }\n : { delivery: undefined };\n}\n\nexport interface DeliveryWords {\n /** The choice's name on a control. */\n label: string;\n /** Two or three words under the control: what happens (copy law R9). */\n hint: string;\n /** The short phrase a summary line uses. */\n summary: string;\n}\n\nexport const DELIVERY_WORDS: Record<SourceDelivery, DeliveryWords> = {\n direct: {\n label: \"Include the text\",\n hint: \"Sent in full\",\n summary: \"Text included\",\n },\n context: {\n label: \"Let the AI look it up\",\n hint: \"Read as needed\",\n summary: \"Looked up when needed\",\n },\n};\n\n/** The choices, in the order every control shows them. */\nexport const DELIVERY_CHOICES: ReadonlyArray<{ value: SourceDelivery } & DeliveryWords> = (\n [\"direct\", \"context\"] as const\n).map((value) => ({ value, ...DELIVERY_WORDS[value] }));\n\n/**\n * What a HOST can use. Not every host can take every delivery: a generator\n * that needs the text up front (flashcards' segmented generator reads the\n * resolved text and nothing else) gets NOTHING from a Source set to \"look it\n * up\" — V2 verifier shots 06/26: the request went out with `delivery:\n * \"context\"` and the page said \"None of the Sources had any text\", which was\n * false. So a host declares the deliveries it can use (`SourceInputProps.\n * deliveries`); the card and the review offer only those, and a Source already\n * set to something the host cannot use is switched back — with a note on it.\n * Omitted = both (a host whose AI can open Sources while it works).\n */\nexport function allowedDeliveries(\n deliveries: readonly SourceDelivery[] | undefined,\n): readonly SourceDelivery[] {\n const allowed = ([\"direct\", \"context\"] as const).filter((d) => !deliveries || deliveries.includes(d));\n // A host that lists nothing it can use still gets the contract default.\n return allowed.length > 0 ? allowed : [\"direct\"];\n}\n\n/** The choices one host offers, in the order every control shows them. */\nexport function deliveryChoicesFor(\n deliveries: readonly SourceDelivery[] | undefined,\n): ReadonlyArray<{ value: SourceDelivery } & DeliveryWords> {\n const allowed = allowedDeliveries(deliveries);\n return DELIVERY_CHOICES.filter((c) => allowed.includes(c.value));\n}\n\n/** The sentence a switched-back Source carries — every intervention announces itself. */\nexport function deliverySwitchedNote(to: SourceDelivery): string {\n return to === \"direct\"\n ? `This Source was set to \"${DELIVERY_WORDS.context.label}\", which this page cannot use — it needs the text up front — so it was switched back to \"${DELIVERY_WORDS.direct.label}\".`\n : `This Source was set to \"${DELIVERY_WORDS.direct.label}\", which this page cannot use, so it was switched to \"${DELIVERY_WORDS.context.label}\".`;\n}\n\n/**\n * Fit a pointer to what the host can use. Returns the patch to apply (null\n * when it already fits) and the delivery it lands on.\n */\nexport function fitDelivery(\n ref: Pick<SourceRef, \"delivery\"> | null | undefined,\n deliveries: readonly SourceDelivery[] | undefined,\n): { patch: ReturnType<typeof deliveryPatch>; to: SourceDelivery } | null {\n if (!ref) return null;\n const allowed = allowedDeliveries(deliveries);\n const current = sourceDelivery(ref);\n if (allowed.includes(current)) return null;\n const to = allowed[0]!;\n return { patch: deliveryPatch(to), to };\n}\n","/**\n * Finding a part of a Source — THE one matcher, used by the Source card's\n * \"Choose parts\" and by \"Review what goes in\".\n *\n * A query is one of:\n * - a page number (\"12\") — the part that covers that page;\n * - a page range (\"3-10\", \"3–10\", \"3 to 10\") — every part inside it;\n * - words — every word must appear in the part's label or its preview (the\n * opening words the manifest carries, contract amendment A5), matched here;\n * or the part is one the server found holding every word in its full text\n * (`POST /sources/parts/search`, via `useSourcePartsSearch`).\n *\n * A part spanning several pages (\"Pages 22–24\") covers each of them: the\n * manifest's numeric `page` is its first page and the label names the span.\n *\n * V1-A: the search promised \"words\" but matched only labels, so\n * \"photosynthesis\" found nothing in a biology course.\n */\n\nimport type { SourceManifestSegment } from \"../index\";\n\n/** A manifest part, with the A5 preview (optional on the wire). */\nexport type SourcePart = SourceManifestSegment & { preview?: string };\n\n/** The ids of parts the server found holding every word (`useSourcePartsSearch`). */\nexport type PartMatchIds = ReadonlySet<string>;\n\nconst RANGE_RE = /^(\\d+)\\s*(?:-|–|—|to)\\s*(\\d+)$/;\nconst SPAN_RE = /(\\d+)\\s*[–—-]\\s*(\\d+)/;\n\n/** The pages a part covers: its label's span (\"Pages 22–24\") or its one page. */\nexport function partPages(part: SourcePart): [number, number] | null {\n if (part.page === undefined || part.page === null) return null;\n const span = /^pages?\\s/i.test(part.label) ? SPAN_RE.exec(part.label) : null;\n if (span) return [Number(span[1]), Number(span[2])];\n return [part.page, part.page];\n}\n\n/** True when a query is words (not a page or a range) — only then is the text searched. */\nexport function isWordQuery(query: string): boolean {\n const q = query.trim().toLowerCase();\n return q.length > 0 && !/^\\d+$/.test(q) && !RANGE_RE.test(q);\n}\n\nfunction normalise(text: string): string {\n return text.toLowerCase().replace(/\\s+/g, \" \");\n}\n\nexport function matchesPart(part: SourcePart, query: string, serverMatches?: PartMatchIds): boolean {\n const q = query.trim().toLowerCase();\n if (!q) return true;\n const pages = partPages(part);\n const range = RANGE_RE.exec(q);\n if (range && pages) {\n const from = Math.min(Number(range[1]), Number(range[2]));\n const to = Math.max(Number(range[1]), Number(range[2]));\n return pages[0] <= to && pages[1] >= from;\n }\n if (/^\\d+$/.test(q) && pages) {\n const n = Number(q);\n return pages[0] <= n && n <= pages[1];\n }\n if (part.id.toLowerCase() === q) return true;\n if (serverMatches?.has(part.id)) return true;\n const haystack = normalise([part.label, part.preview ?? \"\"].join(\" \"));\n return q\n .split(/\\s+/)\n .filter(Boolean)\n .every((word) => haystack.includes(word));\n}\n\n/** The parts a query shows, in the Source's own order. */\nexport function findParts<T extends SourcePart>(\n parts: readonly T[],\n query: string,\n serverMatches?: PartMatchIds,\n): T[] {\n return parts.filter((p) => matchesPart(p, query, serverMatches));\n}\n","/**\n * What a Source that was still landing becomes when the page reloads.\n *\n * Never lose input (table stakes): the pasted text, the link, or an\n * already-uploaded recording is kept in the draft (`SourceDraft.input`), so\n * the input picks it up again by itself — the landing door dedupes by content\n * hash, so landing it a second time reuses the same Source, never a copy.\n * A file that was mid-upload cannot come back (its bytes lived only in the\n * browser tab); the card says so honestly and keeps the file's name so the\n * person can choose it again in one click.\n */\n\nimport type { SourceDraft, SourceIntakeInput } from \"./types\";\n\n/** Shown while a kept input is being landed again after a reload. */\nexport const RELOADED_RESUMING =\n \"The page reloaded while this was being added — picking it up again.\";\n\n/** A kept input exists but has not been re-landed (it will be, or the person can press Try again). */\nexport const RELOADED_WHILE_ADDING =\n \"This was still being added when the page reloaded, so it did not finish. Add it again.\";\n\n/** The kinds whose landing can be repeated from what the draft kept. */\nexport function resumableInput(draft: SourceDraft): SourceIntakeInput | null {\n const input = draft.input;\n if (!input) return null;\n switch (draft.kind) {\n case \"paste\":\n return input.text?.trim() ? input : null;\n case \"web\":\n case \"youtube\":\n return input.url?.trim() ? input : null;\n case \"audio\":\n // An uploaded recording re-transcribes from its file; one recorded in\n // place (the Voice Pad) is already text and lands again from it.\n return input.fileId || input.text?.trim() ? input : null;\n default:\n return null;\n }\n}\n\n/** The sentence for a file whose upload the reload cut off. */\nexport function uploadCutOffSentence(draft: SourceDraft): string {\n return `\"${draft.label}\" was still uploading when the page reloaded, so it did not arrive. Choose it again to add it.`;\n}\n\nexport interface ReloadedCard {\n /** \"resume\" = land the kept input again now; \"reoffer\" = the person must re-choose a file. */\n action: \"resume\" | \"reoffer\" | \"lost\";\n sentence: string;\n}\n\n/**\n * The one decision: a card that was `pending`/`resolving` when the page\n * unloaded. Cards in any other state are restored unchanged (returns null).\n */\nexport function reloadedCard(\n draft: SourceDraft,\n status: \"pending\" | \"resolving\" | \"ready\" | \"error\",\n): ReloadedCard | null {\n if (status !== \"pending\" && status !== \"resolving\") return null;\n if (resumableInput(draft)) return { action: \"resume\", sentence: RELOADED_RESUMING };\n if (draft.kind === \"upload\" || draft.kind === \"image\" || draft.kind === \"audio\")\n return { action: \"reoffer\", sentence: uploadCutOffSentence(draft) };\n return { action: \"lost\", sentence: RELOADED_WHILE_ADDING };\n}\n\n/**\n * The knob for the largest pasted text kept in the device draft (it would\n * crowd the draft store). Read by the intake; while unread nothing is kept and\n * the card says so.\n */\nexport const MAX_KEPT_TEXT_KNOB = { feature: \"sources\", key: \"max_kept_draft_chars\" } as const;\n\n/** Said on a pasted card whose text is too large (or the limit unreadable) to keep for a reload. */\nexport const NOT_KEPT_FOR_RELOAD =\n \"Too large to restore if the page reloads before it is added.\";\n\n/**\n * A landing stopped only because no organization is chosen yet. The card\n * waits; the moment one is set the intake lands every waiting card again from\n * what its draft kept (state, never an in-memory queue — it survives a reload).\n */\nexport const WAITING_FOR_ORGANIZATION =\n \"Waiting for an organization — choose one and this continues by itself.\";\n\n/** A read Source whose keep waits for an organization; kept again once one is set. */\nexport const KEEP_WAITING_FOR_ORGANIZATION =\n \"Read. Waiting for an organization to keep it — choose one and it is kept by itself.\";\n","/**\n * fileSource — how a stored file on a Source card becomes its Source, decided\n * from the SERVER's state alone (USI-3e). Pure: the one read\n * (`/files/{id}/rag-status`) and the file's own organization are INJECTED by\n * the host (`SourceFileState` below), never imported.\n *\n * The server owns reading a file: every upload's finalize already starts the\n * one processing run (the file adapters → a `processed_documents` row), and\n * `/files/{id}/rag-status` merges that run's lifecycle row with the Source it\n * made. So a card never starts its own run while one is live, a reload simply\n * reads the state again (re-attach, never a second job), and a file someone\n * already had (\"use the one you already have\", or picked from Files) is kept\n * the moment its existing Source is seen.\n */\n\nimport type { SourceCardModel } from \"./types\";\n\n/** The part of the server's `/files/{id}/rag-status` answer the decision reads. */\nexport interface FileSourceStatus {\n state: string;\n processed_document_id?: string | null | undefined;\n error?: { message?: string | null | undefined; [detail: string]: unknown } | null | undefined;\n}\n\nexport type FileSourceStep =\n /** The Source exists: keep it and file it against the thing being made. */\n | { do: \"keep\"; processedDocumentId: string }\n /** A run is reading it now (server-side or this tab's own). Look again soon. */\n | { do: \"wait\" }\n /** Nothing is reading it and it has no Source yet: start the one run. */\n | { do: \"start\" }\n /** It cannot become a Source; say why, and stop looking. */\n | { do: \"unreadable\"; reason: string };\n\nexport interface FileSourceContext {\n /** This card already started a run in this page's life. */\n started: boolean;\n /** This tab's processing runner has a live run for the file. */\n localRunning: boolean;\n}\n\nconst UNREADABLE = \"Can't read this file — add a PDF, Word or text copy.\";\n\n/** The one decision. `status` is the server's `/files/{id}/rag-status` answer. */\nexport function nextFileStep(\n status: FileSourceStatus | null,\n ctx: FileSourceContext,\n): FileSourceStep {\n const pdId = status?.processed_document_id ?? null;\n if (pdId) return { do: \"keep\", processedDocumentId: pdId };\n if (ctx.localRunning || status?.state === \"running\") return { do: \"wait\" };\n if (status?.state === \"failed\")\n return {\n do: \"unreadable\",\n reason: status.error?.message\n ? `Can't read this file: ${status.error.message}. Add it again.`\n : UNREADABLE,\n };\n if (!ctx.started) return { do: \"start\" };\n return { do: \"unreadable\", reason: UNREADABLE };\n}\n\n/** How long to wait before looking again: quick at first, then spaced out. */\nexport function fileSourcePollDelayMs(round: number): number {\n if (round < 5) return 3_000;\n if (round < 20) return 6_000;\n return 15_000;\n}\n\n/** A stored file on a card whose Source is not known yet — the recovery reads its state. */\nexport function isWaitingFileCard(card: SourceCardModel): boolean {\n return (\n card.status === \"ready\" &&\n card.draft.ref?.resource_type === \"file\" &&\n !!card.draft.fileId &&\n !card.draft.processedDocumentId\n );\n}\n\n/**\n * True while a waiting file card cannot be asked about yet: `/files/{id}/\n * rag-status` answers only with an organization (the file's own, when the\n * host knows it, or the one the person picked). Without one every read was a\n * refused 400 — every ~3 s, piling up as page errors (V2-F #3). So the card\n * is HELD: it says it is waiting for an organization, offers the one picker,\n * and nothing is asked until one is known.\n *\n * `fileOrganizationId` is the host's lookup of a file's own organization\n * (omitted = the host does not know it).\n */\nexport function fileCardHeldForOrganization(\n card: SourceCardModel,\n activeOrganizationId: string | null | undefined,\n fileOrganizationId?: (fileId: string) => string | null | undefined,\n): boolean {\n if (!isWaitingFileCard(card)) return false;\n if (activeOrganizationId) return false;\n return !fileOrganizationId?.(card.draft.fileId as string);\n}\n","/**\n * The token estimate the planner uses by default — the SAME measured ratios as\n * the web app's one estimator (matrx-frontend `lib/tokens/estimate.ts`) and the\n * server's `CHARS_PER_TOKEN_MEASURED` (aidream, 2026-09-28): 2.9 characters per\n * token for prose with markup, 2.4 for structured payloads. Measured, not\n * assumed — the textbook 4.0 under-counted a real run by 23%.\n *\n * A host that owns its own estimator passes it to `planSourceReview`\n * (`PlanInput.estimateTokens`) so a preview and a run never disagree.\n */\n\nexport const SOURCE_CHARS_PER_TOKEN = {\n prose: 2.9,\n structured: 2.4,\n} as const;\n\n/** Estimated tokens for `chars` characters of prose. */\nexport function estimateSourceTokens(chars: number): number {\n if (!Number.isFinite(chars) || chars <= 0) return 0;\n return Math.ceil(chars / SOURCE_CHARS_PER_TOKEN.prose);\n}\n","/**\n * `@ai-matrx/agents/sources` — THE ONE SOURCE PAYLOAD (contract v1, frozen 2026-09-27).\n *\n * Every request that is built from a person's Sources carries them as a\n * `SourceSet`: a list of `SourceRef` pointers (never blobs) plus how the model\n * should be grounded in them. The server answers with a `SourceManifest`\n * (sizes and states, never bodies — POST /sources/manifest) or a\n * `ResolvedSourceSet` (grounded text for generators — POST /sources/resolve).\n *\n * Contract of record: common-docs `projects/unified-source-input/DESIGN.md`\n * § \"Contract v1 — FROZEN\". A shape change here is an AMENDMENT there first,\n * with its Pydantic twin beside aidream's `parse_resource_reference`.\n *\n * `SourceRef` IS the existing `resource_ref` pointer already on the wire\n * (aidream `services/conversation_context/resource_context.py`), extended with\n * optional fields only — never coin a second pointer type.\n *\n * Pure module: no React, no I/O, no \"use client\".\n */\n\nexport const RESOURCE_REF_KIND = \"resource_ref\" as const;\nexport const SOURCE_SET_KIND = \"source_set\" as const;\nexport const SOURCE_MANIFEST_KIND = \"source_manifest\" as const;\nexport const RESOLVED_SOURCE_SET_KIND = \"resolved_source_set\" as const;\n\n/** The wire version every `SourceSet` carries. */\nexport const SOURCE_SET_VERSION = 1 as const;\n\n/** A bounded preview of one representation promoted into the prompt. */\nexport interface ResourcePromotion {\n representation: string;\n max_chars?: number;\n}\n\nexport type SourceDelivery = \"direct\" | \"context\";\nexport type SourceGrounding = \"whole\" | \"selected\" | \"retrieve\";\n\n/** The pointer — the existing `resource_ref` envelope, extended (all new fields optional). */\nexport interface SourceRef {\n __kind: typeof RESOURCE_REF_KIND;\n /** Server resource token: \"file\" (A2; \"cld_file\" is a server alias) | \"processed_document\" | \"note\" | \"fc_set\" | … */\n resource_type: string;\n resource_id: string;\n /** \"clean\" | \"raw\" | \"pdf\" | a family representation key. Omitted = server's Clean → Raw → original fallback. */\n representation?: string;\n /** Hand-picked Segment ids (rag.kg_chunks ids or \"<resource_id>:<n>\"). */\n include_segments?: string[];\n /** Include the text (default \"direct\") | the AI fetches it on demand (\"context\"). */\n delivery?: SourceDelivery;\n /** Per-Source cap chosen on the review page. */\n max_chars?: number;\n promote?: ResourcePromotion | ResourcePromotion[];\n exclude?: string[];\n}\n\nexport interface SourceSet {\n __kind: typeof SOURCE_SET_KIND;\n version: typeof SOURCE_SET_VERSION;\n sources: SourceRef[];\n /** Only for \"Just a topic\". */\n topic?: string;\n /** Default \"whole\". */\n grounding?: SourceGrounding;\n /** Required in spirit when grounding = \"retrieve\". */\n retrieve_query?: string;\n /** The model whose context window sets the budget. */\n target_model_id?: string;\n}\n\nexport type SourceState = \"ready\" | \"processing\" | \"failed\" | \"unavailable\";\n\nexport interface SourceManifestForm {\n form: string;\n label: string;\n chars: number;\n available: boolean;\n}\n\nexport interface SourceManifestSegment {\n id: string;\n /** \"Page 7\", \"Pages 22–24\" (a part spanning pages), \"0:04–2:31\", a heading path, \"Part 3\". */\n label: string;\n page?: number;\n chars: number;\n /**\n * Amendment A5: the part's opening words (about 160 characters, whitespace\n * collapsed) — never its body. Lets a person see what a part says and find\n * a part by its words.\n */\n preview?: string;\n}\n\nexport interface SourceManifestEntry {\n ref: SourceRef;\n label: string;\n resource_type: string;\n state: SourceState;\n state_detail?: string;\n /** Why it cannot be used — the same words as `DroppedSource.reason`; \"archived\" = show Restore. */\n reason?: DroppedSourceReason | null;\n forms: SourceManifestForm[];\n default_form: string;\n segments?: SourceManifestSegment[];\n}\n\n/** POST /sources/manifest { source_set } → sizes and states, never bodies. */\nexport interface SourceManifest {\n __kind: typeof SOURCE_MANIFEST_KIND;\n sources: SourceManifestEntry[];\n total_chars: number;\n estimated_tokens: number;\n /** null = unknown model; the UI says so. */\n model_context_tokens: number | null;\n}\n\nexport interface ResolvedSourceSegment {\n id: string;\n page?: number;\n chars: number;\n}\n\nexport interface ResolvedSource {\n ref: SourceRef;\n label: string;\n form_used: string;\n /** Grounded: \"### Chunk <id> (page N)\" blocks; never re-chunked. */\n text: string;\n segments: ResolvedSourceSegment[];\n file_id?: string;\n processed_document_id?: string;\n /** \"processing\" = the raw fallback was used. */\n state: \"ready\" | \"processing\";\n truncated: boolean;\n /** Every stand-in announces itself. */\n notes: string[];\n}\n\n/**\n * A1 (2026-09-27): \"not_ready\" = a file not yet read. \"archived\" (2026-10-01) = the Source is\n * archived and this person may know it (its owner, or anyone who can read it anyway): restore it\n * to use it. Anyone else hears \"no_access\". One server rule for every kind (`archived_reason.py`).\n */\nexport type DroppedSourceReason =\n | \"no_access\"\n | \"archived\"\n | \"missing\"\n | \"failed\"\n | \"over_budget\"\n | \"not_ready\";\n\nexport interface DroppedSource {\n ref: SourceRef;\n reason: DroppedSourceReason;\n /** A1: what happened and what to do. */\n detail?: string;\n}\n\n/** POST /sources/resolve { source_set } → grounded text for generators. */\nexport interface ResolvedSourceSet {\n __kind: typeof RESOLVED_SOURCE_SET_KIND;\n sources: ResolvedSource[];\n dropped: DroppedSource[];\n total_chars: number;\n}\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\n/** Builder options. `undefined` is accepted everywhere so callers can forward an existing ref's optional fields. */\nexport interface SourceRefOptions {\n representation?: string | undefined;\n include_segments?: readonly string[] | undefined;\n delivery?: SourceDelivery | undefined;\n max_chars?: number | undefined;\n promote?: ResourcePromotion | ResourcePromotion[] | undefined;\n exclude?: readonly string[] | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Build one pointer. Empty optional fields are omitted (so the wire stays\n * minimal and equal pointers serialise equally); `exclude` is trimmed,\n * lower-cased and de-duplicated exactly as the server normalises it;\n * `include_segments` is de-duplicated in order. Throws on an empty type or id —\n * a pointer to nothing is never built silently.\n */\nexport function createSourceRef(\n resourceType: string,\n resourceId: string,\n options: SourceRefOptions = {},\n): SourceRef {\n const resource_type = resourceType.trim();\n const resource_id = resourceId.trim();\n if (!resource_type) throw new Error(\"createSourceRef: resource_type is required\");\n if (!resource_id) throw new Error(\"createSourceRef: resource_id is required\");\n if (\n options.max_chars !== undefined &&\n (!Number.isInteger(options.max_chars) || options.max_chars <= 0)\n ) {\n throw new Error(\"createSourceRef: max_chars must be a positive integer\");\n }\n const exclude = Array.from(\n new Set(\n (options.exclude ?? [])\n .map((value) => value.trim().toLowerCase())\n .filter(Boolean),\n ),\n );\n const include_segments = Array.from(\n new Set((options.include_segments ?? []).map((id) => id.trim()).filter(Boolean)),\n );\n return {\n __kind: RESOURCE_REF_KIND,\n resource_type,\n resource_id,\n ...(options.representation ? { representation: options.representation } : {}),\n ...(include_segments.length ? { include_segments } : {}),\n ...(options.delivery ? { delivery: options.delivery } : {}),\n ...(options.max_chars !== undefined ? { max_chars: options.max_chars } : {}),\n ...(options.promote ? { promote: options.promote } : {}),\n ...(exclude.length ? { exclude } : {}),\n };\n}\n\nexport function isSourceRef(value: unknown): value is SourceRef {\n return (\n isRecord(value) &&\n value.__kind === RESOURCE_REF_KIND &&\n typeof value.resource_type === \"string\" &&\n value.resource_type.length > 0 &&\n typeof value.resource_id === \"string\" &&\n value.resource_id.length > 0\n );\n}\n\nexport interface SourceSetOptions {\n topic?: string | undefined;\n grounding?: SourceGrounding | undefined;\n retrieve_query?: string | undefined;\n target_model_id?: string | undefined;\n}\n\n/**\n * Build one envelope. Duplicate pointers (same type + id + representation) are\n * collapsed, keeping the first. `grounding: \"retrieve\"` without a query and\n * `grounding: \"selected\"` with no Source carrying `include_segments` throw —\n * both would otherwise resolve to something the person never asked for.\n */\nexport function createSourceSet(\n sources: readonly SourceRef[],\n options: SourceSetOptions = {},\n): SourceSet {\n const seen = new Set<string>();\n const unique: SourceRef[] = [];\n for (const ref of sources) {\n if (!isSourceRef(ref)) throw new Error(\"createSourceSet: every source must be a resource_ref\");\n const key = `${ref.resource_type}\\u0000${ref.resource_id}\\u0000${ref.representation ?? \"\"}`;\n if (seen.has(key)) continue;\n seen.add(key);\n unique.push(ref);\n }\n const topic = options.topic?.trim();\n const retrieve_query = options.retrieve_query?.trim();\n if (options.grounding === \"retrieve\" && !retrieve_query) {\n throw new Error('createSourceSet: grounding \"retrieve\" needs a retrieve_query');\n }\n if (\n options.grounding === \"selected\" &&\n !unique.some((ref) => (ref.include_segments?.length ?? 0) > 0)\n ) {\n throw new Error('createSourceSet: grounding \"selected\" needs at least one Source with include_segments');\n }\n return {\n __kind: SOURCE_SET_KIND,\n version: SOURCE_SET_VERSION,\n sources: unique,\n ...(topic ? { topic } : {}),\n ...(options.grounding ? { grounding: options.grounding } : {}),\n ...(retrieve_query ? { retrieve_query } : {}),\n ...(options.target_model_id ? { target_model_id: options.target_model_id } : {}),\n };\n}\n\n/** Structural guard for a wire value claiming to be a v1 `SourceSet`. */\nexport function isSourceSet(value: unknown): value is SourceSet {\n return (\n isRecord(value) &&\n value.__kind === SOURCE_SET_KIND &&\n value.version === SOURCE_SET_VERSION &&\n Array.isArray(value.sources) &&\n value.sources.every(isSourceRef)\n );\n}\n\nfunction manifestEntryChars(entry: SourceManifestEntry): number {\n const selected = entry.ref.include_segments;\n let chars: number;\n if (selected?.length && entry.segments?.length) {\n const wanted = new Set(selected);\n chars = entry.segments\n .filter((segment) => wanted.has(segment.id))\n .reduce((sum, segment) => sum + segment.chars, 0);\n } else {\n const formKey = entry.ref.representation ?? entry.default_form;\n const form =\n entry.forms.find((candidate) => candidate.form === formKey) ??\n entry.forms.find((candidate) => candidate.form === entry.default_form);\n chars = form?.chars ?? 0;\n }\n return entry.ref.max_chars !== undefined ? Math.min(chars, entry.ref.max_chars) : chars;\n}\n\n/**\n * Characters that will actually go in, computed from the Sources themselves\n * (never trusting a stale `total_chars`):\n * - `ResolvedSourceSet`: the sum of every resolved text's length.\n * - `SourceManifest`: per Source, the chosen form's size (the ref's\n * `representation`, else `default_form`), or the picked Segments' sizes when\n * `include_segments` is set, capped by the ref's `max_chars`. Sources whose\n * state is \"failed\" or \"unavailable\" contribute nothing — they cannot go in.\n */\nexport function totalChars(value: SourceManifest | ResolvedSourceSet): number {\n if (value.__kind === RESOLVED_SOURCE_SET_KIND) {\n return value.sources.reduce((sum, source) => sum + source.text.length, 0);\n }\n return value.sources\n .filter((entry) => entry.state === \"ready\" || entry.state === \"processing\")\n .reduce((sum, entry) => sum + manifestEntryChars(entry), 0);\n}\n","/**\n * The source-list state machine — pure reducers and selectors over\n * `SourceSetState`. Every function returns a NEW state (or the same one when\n * nothing changed) and never touches a store, a network or a clock; the\n * controller (`controller.ts`) applies them through the host's store adapter.\n *\n * The rules here are the ones the web app's Source input has always kept:\n * - landing the same Source twice keeps ONE card and says so on it;\n * - a settled card drops the input it kept for a reload;\n * - a card cut off mid-landing by a reload is restored as an error the\n * input resolves (`interrupted.ts`), never a spinner forever;\n * - a new Source starts on the host's default form.\n */\n\nimport {\n createSourceRef,\n createSourceSet,\n totalChars as sumChars,\n type ResolvedSourceSet,\n type SourceManifest,\n type SourceManifestEntry,\n type SourceRef,\n type SourceRefOptions,\n type SourceSet,\n} from \"../index\";\nimport { deliverySwitchedNote, fitDelivery, type SourceDelivery } from \"./delivery\";\nimport { reloadedCard, WAITING_FOR_ORGANIZATION } from \"./interrupted\";\nimport { partPages } from \"./partsSearch\";\nimport type {\n PersistedSourceCard,\n PersistedSourceInput,\n SourceCardModel,\n SourceDraft,\n SourcePickedPart,\n SourceSetState,\n} from \"./types\";\n\nexport const EMPTY_SOURCE_SET_STATE: SourceSetState = Object.freeze({ cards: Object.freeze([]), topic: \"\" }) as SourceSetState;\n\n/** Said when a Source's parts were re-read (the clean version landed) and the pick was carried over by page. */\nexport const PARTS_MATCHED_BY_PAGE = \"The clean version is ready — your parts were matched to it by page.\";\n\n/** Said when a pick could not be carried over to the Source's new parts: the whole Source goes in until parts are chosen again. */\nexport const PARTS_NOT_MATCHED =\n \"The clean version is ready, but your parts could not be matched to it — choose parts again. Until then the whole Source goes in.\";\n\n/** Said on the one card kept when the same Source lands twice. */\nexport const SAME_SOURCE_AGAIN = \"You added this again — it is the same Source, so it is listed once.\";\n\nexport function isSourceDraft(value: unknown): value is SourceDraft {\n return (\n !!value &&\n typeof value === \"object\" &&\n typeof (value as SourceDraft).kind === \"string\" &&\n typeof (value as SourceDraft).label === \"string\"\n );\n}\n\nexport function sameSourceRef(\n a: Pick<SourceRef, \"resource_type\" | \"resource_id\">,\n b: Pick<SourceRef, \"resource_type\" | \"resource_id\">,\n): boolean {\n return a.resource_type === b.resource_type && a.resource_id === b.resource_id;\n}\n\n/** \"<resource_type>:<resource_id>\" — how a Source is keyed across screens. */\nexport function sourceKey(ref: { resource_type: string; resource_id: string }): string {\n return `${ref.resource_type}:${ref.resource_id}`;\n}\n\n/** The draft kind a registry token is picked as. */\nexport function draftKindForToken(token: string): SourceDraft[\"kind\"] {\n if (token === \"file\") return \"files\";\n if (token === \"note\") return \"notes\";\n if (token === \"processed_document\") return \"your_sources\";\n return \"records\";\n}\n\n/** A new pointer starts on the host's default form (never over one already chosen). */\nexport function withDefaultForm(ref: SourceRef, defaultForm: string | undefined): SourceRef {\n return defaultForm && !ref.representation\n ? createSourceRef(ref.resource_type, ref.resource_id, { ...ref, representation: defaultForm })\n : ref;\n}\n\nfunction cardById(state: SourceSetState, id: string): SourceCardModel | undefined {\n return state.cards.find((c) => c.id === id);\n}\n\nfunction replaceCard(\n state: SourceSetState,\n id: string,\n patch: (card: SourceCardModel) => SourceCardModel,\n): SourceSetState {\n let changed = false;\n const cards = state.cards.map((c) => {\n if (c.id !== id) return c;\n const next = patch(c);\n if (next !== c) changed = true;\n return next;\n });\n return changed ? { ...state, cards } : state;\n}\n\n// ── Reducers ────────────────────────────────────────────────────────────────\n\n/** Add a Source that is already a pointer (a stored record, a landed Source). */\nexport function addReadyCard(\n state: SourceSetState,\n id: string,\n draft: SourceDraft,\n options: { defaultForm?: string | undefined } = {},\n): SourceSetState {\n const ref = draft.ref ? withDefaultForm(draft.ref, options.defaultForm) : null;\n return {\n ...state,\n cards: [...state.cards, { id, draft: { ...draft, ref }, status: \"ready\", error: null, manifest: null }],\n };\n}\n\n/** Add a Source that is still landing; finish it with `settleCard` or `failCard`. */\nexport function addPendingCard(\n state: SourceSetState,\n id: string,\n draft: Omit<SourceDraft, \"ref\">,\n): SourceSetState {\n return {\n ...state,\n cards: [...state.cards, { id, draft: { ...draft, ref: null }, status: \"resolving\", error: null, manifest: null }],\n };\n}\n\n/**\n * A landing answered. The door dedupes by content: landing the same thing\n * twice returns the Source already picked — keep ONE card and say so on it.\n */\nexport function settleCard(\n state: SourceSetState,\n id: string,\n patch: Partial<SourceDraft> & { ref: SourceRef },\n options: { defaultForm?: string | undefined } = {},\n): SourceSetState {\n const card = cardById(state, id);\n if (!card) return state; // removed while it was landing — nothing to finish\n const twin = state.cards.find((c) => c.id !== id && c.draft.ref && sameSourceRef(c.draft.ref, patch.ref));\n if (twin) {\n const without = { ...state, cards: state.cards.filter((c) => c.id !== id) };\n if (twin.draft.notes?.includes(SAME_SOURCE_AGAIN)) return without;\n return replaceCard(without, twin.id, (c) => ({\n ...c,\n draft: { ...c.draft, notes: [...(c.draft.notes ?? []), SAME_SOURCE_AGAIN] },\n }));\n }\n return replaceCard(state, id, (c) => ({\n ...c,\n // Landed: the kept input has done its job and leaves the draft.\n draft: { ...c.draft, ...patch, input: undefined, ref: withDefaultForm(patch.ref, options.defaultForm) },\n status: \"ready\",\n error: null,\n }));\n}\n\n/**\n * A card that failed has ONE state — failed. Its last measurement goes, so it\n * can never also say \"Still being read\" (verify-3: a stored PDF showed both).\n */\nexport function failCard(state: SourceSetState, id: string, sentence: string): SourceSetState {\n return replaceCard(state, id, (c) => ({ ...c, status: \"error\", error: sentence, manifest: null }));\n}\n\n/** Back to landing (after a reload or a failure). */\nexport function restartCard(state: SourceSetState, id: string): SourceSetState {\n return replaceCard(state, id, (c) => ({ ...c, status: \"resolving\", error: null }));\n}\n\n/** Change what a card says or keeps (label, input, fileId, notes, processedDocumentId). */\nexport function updateCardDraft(\n state: SourceSetState,\n id: string,\n patch: Partial<Omit<SourceDraft, \"ref\">>,\n): SourceSetState {\n return replaceCard(state, id, (c) => ({ ...c, draft: { ...c.draft, ...patch } }));\n}\n\nexport function removeCard(state: SourceSetState, id: string): SourceSetState {\n if (!cardById(state, id)) return state;\n return { ...state, cards: state.cards.filter((c) => c.id !== id) };\n}\n\n/** Change the pointer's choices (form, parts, cap, delivery). */\nexport function updateCardRef(state: SourceSetState, id: string, options: SourceRefOptions): SourceSetState {\n return replaceCard(state, id, (c) => {\n if (!c.draft.ref) return c;\n const ref = createSourceRef(c.draft.ref.resource_type, c.draft.ref.resource_id, { ...c.draft.ref, ...options });\n return rememberPickedParts({ ...c, draft: { ...c.draft, ref } });\n });\n}\n\n/**\n * Remember where the picked parts sit (label + pages) from the card's current\n * measurement, so a pick survives the Source being re-split (raw pages → clean\n * parts). No parts picked = nothing remembered.\n */\nexport function rememberPickedParts(card: SourceCardModel): SourceCardModel {\n const ids = card.draft.ref?.include_segments ?? [];\n if (ids.length === 0) {\n return card.draft.pickedParts === undefined ? card : { ...card, draft: { ...card.draft, pickedParts: undefined } };\n }\n const segments = card.manifest?.segments ?? [];\n const known = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));\n const picked: SourcePickedPart[] = [];\n for (const id of ids) {\n const segment = segments.find((s) => s.id === id);\n if (segment) {\n const pages = partPages(segment);\n picked.push({ id, label: segment.label, ...(pages ? { pages } : {}) });\n } else {\n const before = known.get(id);\n if (before) picked.push(before);\n }\n }\n return { ...card, draft: { ...card.draft, pickedParts: picked.length ? picked : undefined } };\n}\n\nfunction withNote(notes: readonly string[] | undefined, note: string, drop: readonly string[] = []): string[] {\n const kept = (notes ?? []).filter((n) => n !== note && !drop.includes(n));\n return [...kept, note];\n}\n\n/**\n * A fresh measurement listed NEW parts (the clean version landed, so the raw\n * pages the person picked no longer exist by id). Carry the pick over by page:\n * every new part that covers a page the old pick covered goes in. When the old\n * pick's pages are unknown, the pick is cleared and the card says so — never\n * \"0 characters · 4 of 21 parts\" with nothing ticked (verify-3, 11d/11e).\n */\nexport function carryPickedParts(card: SourceCardModel, entry: SourceManifestEntry): SourceCardModel {\n const ref = card.draft.ref;\n const picked = ref?.include_segments ?? [];\n const segments = entry.segments ?? [];\n if (!ref || picked.length === 0 || segments.length === 0) return card;\n const ids = new Set(segments.map((s) => s.id));\n const stale = picked.filter((id) => !ids.has(id));\n if (stale.length === 0) return card;\n const remembered = new Map((card.draft.pickedParts ?? []).map((p) => [p.id, p]));\n const oldSegments = card.manifest?.segments ?? [];\n const spans: Array<[number, number]> = [];\n let unknown = 0;\n for (const id of stale) {\n const old = oldSegments.find((s) => s.id === id);\n const pages = remembered.get(id)?.pages ?? (old ? partPages(old) : null);\n if (pages) spans.push(pages);\n else unknown += 1;\n }\n const keep = new Set(picked.filter((id) => ids.has(id)));\n for (const segment of segments) {\n const pages = partPages(segment);\n if (pages && spans.some(([from, to]) => pages[0] <= to && pages[1] >= from)) keep.add(segment.id);\n }\n const nextIds = segments.filter((s) => keep.has(s.id)).map((s) => s.id);\n const matched = unknown === 0 && nextIds.length > 0;\n const nextRef = createSourceRef(ref.resource_type, ref.resource_id, {\n ...ref,\n include_segments: matched ? nextIds : undefined,\n });\n const note = matched ? PARTS_MATCHED_BY_PAGE : PARTS_NOT_MATCHED;\n const other = matched ? PARTS_NOT_MATCHED : PARTS_MATCHED_BY_PAGE;\n return rememberPickedParts({\n ...card,\n manifest: entry,\n draft: { ...card.draft, ref: nextRef, notes: withNote(card.draft.notes, note, [other]) },\n });\n}\n\nexport function setCardWaitForClean(state: SourceSetState, id: string, wait: boolean): SourceSetState {\n return replaceCard(state, id, (c) => ({ ...c, draft: { ...c.draft, waitForClean: wait } }));\n}\n\nexport function setSourceTopic(state: SourceSetState, topic: string): SourceSetState {\n return state.topic === topic ? state : { ...state, topic };\n}\n\n/**\n * What the person removed in \"Review what goes in\": the Sources that went INTO\n * the review (`reviewed`) and did not come back in its answer — keyed by\n * `sourceKey`. A Source that landed while the review was open is never in\n * `reviewed`, so it is never removed by it (verify-4 V4-F #3).\n */\nexport function removedInReview(reviewed: SourceSet, answer: SourceSet): Set<string> {\n const kept = new Set(answer.sources.map(sourceKey));\n return new Set(reviewed.sources.map(sourceKey).filter((k) => !kept.has(k)));\n}\n\n/**\n * Apply a set the review returned (forms, parts, caps, delivery) — and its\n * topic. Pass `reviewed` (the set that was sent INTO the review) and every\n * Source removed there leaves the list, bound by its own card id.\n */\nexport function applyReviewedSourceSet(state: SourceSetState, set: SourceSet, reviewed?: SourceSet): SourceSetState {\n let next = state;\n if (reviewed) {\n const removed = removedInReview(reviewed, set);\n for (const card of state.cards) {\n if (card.draft.ref && removed.has(sourceKey(card.draft.ref))) next = removeCard(next, card.id);\n }\n }\n for (const card of next.cards) {\n const ref = card.draft.ref;\n if (!ref) continue;\n const match = set.sources.find((r) => sameSourceRef(r, ref));\n if (!match) continue;\n next = replaceCard(next, card.id, (c) => rememberPickedParts({ ...c, draft: { ...c.draft, ref: match } }));\n }\n return set.topic !== undefined ? setSourceTopic(next, set.topic) : next;\n}\n\n/** The server measured the ready Sources: each ready card takes its entry. */\nexport function applyManifest(state: SourceSetState, manifest: SourceManifest): SourceSetState {\n let next = state;\n for (const card of state.cards) {\n const ref = card.draft.ref;\n if (!ref || card.status !== \"ready\") continue;\n const entry = manifest.sources.find((e) => sameSourceRef(e.ref, ref));\n if (!entry) continue;\n next = replaceCard(next, card.id, (c) => {\n const carried = carryPickedParts(c, entry);\n if (carried !== c) return carried;\n const measured = { ...c, manifest: entry };\n // Parts picked before their pages were known are remembered now.\n return c.draft.ref?.include_segments?.length && !c.draft.pickedParts ? rememberPickedParts(measured) : measured;\n });\n }\n return next;\n}\n\n/**\n * Only what the host can use (V2-F #1): a Source set to a delivery this surface\n * cannot use (picked elsewhere, restored from a draft, handed in by a link) is\n * switched back, and its card says so. Never a choice that cannot work.\n */\nexport function fitCardDeliveries(\n state: SourceSetState,\n deliveries: readonly SourceDelivery[] | undefined,\n): SourceSetState {\n let next = state;\n for (const card of state.cards) {\n const fit = fitDelivery(card.draft.ref, deliveries);\n if (!fit) continue;\n next = updateCardRef(next, card.id, fit.patch);\n const note = deliverySwitchedNote(fit.to);\n if (!card.draft.notes?.includes(note))\n next = updateCardDraft(next, card.id, { notes: [...(card.draft.notes ?? []), note] });\n }\n return next;\n}\n\n// ── Persistence (a draft store keeps this for a reload) ─────────────────────\n\n/** Read whatever a draft store handed back; anything malformed is dropped. */\nexport function readPersistedSourceInput(data: unknown): PersistedSourceInput {\n const record = data && typeof data === \"object\" ? (data as Record<string, unknown>) : undefined;\n const sources = Array.isArray(record?.sources)\n ? (record.sources as PersistedSourceCard[]).filter(\n (c) => !!c && typeof c.id === \"string\" && isSourceDraft(c.draft),\n )\n : [];\n return { sources, topic: typeof record?.topic === \"string\" ? record.topic : \"\" };\n}\n\nexport function toPersistedSourceInput(state: SourceSetState): PersistedSourceInput {\n return {\n sources: state.cards.map((c) => ({ id: c.id, draft: c.draft, status: c.status, error: c.error })),\n topic: state.topic,\n };\n}\n\n/**\n * The cards a reload brings back. A card cut off mid-landing becomes an error\n * the input resolves (it re-lands the kept input, or asks for the file again)\n * — never a spinner forever. A landing held for an organization lost its hold\n * with the page: it is picked up again like one cut off mid-landing.\n */\nexport function restoredCards(persisted: PersistedSourceInput): SourceCardModel[] {\n return persisted.sources.map((card) => {\n const reloaded = reloadedCard(\n card.draft,\n card.status === \"error\" && card.error === WAITING_FOR_ORGANIZATION ? \"resolving\" : card.status,\n );\n return {\n id: card.id,\n draft: card.draft,\n status: reloaded ? \"error\" : card.status,\n error: reloaded ? reloaded.sentence : (card.error ?? null),\n manifest: null,\n };\n });\n}\n\n// ── Selectors ───────────────────────────────────────────────────────────────\n\nexport function readySourceRefs(state: SourceSetState): SourceRef[] {\n return state.cards.flatMap((c) => (c.status === \"ready\" && c.draft.ref ? [c.draft.ref] : []));\n}\n\nexport function hasSourceRef(state: SourceSetState, resourceType: string, resourceId: string): boolean {\n return state.cards.some(\n (c) => c.draft.ref?.resource_type === resourceType && c.draft.ref.resource_id === resourceId,\n );\n}\n\n/** The frozen v1 payload, built from the ready Sources. */\nexport function selectSourceSet(\n state: SourceSetState,\n options: { targetModelId?: string | undefined } = {},\n): SourceSet {\n const topic = state.topic.trim();\n return createSourceSet(readySourceRefs(state), {\n topic: topic || undefined,\n grounding: \"whole\",\n target_model_id: options.targetModelId,\n });\n}\n\n/**\n * THE one size rule (the contract's `totalChars`): the chosen form, or the\n * picked parts, capped — measured against each card's CURRENT pointer.\n */\nexport function selectTotalChars(state: SourceSetState): number {\n const measured: SourceManifestEntry[] = state.cards.flatMap((c) =>\n c.status === \"ready\" && c.manifest && c.draft.ref ? [{ ...c.manifest, ref: c.draft.ref }] : [],\n );\n if (!measured.length) return 0;\n return sumChars({\n __kind: \"source_manifest\",\n sources: measured,\n total_chars: 0,\n estimated_tokens: 0,\n model_context_tokens: null,\n });\n}\n\n/**\n * THE one size of one Source (verify-3: one Source read 109k, 115k, 108k and\n * 106k on four screens): the contract's rule — the chosen form, or the picked\n * parts, capped by `max_chars` — measured against the card's CURRENT pointer.\n * The card, the header total (`selectTotalChars`) and the review (`SourcePlanEntry.chars`)\n * all read this. Null when it is not measured or cannot go in.\n */\nexport function sourceEntryChars(entry: SourceManifestEntry, ref: SourceRef): number | null {\n if (entry.state !== \"ready\" && entry.state !== \"processing\") return null;\n return sumChars({\n __kind: \"source_manifest\",\n sources: [{ ...entry, ref }],\n total_chars: 0,\n estimated_tokens: 0,\n model_context_tokens: null,\n });\n}\n\nexport function sourceCardChars(card: Pick<SourceCardModel, \"draft\" | \"manifest\">): number | null {\n return card.manifest && card.draft.ref ? sourceEntryChars(card.manifest, card.draft.ref) : null;\n}\n\n/**\n * THE one state of one Source card, derived once: its own lifecycle wins\n * (adding, waiting for an organization, failed); only a card that landed takes\n * the server's measured state. Never two states at once.\n */\nexport type SourceCardState =\n | \"adding\"\n | \"waiting_for_organization\"\n | \"failed\"\n | \"unmeasured\"\n | SourceManifestEntry[\"state\"];\n\nexport function sourceCardState(card: Pick<SourceCardModel, \"status\" | \"error\" | \"manifest\">): SourceCardState {\n if (card.status === \"pending\" || card.status === \"resolving\") return \"adding\";\n if (card.status === \"error\") return card.error === WAITING_FOR_ORGANIZATION ? \"waiting_for_organization\" : \"failed\";\n return card.manifest?.state ?? \"unmeasured\";\n}\n\n/** The server's measured state to show on a card — only for a card that landed (null otherwise). */\nexport function sourceCardMeasuredState(\n card: Pick<SourceCardModel, \"status\" | \"error\" | \"manifest\">,\n): SourceManifestEntry[\"state\"] | null {\n return card.status === \"ready\" ? (card.manifest?.state ?? null) : null;\n}\n\n/** Every Source finished landing (nothing pending) and none failed. */\nexport function selectSettled(state: SourceSetState): boolean {\n return state.cards.every((c) => c.status === \"ready\");\n}\n\n/** How many more Sources fit under the host's max (Infinity when there is none). */\nexport function sourceRoomLeft(state: SourceSetState, max: number | undefined): number {\n return max === undefined ? Number.POSITIVE_INFINITY : Math.max(0, max - state.cards.length);\n}\n\n/**\n * Every generator names a Source the way the person saw it on its card — the\n * file name, the name they gave pasted text — never the stored document's own\n * title (V2-F #5). The server's label stays only for a Source the input does\n * not hold.\n */\nexport function withDisplayNames(\n resolved: ResolvedSourceSet,\n cards: readonly Pick<SourceCardModel, \"draft\">[],\n): ResolvedSourceSet {\n const names = new Map<string, string>();\n for (const c of cards) {\n const label = c.draft.label?.trim();\n if (c.draft.ref && label) names.set(sourceKey(c.draft.ref), label);\n }\n return {\n ...resolved,\n sources: resolved.sources.map((s) => {\n const name = names.get(sourceKey(s.ref));\n return name ? { ...s, label: name } : s;\n }),\n };\n}\n","/**\n * THE PLANNER — one pure function shared by the preview and the result.\n *\n * The research context builder's discipline, generalised: the review shows a\n * number only if the returned `SourceSet` will carry exactly that. So the\n * screen, the budget verdict and the output all come from `planSourceReview`,\n * and nothing else does arithmetic.\n *\n * It mirrors the ONE server handler (aidream\n * `services/conversation_context/source_resolution.py`) rule for rule:\n * - chosen form = the ref's `representation`, else the manifest's `default_form`;\n * - picked parts (`include_segments`) replace the whole form;\n * - `max_chars` keeps whole parts in order until the next one would overflow\n * (`_cap`), cutting only a first part that is bigger than the cap by itself;\n * - the resolved text is the parts rendered as `### Chunk <id> (page N)` blocks\n * joined by a blank line (`render_grounded_chunk` / `_render`), so the count\n * here INCLUDES those headers and matches `POST /sources/resolve` exactly\n * whenever the manifest lists the parts;\n * - \"let the AI look it up\" (`delivery: \"context\"`) sends no text at all;\n * - Sources are budgeted in order and one that would overflow is left out,\n * while later, smaller ones may still go in.\n *\n * Budget tokens use the host's ONE estimator (`PlanInput.estimateTokens`;\n * default `estimateSourceTokens`, the same measured 2.9 chars per token as the\n * web app's `lib/tokens/estimate.ts`). The server uses the SAME measured\n * ratios since 2026-09-28 (aidream `CHARS_PER_TOKEN_MEASURED`), so the two\n * sides agree on what fits — and Sources the planner\n * leaves out are REMOVED from the returned set (named on screen first), so\n * the server never drops something the review showed as going in.\n */\n\nimport type {\n SourceManifest,\n SourceManifestEntry,\n SourceManifestSegment,\n SourceRef,\n SourceSet,\n} from \"../index\";\nimport { createSourceRef, createSourceSet } from \"../index\";\nimport { sourceDelivery } from \"./delivery\";\nimport { sourceEntryChars } from \"./state\";\nimport { estimateSourceTokens } from \"./tokens\";\n\n/** How close to the window counts as \"Getting heavy\" (the champion's 70%). */\nexport const HEAVY_SHARE = 0.7;\n\nexport type SourcePlanStatus =\n /** Its text goes in. */\n | \"included\"\n /** The AI looks it up on demand — no text is sent up front. */\n | \"on_demand\"\n /** Does not fit in what is left of the window — removed from the result. */\n | \"left_out\"\n /** Cannot be used at all (no access, missing, failed). Kept so the host can show it. */\n | \"unusable\";\n\nexport interface SourcePlanEntry {\n index: number;\n ref: SourceRef;\n entry: SourceManifestEntry;\n status: SourcePlanStatus;\n /** Label of the form in use. */\n formLabel: string;\n /** Characters of the chosen form before parts/cap. */\n formChars: number;\n /**\n * THE one size of this Source — the same number its card and the header show\n * (`sourceEntryChars`: the chosen form or picked parts, capped). What a person\n * sees; `sentChars` is only the budget's exact wire length.\n */\n chars: number;\n /** Characters the model receives for this Source (grounding headers included) — the budget's measure. */\n sentChars: number;\n sentTokens: number;\n /** True when parts are known, so `sentChars` is exact; false = the text body only. */\n exact: boolean;\n /** Number of parts that go in, when parts are known. */\n partsSent: number | null;\n partsTotal: number | null;\n /** The per-Source cap cut something. */\n capped: boolean;\n}\n\nexport type BudgetVerdict = \"empty\" | \"fine\" | \"heavy\" | \"too_much\";\n\nexport interface SourcePlan {\n entries: SourcePlanEntry[];\n /** THE one size of what goes in (sum of `chars` of the Sources whose text goes in) — shown to the person. */\n chars: number;\n /** The exact wire length the budget is judged on (grounding headers included). */\n sentChars: number;\n sentTokens: number;\n /** Window the verdict is judged against. */\n windowTokens: number;\n /** True when the window is the labelled default, not the model's own. */\n windowIsFallback: boolean;\n verdict: BudgetVerdict;\n /** Share of the window used, 0..∞. */\n share: number;\n leftOut: SourcePlanEntry[];\n /** Exactly what the review returns. */\n sourceSet: SourceSet;\n}\n\n// ---------------------------------------------------------------------------\n\nconst PAGE_SUFFIX = (page: number | undefined) =>\n page !== undefined && page > 0 ? ` (page ${page})` : \"\";\n\n/** Length of one rendered grounding block: `### Chunk <id>[ (page N)]\\n<text>`. */\nexport function renderedPartChars(\n segment: { id: string; page?: number | undefined },\n chars: number,\n): number {\n return `### Chunk ${segment.id}${PAGE_SUFFIX(segment.page)}`.length + 1 + chars;\n}\n\n/** The server's `_cap`: whole parts in order; only a lone first part is cut. */\nfunction capParts(\n parts: SourceManifestSegment[],\n maxChars: number | undefined,\n): { kept: Array<{ seg: SourceManifestSegment; chars: number }>; capped: boolean } {\n if (!maxChars) return { kept: parts.map((seg) => ({ seg, chars: seg.chars })), capped: false };\n const kept: Array<{ seg: SourceManifestSegment; chars: number }> = [];\n let used = 0;\n for (const seg of parts) {\n if (used + seg.chars <= maxChars) {\n kept.push({ seg, chars: seg.chars });\n used += seg.chars;\n continue;\n }\n const room = maxChars - used;\n if (room > 0 && kept.length === 0) kept.push({ seg, chars: room });\n return { kept, capped: true };\n }\n return { kept, capped: false };\n}\n\nexport function chosenForm(entry: SourceManifestEntry, ref: SourceRef) {\n const key = ref.representation ?? entry.default_form;\n return (\n entry.forms.find((f) => f.form === key) ??\n entry.forms.find((f) => f.form === entry.default_form) ??\n null\n );\n}\n\nfunction isUsable(entry: SourceManifestEntry): boolean {\n return entry.state === \"ready\" || entry.state === \"processing\";\n}\n\nfunction measure(entry: SourceManifestEntry, ref: SourceRef) {\n const form = chosenForm(entry, ref);\n const formChars = form?.chars ?? 0;\n const formLabel = form?.label ?? \"Text\";\n const segments = entry.segments ?? null;\n if (segments && segments.length > 0) {\n const wanted = ref.include_segments?.length ? new Set(ref.include_segments) : null;\n const chosen = wanted ? segments.filter((s) => wanted.has(s.id)) : segments;\n const { kept, capped } = capParts(chosen, ref.max_chars);\n const body = kept.reduce((sum, k) => sum + renderedPartChars(k.seg, k.chars), 0);\n const sentChars = kept.length ? body + 2 * (kept.length - 1) : 0;\n return {\n formChars,\n formLabel,\n sentChars,\n exact: true,\n partsSent: kept.length,\n partsTotal: segments.length,\n capped,\n };\n }\n const capped = ref.max_chars !== undefined && formChars > ref.max_chars;\n return {\n formChars,\n formLabel,\n sentChars: capped ? (ref.max_chars ?? formChars) : formChars,\n exact: false,\n partsSent: null,\n partsTotal: null,\n capped,\n };\n}\n\nexport interface PlanInput {\n manifest: SourceManifest;\n /** The person's current choices, index-aligned with `manifest.sources`. */\n refs: SourceRef[];\n /** The original set — carries topic / grounding / retrieve_query. */\n base: SourceSet;\n /** The model's window, or null when unknown. */\n modelWindowTokens: number | null;\n /** The labelled default used when the model is unknown. */\n fallbackWindowTokens: number;\n targetModelId?: string | undefined;\n /** The host's one token estimator (default: the measured `estimateSourceTokens`). */\n estimateTokens?: ((chars: number) => number) | undefined;\n}\n\nexport function planSourceReview(input: PlanInput): SourcePlan {\n const estimateTokens = input.estimateTokens ?? estimateSourceTokens;\n const windowIsFallback = !input.modelWindowTokens || input.modelWindowTokens <= 0;\n const windowTokens = windowIsFallback\n ? input.fallbackWindowTokens\n : (input.modelWindowTokens as number);\n\n let sentChars = 0;\n const entries: SourcePlanEntry[] = input.manifest.sources.map((entry, index) => {\n const ref = input.refs[index] ?? entry.ref;\n const m = measure(entry, ref);\n const base = { index, ref, entry, ...m, chars: sourceEntryChars(entry, ref) ?? 0 };\n if (!isUsable(entry)) {\n return { ...base, status: \"unusable\" as const, sentChars: 0, sentTokens: 0 };\n }\n if (sourceDelivery(ref) === \"context\") {\n return { ...base, status: \"on_demand\" as const, sentChars: 0, sentTokens: 0 };\n }\n if (estimateTokens(sentChars + m.sentChars) > windowTokens) {\n return { ...base, status: \"left_out\" as const, sentTokens: estimateTokens(m.sentChars) };\n }\n sentChars += m.sentChars;\n return { ...base, status: \"included\" as const, sentTokens: estimateTokens(m.sentChars) };\n });\n\n const sentTokens = estimateTokens(sentChars);\n const leftOut = entries.filter((e) => e.status === \"left_out\");\n const share = windowTokens > 0 ? sentTokens / windowTokens : 0;\n const anythingGoesIn = entries.some((e) => e.status === \"included\" || e.status === \"on_demand\");\n const verdict: BudgetVerdict = !anythingGoesIn && leftOut.length === 0\n ? \"empty\"\n : leftOut.length > 0\n ? \"too_much\"\n : share >= HEAVY_SHARE\n ? \"heavy\"\n : \"fine\";\n\n const kept = entries\n .filter((e) => e.status !== \"left_out\")\n .map((e) =>\n createSourceRef(e.ref.resource_type, e.ref.resource_id, {\n representation: e.ref.representation,\n include_segments: e.ref.include_segments,\n delivery: e.ref.delivery,\n max_chars: e.ref.max_chars,\n promote: e.ref.promote,\n exclude: e.ref.exclude,\n }),\n );\n const grounding =\n input.base.grounding === \"selected\" && !kept.some((r) => r.include_segments?.length)\n ? undefined\n : input.base.grounding;\n const sourceSet = createSourceSet(kept, {\n topic: input.base.topic,\n grounding,\n retrieve_query: input.base.retrieve_query,\n target_model_id: input.targetModelId ?? input.base.target_model_id,\n });\n\n return {\n entries,\n chars: entries.filter((e) => e.status === \"included\").reduce((sum, e) => sum + e.chars, 0),\n sentChars,\n sentTokens,\n windowTokens,\n windowIsFallback,\n verdict,\n share,\n leftOut,\n sourceSet,\n };\n}\n","/**\n * THE one client for the Source doors on the server (aidream\n * `api/routers/source_sets.py`):\n *\n * - `POST /sources/manifest` — sizes, states, forms and parts (never bodies);\n * - `POST /sources/resolve` — the full grounded text a generator reads;\n * - `POST /sources/parts/search` — the ids of one Source's parts that hold\n * every word of a query (the manifest's own part ids; never a body).\n *\n * All three are READS decided by access, never by the selected organization:\n * the server names them in `BODY_CARRIED_READS` (aidream `api/read_by_access.py`),\n * so every call goes out marked `bodyCarriedRead` — with an organization it is\n * still named, with none it is sent naming none instead of being refused on\n * the client (V1-A: \"Select an organization before sending this request\" was a\n * dead end the server never asked for).\n *\n * The TRANSPORT is injected: auth, base URL and error shape belong to the\n * host. A web app binds its typed API client; any other client can use\n * `createFetchSourcesTransport` below.\n */\n\nimport type { ResolvedSourceSet, SourceManifest, SourceRef, SourceSet } from \"../index\";\n\n/** Options every Source door call carries. */\nexport interface SourceCallOptions {\n organizationId?: string | undefined;\n signal?: AbortSignal | undefined;\n}\n\n/** What the transport receives: the call options plus the read marker. */\nexport interface SourceTransportOptions extends SourceCallOptions {\n /** Always true for the Source doors — send without requiring an organization. */\n bodyCarriedRead: true;\n}\n\n/** The server's answer to a part search. */\nexport interface SourcePartsSearchResult {\n segment_ids?: string[] | null | undefined;\n truncated?: boolean | null | undefined;\n /** Set when the Source cannot be searched (\"no_access\", …). */\n unavailable?: string | null | undefined;\n /** What happened and what to do, in the server's words. */\n detail?: string | null | undefined;\n}\n\n/** The three door paths, typed by body and answer. */\nexport interface SourceDoorCalls {\n \"/sources/manifest\": { body: { source_set: SourceSet }; answer: SourceManifest };\n \"/sources/resolve\": { body: { source_set: SourceSet }; answer: ResolvedSourceSet };\n \"/sources/parts/search\": {\n body: { source_ref: SourceRef; query: string };\n answer: SourcePartsSearchResult;\n };\n}\n\nexport type SourceDoorPath = keyof SourceDoorCalls;\n\n/** The host's way to POST to the server (auth + base URL + error shape are its own). */\nexport interface SourcesTransport {\n post<P extends SourceDoorPath>(\n path: P,\n body: SourceDoorCalls[P][\"body\"],\n options: SourceTransportOptions,\n ): Promise<SourceDoorCalls[P][\"answer\"]>;\n}\n\nexport interface SourcesClient {\n manifest(sourceSet: SourceSet, options?: SourceCallOptions): Promise<SourceManifest>;\n resolve(sourceSet: SourceSet, options?: SourceCallOptions): Promise<ResolvedSourceSet>;\n /** The ids of `ref`'s parts whose label or text holds every word of `query`. */\n searchParts(\n ref: SourceRef,\n query: string,\n options?: SourceCallOptions,\n ): Promise<SourcePartsSearchResult>;\n}\n\nfunction marked(options: SourceCallOptions | undefined): SourceTransportOptions {\n return {\n bodyCarriedRead: true,\n ...(options?.organizationId ? { organizationId: options.organizationId } : {}),\n ...(options?.signal ? { signal: options.signal } : {}),\n };\n}\n\nexport function createSourcesClient(transport: SourcesTransport): SourcesClient {\n return {\n manifest: (sourceSet, options) =>\n transport.post(\"/sources/manifest\", { source_set: sourceSet }, marked(options)),\n resolve: (sourceSet, options) =>\n transport.post(\"/sources/resolve\", { source_set: sourceSet }, marked(options)),\n searchParts: (ref, query, options) =>\n transport.post(\"/sources/parts/search\", { source_ref: ref, query }, marked(options)),\n };\n}\n\n/** Thrown by the fetch transport for a non-2xx answer — carries the server's words. */\nexport class SourceDoorError extends Error {\n readonly status: number;\n readonly body: unknown;\n constructor(status: number, message: string, body: unknown) {\n super(message);\n this.name = \"SourceDoorError\";\n this.status = status;\n this.body = body;\n }\n}\n\nexport interface FetchSourcesTransportOptions {\n /** The server's base URL (\"https://server.app.matrxserver.com\"). */\n baseUrl: string;\n /** Headers for each call — the host's auth (a bearer token) goes here. */\n headers?: (() => Record<string, string> | Promise<Record<string, string>>) | undefined;\n /** The header that names the organization (default \"X-Organization-Id\"). */\n organizationHeader?: string | undefined;\n fetch?: typeof fetch | undefined;\n}\n\nfunction refusalMessage(status: number, body: unknown): string {\n if (body && typeof body === \"object\") {\n const record = body as Record<string, unknown>;\n const error = record.error;\n if (error && typeof error === \"object\") {\n const message = (error as Record<string, unknown>).user_message ?? (error as Record<string, unknown>).message;\n if (typeof message === \"string\" && message) return message;\n }\n if (typeof record.detail === \"string\" && record.detail) return record.detail;\n }\n return `The server answered ${status}.`;\n}\n\n/** A plain `fetch` transport for clients without their own API layer. */\nexport function createFetchSourcesTransport(options: FetchSourcesTransportOptions): SourcesTransport {\n const base = options.baseUrl.replace(/\\/+$/, \"\");\n return {\n async post(path, body, call) {\n const doFetch = options.fetch ?? fetch;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers ? await options.headers() : {}),\n };\n if (call.organizationId) headers[options.organizationHeader ?? \"X-Organization-Id\"] = call.organizationId;\n const response = await doFetch(`${base}${path}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n ...(call.signal ? { signal: call.signal } : {}),\n });\n const text = await response.text();\n let parsed: unknown = null;\n try {\n parsed = text ? JSON.parse(text) : null;\n } catch {\n parsed = text;\n }\n if (!response.ok) throw new SourceDoorError(response.status, refusalMessage(response.status, parsed), parsed);\n return parsed as SourceDoorCalls[typeof path][\"answer\"];\n },\n };\n}\n","/**\n * The Source-set controller — the imperative face of the state machine, with\n * every outside dependency injected through one adapter:\n *\n * - `store` where the cards live (a Redux slice, a Zustand store, the\n * in-memory store below — the host's choice);\n * - `persistence` the draft store a reload reads back (optional);\n * - `client` the Source doors (`createSourcesClient(transport)`);\n * - `config` the host's choices: default form, organization, the\n * deliveries it can use, the most Sources it takes.\n *\n * Every screen (the Studio grid, a compact strip, chat's \"+\", the review)\n * drives the SAME controller; `@ai-matrx/agents/sources/react` binds it to\n * React with `useSourceSet(adapter)`.\n */\n\nimport {\n createSourceSet,\n type ResolvedSourceSet,\n type SourceManifest,\n type SourceRef,\n type SourceRefOptions,\n type SourceSet,\n} from \"../index\";\nimport type { SourcesClient } from \"./client\";\nimport type { SourceDelivery } from \"./delivery\";\nimport {\n addPendingCard,\n addReadyCard,\n applyManifest,\n applyReviewedSourceSet,\n EMPTY_SOURCE_SET_STATE,\n failCard,\n fitCardDeliveries,\n hasSourceRef,\n readPersistedSourceInput,\n readySourceRefs,\n removeCard,\n restartCard,\n restoredCards,\n selectSettled,\n selectSourceSet,\n selectTotalChars,\n setCardWaitForClean,\n setSourceTopic,\n settleCard,\n sourceRoomLeft,\n toPersistedSourceInput,\n updateCardDraft,\n updateCardRef,\n withDisplayNames,\n} from \"./state\";\nimport type { PersistedSourceInput, SourceCardModel, SourceDraft, SourceSetState } from \"./types\";\n\n/** Where the cards live. `getState` must return the SAME object until something changes. */\nexport interface SourceSetStore {\n getState(): SourceSetState;\n setState(next: SourceSetState): void;\n subscribe(listener: () => void): () => void;\n /** Called once when a screen mounts (a store that registers entries lazily). */\n init?: (() => void) | undefined;\n}\n\n/** The draft store a reload reads back. `load` returns the raw saved value (stable until it changes). */\nexport interface SourceDraftStorage {\n load(): unknown;\n save(value: PersistedSourceInput): void;\n subscribe?: ((listener: () => void) => () => void) | undefined;\n}\n\nexport interface SourceSetConfig {\n /** The form each new Source starts on (\"clean\" | \"raw\"). Omitted = the server's choice. */\n defaultForm?: string | undefined;\n /** The organization named on the door calls (they answer without one too). */\n organizationId?: string | null | undefined;\n /** How the AI may get the Sources on this surface. Omitted = both. */\n deliveries?: readonly SourceDelivery[] | undefined;\n /** Most Sources the person may pick. Omitted = no limit. */\n max?: number | undefined;\n}\n\nexport interface SourceSetAdapter {\n store: SourceSetStore;\n persistence?: SourceDraftStorage | undefined;\n /** Needed for `manifest()` and `resolve()`. */\n client?: SourcesClient | undefined;\n config?: SourceSetConfig | undefined;\n /** A new card's id (default: a random UUID). */\n createId?: (() => string) | undefined;\n /** A failed call as one sentence with its remedy (default: the error's message). */\n describeError?: ((error: unknown) => string) | undefined;\n}\n\n/** The measurement's own state (not persisted, not shared across controllers). */\nexport interface SourceSetMeta {\n measuring: boolean;\n /** Why the measurement failed, with its remedy. */\n manifestError: string | null;\n}\n\n/** The mutations every intake and screen drives. */\nexport interface SourceSetActions {\n /** Add a Source that is already a pointer (a stored record, a landed Source). */\n addReady(draft: SourceDraft): string;\n /** Add a Source that is still landing; finish it with `settle` or `fail`. */\n addPending(draft: Omit<SourceDraft, \"ref\">): string;\n settle(id: string, patch: Partial<SourceDraft> & { ref: SourceRef }): void;\n fail(id: string, sentence: string): void;\n /** Back to landing. False when the card is gone (removed) — nothing to land. */\n restart(id: string): boolean;\n /** Change what a card that is still landing says or keeps (label, input, fileId, notes). */\n updateDraft(id: string, patch: Partial<Omit<SourceDraft, \"ref\">>): void;\n remove(id: string): void;\n /** Change the pointer's choices (form, parts, cap, delivery). */\n updateRef(id: string, options: SourceRefOptions): void;\n setWaitForClean(id: string, wait: boolean): void;\n setTopic(topic: string): void;\n /** True when this pointer is already picked. */\n hasRef(resourceType: string, resourceId: string): boolean;\n /** How many Sources are picked RIGHT NOW (read from the store, never a stale render). */\n liveCount(): number;\n /** POST /sources/manifest for the ready Sources; cards update with it. */\n manifest(): Promise<SourceManifest | null>;\n}\n\nexport interface SourceSetController extends SourceSetActions {\n getState(): SourceSetState;\n subscribe(listener: () => void): () => void;\n getMeta(): SourceSetMeta;\n subscribeMeta(listener: () => void): () => void;\n /** Replace the host's choices (called on every render by a React binding). */\n configure(config: SourceSetConfig): void;\n readonly config: SourceSetConfig;\n /** Bring back a saved draft once — only into an empty input. True when it restored. */\n restore(saved: unknown): boolean;\n /** The frozen v1 payload, built from the ready Sources. */\n toSourceSet(options?: { targetModelId?: string | undefined }): SourceSet;\n /**\n * Apply a set the review returned (forms, parts, caps, delivery). Pass\n * `reviewed` — the set sent INTO the review — and every Source removed there\n * leaves the list too (only those; one that landed meanwhile stays).\n */\n applySourceSet(set: SourceSet, options?: { reviewed?: SourceSet | undefined }): void;\n /** POST /sources/resolve — the grounded text for a generator, named as the cards name them. */\n resolve(options?: { targetModelId?: string | undefined }): Promise<ResolvedSourceSet>;\n /** Switch back any Source set to a delivery the host cannot use (with a note). */\n fitDeliveries(deliveries?: readonly SourceDelivery[]): void;\n /** How many more Sources fit under the host's max. */\n roomLeft(): number;\n totalChars(): number;\n settled(): boolean;\n}\n\nfunction randomId(): string {\n const cryptoApi = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (cryptoApi?.randomUUID) return cryptoApi.randomUUID();\n return `src-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** An in-memory store — for clients without their own, and for tests. */\nexport function createMemorySourceSetStore(initial: SourceSetState = EMPTY_SOURCE_SET_STATE): SourceSetStore {\n let state = initial;\n const listeners = new Set<() => void>();\n return {\n getState: () => state,\n setState(next) {\n if (next === state) return;\n state = next;\n for (const listener of [...listeners]) listener();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\n/** An in-memory draft store (a stand-in for device storage in tests and previews). */\nexport function createMemorySourceDraftStorage(initial: unknown = undefined): SourceDraftStorage & {\n current(): unknown;\n} {\n let saved: unknown = initial;\n const listeners = new Set<() => void>();\n return {\n load: () => saved,\n save(value) {\n saved = value;\n for (const listener of [...listeners]) listener();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n current: () => saved,\n };\n}\n\nexport function createSourceSetController(adapter: SourceSetAdapter): SourceSetController {\n const { store, persistence } = adapter;\n let config: SourceSetConfig = { ...(adapter.config ?? {}) };\n const createId = adapter.createId ?? randomId;\n const describe = adapter.describeError ?? errorText;\n let meta: SourceSetMeta = { measuring: false, manifestError: null };\n const metaListeners = new Set<() => void>();\n let hydrated = false;\n /** The newest measurement wins: an older answer never overwrites a newer one. */\n let measurement: AbortController | null = null;\n\n const setMeta = (patch: Partial<SourceSetMeta>) => {\n const next = { ...meta, ...patch };\n if (next.measuring === meta.measuring && next.manifestError === meta.manifestError) return;\n meta = next;\n for (const listener of [...metaListeners]) listener();\n };\n\n /** Apply a reducer's result and write the draft (explicit persistence). */\n const commit = (next: SourceSetState) => {\n hydrated = true;\n if (next !== store.getState()) store.setState(next);\n persistence?.save(toPersistedSourceInput(store.getState()));\n };\n\n const has = (id: string) => store.getState().cards.some((c) => c.id === id);\n\n const controller: SourceSetController = {\n getState: () => store.getState(),\n subscribe: (listener) => store.subscribe(listener),\n getMeta: () => meta,\n subscribeMeta(listener) {\n metaListeners.add(listener);\n return () => metaListeners.delete(listener);\n },\n configure(next) {\n config = { ...next };\n },\n get config() {\n return config;\n },\n\n restore(saved) {\n if (hydrated) return false;\n const live = store.getState();\n if (live.cards.length > 0) {\n hydrated = true;\n return false;\n }\n const persisted = readPersistedSourceInput(saved);\n if (persisted.sources.length === 0) return false;\n hydrated = true;\n store.setState({ cards: restoredCards(persisted), topic: live.topic || persisted.topic });\n return true;\n },\n\n addReady(draft) {\n const id = createId();\n commit(addReadyCard(store.getState(), id, draft, { defaultForm: config.defaultForm }));\n return id;\n },\n addPending(draft) {\n const id = createId();\n commit(addPendingCard(store.getState(), id, draft));\n return id;\n },\n settle(id, patch) {\n if (!has(id)) return;\n commit(settleCard(store.getState(), id, patch, { defaultForm: config.defaultForm }));\n },\n fail(id, sentence) {\n if (!has(id)) return;\n commit(failCard(store.getState(), id, sentence));\n },\n restart(id) {\n if (!has(id)) return false;\n commit(restartCard(store.getState(), id));\n return true;\n },\n updateDraft(id, patch) {\n if (!has(id)) return;\n commit(updateCardDraft(store.getState(), id, patch));\n },\n remove(id) {\n commit(removeCard(store.getState(), id));\n },\n updateRef(id, options) {\n if (!store.getState().cards.find((c) => c.id === id)?.draft.ref) return;\n commit(updateCardRef(store.getState(), id, options));\n },\n setWaitForClean(id, wait) {\n if (!has(id)) return;\n commit(setCardWaitForClean(store.getState(), id, wait));\n },\n setTopic(topic) {\n commit(setSourceTopic(store.getState(), topic));\n },\n hasRef: (resourceType, resourceId) => hasSourceRef(store.getState(), resourceType, resourceId),\n liveCount: () => store.getState().cards.length,\n\n toSourceSet: (options = {}) => selectSourceSet(store.getState(), options),\n applySourceSet(set, options = {}) {\n commit(applyReviewedSourceSet(store.getState(), set, options.reviewed));\n },\n\n async manifest() {\n const refs = readySourceRefs(store.getState());\n if (refs.length === 0) {\n setMeta({ manifestError: null });\n return null;\n }\n if (!adapter.client) throw new Error(\"createSourceSetController: manifest() needs a client in the adapter\");\n measurement?.abort();\n const controllerForThis = new AbortController();\n measurement = controllerForThis;\n setMeta({ measuring: true });\n try {\n const result = await adapter.client.manifest(createSourceSet(refs), {\n organizationId: config.organizationId ?? undefined,\n signal: controllerForThis.signal,\n });\n if (measurement !== controllerForThis) return null;\n const next = applyManifest(store.getState(), result);\n if (next !== store.getState()) store.setState(next);\n setMeta({ manifestError: null });\n return result;\n } catch (err) {\n // A superseded measurement was cancelled on purpose — not a failure.\n if (measurement !== controllerForThis) return null;\n setMeta({\n manifestError: `Sizes and parts could not be read: ${describe(err)} Your picks are kept — try again.`,\n });\n return null;\n } finally {\n if (measurement === controllerForThis) setMeta({ measuring: false });\n }\n },\n\n async resolve(options = {}) {\n if (!adapter.client) throw new Error(\"createSourceSetController: resolve() needs a client in the adapter\");\n const resolved = await adapter.client.resolve(controller.toSourceSet(options), {\n organizationId: config.organizationId ?? undefined,\n });\n return withDisplayNames(resolved, store.getState().cards as SourceCardModel[]);\n },\n\n fitDeliveries(deliveries = config.deliveries) {\n const next = fitCardDeliveries(store.getState(), deliveries);\n if (next !== store.getState()) commit(next);\n },\n roomLeft: () => sourceRoomLeft(store.getState(), config.max),\n totalChars: () => selectTotalChars(store.getState()),\n settled: () => selectSettled(store.getState()),\n };\n return controller;\n}\n","/**\n * Source intake — every way NEW material becomes a Source, through the doors\n * that already exist on the server (DESIGN.md amendment A3). Each call adds a\n * card at once (so the person sees it working), then settles it to a pointer\n * or fails it with a sentence and a remedy. Nothing is ever sent onward as a\n * blob.\n *\n * pasted text → `POST /sources/land`, kept.\n * a web page → the host's scraper lands it (`addScrapedPage`), or a link\n * typed before a reload is scraped again (`addWebPage`);\n * `POST /sources/{id}/keep` files it against the thing being made.\n * a file/image → the host's uploader hands over file ids (`addUploaded`); the\n * file is filed against `attachTo` in the direction the\n * association registry declares, and its Source is kept once\n * reading makes one (`fileLanded`, driven by the recovery).\n * existing → a registry item (`addExisting`).\n * YouTube/audio → the transcript comes from the host's readers and lands\n * through `POST /sources/land`.\n *\n * Never lose input: every landing keeps what the person handed over in the\n * draft (`SourceDraft.input` — text, link, uploaded recording; never bytes)\n * until it settles, so `resume` can land it again after a reload, a failure,\n * or once an organization is chosen (the recovery replays every card waiting\n * for one — from state, never an in-memory queue). Landing twice is safe: the\n * door dedupes by (organization, identity, content hash).\n *\n * Every outside dependency is INJECTED (`SourceIntakeDeps`): the doors, the\n * organization gate, the signed-in person, the failure wording.\n */\n\nimport { isAssociationTargetType, isRegisteredPair } from \"@ai-matrx/associations\";\nimport { createSourceRef } from \"../index\";\nimport type { SourceSetActions } from \"./controller\";\nimport {\n KEEP_WAITING_FOR_ORGANIZATION,\n NOT_KEPT_FOR_RELOAD,\n WAITING_FOR_ORGANIZATION,\n resumableInput,\n} from \"./interrupted\";\nimport { draftKindForToken } from \"./state\";\nimport type { SourceAttachTo, SourceCardModel, SourceIntakeInput, SourceKindId } from \"./types\";\n\nconst TRANSCRIPT_NAME_MAX = 120;\n\n/** A door's notice: a sentence, and sometimes a remedy code (\"save_it…\"). */\nexport interface SourceLandingNotice {\n message: string;\n remedy?: string | null | undefined;\n}\n\n/** The target a door files a Source against (`attach_to`). */\nexport interface SourceAttachTarget {\n entity_type: string;\n entity_id: string;\n label: string | null;\n signal: boolean;\n}\n\n/** The part of a landing body the intake reads or sets — the rest is the host's door shape. */\nexport interface SourceLandingBodyBase {\n name: string;\n canonical_identity?: string | null | undefined;\n provenance?: Record<string, unknown> | null | undefined;\n}\n\n/** A landed (or kept) Source's answer. */\nexport interface SourceLandingAnswer {\n processed_document_id: string;\n notices?: SourceLandingNotice[] | null | undefined;\n}\n\n/** What the host's web reader returns for a link. Null = the page could not be read. */\nexport interface ScrapedSourcePage {\n processedDocumentId: string | null | undefined;\n sourceNotices: SourceLandingNotice[];\n pageTitle?: string | null | undefined;\n}\n\n/** What the host's YouTube reader returns. `source` = the server landed a timed transcript Source. */\nexport interface YouTubeTranscriptResult {\n text: string | null | undefined;\n note?: string | null | undefined;\n source?: { processed_document_id: string; title?: string | null | undefined } | null | undefined;\n}\n\n/** One file the host's uploader already uploaded. */\nexport interface UploadedSourceFile {\n fileId: string;\n name: string;\n}\n\n/** The association write (the host's one chokepoint). */\nexport interface SourceAssociationEdge {\n sourceType: string;\n sourceId: string;\n targetType: string;\n targetId: string;\n orgId: string;\n}\n\nexport type SourceAssociationResult = { ok: true } | { ok: false; error: { message: string } };\n\nexport interface SourceIntakeDoors<Body extends SourceLandingBodyBase = SourceLandingBodyBase> {\n /** `POST /sources/land` with the body as given (keep + attach_to set by the intake). */\n land(body: Body & { keep: true; attach_to: SourceAttachTarget[] }): Promise<SourceLandingAnswer>;\n /** `POST /sources/{id}/keep`, filed against the targets. */\n keep(\n processedDocumentId: string,\n options: { attachTo: SourceAttachTarget[]; organizationId: string },\n ): Promise<{ notices?: SourceLandingNotice[] | null | undefined }>;\n /** Build the landing body for text the person handed over. */\n buildTextLanding(input: {\n text: string;\n name?: string | undefined;\n organizationId: string;\n userId: string;\n }): Promise<Body>;\n /** Read a web page (the scraper lands it). Null = it could not be read. */\n scrapeUrl(url: string): Promise<ScrapedSourcePage | null>;\n /** Read a YouTube video's transcript. */\n fetchYouTubeTranscript(url: string): Promise<YouTubeTranscriptResult>;\n /** Write out a recording that is already stored. */\n transcribeFile(input: { fileId: string; organizationId: string }): Promise<{ text?: string | null | undefined }>;\n /** File one edge through the host's association chokepoint. */\n associate(edge: SourceAssociationEdge): Promise<SourceAssociationResult>;\n}\n\nexport interface SourceIntakeDeps<Body extends SourceLandingBodyBase = SourceLandingBodyBase> {\n doors: SourceIntakeDoors<Body>;\n /** The organization to land in — asks the person when none is chosen (the host's gate). */\n ensureOrganization(): Promise<string>;\n /** Run a landing the person asked for so the gate can carry the click intent. Default: run it. */\n holdIntent?: (<T>(run: () => Promise<T>) => Promise<T | undefined>) | undefined;\n /** True when a landing stopped only because no organization is chosen yet. */\n waitsForOrganization(error: unknown): boolean;\n /** A failed landing as one sentence with its remedy. */\n failureSentence(error: unknown): string;\n /** The signed-in person (null while sign-in is still loading). */\n userId(): string | null | undefined;\n /** The YouTube video id in a link, or null. */\n youtubeId(url: string): string | null | undefined;\n /** The largest pasted text kept in the draft for a reload (null = unknown — nothing kept). */\n maxKeptChars(): number | null;\n /** The thing being made — new Sources are filed against it and kept. */\n attachTo?: SourceAttachTo | undefined;\n}\n\nexport interface SourceIntake {\n addPastedText(text: string, name?: string): Promise<void>;\n addWebPage(url: string): Promise<void>;\n /**\n * A page the host's web picker already read (and the scraper landed); null id\n * = land its text instead. `pendingId` = the card `beginWebPage` made when the\n * read started — it is settled instead of a new card being added.\n */\n addScrapedPage(\n page: { url: string; title: string; text: string; processedDocumentId: string | null },\n pendingId?: string | null,\n ): Promise<void>;\n /**\n * The host's web picker STARTED reading a link: a card with the link kept\n * appears at once, so a reload mid-read brings it back and lands it (verify-3\n * 12a/12b: a reload while a page was read lost it, link and all). Finish it\n * with `addScrapedPage(page, id)`; if the person drops the preview, remove it;\n * if the picker goes away mid-read, `resume(card)` lands it through the web door.\n */\n beginWebPage(url: string): string;\n /** Files the host's uploader already uploaded. */\n addUploaded(files: readonly UploadedSourceFile[], kind: SourceKindId): Promise<void>;\n /**\n * A recording made in place (the Voice Pad) that is already written out: it\n * lands as text, but it IS a recording — its card and review say \"Recording\",\n * never \"Pasted text\" — and it keeps its name (\"Recording 3:41 PM\").\n */\n addRecordedText(text: string, name?: string): Promise<void>;\n /** A recording already uploaded — written out, then landed. */\n addUploadedRecording(file: UploadedSourceFile): Promise<void>;\n /** Something the person already has (Use existing / search). Returns false when already picked. */\n addExisting(item: { token: string; id: string; title: string }): boolean;\n addYouTube(url: string): Promise<void>;\n /** Land a card's kept input again (after a reload or a failure). False when nothing was kept. */\n resume(card: SourceCardModel): boolean;\n /** The person chose the file again (uploaded) for a card whose upload was cut off. */\n retryFile(card: SourceCardModel, file: UploadedSourceFile): Promise<void>;\n /** Reading an uploaded file made its Source: keep it and file it against `attachTo`. */\n fileLanded(card: SourceCardModel, processedDocumentId: string): Promise<void>;\n}\n\nexport function sourceAttachTargets(attachTo: SourceAttachTo | undefined): SourceAttachTarget[] {\n return attachTo\n ? [\n {\n entity_type: attachTo.entityType,\n entity_id: attachTo.entityId,\n // The EDGE's label, which the registry names (a deck's Source is its\n // \"source\", a scope's is \"about\") — never the target's display name,\n // which the door refused as an unknown label (USI-3e).\n label: null,\n signal: true,\n },\n ]\n : [];\n}\n\nfunction hostOf(url: string): string {\n try {\n return new URL(url).hostname.replace(/^www\\./, \"\");\n } catch {\n return url;\n }\n}\n\n/** A notice that asks the person to save (keep) the Source — moot once it is kept. */\nfunction isSaveItNotice(remedy: string | null | undefined): boolean {\n return typeof remedy === \"string\" && remedy.startsWith(\"save_it\");\n}\n\nfunction landedNotes(notices: readonly SourceLandingNotice[] | null | undefined): string[] {\n return (notices ?? []).map((n) => n.message).filter(Boolean);\n}\n\n/**\n * Which way a file ↔ `targetType` edge is registered — read from the package's\n * generated association registry (`@ai-matrx/associations`) — or null when it\n * is not registered.\n */\nexport function registeredFileEdge(targetType: string): \"file_to_target\" | \"target_to_file\" | null {\n if (isRegisteredPair(\"file\", targetType)) return \"file_to_target\";\n if (isRegisteredPair(targetType, \"file\")) return \"target_to_file\";\n return null;\n}\n\nexport function createSourceIntake<Body extends SourceLandingBodyBase>(\n set: SourceSetActions,\n deps: SourceIntakeDeps<Body>,\n): SourceIntake {\n const { doors } = deps;\n const attachTo = sourceAttachTargets(deps.attachTo);\n const hold = <T>(run: () => Promise<T>): Promise<T | undefined> =>\n deps.holdIntent ? deps.holdIntent(run) : run();\n const notFiledSuffix = attachTo.length ? \" or filed with what you are making\" : \"\";\n\n /**\n * Fail the card — or, when only the organization is missing, say it is\n * waiting. The card's kept input is its replay: the recovery lands it again\n * the moment an organization is set (state, not a queue).\n */\n const failOrHold = (id: string, err: unknown) => {\n set.fail(id, deps.waitsForOrganization(err) ? WAITING_FOR_ORGANIZATION : deps.failureSentence(err));\n };\n\n const needUser = (): string => {\n const userId = deps.userId();\n if (!userId) throw new Error(\"Your sign-in is still loading, so nothing was added. Try again in a moment.\");\n return userId;\n };\n\n /** Land text through the door as a kept Source; returns the settle patch. */\n const landText = async (body: Body): Promise<{ id: string; notes: string[] }> => {\n const landed = await doors.land({ ...body, keep: true, attach_to: attachTo });\n return { id: landed.processed_document_id, notes: landedNotes(landed.notices) };\n };\n\n const landPaste = async (id: string, trimmed: string, name?: string) => {\n try {\n const organizationId = await deps.ensureOrganization();\n const body = await doors.buildTextLanding({ text: trimmed, name, organizationId, userId: needUser() });\n const landed = await landText(body);\n set.settle(id, {\n label: body.name,\n ref: createSourceRef(\"processed_document\", landed.id),\n processedDocumentId: landed.id,\n notes: landed.notes,\n });\n } catch (err) {\n failOrHold(id, err);\n }\n };\n\n const landWebPage = async (id: string, url: string) => {\n try {\n const organizationId = await deps.ensureOrganization();\n const result = await doors.scrapeUrl(url);\n if (!result) {\n set.fail(\n id,\n \"That page could not be read — it may need a sign-in or block robots. Try another link, or copy the text and use Paste text.\",\n );\n return;\n }\n if (!result.processedDocumentId) {\n set.fail(\n id,\n result.sourceNotices[0]?.message ??\n \"The page was read but did not become a Source, and the server did not say why. Try again.\",\n );\n return;\n }\n // A Source picked for real work is kept (A3): its clean → segment →\n // embed is queued, and it is filed against the thing being made. Once\n // kept, the capture's \"not saved — save it\" notices are no longer true;\n // the keep's own notices replace them.\n let notes: string[];\n try {\n const kept = await doors.keep(result.processedDocumentId, { attachTo, organizationId });\n notes = [\n ...landedNotes(result.sourceNotices.filter((n) => !isSaveItNotice(n.remedy))),\n ...landedNotes(kept.notices),\n ];\n } catch (err) {\n notes = [\n ...landedNotes(result.sourceNotices),\n `It is in your Sources, but it could not be kept for reuse${notFiledSuffix}: ${deps.failureSentence(err)}`,\n ];\n }\n set.settle(id, {\n label: result.pageTitle || hostOf(url),\n ref: createSourceRef(\"processed_document\", result.processedDocumentId),\n processedDocumentId: result.processedDocumentId,\n notes,\n });\n } catch (err) {\n failOrHold(id, err);\n }\n };\n\n const landYouTube = async (id: string, url: string, videoId: string) => {\n try {\n const organizationId = await deps.ensureOrganization();\n const { text, note, source } = await doors.fetchYouTubeTranscript(url);\n if (!text) {\n set.fail(\n id,\n note ??\n \"That video has no speech we could write out (no captions and no clear voice). Try another video, or paste a transcript.\",\n );\n return;\n }\n if (source) {\n // The server landed the timed transcript through the door: the card IS\n // that transcript Source, and \"Choose parts\" lists its timed segments.\n const label = `YouTube — ${source.title || videoId}`.slice(0, TRANSCRIPT_NAME_MAX);\n let notes: string[] = [];\n try {\n const kept = await doors.keep(source.processed_document_id, { attachTo, organizationId });\n notes = landedNotes(kept.notices);\n } catch (err) {\n notes = [\n `It was read, but its Source could not be kept for reuse${notFiledSuffix}: ${deps.failureSentence(err)}`,\n ];\n }\n set.settle(id, {\n label,\n ref: createSourceRef(\"processed_document\", source.processed_document_id),\n processedDocumentId: source.processed_document_id,\n notes,\n });\n return;\n }\n const name = `YouTube — ${text.split(/\\s+/).slice(0, 10).join(\" \")}…`.slice(0, TRANSCRIPT_NAME_MAX);\n const body = await doors.buildTextLanding({ text, name, organizationId, userId: needUser() });\n const landed = await landText({\n ...body,\n // Identity is the video, so the same video twice is one Source.\n canonical_identity: `youtube:${videoId}`,\n provenance: { ...(body.provenance ?? {}), origin_client: \"youtube\", capture_method: \"captions\", final_url: url },\n });\n set.settle(id, {\n label: name,\n ref: createSourceRef(\"processed_document\", landed.id),\n processedDocumentId: landed.id,\n // Untimed: say why it has no parts to choose (the server's own sentence).\n notes: note ? [...landed.notes, note] : landed.notes,\n });\n } catch (err) {\n failOrHold(id, err);\n }\n };\n\n /**\n * File the uploaded file against the thing being made — the ONE associations\n * chokepoint, in the direction the registry declares (`fc_set → file`, but\n * `file → task`); writing it backwards is refused (USI-3e). Returns a note\n * when it could not be filed; the upload itself stands.\n */\n const fileAgainstTarget = async (fileId: string, organizationId: string): Promise<string | null> => {\n const target = deps.attachTo;\n if (!target) return null;\n const what = target.label ? `\"${target.label}\"` : \"what you are making\";\n const direction = registeredFileEdge(target.entityType);\n const cannot = `It was uploaded, but a file cannot be filed with ${what} (a ${target.entityType.replace(/_/g, \" \")}), so it is not listed there.`;\n if (!direction) return cannot;\n if (direction === \"file_to_target\" && !isAssociationTargetType(target.entityType)) return cannot;\n const linked = await doors.associate(\n direction === \"file_to_target\"\n ? {\n sourceType: \"file\",\n sourceId: fileId,\n targetType: target.entityType,\n targetId: target.entityId,\n orgId: organizationId,\n }\n : {\n sourceType: target.entityType,\n sourceId: target.entityId,\n targetType: \"file\",\n targetId: fileId,\n orgId: organizationId,\n },\n );\n return linked.ok ? null : `It was uploaded, but it could not be filed with ${what}: ${linked.error.message}`;\n };\n\n const fileNotes = async (fileId: string): Promise<string[]> => {\n try {\n const organizationId = await deps.ensureOrganization();\n const filed = await fileAgainstTarget(fileId, organizationId);\n return filed ? [filed] : [];\n } catch (err) {\n return deps.waitsForOrganization(err)\n ? []\n : [`It was uploaded, but it could not be filed: ${deps.failureSentence(err)}`];\n }\n };\n\n const transcribeRecording = async (id: string, fileId: string, fileName: string) => {\n try {\n const organizationId = await deps.ensureOrganization();\n const transcription = await doors.transcribeFile({ fileId, organizationId });\n const text = (transcription.text ?? \"\").trim();\n if (text.length < 8) {\n set.fail(\n id,\n \"We couldn't hear enough speech in that recording to write it out. Try a recording with a clear voice.\",\n );\n return;\n }\n const name = `Recording — ${fileName}`.slice(0, TRANSCRIPT_NAME_MAX);\n const body = await doors.buildTextLanding({ text, name, organizationId, userId: needUser() });\n const landed = await landText({\n ...body,\n canonical_identity: `audio-transcript:${fileId}`,\n provenance: { ...(body.provenance ?? {}), origin_client: \"transcription\", capture_method: \"speech\" },\n });\n set.settle(id, {\n label: name,\n ref: createSourceRef(\"processed_document\", landed.id),\n processedDocumentId: landed.id,\n fileId,\n notes: landed.notes,\n });\n } catch (err) {\n failOrHold(id, err);\n }\n };\n\n const intake: SourceIntake = {\n async addPastedText(text, name) {\n const trimmed = text.trim();\n if (!trimmed) return;\n const max = deps.maxKeptChars();\n const kept = max !== null && trimmed.length <= max;\n const id = set.addPending({\n kind: \"paste\",\n label: name?.trim() || \"Pasted text\",\n input: kept ? { text: trimmed, name } : undefined,\n notes: kept ? undefined : [NOT_KEPT_FOR_RELOAD],\n });\n await hold(() => landPaste(id, trimmed, name));\n },\n\n async addRecordedText(text, name) {\n const trimmed = text.trim();\n if (!trimmed) return;\n const max = deps.maxKeptChars();\n const kept = max !== null && trimmed.length <= max;\n const id = set.addPending({\n kind: \"audio\",\n label: name?.trim() || \"Recording\",\n origin: \"Recording\",\n input: kept ? { text: trimmed, name } : undefined,\n notes: kept ? undefined : [NOT_KEPT_FOR_RELOAD],\n });\n await hold(() => landPaste(id, trimmed, name));\n },\n\n async addWebPage(raw) {\n const url = /^https?:\\/\\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;\n const id = set.addPending({ kind: \"web\", label: hostOf(url), origin: url, input: { url } });\n await hold(() => landWebPage(id, url));\n },\n\n beginWebPage(raw) {\n const url = /^https?:\\/\\//i.test(raw.trim()) ? raw.trim() : `https://${raw.trim()}`;\n return set.addPending({ kind: \"web\", label: hostOf(url), origin: url, input: { url } });\n },\n\n async addScrapedPage(page, pendingId) {\n const label = page.title || hostOf(page.url);\n const cardFor = () => {\n if (pendingId && set.restart(pendingId)) {\n set.updateDraft(pendingId, { label, origin: page.url, input: { url: page.url } });\n return pendingId;\n }\n return set.addPending({ kind: \"web\", label, origin: page.url, input: { url: page.url } });\n };\n if (!page.processedDocumentId) {\n // The scrape did not land a Source (or the person edited the text): land what they confirmed.\n const id = cardFor();\n await hold(() => landPaste(id, page.text, label));\n return;\n }\n const pdId = page.processedDocumentId;\n const id = cardFor();\n await hold(async () => {\n let notes: string[] = [];\n try {\n const organizationId = await deps.ensureOrganization();\n const kept = await doors.keep(pdId, { attachTo, organizationId });\n notes = landedNotes(kept.notices);\n } catch (err) {\n notes = deps.waitsForOrganization(err)\n ? [KEEP_WAITING_FOR_ORGANIZATION]\n : [`It is in your Sources, but it could not be kept for reuse${notFiledSuffix}: ${deps.failureSentence(err)}`];\n }\n set.settle(id, {\n label,\n ref: createSourceRef(\"processed_document\", pdId),\n processedDocumentId: pdId,\n notes,\n });\n });\n },\n\n async addUploaded(files, kind) {\n for (const file of files) {\n if (set.hasRef(\"file\", file.fileId)) continue;\n const id = set.addPending({ kind, label: file.name, origin: \"Uploaded file\", fileId: file.fileId });\n const notes = await fileNotes(file.fileId);\n // The Source itself is kept and filed by the recovery from the server's state.\n set.settle(id, { label: file.name, ref: createSourceRef(\"file\", file.fileId), fileId: file.fileId, notes });\n }\n },\n\n async addUploadedRecording(file) {\n const id = set.addPending({\n kind: \"audio\",\n label: file.name,\n origin: \"Recording\",\n fileId: file.fileId,\n input: { fileId: file.fileId },\n });\n await hold(() => transcribeRecording(id, file.fileId, file.name));\n },\n\n addExisting(item) {\n if (set.hasRef(item.token, item.id)) return false;\n set.addReady({\n kind: draftKindForToken(item.token),\n label: item.title,\n ref: createSourceRef(item.token, item.id),\n fileId: item.token === \"file\" ? item.id : undefined,\n processedDocumentId: item.token === \"processed_document\" ? item.id : undefined,\n });\n return true;\n },\n\n async addYouTube(raw) {\n const url = raw.trim();\n const videoId = deps.youtubeId(url);\n if (!videoId) return;\n const id = set.addPending({ kind: \"youtube\", label: \"YouTube video\", origin: url, input: { url } });\n await hold(() => landYouTube(id, url, videoId));\n },\n\n resume(card) {\n const input: SourceIntakeInput | null = resumableInput(card.draft);\n if (!input) return false;\n set.restart(card.id);\n switch (card.draft.kind) {\n case \"paste\":\n void landPaste(card.id, (input.text ?? \"\").trim(), input.name);\n return true;\n case \"web\":\n void landWebPage(card.id, input.url ?? \"\");\n return true;\n case \"youtube\": {\n const videoId = deps.youtubeId(input.url ?? \"\");\n if (!videoId) {\n set.fail(card.id, \"That link is not a YouTube video any more. Remove it and paste the link again.\");\n return true;\n }\n void landYouTube(card.id, input.url ?? \"\", videoId);\n return true;\n }\n case \"audio\":\n if (input.fileId) void transcribeRecording(card.id, input.fileId, card.draft.label);\n else void landPaste(card.id, (input.text ?? \"\").trim(), input.name);\n return true;\n default:\n return false;\n }\n },\n\n async retryFile(card, file) {\n set.restart(card.id);\n set.updateDraft(card.id, { label: file.name, fileId: file.fileId });\n if (card.draft.kind === \"audio\") {\n set.updateDraft(card.id, { input: { fileId: file.fileId } });\n await hold(() => transcribeRecording(card.id, file.fileId, file.name));\n return;\n }\n const notes = await fileNotes(file.fileId);\n set.settle(card.id, { label: file.name, ref: createSourceRef(\"file\", file.fileId), fileId: file.fileId, notes });\n },\n\n async fileLanded(card, processedDocumentId) {\n // Every card opens its Source from now on (and a held keep's waiting note goes).\n const notes = (card.draft.notes ?? []).filter((n) => n !== KEEP_WAITING_FOR_ORGANIZATION);\n set.updateDraft(card.id, { processedDocumentId, notes });\n try {\n const organizationId = await deps.ensureOrganization();\n await doors.keep(processedDocumentId, { attachTo, organizationId });\n } catch (err) {\n if (deps.waitsForOrganization(err)) {\n // Kept again by the recovery once an organization is set.\n set.updateDraft(card.id, { processedDocumentId, notes: [...notes, KEEP_WAITING_FOR_ORGANIZATION] });\n return;\n }\n set.updateDraft(card.id, {\n processedDocumentId,\n notes: [\n ...notes,\n `It was read, but its Source could not be kept for reuse${notFiledSuffix}: ${deps.failureSentence(err)}`,\n ],\n });\n }\n },\n };\n return intake;\n}\n","/**\n * Recovery — the UI-free half of \"never lose input\" (USI-3b), as decisions and\n * one step function. A React binding (`@ai-matrx/agents/sources/react`\n * `useSourceRecovery`) schedules them; any other client can call them itself.\n *\n * 1. A Source a reload cut off while it was landing, whose input the draft\n * kept (`interrupted.ts`), is handed back to the door once — the door\n * dedupes by content hash, so a second landing reuses the same Source.\n * 2. A landing that waited for an organization is landed again the moment one\n * is set — from the card's kept input, or, for a read Source whose keep\n * waited, by keeping it again. State, never an in-memory queue.\n * 3. A stored file's Source (new upload, reused copy, or picked file) is read\n * from the SERVER's state (`fileSource.ts`): kept and filed once it exists,\n * the one run started only when nothing is reading it, re-attached after a\n * reload — never a duplicate run.\n *\n * The once-per-card guards live on `globalThis` (one registry however many\n * loader graphs import this module), so two inputs on one surface, or a\n * re-mount, never land the same card twice.\n */\n\nimport type { SourceSetActions } from \"./controller\";\nimport {\n fileCardHeldForOrganization,\n isWaitingFileCard,\n nextFileStep,\n type FileSourceStatus,\n} from \"./fileSource\";\nimport type { SourceIntake } from \"./intake\";\nimport { KEEP_WAITING_FOR_ORGANIZATION, RELOADED_RESUMING, WAITING_FOR_ORGANIZATION } from \"./interrupted\";\nimport type { SourceCardModel } from \"./types\";\n\ninterface RecoveryGuards {\n resumedCards: Set<string>;\n keptFileSources: Set<string>;\n startedFileRuns: Set<string>;\n}\n\n// Module-level state is banned in our packages (dual ESM/CJS graphs would\n// split it): the guards live on globalThis under one registered symbol.\nconst GUARDS = Symbol.for(\"ai-matrx.agents.sources.recovery-guards\");\n\nexport function sourceRecoveryGuards(): RecoveryGuards {\n const slot = globalThis as unknown as Record<symbol, RecoveryGuards | undefined>;\n let guards = slot[GUARDS];\n if (!guards) {\n guards = { resumedCards: new Set(), keptFileSources: new Set(), startedFileRuns: new Set() };\n slot[GUARDS] = guards;\n }\n return guards;\n}\n\n/** Cards a reload cut off whose kept input lands again now. */\nexport function cardsToResume(cards: readonly SourceCardModel[]): SourceCardModel[] {\n return cards.filter((c) => c.status === \"error\" && c.error === RELOADED_RESUMING);\n}\n\n/** Resume each cut-off card once (per card id, across every input). */\nexport function resumeInterrupted(cards: readonly SourceCardModel[], intake: Pick<SourceIntake, \"resume\">): void {\n const { resumedCards } = sourceRecoveryGuards();\n for (const card of cardsToResume(cards)) {\n if (resumedCards.has(card.id)) continue;\n resumedCards.add(card.id);\n intake.resume(card);\n }\n}\n\n/** Cards that waited for an organization (a landing, or a read Source's keep). */\nexport function cardsWaitingForOrganization(cards: readonly SourceCardModel[]): SourceCardModel[] {\n return cards.filter(\n (s) =>\n (s.status === \"error\" && s.error === WAITING_FOR_ORGANIZATION) ||\n (!!s.draft.processedDocumentId && !!s.draft.notes?.includes(KEEP_WAITING_FOR_ORGANIZATION)),\n );\n}\n\n/** An organization is known now: land or keep every card that waited for one. */\nexport function continueAfterOrganization(\n cards: readonly SourceCardModel[],\n intake: Pick<SourceIntake, \"resume\" | \"fileLanded\">,\n): void {\n for (const card of cards) {\n if (card.status === \"error\" && card.error === WAITING_FOR_ORGANIZATION) {\n intake.resume(card);\n } else if (card.draft.processedDocumentId && card.draft.notes?.includes(KEEP_WAITING_FOR_ORGANIZATION)) {\n void intake.fileLanded(card, card.draft.processedDocumentId);\n }\n }\n}\n\n/** The host's processing runner, as far as the recovery needs it. */\nexport interface SourceFileRunner {\n jobs: ReadonlyArray<{ cldFileId?: string | null | undefined; status: string; processedDocumentId?: string | null | undefined }>;\n runForCldFile(fileId: string, label: string, reason: string): Promise<unknown>;\n}\n\nexport interface FileRecoveryDeps {\n /** The organization the person picked (null = none yet). */\n organizationId: string | null | undefined;\n /** The server's `/files/{id}/rag-status` read. */\n readFileState(fileId: string, signal?: AbortSignal): Promise<FileSourceStatus>;\n /** The host's lookup of a file's own organization (omitted = unknown). */\n fileOrganizationId?: ((fileId: string) => string | null | undefined) | undefined;\n}\n\n/** A file card the recovery may ask about now (waiting, and not held for an organization). */\nexport function isAskableFileCard(card: SourceCardModel, deps: Pick<FileRecoveryDeps, \"organizationId\" | \"fileOrganizationId\">): boolean {\n return isWaitingFileCard(card) && !fileCardHeldForOrganization(card, deps.organizationId, deps.fileOrganizationId);\n}\n\n/**\n * One look at every askable file card: a Source → keep and file it; a live run\n * → look again; nothing reading it → start the one run (once); unreadable →\n * say so. Returns true while any card still waits (look again later).\n */\nexport async function lookAtFileCards(\n cards: readonly SourceCardModel[],\n ctx: {\n set: Pick<SourceSetActions, \"fail\" | \"manifest\">;\n intake: Pick<SourceIntake, \"fileLanded\">;\n runner: SourceFileRunner;\n signal: AbortSignal;\n } & FileRecoveryDeps,\n): Promise<boolean> {\n const { keptFileSources, startedFileRuns } = sourceRecoveryGuards();\n let anyWaiting = false;\n for (const card of cards.filter((c) => isAskableFileCard(c, ctx))) {\n const fileId = card.draft.fileId as string;\n const guard = `${card.id}:${fileId}`;\n if (keptFileSources.has(guard)) continue;\n let status: FileSourceStatus | null = null;\n try {\n status = await ctx.readFileState(fileId, ctx.signal);\n } catch {\n // A missed read is not an answer — look again next round.\n if (ctx.signal.aborted) return false;\n anyWaiting = true;\n continue;\n }\n if (ctx.signal.aborted) return false;\n const localJob = ctx.runner.jobs.find((j) => j.cldFileId === fileId) ?? null;\n const step = nextFileStep(status, {\n started: startedFileRuns.has(guard),\n localRunning: localJob?.status === \"running\",\n });\n const localPdId = localJob?.processedDocumentId ?? null;\n if (step.do === \"keep\" || localPdId) {\n keptFileSources.add(guard);\n const pdId = step.do === \"keep\" ? step.processedDocumentId : (localPdId as string);\n await ctx.intake.fileLanded(card, pdId);\n // The pointer did not change, so nothing else re-measures: ask once now.\n void ctx.set.manifest();\n } else if (step.do === \"start\") {\n startedFileRuns.add(guard);\n anyWaiting = true;\n void ctx.runner.runForCldFile(fileId, card.draft.label, \"Reading it into a Source\").catch(() => undefined);\n } else if (step.do === \"unreadable\") {\n keptFileSources.add(guard);\n ctx.set.fail(card.id, step.reason);\n } else {\n anyWaiting = true;\n }\n }\n return anyWaiting;\n}\n"],"mappings":"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","names":["capped","id"]}