m3triq 0.1.0 → 0.2.1

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.
@@ -0,0 +1,122 @@
1
+ import { output, formatTable } from '../output.js';
2
+ import { createAgentsClient } from '../cli.js';
3
+ import { requireApiKey } from '../config.js';
4
+ export function registerZincCommands(program) {
5
+ const zinc = program
6
+ .command('zinc')
7
+ .description('Query ZINC purchasable compounds (self-hosted, 14M drug-like)')
8
+ .hook('preAction', () => { requireApiKey(); });
9
+ // ── m3t zinc search ───────────────���───────────────────────────
10
+ zinc
11
+ .command('search')
12
+ .option('--mw-min <n>', 'Min molecular weight')
13
+ .option('--mw-max <n>', 'Max molecular weight')
14
+ .option('--logp-min <n>', 'Min LogP')
15
+ .option('--logp-max <n>', 'Max LogP')
16
+ .option('--subset <s>', 'Subset: drug-like, lead-like, fragment-like, fda, in-stock')
17
+ .option('--limit <n>', 'Max results', '20')
18
+ .description('Search purchasable compounds by properties')
19
+ .action(async (opts) => {
20
+ const agents = createAgentsClient();
21
+ const params = {
22
+ limit: parseInt(opts.limit),
23
+ };
24
+ if (opts.mwMin)
25
+ params.mw_min = parseFloat(opts.mwMin);
26
+ if (opts.mwMax)
27
+ params.mw_max = parseFloat(opts.mwMax);
28
+ if (opts.logpMin)
29
+ params.logp_min = parseFloat(opts.logpMin);
30
+ if (opts.logpMax)
31
+ params.logp_max = parseFloat(opts.logpMax);
32
+ if (opts.subset)
33
+ params.subset = opts.subset;
34
+ const data = await agents.callMcpTool('zinc', 'search_purchasable', params);
35
+ if (typeof data.result === 'string') {
36
+ output(data, data.result);
37
+ return;
38
+ }
39
+ const compounds = extractArray(data, ['compounds', 'results', 'data']);
40
+ if (compounds.length === 0) {
41
+ output([], 'No compounds found.');
42
+ return;
43
+ }
44
+ const rows = compounds.map(c => [
45
+ str(c.zinc_id),
46
+ str(c.smiles || c.canonical_smiles, 45),
47
+ str(c.mw || c.molecular_weight),
48
+ str(c.logp),
49
+ str(c.subset || c.sub_set),
50
+ ]);
51
+ output(compounds, formatTable(['ZINC ID', 'SMILES', 'MW', 'LogP', 'Subset'], rows));
52
+ });
53
+ // ── m3t zinc info <zinc_id> ───────────────────────────────────
54
+ zinc
55
+ .command('info')
56
+ .argument('<id>', 'ZINC compound ID (e.g., ZINC000000000001)')
57
+ .description('Get details for a ZINC compound')
58
+ .action(async (id) => {
59
+ const agents = createAgentsClient();
60
+ const data = await agents.callMcpTool('zinc', 'get_compound', { zinc_id: id });
61
+ if (typeof data.result === 'string') {
62
+ output(data, data.result);
63
+ }
64
+ else {
65
+ output(data, JSON.stringify(data, null, 2));
66
+ }
67
+ });
68
+ // ── m3t zinc random ───────��──────────────────────────────���────
69
+ zinc
70
+ .command('random')
71
+ .option('--count <n>', 'Number of compounds', '20')
72
+ .option('--subset <s>', 'Subset: drug-like, lead-like, fragment-like')
73
+ .description('Get random purchasable compounds')
74
+ .action(async (opts) => {
75
+ const agents = createAgentsClient();
76
+ const params = {
77
+ count: parseInt(opts.count),
78
+ };
79
+ if (opts.subset)
80
+ params.subset = opts.subset;
81
+ const data = await agents.callMcpTool('zinc', 'get_random_compounds', params);
82
+ if (typeof data.result === 'string') {
83
+ output(data, data.result);
84
+ return;
85
+ }
86
+ const compounds = extractArray(data, ['compounds', 'results', 'data']);
87
+ if (compounds.length === 0) {
88
+ output([], 'No compounds found.');
89
+ return;
90
+ }
91
+ const rows = compounds.map(c => [
92
+ str(c.zinc_id),
93
+ str(c.smiles || c.canonical_smiles, 45),
94
+ str(c.mw || c.molecular_weight),
95
+ str(c.logp),
96
+ ]);
97
+ output(compounds, formatTable(['ZINC ID', 'SMILES', 'MW', 'LogP'], rows));
98
+ });
99
+ }
100
+ // ── Helpers ────���──────────────────────��───────────────────────────
101
+ function str(val, maxLen) {
102
+ const s = val != null ? String(val) : '-';
103
+ return maxLen ? s.substring(0, maxLen) : s;
104
+ }
105
+ function extractArray(data, keys) {
106
+ if (Array.isArray(data))
107
+ return data;
108
+ for (const key of keys) {
109
+ if (Array.isArray(data[key]))
110
+ return data[key];
111
+ }
112
+ if (typeof data.result === 'string') {
113
+ try {
114
+ return extractArray(JSON.parse(data.result), keys);
115
+ }
116
+ catch { /* not JSON */ }
117
+ }
118
+ if (typeof data.result === 'object' && data.result !== null) {
119
+ return extractArray(data.result, keys);
120
+ }
121
+ return [];
122
+ }
package/dist/types.d.ts CHANGED
@@ -3,6 +3,40 @@ export interface Project {
3
3
  name: string;
4
4
  description: string;
5
5
  created_at: string;
6
+ updated_at?: string;
7
+ last_activity_at?: string;
8
+ context?: string;
9
+ session_count?: number;
10
+ user_role?: string;
11
+ owner_email?: string;
12
+ owner_name?: string;
13
+ member_count?: number;
14
+ is_shared?: boolean;
15
+ }
16
+ export interface ChatSession {
17
+ id: string;
18
+ title: string;
19
+ created_at: string;
20
+ updated_at: string;
21
+ message_count?: number;
22
+ has_notes?: boolean;
23
+ context_notes?: string;
24
+ project?: string;
25
+ project_name?: string;
26
+ user_name?: string;
27
+ selected_tab?: number;
28
+ model?: string;
29
+ messages?: ChatMessage[];
30
+ }
31
+ export interface ChatMessage {
32
+ id: number;
33
+ role: 'user' | 'assistant';
34
+ content: string;
35
+ order: number;
36
+ created_at: string;
37
+ elapsed_time?: number | null;
38
+ total_tokens?: number | null;
39
+ thinking_steps?: unknown[];
6
40
  }
