lightnode-sdk 0.8.10 → 0.9.1
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/add.js +44 -21
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -1
- package/dist/inference.d.ts +66 -0
- package/dist/inference.js +92 -11
- package/package.json +1 -1
package/dist/add.js
CHANGED
|
@@ -963,7 +963,7 @@ const NEXTJS_CHAT_WEB3_PAGE = `// app/chat-web3/page.tsx
|
|
|
963
963
|
|
|
964
964
|
import { useEffect, useRef, useState } from "react";
|
|
965
965
|
import { useAccount, useWalletClient, usePublicClient } from "wagmi";
|
|
966
|
-
import { siweSignIn, GatewayClient,
|
|
966
|
+
import { siweSignIn, GatewayClient, LightChatSession, estimateJobFee, NETWORKS } from "lightnode-sdk";
|
|
967
967
|
import { Streamdown } from "streamdown";
|
|
968
968
|
import { ConnectButton } from "@/components/connect-button";
|
|
969
969
|
import { LcaiMark } from "@/components/lcai-mark";
|
|
@@ -997,6 +997,9 @@ export default function ChatWeb3() {
|
|
|
997
997
|
const [err, setErr] = useState<string | null>(null);
|
|
998
998
|
const [feeLcai, setFeeLcai] = useState<number | null>(null);
|
|
999
999
|
const endRef = useRef<HTMLDivElement>(null);
|
|
1000
|
+
// Reused across turns so follow-ups skip SIWE + createSession.
|
|
1001
|
+
const sessionRef = useRef<LightChatSession | null>(null);
|
|
1002
|
+
const sessionKeyRef = useRef<string>("");
|
|
1000
1003
|
|
|
1001
1004
|
// Read the on-chain fee for the connected network so we can show the
|
|
1002
1005
|
// visitor the real cost per turn before they click Send.
|
|
@@ -1037,6 +1040,31 @@ export default function ChatWeb3() {
|
|
|
1037
1040
|
});
|
|
1038
1041
|
}
|
|
1039
1042
|
|
|
1043
|
+
/**
|
|
1044
|
+
* Open a session on the first turn (or after expiry / a model or wallet
|
|
1045
|
+
* change), then reuse it so every follow-up turn skips SIWE + createSession.
|
|
1046
|
+
*/
|
|
1047
|
+
async function ensureSession(): Promise<LightChatSession> {
|
|
1048
|
+
if (!walletClient || !publicClient || !address || !network) throw new Error("connect a wallet first");
|
|
1049
|
+
const key = \`\${address}:\${network}:\${model}\`;
|
|
1050
|
+
const existing = sessionRef.current;
|
|
1051
|
+
if (existing && !existing.expired && sessionKeyRef.current === key) return existing;
|
|
1052
|
+
setBusyStage("Sign in with your wallet (SIWE)...");
|
|
1053
|
+
const siwe = await siweSignIn(walletClient as unknown as Parameters<typeof siweSignIn>[0], network);
|
|
1054
|
+
setBusyStage("Approve createSession in your wallet (one-time per session)...");
|
|
1055
|
+
const gateway = new GatewayClient({ network, bearer: siwe.bearer });
|
|
1056
|
+
const chat = await LightChatSession.open({
|
|
1057
|
+
gateway,
|
|
1058
|
+
wallet: walletClient as unknown as Parameters<typeof LightChatSession.open>[0]["wallet"],
|
|
1059
|
+
publicClient: publicClient as unknown as Parameters<typeof LightChatSession.open>[0]["publicClient"],
|
|
1060
|
+
network: NETWORKS[network],
|
|
1061
|
+
model,
|
|
1062
|
+
});
|
|
1063
|
+
sessionRef.current = chat;
|
|
1064
|
+
sessionKeyRef.current = key;
|
|
1065
|
+
return chat;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1040
1068
|
async function send() {
|
|
1041
1069
|
if (!walletClient || !publicClient || !address || !network) {
|
|
1042
1070
|
setErr("Connect a wallet on LightChain mainnet (9200) or testnet (8200) first.");
|
|
@@ -1053,26 +1081,21 @@ export default function ChatWeb3() {
|
|
|
1053
1081
|
try {
|
|
1054
1082
|
const system = "You are a concise assistant. Reply in one or two short sentences.";
|
|
1055
1083
|
const prompt = composePrompt(history, next, system);
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
const
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
// Stream each decrypted chunk into the assistant bubble as it arrives.
|
|
1072
|
-
onChunk: (_chunk, totalSoFar) => {
|
|
1073
|
-
setBusyStage("");
|
|
1074
|
-
patchLastAssistant({ text: totalSoFar });
|
|
1075
|
-
},
|
|
1084
|
+
const onChunk = (_chunk: string, totalSoFar: string) => {
|
|
1085
|
+
setBusyStage("");
|
|
1086
|
+
patchLastAssistant({ text: totalSoFar });
|
|
1087
|
+
};
|
|
1088
|
+
|
|
1089
|
+
const chat = await ensureSession();
|
|
1090
|
+
setBusyStage("Approve the per-turn transaction in your wallet...");
|
|
1091
|
+
const result = await chat.send(prompt, { onChunk }).catch(async () => {
|
|
1092
|
+
// Session expired or the worker stopped serving - reopen once and retry.
|
|
1093
|
+
sessionRef.current = null;
|
|
1094
|
+
patchLastAssistant({ text: "" });
|
|
1095
|
+
setBusyStage("Re-opening session...");
|
|
1096
|
+
const fresh = await ensureSession();
|
|
1097
|
+
setBusyStage("Approve the per-turn transaction in your wallet...");
|
|
1098
|
+
return fresh.send(prompt, { onChunk });
|
|
1076
1099
|
});
|
|
1077
1100
|
|
|
1078
1101
|
patchLastAssistant({
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NETWORKS, WORKER_REGISTRY, REGISTRY_TOPICS } from "./networks.js";
|
|
2
2
|
import { fetchWorkerModels, fromWei, resolveJobTransactions } from "./subgraph.js";
|
|
3
3
|
import { aggregateModelStats, aggregateWorkerStats, networkAnalytics, modelStatsCsv, workerStatsCsv, workerJobsCsv } from "./analytics.js";
|
|
4
|
-
import { modelId as computeModelId, estimateJobFee, JOB_REGISTRY_CONSUMER_ABI, consumerGatewayUrl, consumerGatewayHost, prepareSession, submitPrompt, decryptResponse, generateEcdhKeyPair, runInference, runInferenceWithKey, runInferenceStream } from "./inference.js";
|
|
4
|
+
import { modelId as computeModelId, estimateJobFee, JOB_REGISTRY_CONSUMER_ABI, consumerGatewayUrl, consumerGatewayHost, prepareSession, submitPrompt, decryptResponse, generateEcdhKeyPair, runInference, runInferenceWithKey, runInferenceStream, openSession, runJobOnSession, LightChatSession } from "./inference.js";
|
|
5
5
|
import { Conversation, chat } from "./chat.js";
|
|
6
6
|
import { runInferenceBatch } from "./batch.js";
|
|
7
7
|
import { Agent, parseAgentOutput } from "./agent.js";
|
|
@@ -135,7 +135,7 @@ export declare class LightNode {
|
|
|
135
135
|
* may pin an older minor than the local install command suggests).
|
|
136
136
|
*/
|
|
137
137
|
export declare const SDK_VERSION = "0.7.20";
|
|
138
|
-
export { NETWORKS, WORKER_REGISTRY, REGISTRY_TOPICS, aggregateModelStats, aggregateWorkerStats, networkAnalytics, modelStatsCsv, workerStatsCsv, workerJobsCsv, fromWei, resolveJobTransactions, siweSignIn, siweChallenge, siweVerify, 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
|
+
export { NETWORKS, WORKER_REGISTRY, REGISTRY_TOPICS, aggregateModelStats, aggregateWorkerStats, networkAnalytics, modelStatsCsv, workerStatsCsv, workerJobsCsv, fromWei, resolveJobTransactions, siweSignIn, siweChallenge, siweVerify, fetchWorkerModels, computeModelId as modelId, estimateJobFee, JOB_REGISTRY_CONSUMER_ABI, consumerGatewayUrl, consumerGatewayHost, GatewayClient, GatewayHttpError, prepareSession, submitPrompt, decryptResponse, generateEcdhKeyPair, crypto, runInference, runInferenceWithKey, runInferenceStream, openSession, runJobOnSession, LightChatSession, 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, };
|
|
139
139
|
export type { BearerSource, GatewayClientOptions, SelectSessionResult, PrepareSessionResult, UploadBlobResult, SessionTokenResult } from "./gateway.js";
|
|
140
140
|
export type { SessionPreparation, RunInferenceArgs, RunInferenceResult, RunInferenceWithKeyArgs, RunInferenceStreamResult } from "./inference.js";
|
|
141
141
|
export type { ChatRole, ChatMessage, ConversationOptions, ConversationSendResult } from "./chat.js";
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ 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
3
|
import { isRegistered, fetchOnchainEligibleModels } from "./onchain.js";
|
|
4
4
|
import { aggregateModelStats, aggregateWorkerStats, networkAnalytics, modelStatsCsv, workerStatsCsv, workerJobsCsv, } from "./analytics.js";
|
|
5
|
-
import { modelId as computeModelId, estimateJobFee, JOB_REGISTRY_CONSUMER_ABI, consumerGatewayUrl, consumerGatewayHost, prepareSession, submitPrompt, decryptResponse, generateEcdhKeyPair, runInference, runInferenceWithKey, runInferenceStream, } from "./inference.js";
|
|
5
|
+
import { modelId as computeModelId, estimateJobFee, JOB_REGISTRY_CONSUMER_ABI, consumerGatewayUrl, consumerGatewayHost, prepareSession, submitPrompt, decryptResponse, generateEcdhKeyPair, runInference, runInferenceWithKey, runInferenceStream, openSession, runJobOnSession, LightChatSession, } from "./inference.js";
|
|
6
6
|
import { Conversation, chat } from "./chat.js";
|
|
7
7
|
import { runInferenceBatch } from "./batch.js";
|
|
8
8
|
import { Agent, parseAgentOutput } from "./agent.js";
|
|
@@ -233,6 +233,8 @@ runInference,
|
|
|
233
233
|
runInferenceWithKey,
|
|
234
234
|
// v0.4.9 AsyncIterable<string> wrapper around runInferenceWithKey.
|
|
235
235
|
runInferenceStream,
|
|
236
|
+
// v0.9.0 session reuse: open once, run many jobs (follow-ups skip createSession).
|
|
237
|
+
openSession, runJobOnSession, LightChatSession,
|
|
236
238
|
// v0.5.0 multi-turn conversation helper (history client-side; one inference per turn).
|
|
237
239
|
Conversation, chat,
|
|
238
240
|
// v0.6.0 batch runner: many prompts, capped parallelism, stable result order.
|
package/dist/inference.d.ts
CHANGED
|
@@ -204,6 +204,72 @@ export interface RunInferenceResult {
|
|
|
204
204
|
submitTx: `0x${string}`;
|
|
205
205
|
}>;
|
|
206
206
|
}
|
|
207
|
+
/** A live, on-chain session. Open once, then run many jobs through it - each
|
|
208
|
+
* follow-up turn skips SIWE + createSession, leaving just the submitJob tx. */
|
|
209
|
+
export interface OpenSession {
|
|
210
|
+
readonly gateway: GatewayClient;
|
|
211
|
+
readonly wallet: MinimalWalletClient;
|
|
212
|
+
readonly publicClient: MinimalPublicClient;
|
|
213
|
+
readonly network: NetworkConfig;
|
|
214
|
+
readonly model: string;
|
|
215
|
+
readonly fee: number;
|
|
216
|
+
readonly sessionId: bigint;
|
|
217
|
+
readonly sessionKey: Uint8Array;
|
|
218
|
+
readonly worker: `0x${string}`;
|
|
219
|
+
readonly createTx: `0x${string}`;
|
|
220
|
+
/** Unix seconds when the on-chain session window closes. */
|
|
221
|
+
readonly expirySec: number;
|
|
222
|
+
}
|
|
223
|
+
export interface OpenSessionArgs {
|
|
224
|
+
gateway: GatewayClient;
|
|
225
|
+
wallet: MinimalWalletClient;
|
|
226
|
+
publicClient: MinimalPublicClient;
|
|
227
|
+
network: NetworkConfig;
|
|
228
|
+
model?: string;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* prepareSession + the on-chain createSession tx. Do this once, then run many
|
|
232
|
+
* jobs through the handle with `runJobOnSession`. Re-open when `expirySec`
|
|
233
|
+
* passes or the chosen worker stops serving.
|
|
234
|
+
*/
|
|
235
|
+
export declare function openSession(args: OpenSessionArgs): Promise<OpenSession>;
|
|
236
|
+
export interface RunJobOpts {
|
|
237
|
+
onChunk?: (chunk: string, totalSoFar: string) => void;
|
|
238
|
+
jobCompletedTimeoutMs?: number;
|
|
239
|
+
WebSocket?: WebSocketCtor;
|
|
240
|
+
relayUrl?: string;
|
|
241
|
+
signal?: AbortSignal;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Run ONE job against an already-open session: submitPrompt + submitJob + relay
|
|
245
|
+
* stream + wait for JobCompleted. No SIWE, no createSession.
|
|
246
|
+
*/
|
|
247
|
+
export declare function runJobOnSession(session: OpenSession, prompt: string, opts?: RunJobOpts, attempt?: number): Promise<RunInferenceResult>;
|
|
248
|
+
/**
|
|
249
|
+
* A reusable, wallet-signed inference session. Open it once (SIWE happens before
|
|
250
|
+
* this; createSession happens here), then call `.send()` per turn - each
|
|
251
|
+
* follow-up turn skips createSession, leaving just the submitJob tx. Re-open
|
|
252
|
+
* (call `LightChatSession.open(...)` again) when `expired` is true or a
|
|
253
|
+
* `.send()` throws because the worker stopped serving.
|
|
254
|
+
*
|
|
255
|
+
* @example
|
|
256
|
+
* ```ts
|
|
257
|
+
* const session = await LightChatSession.open({ gateway, wallet, publicClient, network, model: "llama3-8b" });
|
|
258
|
+
* const a = await session.send("Who wrote The Great Gatsby?", { onChunk });
|
|
259
|
+
* const b = await session.send("In what year?", { onChunk }); // no createSession
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
export declare class LightChatSession {
|
|
263
|
+
private readonly session;
|
|
264
|
+
private constructor();
|
|
265
|
+
static open(args: OpenSessionArgs): Promise<LightChatSession>;
|
|
266
|
+
get sessionId(): bigint;
|
|
267
|
+
get worker(): `0x${string}`;
|
|
268
|
+
get model(): string;
|
|
269
|
+
/** true once the on-chain session window has closed; re-open before sending. */
|
|
270
|
+
get expired(): boolean;
|
|
271
|
+
send(prompt: string, opts?: RunJobOpts): Promise<RunInferenceResult>;
|
|
272
|
+
}
|
|
207
273
|
/**
|
|
208
274
|
* One call, full encrypted inference. Same code path the live playground at
|
|
209
275
|
* lightnode.app/playground drives, condensed into a single function.
|
package/dist/inference.js
CHANGED
|
@@ -228,14 +228,15 @@ function pickWebSocket(provided) {
|
|
|
228
228
|
function topicAsUint(hex) {
|
|
229
229
|
return BigInt(hex);
|
|
230
230
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
/**
|
|
232
|
+
* prepareSession + the on-chain createSession tx. Do this once, then run many
|
|
233
|
+
* jobs through the handle with `runJobOnSession`. Re-open when `expirySec`
|
|
234
|
+
* passes or the chosen worker stops serving.
|
|
235
|
+
*/
|
|
236
|
+
export async function openSession(args) {
|
|
237
|
+
const { gateway, wallet, publicClient, network, model = "llama3-8b" } = args;
|
|
236
238
|
const prepared = await prepareSession(gateway, model);
|
|
237
239
|
const fee = await estimateJobFee(network, model);
|
|
238
|
-
// 2. createSession on-chain
|
|
239
240
|
const createTx = await wallet.writeContract({
|
|
240
241
|
address: network.jobRegistry,
|
|
241
242
|
abi: JOB_REGISTRY_ABI_PARSED,
|
|
@@ -256,15 +257,48 @@ async function runOneAttempt(args, attempt) {
|
|
|
256
257
|
const createLog = (await publicClient.getLogs({ address: network.jobRegistry, blockHash: createReceipt.blockHash })).find((l) => l.transactionHash === createTx && l.topics[0] === SESSION_CREATED_TOPIC);
|
|
257
258
|
if (!createLog)
|
|
258
259
|
throw new Error("SessionCreated log missing in createSession receipt");
|
|
259
|
-
|
|
260
|
+
return {
|
|
261
|
+
gateway,
|
|
262
|
+
wallet,
|
|
263
|
+
publicClient,
|
|
264
|
+
network,
|
|
265
|
+
model,
|
|
266
|
+
fee,
|
|
267
|
+
sessionId: topicAsUint(createLog.topics[1]),
|
|
268
|
+
sessionKey: prepared.sessionKey,
|
|
269
|
+
worker: prepared.createSessionArgs.worker,
|
|
270
|
+
createTx,
|
|
271
|
+
expirySec: Number(prepared.createSessionArgs.expiry),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Run ONE job against an already-open session: submitPrompt + submitJob + relay
|
|
276
|
+
* stream + wait for JobCompleted. No SIWE, no createSession.
|
|
277
|
+
*/
|
|
278
|
+
export async function runJobOnSession(session, prompt, opts = {}, attempt = 1) {
|
|
279
|
+
const { gateway, wallet, publicClient, network, sessionId, sessionKey, worker, fee, createTx } = session;
|
|
280
|
+
const { onChunk, jobCompletedTimeoutMs = 120000 } = opts;
|
|
281
|
+
const WS = pickWebSocket(opts.WebSocket);
|
|
282
|
+
const relayUrl = opts.relayUrl ?? `wss://relay.${network.id}.lightchain.ai/ws`;
|
|
283
|
+
// Shim so the job body below can keep referencing prepared.* unchanged.
|
|
284
|
+
const prepared = { sessionKey, createSessionArgs: { worker } };
|
|
260
285
|
// 3. relay token + WebSocket
|
|
286
|
+
// Poll the gateway for the relay token with a fast backoff (it's usually ready
|
|
287
|
+
// within ~1s of createSession). Catch it sooner than a fixed 1s interval, and
|
|
288
|
+
// cap the total at a 20s deadline instead of 30 fixed iterations.
|
|
261
289
|
let relayToken;
|
|
262
|
-
|
|
290
|
+
const tokenDeadline = Date.now() + 20000;
|
|
291
|
+
let tokenDelay = 250;
|
|
292
|
+
while (!relayToken) {
|
|
263
293
|
const r = await gateway.getSessionToken(Number(sessionId));
|
|
264
|
-
if ("token" in r && r.token)
|
|
294
|
+
if ("token" in r && r.token) {
|
|
265
295
|
relayToken = r.token;
|
|
266
|
-
|
|
267
|
-
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
if (Date.now() >= tokenDeadline)
|
|
299
|
+
break;
|
|
300
|
+
await new Promise((res) => setTimeout(res, tokenDelay));
|
|
301
|
+
tokenDelay = Math.min(tokenDelay * 2, 2000);
|
|
268
302
|
}
|
|
269
303
|
if (!relayToken)
|
|
270
304
|
throw new RelayTokenTimeoutError();
|
|
@@ -451,6 +485,53 @@ async function runOneAttempt(args, attempt) {
|
|
|
451
485
|
stalled: [],
|
|
452
486
|
};
|
|
453
487
|
}
|
|
488
|
+
/** One attempt = open a fresh session, then run one job through it. */
|
|
489
|
+
async function runOneAttempt(args, attempt) {
|
|
490
|
+
const session = await openSession({
|
|
491
|
+
gateway: args.gateway,
|
|
492
|
+
wallet: args.wallet,
|
|
493
|
+
publicClient: args.publicClient,
|
|
494
|
+
network: args.network,
|
|
495
|
+
model: args.model,
|
|
496
|
+
});
|
|
497
|
+
return runJobOnSession(session, args.prompt, {
|
|
498
|
+
onChunk: args.onChunk,
|
|
499
|
+
jobCompletedTimeoutMs: args.jobCompletedTimeoutMs,
|
|
500
|
+
WebSocket: args.WebSocket,
|
|
501
|
+
relayUrl: args.relayUrl,
|
|
502
|
+
signal: args.signal,
|
|
503
|
+
}, attempt);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* A reusable, wallet-signed inference session. Open it once (SIWE happens before
|
|
507
|
+
* this; createSession happens here), then call `.send()` per turn - each
|
|
508
|
+
* follow-up turn skips createSession, leaving just the submitJob tx. Re-open
|
|
509
|
+
* (call `LightChatSession.open(...)` again) when `expired` is true or a
|
|
510
|
+
* `.send()` throws because the worker stopped serving.
|
|
511
|
+
*
|
|
512
|
+
* @example
|
|
513
|
+
* ```ts
|
|
514
|
+
* const session = await LightChatSession.open({ gateway, wallet, publicClient, network, model: "llama3-8b" });
|
|
515
|
+
* const a = await session.send("Who wrote The Great Gatsby?", { onChunk });
|
|
516
|
+
* const b = await session.send("In what year?", { onChunk }); // no createSession
|
|
517
|
+
* ```
|
|
518
|
+
*/
|
|
519
|
+
export class LightChatSession {
|
|
520
|
+
constructor(session) {
|
|
521
|
+
this.session = session;
|
|
522
|
+
}
|
|
523
|
+
static async open(args) {
|
|
524
|
+
return new LightChatSession(await openSession(args));
|
|
525
|
+
}
|
|
526
|
+
get sessionId() { return this.session.sessionId; }
|
|
527
|
+
get worker() { return this.session.worker; }
|
|
528
|
+
get model() { return this.session.model; }
|
|
529
|
+
/** true once the on-chain session window has closed; re-open before sending. */
|
|
530
|
+
get expired() { return Date.now() / 1000 >= this.session.expirySec; }
|
|
531
|
+
send(prompt, opts = {}) {
|
|
532
|
+
return runJobOnSession(this.session, prompt, opts);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
454
535
|
/**
|
|
455
536
|
* One call, full encrypted inference. Same code path the live playground at
|
|
456
537
|
* lightnode.app/playground drives, condensed into a single function.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lightnode-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
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",
|