lightnode-sdk 0.8.8 → 0.8.9

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 (2) hide show
  1. package/dist/add.js +64 -28
  2. package/package.json +1 -1
package/dist/add.js CHANGED
@@ -978,7 +978,9 @@ type Turn = {
978
978
  jobCompletedTx?: \`0x\${string}\` | null;
979
979
  };
980
980
 
981
- const MODEL = "llama3-8b";
981
+ // Models live on LightChain mainnet. The visitor picks one per the dropdown.
982
+ const MODELS = ["llama3-8b", "llama3-70b"] as const;
983
+ type ModelId = (typeof MODELS)[number];
982
984
 
983
985
  export default function ChatWeb3() {
984
986
  const { address, chain } = useAccount();
@@ -987,6 +989,7 @@ export default function ChatWeb3() {
987
989
  const { data: walletClient } = useWalletClient({ chainId: chain?.id });
988
990
  const publicClient = usePublicClient({ chainId: chain?.id });
989
991
 
992
+ const [model, setModel] = useState<ModelId>("llama3-8b");
990
993
  const [turns, setTurns] = useState<Turn[]>([]);
991
994
  const [input, setInput] = useState("");
992
995
  const [busy, setBusy] = useState(false);
@@ -1000,12 +1003,12 @@ export default function ChatWeb3() {
1000
1003
  useEffect(() => {
1001
1004
  if (!network) { setFeeLcai(null); return; }
1002
1005
  let cancelled = false;
1003
- estimateJobFee(NETWORKS[network], MODEL).then(
1006
+ estimateJobFee(NETWORKS[network], model).then(
1004
1007
  (fee) => { if (!cancelled) setFeeLcai(fee); },
1005
1008
  () => { if (!cancelled) setFeeLcai(null); },
1006
1009
  );
1007
1010
  return () => { cancelled = true; };
1008
- }, [network]);
1011
+ }, [network, model]);
1009
1012
 
1010
1013
  // Keep the latest turn in view. Instant while streaming (smooth scrolling on
1011
1014
  // every chunk competes for the main thread); smooth once idle.
@@ -1062,7 +1065,7 @@ export default function ChatWeb3() {
1062
1065
  wallet: walletClient as unknown as Parameters<typeof runInference>[0]["wallet"],
1063
1066
  publicClient: publicClient as unknown as Parameters<typeof runInference>[0]["publicClient"],
1064
1067
  network: NETWORKS[network],
1065
- model: MODEL,
1068
+ model,
1066
1069
  jobCompletedTimeoutMs: 120_000,
1067
1070
  maxRetries: 1,
1068
1071
  // Stream each decrypted chunk into the assistant bubble as it arrives.
@@ -1207,14 +1210,17 @@ export default function ChatWeb3() {
1207
1210
  />
1208
1211
  </div>
1209
1212
  <div className="mt-1 flex items-center justify-between gap-2">
1210
- <span className="inline-flex items-center gap-1.5 rounded-lg px-2 py-1 text-xs font-medium text-muted-foreground">
1211
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
1212
- <rect x="4" y="4" width="16" height="16" rx="2" />
1213
- <rect x="9" y="9" width="6" height="6" />
1214
- <path d="M9 2v2M15 2v2M9 20v2M15 20v2M2 9h2M2 15h2M20 9h2M20 15h2" />
1215
- </svg>
1216
- {MODEL}
1217
- </span>
1213
+ <select
1214
+ value={model}
1215
+ onChange={(e) => setModel(e.target.value as ModelId)}
1216
+ disabled={busy}
1217
+ title="Model (both live on LightChain mainnet)"
1218
+ className="rounded-lg border border-border bg-background px-2 py-1 text-xs font-medium text-muted-foreground outline-none focus:ring-2 focus:ring-primary disabled:opacity-50"
1219
+ >
1220
+ {MODELS.map((m) => (
1221
+ <option key={m} value={m}>{m}</option>
1222
+ ))}
1223
+ </select>
1218
1224
  <button
1219
1225
  type="button"
1220
1226
  onClick={() => send()}
@@ -1267,7 +1273,8 @@ type Result = {
1267
1273
  elapsedMs: number;
1268
1274
  };
1269
1275
 
1270
- const MODEL = "llama3-8b";
1276
+ const MODELS = ["llama3-8b", "llama3-70b"] as const;
1277
+ type ModelId = (typeof MODELS)[number];
1271
1278
 
1272
1279
  export default function InferenceWeb3() {
1273
1280
  const { address, chain } = useAccount();
@@ -1276,6 +1283,7 @@ export default function InferenceWeb3() {
1276
1283
  const { data: walletClient } = useWalletClient({ chainId: chain?.id });
1277
1284
  const publicClient = usePublicClient({ chainId: chain?.id });
1278
1285
 
1286
+ const [model, setModel] = useState<ModelId>("llama3-8b");
1279
1287
  const [system, setSystem] = useState("You are a concise assistant. Reply in one or two short sentences.");
1280
1288
  const [prompt, setPrompt] = useState("Reply with the single word OK.");
1281
1289
  const [busy, setBusy] = useState(false);
@@ -1288,12 +1296,12 @@ export default function InferenceWeb3() {
1288
1296
  useEffect(() => {
1289
1297
  if (!network) { setFeeLcai(null); return; }
1290
1298
  let cancelled = false;
1291
- estimateJobFee(NETWORKS[network], MODEL).then(
1299
+ estimateJobFee(NETWORKS[network], model).then(
1292
1300
  (fee) => { if (!cancelled) setFeeLcai(fee); },
1293
1301
  () => { if (!cancelled) setFeeLcai(null); },
1294
1302
  );
1295
1303
  return () => { cancelled = true; };
1296
- }, [network]);
1304
+ }, [network, model]);
1297
1305
 
1298
1306
  async function run() {
1299
1307
  if (!walletClient || !publicClient || !address || !network) {
@@ -1319,7 +1327,7 @@ export default function InferenceWeb3() {
1319
1327
  wallet: walletClient as unknown as Parameters<typeof runInference>[0]["wallet"],
1320
1328
  publicClient: publicClient as unknown as Parameters<typeof runInference>[0]["publicClient"],
1321
1329
  network: NETWORKS[network],
1322
- model: MODEL,
1330
+ model,
1323
1331
  jobCompletedTimeoutMs: 120_000,
1324
1332
  maxRetries: 1,
1325
1333
  // Stream the answer live as decrypted chunks arrive.
@@ -1382,10 +1390,23 @@ export default function InferenceWeb3() {
1382
1390
  className="resize-none rounded-xl border border-border bg-card px-3 py-2 font-mono text-xs text-foreground outline-none focus:ring-2 focus:ring-primary" />
1383
1391
  </label>
1384
1392
 
1385
- <button type="button" onClick={() => run()} disabled={busy || !prompt.trim() || !address || !network}
1386
- className="self-start rounded-xl bg-gradient-primary px-4 py-2 text-sm font-medium text-white transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40">
1387
- {busy ? (busyStage || "Running...") : "Run inference"}
1388
- </button>
1393
+ <div className="flex items-center gap-3">
1394
+ <select
1395
+ value={model}
1396
+ onChange={(e) => setModel(e.target.value as ModelId)}
1397
+ disabled={busy}
1398
+ title="Model (both live on LightChain mainnet)"
1399
+ className="rounded-xl border border-border bg-card px-2 py-2 text-xs font-medium text-muted-foreground outline-none focus:ring-2 focus:ring-primary disabled:opacity-50"
1400
+ >
1401
+ {MODELS.map((m) => (
1402
+ <option key={m} value={m}>{m}</option>
1403
+ ))}
1404
+ </select>
1405
+ <button type="button" onClick={() => run()} disabled={busy || !prompt.trim() || !address || !network}
1406
+ className="rounded-xl bg-gradient-primary px-4 py-2 text-sm font-medium text-white transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40">
1407
+ {busy ? (busyStage || "Running...") : "Run inference"}
1408
+ </button>
1409
+ </div>
1389
1410
 
1390
1411
  {err && (
1391
1412
  <p className="rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">
@@ -1464,7 +1485,8 @@ type Result = {
1464
1485
  jobCompleted: \`0x\${string}\` | null;
1465
1486
  };
1466
1487
 
1467
- const MODEL = "llama3-8b";
1488
+ const MODELS = ["llama3-8b", "llama3-70b"] as const;
1489
+ type ModelId = (typeof MODELS)[number];
1468
1490
 
1469
1491
  export default function JudgeWeb3() {
1470
1492
  const { address, chain } = useAccount();
@@ -1473,6 +1495,7 @@ export default function JudgeWeb3() {
1473
1495
  const { data: walletClient } = useWalletClient({ chainId: chain?.id });
1474
1496
  const publicClient = usePublicClient({ chainId: chain?.id });
1475
1497
 
1498
+ const [model, setModel] = useState<ModelId>("llama3-8b");
1476
1499
  const [criteria, setCriteria] = useState("Run a mile under 8 minutes");
1477
1500
  const [evidence, setEvidence] = useState('{"distance_km": 1.61, "time_minutes": 7.4}');
1478
1501
  const [busy, setBusy] = useState(false);
@@ -1485,12 +1508,12 @@ export default function JudgeWeb3() {
1485
1508
  useEffect(() => {
1486
1509
  if (!network) { setFeeLcai(null); return; }
1487
1510
  let cancelled = false;
1488
- estimateJobFee(NETWORKS[network], MODEL).then(
1511
+ estimateJobFee(NETWORKS[network], model).then(
1489
1512
  (fee) => { if (!cancelled) setFeeLcai(fee); },
1490
1513
  () => { if (!cancelled) setFeeLcai(null); },
1491
1514
  );
1492
1515
  return () => { cancelled = true; };
1493
- }, [network]);
1516
+ }, [network, model]);
1494
1517
 
1495
1518
  /** Parse the verdict defensively; fall back to the first {...} block. */
1496
1519
  function parseVerdict(answer: string): Verdict | null {
@@ -1535,7 +1558,7 @@ Reply with STRICT JSON only, matching: { "passed": boolean, "confidence": 0-1, "
1535
1558
  wallet: walletClient as unknown as Parameters<typeof runInference>[0]["wallet"],
1536
1559
  publicClient: publicClient as unknown as Parameters<typeof runInference>[0]["publicClient"],
1537
1560
  network: NETWORKS[network],
1538
- model: MODEL,
1561
+ model,
1539
1562
  jobCompletedTimeoutMs: 120_000,
1540
1563
  maxRetries: 1,
1541
1564
  // Show the model's raw output streaming in while it generates the verdict.
@@ -1598,10 +1621,23 @@ Reply with STRICT JSON only, matching: { "passed": boolean, "confidence": 0-1, "
1598
1621
  className="resize-none rounded-xl border border-border bg-card px-3 py-2 font-mono text-xs text-foreground outline-none focus:ring-2 focus:ring-primary" />
1599
1622
  </label>
1600
1623
 
1601
- <button type="button" onClick={() => run()} disabled={busy || !criteria.trim() || !evidence.trim() || !address || !network}
1602
- className="self-start rounded-xl bg-gradient-primary px-4 py-2 text-sm font-medium text-white transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40">
1603
- {busy ? (busyStage || "Judging...") : "Get AI verdict"}
1604
- </button>
1624
+ <div className="flex items-center gap-3">
1625
+ <select
1626
+ value={model}
1627
+ onChange={(e) => setModel(e.target.value as ModelId)}
1628
+ disabled={busy}
1629
+ title="Model (both live on LightChain mainnet)"
1630
+ className="rounded-xl border border-border bg-card px-2 py-2 text-xs font-medium text-muted-foreground outline-none focus:ring-2 focus:ring-primary disabled:opacity-50"
1631
+ >
1632
+ {MODELS.map((m) => (
1633
+ <option key={m} value={m}>{m}</option>
1634
+ ))}
1635
+ </select>
1636
+ <button type="button" onClick={() => run()} disabled={busy || !criteria.trim() || !evidence.trim() || !address || !network}
1637
+ className="rounded-xl bg-gradient-primary px-4 py-2 text-sm font-medium text-white transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-40">
1638
+ {busy ? (busyStage || "Judging...") : "Get AI verdict"}
1639
+ </button>
1640
+ </div>
1605
1641
 
1606
1642
  {err && (
1607
1643
  <p className="rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lightnode-sdk",
3
- "version": "0.8.8",
3
+ "version": "0.8.9",
4
4
  "description": "Read-only TypeScript client for LightChain AI: workers, jobs, models, on-chain registration, and per-model network analytics. Independent, community-built (not an official LightChain package).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",