7
41
  export interface Job {
8
42
  id: string;
@@ -55,6 +89,46 @@ export interface DiffDockParams {
55
89
  protein_pdb: string;
56
90
  num_samples?: number;
57
91
  }
92
+ export type Boltz2MoleculeType = 'protein' | 'dna' | 'rna';
93
+ export interface Boltz2Polymer {
94
+ molecule_type: Boltz2MoleculeType;
95
+ sequence: string;
96
+ id?: string;
97
+ }
98
+ export interface Boltz2Ligand {
99
+ smiles?: string;
100
+ ccd_code?: string;
101
+ }
102
+ export interface Boltz2McpParams {
103
+ polymers: Boltz2Polymer[];
104
+ ligands?: Boltz2Ligand[];
105
+ recycling_steps?: number;
106
+ sampling_steps?: number;
107
+ diffusion_samples?: number;
108
+ step_scale?: number;
109
+ }
110
+ export interface Boltz2McpResult {
111
+ success?: boolean;
112
+ model?: string;
113
+ complex?: string;
114
+ output_format?: string;
115
+ diffusion_samples?: number;
116
+ num_structures_returned?: number;
117
+ structure_data?: string;
118
+ confidence_scores?: number[];
119
+ best_confidence?: number | null;
120
+ affinities?: Record<string, unknown> | null;
121
+ metrics?: Record<string, unknown> | null;
122
+ quality?: string;
123
+ message?: string;
124
+ error?: string;
125
+ }
126
+ export interface Boltz2JobParams {
127
+ project_id: string;
128
+ title: string;
129
+ result_data: Record<string, unknown>;
130
+ description?: string;
131
+ }
58
132
  export interface SandboxParams {
59
133
  project_id: string;
60
134
  script: string;
@@ -69,3 +143,48 @@ export interface McpCallResult {
69
143
  result?: unknown;
70
144
  [key: string]: unknown;
71
145
  }
146
+ export interface CreditUsageLogEntry {
147
+ event: string;
148
+ credits: number;
149
+ job_id?: string | null;
150
+ note?: string;
151
+ metadata?: Record<string, unknown>;
152
+ created_at: string;
153
+ }
154
+ export interface CreditQuota {
155
+ tier: string;
156
+ monthly_credits: number;
157
+ credits_used: number;
158
+ topup_credits: number;
159
+ credits_remaining: number;
160
+ usage_percentage: number;
161
+ period_start?: string;
162
+ period_end?: string;
163
+ is_quota_exceeded: boolean;
164
+ last_used?: string | null;
165
+ recent_events?: CreditUsageLogEntry[];
166
+ }
167
+ export interface CreditLogResponse {
168
+ count: number;
169
+ next: string | null;
170
+ previous: string | null;
171
+ results: CreditUsageLogEntry[];
172
+ }
173
+ export interface PricingItem {
174
+ label: string;
175
+ unit: string;
176
+ credits: number;
177
+ note?: string;
178
+ }
179
+ export interface PricingCatalog {
180
+ credit_usd: number;
181
+ note: string;
182
+ jobs: PricingItem[];
183
+ md_simulation: PricingItem[];
184
+ sandbox: PricingItem;
185
+ ai: {
186
+ label: string;
187
+ unit: string;
188
+ range: string;
189
+ };
190
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "m3triq",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "M3TRIQ — protein-ligand analysis from the terminal",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,8 +10,11 @@
10
10
  "keywords": ["bioinformatics", "chembl", "docking", "protein", "ligand", "drug-discovery", "cli"],
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "https://github.com/khai-m3triq/m3t_mono.git",
14
- "directory": "m3triq_cli"
13
+ "url": "https://github.com/M3TRIQ/m3t.git"
14
+ },
15
+ "homepage": "https://github.com/M3TRIQ/m3t#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/M3TRIQ/m3t/issues"
15
18
  },
16
19
  "scripts": {
17
20
  "build": "tsc",