Uanderson Silva commited on
Commit
32a4f79
·
1 Parent(s): 098ab50

integrate with coder agent

Browse files
README_GH.md CHANGED
@@ -19,6 +19,8 @@ O sistema é implementado em **TypeScript** e **Node.js**, utilizando a bibliote
19
 
20
  O sistema é composto por agentes especializados que colaboram entre si em diferentes etapas do processo:
21
 
 
 
22
  1. **Exploração e análise dos requisitos**
23
 
24
  * Processamento e compreensão dos documentos fornecidos;
 
19
 
20
  O sistema é composto por agentes especializados que colaboram entre si em diferentes etapas do processo:
21
 
22
+ ![Arquitetura Geral](./assets/architecture.png)
23
+
24
  1. **Exploração e análise dos requisitos**
25
 
26
  * Processamento e compreensão dos documentos fornecidos;
frontend/src/App.tsx CHANGED
@@ -1,10 +1,25 @@
1
  import { useState, useRef, useCallback } from "react";
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  interface AgentResult {
4
  contract?: string;
5
  compilationErrors?: string[];
6
  reviewSummary?: string;
7
- vulnerabilities?: Array<{ type: string; severity: string; description: string }>;
8
  results?: unknown[];
9
  }
10
 
@@ -58,8 +73,10 @@ export function App() {
58
  for (const line of lines) {
59
  if (line.startsWith("event:")) {
60
  currentEvent = line.slice(6).trim();
 
61
  } else if (line.startsWith("data:")) {
62
  const data = line.slice(5).trim();
 
63
  switch (currentEvent) {
64
  case "log":
65
  appendLog(data);
@@ -90,12 +107,10 @@ export function App() {
90
  return (
91
  <div style={styles.container}>
92
  <header style={styles.header}>
93
- <h1 style={styles.title}>
94
- Multi-Agent: Geração, Auditoria e Teste de Smart Contracts
95
- </h1>
96
  <p style={styles.subtitle}>
97
- Descreva um cenário ou requisito cuja solução seja um smart contract em Solidity.
98
- O sistema irá gerar, compilar, auditar e testar o contrato automaticamente.
99
  </p>
100
  </header>
101
 
@@ -103,15 +118,21 @@ export function App() {
103
  <textarea
104
  value={requirements}
105
  onChange={(e) => setRequirements(e.target.value)}
106
- placeholder={"Ex: Crie um token ERC20 com as seguintes características:\n- Nome: MeuToken, Símbolo: MTK\n- Supply inicial de 1.000.000 tokens\n- Funções de mint (apenas owner) e burn\n- Pausável pelo owner"}
 
 
107
  style={styles.textarea}
108
  rows={6}
109
  disabled={running}
110
  />
111
- <button type="submit" disabled={running || !requirements.trim()} style={{
112
- ...styles.button,
113
- opacity: running || !requirements.trim() ? 0.5 : 1,
114
- }}>
 
 
 
 
115
  {running ? "Executando pipeline..." : "Executar Pipeline"}
116
  </button>
117
  </form>
@@ -122,7 +143,9 @@ export function App() {
122
  <h2 style={styles.sectionTitle}>📋 Log de Execução</h2>
123
  <div style={styles.logBox}>
124
  {logs.map((log, i) => (
125
- <div key={i} style={styles.logLine}>{log}</div>
 
 
126
  ))}
127
  <div ref={logsEndRef} />
128
  </div>
@@ -163,9 +186,33 @@ export function App() {
163
  {auditorResult && (
164
  <section style={styles.section}>
165
  <h2 style={styles.sectionTitle}>🔍 Agente Auditor</h2>
166
- <div style={styles.codeBox}>
167
- <pre style={styles.code}>{JSON.stringify(auditorResult.vulnerabilities, null, 2)}</pre>
168
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  </section>
170
  )}
171
 
@@ -186,6 +233,19 @@ export function App() {
186
  );
187
  }
188
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  const styles: Record<string, React.CSSProperties> = {
190
  container: {
191
  maxWidth: 900,
@@ -305,4 +365,36 @@ const styles: Record<string, React.CSSProperties> = {
305
  color: "#cbd5e1",
306
  whiteSpace: "pre-wrap",
307
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  };
 
1
  import { useState, useRef, useCallback } from "react";
2
 
3
+ interface Finding {
4
+ title: string;
5
+ description: string;
6
+ recommendation: string;
7
+ severity: "high" | "medium" | "low";
8
+ codeSnippet: string;
9
+ location: string;
10
+ path: string;
11
+ judgeReview: {
12
+ review: string;
13
+ confidence: number;
14
+ exploitablePaths: string[];
15
+ };
16
+ }
17
+
18
  interface AgentResult {
19
  contract?: string;
20
  compilationErrors?: string[];
21
  reviewSummary?: string;
22
+ findings?: Finding[];
23
  results?: unknown[];
24
  }
25
 
 
73
  for (const line of lines) {
74
  if (line.startsWith("event:")) {
75
  currentEvent = line.slice(6).trim();
76
+ console.log("event", currentEvent);
77
  } else if (line.startsWith("data:")) {
78
  const data = line.slice(5).trim();
79
+ console.log("data", data);
80
  switch (currentEvent) {
81
  case "log":
82
  appendLog(data);
 
107
  return (
108
  <div style={styles.container}>
109
  <header style={styles.header}>
110
+ <h1 style={styles.title}>Multi-Agent: Geração, Auditoria e Teste de Smart Contracts</h1>
 
 
111
  <p style={styles.subtitle}>
112
+ Descreva um cenário ou requisito cuja solução seja um smart contract em Solidity. O sistema irá gerar,
113
+ compilar, auditar e testar o contrato automaticamente.
114
  </p>
115
  </header>
116
 
 
118
  <textarea
119
  value={requirements}
120
  onChange={(e) => setRequirements(e.target.value)}
121
+ placeholder={
122
+ "Ex: Crie um token ERC20 com as seguintes características:\n- Nome: MeuToken, Símbolo: MTK\n- Supply inicial de 1.000.000 tokens\n- Funções de mint (apenas owner) e burn\n- Pausável pelo owner"
123
+ }
124
  style={styles.textarea}
125
  rows={6}
126
  disabled={running}
127
  />
128
+ <button
129
+ type="submit"
130
+ disabled={running || !requirements.trim()}
131
+ style={{
132
+ ...styles.button,
133
+ opacity: running || !requirements.trim() ? 0.5 : 1,
134
+ }}
135
+ >
136
  {running ? "Executando pipeline..." : "Executar Pipeline"}
137
  </button>
138
  </form>
 
143
  <h2 style={styles.sectionTitle}>📋 Log de Execução</h2>
144
  <div style={styles.logBox}>
145
  {logs.map((log, i) => (
146
+ <div key={i} style={styles.logLine}>
147
+ {log}
148
+ </div>
149
  ))}
150
  <div ref={logsEndRef} />
151
  </div>
 
186
  {auditorResult && (
187
  <section style={styles.section}>
188
  <h2 style={styles.sectionTitle}>🔍 Agente Auditor</h2>
189
+ {auditorResult.findings && auditorResult.findings.length > 0 ? (
190
+ auditorResult.findings.map((f, i) => (
191
+ <div key={i} style={{ ...styles.findingCard, borderColor: severityColor(f.severity) }}>
192
+ <div style={styles.findingHeader}>
193
+ <span style={{ ...styles.severityBadge, background: severityColor(f.severity) }}>
194
+ {f.severity.toUpperCase()}
195
+ </span>
196
+ <span style={styles.findingTitle}>{f.title}</span>
197
+ </div>
198
+ <p style={styles.findingText}>{f.description}</p>
199
+ <p style={{ ...styles.findingText, color: "#94a3b8" }}>
200
+ <strong>Localização:</strong> {f.location ?? "-"}
201
+ </p>
202
+ {f.codeSnippet && <pre style={styles.code}>{f.codeSnippet}</pre>}
203
+ <p style={{ ...styles.findingText, color: "#94a3b8" }}>
204
+ <strong>Recomendação:</strong> {f.recommendation}
205
+ </p>
206
+ <p style={{ ...styles.findingText, color: "#64748b", fontSize: 12 }}>
207
+ Confiança: {Math.round(f.judgeReview.confidence)}% — {f.judgeReview.review}
208
+ </p>
209
+ </div>
210
+ ))
211
+ ) : (
212
+ <div style={styles.resultBox}>
213
+ <p style={styles.resultText}>Nenhuma vulnerabilidade encontrada.</p>
214
+ </div>
215
+ )}
216
  </section>
217
  )}
218
 
 
233
  );
234
  }
235
 
236
+ const severityColor = (severity: string) => {
237
+ switch (severity) {
238
+ case "high":
239
+ return "#ef4444";
240
+ case "medium":
241
+ return "#f97316";
242
+ case "low":
243
+ return "#eab308";
244
+ default:
245
+ return "#64748b";
246
+ }
247
+ };
248
+
249
  const styles: Record<string, React.CSSProperties> = {
250
  container: {
251
  maxWidth: 900,
 
365
  color: "#cbd5e1",
366
  whiteSpace: "pre-wrap",
367
  },
368
+ findingCard: {
369
+ background: "#1e293b",
370
+ border: "1px solid",
371
+ borderRadius: 8,
372
+ padding: 16,
373
+ marginBottom: 12,
374
+ },
375
+ findingHeader: {
376
+ display: "flex",
377
+ alignItems: "center",
378
+ gap: 10,
379
+ marginBottom: 8,
380
+ },
381
+ severityBadge: {
382
+ fontSize: 11,
383
+ fontWeight: 700,
384
+ color: "#fff",
385
+ padding: "2px 8px",
386
+ borderRadius: 4,
387
+ letterSpacing: "0.05em",
388
+ },
389
+ findingTitle: {
390
+ fontSize: 15,
391
+ fontWeight: 600,
392
+ color: "#f8fafc",
393
+ },
394
+ findingText: {
395
+ margin: "4px 0",
396
+ fontSize: 13,
397
+ lineHeight: 1.6,
398
+ color: "#cbd5e1",
399
+ },
400
  };
package-lock.json CHANGED
@@ -330,9 +330,9 @@
330
  }
331
  },
332
  "node_modules/@langchain/core": {
333
- "version": "1.1.47",
334
- "resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.1.47.tgz",
335
- "integrity": "sha512-+fiPu6ZFnJMrZyKeM77OIVPoMPAY6OKWacnPlojHtXTbMMzb2cEOKAJV0U07cDl86NHSCIYYa0i4CyKZzXbHQQ==",
336
  "license": "MIT",
337
  "dependencies": {
338
  "@cfworker/json-schema": "^4.0.2",
@@ -363,13 +363,13 @@
363
  }
364
  },
365
  "node_modules/@langchain/langgraph": {
366
- "version": "1.3.0",
367
- "resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-1.3.0.tgz",
368
- "integrity": "sha512-QvhTjiyqFPz81A+y6LHs223w6DTjv5+882DT4mup72bd72rRhNjTYo5fhes5um0swnKArvY/arc7KeFInfHHWw==",
369
  "license": "MIT",
370
  "dependencies": {
371
  "@langchain/langgraph-checkpoint": "^1.0.2",
372
- "@langchain/langgraph-sdk": "~1.9.0",
373
  "@langchain/protocol": "^0.0.15",
374
  "@standard-schema/spec": "1.1.0",
375
  "uuid": "^10.0.0"
@@ -418,12 +418,11 @@
418
  }
419
  },
420
  "node_modules/@langchain/langgraph-sdk": {
421
- "version": "1.9.1",
422
- "resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-1.9.1.tgz",
423
- "integrity": "sha512-pHojybde9HoMz7ZDtyW3pgDdomAN4C0pbdgXASjccFS+S2Cqx75iZBtBUUg1A/CSer5xh9GakdIqyihxZOf7VA==",
424
  "license": "MIT",
425
  "dependencies": {
426
- "@langchain/core": "^1.1.44",
427
  "@langchain/protocol": "^0.0.15",
428
  "@types/json-schema": "^7.0.15",
429
  "p-queue": "^9.0.1",
@@ -431,6 +430,7 @@
431
  "uuid": "^13.0.0"
432
  },
433
  "peerDependencies": {
 
434
  "react": "^18 || ^19",
435
  "react-dom": "^18 || ^19",
436
  "svelte": "^4.0.0 || ^5.0.0",
@@ -458,9 +458,9 @@
458
  "license": "MIT"
459
  },
460
  "node_modules/@langchain/langgraph-sdk/node_modules/p-queue": {
461
- "version": "9.2.0",
462
- "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.2.0.tgz",
463
- "integrity": "sha512-dWgLE8AH0HjQ9fe74pUkKkvzzYT18Inp4zra3lKHnnwqGvcfcUBrvF2EAVX+envufDNBOzpPq/IBUONDbI7+3g==",
464
  "license": "MIT",
465
  "dependencies": {
466
  "eventemitter3": "^5.0.4",
@@ -1061,6 +1061,26 @@
1061
  "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1062
  }
1063
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1064
  "node_modules/assertion-error": {
1065
  "version": "2.0.1",
1066
  "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
@@ -1203,41 +1223,6 @@
1203
  "node": ">=8"
1204
  }
1205
  },
1206
- "node_modules/color-convert": {
1207
- "version": "2.0.1",
1208
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1209
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1210
- "dev": true,
1211
- "license": "MIT",
1212
- "dependencies": {
1213
- "color-name": "~1.1.4"
1214
- },
1215
- "engines": {
1216
- "node": ">=7.0.0"
1217
- }
1218
- },
1219
- "node_modules/color-name": {
1220
- "version": "1.1.4",
1221
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1222
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1223
- "dev": true,
1224
- "license": "MIT"
1225
- },
1226
- "node_modules/command-exists": {
1227
- "version": "1.2.9",
1228
- "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
1229
- "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
1230
- "license": "MIT"
1231
- },
1232
- "node_modules/commander": {
1233
- "version": "8.3.0",
1234
- "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
1235
- "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
1236
- "license": "MIT",
1237
- "engines": {
1238
- "node": ">= 12"
1239
- }
1240
- },
1241
  "node_modules/color": {
1242
  "version": "5.0.3",
1243
  "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz",
@@ -1284,6 +1269,21 @@
1284
  "node": ">=18"
1285
  }
1286
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1287
  "node_modules/convert-source-map": {
1288
  "version": "2.0.0",
1289
  "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -1361,6 +1361,12 @@
1361
  "node": ">= 0.4"
1362
  }
1363
  },
 
 
 
 
 
 
1364
  "node_modules/es-define-property": {
1365
  "version": "1.0.1",
1366
  "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -1381,12 +1387,6 @@
1381
  "node": ">= 0.4"
1382
  }
1383
  },
1384
- "node_modules/enabled": {
1385
- "version": "2.0.0",
1386
- "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
1387
- "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==",
1388
- "license": "MIT"
1389
- },
1390
  "node_modules/es-module-lexer": {
1391
  "version": "2.1.0",
1392
  "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
@@ -1460,6 +1460,12 @@
1460
  }
1461
  }
1462
  },
 
 
 
 
 
 
1463
  "node_modules/fill-range": {
1464
  "version": "7.1.1",
1465
  "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -1483,6 +1489,12 @@
1483
  "micromatch": "^4.0.2"
1484
  }
1485
  },
 
 
 
 
 
 
1486
  "node_modules/follow-redirects": {
1487
  "version": "1.16.0",
1488
  "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
@@ -1518,18 +1530,6 @@
1518
  "node": ">=12"
1519
  }
1520
  },
1521
- "node_modules/fecha": {
1522
- "version": "4.2.3",
1523
- "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
1524
- "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
1525
- "license": "MIT"
1526
- },
1527
- "node_modules/fn.name": {
1528
- "version": "1.1.0",
1529
- "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
1530
- "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
1531
- "license": "MIT"
1532
- },
1533
  "node_modules/fsevents": {
1534
  "version": "2.3.3",
1535
  "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -1672,6 +1672,12 @@
1672
  "node": ">=16.9.0"
1673
  }
1674
  },
 
 
 
 
 
 
1675
  "node_modules/is-docker": {
1676
  "version": "2.2.1",
1677
  "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
@@ -1688,16 +1694,10 @@
1688
  "url": "https://github.com/sponsors/sindresorhus"
1689
  }
1690
  },
1691
- "node_modules/inherits": {
1692
- "version": "2.0.4",
1693
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1694
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1695
- "license": "ISC"
1696
- },
1697
  "node_modules/is-network-error": {
1698
- "version": "1.3.1",
1699
- "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.1.tgz",
1700
- "integrity": "sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==",
1701
  "license": "MIT",
1702
  "engines": {
1703
  "node": ">=16"
@@ -1716,6 +1716,18 @@
1716
  "node": ">=0.12.0"
1717
  }
1718
  },
 
 
 
 
 
 
 
 
 
 
 
 
1719
  "node_modules/is-wsl": {
1720
  "version": "2.2.0",
1721
  "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
@@ -1749,18 +1761,6 @@
1749
  "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
1750
  "license": "MIT"
1751
  },
1752
- "node_modules/is-stream": {
1753
- "version": "2.0.1",
1754
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
1755
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
1756
- "license": "MIT",
1757
- "engines": {
1758
- "node": ">=8"
1759
- },
1760
- "funding": {
1761
- "url": "https://github.com/sponsors/sindresorhus"
1762
- }
1763
- },
1764
  "node_modules/js-tiktoken": {
1765
  "version": "1.0.21",
1766
  "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.21.tgz",
@@ -1770,6 +1770,19 @@
1770
  "base64-js": "^1.5.1"
1771
  }
1772
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
1773
  "node_modules/json-stable-stringify": {
1774
  "version": "1.3.0",
1775
  "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
@@ -1823,19 +1836,6 @@
1823
  "graceful-fs": "^4.1.11"
1824
  }
1825
  },
1826
- "node_modules/json-schema-to-ts": {
1827
- "version": "3.1.1",
1828
- "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz",
1829
- "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==",
1830
- "license": "MIT",
1831
- "dependencies": {
1832
- "@babel/runtime": "^7.18.3",
1833
- "ts-algebra": "^2.0.0"
1834
- },
1835
- "engines": {
1836
- "node": ">=16"
1837
- }
1838
- },
1839
  "node_modules/kuler": {
1840
  "version": "2.0.0",
1841
  "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
@@ -1843,12 +1843,12 @@
1843
  "license": "MIT"
1844
  },
1845
  "node_modules/langchain": {
1846
- "version": "1.4.0",
1847
- "resolved": "https://registry.npmjs.org/langchain/-/langchain-1.4.0.tgz",
1848
- "integrity": "sha512-p3H5U1vfO0T4ri/xxqI6jccRP3LYmOW6KGxaJcwI5mIGVR/G6eNhZyjSZB9d7me6J7an4Pc6zA8tH8Qa6/7xwA==",
1849
  "license": "MIT",
1850
  "dependencies": {
1851
- "@langchain/langgraph": "^1.3.0",
1852
  "@langchain/langgraph-checkpoint": "^1.0.1",
1853
  "langsmith": ">=0.5.0 <1.0.0",
1854
  "zod": "^3.25.76 || ^4"
@@ -1857,7 +1857,7 @@
1857
  "node": ">=20"
1858
  },
1859
  "peerDependencies": {
1860
- "@langchain/core": "^1.1.44"
1861
  }
1862
  },
1863
  "node_modules/langsmith": {
@@ -2291,6 +2291,15 @@
2291
  ],
2292
  "license": "MIT"
2293
  },
 
 
 
 
 
 
 
 
 
2294
  "node_modules/open": {
2295
  "version": "7.4.2",
2296
  "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
@@ -2308,15 +2317,6 @@
2308
  "url": "https://github.com/sponsors/sindresorhus"
2309
  }
2310
  },
