@inflexa-ai/harness 0.16.0 → 0.18.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 (295) hide show
  1. package/dist/agents/conversation-agent.d.ts +3 -0
  2. package/dist/agents/conversation-agent.js +5 -2
  3. package/dist/agents/report-builder.d.ts +2 -0
  4. package/dist/agents/report-builder.js +2 -0
  5. package/dist/agents/sandbox/shared.d.ts +3 -0
  6. package/dist/agents/sandbox/shared.js +5 -0
  7. package/dist/agents/sandbox/types.d.ts +1 -1
  8. package/dist/app/chat-turn.d.ts +2 -0
  9. package/dist/app/chat-turn.js +11 -2
  10. package/dist/app/spawn-report-session.d.ts +85 -0
  11. package/dist/app/spawn-report-session.js +83 -0
  12. package/dist/app/synthesize-run.d.ts +3 -0
  13. package/dist/app/synthesize-run.js +2 -1
  14. package/dist/citations/__fixtures__/resolver.d.ts +3 -0
  15. package/dist/citations/__fixtures__/resolver.js +9 -0
  16. package/dist/citations/aggregate.d.ts +3 -0
  17. package/dist/citations/aggregate.js +44 -0
  18. package/dist/citations/clients/arxiv.d.ts +6 -0
  19. package/dist/citations/clients/arxiv.js +34 -0
  20. package/dist/citations/clients/common.d.ts +11 -0
  21. package/dist/citations/clients/common.js +43 -0
  22. package/dist/citations/clients/crossref.d.ts +8 -0
  23. package/dist/citations/clients/crossref.js +98 -0
  24. package/dist/citations/clients/doi-registry.d.ts +3 -0
  25. package/dist/citations/clients/doi-registry.js +95 -0
  26. package/dist/citations/clients/pubmed.d.ts +6 -0
  27. package/dist/citations/clients/pubmed.js +83 -0
  28. package/dist/citations/clients/semantic-scholar.d.ts +6 -0
  29. package/dist/citations/clients/semantic-scholar.js +60 -0
  30. package/dist/citations/compare.d.ts +9 -0
  31. package/dist/citations/compare.js +72 -0
  32. package/dist/citations/match.d.ts +11 -0
  33. package/dist/citations/match.js +173 -0
  34. package/dist/citations/normalize.d.ts +31 -0
  35. package/dist/citations/normalize.js +187 -0
  36. package/dist/citations/plan.d.ts +2 -0
  37. package/dist/citations/plan.js +59 -0
  38. package/dist/citations/resolve.d.ts +28 -0
  39. package/dist/citations/resolve.js +238 -0
  40. package/dist/citations/types.d.ts +583 -0
  41. package/dist/citations/types.js +129 -0
  42. package/dist/contracts/chat-events.d.ts +9 -0
  43. package/dist/contracts/index.d.ts +6 -2
  44. package/dist/contracts/index.js +3 -1
  45. package/dist/contracts/organ-system.d.ts +49 -0
  46. package/dist/contracts/organ-system.js +67 -0
  47. package/dist/contracts/report-blocks.d.ts +564 -0
  48. package/dist/contracts/report-blocks.js +117 -0
  49. package/dist/contracts/report-reference.d.ts +459 -0
  50. package/dist/contracts/report-reference.js +256 -0
  51. package/dist/contracts/schemas/chat-events.d.ts +2 -0
  52. package/dist/contracts/schemas/chat-events.js +2 -0
  53. package/dist/contracts/schemas/chat-parts.d.ts +8 -8
  54. package/dist/contracts/severity.d.ts +15 -0
  55. package/dist/contracts/severity.js +10 -0
  56. package/dist/contracts/target-dossier.d.ts +8673 -12970
  57. package/dist/contracts/target-dossier.js +534 -591
  58. package/dist/data/safety-panel-schema.d.ts +18 -5
  59. package/dist/data/safety-panel-schema.js +4 -4
  60. package/dist/execution/artifact-metadata.js +1 -0
  61. package/dist/execution/report-runner.js +1 -3
  62. package/dist/execution/run-synthesis.d.ts +3 -0
  63. package/dist/execution/run-synthesis.js +3 -0
  64. package/dist/index.d.ts +12 -1
  65. package/dist/index.js +22 -0
  66. package/dist/lib/async-utils.d.ts +16 -4
  67. package/dist/lib/async-utils.js +20 -15
  68. package/dist/lib/cache.d.ts +8 -0
  69. package/dist/lib/cache.js +35 -0
  70. package/dist/lib/host-concurrency.js +1 -0
  71. package/dist/lib/rate-limit.d.ts +35 -0
  72. package/dist/lib/rate-limit.js +121 -0
  73. package/dist/literature/sources/arxiv.d.ts +22 -0
  74. package/dist/literature/sources/arxiv.js +103 -0
  75. package/dist/literature/sources/http.d.ts +28 -0
  76. package/dist/literature/sources/http.js +97 -0
  77. package/dist/literature/sources/pubmed.d.ts +68 -0
  78. package/dist/literature/sources/pubmed.js +266 -0
  79. package/dist/literature/sources/semantic-scholar.d.ts +24 -0
  80. package/dist/literature/sources/semantic-scholar.js +71 -0
  81. package/dist/loop/__fixtures__/scripted-provider.js +23 -2
  82. package/dist/loop/run-agent.js +58 -10
  83. package/dist/loop/tool-detail.d.ts +40 -0
  84. package/dist/loop/tool-detail.js +35 -3
  85. package/dist/loop/types.d.ts +13 -0
  86. package/dist/memory/thread-history.d.ts +10 -0
  87. package/dist/memory/thread-history.js +12 -1
  88. package/dist/memory/thread-store.d.ts +142 -25
  89. package/dist/memory/thread-store.js +228 -40
  90. package/dist/prompts/literature-reviewer.d.ts +1 -1
  91. package/dist/prompts/literature-reviewer.js +2 -0
  92. package/dist/prompts/target-assessment/briefs/executive-recommendation.d.ts +1 -1
  93. package/dist/prompts/target-assessment/briefs/executive-recommendation.js +5 -5
  94. package/dist/prompts/target-assessment/briefs/liability-bullets.d.ts +1 -1
  95. package/dist/prompts/target-assessment/briefs/liability-bullets.js +1 -1
  96. package/dist/prompts/target-assessment/briefs/target-organ-liabilities.d.ts +1 -1
  97. package/dist/prompts/target-assessment/briefs/target-organ-liabilities.js +11 -3
  98. package/dist/prompts/target-assessment/investigation/adversarial-critique.d.ts +1 -0
  99. package/dist/prompts/target-assessment/investigation/adversarial-critique.js +67 -0
  100. package/dist/prompts/target-assessment/investigation/claim-reverification.d.ts +1 -0
  101. package/dist/prompts/target-assessment/investigation/claim-reverification.js +49 -0
  102. package/dist/prompts/target-assessment/investigation/index.d.ts +3 -0
  103. package/dist/prompts/target-assessment/investigation/index.js +3 -0
  104. package/dist/prompts/target-assessment/investigation/mechanism-proposal.d.ts +1 -0
  105. package/dist/prompts/target-assessment/investigation/mechanism-proposal.js +49 -0
  106. package/dist/prompts/target-assessment/tox-voice/index.d.ts +1 -1
  107. package/dist/prompts/target-assessment/tox-voice/vocabulary.d.ts +8 -5
  108. package/dist/prompts/target-assessment/tox-voice/vocabulary.js +9 -20
  109. package/dist/providers/__fixtures__/session.d.ts +5 -4
  110. package/dist/providers/__fixtures__/session.js +4 -4
  111. package/dist/report-model/block-walk.d.ts +56 -0
  112. package/dist/report-model/block-walk.js +89 -0
  113. package/dist/report-model/draft-finish.d.ts +60 -0
  114. package/dist/report-model/draft-finish.js +56 -0
  115. package/dist/report-model/draft-operations.d.ts +125 -0
  116. package/dist/report-model/draft-operations.js +341 -0
  117. package/dist/report-model/draft-read.d.ts +59 -0
  118. package/dist/report-model/draft-read.js +109 -0
  119. package/dist/report-model/draft.d.ts +51 -0
  120. package/dist/report-model/draft.js +32 -0
  121. package/dist/report-model/fixture-resolver.d.ts +8 -0
  122. package/dist/report-model/fixture-resolver.js +252 -0
  123. package/dist/report-model/mint-snapshot.d.ts +30 -0
  124. package/dist/report-model/mint-snapshot.js +40 -0
  125. package/dist/report-model/reference-resolver.d.ts +113 -0
  126. package/dist/report-model/reference-resolver.js +60 -0
  127. package/dist/report-model/structural-validation.d.ts +22 -0
  128. package/dist/report-model/structural-validation.js +68 -0
  129. package/dist/report-model/validate.d.ts +40 -0
  130. package/dist/report-model/validate.js +80 -0
  131. package/dist/report-render/chart.d.ts +33 -0
  132. package/dist/report-render/chart.js +538 -0
  133. package/dist/report-render/page.d.ts +127 -0
  134. package/dist/report-render/page.js +307 -0
  135. package/dist/report-render/references.d.ts +32 -0
  136. package/dist/report-render/references.js +44 -0
  137. package/dist/report-render/render.d.ts +25 -0
  138. package/dist/report-render/render.js +125 -0
  139. package/dist/report-render/script-json.d.ts +13 -0
  140. package/dist/report-render/script-json.js +15 -0
  141. package/dist/report-render/types.d.ts +39 -0
  142. package/dist/report-render/types.js +10 -0
  143. package/dist/report-render/views/chart-view.d.ts +11 -0
  144. package/dist/report-render/views/chart-view.js +23 -0
  145. package/dist/report-render/views/page-view.d.ts +20 -0
  146. package/dist/report-render/views/page-view.js +49 -0
  147. package/dist/report-render/views/prose.d.ts +28 -0
  148. package/dist/report-render/views/prose.js +75 -0
  149. package/dist/report-render/views/references-view.d.ts +20 -0
  150. package/dist/report-render/views/references-view.js +64 -0
  151. package/dist/report-render/views/values.d.ts +42 -0
  152. package/dist/report-render/views/values.js +43 -0
  153. package/dist/runtime/assemble.d.ts +50 -4
  154. package/dist/runtime/assemble.js +47 -3
  155. package/dist/runtime/boot.d.ts +3 -3
  156. package/dist/runtime/boot.js +22 -5
  157. package/dist/runtime/dbos.d.ts +4 -4
  158. package/dist/state/artifacts.d.ts +16 -0
  159. package/dist/state/artifacts.js +18 -0
  160. package/dist/state/init.js +77 -1
  161. package/dist/state/purge-analysis.js +1 -0
  162. package/dist/state/report-versions.d.ts +132 -0
  163. package/dist/state/report-versions.js +194 -0
  164. package/dist/state/schema.d.ts +2 -2
  165. package/dist/tasks/data-profile.js +1 -0
  166. package/dist/tools/bio/chembl.js +1 -0
  167. package/dist/tools/bio/comptox.js +1 -0
  168. package/dist/tools/bio/drug-gene-interactions.js +1 -0
  169. package/dist/tools/bio/gene-disease-evidence.js +1 -0
  170. package/dist/tools/bio/gene-preclinical-profile.d.ts +1 -1
  171. package/dist/tools/bio/gene-preclinical-profile.js +1 -0
  172. package/dist/tools/bio/keys.d.ts +4 -2
  173. package/dist/tools/bio/keys.js +3 -2
  174. package/dist/tools/bio/lookup-annotation.js +1 -0
  175. package/dist/tools/bio/opentargets.d.ts +3 -3
  176. package/dist/tools/bio/opentargets.js +4 -3
  177. package/dist/tools/bio/pubchem.js +1 -0
  178. package/dist/tools/bio/pubmed.js +4 -4
  179. package/dist/tools/bio/search-clinical-trials.js +1 -0
  180. package/dist/tools/bio/search-faers.js +1 -0
  181. package/dist/tools/bio/search-geo-datasets.js +1 -0
  182. package/dist/tools/bio/search-interactions.js +1 -0
  183. package/dist/tools/bio/target-safety.d.ts +4 -6
  184. package/dist/tools/bio/target-safety.js +7 -6
  185. package/dist/tools/define-tool.d.ts +19 -12
  186. package/dist/tools/define-tool.js +4 -2
  187. package/dist/tools/display/show-user.js +1 -0
  188. package/dist/tools/iterate-report.js +2 -0
  189. package/dist/tools/lib/chembl-client.d.ts +2 -0
  190. package/dist/tools/lib/chembl-client.js +1 -0
  191. package/dist/tools/lib/monarch-client.d.ts +42 -0
  192. package/dist/tools/lib/monarch-client.js +100 -0
  193. package/dist/tools/lib/ncbi-utils.d.ts +3 -58
  194. package/dist/tools/lib/ncbi-utils.js +2 -286
  195. package/dist/tools/lib/pubmed-client.d.ts +5 -12
  196. package/dist/tools/lib/pubmed-client.js +20 -79
  197. package/dist/tools/report/build-report.js +1 -0
  198. package/dist/tools/report/mint-preview-url.js +1 -0
  199. package/dist/tools/report/preview-snapshot.js +1 -0
  200. package/dist/tools/report/submit-report.js +1 -0
  201. package/dist/tools/report/version-fs.js +4 -0
  202. package/dist/tools/report-authoring/authoring-tools.d.ts +134 -0
  203. package/dist/tools/report-authoring/authoring-tools.js +352 -0
  204. package/dist/tools/research/context7-docs.js +2 -0
  205. package/dist/tools/research/generate-analogy-report.js +3 -2
  206. package/dist/tools/research/generate-plan.js +3 -0
  207. package/dist/tools/research/index.d.ts +1 -0
  208. package/dist/tools/research/index.js +1 -0
  209. package/dist/tools/research/inspect-data-profile.js +4 -0
  210. package/dist/tools/research/inspect-run.d.ts +1 -1
  211. package/dist/tools/research/literature-reviewer.d.ts +3 -0
  212. package/dist/tools/research/literature-reviewer.js +3 -0
  213. package/dist/tools/research/resolve-citation.d.ts +3 -0
  214. package/dist/tools/research/resolve-citation.js +15 -0
  215. package/dist/tools/research/search-arxiv.d.ts +3 -19
  216. package/dist/tools/research/search-arxiv.js +10 -105
  217. package/dist/tools/research/search-github-repos.js +1 -0
  218. package/dist/tools/research/search-semantic-scholar.d.ts +8 -33
  219. package/dist/tools/research/search-semantic-scholar.js +30 -88
  220. package/dist/tools/sandbox/list-available-packages.js +23 -0
  221. package/dist/tools/sandbox/list-available-refs.js +37 -2
  222. package/dist/tools/sandbox/report-blocker.js +1 -0
  223. package/dist/tools/sandbox/skills.js +2 -0
  224. package/dist/tools/workspace/file-stat.js +1 -0
  225. package/dist/tools/workspace/show-file.js +2 -0
  226. package/dist/tools/workspace/show-plan.js +1 -0
  227. package/dist/workflows/execute-analysis.d.ts +8 -1
  228. package/dist/workflows/execute-analysis.js +6 -5
  229. package/dist/workflows/execute-target-assessment.d.ts +13 -2
  230. package/dist/workflows/execute-target-assessment.js +78 -16
  231. package/dist/workflows/sandbox-step.d.ts +5 -0
  232. package/dist/workflows/sandbox-step.js +1 -0
  233. package/dist/workflows/target-assessment/assemblers/index.d.ts +1 -1
  234. package/dist/workflows/target-assessment/assemblers/index.js +1 -1
  235. package/dist/workflows/target-assessment/assemblers/literature.d.ts +9 -27
  236. package/dist/workflows/target-assessment/assemblers/literature.js +32 -48
  237. package/dist/workflows/target-assessment/assemblers/orchestrator.d.ts +17 -9
  238. package/dist/workflows/target-assessment/assemblers/orchestrator.js +195 -85
  239. package/dist/workflows/target-assessment/assemblers/safety.d.ts +70 -48
  240. package/dist/workflows/target-assessment/assemblers/safety.js +125 -42
  241. package/dist/workflows/target-assessment/collectors/index.d.ts +5 -2
  242. package/dist/workflows/target-assessment/collectors/index.js +48 -5
  243. package/dist/workflows/target-assessment/coverage.d.ts +43 -27
  244. package/dist/workflows/target-assessment/coverage.js +33 -29
  245. package/dist/workflows/target-assessment/fanout/index.js +1 -0
  246. package/dist/workflows/target-assessment/investigation/index.d.ts +97 -0
  247. package/dist/workflows/target-assessment/investigation/index.js +419 -0
  248. package/dist/workflows/target-assessment/lib/approval-precedents.d.ts +26 -5
  249. package/dist/workflows/target-assessment/lib/approval-precedents.js +95 -29
  250. package/dist/workflows/target-assessment/lib/citation-validator.js +1 -1
  251. package/dist/workflows/target-assessment/lib/clinical-consequence-annotator.d.ts +2 -2
  252. package/dist/workflows/target-assessment/lib/clinical-evidence-attribution.d.ts +2 -3
  253. package/dist/workflows/target-assessment/lib/clinical-evidence-attribution.js +0 -4
  254. package/dist/workflows/target-assessment/lib/compute-derived.d.ts +6 -5
  255. package/dist/workflows/target-assessment/lib/compute-derived.js +14 -5
  256. package/dist/workflows/target-assessment/lib/family-complex-supplement.d.ts +5 -6
  257. package/dist/workflows/target-assessment/lib/family-complex-supplement.js +2 -3
  258. package/dist/workflows/target-assessment/lib/fda-label-safety.d.ts +72 -0
  259. package/dist/workflows/target-assessment/lib/fda-label-safety.js +166 -0
  260. package/dist/workflows/target-assessment/lib/heterodimer-filter.d.ts +0 -9
  261. package/dist/workflows/target-assessment/lib/heterodimer-filter.js +0 -10
  262. package/dist/workflows/target-assessment/lib/hpo-organ-map.d.ts +34 -0
  263. package/dist/workflows/target-assessment/lib/hpo-organ-map.js +63 -0
  264. package/dist/workflows/target-assessment/lib/impc-organ-map.d.ts +19 -0
  265. package/dist/workflows/target-assessment/lib/impc-organ-map.js +39 -0
  266. package/dist/workflows/target-assessment/lib/meddra-organ-map.d.ts +24 -14
  267. package/dist/workflows/target-assessment/lib/meddra-organ-map.js +59 -47
  268. package/dist/workflows/target-assessment/lib/recommendation-sanitizer.js +1 -1
  269. package/dist/workflows/target-assessment/lib/regulatory-actions.d.ts +2 -3
  270. package/dist/workflows/target-assessment/lib/regulatory-actions.js +33 -4
  271. package/dist/workflows/target-assessment/lib/safety-corroboration.d.ts +44 -0
  272. package/dist/workflows/target-assessment/lib/safety-corroboration.js +273 -0
  273. package/dist/workflows/target-assessment/lib/target-identity-filter.d.ts +5 -7
  274. package/dist/workflows/target-assessment/lib/target-identity-filter.js +5 -7
  275. package/dist/workflows/target-assessment/metrics.d.ts +1 -6
  276. package/dist/workflows/target-assessment/metrics.js +1 -13
  277. package/dist/workflows/target-assessment/phase4-assemble.d.ts +2149 -809
  278. package/dist/workflows/target-assessment/phase4-assemble.js +19 -19
  279. package/dist/workflows/target-assessment/phase5-persist.d.ts +20 -21
  280. package/dist/workflows/target-assessment/phase5-persist.js +56 -173
  281. package/dist/workflows/target-assessment/schemas.d.ts +48 -3
  282. package/dist/workflows/target-assessment/schemas.js +19 -0
  283. package/dist/workflows/target-assessment/steps/fanout/polypharm-for-one-modulator-step.d.ts +1 -0
  284. package/dist/workflows/target-assessment/steps/fanout/polypharm-for-one-modulator-step.js +2 -0
  285. package/dist/workflows/target-assessment/steps/phase2-aggregate.d.ts +27 -63
  286. package/dist/workflows/target-assessment/steps/phase2-aggregate.js +0 -4
  287. package/dist/workflows/target-assessment/steps/phase3-aggregate.d.ts +28 -155
  288. package/dist/workflows/target-assessment/steps/phase3-aggregate.js +0 -6
  289. package/dist/workflows/target-assessment/steps/synthesis/diagnostics.d.ts +0 -6
  290. package/dist/workflows/target-assessment/steps/synthesis/diagnostics.js +0 -18
  291. package/dist/workflows/target-assessment/sub-workflows/per-modulator-polypharm.d.ts +1 -0
  292. package/dist/workflows/target-assessment/synthesis/index.d.ts +52 -5
  293. package/dist/workflows/target-assessment/synthesis/index.js +4 -1
  294. package/dist/workflows/target-assessment/synthesis-probes.d.ts +3 -3
  295. package/package.json +4 -1
