@inflexa-ai/harness 0.1.1 → 0.2.0

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.
Files changed (268) hide show
  1. package/dist/agents/conversation-agent.d.ts +12 -11
  2. package/dist/agents/conversation-agent.js +30 -33
  3. package/dist/agents/report-builder.js +2 -1
  4. package/dist/agents/sandbox/bulk-transcriptomics-agent.js +1 -1
  5. package/dist/agents/sandbox/cheminformatics-agent.js +1 -19
  6. package/dist/agents/sandbox/chromatin-agent.js +1 -10
  7. package/dist/agents/sandbox/dna-methylation-agent.js +1 -10
  8. package/dist/agents/sandbox/drug-repurposing-agent.js +4 -14
  9. package/dist/agents/sandbox/enrichment-agent.js +1 -10
  10. package/dist/agents/sandbox/ephemeral-executor.js +1 -10
  11. package/dist/agents/sandbox/genomic-variant-agent.js +1 -3
  12. package/dist/agents/sandbox/immune-profiling-agent.js +1 -13
  13. package/dist/agents/sandbox/metabolomics-agent.js +1 -1
  14. package/dist/agents/sandbox/microbiome-agent.js +1 -1
  15. package/dist/agents/sandbox/multi-omics-integration-agent.js +1 -12
  16. package/dist/agents/sandbox/multimodal-sc-agent.js +1 -1
  17. package/dist/agents/sandbox/network-agent.js +1 -10
  18. package/dist/agents/sandbox/pkpd-clinical-response-agent.js +2 -8
  19. package/dist/agents/sandbox/proteomics-agent.js +1 -1
  20. package/dist/agents/sandbox/scientific-executor.js +1 -10
  21. package/dist/agents/sandbox/shared.d.ts +17 -6
  22. package/dist/agents/sandbox/shared.js +49 -38
  23. package/dist/agents/sandbox/single-cell-agent.js +1 -1
  24. package/dist/agents/sandbox/spatial-omics-agent.js +1 -1
  25. package/dist/agents/sandbox/statistical-modeling-agent.js +1 -1
  26. package/dist/agents/sandbox/translational-safety-agent.js +3 -9
  27. package/dist/agents/sandbox/types.d.ts +1 -1
  28. package/dist/agents/system-prompt.d.ts +37 -11
  29. package/dist/agents/system-prompt.js +35 -12
  30. package/dist/app/data-profile-orientation.d.ts +34 -0
  31. package/dist/app/data-profile-orientation.js +117 -0
  32. package/dist/contracts/schemas/chat-parts.d.ts +9 -9
  33. package/dist/execution/artifact-metadata.js +2 -1
  34. package/dist/execution/ephemeral-runner.d.ts +13 -0
  35. package/dist/execution/ephemeral-runner.js +23 -1
  36. package/dist/execution/run-synthesis.js +20 -19
  37. package/dist/execution/step-summary.js +2 -1
  38. package/dist/index.d.ts +6 -2
  39. package/dist/index.js +19 -5
  40. package/dist/loop/__fixtures__/scripted-provider.d.ts +2 -2
  41. package/dist/loop/__fixtures__/scripted-provider.js +2 -1
  42. package/dist/loop/metrics.d.ts +33 -1
  43. package/dist/loop/metrics.js +56 -2
  44. package/dist/loop/run-agent.d.ts +13 -1
  45. package/dist/loop/run-agent.js +19 -4
  46. package/dist/memory/card-builders.d.ts +8 -1
  47. package/dist/memory/card-builders.js +20 -3
  48. package/dist/memory/reconstruct-cards.js +4 -3
  49. package/dist/memory/thread-history.d.ts +27 -2
  50. package/dist/memory/thread-history.js +45 -5
  51. package/dist/memory/working-memory.d.ts +93 -10
  52. package/dist/memory/working-memory.js +220 -84
  53. package/dist/prompts/SOUL.d.ts +22 -9
  54. package/dist/prompts/SOUL.js +56 -37
  55. package/dist/prompts/analogical-reasoner.d.ts +1 -1
  56. package/dist/prompts/analogical-reasoner.js +2 -2
  57. package/dist/prompts/briefing.d.ts +100 -0
  58. package/dist/prompts/briefing.js +166 -0
  59. package/dist/prompts/conversation.d.ts +1 -1
  60. package/dist/prompts/conversation.js +94 -440
  61. package/dist/prompts/literature-reviewer.d.ts +1 -1
  62. package/dist/prompts/literature-reviewer.js +10 -10
  63. package/dist/prompts/planner.js +28 -59
  64. package/dist/prompts/report-builder.d.ts +1 -1
  65. package/dist/prompts/report-builder.js +71 -24
  66. package/dist/prompts/sandbox/bulk-transcriptomics-agent.d.ts +1 -1
  67. package/dist/prompts/sandbox/bulk-transcriptomics-agent.js +2 -7
  68. package/dist/prompts/sandbox/cheminformatics-agent.d.ts +1 -1
  69. package/dist/prompts/sandbox/cheminformatics-agent.js +11 -15
  70. package/dist/prompts/sandbox/chromatin-agent.d.ts +1 -1
  71. package/dist/prompts/sandbox/chromatin-agent.js +3 -7
  72. package/dist/prompts/sandbox/data-profiler.d.ts +1 -1
  73. package/dist/prompts/sandbox/data-profiler.js +13 -8
  74. package/dist/prompts/sandbox/dna-methylation-agent.d.ts +1 -1
  75. package/dist/prompts/sandbox/dna-methylation-agent.js +2 -7
  76. package/dist/prompts/sandbox/drug-repurposing-agent.d.ts +1 -1
  77. package/dist/prompts/sandbox/drug-repurposing-agent.js +15 -16
  78. package/dist/prompts/sandbox/enrichment-agent.d.ts +1 -1
  79. package/dist/prompts/sandbox/enrichment-agent.js +2 -9
  80. package/dist/prompts/sandbox/genomic-variant-agent.d.ts +1 -1
  81. package/dist/prompts/sandbox/genomic-variant-agent.js +2 -6
  82. package/dist/prompts/sandbox/immune-profiling-agent.d.ts +1 -1
  83. package/dist/prompts/sandbox/immune-profiling-agent.js +3 -8
  84. package/dist/prompts/sandbox/metabolomics-agent.d.ts +1 -1
  85. package/dist/prompts/sandbox/metabolomics-agent.js +1 -7
  86. package/dist/prompts/sandbox/microbiome-agent.d.ts +1 -1
  87. package/dist/prompts/sandbox/microbiome-agent.js +2 -7
  88. package/dist/prompts/sandbox/multi-omics-integration-agent.d.ts +1 -1
  89. package/dist/prompts/sandbox/multi-omics-integration-agent.js +2 -8
  90. package/dist/prompts/sandbox/multimodal-sc-agent.d.ts +1 -1
  91. package/dist/prompts/sandbox/multimodal-sc-agent.js +2 -7
  92. package/dist/prompts/sandbox/network-agent.d.ts +1 -1
  93. package/dist/prompts/sandbox/network-agent.js +2 -7
  94. package/dist/prompts/sandbox/proteomics-agent.d.ts +1 -1
  95. package/dist/prompts/sandbox/proteomics-agent.js +2 -9
  96. package/dist/prompts/sandbox/single-cell-agent.d.ts +1 -1
  97. package/dist/prompts/sandbox/single-cell-agent.js +2 -9
  98. package/dist/prompts/sandbox/spatial-omics-agent.d.ts +1 -1
  99. package/dist/prompts/sandbox/spatial-omics-agent.js +3 -6
  100. package/dist/prompts/sandbox/statistical-modeling-agent.d.ts +1 -1
  101. package/dist/prompts/sandbox/statistical-modeling-agent.js +2 -7
  102. package/dist/prompts/sandbox/translational-safety-agent.d.ts +1 -1
  103. package/dist/prompts/sandbox/translational-safety-agent.js +13 -14
  104. package/dist/prompts/sandbox-standards.d.ts +22 -14
  105. package/dist/prompts/sandbox-standards.js +91 -71
  106. package/dist/prompts/synthesis-agent.d.ts +1 -1
  107. package/dist/prompts/synthesis-agent.js +33 -131
  108. package/dist/provenance/collector.js +1 -1
  109. package/dist/providers/ai-sdk.js +31 -4
  110. package/dist/providers/prompt-cache.d.ts +74 -0
  111. package/dist/providers/prompt-cache.js +77 -0
  112. package/dist/providers/types.d.ts +33 -0
  113. package/dist/reference-data/catalog.d.ts +131 -0
  114. package/dist/reference-data/catalog.js +348 -0
  115. package/dist/reference-data/receipt.d.ts +41 -0
  116. package/dist/reference-data/receipt.js +40 -0
  117. package/dist/schemas/data-profile-schemas.js +5 -3
  118. package/dist/schemas/plan-schemas.d.ts +21 -21
  119. package/dist/schemas/plan-schemas.js +9 -3
  120. package/dist/schemas/run-synthesis.d.ts +8 -4
  121. package/dist/schemas/run-synthesis.js +92 -56
  122. package/dist/schemas/validate-plan.js +1 -1
  123. package/dist/schemas/workflow-state.d.ts +7 -1
  124. package/dist/schemas/workflow-state.js +33 -19
  125. package/dist/state/artifacts.d.ts +13 -0
  126. package/dist/state/artifacts.js +27 -0
  127. package/dist/state/data-profile.d.ts +64 -5
  128. package/dist/state/index.d.ts +3 -3
  129. package/dist/state/index.js +1 -1
  130. package/dist/tasks/data-profile.d.ts +20 -2
  131. package/dist/tasks/data-profile.js +71 -22
  132. package/dist/tools/bio/chembl.d.ts +38 -0
  133. package/dist/tools/bio/chembl.js +138 -0
  134. package/dist/tools/bio/comptox.d.ts +50 -0
  135. package/dist/tools/bio/comptox.js +149 -0
  136. package/dist/tools/bio/get-impc-ko-profile.js +9 -6
  137. package/dist/tools/bio/index.d.ts +5 -17
  138. package/dist/tools/bio/index.js +5 -17
  139. package/dist/tools/bio/keys.d.ts +14 -9
  140. package/dist/tools/bio/keys.js +16 -16
  141. package/dist/tools/bio/opentargets.d.ts +38 -0
  142. package/dist/tools/bio/opentargets.js +89 -0
  143. package/dist/tools/bio/pubchem.d.ts +29 -0
  144. package/dist/tools/bio/pubchem.js +92 -0
  145. package/dist/tools/bio/pubmed.d.ts +51 -0
  146. package/dist/tools/bio/pubmed.js +100 -0
  147. package/dist/tools/bio/search-bgee-expression.js +12 -6
  148. package/dist/tools/bio/search-clinical-trials.js +16 -5
  149. package/dist/tools/bio/search-faers.js +8 -4
  150. package/dist/tools/bio/search-geo-datasets.js +20 -6
  151. package/dist/tools/bio/search-gwas-catalog.d.ts +1 -1
  152. package/dist/tools/bio/search-pharmgkb.js +10 -4
  153. package/dist/tools/display/index.d.ts +1 -0
  154. package/dist/tools/display/index.js +1 -0
  155. package/dist/tools/display/normalize-echart-spec.d.ts +61 -0
  156. package/dist/tools/display/normalize-echart-spec.js +211 -0
  157. package/dist/tools/display/show-user.d.ts +6 -1
  158. package/dist/tools/display/show-user.js +25 -12
  159. package/dist/tools/execute-plan.js +5 -2
  160. package/dist/tools/iterate-report.d.ts +168 -118
  161. package/dist/tools/iterate-report.js +334 -96
  162. package/dist/tools/lib/chembl-client.d.ts +12 -0
  163. package/dist/tools/lib/chembl-client.js +127 -0
  164. package/dist/tools/lib/ctx-ops.d.ts +224 -0
  165. package/dist/tools/lib/ctx-ops.js +450 -0
  166. package/dist/tools/lib/iuphar-client.js +10 -1
  167. package/dist/tools/lib/openfda-client.js +11 -3
  168. package/dist/tools/lib/pathway-client.js +10 -4
  169. package/dist/tools/lib/pubchem-ops.d.ts +74 -0
  170. package/dist/tools/lib/pubchem-ops.js +224 -0
  171. package/dist/tools/memory/update-working-memory.d.ts +45 -7
  172. package/dist/tools/memory/update-working-memory.js +111 -41
  173. package/dist/tools/report/index.d.ts +3 -2
  174. package/dist/tools/report/index.js +3 -2
  175. package/dist/tools/research/generate-analogy-report.js +25 -12
  176. package/dist/tools/research/generate-plan.d.ts +12 -5
  177. package/dist/tools/research/generate-plan.js +168 -37
  178. package/dist/tools/research/index.d.ts +1 -0
  179. package/dist/tools/research/index.js +1 -0
  180. package/dist/tools/research/inspect-data-profile.d.ts +85 -0
  181. package/dist/tools/research/inspect-data-profile.js +161 -0
  182. package/dist/tools/research/literature-reviewer.js +3 -4
  183. package/dist/tools/sandbox/list-available-packages.d.ts +79 -5
  184. package/dist/tools/sandbox/list-available-packages.js +152 -10
  185. package/dist/tools/sandbox/list-available-refs.d.ts +141 -5
  186. package/dist/tools/sandbox/list-available-refs.js +647 -134
  187. package/dist/tools/sandbox/report-blocker.d.ts +39 -9
  188. package/dist/tools/sandbox/report-blocker.js +43 -20
  189. package/dist/tools/workspace/read-file.js +4 -5
  190. package/dist/tools/workspace/run-exec.d.ts +4 -4
  191. package/dist/tools/workspace/run-exec.js +4 -4
  192. package/dist/tools/workspace/show-file.js +10 -6
  193. package/dist/tools/workspace/show-plan.js +12 -6
  194. package/dist/tools/workspace/workspace-search.d.ts +1 -1
  195. package/dist/tools/workspace/workspace-search.js +11 -5
  196. package/dist/workflows/execute-analysis.d.ts +43 -4
  197. package/dist/workflows/execute-analysis.js +107 -6
  198. package/dist/workflows/target-assessment/lib/citation-validator.js +2 -2
  199. package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.js +2 -1
  200. package/dist/workspace/paths.d.ts +2 -2
  201. package/dist/workspace/paths.js +2 -2
  202. package/package.json +33 -33
  203. package/dist/execution/filesystem-artifact-registry.d.ts +0 -57
  204. package/dist/execution/filesystem-artifact-registry.js +0 -92
  205. package/dist/lib/identifiers.d.ts +0 -8
  206. package/dist/lib/identifiers.js +0 -10
  207. package/dist/lib/mime-detect.d.ts +0 -17
  208. package/dist/lib/mime-detect.js +0 -29
  209. package/dist/lib/streamed-download.d.ts +0 -28
  210. package/dist/lib/streamed-download.js +0 -111
  211. package/dist/lib/trace-context.d.ts +0 -11
  212. package/dist/lib/trace-context.js +0 -49
  213. package/dist/providers/llm-capabilities.d.ts +0 -33
  214. package/dist/providers/llm-capabilities.js +0 -58
  215. package/dist/schemas/render-step-prompt.d.ts +0 -32
  216. package/dist/schemas/render-step-prompt.js +0 -76
  217. package/dist/tools/bio/find-approval-precedent.d.ts +0 -32
  218. package/dist/tools/bio/find-approval-precedent.js +0 -72
  219. package/dist/tools/bio/get-article-details.d.ts +0 -11
  220. package/dist/tools/bio/get-article-details.js +0 -20
  221. package/dist/tools/bio/get-article-full-text.d.ts +0 -19
  222. package/dist/tools/bio/get-article-full-text.js +0 -32
  223. package/dist/tools/bio/get-bioactivity.d.ts +0 -11
  224. package/dist/tools/bio/get-bioactivity.js +0 -23
  225. package/dist/tools/bio/get-drug-info.d.ts +0 -9
  226. package/dist/tools/bio/get-drug-info.js +0 -22
  227. package/dist/tools/bio/get-mechanism.d.ts +0 -8
  228. package/dist/tools/bio/get-mechanism.js +0 -18
  229. package/dist/tools/bio/get-pubchem-assays.d.ts +0 -22
  230. package/dist/tools/bio/get-pubchem-assays.js +0 -107
  231. package/dist/tools/bio/get-pubchem-cross-refs.d.ts +0 -15
  232. package/dist/tools/bio/get-pubchem-cross-refs.js +0 -68
  233. package/dist/tools/bio/get-target-safety.d.ts +0 -18
  234. package/dist/tools/bio/get-target-safety.js +0 -26
  235. package/dist/tools/bio/search-compounds.d.ts +0 -22
  236. package/dist/tools/bio/search-compounds.js +0 -160
  237. package/dist/tools/bio/search-ctx-chemical.d.ts +0 -50
  238. package/dist/tools/bio/search-ctx-chemical.js +0 -130
  239. package/dist/tools/bio/search-ctx-exposure.d.ts +0 -55
  240. package/dist/tools/bio/search-ctx-exposure.js +0 -176
  241. package/dist/tools/bio/search-ctx-hazard.d.ts +0 -111
  242. package/dist/tools/bio/search-ctx-hazard.js +0 -178
  243. package/dist/tools/bio/search-opentargets.d.ts +0 -11
  244. package/dist/tools/bio/search-opentargets.js +0 -25
  245. package/dist/tools/bio/search-pubchem-compound.d.ts +0 -26
  246. package/dist/tools/bio/search-pubchem-compound.js +0 -110
  247. package/dist/tools/bio/search-pubmed.d.ts +0 -17
  248. package/dist/tools/bio/search-pubmed.js +0 -31
  249. package/dist/tools/bio/search-targets.d.ts +0 -9
  250. package/dist/tools/bio/search-targets.js +0 -20
  251. package/dist/tools/bio/search-toxcast.d.ts +0 -36
  252. package/dist/tools/bio/search-toxcast.js +0 -141
  253. package/dist/workflows/register-workflows.d.ts +0 -51
  254. package/dist/workflows/register-workflows.js +0 -48
  255. package/dist/workflows/resume-execute-analysis.d.ts +0 -70
  256. package/dist/workflows/resume-execute-analysis.js +0 -80
  257. package/dist/workflows/target-assessment/correction-loop.d.ts +0 -45
  258. package/dist/workflows/target-assessment/correction-loop.js +0 -62
  259. package/dist/workflows/target-assessment/steps/phase0-resolve.d.ts +0 -71
  260. package/dist/workflows/target-assessment/steps/phase0-resolve.js +0 -21
  261. package/dist/workflows/target-assessment/steps/phase1-aggregate.d.ts +0 -1018
  262. package/dist/workflows/target-assessment/steps/phase1-aggregate.js +0 -25
  263. package/dist/workspace/mount-strategy.d.ts +0 -50
  264. package/dist/workspace/mount-strategy.js +0 -67
  265. package/dist/workspace/provenance-collector.d.ts +0 -34
  266. package/dist/workspace/provenance-collector.js +0 -16
  267. package/dist/workspace/workspace-paths.d.ts +0 -26
  268. package/dist/workspace/workspace-paths.js +0 -31
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Prompt-cache policy → provider wire options.
3
+ *
4
+ * This is the **only** place in the harness that names a vendor for caching.
5
+ * Everything upstream — `PromptCachePolicy`, `ChatUsage`, `RunAgentOptions` —
6
+ * speaks the neutral harness concept; this module translates it once, at the
7
+ * provider seam, so the loop never learns which vendor it is talking to.
8
+ *
9
+ * ## Why the emitted options are safe on every provider
10
+ *
11
+ * The AI SDK's `providerOptions` is a namespaced bag: each provider reads only
12
+ * `providerOptions[<its own name>]` and ignores every other key
13
+ * (`parseProviderOptions` in `@ai-sdk/provider-utils` returns `undefined` when
14
+ * its namespace is absent). So the `anthropic` namespace is inert — not an
15
+ * error — on an OpenAI-compatible model, which is exactly what we want: that
16
+ * family does automatic server-side prefix caching and needs no directive.
17
+ *
18
+ * ## What the Anthropic namespace does
19
+ *
20
+ * A request-level `cacheControl` makes the provider emit a single top-level
21
+ * `cache_control` marker; the server then places the breakpoint on the last
22
+ * cacheable block, so the whole prefix (tools → system → history) is cached
23
+ * without the harness hand-placing per-block markers.
24
+ *
25
+ * ## Cache defeaters — what silently kills the hit rate
26
+ *
27
+ * The cache keys on an *exact prefix*. Anything that perturbs the head of the
28
+ * request invalidates everything after it. One known defeater remains in this
29
+ * codebase, flagged at its own site as a separate change:
30
+ *
31
+ * 1. `runAgent`'s forced wrap-up swaps the tool set to `{}` — tools sit at the
32
+ * very front of the prefix, so that one call reads nothing back and rewrites
33
+ * the cache from scratch (`loop/run-agent.ts`).
34
+ *
35
+ * `loadRecent`'s history eviction used to be a second defeater — it advanced the
36
+ * window one turn per turn, shifting the message prefix every request. It now
37
+ * evicts in whole blocks so the prefix holds still between block boundaries
38
+ * (`memory/thread-history.ts`).
39
+ *
40
+ * A sandbox agent's system prompt is NOT one of them: it is a pure function of
41
+ * its agent type, byte-identical across every step of every run, and the per-step
42
+ * paths ride in the step's briefing instead (`agents/sandbox/shared.ts`,
43
+ * `prompts/briefing.ts`). Keep it that way — one interpolated id or path there
44
+ * makes every step's ~20k-char prefix unique.
45
+ *
46
+ * ## Where caching is a no-op regardless
47
+ *
48
+ * The Claude Max OAuth path does not honour cache directives, and the OSS CLI
49
+ * defaults to routing through a local CLIProxyAPI on exactly that path. Caching
50
+ * only engages against a direct API key or a gateway. The cache-token metrics
51
+ * (`loop/metrics.ts`) are what tell the two apart at runtime — a flat-zero
52
+ * `cache_read_tokens` counter is the symptom.
53
+ */
54
+ /**
55
+ * The default policy: cache with the 5-minute TTL.
56
+ *
57
+ * A cache write costs a premium over a plain input token and only pays for
58
+ * itself once something reads it back, so caching is worth it exactly when a
59
+ * shared prefix is re-sent within the TTL. An agent loop always re-sends: every
60
+ * iteration replays the same tools + system + the whole transcript so far, and
61
+ * even a two-iteration run breaks even. The 5m TTL covers a live loop; `1h` is
62
+ * for hosts that also want the *next* turn on a thread to land warm, and costs
63
+ * more per write. One-shot LLM calls should stay `"off"` — they pay the write
64
+ * premium for a cache nothing ever reads.
65
+ */
66
+ export const DEFAULT_PROMPT_CACHE = { ttl: "5m" };
67
+ /**
68
+ * Translate a neutral cache policy into provider wire options.
69
+ *
70
+ * Returns `undefined` for `"off"` so the caller can leave `providerOptions`
71
+ * entirely unset rather than sending an empty bag.
72
+ */
73
+ export function promptCacheProviderOptions(policy) {
74
+ if (policy === "off")
75
+ return undefined;
76
+ return { anthropic: { cacheControl: { type: "ephemeral", ttl: policy.ttl } } };
77
+ }
@@ -24,12 +24,45 @@ export interface ChatRequest {
24
24
  };
