@halot/sdk 1.0.2 → 1.0.4
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 +28 -35
- package/dist/network-config.d.ts +2 -0
- package/dist/network-config.js +13 -0
- package/dist/types/verifier.d.ts +4 -3
- package/dist/types/verifier.js +5 -6
- package/dist/zero-g/compute.d.ts +11 -4
- package/dist/zero-g/compute.js +37 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ against the Halot facilitator endpoints.
|
|
|
45
45
|
|
|
46
46
|
### Before you use it
|
|
47
47
|
|
|
48
|
-
The route must use a real registered `serviceId
|
|
48
|
+
The route must use a real registered `serviceId` and provider-signed report headers.
|
|
49
49
|
|
|
50
50
|
The actual order is:
|
|
51
51
|
|
|
@@ -59,18 +59,37 @@ If you are using middleware for a service, you do not need `halot provider run`
|
|
|
59
59
|
|
|
60
60
|
```ts
|
|
61
61
|
import express from 'express';
|
|
62
|
-
import {
|
|
62
|
+
import { Wallet } from 'ethers';
|
|
63
|
+
import { createActorAuthHeaders, halot, nowIso } from '@halot/sdk';
|
|
63
64
|
|
|
64
65
|
const app = express();
|
|
65
66
|
app.use(express.json());
|
|
66
67
|
|
|
68
|
+
const providerId = process.env.HALOT_PROVIDER_ID!;
|
|
69
|
+
const providerWallet = new Wallet(process.env.HALOT_PROVIDER_PRIVATE_KEY!);
|
|
70
|
+
|
|
71
|
+
const providerHeaders = async (_req, context) => {
|
|
72
|
+
if (context.providerId !== providerId) {
|
|
73
|
+
throw new Error(`Assigned provider ${context.providerId} does not match configured provider ${providerId}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return createActorAuthHeaders(providerWallet, {
|
|
77
|
+
actorId: providerId,
|
|
78
|
+
role: 'provider',
|
|
79
|
+
method: 'POST',
|
|
80
|
+
path: '/facilitator/report',
|
|
81
|
+
timestamp: nowIso(),
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
67
85
|
app.post('/text', halot({
|
|
68
86
|
serviceId: 'svc_text_gpt54',
|
|
87
|
+
providerHeaders,
|
|
69
88
|
}), async (req, res) => {
|
|
70
|
-
const { jobId, providerId, requesterAddress } = req.halot;
|
|
89
|
+
const { jobId, providerId: assignedProviderId, requesterAddress } = req.halot;
|
|
71
90
|
const text = await runProviderLogic(req.body.message, {
|
|
72
91
|
jobId,
|
|
73
|
-
providerId,
|
|
92
|
+
providerId: assignedProviderId,
|
|
74
93
|
requesterAddress,
|
|
75
94
|
});
|
|
76
95
|
|
|
@@ -78,6 +97,8 @@ app.post('/text', halot({
|
|
|
78
97
|
});
|
|
79
98
|
```
|
|
80
99
|
|
|
100
|
+
`HALOT_PROVIDER_ID` is the provider ID returned by provider registration. `HALOT_PROVIDER_PRIVATE_KEY` is the private key for that provider actor authority. You can load those values from a secret manager or the CLI-generated authority file instead of env; the important part is that `/facilitator/report` is signed by the same provider actor that owns the registered service.
|
|
101
|
+
|
|
81
102
|
### One route, multiple services
|
|
82
103
|
|
|
83
104
|
If one route fronts multiple registered services, resolve `serviceId` from the request:
|
|
@@ -90,47 +111,19 @@ app.post('/text', halot({
|
|
|
90
111
|
return 'svc_text_gpt54';
|
|
91
112
|
case 'gpt-5.4-mini':
|
|
92
113
|
return 'svc_text_gpt54mini';
|
|
114
|
+
case 'gpt-5.4-nano':
|
|
115
|
+
return 'svc_text_gpt54nano';
|
|
93
116
|
default:
|
|
94
117
|
throw new Error('Unsupported model');
|
|
95
118
|
}
|
|
96
119
|
},
|
|
120
|
+
providerHeaders,
|
|
97
121
|
}), async (req, res) => {
|
|
98
122
|
const text = await runProviderLogic(req.body.message);
|
|
99
123
|
res.json({ text, model: req.body.model });
|
|
100
124
|
});
|
|
101
125
|
```
|
|
102
126
|
|
|
103
|
-
### Signing facilitator report requests
|
|
104
|
-
|
|
105
|
-
Use `providerHeaders` when your provider app needs to sign `/facilitator/report` as the registered provider:
|
|
106
|
-
|
|
107
|
-
```ts
|
|
108
|
-
import express from 'express';
|
|
109
|
-
import { createActorAuthHeaders, halot } from '@halot/sdk';
|
|
110
|
-
|
|
111
|
-
const app = express();
|
|
112
|
-
app.use(express.json());
|
|
113
|
-
|
|
114
|
-
const providerWallet = {
|
|
115
|
-
address: process.env.PROVIDER_ADDRESS!,
|
|
116
|
-
signMessage: async (message: string) => signWithWallet(message),
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
app.post('/text', halot({
|
|
120
|
-
serviceId: 'svc_text_gpt54',
|
|
121
|
-
providerHeaders: async (_req, context) => createActorAuthHeaders(providerWallet, {
|
|
122
|
-
actorId: context.providerId,
|
|
123
|
-
role: 'provider',
|
|
124
|
-
method: 'POST',
|
|
125
|
-
path: '/facilitator/report',
|
|
126
|
-
timestamp: new Date().toISOString(),
|
|
127
|
-
}),
|
|
128
|
-
}), async (req, res) => {
|
|
129
|
-
const text = await runProviderLogic(req.body.message);
|
|
130
|
-
res.json({ text });
|
|
131
|
-
});
|
|
132
|
-
```
|
|
133
|
-
|
|
134
127
|
### Middleware flow
|
|
135
128
|
|
|
136
129
|
When a requester calls your middleware route:
|
package/dist/network-config.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { SettlementNetwork } from './types/common';
|
|
|
2
2
|
export type HalotNetworkMode = 'testnet' | 'mainnet';
|
|
3
3
|
export type ZeroGAuthorityNetwork = Extract<SettlementNetwork, '0g:testnet' | '0g:mainnet'>;
|
|
4
4
|
export type StellarNetwork = Extract<SettlementNetwork, 'stellar:testnet' | 'stellar:mainnet'>;
|
|
5
|
+
export declare const DEFAULT_ZERO_G_VERIFIER_EVALUATION_MODEL = "openai/gpt-oss-20b";
|
|
5
6
|
export type SpaceIdDefaults = {
|
|
6
7
|
tldId: number;
|
|
7
8
|
chainId: number;
|
|
@@ -34,3 +35,4 @@ export declare function resolveZeroGAuthorityProfile(network: ZeroGAuthorityNetw
|
|
|
34
35
|
export declare function resolveStellarNetworkProfile(network: StellarNetwork): StellarNetworkProfile;
|
|
35
36
|
export declare function resolveZeroGAuthorityByChainId(chainId: number): ZeroGAuthorityNetwork;
|
|
36
37
|
export declare function createZeroGStorageUri(rootHash: string): string;
|
|
38
|
+
export declare function normalizeZeroGVerifierEvaluationModel(model: string): string;
|
package/dist/network-config.js
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_ZERO_G_VERIFIER_EVALUATION_MODEL = void 0;
|
|
3
4
|
exports.resolveZeroGAuthorityProfile = resolveZeroGAuthorityProfile;
|
|
4
5
|
exports.resolveStellarNetworkProfile = resolveStellarNetworkProfile;
|
|
5
6
|
exports.resolveZeroGAuthorityByChainId = resolveZeroGAuthorityByChainId;
|
|
6
7
|
exports.createZeroGStorageUri = createZeroGStorageUri;
|
|
8
|
+
exports.normalizeZeroGVerifierEvaluationModel = normalizeZeroGVerifierEvaluationModel;
|
|
9
|
+
exports.DEFAULT_ZERO_G_VERIFIER_EVALUATION_MODEL = 'openai/gpt-oss-20b';
|
|
10
|
+
const zeroGVerifierModelAliases = {
|
|
11
|
+
'gpt-oss-20b': 'openai/gpt-oss-20b',
|
|
12
|
+
'gemma-3-27b-it': 'google/gemma-3-27b-it',
|
|
13
|
+
'qwen-2.5-7b-instruct': 'qwen/qwen-2.5-7b-instruct',
|
|
14
|
+
};
|
|
7
15
|
const zeroGAuthorityProfiles = {
|
|
8
16
|
'0g:testnet': {
|
|
9
17
|
network: '0g:testnet',
|
|
@@ -62,3 +70,8 @@ function resolveZeroGAuthorityByChainId(chainId) {
|
|
|
62
70
|
function createZeroGStorageUri(rootHash) {
|
|
63
71
|
return `0g://${rootHash}`;
|
|
64
72
|
}
|
|
73
|
+
function normalizeZeroGVerifierEvaluationModel(model) {
|
|
74
|
+
const trimmed = model.trim();
|
|
75
|
+
const alias = zeroGVerifierModelAliases[trimmed.toLowerCase()];
|
|
76
|
+
return alias ?? trimmed;
|
|
77
|
+
}
|
package/dist/types/verifier.d.ts
CHANGED
|
@@ -35,11 +35,12 @@ export declare const VerifierConfigSchema: z.ZodObject<{
|
|
|
35
35
|
computeBudgetPerJob: z.ZodString;
|
|
36
36
|
}, z.core.$strip>;
|
|
37
37
|
}, z.core.$strip>;
|
|
38
|
+
export declare const EvaluationModelConfigSchema: z.ZodObject<{
|
|
39
|
+
model: z.ZodString;
|
|
40
|
+
}, z.core.$strip>;
|
|
38
41
|
export declare const ModelConfigSchema: z.ZodObject<{
|
|
39
42
|
evaluationModel: z.ZodObject<{
|
|
40
|
-
|
|
41
|
-
serviceType: z.ZodDefault<z.ZodString>;
|
|
42
|
-
verifiability: z.ZodDefault<z.ZodString>;
|
|
43
|
+
model: z.ZodString;
|
|
43
44
|
}, z.core.$strip>;
|
|
44
45
|
sdk: z.ZodObject<{
|
|
45
46
|
network: z.ZodString;
|
package/dist/types/verifier.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VerifierStatsSchema = exports.RegisteredVerifierSchema = exports.SpecializationsSchema = exports.InferenceTemplateSchema = exports.ModelConfigSchema = exports.VerifierConfigSchema = void 0;
|
|
3
|
+
exports.VerifierStatsSchema = exports.RegisteredVerifierSchema = exports.SpecializationsSchema = exports.InferenceTemplateSchema = exports.ModelConfigSchema = exports.EvaluationModelConfigSchema = exports.VerifierConfigSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const common_1 = require("./common");
|
|
6
6
|
exports.VerifierConfigSchema = zod_1.z.object({
|
|
@@ -31,12 +31,11 @@ exports.VerifierConfigSchema = zod_1.z.object({
|
|
|
31
31
|
computeBudgetPerJob: zod_1.z.string(),
|
|
32
32
|
}),
|
|
33
33
|
});
|
|
34
|
+
exports.EvaluationModelConfigSchema = zod_1.z.object({
|
|
35
|
+
model: zod_1.z.string().trim().min(1),
|
|
36
|
+
});
|
|
34
37
|
exports.ModelConfigSchema = zod_1.z.object({
|
|
35
|
-
evaluationModel:
|
|
36
|
-
providerAddress: zod_1.z.string().default(''),
|
|
37
|
-
serviceType: zod_1.z.string().default('chatbot'),
|
|
38
|
-
verifiability: zod_1.z.string().default('TeeML'),
|
|
39
|
-
}),
|
|
38
|
+
evaluationModel: exports.EvaluationModelConfigSchema,
|
|
40
39
|
sdk: zod_1.z.object({
|
|
41
40
|
network: zod_1.z.string(),
|
|
42
41
|
rpcUrl: zod_1.z.string().optional(),
|
package/dist/zero-g/compute.d.ts
CHANGED
|
@@ -7,13 +7,12 @@ export type ComputeEvaluationInput = {
|
|
|
7
7
|
input: unknown;
|
|
8
8
|
result: unknown;
|
|
9
9
|
service: Service;
|
|
10
|
-
|
|
10
|
+
model: string;
|
|
11
11
|
systemPrompt?: string;
|
|
12
12
|
promptTemplate?: string;
|
|
13
13
|
outputSchema?: Record<string, string>;
|
|
14
14
|
maxTokens?: number;
|
|
15
15
|
temperature?: number;
|
|
16
|
-
model?: string;
|
|
17
16
|
};
|
|
18
17
|
export type ComputeEvaluationOutput = {
|
|
19
18
|
decision: Decision;
|
|
@@ -26,16 +25,23 @@ export type ComputeEvaluationOutput = {
|
|
|
26
25
|
export type ZeroGComputeOptions = {
|
|
27
26
|
rpcUrl?: string;
|
|
28
27
|
privateKey?: string;
|
|
29
|
-
providerAddress?: string;
|
|
30
28
|
ledgerContractAddress?: string;
|
|
31
29
|
inferenceContractAddress?: string;
|
|
32
30
|
fineTuningContractAddress?: string;
|
|
33
31
|
fetchImplementation?: typeof fetch;
|
|
34
32
|
};
|
|
33
|
+
type ZeroGInferenceServiceRecord = {
|
|
34
|
+
provider: string;
|
|
35
|
+
serviceType: string;
|
|
36
|
+
url: string;
|
|
37
|
+
model: string;
|
|
38
|
+
verifiability: string;
|
|
39
|
+
teeSignerAcknowledged: boolean;
|
|
40
|
+
};
|
|
41
|
+
export declare function selectZeroGComputeProvider(services: ZeroGInferenceServiceRecord[], requestedModel: string): ZeroGInferenceServiceRecord;
|
|
35
42
|
export declare class ZeroGComputeService {
|
|
36
43
|
private readonly rpcUrl?;
|
|
37
44
|
private readonly privateKey?;
|
|
38
|
-
private readonly providerAddress?;
|
|
39
45
|
private readonly ledgerContractAddress?;
|
|
40
46
|
private readonly inferenceContractAddress?;
|
|
41
47
|
private readonly fineTuningContractAddress?;
|
|
@@ -51,3 +57,4 @@ export declare class ZeroGComputeService {
|
|
|
51
57
|
private parseDecision;
|
|
52
58
|
private createWallet;
|
|
53
59
|
}
|
|
60
|
+
export {};
|
package/dist/zero-g/compute.js
CHANGED
|
@@ -1,15 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ZeroGComputeService = void 0;
|
|
4
|
+
exports.selectZeroGComputeProvider = selectZeroGComputeProvider;
|
|
4
5
|
const _0g_serving_broker_1 = require("@0glabs/0g-serving-broker");
|
|
5
6
|
const ethers_1 = require("ethers");
|
|
7
|
+
const network_config_1 = require("../network-config");
|
|
6
8
|
const artifacts_1 = require("../utils/artifacts");
|
|
7
9
|
const hash_1 = require("../utils/hash");
|
|
8
10
|
const id_1 = require("../utils/id");
|
|
11
|
+
function normalizeModel(model) {
|
|
12
|
+
return (0, network_config_1.normalizeZeroGVerifierEvaluationModel)(model).toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
function formatAvailableModels(services) {
|
|
15
|
+
return [...new Set(services
|
|
16
|
+
.filter((service) => service.serviceType === 'chatbot' && service.verifiability === 'TeeML')
|
|
17
|
+
.map((service) => service.model))].sort().join(', ');
|
|
18
|
+
}
|
|
19
|
+
function selectZeroGComputeProvider(services, requestedModel) {
|
|
20
|
+
const normalizedRequestedModel = normalizeModel(requestedModel);
|
|
21
|
+
const matchingModel = services.filter((service) => normalizeModel(service.model) === normalizedRequestedModel);
|
|
22
|
+
if (matchingModel.length === 0) {
|
|
23
|
+
const availableModels = formatAvailableModels(services);
|
|
24
|
+
throw new Error(availableModels
|
|
25
|
+
? `0G model "${requestedModel}" is not available. Current TeeML chatbot models: ${availableModels}.`
|
|
26
|
+
: `0G model "${requestedModel}" is not available.`);
|
|
27
|
+
}
|
|
28
|
+
const teeMlChatbotMatches = matchingModel.filter((service) => (service.serviceType === 'chatbot' &&
|
|
29
|
+
service.verifiability === 'TeeML'));
|
|
30
|
+
if (teeMlChatbotMatches.length === 0) {
|
|
31
|
+
throw new Error(`0G model "${requestedModel}" is registered but not as a TeeML chatbot service.`);
|
|
32
|
+
}
|
|
33
|
+
if (teeMlChatbotMatches.length === 1) {
|
|
34
|
+
return teeMlChatbotMatches[0];
|
|
35
|
+
}
|
|
36
|
+
const acknowledgedMatches = teeMlChatbotMatches.filter((service) => service.teeSignerAcknowledged);
|
|
37
|
+
if (acknowledgedMatches.length === 1) {
|
|
38
|
+
return acknowledgedMatches[0];
|
|
39
|
+
}
|
|
40
|
+
throw new Error(`0G model "${requestedModel}" resolves to multiple TeeML chatbot providers: ${teeMlChatbotMatches.map((service) => service.provider).join(', ')}.`);
|
|
41
|
+
}
|
|
9
42
|
class ZeroGComputeService {
|
|
10
43
|
rpcUrl;
|
|
11
44
|
privateKey;
|
|
12
|
-
providerAddress;
|
|
13
45
|
ledgerContractAddress;
|
|
14
46
|
inferenceContractAddress;
|
|
15
47
|
fineTuningContractAddress;
|
|
@@ -17,7 +49,6 @@ class ZeroGComputeService {
|
|
|
17
49
|
constructor(options = {}) {
|
|
18
50
|
this.rpcUrl = options.rpcUrl;
|
|
19
51
|
this.privateKey = options.privateKey;
|
|
20
|
-
this.providerAddress = options.providerAddress;
|
|
21
52
|
this.ledgerContractAddress = options.ledgerContractAddress;
|
|
22
53
|
this.inferenceContractAddress = options.inferenceContractAddress;
|
|
23
54
|
this.fineTuningContractAddress = options.fineTuningContractAddress;
|
|
@@ -27,20 +58,21 @@ class ZeroGComputeService {
|
|
|
27
58
|
return this.evaluateWithZeroG(input);
|
|
28
59
|
}
|
|
29
60
|
async evaluateWithZeroG(input) {
|
|
30
|
-
const providerAddress = (0, ethers_1.getAddress)(input.providerAddress ?? this.providerAddress ?? '');
|
|
31
61
|
const wallet = this.createWallet();
|
|
32
62
|
const broker = await (0, _0g_serving_broker_1.createZGComputeNetworkBroker)(wallet, this.ledgerContractAddress, this.inferenceContractAddress, this.fineTuningContractAddress);
|
|
63
|
+
const selectedService = selectZeroGComputeProvider(await broker.inference.listService(0, 100, true), input.model);
|
|
64
|
+
const providerAddress = (0, ethers_1.getAddress)(selectedService.provider);
|
|
65
|
+
const endpoint = `${selectedService.url}/v1/proxy`;
|
|
33
66
|
if (!(await broker.inference.acknowledged(providerAddress))) {
|
|
34
67
|
await broker.inference.acknowledgeProviderSigner(providerAddress);
|
|
35
68
|
}
|
|
36
|
-
const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress);
|
|
37
69
|
const artifacts = await (0, artifacts_1.resolveImageArtifacts)(input.input, input.result, {
|
|
38
70
|
fetchImplementation: this.fetchImplementation,
|
|
39
71
|
outputFormat: input.service.output.format,
|
|
40
72
|
});
|
|
41
73
|
const prompt = this.renderPrompt(input, artifacts);
|
|
42
74
|
const requestBody = {
|
|
43
|
-
model:
|
|
75
|
+
model: selectedService.model,
|
|
44
76
|
messages: [
|
|
45
77
|
{
|
|
46
78
|
role: 'system',
|