celltype-cli 0.1.0__py3-none-any.whl

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 (89) hide show
  1. celltype_cli-0.1.0.dist-info/METADATA +267 -0
  2. celltype_cli-0.1.0.dist-info/RECORD +89 -0
  3. celltype_cli-0.1.0.dist-info/WHEEL +4 -0
  4. celltype_cli-0.1.0.dist-info/entry_points.txt +2 -0
  5. celltype_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
  6. ct/__init__.py +3 -0
  7. ct/agent/__init__.py +0 -0
  8. ct/agent/case_studies.py +426 -0
  9. ct/agent/config.py +523 -0
  10. ct/agent/doctor.py +544 -0
  11. ct/agent/knowledge.py +523 -0
  12. ct/agent/loop.py +99 -0
  13. ct/agent/mcp_server.py +478 -0
  14. ct/agent/orchestrator.py +733 -0
  15. ct/agent/runner.py +656 -0
  16. ct/agent/sandbox.py +481 -0
  17. ct/agent/session.py +145 -0
  18. ct/agent/system_prompt.py +186 -0
  19. ct/agent/trace_store.py +228 -0
  20. ct/agent/trajectory.py +169 -0
  21. ct/agent/types.py +182 -0
  22. ct/agent/workflows.py +462 -0
  23. ct/api/__init__.py +1 -0
  24. ct/api/app.py +211 -0
  25. ct/api/config.py +120 -0
  26. ct/api/engine.py +124 -0
  27. ct/cli.py +1448 -0
  28. ct/data/__init__.py +0 -0
  29. ct/data/compute_providers.json +59 -0
  30. ct/data/cro_database.json +395 -0
  31. ct/data/downloader.py +238 -0
  32. ct/data/loaders.py +252 -0
  33. ct/kb/__init__.py +5 -0
  34. ct/kb/benchmarks.py +147 -0
  35. ct/kb/governance.py +106 -0
  36. ct/kb/ingest.py +415 -0
  37. ct/kb/reasoning.py +129 -0
  38. ct/kb/schema_monitor.py +162 -0
  39. ct/kb/substrate.py +387 -0
  40. ct/models/__init__.py +0 -0
  41. ct/models/llm.py +370 -0
  42. ct/tools/__init__.py +195 -0
  43. ct/tools/_compound_resolver.py +297 -0
  44. ct/tools/biomarker.py +368 -0
  45. ct/tools/cellxgene.py +282 -0
  46. ct/tools/chemistry.py +1371 -0
  47. ct/tools/claude.py +390 -0
  48. ct/tools/clinical.py +1153 -0
  49. ct/tools/clue.py +249 -0
  50. ct/tools/code.py +1069 -0
  51. ct/tools/combination.py +397 -0
  52. ct/tools/compute.py +402 -0
  53. ct/tools/cro.py +413 -0
  54. ct/tools/data_api.py +2114 -0
  55. ct/tools/design.py +295 -0
  56. ct/tools/dna.py +575 -0
  57. ct/tools/experiment.py +604 -0
  58. ct/tools/expression.py +655 -0
  59. ct/tools/files.py +957 -0
  60. ct/tools/genomics.py +1387 -0
  61. ct/tools/http_client.py +146 -0
  62. ct/tools/imaging.py +319 -0
  63. ct/tools/intel.py +223 -0
  64. ct/tools/literature.py +743 -0
  65. ct/tools/network.py +422 -0
  66. ct/tools/notification.py +111 -0
  67. ct/tools/omics.py +3330 -0
  68. ct/tools/ops.py +1230 -0
  69. ct/tools/parity.py +649 -0
  70. ct/tools/pk.py +245 -0
  71. ct/tools/protein.py +678 -0
  72. ct/tools/regulatory.py +643 -0
  73. ct/tools/remote_data.py +179 -0
  74. ct/tools/report.py +181 -0
  75. ct/tools/repurposing.py +376 -0
  76. ct/tools/safety.py +1280 -0
  77. ct/tools/shell.py +178 -0
  78. ct/tools/singlecell.py +533 -0
  79. ct/tools/statistics.py +552 -0
  80. ct/tools/structure.py +882 -0
  81. ct/tools/target.py +901 -0
  82. ct/tools/translational.py +123 -0
  83. ct/tools/viability.py +218 -0
  84. ct/ui/__init__.py +0 -0
  85. ct/ui/markdown.py +31 -0
  86. ct/ui/status.py +258 -0
  87. ct/ui/suggestions.py +567 -0
  88. ct/ui/terminal.py +1456 -0
  89. ct/ui/traces.py +112 -0