25
25
  readonly providerOptions?: ProviderOptions;
26
26
  }
27
+ /**
28
+ * Vendor-neutral prompt-cache policy — a harness concept, not a vendor one.
29
+ *
30
+ * `{ ttl }` asks the provider to cache the request prefix (system + tools +
31
+ * message history) for that lifetime; `"off"` sends no cache directive at all.
32
+ * Vendors that cache automatically (the OpenAI-compatible family does prefix
33
+ * caching server-side, unprompted) need no directive, so the policy is a no-op
34
+ * for them rather than an error — see `./prompt-cache.ts`, the single place the
35
+ * harness translates this into vendor wire options.
36
+ */
37
+ export type PromptCachePolicy = {
38
+ readonly ttl: "5m" | "1h";
39
+ } | "off";
40
+ /**
41
+ * Token accounting for one chat call, in harness-neutral names.
42
+ *
43
+ * `inputTokens` is the *total* billed prefix — cached and uncached alike — so a
44
+ * cache hit rate is `cacheReadInputTokens / inputTokens`, not a ratio against
45
+ * some separate uncached figure. `cacheCreationInputTokens` is the write that
46
+ * seeds the cache (billed at a premium; it only pays for itself once a later
47
+ * call reads it back).
48
+ *
49
+ * Every field is optional: a provider that reports no usage at all, or reports
50
+ * totals without a cache breakdown, is legitimate. Absent means "not reported",
51
+ * never "zero".
52
+ */
53
+ export interface ChatUsage {
54
+ readonly inputTokens?: number;
55
+ readonly outputTokens?: number;
56
+ readonly cacheCreationInputTokens?: number;
57
+ readonly cacheReadInputTokens?: number;
58
+ }
27
59
  export interface ChatResponse {
28
60
  readonly message: Extract<ModelMessage, {
29
61
  role: "assistant";
30
62
  }>;
31
63
  readonly finishReason: FinishReason;
32
64
  readonly rawFinishReason?: string;
65
+ readonly usage?: ChatUsage;
33
66
  }