2311
- "node_modules/one-time": {
2312
- "version": "1.0.0",
2313
- "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
2314
- "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
2315
- "license": "MIT",
2316
- "dependencies": {
2317
- "fn.name": "1.x.x"
2318
- }
2319
- },
2320
  "node_modules/openai": {
2321
  "version": "6.36.0",
2322
  "resolved": "https://registry.npmjs.org/openai/-/openai-6.36.0.tgz",
@@ -2566,6 +2566,35 @@
2566
  "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.18"
2567
  }
2568
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2569
  "node_modules/semver": {
2570
  "version": "5.7.2",
2571
  "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
@@ -2616,35 +2645,6 @@
2616
  "node": ">=8"
2617
  }
2618
  },
2619
- "node_modules/safe-buffer": {
2620
- "version": "5.2.1",
2621
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
2622
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
2623
- "funding": [
2624
- {
2625
- "type": "github",
2626
- "url": "https://github.com/sponsors/feross"
2627
- },
2628
- {
2629
- "type": "patreon",
2630
- "url": "https://www.patreon.com/feross"
2631
- },
2632
- {
2633
- "type": "consulting",
2634
- "url": "https://feross.org/support"
2635
- }
2636
- ],
2637
- "license": "MIT"
2638
- },
2639
- "node_modules/safe-stable-stringify": {
2640
- "version": "2.5.0",
2641
- "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
2642
- "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
2643
- "license": "MIT",
2644
- "engines": {
2645
- "node": ">=10"
2646
- }
2647
- },
2648
  "node_modules/siginfo": {
2649
  "version": "2.0.0",
2650
  "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
@@ -2716,6 +2716,15 @@
2716
  "dev": true,
2717
  "license": "MIT"
2718
  },
 
 
 
 
 
 
 
 
 
