lightnode-sdk 0.4.1 → 0.4.2

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.
@@ -159,7 +159,7 @@ export interface RunInferenceArgs {
159
159
  onChunk?: (chunk: string, totalSoFar: string) => void;
160
160
  /** Retry count if a worker stalls. Default 2 (so up to 3 paid attempts). */
161
161
  maxRetries?: number;
162
- /** How long to wait for JobCompleted before declaring the worker stalled. Default 90s. */
162
+ /** How long to wait for JobCompleted before declaring the worker stalled. Default 120s. */
163
163
  jobCompletedTimeoutMs?: number;
164
164
  /**
165
165
  * WebSocket constructor. In a browser, omit and `globalThis.WebSocket` is
@@ -179,7 +179,12 @@ export interface RunInferenceResult {
179
179
  txs: {
180
180
  createSession: `0x${string}`;
181
181
  submitJob: `0x${string}`;
182
- jobCompleted: `0x${string}`;
182
+ /**
183
+ * Worker's commit-result tx. Null if the on-chain event hasn't landed by the
184
+ * deadline but the WS-delivered, session-key-decrypted answer DID arrive -
185
+ * in that case the answer is still authentic; this is just the explorer link.
186
+ */
187
+ jobCompleted: `0x${string}` | null;
183
188
  };
184
189
  /** The dispatcher-assigned worker that produced this response. */
185
190
  worker: `0x${string}`;
package/dist/inference.js CHANGED
@@ -190,7 +190,7 @@ function topicAsUint(hex) {
190
190
  return BigInt(hex);
191
191
  }
192
192
  async function runOneAttempt(args, attempt) {
193
- const { prompt, gateway, wallet, publicClient, network, model = "llama3-8b", onChunk, jobCompletedTimeoutMs = 90000, } = args;
193
+ const { prompt, gateway, wallet, publicClient, network, model = "llama3-8b", onChunk, jobCompletedTimeoutMs = 120000, } = args;
194
194
  const WS = pickWebSocket(args.WebSocket);
195
195
  const relayUrl = args.relayUrl ?? `wss://relay.${network.id}.lightchain.ai/ws`;
196
196
  // 1. prepareSession
@@ -326,6 +326,11 @@ async function runOneAttempt(args, attempt) {
326
326
  throw new Error("JobSubmitted log missing in submitJob receipt");
327
327
  const jobId = topicAsUint(jobLog.topics[1]);
328
328
  // 6. wait for JobCompleted
329
+ // KEY INVARIANT: the real result is the WS-delivered, session-key-decrypted
330
+ // ciphertext. JobCompleted is an explorer pointer (the worker's commit-result
331
+ // tx). If the WS already produced an answer (chunks.length > 0) we MUST
332
+ // accept it even if the on-chain event hasn't landed - throwing stalled here
333
+ // wipes a delivered answer on retry, which reads as "the call returned nothing".
329
334
  const deadline = Date.now() + jobCompletedTimeoutMs;
330
335
  const jobIdTopic = (`0x${jobId.toString(16).padStart(64, "0")}`);
331
336
  let completed = null;
@@ -338,8 +343,14 @@ async function runOneAttempt(args, attempt) {
338
343
  });
339
344
  completed =
340
345
  logs.find((l) => l.topics[0] === JOB_COMPLETED_TOPIC && l.topics[1] === jobIdTopic) ?? null;
346
+ if (completed)
347
+ break;
348
+ // If the WS already delivered the answer, stop polling - no point burning
349
+ // more time on a confirmation that only serves as an explorer link.
350
+ if (chunks.length > 0)
351
+ break;
341
352
  }
342
- if (!completed) {
353
+ if (!completed && chunks.length === 0) {
343
354
  try {
344
355
  ws.close();
345
356
  }
@@ -363,7 +374,11 @@ async function runOneAttempt(args, attempt) {
363
374
  }
364
375
  return {
365
376
  answer: chunks.join(""),
366
- txs: { createSession: createTx, submitJob: submitTx, jobCompleted: completed.transactionHash },
377
+ // completed may be null when the answer arrived via the WS but JobCompleted
378
+ // hasn't landed on-chain yet. The decrypted answer is still authentic
379
+ // (session-key bound); callers can poll for the event later if they want
380
+ // the explorer-link form of the proof.
381
+ txs: { createSession: createTx, submitJob: submitTx, jobCompleted: completed?.transactionHash ?? null },
367
382
  worker: prepared.createSessionArgs.worker,
368
383
  sessionId,
369
384
  jobId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lightnode-sdk",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
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",