34
67
  export type ChatStreamEvent = {
35
68
  readonly type: "text-delta";
@@ -0,0 +1,131 @@
1
+ import { type Result } from "neverthrow";
2
+ import { z } from "zod";
3
+ /** Schema version for the checked-in reference-data catalog. */
4
+ export declare const REFERENCE_DATA_CATALOG_VERSION: 1;
5
+ /** Dataset-relative destination of one artifact below its install path. */
6
+ export declare const ReferenceArtifactPathSchema: z.ZodString;
7
+ /** Lowercase SHA-256 digest of one artifact's bytes. */
8
+ export declare const ReferenceSha256Schema: z.ZodString;
9
+ /** One immutable final file distributed for a reference dataset. */
10
+ export declare const ReferenceArtifactSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
11
+ integrity: z.ZodLiteral<"pinned">;
12
+ path: z.ZodString;
13
+ url: z.ZodURL;
14
+ bytes: z.ZodNumber;
15
+ sha256: z.ZodString;
16
+ }, z.core.$strict>, z.ZodObject<{
17
+ integrity: z.ZodLiteral<"unpinned">;
18
+ path: z.ZodString;
19
+ url: z.ZodURL;
20
+ }, z.core.$strict>], "integrity">;
21
+ /** Which integrity guarantee an artifact can actually offer. */
22
+ export type ReferenceIntegrity = z.infer<typeof ReferenceArtifactSchema>["integrity"];
23
+ /** Provenance and licensing information for one supported reference dataset. */
24
+ export declare const ReferenceDatasetSchema: z.ZodObject<{
25
+ id: z.ZodString;
26
+ version: z.ZodString;
27
+ title: z.ZodString;
28
+ description: z.ZodString;
29
+ sourceUrl: z.ZodURL;
30
+ license: z.ZodObject<{
31
+ identifier: z.ZodString;
32
+ url: z.ZodOptional<z.ZodURL>;
33
+ }, z.core.$strip>;
34
+ recommendation: z.ZodObject<{
35
+ group: z.ZodString;
36
+ recommended: z.ZodBoolean;
37
+ }, z.core.$strip>;
38
+ artifacts: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
39
+ integrity: z.ZodLiteral<"pinned">;
40
+ path: z.ZodString;
41
+ url: z.ZodURL;
42
+ bytes: z.ZodNumber;
43
+ sha256: z.ZodString;
44
+ }, z.core.$strict>, z.ZodObject<{
45
+ integrity: z.ZodLiteral<"unpinned">;
46
+ path: z.ZodString;
47
+ url: z.ZodURL;
48
+ }, z.core.$strict>], "integrity">>;
49
+ }, z.core.$strip>;
50
+ /** Versioned canonical catalog consumed identically by every harness embedder. */
51
+ export declare const ReferenceDataCatalogSchema: z.ZodObject<{
52
+ version: z.ZodLiteral<1>;
53
+ datasets: z.ZodArray<z.ZodObject<{
54
+ id: z.ZodString;
55
+ version: z.ZodString;
56
+ title: z.ZodString;
57
+ description: z.ZodString;
58
+ sourceUrl: z.ZodURL;
59
+ license: z.ZodObject<{
60
+ identifier: z.ZodString;
61
+ url: z.ZodOptional<z.ZodURL>;
62
+ }, z.core.$strip>;
63
+ recommendation: z.ZodObject<{
64
+ group: z.ZodString;
65
+ recommended: z.ZodBoolean;
66
+ }, z.core.$strip>;
67
+ artifacts: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
68
+ integrity: z.ZodLiteral<"pinned">;
69
+ path: z.ZodString;
70
+ url: z.ZodURL;
71
+ bytes: z.ZodNumber;
72
+ sha256: z.ZodString;
73
+ }, z.core.$strict>, z.ZodObject<{
74
+ integrity: z.ZodLiteral<"unpinned">;
75
+ path: z.ZodString;
76
+ url: z.ZodURL;
77
+ }, z.core.$strict>], "integrity">>;
78
+ }, z.core.$strip>>;
79
+ }, z.core.$strip>;
80
+ type DeepReadonly<T> = T extends (...args: never[]) => unknown ? T : T extends readonly (infer Item)[] ? readonly DeepReadonly<Item>[] : T extends object ? {
81
+ readonly [Key in keyof T]: DeepReadonly<T[Key]>;
82
+ } : T;
83
+ export type ReferenceArtifact = DeepReadonly<z.infer<typeof ReferenceArtifactSchema>>;
84
+ export type ReferenceDataset = DeepReadonly<z.infer<typeof ReferenceDatasetSchema>>;
85
+ export type ReferenceDataCatalog = DeepReadonly<z.infer<typeof ReferenceDataCatalogSchema>>;
86
+ /**
87
+ * Stable identity of one artifact within the catalog, independent of its URL.
88
+ * Embedders key resumable partials off this, so a moved upstream URL does not
89
+ * orphan a half-finished transfer.
90
+ */
91
+ export declare function referenceArtifactKey(dataset: {
92
+ readonly id: string;
93
+ readonly version: string;
94
+ }, artifact: {
95
+ readonly path: string;
96
+ }): string;
97
+ /**
98
+ * Canonical release catalog. Every artifact is fetched directly from the third
99
+ * party that publishes it; this project hosts, mirrors, and redistributes
100
+ * nothing. Entries are added only with real upstream URLs, provenance, and
101
+ * licensing data — plus a size and digest whenever the upstream publishes
102
+ * immutable bytes we can pin to.
103
+ *
104
+ * `version` is the dataset's upstream release identifier. Datasets built on an
105
+ * upstream that has no immutable release — NCBI regenerates `gene_info` daily,
106
+ * Reactome overwrites `current` and deletes prior releases — are versioned
107
+ * `current` and carry `unpinned` artifacts.
108
+ */
109
+ export declare const REFERENCE_DATA_CATALOG: ReferenceDataCatalog;
110
+ /** One selected dataset and its host-neutral installation location. */
111
+ export type ReferenceInstallPlanDataset = ReferenceDataset & {
112
+ readonly installPath: string;
113
+ };
114
+ /** Deterministic plan; every artifact carries the upstream URL it is fetched from. */
115
+ export interface ReferenceInstallPlan {
116
+ readonly catalogVersion: typeof REFERENCE_DATA_CATALOG_VERSION;
117
+ readonly datasets: readonly ReferenceInstallPlanDataset[];
118
+ }
119
+ /** A requested dataset id was not present in the selected catalog. */
120
+ export declare class UnknownReferenceDatasetError extends Error {
121
+ readonly code: "unknown_reference_dataset";
122
+ readonly unknownId: string;
123
+ readonly availableIds: readonly string[];
124
+ constructor(unknownId: string, availableIds: readonly string[]);
125
+ }
126
+ /** Resolve dataset ids without I/O, preserving a stable dataset-id ordering. */
127
+ /** @internal Fixture seam for harness contract tests; not exported by the package barrel. */
128
+ export declare function resolveReferenceInstallPlanFromCatalogForTesting(datasetIds: readonly string[], catalog: ReferenceDataCatalog): Result<ReferenceInstallPlan, UnknownReferenceDatasetError>;
129
+ /** Resolve ids strictly against the immutable canonical catalog shipped by this package. */
130
+ export declare function resolveReferenceInstallPlan(datasetIds: readonly string[]): Result<ReferenceInstallPlan, UnknownReferenceDatasetError>;
131
+ export {};
@@ -0,0 +1,348 @@
1
+ import { posix as posixPath } from "node:path";
2
+ import { err, ok } from "neverthrow";
3
+ import { z } from "zod";
4
+ /** Schema version for the checked-in reference-data catalog. */
5
+ export const REFERENCE_DATA_CATALOG_VERSION = 1;
6
+ const SAFE_ID = /^[a-z0-9]+(?:[._-][a-z0-9]+)*$/;
7
+ const SAFE_VERSION = /^[A-Za-z0-9]+(?:[._-][A-Za-z0-9]+)*$/;
8
+ const SHA256 = /^[a-f0-9]{64}$/;
9
+ function isSafeRelativePath(value) {
10
+ if (value.length === 0 || value.includes("\\") || value.startsWith("/"))
11
+ return false;
12
+ const segments = value.split("/");
13
+ return segments.every((segment) => segment.length > 0 && segment !== "." && segment !== "..") && posixPath.normalize(value) === value;
14
+ }
15
+ /** Dataset-relative destination of one artifact below its install path. */
16
+ export const ReferenceArtifactPathSchema = z.string().refine(isSafeRelativePath, "Expected a safe dataset-relative path");
17
+ /** Lowercase SHA-256 digest of one artifact's bytes. */
18
+ export const ReferenceSha256Schema = z.string().regex(SHA256, "Expected a lowercase SHA-256 digest");
19
+ /**
20
+ * Artifacts are fetched from the upstream that publishes them — this project
21
+ * redistributes nothing — so the URL must be a real third-party https endpoint.
22
+ */
23
+ const ReferenceArtifactUrlSchema = z.url().refine((value) => value.startsWith("https://"), "Reference artifacts must be fetched over https");
24
+ /**
25
+ * An artifact whose upstream publishes immutable, versioned bytes. The catalog
26
+ * carries the size and digest, so a download is verified against *this file*
27
+ * before it is ever activated: a mismatch means the bytes are not what we
28
+ * reviewed, and the install fails.
29
+ */
30
+ const PinnedReferenceArtifactSchema = z.strictObject({
31
+ integrity: z.literal("pinned"),
32
+ path: ReferenceArtifactPathSchema,
33
+ url: ReferenceArtifactUrlSchema,
34
+ bytes: z.number().int().positive(),
35
+ sha256: ReferenceSha256Schema,
36
+ });
37
+ /**
38
+ * An artifact whose upstream regenerates the same URL in place — NCBI rebuilds
39
+ * `gene_info` continuously and Reactome's `current` release is overwritten and
40
+ * its predecessors deleted. No checked-in digest can survive that, and pinning
41
+ * one would only guarantee a broken download. Integrity is therefore
42
+ * trust-on-first-use: the installer records the bytes it actually received in
43
+ * the receipt, and `verify` proves the files have not changed *since install*.
44
+ * This is a weaker guarantee than `pinned` and is surfaced as such to the user.
45
+ */
46
+ const UnpinnedReferenceArtifactSchema = z.strictObject({
47
+ integrity: z.literal("unpinned"),
48
+ path: ReferenceArtifactPathSchema,
49
+ url: ReferenceArtifactUrlSchema,
50
+ });
51
+ /** One immutable final file distributed for a reference dataset. */
52
+ export const ReferenceArtifactSchema = z.discriminatedUnion("integrity", [PinnedReferenceArtifactSchema, UnpinnedReferenceArtifactSchema]);
53
+ /** Provenance and licensing information for one supported reference dataset. */
54
+ export const ReferenceDatasetSchema = z.object({
55
+ id: z.string().regex(SAFE_ID, "Expected a stable lowercase dataset id"),
56
+ version: z.string().regex(SAFE_VERSION, "Expected a safe dataset version path segment"),
57
+ title: z.string().min(1),
58
+ description: z.string().min(1),
59
+ sourceUrl: z.url(),
60
+ license: z.object({
61
+ identifier: z.string().min(1),
62
+ url: z.url().optional(),
63
+ }),
64
+ recommendation: z.object({
65
+ group: z.string().min(1),
66
+ recommended: z.boolean(),
67
+ }),
68
+ artifacts: z.array(ReferenceArtifactSchema).min(1),
69
+ });
70
+ /** Versioned canonical catalog consumed identically by every harness embedder. */
71
+ export const ReferenceDataCatalogSchema = z
72
+ .object({
73
+ version: z.literal(REFERENCE_DATA_CATALOG_VERSION),
74
+ datasets: z.array(ReferenceDatasetSchema),
75
+ })
76
+ .superRefine((catalog, ctx) => {
77
+ const ids = new Set();
78
+ for (const [datasetIndex, dataset] of catalog.datasets.entries()) {
79
+ if (ids.has(dataset.id)) {
80
+ ctx.addIssue({ code: "custom", message: `Duplicate dataset id: ${dataset.id}`, path: ["datasets", datasetIndex, "id"] });
81
+ }
82
+ ids.add(dataset.id);
83
+ const paths = new Set();
84
+ for (const [artifactIndex, artifact] of dataset.artifacts.entries()) {
85
+ if (paths.has(artifact.path)) {
86
+ ctx.addIssue({
87
+ code: "custom",
88
+ message: `Duplicate artifact path in ${dataset.id}: ${artifact.path}`,
89
+ path: ["datasets", datasetIndex, "artifacts", artifactIndex, "path"],
90
+ });
91
+ }
92
+ paths.add(artifact.path);
93
+ }
94
+ }
95
+ });
96
+ /**
97
+ * Stable identity of one artifact within the catalog, independent of its URL.
98
+ * Embedders key resumable partials off this, so a moved upstream URL does not
99
+ * orphan a half-finished transfer.
100
+ */
101
+ export function referenceArtifactKey(dataset, artifact) {
102
+ return `${dataset.id}/${dataset.version}/${artifact.path}`;
103
+ }
104
+ function deepFreeze(value) {
105
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
106
+ for (const nested of Object.values(value))
107
+ deepFreeze(nested);
108
+ Object.freeze(value);
109
+ }
110
+ return value;
111
+ }
112
+ /**
113
+ * Canonical release catalog. Every artifact is fetched directly from the third
114
+ * party that publishes it; this project hosts, mirrors, and redistributes
115
+ * nothing. Entries are added only with real upstream URLs, provenance, and
116
+ * licensing data — plus a size and digest whenever the upstream publishes
117
+ * immutable bytes we can pin to.
118
+ *
119
+ * `version` is the dataset's upstream release identifier. Datasets built on an
120
+ * upstream that has no immutable release — NCBI regenerates `gene_info` daily,
121
+ * Reactome overwrites `current` and deletes prior releases — are versioned
122
+ * `current` and carry `unpinned` artifacts.
123
+ */
124
+ export const REFERENCE_DATA_CATALOG = deepFreeze(ReferenceDataCatalogSchema.parse({
125
+ version: REFERENCE_DATA_CATALOG_VERSION,
126
+ datasets: [
127
+ {
128
+ id: "ncbi-gene-human",
129
+ version: "current",
130
+ title: "NCBI human gene identifiers",
131
+ description: "Entrez Gene records for Homo sapiens (NCBI taxonomy 9606): identifiers, approved symbols, synonyms, and cross-references (Ensembl, HGNC) in the dbXrefs column. Tab-separated, gzipped. NCBI rebuilds this file in place, so it is verified against what you downloaded rather than a checked-in digest.",
132
+ sourceUrl: "https://ftp.ncbi.nlm.nih.gov/gene/DATA/GENE_INFO/Mammalia/",
133
+ license: {
134
+ identifier: "NCBI-Molecular-Data-Usage-Policy",
135
+ url: "https://www.ncbi.nlm.nih.gov/home/about/policies/",
136
+ },
137
+ recommendation: { group: "gene-identifiers", recommended: true },
138
+ artifacts: [
139
+ {
140
+ integrity: "unpinned",
141
+ path: "Homo_sapiens.gene_info.gz",
142
+ url: "https://ftp.ncbi.nlm.nih.gov/gene/DATA/GENE_INFO/Mammalia/Homo_sapiens.gene_info.gz",
143
+ },
144
+ ],
145
+ },
146
+ {
147
+ id: "ncbi-gene-mouse",
148
+ version: "current",
149
+ title: "NCBI mouse gene identifiers",
150
+ description: "Entrez Gene records for Mus musculus (NCBI taxonomy 10090): identifiers, approved symbols, synonyms, and cross-references (Ensembl, MGI) in the dbXrefs column. Tab-separated, gzipped. NCBI rebuilds this file in place, so it is verified against what you downloaded rather than a checked-in digest.",
151
+ sourceUrl: "https://ftp.ncbi.nlm.nih.gov/gene/DATA/GENE_INFO/Mammalia/",
152
+ license: {
153
+ identifier: "NCBI-Molecular-Data-Usage-Policy",
154
+ url: "https://www.ncbi.nlm.nih.gov/home/about/policies/",
155
+ },
156
+ recommendation: { group: "gene-identifiers", recommended: true },
157
+ artifacts: [
158
+ {
159
+ integrity: "unpinned",
160
+ path: "Mus_musculus.gene_info.gz",
161
+ url: "https://ftp.ncbi.nlm.nih.gov/gene/DATA/GENE_INFO/Mammalia/Mus_musculus.gene_info.gz",
162
+ },
163
+ ],
164
+ },
165
+ {
166
+ id: "ncbi-gene-rat",
167
+ version: "current",
168
+ title: "NCBI rat gene identifiers",
169
+ description: "Entrez Gene records for Rattus norvegicus (NCBI taxonomy 10116): identifiers, approved symbols, synonyms, and cross-references (Ensembl, RGD) in the dbXrefs column. Tab-separated, gzipped. NCBI rebuilds this file in place, so it is verified against what you downloaded rather than a checked-in digest.",
170
+ sourceUrl: "https://ftp.ncbi.nlm.nih.gov/gene/DATA/GENE_INFO/Mammalia/",
171
+ license: {
172
+ identifier: "NCBI-Molecular-Data-Usage-Policy",
173
+ url: "https://www.ncbi.nlm.nih.gov/home/about/policies/",
174
+ },
175
+ recommendation: { group: "gene-identifiers", recommended: true },
176
+ artifacts: [
177
+ {
178
+ integrity: "unpinned",
179
+ path: "Rattus_norvegicus.gene_info.gz",
180
+ url: "https://ftp.ncbi.nlm.nih.gov/gene/DATA/GENE_INFO/Mammalia/Rattus_norvegicus.gene_info.gz",
181
+ },
182
+ ],
183
+ },
184
+ {
185
+ id: "reactome-pathways",
186
+ version: "current",
187
+ title: "Reactome pathways",
188
+ description: "Reactome pathway gene sets (GMT) and the pathway index — the enrichment workhorse, ~2 MB. Reactome overwrites its `current` release each quarter and removes the prior one, so this is verified against what you downloaded rather than a checked-in digest. For identifier-to-pathway mapping tables, add `reactome-mappings`.",
189
+ sourceUrl: "https://reactome.org/download-data",
190
+ license: { identifier: "CC0-1.0", url: "https://reactome.org/license" },
191
+ recommendation: { group: "pathways", recommended: true },
192
+ artifacts: [
193
+ { integrity: "unpinned", path: "ReactomePathways.gmt", url: "https://reactome.org/download/current/ReactomePathways.gmt" },
194
+ { integrity: "unpinned", path: "ReactomePathways.txt", url: "https://reactome.org/download/current/ReactomePathways.txt" },
195
+ ],
196
+ },
197
+ {
198
+ // Split out of `reactome-pathways` and NOT recommended by default: upstream serves these
199
+ // as uncompressed TSV and they total roughly 700 MB, two orders of magnitude more than the
200
+ // GMT most workflows actually want. Anyone who needs Entrez/Ensembl/UniProt -> pathway
201
+ // joins opts in deliberately, rather than every `setup` paying for them by accident.
202
+ id: "reactome-mappings",
203
+ version: "current",
204
+ title: "Reactome identifier mappings (large)",
205
+ description: "Entrez/Ensembl/UniProt-to-Reactome mapping tables at all pathway levels. Large: roughly 700 MB of uncompressed TSV, because Reactome publishes no compressed form. Only needed to join external identifiers onto Reactome pathways; the gene sets themselves live in `reactome-pathways`.",
206
+ sourceUrl: "https://reactome.org/download-data",
207
+ license: { identifier: "CC0-1.0", url: "https://reactome.org/license" },
208
+ recommendation: { group: "pathways", recommended: false },
209
+ artifacts: [
210
+ {
211
+ integrity: "unpinned",
212
+ path: "NCBI2Reactome_All_Levels.txt",
213
+ url: "https://reactome.org/download/current/NCBI2Reactome_All_Levels.txt",
214
+ },
215
+ {
216
+ integrity: "unpinned",
217
+ path: "Ensembl2Reactome_All_Levels.txt",
218
+ url: "https://reactome.org/download/current/Ensembl2Reactome_All_Levels.txt",
219
+ },
220
+ {
221
+ integrity: "unpinned",
222
+ path: "UniProt2Reactome_All_Levels.txt",
223
+ url: "https://reactome.org/download/current/UniProt2Reactome_All_Levels.txt",
224
+ },
225
+ ],
226
+ },
227
+ {
228
+ id: "wikipathways-human",
229
+ version: "2026.07.10",
230
+ title: "WikiPathways human pathways",
231
+ description: "Community-curated Homo sapiens pathway gene sets (GMT) from the immutable 2026-07-10 WikiPathways snapshot.",
232
+ sourceUrl: "https://data.wikipathways.org/20260710/gmt/",
233
+ license: { identifier: "CC0-1.0", url: "https://www.wikipathways.org/about/terms.html" },
234
+ recommendation: { group: "pathways", recommended: true },
235
+ artifacts: [
236
+ {
237
+ integrity: "pinned",
238
+ path: "wikipathways_Homo_sapiens.gmt",
239
+ url: "https://data.wikipathways.org/20260710/gmt/wikipathways-20260710-gmt-Homo_sapiens.gmt",
240
+ bytes: 341_474,
241
+ sha256: "79615a079246bb0b07cc3505265b1f75ea6cffec88001ce27f644dd86a39c97d",
242
+ },
243
+ ],
244
+ },
245
+ {
246
+ id: "collectri-human",
247
+ version: "2.0",
248
+ title: "CollecTRI human regulatory network",
249
+ description: "A literature-curated human transcription-factor target interaction network (CSV) from the immutable Zenodo record 8192729.",
250
+ sourceUrl: "https://zenodo.org/records/8192729",
251
+ license: { identifier: "CC-BY-4.0", url: "https://zenodo.org/records/8192729" },
252
+ recommendation: { group: "regulatory-networks", recommended: true },
253
+ artifacts: [
254
+ {
255
+ integrity: "pinned",
256
+ path: "CollecTRI_regulons.csv",
257
+ url: "https://zenodo.org/records/8192729/files/CollecTRI_regulons.csv",
258
+ bytes: 4_345_649,
259
+ sha256: "4473c9189dd53dacc80297709ad1452dda1086a1cc2185f9a56146c261668701",
260
+ },
261
+ ],
262
+ },
263
+ {
264
+ id: "gtex-v8",
265
+ version: "8",
266
+ title: "GTEx v8 normal tissue expression",
267
+ description: "GTEx v8 median gene TPM by tissue (GCT) with the sample attributes table, for normal-reference workflows. Immutable v8 release files.",
268
+ sourceUrl: "https://gtexportal.org/home/downloads/adult-gtex/bulk_tissue_expression",
269
+ license: { identifier: "GTEx-Portal-Data-License", url: "https://gtexportal.org/home/license" },
270
+ recommendation: { group: "normal-expression", recommended: true },
271
+ artifacts: [
272
+ {
273
+ integrity: "pinned",
274
+ path: "GTEx_Analysis_2017-06-05_v8_RNASeQCv1.1.9_gene_median_tpm.gct.gz",
275
+ url: "https://storage.googleapis.com/adult-gtex/bulk-gex/v8/rna-seq/GTEx_Analysis_2017-06-05_v8_RNASeQCv1.1.9_gene_median_tpm.gct.gz",
276
+ bytes: 6_952_331,
277
+ sha256: "ee7201ff2f280b0de5657d4b08e9a240362d9757efed7f7bd5dba35a5f8617b8",
278
+ },
279
+ {
280
+ integrity: "pinned",
281
+ path: "GTEx_Analysis_v8_Annotations_SampleAttributesDS.txt",
282
+ url: "https://storage.googleapis.com/adult-gtex/annotations/v8/metadata-files/GTEx_Analysis_v8_Annotations_SampleAttributesDS.txt",
283
+ bytes: 11_512_258,
284
+ sha256: "74f6ab4c34ed2648d708a0ae6e6dff324f6c86ea723ae7d1c37d76f5221148f0",
285
+ },
286
+ ],
287
+ },
288
+ {
289
+ id: "celltypist-immune",
290
+ version: "2",
291
+ title: "CellTypist immune cell models",
292
+ description: "CellTypist Immune All low- and high-resolution models for immune cell-type annotation. Load by absolute path — CellTypist's by-name lookup expects its own cache layout, which the reference store deliberately does not impersonate.",
293
+ sourceUrl: "https://www.celltypist.org/models",
294
+ license: { identifier: "NOASSERTION" },
295
+ recommendation: { group: "cell-typing", recommended: true },
296
+ artifacts: [
297
+ {
298
+ integrity: "pinned",
299
+ path: "Immune_All_Low.pkl",
300
+ url: "https://celltypist.cog.sanger.ac.uk/models/Pan_Immune_CellTypist/v2/Immune_All_Low.pkl",
301
+ bytes: 2_824_990,
302
+ sha256: "290874d35dac039d4c9218c343fde4aac1077709b72a331ce7266f6828c36502",
303
+ },
304
+ {
305
+ integrity: "pinned",
306
+ path: "Immune_All_High.pkl",
307
+ url: "https://celltypist.cog.sanger.ac.uk/models/Pan_Immune_CellTypist/v2/Immune_All_High.pkl",
308
+ bytes: 1_070_426,
309
+ sha256: "a715fec36c2c421f7c4e31cf4cb4bea883eedab7fd7b20a4b76f091c22660448",
310
+ },
311
+ ],
312
+ },
313
+ ],
314
+ }));
315
+ /** A requested dataset id was not present in the selected catalog. */
316
+ export class UnknownReferenceDatasetError extends Error {
317
+ code = "unknown_reference_dataset";
318
+ unknownId;
319
+ availableIds;
320
+ constructor(unknownId, availableIds) {
321
+ super(`Unknown reference dataset "${unknownId}". Available ids: ${availableIds.join(", ") || "(none)"}`);
322
+ this.name = "UnknownReferenceDatasetError";
323
+ this.unknownId = unknownId;
324
+ this.availableIds = availableIds;
325
+ }
326
+ }
327
+ /** Resolve dataset ids without I/O, preserving a stable dataset-id ordering. */
328
+ /** @internal Fixture seam for harness contract tests; not exported by the package barrel. */
329
+ export function resolveReferenceInstallPlanFromCatalogForTesting(datasetIds, catalog) {
330
+ const byId = new Map(catalog.datasets.map((dataset) => [dataset.id, dataset]));
331
+ const availableIds = [...byId.keys()].sort();
332
+ const selectedIds = [...new Set(datasetIds)].sort();
333
+ for (const id of selectedIds) {
334
+ if (!byId.has(id))
335
+ return err(new UnknownReferenceDatasetError(id, availableIds));
336
+ }
337
+ return ok({
338
+ catalogVersion: catalog.version,
339
+ datasets: selectedIds.map((id) => {
340
+ const dataset = byId.get(id);
341
+ return { ...dataset, installPath: `${dataset.id}/${dataset.version}` };
342
+ }),
343
+ });
344
+ }
345
+ /** Resolve ids strictly against the immutable canonical catalog shipped by this package. */
346
+ export function resolveReferenceInstallPlan(datasetIds) {
347
+ return resolveReferenceInstallPlanFromCatalogForTesting(datasetIds, REFERENCE_DATA_CATALOG);
348
+ }
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ /** Schema version for installation receipts shared by all embedders. */
3
+ export declare const REFERENCE_INSTALL_RECEIPT_VERSION: 1;
4
+ /**
5
+ * What was actually written to disk for one artifact. The size and digest are
6
+ * *observed at install*, never copied from the catalog — for a `pinned`
7
+ * artifact they equal the catalog's (the install would have failed otherwise),
8
+ * and for an `unpinned` one they are the only record of what the mutable
9
+ * upstream served, which is what `verify` later checks the files against.
10
+ */
11
+ declare const ReferenceReceiptArtifactSchema: z.ZodObject<{
12
+ path: z.ZodString;
13
+ bytes: z.ZodNumber;
14
+ sha256: z.ZodString;
15
+ integrity: z.ZodEnum<{
16
+ pinned: "pinned";
17
+ unpinned: "unpinned";
18
+ }>;
19
+ }, z.core.$strip>;
20
+ /** Optional metadata describing one activated reference dataset version. */
21
+ export declare const ReferenceInstallReceiptSchema: z.ZodObject<{
22
+ version: z.ZodLiteral<1>;
23
+ datasetId: z.ZodString;
24
+ datasetVersion: z.ZodString;
25
+ activatedAt: z.ZodISODateTime;
26
+ artifacts: z.ZodArray<z.ZodObject<{
27
+ path: z.ZodString;
28
+ bytes: z.ZodNumber;
29
+ sha256: z.ZodString;
30
+ integrity: z.ZodEnum<{
31
+ pinned: "pinned";
32
+ unpinned: "unpinned";
33
+ }>;
34
+ }, z.core.$strip>>;
35
+ }, z.core.$strip>;
36
+ export type ReferenceInstallReceipt = z.infer<typeof ReferenceInstallReceiptSchema>;
37
+ /** One artifact as recorded by a completed installation. */
38
+ export type ReferenceReceiptArtifact = z.infer<typeof ReferenceReceiptArtifactSchema>;
39
+ /** Parse optional/untrusted receipt metadata; invalid receipts are ignored. */
40
+ export declare function parseReferenceInstallReceipt(input: unknown): ReferenceInstallReceipt | undefined;
41
+ export {};