2719
  "node_modules/supports-color": {
2720
  "version": "7.2.0",
2721
  "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -2729,15 +2738,6 @@
2729
  "node": ">=8"
2730
  }
2731
  },
2732
- "node_modules/string_decoder": {
2733
- "version": "1.3.0",
2734
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
2735
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
2736
- "license": "MIT",
2737
- "dependencies": {
2738
- "safe-buffer": "~5.2.0"
2739
- }
2740
- },
2741
  "node_modules/text-hex": {
2742
  "version": "1.0.0",
2743
  "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
@@ -3087,22 +3087,6 @@
3087
  "node": ">=8"
3088
  }
3089
  },
3090
- "node_modules/yaml": {
3091
- "version": "2.9.0",
3092
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
3093
- "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
3094
- "dev": true,
3095
- "license": "ISC",
3096
- "bin": {
3097
- "yaml": "bin.mjs"
3098
- },
3099
- "engines": {
3100
- "node": ">= 14.6"
3101
- },
3102
- "funding": {
3103
- "url": "https://github.com/sponsors/eemeli"
3104
- }
3105
- },
3106
  "node_modules/winston": {
3107
  "version": "3.19.0",
3108
  "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz",
@@ -3139,6 +3123,22 @@
3139
  "node": ">= 12.0.0"
3140
  }