@@ -42,6 +42,7 @@ export function createSubmitReportTool(state) {
42
42
  "samples — the rest had no QC row'. " +
43
43
  "Leave empty when the report shipped cleanly."),
44
44
  }),
45
+ describeCall: "none",
45
46
  execute: async (input) => {
46
47
  const problems = [];
47
48
  // 1. report.html.j2 exists — the report itself, as opposed to the
@@ -44,6 +44,7 @@ export function createVersionFsTools(state) {
44
44
  path: z.string().min(1),
45
45
  content: z.string(),
46
46
  }),
47
+ describeCall: "none",
47
48
  execute: async ({ path, content }) => {
48
49
  const resolved = resolveAgentPath(path, state.versionDir);
49
50
  if (resolved.kind === "out_of_scope") {
@@ -73,6 +74,7 @@ export function createVersionFsTools(state) {
73
74
  oldText: z.string().min(1),
74
75
  newText: z.string(),
75
76
  }),
77
+ describeCall: "none",
76
78
  execute: async ({ path, oldText, newText }) => {
77
79
  const resolved = resolveAgentPath(path, state.versionDir);
78
80
  if (resolved.kind === "out_of_scope") {
@@ -112,6 +114,7 @@ export function createVersionFsTools(state) {
112
114
  inputSchema: z.object({
113
115
  path: z.string().min(1),
114
116
  }),
117
+ describeCall: "none",
115
118
  execute: async ({ path }) => {
116
119
  const resolved = resolveAgentPath(path, state.versionDir);
117
120
  if (resolved.kind === "out_of_scope") {
@@ -148,6 +151,7 @@ export function createVersionFsTools(state) {
148
151
  inputSchema: z.object({
149
152
  path: z.string().min(1),
150
153
  }),
154
+ describeCall: "none",
151
155
  execute: async ({ path }) => {
152
156
  const resolved = resolveAgentPath(path, state.versionDir);
153
157
  if (resolved.kind === "out_of_scope") {
@@ -0,0 +1,134 @@
1
+ /**
2
+ * The authoring tool surface over the draft operations.
3
+ *
4
+ * The factory closes over a private draft holder and the pinned snapshot. It gives eight tools and a
5
+ * read of the current draft. The tools read no ambient state, thus two factories hold two independent
6
+ * drafts.
7
+ *
8
+ * Each tool maps its flat input onto a core operation, and it applies the pure operation. The holder
9
+ * swaps only on a landed operation. A refused operation returns typed data in the ok channel, and the
10
+ * error channel stays for an unexpected failure.
11
+ *
12
+ * The primitive admits a flat object input only. Thus a destination is four optional fields, and not a
13
+ * nested union. A conflict between the flat fields refuses before the core runs.
14
+ */
15
+ import { z } from "zod";
16
+ import { type DraftRefusal } from "../../report-model/draft-operations.js";
17
+ import { type OutlineEntry, type ReadableBlock } from "../../report-model/draft-read.js";
18
+ import { type FinishResult } from "../../report-model/draft-finish.js";
19
+ import { type DraftDocument } from "../../report-model/draft.js";
20
+ import type { ReportSnapshot } from "../../report-model/reference-resolver.js";
21
+ import { type Tool } from "../define-tool.js";
22
+ /** The flat destination fields. An anchor is `before` or `after`, and a place is `start` or `end`. */
23
+ declare const addBlockInput: z.ZodObject<{
24
+ block: z.ZodUnion<readonly [z.ZodType<import("../../report-model/draft.js").DraftBlock, unknown, z.core.$ZodTypeInternals<import("../../report-model/draft.js").DraftBlock, unknown>>, z.ZodUnknown]>;
25
+ parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
26
+ place: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
27
+ end: "end";
28
+ start: "start";
29
+ }>>>;
30
+ before: z.ZodOptional<z.ZodNullable<z.ZodString>>;
31
+ after: z.ZodOptional<z.ZodNullable<z.ZodString>>;
32
+ }, z.core.$strip>;
33
+ /**
34
+ * The change payload is a title for a section target, or a block for an atom target, and exactly one of
35
+ * the two. Both fields are absentable, because a section retitle names no block. Zod 4 treats a bare
36
+ * `z.unknown()` as a required key, thus an optional marker is what makes the retitle call representable.
37
+ */
38
+ declare const changeBlockInput: z.ZodObject<{
39
+ targetId: z.ZodString;
40
+ title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
41
+ block: z.ZodOptional<z.ZodUnion<readonly [z.ZodType<import("../../report-model/draft.js").DraftBlock, unknown, z.core.$ZodTypeInternals<import("../../report-model/draft.js").DraftBlock, unknown>>, z.ZodUnknown]>>;
42
+ }, z.core.$strip>;
43
+ declare const removeBlockInput: z.ZodObject<{
44
+ targetId: z.ZodString;
45
+ }, z.core.$strip>;
46
+ declare const moveBlockInput: z.ZodObject<{
47
+ targetId: z.ZodString;
48
+ parentId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
49
+ place: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
50
+ end: "end";
51
+ start: "start";
52
+ }>>>;
53
+ before: z.ZodOptional<z.ZodNullable<z.ZodString>>;
54
+ after: z.ZodOptional<z.ZodNullable<z.ZodString>>;
55
+ }, z.core.$strip>;
56
+ declare const readOutlineInput: z.ZodObject<{}, z.core.$strip>;
57
+ /** The read names its target with the same field name as each mutation, thus one id key serves them all. */
58
+ declare const readBlockInput: z.ZodObject<{
59
+ targetId: z.ZodString;
60
+ }, z.core.$strip>;
61
+ declare const setTitleInput: z.ZodObject<{
62
+ title: z.ZodString;
63
+ }, z.core.$strip>;
64
+ declare const finishDraftInput: z.ZodObject<{}, z.core.$strip>;
65
+ export type AddBlockInput = z.infer<typeof addBlockInput>;
66
+ export type ChangeBlockInput = z.infer<typeof changeBlockInput>;
67
+ export type RemoveBlockInput = z.infer<typeof removeBlockInput>;
68
+ export type MoveBlockInput = z.infer<typeof moveBlockInput>;
69
+ export type ReadOutlineInput = z.infer<typeof readOutlineInput>;
70
+ export type ReadBlockInput = z.infer<typeof readBlockInput>;
71
+ export type SetTitleInput = z.infer<typeof setTitleInput>;
72
+ export type FinishDraftInput = z.infer<typeof finishDraftInput>;
73
+ /** One container that an operation changed, and the child order inside it after the operation. */
74
+ export interface ChangedContainer {
75
+ /** The section that holds the children. It is absent when the container is the root. */
76
+ parentId?: string;
77
+ children: OutlineEntry[];
78
+ }
79
+ /**
80
+ * The result of a mutation tool. A refusal carries the typed reason.
81
+ *
82
+ * A landing carries the child order of each container that it changed, and not the whole outline. A whole
83
+ * outline costs the size of the draft on every landing, thus composing a report of n blocks would spend
84
+ * n-squared outline entries of agent context to author it. Only the container that the operation touched
85
+ * can surprise the agent: it chose the id, and the rest of the tree did not move. `read_outline` stays
86
+ * the way to read the whole draft, and it costs one call when the agent wants one.
87
+ *
88
+ * A move across two containers reports both. An operation that changes no child order reports none.
89
+ */
90
+ export type MutationResult = {
91
+ applied: true;
92
+ changed: ChangedContainer[];
93
+ } | {
94
+ applied: false;
95
+ refusal: DraftRefusal;
96
+ };
97
+ /** The result of `read_outline`. */
98
+ export interface OutlineResult {
99
+ outline: OutlineEntry[];
100
+ }
101
+ /** The result of `read_block`. An absent block is an expected outcome, thus it stays in the ok channel. */
102
+ export type ReadBlockResult = {
103
+ found: true;
104
+ block: ReadableBlock;
105
+ } | {
106
+ found: false;
107
+ };
108
+ /** The state that the factory closes over. */
109
+ export interface ReportAuthoringState {
110
+ readonly snapshot: ReportSnapshot;
111
+ /** The draft to start from. The default is an empty draft. */
112
+ readonly initialDraft?: DraftDocument;
113
+ }
114
+ /** The eight authoring tools, plus a read of the current draft. */
115
+ export interface ReportAuthoringTools {
116
+ readonly add_block: Tool<AddBlockInput, MutationResult>;
117
+ readonly change_block: Tool<ChangeBlockInput, MutationResult>;
118
+ readonly remove_block: Tool<RemoveBlockInput, MutationResult>;
119
+ readonly move_block: Tool<MoveBlockInput, MutationResult>;
120
+ readonly set_title: Tool<SetTitleInput, MutationResult>;
121
+ readonly read_outline: Tool<ReadOutlineInput, OutlineResult>;
122
+ readonly read_block: Tool<ReadBlockInput, ReadBlockResult>;
123
+ readonly finish_draft: Tool<FinishDraftInput, FinishResult>;
124
+ currentDraft(): DraftDocument;
125
+ }
126
+ /**
127
+ * Make the eight authoring tools over one draft.
128
+ *
129
+ * The holder is a private `let`. Each tool reads the holder at call time, thus a landing through one tool
130
+ * shows in the next call of every tool. The holder swaps only inside `land`, thus a refused operation
131
+ * leaves the draft as it was.
132
+ */
133
+ export declare function createReportAuthoringTools(state: ReportAuthoringState): ReportAuthoringTools;
134
+ export {};
@@ -0,0 +1,352 @@
1
+ /**
2
+ * The authoring tool surface over the draft operations.
3
+ *
4
+ * The factory closes over a private draft holder and the pinned snapshot. It gives eight tools and a
5
+ * read of the current draft. The tools read no ambient state, thus two factories hold two independent
6
+ * drafts.
7
+ *
8
+ * Each tool maps its flat input onto a core operation, and it applies the pure operation. The holder
9
+ * swaps only on a landed operation. A refused operation returns typed data in the ok channel, and the
10
+ * error channel stays for an unexpected failure.
11
+ *
12
+ * The primitive admits a flat object input only. Thus a destination is four optional fields, and not a
13
+ * nested union. A conflict between the flat fields refuses before the core runs.
14
+ */
15
+ import { err, ok } from "neverthrow";
16
+ import { z } from "zod";
17
+ import { addBlock, changeBlock, locate, moveBlock, removeBlock, setTitle, } from "../../report-model/draft-operations.js";
18
+ import { buildOutline, childOutline, readBlock } from "../../report-model/draft-read.js";
19
+ import { finishDraft } from "../../report-model/draft-finish.js";
20
+ import { DraftBlockSchema } from "../../report-model/draft.js";
21
+ import { defineTool } from "../define-tool.js";
22
+ /**
23
+ * The block payload.
24
+ *
25
+ * The published JSON Schema carries the whole draft grammar, because a tool is self-describing at attach
26
+ * time and the schema is the only place where the model learns the shape of the eight block kinds. A bare
27
+ * `z.unknown()` emits the empty schema, which tells the model nothing and leaves it to discover each
28
+ * required field through one refusal at a time.
29
+ *
30
+ * The `z.unknown()` member keeps the runtime parse permissive. Thus a malformed payload still reaches the
31
+ * core, which parses it with the same grammar and refuses `malformed-block` as typed data in the ok
32
+ * channel. A strict input schema would turn that designed refusal into a hard input-validation error from
33
+ * the loop.
34
+ */
35
+ const blockPayload = z.union([DraftBlockSchema, z.unknown()]);
36
+ /**
37
+ * A flat field that the model can leave out.
38
+ *
39
+ * Nullish, and not optional. A model that must choose one of four destination fields routinely sends
40
+ * `null` for the three it does not use, and strict function calling requires every declared key to be
41
+ * present. Under `.optional()` each of those nulls fails the input parse, and the block never lands.
42
+ */
43
+ const absentable = (schema) => schema.nullish();
44
+ /** The flat destination fields. An anchor is `before` or `after`, and a place is `start` or `end`. */
45
+ const addBlockInput = z.object({
46
+ block: blockPayload,
47
+ parentId: absentable(z.string()),
48
+ place: absentable(z.enum(["start", "end"])),
49
+ before: absentable(z.string()),
50
+ after: absentable(z.string()),
51
+ });
52
+ /**
53
+ * The change payload is a title for a section target, or a block for an atom target, and exactly one of
54
+ * the two. Both fields are absentable, because a section retitle names no block. Zod 4 treats a bare
55
+ * `z.unknown()` as a required key, thus an optional marker is what makes the retitle call representable.
56
+ */
57
+ const changeBlockInput = z.object({
58
+ targetId: z.string(),
59
+ title: absentable(z.string()),
60
+ block: blockPayload.optional(),
61
+ });
62
+ const removeBlockInput = z.object({
63
+ targetId: z.string(),
64
+ });
65
+ const moveBlockInput = z.object({
66
+ targetId: z.string(),
67
+ parentId: absentable(z.string()),
68
+ place: absentable(z.enum(["start", "end"])),
69
+ before: absentable(z.string()),
70
+ after: absentable(z.string()),
71
+ });
72
+ const readOutlineInput = z.object({});
73
+ /** The read names its target with the same field name as each mutation, thus one id key serves them all. */
74
+ const readBlockInput = z.object({
75
+ targetId: z.string(),
76
+ });
77
+ const setTitleInput = z.object({
78
+ title: z.string().min(1),
79
+ });
80
+ const finishDraftInput = z.object({});
81
+ /** Read an absentable field. An explicit `null` and an omitted key both mean that the model gave no value. */
82
+ function given(value) {
83
+ return value ?? undefined;
84
+ }
85
+ /**
86
+ * Map the flat destination fields onto the core destination.
87
+ *
88
+ * Two anchors, or an anchor beside a place, name two places at one time. Thus the map refuses with
89
+ * `conflicting-destination`, and the detail names the conflict. An anchor implies its own parent, thus a
90
+ * place beside an anchor is a contradiction and not a refinement.
91
+ *
92
+ * The reason is not `unknown-target`, which means that no block holds a named id. A conflict is a fault in
93
+ * the shape of the call, and the repair is to drop one field. An agent that reads `unknown-target` instead
94
+ * goes back to the outline for a better id, finds the ids were already correct, and sends the same
95
+ * conflicting pair again.
96
+ */
97
+ function toDestination(input) {
98
+ const parentId = given(input.parentId);
99
+ const place = given(input.place);
100
+ const before = given(input.before);
101
+ const after = given(input.after);
102
+ if (before !== undefined && after !== undefined) {
103
+ return err({ reason: "conflicting-destination", detail: "a destination names `before` or `after`, not both" });
104
+ }
105
+ const hasAnchor = before !== undefined || after !== undefined;
106
+ if (hasAnchor && place !== undefined) {
107
+ return err({ reason: "conflicting-destination", detail: "a destination names an anchor or a `place`, not both" });
108
+ }
109
+ let resolvedPlace;
110
+ if (before !== undefined) {
111
+ resolvedPlace = { before };
112
+ }
113
+ else if (after !== undefined) {
114
+ resolvedPlace = { after };
115
+ }
116
+ else {
117
+ resolvedPlace = place;
118
+ }
119
+ return ok({ parentId, place: resolvedPlace });
120
+ }
121
+ /**
122
+ * Map the flat change fields onto the core change operation.
123
+ *
124
+ * A change names a title or a block, and exactly one of the two. Neither field and both fields each name
125
+ * an ambiguous change. Thus the map refuses with `payload-kind-mismatch`.
126
+ */
127
+ function toChangeOperation(input) {
128
+ const title = given(input.title);
129
+ const block = given(input.block);
130
+ if (title !== undefined && block !== undefined) {
131
+ return err({ reason: "payload-kind-mismatch", detail: "a change names a `title` or a `block`, not both" });
132
+ }
133
+ if (title !== undefined) {
134
+ return ok({ targetId: input.targetId, title });
135
+ }
136
+ if (block !== undefined) {
137
+ return ok({ targetId: input.targetId, block: decodeBlockPayload(block) });
138
+ }
139
+ return err({ reason: "payload-kind-mismatch", detail: "a change names a `title` or a `block`" });
140
+ }
141
+ /**
142
+ * Give the block payload as the core expects it, and decode a double-encoded one.
143
+ *
144
+ * A model routinely sends a nested object as a `JSON.stringify` string. The loop repairs that at its own
145
+ * input boundary, but only for a schema that rejects the string, and this payload accepts any value so
146
+ * that a malformed block can come back as a typed refusal. Thus the decode happens here. A string that is
147
+ * not JSON passes through as it is, and the core refuses it as a malformed block.
148
+ */
149
+ function decodeBlockPayload(block) {
150
+ if (typeof block !== "string") {
151
+ return block;
152
+ }
153
+ try {
154
+ return JSON.parse(block);
155
+ }
156
+ catch {
157
+ return block;
158
+ }
159
+ }
160
+ /** Read the `kind` of an untyped block payload, or `undefined` when the payload names none. */
161
+ function readKind(block) {
162
+ return readStringField(block, "kind");
163
+ }
164
+ /** Read the `id` of an untyped block payload, or `undefined` when the payload names none. */
165
+ function readId(block) {
166
+ return readStringField(block, "id");
167
+ }
168
+ function readStringField(block, field) {
169
+ if (block !== null && typeof block === "object") {
170
+ const value = block[field];
171
+ if (typeof value === "string") {
172
+ return value;
173
+ }
174
+ }
175
+ return undefined;
176
+ }
177
+ /**
178
+ * The id of the section that holds a block, or `undefined` when the block sits at the root.
179
+ *
180
+ * The two cases are not distinguishable from the value alone, thus a caller that needs to tell "the root"
181
+ * from "no such block" tests the block itself first.
182
+ */
183
+ function holderIdOf(document, blockId) {
184
+ return locate(document, blockId)?.parent?.id;
185
+ }
186
+ /** Read the child order of one container out of a document. */
187
+ function containerIn(document, parentId) {
188
+ if (parentId === undefined) {
189
+ return { children: childOutline(document.sections, 0) };
190
+ }
191
+ const located = locate(document, parentId);
192
+ // A parent id reaches here only from a landed operation, which already resolved it to a section. The
193
+ // empty fall-back keeps the read total rather than asserting that.
194
+ const children = located !== undefined && located.block.kind === "section" ? located.block.blocks : [];
195
+ return { parentId, children: childOutline(children, located?.path.length ?? 0) };
196
+ }
197
+ /**
198
+ * Every tool of this surface runs inline.
199
+ *
200
+ * The draft is closure memory with no durable backing. A step-mode tool goes through `DBOS.runStep`, which
201
+ * caches the result of a step and replays it without running the body. A replay after a host restart would
202
+ * hand the agent the cached `applied: true` outline of each landed operation while the rebuilt closure
203
+ * holds an empty draft, and the finish would then report an empty document for a report that the
204
+ * transcript shows as complete. Inline mode keeps the tool result and the draft in one lifetime.
205
+ */
206
+ const AUTHORING_EXECUTION_MODE = "inline";
207
+ /**
208
+ * Make the eight authoring tools over one draft.
209
+ *
210
+ * The holder is a private `let`. Each tool reads the holder at call time, thus a landing through one tool
211
+ * shows in the next call of every tool. The holder swaps only inside `land`, thus a refused operation
212
+ * leaves the draft as it was.
213
+ */
214
+ export function createReportAuthoringTools(state) {
215
+ const snapshot = state.snapshot;
216
+ let draft = state.initialDraft ?? { title: "", sections: [] };
217
+ /**
218
+ * Swap the holder on a landing, and report the containers that the operation changed.
219
+ *
220
+ * `holders` names them by id, and it reads the draft as it was and the draft as it becomes, because a
221
+ * removed block has a holder only in the first and an added block has one only in the second. The
222
+ * child order comes out of `next` in either case.
223
+ */
224
+ const land = (result, holders) => result.match((next) => {
225
+ const previous = draft;
226
+ draft = next;
227
+ // A move inside one container names the same holder two times.
228
+ const unique = [...new Set(holders(previous, next))];
229
+ return { applied: true, changed: unique.map((parentId) => containerIn(next, parentId)) };
230
+ }, (refusal) => ({ applied: false, refusal }));
231
+ const refuse = (refusal) => ({ applied: false, refusal });
232
+ const add_block = defineTool({
233
+ id: "add_block",
234
+ description: "Add one block to the draft. The `block` schema gives the eight kinds and the fields of each one. " +
235
+ "You choose the `id` of the block, and it must be unique in the draft. " +
236
+ "Name the destination with `parentId` and one of `place`, `before`, or `after`. " +
237
+ "The root admits a section only, and an atom needs a section as its parent.",
238
+ inputSchema: addBlockInput,
239
+ executionMode: AUTHORING_EXECUTION_MODE,
240
+ describeCall: (input) => {
241
+ const kind = readKind(decodeBlockPayload(input.block));
242
+ return kind !== undefined ? `add ${kind}` : "add a block";
243
+ },
244
+ execute: async (input) => {
245
+ const destination = toDestination(input);
246
+ if (destination.isErr()) {
247
+ return ok(refuse(destination.error));
248
+ }
249
+ const block = decodeBlockPayload(input.block);
250
+ const addedId = readId(block);
251
+ return ok(land(addBlock(draft, { block, destination: destination.value }, snapshot), (_previous, next) => [
252
+ addedId === undefined ? undefined : holderIdOf(next, addedId),
253
+ ]));
254
+ },
255
+ });
256
+ const change_block = defineTool({
257
+ id: "change_block",
258
+ description: "Change one block by its id. Give a `title` to retitle a section, or a `block` to replace an atom, and never both. " +
259
+ "The change keeps the id of the target, thus the `id` of the payload does not matter. A kind change is permitted.",
260
+ inputSchema: changeBlockInput,
261
+ executionMode: AUTHORING_EXECUTION_MODE,
262
+ describeCall: (input) => `change ${input.targetId}`,
263
+ execute: async (input) => {
264
+ const operation = toChangeOperation(input);
265
+ if (operation.isErr()) {
266
+ return ok(refuse(operation.error));
267
+ }
268
+ return ok(land(changeBlock(draft, operation.value, snapshot), (_previous, next) => [holderIdOf(next, input.targetId)]));
269
+ },
270
+ });
271
+ const remove_block = defineTool({
272
+ id: "remove_block",
273
+ description: "Remove one block by its id. A removed section takes its whole subtree with it, and the id is free for a later add.",
274
+ inputSchema: removeBlockInput,
275
+ executionMode: AUTHORING_EXECUTION_MODE,
276
+ describeCall: (input) => `remove ${input.targetId}`,
277
+ execute: async (input) => ok(land(removeBlock(draft, { targetId: input.targetId }, snapshot), (previous) => [holderIdOf(previous, input.targetId)])),
278
+ });
279
+ const move_block = defineTool({
280
+ id: "move_block",
281
+ description: "Move one block by its id to a new destination. Name the destination with `parentId` and one of `place`, `before`, or `after`. " +
282
+ "A section cannot move into its own subtree.",
283
+ inputSchema: moveBlockInput,
284
+ executionMode: AUTHORING_EXECUTION_MODE,
285
+ describeCall: (input) => `move ${input.targetId}`,
286
+ execute: async (input) => {
287
+ const destination = toDestination(input);
288
+ if (destination.isErr()) {
289
+ return ok(refuse(destination.error));
290
+ }
291
+ return ok(land(moveBlock(draft, { targetId: input.targetId, destination: destination.value }, snapshot), (previous, next) => [
292
+ holderIdOf(previous, input.targetId),
293
+ holderIdOf(next, input.targetId),
294
+ ]));
295
+ },
296
+ });
297
+ const set_title = defineTool({
298
+ id: "set_title",
299
+ description: "Set the title of the report document. A draft starts with no title, and a document needs one. " +
300
+ "The title names the whole report, and it is not the title of a section.",
301
+ inputSchema: setTitleInput,
302
+ executionMode: AUTHORING_EXECUTION_MODE,
303
+ describeCall: (input) => `title the report ${input.title}`,
304
+ // The title sits on the document, thus no container changes its child order.
305
+ execute: async (input) => ok(land(ok(setTitle(draft, input.title)), () => [])),
306
+ });
307
+ const read_outline = defineTool({
308
+ id: "read_outline",
309
+ description: "Read the outline of the draft. Each entry gives the id, the kind, the nesting depth, and a short label. " +
310
+ "A label that ends with the character … is clipped. Use the outline as the primary view of the draft, " +
311
+ "and read one block when the label is not enough.",
312
+ inputSchema: readOutlineInput,
313
+ executionMode: AUTHORING_EXECUTION_MODE,
314
+ // The input carries no field, thus a hook can only restate the name of the tool.
315
+ describeCall: "none",
316
+ execute: async () => ok({ outline: buildOutline(draft) }),
317
+ });
318
+ const read_block = defineTool({
319
+ id: "read_block",
320
+ description: "Read one block by its id. An atom gives the full block with its bindings. A section gives its title and the id of each child, " +
321
+ "because the outline already names every block under it. Use it when the outline label is not enough.",
322
+ inputSchema: readBlockInput,
323
+ executionMode: AUTHORING_EXECUTION_MODE,
324
+ describeCall: (input) => `read ${input.targetId}`,
325
+ execute: async (input) => {
326
+ const block = readBlock(draft, input.targetId);
327
+ const result = block !== undefined ? { found: true, block } : { found: false };
328
+ return ok(result);
329
+ },
330
+ });
331
+ const finish_draft = defineTool({
332
+ id: "finish_draft",
333
+ description: "Finish the draft. The result gives each completeness gap, or the valid report document, and each advisory warning. " +
334
+ "Use it to make sure that the draft passes the whole document schema, the id rule, and the structural tier.",
335
+ inputSchema: finishDraftInput,
336
+ executionMode: AUTHORING_EXECUTION_MODE,
337
+ // The input carries no field, thus a hook can only restate the name of the tool.
338
+ describeCall: "none",
339
+ execute: async () => ok(finishDraft(draft, snapshot)),
340
+ });
341
+ return {
342
+ add_block,
343
+ change_block,
344
+ remove_block,
345
+ move_block,
346
+ set_title,
347
+ read_outline,
348
+ read_block,
349
+ finish_draft,
350
+ currentDraft: () => draft,
351
+ };
352
+ }
@@ -25,6 +25,7 @@ export const resolveLibraryIdTool = defineTool({
25
25
  libraryName: z.string().describe("Package or library name to search for (e.g., 'scanpy', 'pysam', 'lifelines')."),
26
26
  query: z.string().describe("What you need help with — used to rank results by relevance (e.g., 'how to run differential expression')."),
27
27
  }),
28
+ describeCall: "none",
28
29
  execute: async ({ libraryName, query }) => {
29
30
  const result = await apiFetchValidated(`${CONTEXT7_BASE}/search?query=${encodeURIComponent(libraryName)}&topic=${encodeURIComponent(query)}`, Context7SearchResponseSchema, { maxRetries: 1 });
30
31
  if (result.isErr())
@@ -48,6 +49,7 @@ export const queryDocsTool = defineTool({
48
49
  libraryId: z.string().describe("Context7 library ID from resolve-library-id (e.g., '/scverse/scanpy')."),
49
50
  query: z.string().describe("Specific question about the library (e.g., 'rank_genes_groups function parameters and usage')."),
50
51
  }),
52
+ describeCall: "none",
51
53
  execute: async ({ libraryId, query }) => {
52
54
  const result = await apiFetchValidated(`${CONTEXT7_BASE}/docs?libraryId=${encodeURIComponent(libraryId)}&query=${encodeURIComponent(query)}`, Context7DocsResponseSchema, { maxRetries: 1 });
53
55
  if (result.isErr())
@@ -23,7 +23,7 @@ import { finalText, runAgent } from "../../loop/run-agent.js";
23
23
  import { passthroughStep } from "../../loop/run-step.js";
24
24
  import { defineTool } from "../define-tool.js";
25
25
  // Cross-domain search tools the analogical-reasoner uses.
26
- import { searchSemanticScholarTool } from "./search-semantic-scholar.js";
26
+ import { createSearchSemanticScholarTool } from "./search-semantic-scholar.js";
27
27
  import { searchArxivTool } from "./search-arxiv.js";
28
28
  import { createSearchGithubReposTool } from "./search-github-repos.js";
29
29
  // Biology literature — reused for analogies that land back in biology.
@@ -156,7 +156,7 @@ function buildConversionPrompt(rawOutput) {
156
156
  export function createGenerateAnalogyReportTool(deps) {
157
157
  const ncbi = createNcbiTools(deps.bioKeys);
158
158
  const reasonerTools = [
159
- searchSemanticScholarTool,
159
+ createSearchSemanticScholarTool({ ...(deps.bioKeys.semanticScholar === undefined ? {} : { apiKey: deps.bioKeys.semanticScholar }) }),
160
160
  searchArxivTool,
161
161
  createSearchGithubReposTool({ githubToken: deps.bioKeys.github }),
162
162
  ncbi.pubmed,
@@ -193,6 +193,7 @@ export function createGenerateAnalogyReportTool(deps) {
193
193
  "latency on the same failure). Surface the message and ask the user to " +
194
194
  "narrow the problem.",
195
195
  inputSchema: generateAnalogyReportInputSchema,
196
+ describeCall: "none",
196
197
  execute: async (input, ctx) => {
197
198
  const childSession = forSubAgent(ctx.session, AGENT_ID);
198
199
  // Phase 1+2: drive the research agent over the cross-domain toolset.
@@ -344,6 +344,7 @@ function buildInnerTools(holder, trace, persistCtx, pool, resourcePolicy, logger
344
344
  // structured issue reporting.
345
345
  plan: z.union([PlannerPlanSchema, z.unknown()]).describe("Candidate plan; malformed values are reported in issues."),
346
346
  }),
347
+ describeCall: "none",
347
348
  execute: async (input) => {
348
349
  if (holder.outcome !== null) {
349
350
  trace.duplicateTerminalCalls++;
@@ -416,6 +417,7 @@ function buildInnerTools(holder, trace, persistCtx, pool, resourcePolicy, logger
416
417
  question: z.string().min(1),
417
418
  questionContext: z.string().optional(),
418
419
  }),
420
+ describeCall: "none",
419
421
  execute: async (input) => {
420
422
  if (holder.outcome !== null) {
421
423
  trace.duplicateTerminalCalls++;
@@ -670,6 +672,7 @@ export function createGeneratePlanTool(deps) {
670
672
  .optional()
671
673
  .describe("The planId of the prior plan being iterated on. Set only when " + "the user is asking for modifications to an existing plan."),
672
674
  }),
675
+ describeCall: ({ researchQuestion }) => researchQuestion,
673
676
  execute: async (input, ctx) => {
674
677
  const analysisId = scopeResource(ctx.session.scope).resourceId;
675
678
  // Bound per invocation: `analysisId` comes from the call-time session, not from
@@ -14,3 +14,4 @@ export * from "./context7-docs.js";
14
14
  export * from "./search-semantic-scholar.js";
15
15
  export * from "./search-arxiv.js";
16
16
  export * from "./search-github-repos.js";
17
+ export * from "./resolve-citation.js";
@@ -14,3 +14,4 @@ export * from "./context7-docs.js";
14
14
  export * from "./search-semantic-scholar.js";
15
15
  export * from "./search-arxiv.js";
16
16
  export * from "./search-github-repos.js";
17
+ export * from "./resolve-citation.js";
@@ -98,6 +98,10 @@ export function createInspectDataProfileTool(pool) {
98
98
  .optional()
99
99
  .describe(`Per-file records per page. Only used when scope is 'files'. Default ${DEFAULT_PAGE_SIZE}, max ${MAX_PAGE_SIZE}.`),
100
100
  }),
101
+ // `execute` defaults both fields internally, and the hook applies the same
102
+ // defaults. Without them the ordinary call, which names no field at all,
103
+ // gives no detail. `page` acts only on the `files` scope, as in `execute`.
104
+ describeCall: ({ scope, page }) => ((scope ?? "overview") === "files" ? `files (page ${page ?? 1})` : "overview"),
101
105
  execute: async (input, ctx) => {
102
106
  const resourceId = scopeResource(ctx.session.scope).resourceId;
103
107
  const status = unwrapOrThrow(await loadDataProfileStatus(pool, resourceId));
@@ -53,7 +53,7 @@ declare function formatRun(r: CortexRunRow, verbose: boolean, exposePaths?: bool
53
53
  synthesisReason?: string | undefined;
54
54
  runId: string;
55
55
  workflowName: string;
56
- status: "running" | "completed" | "failed" | "partial" | "canceled" | "suspended_insufficient_funds";
56
+ status: "partial" | "running" | "completed" | "failed" | "canceled" | "suspended_insufficient_funds";
57
57
  startedAt: string;
58
58
  completedAt: string | null;
59
59
  planId: string | null;
@@ -19,6 +19,7 @@ import { type Tool } from "../define-tool.js";
19
19
  import { type BioToolKeys } from "../bio/keys.js";
20
20
  import type { Logger } from "../../lib/logger.js";
21
21
  import type { UsageRecorder } from "../../billing/usage-recorder.js";
22
+ import type { CitationResolver } from "../../citations/types.js";
22
23
  export interface LiteratureReviewerDeps {
23
24
  /** Operational logging seam; omitted falls back to no-op. */
24
25
  readonly logger?: Logger;
@@ -30,6 +31,8 @@ export interface LiteratureReviewerDeps {
30
31
  readonly bioKeys: BioToolKeys;
31
32
  /** LLM usage-accounting seam for the child loop; omitted falls back to the no-op recorder. */
32
33
  readonly usageRecorder?: UsageRecorder;
34
+ /** Shared bibliographic verification service; all agent surfaces share its pacing/cache. */
35
+ readonly citationResolver: CitationResolver;
33
36
  }
34
37
  /** Build the `literature_reviewer` delegation tool bound to its provider. */
35
38
  export declare function createLiteratureReviewerTool(deps: LiteratureReviewerDeps): Tool;