lightnode-sdk 0.7.4 → 0.7.6
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/dist/cli.js +33 -4
- package/dist/index.d.ts +14 -3
- package/dist/index.js +33 -2
- package/dist/onchain.d.ts +21 -4
- package/dist/onchain.js +105 -4
- package/dist/types.d.ts +19 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -49,6 +49,7 @@ Worker operator (needs PRIVATE_KEY in env; signs as the worker key):
|
|
|
49
49
|
worker preflight run one real test inference, print verdict + timings
|
|
50
50
|
([--key 0x...] [--model llama3-8b] [--deadline 60])
|
|
51
51
|
worker status [addr] registration, stake, claimable, live protocol config
|
|
52
|
+
worker models <addr> models served, reconciled vs chain (servingNow truth)
|
|
52
53
|
worker can-deregister check what blocks the exit (in-flight jobs), no spend
|
|
53
54
|
worker settle release completed jobs past their window + withdraw
|
|
54
55
|
worker clearstuck claimTimeout acked, past-deadline jobs (unblocks exit)
|
|
@@ -313,10 +314,38 @@ async function main() {
|
|
|
313
314
|
}
|
|
314
315
|
break;
|
|
315
316
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
317
|
+
if (sub === "models") {
|
|
318
|
+
// The models a worker serves, reconciled against the chain (read-only,
|
|
319
|
+
// no key). onchainEligible is the truth; indexedActive is the subgraph's
|
|
320
|
+
// (which goes stale after a deregister/re-register).
|
|
321
|
+
const addr = positionals[2] ?? die("usage: lightnode worker models <address> [--net testnet]");
|
|
322
|
+
const served = await ln.getServedModels(addr);
|
|
323
|
+
console.log(JSON.stringify(served.map((m) => ({
|
|
324
|
+
model: m.name ?? m.modelId,
|
|
325
|
+
servingNow: m.onchainEligible, // true | false | null (chain unavailable)
|
|
326
|
+
indexedActive: m.indexedActive,
|
|
327
|
+
feeLcai: m.feeWei ? Number(BigInt(m.feeWei)) / 1e18 : null,
|
|
328
|
+
maxOutputTokens: m.maxOutputTokens ?? null,
|
|
329
|
+
})), null, 2));
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
// Default: one-shot worker summary by address. Registration is read straight
|
|
333
|
+
// from the chain (isRegistered); served models are reconciled against the
|
|
334
|
+
// chain via getServedModels (onchainEligible), so a stale index row can't
|
|
335
|
+
// misreport what the worker actually serves.
|
|
336
|
+
const addr = sub ?? die("usage: lightnode worker <address|watch|preflight|status|models|can-deregister|settle|clearstuck|withdraw|deregister> [...]");
|
|
337
|
+
const [w, registered, jobs, served] = await Promise.all([
|
|
338
|
+
ln.getWorker(addr),
|
|
339
|
+
ln.isRegistered(addr),
|
|
340
|
+
ln.getWorkerJobs(addr, 5),
|
|
341
|
+
ln.getServedModels(addr).catch(() => []),
|
|
342
|
+
]);
|
|
343
|
+
console.log(JSON.stringify({
|
|
344
|
+
onchainRegistered: registered,
|
|
345
|
+
servingModels: served.filter((m) => m.onchainEligible === true).map((m) => m.name ?? m.modelId),
|
|
346
|
+
worker: w,
|
|
347
|
+
recentJobs: jobs.map((j) => ({ id: j.id, state: j.state })),
|
|
348
|
+
}, null, 2));
|
|
320
349
|
break;
|
|
321
350
|
}
|
|
322
351
|
case "job": {
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { OnchainModelRegistry, AIVM_MODEL_REGISTRY_ABI, BENCHMARK_REGISTRY_ABI,
|
|
|
13
13
|
import { StalledWorkerError, OnChainRevertError, RelayTokenTimeoutError, GatewayAuthError, isStalledWorker } from "./errors.js";
|
|
14
14
|
import { GatewayClient, GatewayHttpError } from "./gateway.js";
|
|
15
15
|
import * as crypto from "./crypto.js";
|
|
16
|
-
import type { NetworkId, NetworkConfig, Worker, Job, JobTransactions, ModelInfo, WorkerModel, NetworkStats, ModelStat, WorkerStat, NetworkAnalytics } from "./types.js";
|
|
16
|
+
import type { NetworkId, NetworkConfig, Worker, Job, JobTransactions, ModelInfo, WorkerModel, ServedModel, NetworkStats, ModelStat, WorkerStat, NetworkAnalytics } from "./types.js";
|
|
17
17
|
/**
|
|
18
18
|
* Read-only client for a LightChain AI network. Pure reads from the public indexer
|
|
19
19
|
* and the chain; no keys, no writes. Independent, community-built.
|
|
@@ -42,6 +42,17 @@ export declare class LightNode {
|
|
|
42
42
|
* whether the worker is currently serving them.
|
|
43
43
|
*/
|
|
44
44
|
getWorkerModels(address: string): Promise<WorkerModel[]>;
|
|
45
|
+
/**
|
|
46
|
+
* The models a worker is serving, RECONCILED against the chain. getWorkerModels
|
|
47
|
+
* returns the raw subgraph rows, which go stale after a deregister/re-register
|
|
48
|
+
* (the indexer never clears removals). This joins those rows to model names AND
|
|
49
|
+
* to the authoritative on-chain WorkerRegistry.isEligible(worker, modelId), so
|
|
50
|
+
* each `ServedModel` carries both `indexedActive` (subgraph) and
|
|
51
|
+
* `onchainEligible` (chain truth). Use `onchainEligible === true` to decide what
|
|
52
|
+
* the worker ACTUALLY serves right now; it falls back to null (rely on
|
|
53
|
+
* `indexedActive`) if the chain read is unavailable.
|
|
54
|
+
*/
|
|
55
|
+
getServedModels(address: string): Promise<ServedModel[]>;
|
|
45
56
|
/** The network's registered models (name, fee, output limit, whitelist flags). */
|
|
46
57
|
getModels(): Promise<ModelInfo[]>;
|
|
47
58
|
/** Registered workers (default top 200). */
|
|
@@ -122,7 +133,7 @@ export declare class LightNode {
|
|
|
122
133
|
* (especially in registry-proxy environments like StackBlitz where lockfiles
|
|
123
134
|
* may pin an older minor than the local install command suggests).
|
|
124
135
|
*/
|
|
125
|
-
export declare const SDK_VERSION = "0.7.
|
|
136
|
+
export declare const SDK_VERSION = "0.7.6";
|
|
126
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, };
|
|
127
138
|
export type { BearerSource, GatewayClientOptions, SelectSessionResult, PrepareSessionResult, UploadBlobResult, SessionTokenResult } from "./gateway.js";
|
|
128
139
|
export type { SessionPreparation, RunInferenceArgs, RunInferenceResult, RunInferenceWithKeyArgs, RunInferenceStreamResult } from "./inference.js";
|
|
@@ -134,4 +145,4 @@ export type { BridgeChain, BridgeEndpoints, BridgeTransferArgs } from "./bridge.
|
|
|
134
145
|
export type { DaoChain, DaoAddresses, ProposalSummary, ProposalRow, DaoConfig } from "./dao.js";
|
|
135
146
|
export type { BaseModel, ModelVariant, AccessTier, AccessPolicy, Benchmark, OnchainModelRegistryOptions } from "./onchain-models.js";
|
|
136
147
|
export type { MinimalWalletClient, MinimalPublicClient, WorkerOperatorOpts, WorkerProtocolConfig, WorkerStatus, DeregisterReadiness, StuckJob, EarningsBreakdown, OnchainJob, JobState, DecodedWorkerError, } from "./worker-operator.js";
|
|
137
|
-
export type { NetworkId, NetworkConfig, Worker, Job, JobTransactions, ModelInfo, WorkerModel, NetworkStats, ModelStat, WorkerStat, NetworkAnalytics };
|
|
148
|
+
export type { NetworkId, NetworkConfig, Worker, Job, JobTransactions, ModelInfo, WorkerModel, ServedModel, NetworkStats, ModelStat, WorkerStat, NetworkAnalytics };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NETWORKS, WORKER_REGISTRY, REGISTRY_TOPICS } from "./networks.js";
|
|
2
2
|
import { fetchWorker, fetchWorkerJobs, fetchWorkerModels, fetchRecentJobs, fetchJob, fetchModels, fetchWorkers, summarize, fromWei, resolveJobTransactions, } from "./subgraph.js";
|
|
3
|
-
import { isRegistered } from "./onchain.js";
|
|
3
|
+
import { isRegistered, fetchOnchainEligibleModels } from "./onchain.js";
|
|
4
4
|
import { aggregateModelStats, aggregateWorkerStats, networkAnalytics, modelStatsCsv, workerStatsCsv, workerJobsCsv, } from "./analytics.js";
|
|
5
5
|
import { modelId as computeModelId, estimateJobFee, JOB_REGISTRY_CONSUMER_ABI, consumerGatewayUrl, consumerGatewayHost, prepareSession, submitPrompt, decryptResponse, generateEcdhKeyPair, runInference, runInferenceWithKey, runInferenceStream, } from "./inference.js";
|
|
6
6
|
import { Conversation, chat } from "./chat.js";
|
|
@@ -51,6 +51,37 @@ export class LightNode {
|
|
|
51
51
|
getWorkerModels(address) {
|
|
52
52
|
return fetchWorkerModels(this.network, address);
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* The models a worker is serving, RECONCILED against the chain. getWorkerModels
|
|
56
|
+
* returns the raw subgraph rows, which go stale after a deregister/re-register
|
|
57
|
+
* (the indexer never clears removals). This joins those rows to model names AND
|
|
58
|
+
* to the authoritative on-chain WorkerRegistry.isEligible(worker, modelId), so
|
|
59
|
+
* each `ServedModel` carries both `indexedActive` (subgraph) and
|
|
60
|
+
* `onchainEligible` (chain truth). Use `onchainEligible === true` to decide what
|
|
61
|
+
* the worker ACTUALLY serves right now; it falls back to null (rely on
|
|
62
|
+
* `indexedActive`) if the chain read is unavailable.
|
|
63
|
+
*/
|
|
64
|
+
async getServedModels(address) {
|
|
65
|
+
const [rows, registry] = await Promise.all([
|
|
66
|
+
fetchWorkerModels(this.network, address),
|
|
67
|
+
fetchModels(this.network),
|
|
68
|
+
]);
|
|
69
|
+
if (rows.length === 0)
|
|
70
|
+
return [];
|
|
71
|
+
const byId = new Map(registry.map((m) => [m.id.toLowerCase(), m]));
|
|
72
|
+
const eligible = await fetchOnchainEligibleModels(this.network, address, rows.map((r) => r.model_id)).catch(() => null);
|
|
73
|
+
return rows.map((r) => {
|
|
74
|
+
const info = byId.get(r.model_id.toLowerCase());
|
|
75
|
+
return {
|
|
76
|
+
modelId: r.model_id,
|
|
77
|
+
name: info?.name ?? null,
|
|
78
|
+
feeWei: info?.fee,
|
|
79
|
+
maxOutputTokens: info?.max_output_tokens,
|
|
80
|
+
indexedActive: r.is_active,
|
|
81
|
+
onchainEligible: eligible ? (eligible.get(r.model_id.toLowerCase()) ?? null) : null,
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
}
|
|
54
85
|
/** The network's registered models (name, fee, output limit, whitelist flags). */
|
|
55
86
|
getModels() {
|
|
56
87
|
return fetchModels(this.network);
|
|
@@ -181,7 +212,7 @@ export class LightNode {
|
|
|
181
212
|
* (especially in registry-proxy environments like StackBlitz where lockfiles
|
|
182
213
|
* may pin an older minor than the local install command suggests).
|
|
183
214
|
*/
|
|
184
|
-
export const SDK_VERSION = "0.7.
|
|
215
|
+
export const SDK_VERSION = "0.7.6";
|
|
185
216
|
export { NETWORKS, WORKER_REGISTRY, REGISTRY_TOPICS, aggregateModelStats, aggregateWorkerStats, networkAnalytics, modelStatsCsv, workerStatsCsv, workerJobsCsv, fromWei,
|
|
186
217
|
// v0.7.3 per-job transaction-hash resolver (lifts the upstream
|
|
187
218
|
// subgraph's "block-only" Job entity to a deep-linkable Job + tx pair).
|
package/dist/onchain.d.ts
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import type { NetworkConfig } from "./types.js";
|
|
2
2
|
/**
|
|
3
|
-
* Authoritative worker registration
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* Authoritative worker registration from the chain. Prefers a direct
|
|
4
|
+
* WorkerRegistry.isWorkerRegistered() eth_call (instant, current state); falls
|
|
5
|
+
* back to scanning the join/exit event log if that read is unavailable. Both are
|
|
6
|
+
* independent of the public indexer, which can lag a deregister -> re-register
|
|
7
|
+
* cycle. Returns true/false, or null when the chain can't answer.
|
|
7
8
|
*/
|
|
8
9
|
export declare function isRegistered(cfg: NetworkConfig, address: string): Promise<boolean | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Registration from the WorkerRegistry join/exit event log - the fallback when
|
|
12
|
+
* the direct read is unavailable. Takes the latest of the worker's join/exit
|
|
13
|
+
* events; null when the chain can't answer or there are no events for it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isRegisteredFromEvents(cfg: NetworkConfig, address: string): Promise<boolean | null>;
|
|
16
|
+
/**
|
|
17
|
+
* On-chain truth for which of `modelIds` a worker currently serves, via
|
|
18
|
+
* WorkerRegistry.isEligible(worker, modelId). Stronger than the subgraph's
|
|
19
|
+
* WorkerModel.is_active: the indexer lists a worker's models from its LAST
|
|
20
|
+
* registration and never indexes removals, so it goes stale after a
|
|
21
|
+
* deregister/re-register (it can show a model the worker no longer serves, or
|
|
22
|
+
* miss the current one). Returns a Map keyed by lowercased modelId; null on any
|
|
23
|
+
* RPC failure so callers can fall back to the index. One eth_call per model.
|
|
24
|
+
*/
|
|
25
|
+
export declare function fetchOnchainEligibleModels(cfg: NetworkConfig, address: string, modelIds: string[]): Promise<Map<string, boolean> | null>;
|
package/dist/onchain.js
CHANGED
|
@@ -2,13 +2,63 @@ import { REGISTRY_TOPICS } from "./networks.js";
|
|
|
2
2
|
function addressTopic(address) {
|
|
3
3
|
return "0x" + address.toLowerCase().replace(/^0x/, "").padStart(64, "0");
|
|
4
4
|
}
|
|
5
|
+
// WorkerRegistry.isWorkerRegistered(address) selector. Unlike most of the
|
|
6
|
+
// predeploy's getters this view does NOT revert, and it reflects current state
|
|
7
|
+
// instantly - so it never lags a register/deregister the way the event log can
|
|
8
|
+
// when several happen in quick succession.
|
|
9
|
+
const IS_WORKER_REGISTERED_SELECTOR = "0xe798a7da";
|
|
5
10
|
/**
|
|
6
|
-
* Authoritative worker registration
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
11
|
+
* Authoritative worker registration from the chain. Prefers a direct
|
|
12
|
+
* WorkerRegistry.isWorkerRegistered() eth_call (instant, current state); falls
|
|
13
|
+
* back to scanning the join/exit event log if that read is unavailable. Both are
|
|
14
|
+
* independent of the public indexer, which can lag a deregister -> re-register
|
|
15
|
+
* cycle. Returns true/false, or null when the chain can't answer.
|
|
10
16
|
*/
|
|
11
17
|
export async function isRegistered(cfg, address) {
|
|
18
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(address))
|
|
19
|
+
return null;
|
|
20
|
+
const direct = await isRegisteredDirect(cfg, address);
|
|
21
|
+
if (direct !== null)
|
|
22
|
+
return direct;
|
|
23
|
+
return isRegisteredFromEvents(cfg, address);
|
|
24
|
+
}
|
|
25
|
+
/** Direct contract read - the preferred, lag-free path. null on any failure. */
|
|
26
|
+
async function isRegisteredDirect(cfg, address) {
|
|
27
|
+
const ctrl = new AbortController();
|
|
28
|
+
const timer = setTimeout(() => ctrl.abort(), 8000);
|
|
29
|
+
try {
|
|
30
|
+
const data = `${IS_WORKER_REGISTERED_SELECTOR}${address.toLowerCase().replace(/^0x/, "").padStart(64, "0")}`;
|
|
31
|
+
const res = await fetch(cfg.rpc, {
|
|
32
|
+
method: "POST",
|
|
33
|
+
headers: { "content-type": "application/json" },
|
|
34
|
+
body: JSON.stringify({
|
|
35
|
+
jsonrpc: "2.0",
|
|
36
|
+
id: 1,
|
|
37
|
+
method: "eth_call",
|
|
38
|
+
params: [{ to: cfg.workerRegistry, data }, "latest"],
|
|
39
|
+
}),
|
|
40
|
+
signal: ctrl.signal,
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok)
|
|
43
|
+
return null;
|
|
44
|
+
const json = (await res.json());
|
|
45
|
+
if (json.error || typeof json.result !== "string")
|
|
46
|
+
return null;
|
|
47
|
+
return /0*1$/.test(json.result.replace(/^0x/, ""));
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Registration from the WorkerRegistry join/exit event log - the fallback when
|
|
58
|
+
* the direct read is unavailable. Takes the latest of the worker's join/exit
|
|
59
|
+
* events; null when the chain can't answer or there are no events for it.
|
|
60
|
+
*/
|
|
61
|
+
export async function isRegisteredFromEvents(cfg, address) {
|
|
12
62
|
if (!/^0x[a-fA-F0-9]{40}$/.test(address))
|
|
13
63
|
return null;
|
|
14
64
|
const ctrl = new AbortController();
|
|
@@ -55,3 +105,54 @@ export async function isRegistered(cfg, address) {
|
|
|
55
105
|
clearTimeout(timer);
|
|
56
106
|
}
|
|
57
107
|
}
|
|
108
|
+
// WorkerRegistry.isEligible(address,bytes32) selector. This view does NOT revert
|
|
109
|
+
// on the deployed predeploy (unlike most of its getters), so it's a reliable
|
|
110
|
+
// on-chain read of whether a worker currently serves a given model.
|
|
111
|
+
const IS_ELIGIBLE_SELECTOR = "0xdb3ebef1";
|
|
112
|
+
/**
|
|
113
|
+
* On-chain truth for which of `modelIds` a worker currently serves, via
|
|
114
|
+
* WorkerRegistry.isEligible(worker, modelId). Stronger than the subgraph's
|
|
115
|
+
* WorkerModel.is_active: the indexer lists a worker's models from its LAST
|
|
116
|
+
* registration and never indexes removals, so it goes stale after a
|
|
117
|
+
* deregister/re-register (it can show a model the worker no longer serves, or
|
|
118
|
+
* miss the current one). Returns a Map keyed by lowercased modelId; null on any
|
|
119
|
+
* RPC failure so callers can fall back to the index. One eth_call per model.
|
|
120
|
+
*/
|
|
121
|
+
export async function fetchOnchainEligibleModels(cfg, address, modelIds) {
|
|
122
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(address) || modelIds.length === 0)
|
|
123
|
+
return null;
|
|
124
|
+
const addrArg = address.toLowerCase().replace(/^0x/, "").padStart(64, "0");
|
|
125
|
+
const ctrl = new AbortController();
|
|
126
|
+
const timer = setTimeout(() => ctrl.abort(), 8000);
|
|
127
|
+
try {
|
|
128
|
+
const entries = await Promise.all(modelIds.map(async (id) => {
|
|
129
|
+
const idArg = id.toLowerCase().replace(/^0x/, "").padStart(64, "0");
|
|
130
|
+
const res = await fetch(cfg.rpc, {
|
|
131
|
+
method: "POST",
|
|
132
|
+
headers: { "content-type": "application/json" },
|
|
133
|
+
body: JSON.stringify({
|
|
134
|
+
jsonrpc: "2.0",
|
|
135
|
+
id: 1,
|
|
136
|
+
method: "eth_call",
|
|
137
|
+
params: [{ to: cfg.workerRegistry, data: `${IS_ELIGIBLE_SELECTOR}${addrArg}${idArg}` }, "latest"],
|
|
138
|
+
}),
|
|
139
|
+
signal: ctrl.signal,
|
|
140
|
+
});
|
|
141
|
+
if (!res.ok)
|
|
142
|
+
throw new Error(`rpc ${res.status}`);
|
|
143
|
+
const json = (await res.json());
|
|
144
|
+
if (json.error || typeof json.result !== "string")
|
|
145
|
+
throw new Error("eth_call failed");
|
|
146
|
+
// bool return: true iff the 32-byte word ends in 1.
|
|
147
|
+
const eligible = /0*1$/.test(json.result.replace(/^0x/, ""));
|
|
148
|
+
return [id.toLowerCase(), eligible];
|
|
149
|
+
}));
|
|
150
|
+
return new Map(entries);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
clearTimeout(timer);
|
|
157
|
+
}
|
|
158
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -78,6 +78,25 @@ export interface WorkerModel {
|
|
|
78
78
|
created_at?: number;
|
|
79
79
|
updated_at?: number;
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* A worker's served model, reconciled against the chain. Combines the subgraph
|
|
83
|
+
* WorkerModel row (name, is_active) with the authoritative on-chain
|
|
84
|
+
* WorkerRegistry.isEligible read, so you can tell a model the worker ACTUALLY
|
|
85
|
+
* serves now from a stale index row left over after a deregister/re-register.
|
|
86
|
+
*/
|
|
87
|
+
export interface ServedModel {
|
|
88
|
+
modelId: string;
|
|
89
|
+
name: string | null;
|
|
90
|
+
feeWei?: string;
|
|
91
|
+
maxOutputTokens?: number;
|
|
92
|
+
/** Subgraph WorkerModel.is_active (can be stale after deregister/re-register). */
|
|
93
|
+
indexedActive: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* On-chain WorkerRegistry.isEligible(worker, modelId) - the authoritative
|
|
96
|
+
* "is it serving this right now". null when the chain read was unavailable.
|
|
97
|
+
*/
|
|
98
|
+
onchainEligible: boolean | null;
|
|
99
|
+
}
|
|
81
100
|
export interface NetworkStats {
|
|
82
101
|
total: number;
|
|
83
102
|
active: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lightnode-sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.6",
|
|
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",
|