3141
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3142
  "node_modules/zod": {
3143
  "version": "4.4.3",
3144
  "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
 
330
  }
331
  },
332
  "node_modules/@langchain/core": {
333
+ "version": "1.1.48",
334
+ "resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.1.48.tgz",
335
+ "integrity": "sha512-fQU6Guyb1pwc2fEplmA8FPbKfOMAofjnyJzExevro0FxEiuGHE18Ov/ZHmT9trWCDTZRI9eW1VIc6aChxV8pAQ==",
336
  "license": "MIT",
337
  "dependencies": {
338
  "@cfworker/json-schema": "^4.0.2",
 
363
  }
364
  },
365
  "node_modules/@langchain/langgraph": {
366
+ "version": "1.3.2",
367
+ "resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-1.3.2.tgz",
368
+ "integrity": "sha512-SL7Ktsr681R7da+1b2MVOWEbaCoFJOXEJPTGOjg4JIG4C7quWbTYC8DzxhcCxte6D/8cGp0rYDBnbKLXEpNqlA==",
369
  "license": "MIT",
370
  "dependencies": {
371
  "@langchain/langgraph-checkpoint": "^1.0.2",
372
+ "@langchain/langgraph-sdk": "~1.9.4",
373
  "@langchain/protocol": "^0.0.15",
374
  "@standard-schema/spec": "1.1.0",
375
  "uuid": "^10.0.0"
 
418
  }
419
  },
420
  "node_modules/@langchain/langgraph-sdk": {
421
+ "version": "1.9.6",
422
+ "resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-1.9.6.tgz",
423
+ "integrity": "sha512-cem5LckknNULd8o4WiOpf+rv+Qxvfpf5MzXiCQb9JnEfJdCRrWsl0/qBeZRpAXMf/1Va3uDMZouTmw9odmI0Hw==",
424
  "license": "MIT",
425
  "dependencies": {
 
426
  "@langchain/protocol": "^0.0.15",
427
  "@types/json-schema": "^7.0.15",
428
  "p-queue": "^9.0.1",
 
430
  "uuid": "^13.0.0"
431
  },
432
  "peerDependencies": {
433
+ "@langchain/core": "^1.1.44",
434
  "react": "^18 || ^19",
435
  "react-dom": "^18 || ^19",
436
  "svelte": "^4.0.0 || ^5.0.0",
 
458
  "license": "MIT"
459
  },
460
  "node_modules/@langchain/langgraph-sdk/node_modules/p-queue": {
461
+ "version": "9.3.0",
462
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.0.tgz",
463
+ "integrity": "sha512-7NED7xhQ74Ngp4JP/2e0VZHp7vSWfJfqeiR92jPgxsz6m0Se4P03YoTKa9dDXyZ3r6P616gUXttrB6nnHYKang==",
464
  "license": "MIT",
465
  "dependencies": {
466
  "eventemitter3": "^5.0.4",
 
1061
  "url": "https://github.com/chalk/ansi-styles?sponsor=1"
1062
  }
1063
  },
1064
+ "node_modules/ansi-styles/node_modules/color-convert": {
1065
+ "version": "2.0.1",
1066
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1067
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1068
+ "dev": true,
1069
+ "license": "MIT",
1070
+ "dependencies": {
1071
+ "color-name": "~1.1.4"
1072
+ },
1073
+ "engines": {
1074
+ "node": ">=7.0.0"
1075
+ }
1076
+ },
1077
+ "node_modules/ansi-styles/node_modules/color-name": {
1078
+ "version": "1.1.4",
1079
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1080
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1081
+ "dev": true,
1082
+ "license": "MIT"
1083
+ },
1084
  "node_modules/assertion-error": {
1085
  "version": "2.0.1",
1086
  "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
 
1223
  "node": ">=8"
1224
  }
1225
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1226
  "node_modules/color": {
1227
  "version": "5.0.3",
1228
  "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz",
 
1269
  "node": ">=18"
1270
  }
1271
  },
1272
+ "node_modules/command-exists": {
1273
+ "version": "1.2.9",
1274
+ "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
1275
+ "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==",
1276
+ "license": "MIT"
1277
+ },
1278
+ "node_modules/commander": {
1279
+ "version": "8.3.0",
1280
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
1281
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
1282
+ "license": "MIT",
1283
+ "engines": {
1284
+ "node": ">= 12"
1285
+ }
1286
+ },
1287
  "node_modules/convert-source-map": {
1288
  "version": "2.0.0",
1289
  "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
 
1361
  "node": ">= 0.4"
1362
  }
1363
  },
1364
+ "node_modules/enabled": {
1365
+ "version": "2.0.0",
1366
+ "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
1367
+ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==",
1368
+ "license": "MIT"
1369
+ },
1370
  "node_modules/es-define-property": {
1371
  "version": "1.0.1",
1372
  "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
 
1387
  "node": ">= 0.4"
1388
  }
1389
  },
 
 
 
 
 
 
1390
  "node_modules/es-module-lexer": {
1391
  "version": "2.1.0",
1392
  "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
 
1460
  }
1461
  }
1462
  },
1463
+ "node_modules/fecha": {
1464
+ "version": "4.2.3",
1465
+ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
1466
+ "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
1467
+ "license": "MIT"
1468
+ },
1469
  "node_modules/fill-range": {
1470
  "version": "7.1.1",
1471
  "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
 
1489
  "micromatch": "^4.0.2"
1490
  }
1491
  },
1492
+ "node_modules/fn.name": {
1493
+ "version": "1.1.0",
1494
+ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
1495
+ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
1496
+ "license": "MIT"
1497
+ },
1498
  "node_modules/follow-redirects": {
1499
  "version": "1.16.0",
1500
  "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
 
1530
  "node": ">=12"
1531
  }
1532
  },
 
 
 
 
 
 
 
 
 
 
 
 
1533
  "node_modules/fsevents": {
1534
  "version": "2.3.3",
1535
  "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
 
1672
  "node": ">=16.9.0"
1673
  }
1674
  },
