lightnode-sdk 0.7.7 → 0.7.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.
- package/README.md +13 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/inference.js +59 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -226,6 +226,15 @@ forever and **blocks deregistration** - and no official tool clears it. The
|
|
|
226
226
|
JobRegistry's `claimTimeout` is permissionless, so the operator can self-clear
|
|
227
227
|
it. `unstickAndDeregister()` is the one-call rescue.
|
|
228
228
|
|
|
229
|
+
The second thing it gets right is **gas-correct writes**. The worker daemon
|
|
230
|
+
under-sets the gas limit on its WorkerRegistry writes, so `addSupportedModel` and
|
|
231
|
+
`deregisterWorker` run out of gas and revert on-chain - the daemon reports a
|
|
232
|
+
failure (or, for deregister, some indexers still flip the worker to
|
|
233
|
+
"deregistered" while the stake never moves). Every write here estimates the gas
|
|
234
|
+
first and sends with a margin, so the transaction lands. `addModel()` is the
|
|
235
|
+
gas-correct version of the model-add the daemon botches; `deregister()` is the
|
|
236
|
+
gas-correct exit.
|
|
237
|
+
|
|
229
238
|
```ts
|
|
230
239
|
import { WorkerOperator } from "lightnode-sdk";
|
|
231
240
|
import { createPublicClient, createWalletClient, http } from "viem";
|
|
@@ -275,8 +284,9 @@ Full method reference (`jobIds` are the worker's IDs from
|
|
|
275
284
|
| `withdraw()` | yes | pull the earned balance into the worker wallet |
|
|
276
285
|
| `topUpStake(lcai)` | yes | add stake |
|
|
277
286
|
| `withdrawStake(lcai)` | yes | remove stake above the floor |
|
|
287
|
+
| `addModel(tagOrId)` | yes | add a supported model to a registered worker on-chain, gas-correct (no-op if already served) |
|
|
278
288
|
| `reinstate()` | yes | reactivate a suspended worker |
|
|
279
|
-
| `deregister()` | yes | exit and release stake (reverts if in-flight jobs remain) |
|
|
289
|
+
| `deregister()` | yes | exit and release stake, gas-correct (reverts if in-flight jobs remain) |
|
|
280
290
|
| `unstickAndDeregister(jobIds)` | yes | clear stuck + release + withdraw + deregister, in one call |
|
|
281
291
|
|
|
282
292
|
> **Mainnet slashing.** `claimTimeout` / `clearStuck` / `unstickAndDeregister`
|
|
@@ -443,6 +453,8 @@ controls. Mainnet `clearstuck` and `deregister` realize a slash, so they require
|
|
|
443
453
|
|
|
444
454
|
```bash
|
|
445
455
|
npx lightnode worker status 0x... # registration, stake, claimable, live config
|
|
456
|
+
npx lightnode worker models 0x... # models served, reconciled vs chain (servingNow truth)
|
|
457
|
+
PRIVATE_KEY=0x... npx lightnode worker preflight # one real test inference, print verdict + timings
|
|
446
458
|
PRIVATE_KEY=0x... npx lightnode worker can-deregister # what blocks the exit, before spending gas
|
|
447
459
|
PRIVATE_KEY=0x... npx lightnode worker settle # release completed jobs past their window + withdraw
|
|
448
460
|
PRIVATE_KEY=0x... npx lightnode worker withdraw # pull the earned balance into the worker wallet
|
package/dist/index.d.ts
CHANGED
|
@@ -133,7 +133,7 @@ export declare class LightNode {
|
|
|
133
133
|
* (especially in registry-proxy environments like StackBlitz where lockfiles
|
|
134
134
|
* may pin an older minor than the local install command suggests).
|
|
135
135
|
*/
|
|
136
|
-
export declare const SDK_VERSION = "0.7.
|
|
136
|
+
export declare const SDK_VERSION = "0.7.9";
|
|
137
137
|
export { NETWORKS, WORKER_REGISTRY, REGISTRY_TOPICS, aggregateModelStats, aggregateWorkerStats, networkAnalytics, modelStatsCsv, workerStatsCsv, workerJobsCsv, fromWei, resolveJobTransactions, fetchWorkerModels, computeModelId as modelId, estimateJobFee, JOB_REGISTRY_CONSUMER_ABI, consumerGatewayUrl, consumerGatewayHost, GatewayClient, GatewayHttpError, prepareSession, submitPrompt, decryptResponse, generateEcdhKeyPair, crypto, runInference, runInferenceWithKey, runInferenceStream, Conversation, chat, runInferenceBatch, Agent, parseAgentOutput, workerPreflight, workerWatch, Bridge, BRIDGE_ROUTE, HYPERLANE_ROUTER_ABI, ERC20_ABI, addressToBytes32, quoteBridgeFee, bridgeableBalance, bridgeAllowance, approveBridge, bridgeTransfer, DAO, DAO_ADDRESSES, ProposalState, PROPOSAL_STATE_LABEL, VoteSupport, GOVERNOR_ABI, VOTES_ABI, OnchainModelRegistry, AIVM_MODEL_REGISTRY_ABI, BENCHMARK_REGISTRY_ABI, ModelStatus, MODEL_STATUS_LABEL, StalledWorkerError, OnChainRevertError, RelayTokenTimeoutError, GatewayAuthError, isStalledWorker, WorkerOperator, WORKER_REGISTRY_ABI, JOB_REGISTRY_OPERATOR_ABI, AI_CONFIG_ABI, JOB_STATE, decodeWorkerError, WorkerOpError, isWorkerOpError, };
|
|
138
138
|
export type { BearerSource, GatewayClientOptions, SelectSessionResult, PrepareSessionResult, UploadBlobResult, SessionTokenResult } from "./gateway.js";
|
|
139
139
|
export type { SessionPreparation, RunInferenceArgs, RunInferenceResult, RunInferenceWithKeyArgs, RunInferenceStreamResult } from "./inference.js";
|
package/dist/index.js
CHANGED
|
@@ -212,7 +212,7 @@ export class LightNode {
|
|
|
212
212
|
* (especially in registry-proxy environments like StackBlitz where lockfiles
|
|
213
213
|
* may pin an older minor than the local install command suggests).
|
|
214
214
|
*/
|
|
215
|
-
export const SDK_VERSION = "0.7.
|
|
215
|
+
export const SDK_VERSION = "0.7.9";
|
|
216
216
|
export { NETWORKS, WORKER_REGISTRY, REGISTRY_TOPICS, aggregateModelStats, aggregateWorkerStats, networkAnalytics, modelStatsCsv, workerStatsCsv, workerJobsCsv, fromWei,
|
|
217
217
|
// v0.7.3 per-job transaction-hash resolver (lifts the upstream
|
|
218
218
|
// subgraph's "block-only" Job entity to a deep-linkable Job + tx pair).
|
package/dist/inference.js
CHANGED
|
@@ -75,35 +75,66 @@ export const JOB_REGISTRY_CONSUMER_ABI = [
|
|
|
75
75
|
*/
|
|
76
76
|
export async function prepareSession(gateway, modelTag) {
|
|
77
77
|
const id = modelId(modelTag);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
encWorkerKey: bytesToBase64(encWorker),
|
|
93
|
-
encDisputerKey: bytesToBase64(encDisputer),
|
|
94
|
-
});
|
|
95
|
-
return {
|
|
96
|
-
sessionKey,
|
|
97
|
-
nonce: prepared.nonce,
|
|
98
|
-
createSessionArgs: {
|
|
99
|
-
paramsHash: id,
|
|
100
|
-
worker: prepared.worker,
|
|
101
|
-
encWorkerKey: bytesToHex(encWorker),
|
|
102
|
-
ephemeralPubKey: bytesToHex(encDisputer),
|
|
103
|
-
initState: prepared.signature,
|
|
104
|
-
expiry: BigInt(prepared.expiry),
|
|
105
|
-
},
|
|
78
|
+
// The gateway returns 409 selection_mismatch when a NEWER selectSession()
|
|
79
|
+
// for the same wallet supersedes ours between the select and the prepare.
|
|
80
|
+
// The error message is literally "re-run POST /api/sessions/select", so we
|
|
81
|
+
// do exactly that: rebuild from a fresh selection. Backoff spans several
|
|
82
|
+
// seconds because the gateway's selection TTL can be in that range - quick
|
|
83
|
+
// retries inside that window just hit the same stuck state. Random jitter
|
|
84
|
+
// keeps two concurrent callers from synchronising on identical schedules.
|
|
85
|
+
const MAX_ATTEMPTS = 6;
|
|
86
|
+
const BACKOFFS_MS = [0, 500, 1500, 4000, 9000, 18000];
|
|
87
|
+
const jitter = (ms) => ms + Math.floor(Math.random() * 250);
|
|
88
|
+
let lastErr = null;
|
|
89
|
+
const isSelectionMismatch = (e) => {
|
|
90
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
91
|
+
return /selection_mismatch|selection was superseded|409/.test(msg);
|
|
106
92
|
};
|
|
93
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
94
|
+
if (attempt > 0)
|
|
95
|
+
await new Promise((r) => setTimeout(r, jitter(BACKOFFS_MS[attempt])));
|
|
96
|
+
try {
|
|
97
|
+
// Wrap BOTH gateway calls. selectSession itself can 409 if a newer
|
|
98
|
+
// call has already superseded ours by the time the gateway processes
|
|
99
|
+
// it. prepareSession 409s when the same happens between select and
|
|
100
|
+
// prepare. The whole select -> prepare flow is one atomic unit.
|
|
101
|
+
const selected = await gateway.selectSession(id);
|
|
102
|
+
const sessionKey = await generateSessionKey();
|
|
103
|
+
// Workers' pubkeys arrive as base64; disputer's as hex - decodePublicKey
|
|
104
|
+
// accepts either.
|
|
105
|
+
const workerPub = await importPublicKey(decodePublicKey(selected.workerEncryptionKey));
|
|
106
|
+
const encWorker = await encryptSessionKey(sessionKey, workerPub);
|
|
107
|
+
const encDisputer = selected.disputerEncryptionKey
|
|
108
|
+
? await encryptSessionKey(sessionKey, await importPublicKey(decodePublicKey(selected.disputerEncryptionKey)))
|
|
109
|
+
: new Uint8Array(0);
|
|
110
|
+
const prepared = await gateway.prepareSession({
|
|
111
|
+
modelId: id,
|
|
112
|
+
encWorkerKey: bytesToBase64(encWorker),
|
|
113
|
+
encDisputerKey: bytesToBase64(encDisputer),
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
sessionKey,
|
|
117
|
+
nonce: prepared.nonce,
|
|
118
|
+
createSessionArgs: {
|
|
119
|
+
paramsHash: id,
|
|
120
|
+
worker: prepared.worker,
|
|
121
|
+
encWorkerKey: bytesToHex(encWorker),
|
|
122
|
+
ephemeralPubKey: bytesToHex(encDisputer),
|
|
123
|
+
initState: prepared.signature,
|
|
124
|
+
expiry: BigInt(prepared.expiry),
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
lastErr = e;
|
|
130
|
+
if (!isSelectionMismatch(e))
|
|
131
|
+
throw e;
|
|
132
|
+
// else loop: a newer select stole this session, try again from select.
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
throw lastErr instanceof Error
|
|
136
|
+
? lastErr
|
|
137
|
+
: new Error("prepareSession: gateway selection_mismatch did not clear");
|
|
107
138
|
}
|
|
108
139
|
/**
|
|
109
140
|
* Encrypt a UTF-8 prompt with the session key, upload as a blob, and return
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lightnode-sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.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",
|