@@ -0,0 +1,426 @@
1
+ """Curated case study definitions and runner for ct.
2
+
3
+ Provides pre-defined multi-agent research profiles for landmark drugs,
4
+ designed for demos, conference presentations, and sales collateral.
5
+
6
+ Each case study defines 3-4 complementary research angles that are
7
+ executed in parallel via the ResearchOrchestrator (bypassing the LLM
8
+ decomposition step).
9
+ """
10
+
11
+ import logging
12
+ from dataclasses import dataclass, field
13
+
14
+ from ct.agent.orchestrator import OrchestratorResult, ResearchOrchestrator, ThreadGoal
15
+
16
+ logger = logging.getLogger("ct.case_studies")
17
+
18
+
19
+ @dataclass
20
+ class CaseStudy:
21
+ """A curated drug case study for demo/showcase purposes."""
22
+
23
+ id: str
24
+ name: str
25
+ compound: str
26
+ targets: list[str]
27
+ indication: str
28
+ description: str
29
+ thread_goals: list[dict] = field(default_factory=list)
30
+
31
+
32
+ # ─── Case study registry ──────────────────────────────────────
33
+
34
+ CASE_STUDIES: dict[str, CaseStudy] = {
35
+ "revlimid": CaseStudy(
36
+ id="revlimid",
37
+ name="Revlimid (lenalidomide)",
38
+ compound="lenalidomide",
39
+ targets=["CRBN", "IKZF1", "IKZF3"],
40
+ indication="multiple myeloma",
41
+ description=(
42
+ "Lenalidomide is the poster child of molecular glue degraders — "
43
+ "an IMiD that hijacks CRBN to degrade IKZF1/3 transcription factors. "
44
+ "A $12B/yr blockbuster that transformed myeloma treatment."
45
+ ),
46
+ thread_goals=[
47
+ {
48
+ "angle": "Target Biology & Mechanism",
49
+ "goal": (
50
+ "Investigate CRBN E3 ligase biology, IKZF1/IKZF3 neosubstrate "
51
+ "degradation mechanism, and co-essential gene networks for "
52
+ "lenalidomide targets in multiple myeloma."
53
+ ),
54
+ "suggested_tools": [
55
+ "target.druggability",
56
+ "target.expression_profile",
57
+ "target.coessentiality",
58
+ "target.disease_association",
59
+ ],
60
+ },
61
+ {
62
+ "angle": "Chemical Analysis & SAR",
63
+ "goal": (
64
+ "Analyze lenalidomide structure, SAR landscape, find similar "
65
+ "IMiD compounds in ChEMBL, and assess ADMET properties."
66
+ ),
67
+ "suggested_tools": [
68
+ "chemistry.similarity_search",
69
+ "chemistry.sar_analyze",
70
+ "chemistry.descriptors",
71
+ "safety.admet_predict",
72
+ ],
73
+ },
74
+ {
75
+ "angle": "Clinical Landscape",
76
+ "goal": (
77
+ "Map lenalidomide clinical indications, competitive landscape "
78
+ "in multiple myeloma, active clinical trials, and patient "
79
+ "population estimates."
80
+ ),
81
+ "suggested_tools": [
82
+ "clinical.indication_map",
83
+ "clinical.competitive_landscape",
84
+ "clinical.trial_search",
85
+ "clinical.population_size",
86
+ ],
87
+ },
88
+ {
89
+ "angle": "Safety & Resistance",
90
+ "goal": (
91
+ "Profile lenalidomide safety: SALL4 risk, antitarget activity, "
92
+ "known resistance mutations in CRBN, and biomarker strategy "
93
+ "for patient selection."
94
+ ),
95
+ "suggested_tools": [
96
+ "safety.sall4_risk",
97
+ "safety.antitarget_profile",
98
+ "biomarker.resistance_profile",
99
+ "biomarker.mutation_sensitivity",
100
+ ],
101
+ },
102
+ ],
103
+ ),
104
+ "gleevec": CaseStudy(
105
+ id="gleevec",
106
+ name="Gleevec (imatinib)",
107
+ compound="imatinib",
108
+ targets=["BCR-ABL", "ABL1", "KIT", "PDGFRA"],
109
+ indication="chronic myeloid leukemia",
110
+ description=(
111
+ "Imatinib revolutionized cancer therapy as the first rationally "
112
+ "designed kinase inhibitor. It transformed CML from a fatal "
113
+ "diagnosis to a manageable chronic condition."
114
+ ),
115
+ thread_goals=[
116
+ {
117
+ "angle": "Target Biology & Selectivity",
118
+ "goal": (
119
+ "Investigate BCR-ABL fusion biology, ABL1 kinase domain, "
120
+ "off-target kinase activity on KIT and PDGFRA, and "
121
+ "expression profiles across leukemia subtypes."
122
+ ),
123
+ "suggested_tools": [
124
+ "target.druggability",
125
+ "target.expression_profile",
126
+ "data_api.uniprot_lookup",
127
+ "network.ppi_analysis",
128
+ ],
129
+ },
130
+ {
131
+ "angle": "Structural & Chemical Analysis",
132
+ "goal": (
133
+ "Analyze imatinib binding mode, SAR of 2-phenylaminopyrimidine "
134
+ "scaffold, compare with nilotinib/dasatinib, and assess "
135
+ "key pharmacophore features."
136
+ ),
137
+ "suggested_tools": [
138
+ "chemistry.sar_analyze",
139
+ "chemistry.similarity_search",
140
+ "chemistry.pharmacophore",
141
+ "structure.binding_site",
142
+ ],
143
+ },
144
+ {
145
+ "angle": "Resistance & Biomarkers",
146
+ "goal": (
147
+ "Profile imatinib resistance mutations (T315I gatekeeper), "
148
+ "resistance mechanisms, and biomarker-guided treatment "
149
+ "selection strategies in CML."
150
+ ),
151
+ "suggested_tools": [
152
+ "biomarker.resistance_profile",
153
+ "biomarker.mutation_sensitivity",
154
+ "genomics.variant_annotate",
155
+ "literature.pubmed_search",
156
+ ],
157
+ },
158
+ ],
159
+ ),
160
+ "keytruda": CaseStudy(
161
+ id="keytruda",
162
+ name="Keytruda (pembrolizumab)",
163
+ compound="pembrolizumab",
164
+ targets=["PD-1", "PDCD1"],
165
+ indication="non-small cell lung cancer",
166
+ description=(
167
+ "Pembrolizumab is the world's best-selling drug ($25B/yr) — "
168
+ "a PD-1 checkpoint inhibitor that unleashes the immune system "
169
+ "against cancer. Approved in 30+ tumor types."
170
+ ),
171
+ thread_goals=[
172
+ {
173
+ "angle": "Immuno-Oncology Mechanism",
174
+ "goal": (
175
+ "Investigate PD-1/PD-L1 checkpoint biology, immune evasion "
176
+ "mechanisms, and immune cell infiltration patterns across "
177
+ "pembrolizumab-responsive tumor types."
178
+ ),
179
+ "suggested_tools": [
180
+ "target.expression_profile",
181
+ "target.disease_association",
182
+ "expression.immune_score",
183
+ "expression.deconvolution",
184
+ ],
185
+ },
186
+ {
187
+ "angle": "Biomarker Strategy",
188
+ "goal": (
189
+ "Analyze pembrolizumab biomarkers: PD-L1 expression (TPS/CPS), "
190
+ "MSI-H/dMMR, TMB, and emerging biomarkers for response "
191
+ "prediction across indications."
192
+ ),
193
+ "suggested_tools": [
194
+ "biomarker.panel_select",
195
+ "biomarker.mutation_sensitivity",
196
+ "genomics.gwas_lookup",
197
+ "literature.pubmed_search",
198
+ ],
199
+ },
200
+ {
201
+ "angle": "Clinical Positioning",
202
+ "goal": (
203
+ "Map pembrolizumab across 30+ approved indications, "
204
+ "competitive landscape vs nivolumab/atezolizumab, ongoing "
205
+ "combination trials, and market positioning."
206
+ ),
207
+ "suggested_tools": [
208
+ "clinical.indication_map",
209
+ "clinical.competitive_landscape",
210
+ "clinical.trial_search",
211
+ "clinical.population_size",
212
+ ],
213
+ },
214
+ {
215
+ "angle": "Combination & Resistance",
216
+ "goal": (
217
+ "Explore pembrolizumab combination strategies (chemo, TKIs, "
218
+ "other I/O agents), mechanisms of acquired resistance, and "
219
+ "potential synergy partners."
220
+ ),
221
+ "suggested_tools": [
222
+ "combination.synergy_predict",
223
+ "biomarker.resistance_profile",
224
+ "literature.pubmed_search",
225
+ "expression.pathway_enrichment",
226
+ ],
227
+ },
228
+ ],
229
+ ),
230
+ "ozempic": CaseStudy(
231
+ id="ozempic",
232
+ name="Ozempic (semaglutide)",
233
+ compound="semaglutide",
234
+ targets=["GLP1R"],
235
+ indication="type 2 diabetes / obesity",
236
+ description=(
237
+ "Semaglutide is the GLP-1 receptor agonist behind the obesity "
238
+ "revolution. Originally for T2D, it crossed over into obesity, "
239
+ "cardiovascular protection, and potentially NASH/MASH."
240
+ ),
241
+ thread_goals=[
242
+ {
243
+ "angle": "Target Biology & Signaling",
244
+ "goal": (
245
+ "Investigate GLP-1 receptor biology, downstream signaling "
246
+ "cascades, expression across metabolic tissues, and "
247
+ "structural basis for semaglutide binding."
248
+ ),
249
+ "suggested_tools": [
250
+ "target.druggability",
251
+ "target.expression_profile",
252
+ "data_api.uniprot_lookup",
253
+ "expression.pathway_enrichment",
254
+ ],
255
+ },
256
+ {
257
+ "angle": "Clinical Indications & Expansion",
258
+ "goal": (
259
+ "Map semaglutide clinical indications (T2D, obesity, CVOT), "
260
+ "pipeline expansion into NASH/MASH and Alzheimer's, "
261
+ "competitive landscape vs tirzepatide."
262
+ ),
263
+ "suggested_tools": [
264
+ "clinical.indication_map",
265
+ "clinical.competitive_landscape",
266
+ "clinical.trial_search",
267
+ "clinical.population_size",
268
+ ],
269
+ },
270
+ {
271
+ "angle": "Safety & Pharmacology",
272
+ "goal": (
273
+ "Assess semaglutide safety profile: GI side effects, "
274
+ "thyroid C-cell risk, pancreatitis signal, and long-term "
275
+ "cardiovascular outcomes data."
276
+ ),
277
+ "suggested_tools": [
278
+ "safety.admet_predict",
279
+ "safety.classify",
280
+ "literature.pubmed_search",
281
+ "data_api.drug_info",
282
+ ],
283
+ },
284
+ ],
285
+ ),
286
+ "xalkori": CaseStudy(
287
+ id="xalkori",
288
+ name="Xalkori (crizotinib)",
289
+ compound="crizotinib",
290
+ targets=["ALK", "ROS1", "MET"],
291
+ indication="ALK+ non-small cell lung cancer",
292
+ description=(
293
+ "Crizotinib pioneered precision oncology — the first ALK inhibitor "
294
+ "approved alongside a companion diagnostic. It proved that matching "
295
+ "drugs to molecular subtypes transforms outcomes."
296
+ ),
297
+ thread_goals=[
298
+ {
299
+ "angle": "Target Biology & Fusions",
300
+ "goal": (
301
+ "Investigate ALK fusion biology (EML4-ALK), ROS1 "
302
+ "rearrangements, MET amplification, and expression/dependency "
303
+ "profiles across NSCLC subtypes."
304
+ ),
305
+ "suggested_tools": [
306
+ "target.druggability",
307
+ "target.expression_profile",
308
+ "target.disease_association",
309
+ "genomics.variant_annotate",
310
+ ],
311
+ },
312
+ {
313
+ "angle": "Chemical SAR & Next-Gen Inhibitors",
314
+ "goal": (
315
+ "Analyze crizotinib SAR (aminopyridine scaffold), compare "
316
+ "with next-gen ALK inhibitors (alectinib, lorlatinib), "
317
+ "and structural basis for selectivity."
318
+ ),
319
+ "suggested_tools": [
320
+ "chemistry.sar_analyze",
321
+ "chemistry.similarity_search",
322
+ "chemistry.descriptors",
323
+ "structure.binding_site",
324
+ ],
325
+ },
326
+ {
327
+ "angle": "Resistance & Companion Diagnostics",
328
+ "goal": (
329
+ "Profile crizotinib resistance mutations (L1196M, G1269A), "
330
+ "next-gen ALK inhibitor strategies, and companion diagnostic "
331
+ "requirements for ALK/ROS1 testing."
332
+ ),
333
+ "suggested_tools": [
334
+ "biomarker.resistance_profile",
335
+ "biomarker.mutation_sensitivity",
336
+ "biomarker.panel_select",
337
+ "literature.pubmed_search",
338
+ ],
339
+ },
340
+ ],
341
+ ),
342
+ }
343
+
344
+
345
+ def build_thread_goals(case: CaseStudy) -> list[ThreadGoal]:
346
+ """Convert case study thread_goals dicts into ThreadGoal objects.
347
+
348
+ Parameters
349
+ ----------
350
+ case : CaseStudy
351
+ The case study whose thread goals to build.
352
+
353
+ Returns
354
+ -------
355
+ list[ThreadGoal]
356
+ Ordered list of ThreadGoal objects with sequential IDs.
357
+ """
358
+ goals = []
359
+ for i, g in enumerate(case.thread_goals, start=1):
360
+ goals.append(
361
+ ThreadGoal(
362
+ thread_id=i,
363
+ angle=g["angle"],
364
+ goal=g["goal"],
365
+ suggested_tools=g.get("suggested_tools", []),
366
+ )
367
+ )
368
+ return goals
369
+
370
+
371
+ def run_case_study(
372
+ session,
373
+ case_id: str,
374
+ n_threads: int = None,
375
+ ) -> OrchestratorResult:
376
+ """Run a curated case study through the multi-agent orchestrator.
377
+
378
+ Parameters
379
+ ----------
380
+ session : Session
381
+ Active ct session.
382
+ case_id : str
383
+ Case study slug (e.g. "revlimid", "gleevec").
384
+ n_threads : int, optional
385
+ Number of threads. Defaults to the number of thread goals defined
386
+ in the case study.
387
+
388
+ Returns
389
+ -------
390
+ OrchestratorResult
391
+ Merged results from all research threads.
392
+
393
+ Raises
394
+ ------
395
+ ValueError
396
+ If *case_id* is not found in the registry.
397
+ """
398
+ if case_id not in CASE_STUDIES:
399
+ available = ", ".join(sorted(CASE_STUDIES.keys()))
400
+ raise ValueError(
401
+ f"Unknown case study '{case_id}'. Available: {available}"
402
+ )
403
+
404
+ case = CASE_STUDIES[case_id]
405
+ goals = build_thread_goals(case)
406
+
407
+ if n_threads is None:
408
+ n_threads = len(goals)
409
+
410
+ # Build query from case study metadata
411
+ query = (
412
+ f"Comprehensive analysis of {case.name}: {case.description} "
413
+ f"Compound: {case.compound}. "
414
+ f"Primary targets: {', '.join(case.targets)}. "
415
+ f"Indication: {case.indication}."
416
+ )
417
+
418
+ context = {
419
+ "compound": case.compound,
420
+ "targets": ", ".join(case.targets),
421
+ "indication": case.indication,
422
+ "case_study": case.id,
423
+ }
424
+
425
+ orchestrator = ResearchOrchestrator(session, n_threads=n_threads)
426
+ return orchestrator.run(query, context, preset_goals=goals)