1675
+ "node_modules/inherits": {
1676
+ "version": "2.0.4",
1677
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1678
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1679
+ "license": "ISC"
1680
+ },
1681
  "node_modules/is-docker": {
1682
  "version": "2.2.1",
1683
  "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
 
1694
  "url": "https://github.com/sponsors/sindresorhus"
1695
  }
1696
  },
 
 
 
 
 
 
1697
  "node_modules/is-network-error": {
1698
+ "version": "1.3.2",
1699
+ "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.2.tgz",
1700
+ "integrity": "sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==",
1701
  "license": "MIT",
1702
  "engines": {
1703
  "node": ">=16"
 
1716
  "node": ">=0.12.0"
1717
  }
1718
  },
1719
+ "node_modules/is-stream": {
1720
+ "version": "2.0.1",
1721
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
1722
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
1723
+ "license": "MIT",
1724
+ "engines": {
1725
+ "node": ">=8"
1726
+ },
1727
+ "funding": {
1728
+ "url": "https://github.com/sponsors/sindresorhus"
1729
+ }
1730
+ },
1731
  "node_modules/is-wsl": {
1732
  "version": "2.2.0",
1733
  "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
 
1761
  "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==",
1762
  "license": "MIT"
1763
  },
 
 
 
 
 
 
 
 
 
 
 
 
1764
  "node_modules/js-tiktoken": {
1765
  "version": "1.0.21",
1766
  "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.21.tgz",
 
1770
  "base64-js": "^1.5.1"
1771
  }
1772
  },
1773
+ "node_modules/json-schema-to-ts": {
1774
+ "version": "3.1.1",
1775
+ "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz",
1776
+ "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==",
1777
+ "license": "MIT",
1778
+ "dependencies": {
1779
+ "@babel/runtime": "^7.18.3",
1780
+ "ts-algebra": "^2.0.0"
1781
+ },
1782
+ "engines": {
1783
+ "node": ">=16"
1784
+ }
1785
+ },
1786
  "node_modules/json-stable-stringify": {
1787
  "version": "1.3.0",
1788
  "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
 
1836
  "graceful-fs": "^4.1.11"
1837
  }
1838
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
1839
  "node_modules/kuler": {
1840
  "version": "2.0.0",
1841
  "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
 
1843
  "license": "MIT"
1844
  },
1845
  "node_modules/langchain": {
1846
+ "version": "1.4.2",
1847
+ "resolved": "https://registry.npmjs.org/langchain/-/langchain-1.4.2.tgz",
1848
+ "integrity": "sha512-SLGipy0r4nqQD0aiUOBYLMeGFfB/QiYnMndfZ8sGN89vXDCIXbYqcE7G/4QDDX3nZsM7/emQpoScmlxEX6sDnQ==",
1849
  "license": "MIT",
1850
  "dependencies": {
1851
+ "@langchain/langgraph": "^1.3.2",
1852
  "@langchain/langgraph-checkpoint": "^1.0.1",
1853
  "langsmith": ">=0.5.0 <1.0.0",
1854
  "zod": "^3.25.76 || ^4"
 
1857
  "node": ">=20"
1858
  },
1859
  "peerDependencies": {
1860
+ "@langchain/core": "^1.1.48"
1861
  }
1862
  },
1863
  "node_modules/langsmith": {
 
2291
  ],
2292
  "license": "MIT"
2293
  },
2294
+ "node_modules/one-time": {
2295
+ "version": "1.0.0",
2296
+ "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
2297
+ "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
2298
+ "license": "MIT",
2299
+ "dependencies": {
2300
+ "fn.name": "1.x.x"
2301
+ }
2302
+ },
2303
  "node_modules/open": {
2304
  "version": "7.4.2",
2305
  "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
 
2317
  "url": "https://github.com/sponsors/sindresorhus"
2318
  }
2319
  },
 
 
 
 
 
 
 
 
 
2320
  "node_modules/openai": {
2321
  "version": "6.36.0",
2322
  "resolved": "https://registry.npmjs.org/openai/-/openai-6.36.0.tgz",
 
2566
  "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.18"
2567
  }
2568
  },
2569
+ "node_modules/safe-buffer": {
2570
+ "version": "5.2.1",
2571
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
2572
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
2573
+ "funding": [
2574
+ {
2575
+ "type": "github",
2576
+ "url": "https://github.com/sponsors/feross"
2577
+ },
2578
+ {
2579
+ "type": "patreon",
2580
+ "url": "https://www.patreon.com/feross"
2581
+ },
2582
+ {
2583
+ "type": "consulting",
2584
+ "url": "https://feross.org/support"
2585
+ }
2586
+ ],
2587
+ "license": "MIT"
2588
+ },
2589
+ "node_modules/safe-stable-stringify": {
2590
+ "version": "2.5.0",
2591
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
2592
+ "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
2593
+ "license": "MIT",
2594
+ "engines": {
2595
+ "node": ">=10"
2596
+ }
2597
+ },
2598
  "node_modules/semver": {
2599
  "version": "5.7.2",
2600
  "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
 
2645
  "node": ">=8"
2646
  }
2647
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2648
  "node_modules/siginfo": {
2649
  "version": "2.0.0",
2650
  "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
 
2716
  "dev": true,
2717
  "license": "MIT"
2718
  },
2719
+ "node_modules/string_decoder": {
2720
+ "version": "1.3.0",
2721
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
2722
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
2723
+ "license": "MIT",
2724
+ "dependencies": {
2725
+ "safe-buffer": "~5.2.0"
2726
+ }
2727
+ },
2728
  "node_modules/supports-color": {
2729
  "version": "7.2.0",
2730
  "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
 
2738
  "node": ">=8"
2739
  }
2740
  },
 
 
 
 
 
 
 
 
 
2741
  "node_modules/text-hex": {
2742
  "version": "1.0.0",
2743
  "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
 
3087
  "node": ">=8"
3088
  }
3089
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3090
  "node_modules/winston": {
3091
  "version": "3.19.0",
3092
  "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz",
 
3123
  "node": ">= 12.0.0"
3124
  }
3125
  },
3126
+ "node_modules/yaml": {
3127
+ "version": "2.9.0",
3128
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
3129
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
3130
+ "dev": true,
3131
+ "license": "ISC",
3132
+ "bin": {
3133
+ "yaml": "bin.mjs"
3134
+ },
3135
+ "engines": {
3136
+ "node": ">= 14.6"
3137
+ },
3138
+ "funding": {
3139
+ "url": "https://github.com/sponsors/eemeli"
3140
+ }
3141
+ },
3142
  "node_modules/zod": {
3143
  "version": "4.4.3",
3144
  "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
src/agents/auditor/agent.ts CHANGED
@@ -6,7 +6,7 @@ import { END, type GraphNode, START, StateGraph } from "@langchain/langgraph";
6
  import { z } from "zod";
7
 
8
  import { logger } from "../../logger.ts";
9
- import { judgeFindingsModel, findVulnerabilitiesModel, gatherContextModel } from "./model.ts";
10
  import { JUDGE_FINDINGS_PROMPT, FIND_VULNERABILITIES_PROMPT, GATHER_CONTEXT_PROMPT } from "./prompts.ts";
11
  import { AuditorState, JudgeReviewSchema, CandidateFindingSchema } from "./state.ts";
12
  import { analyzeSolidityFile } from "./tools/solidity-analyzer-tool.ts";
@@ -24,6 +24,8 @@ import {
24
  } from "./config.ts";
25
  import { matchLines } from "./utils.ts";
26
 
 
 
27
  const walkDirectory = (dir: string, depth: number, solFiles: string[], docFiles: string[]) => {
28
  if (depth > MAX_DEPTH) return;
29
 
@@ -119,7 +121,7 @@ const gatherContext: GraphNode<typeof AuditorState> = async (state) => {
119
  parts.push(`### ${filePath}\n\`\`\`solidity\n${source}\n\`\`\``);
120
  }
121
 
122
- const model = gatherContextModel.withStructuredOutput(z.object({ context: z.string() }));
123
  const result = await model.invoke([new SystemMessage(GATHER_CONTEXT_PROMPT), new HumanMessage(parts.join("\n\n"))]);
124
 
125
  logger.info(`gatherContext: context built (${parts.join("\n\n").length} chars)`);
@@ -129,7 +131,7 @@ const gatherContext: GraphNode<typeof AuditorState> = async (state) => {
129
  };
130
 
131
  const findVulnerabilities: GraphNode<typeof AuditorState> = async (state) => {
132
- const model = findVulnerabilitiesModel.withStructuredOutput(z.object({ findings: z.array(CandidateFindingSchema) }));
133
 
134
  const previousFeedback =
135
  state.judgeReviews.length > 0
@@ -192,7 +194,7 @@ const judgeFindings: GraphNode<typeof AuditorState> = async (state) => {
192
  };
193
  }
194
 
195
- const model = judgeFindingsModel.withStructuredOutput(JudgeReviewSchema);
196
 
197
  logger.info(`judgeFindings: reviewing ${state.candidateFindings.length} candidate finding(s) in parallel`);
198
 
 
6
  import { z } from "zod";
7
 
8
  import { logger } from "../../logger.ts";
9
+ import { createLLM } from "../../config/llm.ts";
10
  import { JUDGE_FINDINGS_PROMPT, FIND_VULNERABILITIES_PROMPT, GATHER_CONTEXT_PROMPT } from "./prompts.ts";
11
  import { AuditorState, JudgeReviewSchema, CandidateFindingSchema } from "./state.ts";
12
  import { analyzeSolidityFile } from "./tools/solidity-analyzer-tool.ts";
 
24
  } from "./config.ts";
25
  import { matchLines } from "./utils.ts";
26
 
27
+ const llm = createLLM();
28
+
29
  const walkDirectory = (dir: string, depth: number, solFiles: string[], docFiles: string[]) => {
30
  if (depth > MAX_DEPTH) return;
31
 
 
121
  parts.push(`### ${filePath}\n\`\`\`solidity\n${source}\n\`\`\``);
122
  }
123
 
124
+ const model = llm.withStructuredOutput(z.object({ context: z.string() }));
125
  const result = await model.invoke([new SystemMessage(GATHER_CONTEXT_PROMPT), new HumanMessage(parts.join("\n\n"))]);
126
 
127
  logger.info(`gatherContext: context built (${parts.join("\n\n").length} chars)`);
 
131
  };
132
 
133
  const findVulnerabilities: GraphNode<typeof AuditorState> = async (state) => {
134
+ const model = llm.withStructuredOutput(z.object({ findings: z.array(CandidateFindingSchema) }));
135
 
136
  const previousFeedback =
137
  state.judgeReviews.length > 0
 
194
  };
195
  }
196
 
197
+ const model = llm.withStructuredOutput(JudgeReviewSchema);
198
 
199
  logger.info(`judgeFindings: reviewing ${state.candidateFindings.length} candidate finding(s) in parallel`);
200
 
src/agents/auditor/model.ts DELETED
@@ -1,13 +0,0 @@
1
- import { ChatAnthropic } from "@langchain/anthropic";
2
-
3
- export const gatherContextModel = new ChatAnthropic({
4
- model: "claude-haiku-4-5",
5
- });
6
-
7
- export const findVulnerabilitiesModel = new ChatAnthropic({
8
- model: "claude-sonnet-4-6",
9
- });
10
-
11
- export const judgeFindingsModel = new ChatAnthropic({
12
- model: "claude-sonnet-4-6",
13
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/agents/auditor/prompts.ts CHANGED
@@ -1,51 +1,50 @@
1
- // TODO: Compact the entire full context (parts: docs + static analysis) and infer the sections conciselly
2
- export const GATHER_CONTEXT_PROMPT = `You are a smart contract security expert. You will receive documentation, a structural analysis, and the full source of all in-scope Solidity contracts. Produce a thorough protocol context that will guide vulnerability discovery.
3
 
4
- Structure your output in the following sections:
5
 
6
- ## 1. Contract Overview
7
- For each contract: its purpose, kind (contract/interface/library/abstract), inheritance chain, and key dependencies on other in-scope contracts or external protocols.
8
 
9
- ## 2. State & Storage Map
10
- List all meaningful state variables across contracts, what they represent, and which functions read or write them. Flag shared or inherited storage.
11
 
12
- ## 3. Key Flows
13
- Trace the main execution paths and state transitions end-to-end across contracts (e.g., depositmint shares → updateRewards; withdrawburn shares → transfer ETH). Include cross-contract calls.
14
 
15
- ## 4. Invariants
16
- Conditions that must always hold (e.g., "total supply must equal sum of all balances", "contract ETH balancesum of all user deposits"). Derive these from both the source and any documentation.
17
 
18
- ## 5. Design Assumptions
19
- What the protocol assumes about callers, external contracts, oracles, admin keys, and token behavior (e.g., "tokens are ERC-20 compliant", "admin is trusted", "no fee-on-transfer tokens").
20
 
21
- ## 6. Business Rules
22
- Access controls, fee structures, timelocks, caps, pausing mechanisms, upgrade patterns, and any other domain constraints.
23
 
24
- Be precise and exhaustivethe richer the context, the more accurately vulnerabilities can be identified and validated.`;
25
 
26
- export const FIND_VULNERABILITIES_PROMPT = `You are an expert smart contract security auditor specializing in Solidity. Systematically analyze the contract source code and protocol context to identify security vulnerabilities.
27
 
28
- For each vulnerability provide ALL of the following fields:
29
 
30
- - **title**: Short, precise name (e.g., "Reentrancy in withdraw", "Missing access control on setFee").
31
- - **description**: Explain the EXPECTED behavior vs the OBSERVED (vulnerable) behavior in 24 sentences.
32
- - **recommendation**: Specific, actionable remediation (e.g., "Apply checks-effects-interactions pattern", "Add onlyOwner modifier").
33
- - **severity**: One of "high" (direct fund loss or contract takeover), "medium" (indirect or conditional risk), "low" (best-practice issue, no immediate financial risk).
34
- - **codeSnippet**: The exact vulnerable code block as it appears in the source.
35
 
36
- Vulnerability categories to systematically check: reentrancy (single- and cross-function), access control, integer overflow/underflow, oracle manipulation, flash loan attacks, front-running/MEV, signature replay, storage collisions, uninitialized proxies, unsafe delegatecall, gas griefing, denial of service, precision loss, and logic/business rule violations.
37
 
38
- If judge feedback is provided from a previous iteration, remove confirmed false positives from your list and refine or expand remaining findings based on the critique.`;
39
 
40
- export const JUDGE_FINDINGS_PROMPT = `You are a rigorous smart contract security reviewer. Evaluate each candidate vulnerability submitted by the auditor and determine whether it is a true positive or a false positive.
41
 
42
- For each finding provide ALL of the following fields:
43
 
44
- - **review**: Detailed analysis (36 sentences) explaining why the vulnerability is or isn't real. Reference specific code, protocol invariants, preconditions, and mitigating controls.
45
- - **isFalsePositive**: true if the finding is NOT exploitable in practice; false if it IS a real vulnerability.
46
- - **confidence**: Integer 0–100 reflecting your confidence in this verdict.
47
- - **exploitablePaths**: Array of strings. If a true positive, provide concrete paths confirming exploitability with real values. Each trace must describe the attacker steps with realistic inputs/values (e.g., "1. Attacker calls deposit(100 ETH) 2. Attacker contract fallback re-enters withdraw() before balance update 3. Attacker drains 100 ETH twice"). If a false positive, provide the reasoning that blocks the exploit.
48
 
49
- A finding is a false positive if and only if: the exploit path is unreachable given access controls or preconditions, it is already fully mitigated by the code, it requires impossible or economically infeasible conditions, or it is explicitly documented as by-design behavior in the protocol assumptions.
50
 
51
- You must provide exactly one review object per finding, in the same order as the findings were presented.`;
 
1
+ export const GATHER_CONTEXT_PROMPT = `Você é um especialista em segurança de smart contracts. Você receberá documentação, uma análise estrutural e o código-fonte completo de todos os contratos Solidity em escopo. Produza um contexto detalhado do protocolo que guiará a descoberta de vulnerabilidades.
 
2
 
3
+ Estruture sua resposta nas seguintes seções:
4
 
5
+ ## 1. Visão Geral dos Contratos
6
+ Para cada contrato: seu propósito, tipo (contract/interface/library/abstract), cadeia de herança e principais dependências de outros contratos em escopo ou protocolos externos.
7
 
8
+ ## 2. Mapa de Estado e Armazenamento
9
+ Liste todas as variáveis de estado relevantes entre os contratos, o que representam e quais funções as leem ou escrevem. Sinalize armazenamento compartilhado ou herdado.
10
 
11
+ ## 3. Fluxos Principais
12
+ Trace os principais caminhos de execução e transições de estado de ponta a ponta entre contratos (ex.: depósitocunhar shares → atualizar recompensas; saquequeimar shares → transferir ETH). Inclua chamadas entre contratos.
13
 
14
+ ## 4. Invariantes
15
+ Condições que devem sempre ser verdadeiras (ex.: "o supply total deve ser igual à soma de todos os saldos", "o saldo de ETH do contrato soma de todos os depósitos dos usuários"). Derive-as tanto do código-fonte quanto da documentação.
16
 
17
+ ## 5. Premissas de Design
18
+ O que o protocolo assume sobre chamadores, contratos externos, oráculos, chaves de administrador e comportamento de tokens (ex.: "tokens são compatíveis com ERC-20", "o admin é confiável", "sem tokens com taxa de transferência").
19
 
20
+ ## 6. Regras de Negócio
21
+ Controles de acesso, estruturas de taxas, timelocks, limites, mecanismos de pausa, padrões de atualização e quaisquer outras restrições de domínio.
22
 
23
+ Seja preciso e exaustivoquanto mais rico o contexto, com mais precisão as vulnerabilidades podem ser identificadas e validadas.`;
24
 
25
+ export const FIND_VULNERABILITIES_PROMPT = `Você é um auditor especialista em segurança de smart contracts com foco em Solidity. Analise sistematicamente o código-fonte do contrato e o contexto do protocolo para identificar vulnerabilidades de segurança.
26
 
27
+ Para cada vulnerabilidade, forneça TODOS os seguintes campos:
28
 
29
+ - **title**: Nome curto e preciso (ex.: "Reentrância em withdraw", "Controle de acesso ausente em setFee").
30
+ - **description**: Explique o comportamento ESPERADO versus o comportamento OBSERVADO (vulnerável) em 2 a 4 frases.
31
+ - **recommendation**: Correção específica e acionável (ex.: "Aplicar o padrão checks-effects-interactions", "Adicionar o modificador onlyOwner").
32
+ - **severity**: Um de "high" (perda direta de fundos ou tomada de controle do contrato), "medium" (risco indireto ou condicional), "low" (problema de boas práticas, sem risco financeiro imediato).
33
+ - **codeSnippet**: O bloco de código vulnerável exatamente como aparece no código-fonte.
34
 
35
+ Categorias de vulnerabilidades a verificar sistematicamente: reentrância (simples e entre funções), controle de acesso, overflow/underflow de inteiros, manipulação de oráculo, ataques de flash loan, front-running/MEV, replay de assinatura, colisões de armazenamento, proxies não inicializados, delegatecall inseguro, griefing de gas, negação de serviço, perda de precisão e violações de lógica/regras de negócio.
36
 
37
+ Se feedback do juiz de uma iteração anterior for fornecido, remova os falsos positivos confirmados da sua lista e refine ou expanda os achados restantes com base na crítica.`;
38
 
39
+ export const JUDGE_FINDINGS_PROMPT = `Você é um revisor rigoroso de segurança de smart contracts. Avalie cada vulnerabilidade candidata submetida pelo auditor e determine se é um verdadeiro positivo ou um falso positivo.
40
 
41
+ Para cada achado, forneça TODOS os seguintes campos:
42
 
43
+ - **review**: Análise detalhada (3 a 6 frases) explicando por que a vulnerabilidade é ou não real. Referencie código específico, invariantes do protocolo, pré-condições e controles mitigadores.
44
+ - **isFalsePositive**: true se o achado NÃO for explorável na prática; false se for uma vulnerabilidade real.
45
+ - **confidence**: Número inteiro de 0 a 100 refletindo sua confiança no veredicto.
46
+ - **exploitablePaths**: Array de strings. Se for verdadeiro positivo, forneça caminhos concretos confirmando a explorabilidade com valores reais. Cada rastreamento deve descrever os passos do atacante com entradas/valores realistas (ex.: "1. Atacante chama deposit(100 ETH) 2. Contrato do atacante no fallback chama withdraw() novamente antes da atualização do saldo 3. Atacante drena 100 ETH duas vezes"). Se for falso positivo, forneça o raciocínio que bloqueia o exploit.
47
 
48
+ Um achado é falso positivo somente se: o caminho de exploit for inacessível dados os controles de acesso ou pré-condições, estiver totalmente mitigado pelo código, exigir condições impossíveis ou economicamente inviáveis, ou for explicitamente documentado como comportamento esperado nas premissas do protocolo.
49
 
50
+ Você deve fornecer exatamente um objeto de revisão por achado, na mesma ordem em que os achados foram apresentados.`;
src/config/llm.ts CHANGED
@@ -1,7 +1,8 @@
1
  import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
 
2
  import type { BaseChatModel } from "@langchain/core/language_models/chat_models";
3
 
4
- export type LLMProvider = "google" | "openrouter";
5
 
6
  export function createLLM(overrideProvider?: LLMProvider): BaseChatModel {
7
  const provider = overrideProvider || (process.env.LLM_PROVIDER as LLMProvider) || "google";
@@ -14,6 +15,11 @@ export function createLLM(overrideProvider?: LLMProvider): BaseChatModel {
14
  temperature: 0.2,
15
  }) as BaseChatModel;
16
  }
 
 
 
 
 
17
  case "google":
18
  default:
19
  return new ChatGoogleGenerativeAI({
 
1
  import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
2
+ import { ChatAnthropic } from "@langchain/anthropic";
3
  import type { BaseChatModel } from "@langchain/core/language_models/chat_models";
4
 
5
+ export type LLMProvider = "google" | "openrouter" | "anthropic";
6
 
7
  export function createLLM(overrideProvider?: LLMProvider): BaseChatModel {
8
  const provider = overrideProvider || (process.env.LLM_PROVIDER as LLMProvider) || "google";
 
15
  temperature: 0.2,
16
  }) as BaseChatModel;
17
  }
18
+ case "anthropic":
19
+ return new ChatAnthropic({
20
+ model: process.env.ANTHROPIC_MODEL || "claude-sonnet-4-6",
21
+ temperature: 0.2,
22
+ });
23
  case "google":
24
  default:
25
  return new ChatGoogleGenerativeAI({
src/index.ts CHANGED
@@ -27,9 +27,9 @@ console.log(coderResult.contract);
27
  const __dirname = dirname(fileURLToPath(import.meta.url));
28
  const outputDir = resolve(__dirname, "agents/coder/outputs");
29
  mkdirSync(outputDir, { recursive: true });
30
- const outputPath = resolve(outputDir, "Contract.sol");
31
- writeFileSync(outputPath, coderResult.contract, "utf-8");
32
- console.log("\nContrato salvo em:", outputPath);
33
 
34
  console.log("\n======= Auditor =======");
35
  logger.info("Starting auditorAgent");
@@ -37,7 +37,10 @@ logger.info("Starting auditorAgent");
37
  const auditorResult = await auditorAgent.invoke({ repoPath: outputDir });
38
 
39
  logger.info("Agent completed");
40
- logger.debug(`Agent result:\n${JSON.stringify(auditorResult, null, 2)}`);
 
 
 
41
 
42
  const testerResult = await testerAgent.invoke({
43
  solidityFiles: [coderResult.contract],
 
27
  const __dirname = dirname(fileURLToPath(import.meta.url));
28
  const outputDir = resolve(__dirname, "agents/coder/outputs");
29
  mkdirSync(outputDir, { recursive: true });
30
+ writeFileSync(resolve(outputDir, "Contract.sol"), coderResult.contract, "utf-8");
31
+ writeFileSync(resolve(outputDir, "README.md"), requirementsText, "utf-8");
32
+ console.log("\nContrato e requisitos salvos em:", outputDir);
33
 
34
  console.log("\n======= Auditor =======");
35
  logger.info("Starting auditorAgent");
 
37
  const auditorResult = await auditorAgent.invoke({ repoPath: outputDir });
38
 
39
  logger.info("Agent completed");
40
+ logger.info(`Findings: ${auditorResult.findings.length}`);
41
+ for (const f of auditorResult.findings) {
42
+ logger.info(` [${f.severity.toUpperCase()}] ${f.title} — ${f.location}`);
43
+ }
44
 
45
  const testerResult = await testerAgent.invoke({
46
  solidityFiles: [coderResult.contract],
src/server.ts CHANGED
@@ -1,4 +1,8 @@
1
  import "dotenv/config";
 
 
 
 
2
  import { serve } from "@hono/node-server";
3
  import { Hono } from "hono";
4
  import { cors } from "hono/cors";
@@ -42,32 +46,49 @@ app.post("/api/run", (c) => {
42
  await send("log", "[Coder] Contrato compilado sem erros.");
43
  }
44
 
45
- await send("coder", JSON.stringify({
46
- contract: coderResult.contract,
47
- compilationErrors: coderResult.compilationErrors,
48
- reviewSummary: coderResult.reviewSummary,
49
- }));
 
 
 
50
 
51
  // === AUDITOR ===
 
 
 
 
 
52
  await send("log", "[Auditor] Iniciando auditoria de segurança...");
53
- const auditorResult = await auditorAgent.invoke({ solidityFile: coderResult.contract });
54
- await send("log", `[Auditor] ${auditorResult.vulnerabilities.length} vulnerabilidade(s) encontrada(s).`);
 
 
 
55
 
56
- await send("auditor", JSON.stringify({
57
- vulnerabilities: auditorResult.vulnerabilities,
58
- }));
 
 
 
59
 
60
  // === TESTER ===
61
  await send("log", "[Tester] Gerando testes de prova de conceito...");
62
  const testerResult = await testerAgent.invoke({
63
  solidityFiles: [coderResult.contract],
64
- vulnerability: auditorResult.vulnerabilities[0] ?? {},
65
  });
66
  await send("log", `[Tester] ${testerResult.results.length} resultado(s) de teste.`);
67
 
68
- await send("tester", JSON.stringify({
69
- results: testerResult.results,
70
- }));
 
 
 
71
 
72
  await send("log", "Pipeline concluído.");
73
  await send("done", "ok");
 
1
  import "dotenv/config";
2
+
3
+ import { mkdirSync, writeFileSync } from "node:fs";
4
+ import { resolve } from "node:path";
5
+ import { tmpdir } from "node:os";
6
  import { serve } from "@hono/node-server";
7
  import { Hono } from "hono";
8
  import { cors } from "hono/cors";
 
46
  await send("log", "[Coder] Contrato compilado sem erros.");
47
  }
48
 
49
+ await send(
50
+ "coder",
51
+ JSON.stringify({
52
+ contract: coderResult.contract,
53
+ compilationErrors: coderResult.compilationErrors,
54
+ reviewSummary: coderResult.reviewSummary,
55
+ }),
56
+ );
57
 
58
  // === AUDITOR ===
59
+ const outputDir = resolve(tmpdir(), `talp1-${Date.now()}`);
60
+ mkdirSync(outputDir, { recursive: true });
61
+ writeFileSync(resolve(outputDir, "Contract.sol"), coderResult.contract, "utf-8");
62
+ writeFileSync(resolve(outputDir, "README.md"), requirements, "utf-8");
63
+
64
  await send("log", "[Auditor] Iniciando auditoria de segurança...");
65
+ const auditorResult = await auditorAgent.invoke({ repoPath: outputDir });
66
+ await send("log", `[Auditor] ${auditorResult.findings.length} vulnerabilidade(s) encontrada(s).`);
67
+ for (const f of auditorResult.findings) {
68
+ await send("log", `[Auditor] [${f.severity.toUpperCase()}] ${f.title} — ${f.location}`);
69
+ }
70
 
71
+ await send(
72
+ "auditor",
73
+ JSON.stringify({
74
+ findings: auditorResult.findings,
75
+ }),
76
+ );
77
 
78
  // === TESTER ===
79
  await send("log", "[Tester] Gerando testes de prova de conceito...");
80
  const testerResult = await testerAgent.invoke({
81
  solidityFiles: [coderResult.contract],
82
+ vulnerability: auditorResult.findings[0] ?? {},
83
  });
84
  await send("log", `[Tester] ${testerResult.results.length} resultado(s) de teste.`);
85
 
86
+ await send(
87
+ "tester",
88
+ JSON.stringify({
89
+ results: testerResult.results,
90
+ }),
91
+ );
92
 
93
  await send("log", "Pipeline concluído.");
94
  await send("done", "ok");