@antseed/node 0.2.106 → 0.2.108
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/billing/index.d.ts +2 -0
- package/dist/billing/index.d.ts.map +1 -0
- package/dist/billing/index.js +2 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/billing/unit.d.ts +3 -0
- package/dist/billing/unit.d.ts.map +1 -0
- package/dist/billing/unit.js +3 -0
- package/dist/billing/unit.js.map +1 -0
- package/dist/buyer-request-handler.d.ts +1 -54
- package/dist/buyer-request-handler.d.ts.map +1 -1
- package/dist/buyer-request-handler.js +2 -379
- package/dist/buyer-request-handler.js.map +1 -1
- package/dist/discovery/announcer.d.ts +7 -1
- package/dist/discovery/announcer.d.ts.map +1 -1
- package/dist/discovery/announcer.js +84 -33
- package/dist/discovery/announcer.js.map +1 -1
- package/dist/discovery/http-metadata-resolver.d.ts +4 -0
- package/dist/discovery/http-metadata-resolver.d.ts.map +1 -1
- package/dist/discovery/http-metadata-resolver.js +42 -2
- package/dist/discovery/http-metadata-resolver.js.map +1 -1
- package/dist/discovery/index.d.ts +1 -1
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/discovery/index.js +1 -1
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/metadata-codec.d.ts +4 -4
- package/dist/discovery/metadata-codec.d.ts.map +1 -1
- package/dist/discovery/metadata-codec.js +339 -23
- package/dist/discovery/metadata-codec.js.map +1 -1
- package/dist/discovery/metadata-validator.d.ts +7 -3
- package/dist/discovery/metadata-validator.d.ts.map +1 -1
- package/dist/discovery/metadata-validator.js +139 -8
- package/dist/discovery/metadata-validator.js.map +1 -1
- package/dist/discovery/peer-lookup.d.ts +1 -0
- package/dist/discovery/peer-lookup.d.ts.map +1 -1
- package/dist/discovery/peer-lookup.js +23 -5
- package/dist/discovery/peer-lookup.js.map +1 -1
- package/dist/discovery/peer-metadata.d.ts +2 -90
- package/dist/discovery/peer-metadata.d.ts.map +1 -1
- package/dist/discovery/peer-metadata.js +3 -11
- package/dist/discovery/peer-metadata.js.map +1 -1
- package/dist/discovery/seller-address-resolver.d.ts +1 -49
- package/dist/discovery/seller-address-resolver.d.ts.map +1 -1
- package/dist/discovery/seller-address-resolver.js +2 -114
- package/dist/discovery/seller-address-resolver.js.map +1 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -0
- package/dist/health/model-health-checker.d.ts +6 -5
- package/dist/health/model-health-checker.d.ts.map +1 -1
- package/dist/health/model-health-checker.js +22 -10
- package/dist/health/model-health-checker.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/seller-provider.d.ts +6 -0
- package/dist/interfaces/seller-provider.d.ts.map +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +34 -5
- package/dist/node.js.map +1 -1
- package/dist/p2p/connection-auth.d.ts +3 -8
- package/dist/p2p/connection-auth.d.ts.map +1 -1
- package/dist/p2p/connection-auth.js +4 -6
- package/dist/p2p/connection-auth.js.map +1 -1
- package/dist/p2p/connection-manager.d.ts +3 -1
- package/dist/p2p/connection-manager.d.ts.map +1 -1
- package/dist/p2p/connection-manager.js.map +1 -1
- package/dist/p2p/identity.d.ts +1 -21
- package/dist/p2p/identity.d.ts.map +1 -1
- package/dist/p2p/identity.js +3 -62
- package/dist/p2p/identity.js.map +1 -1
- package/dist/p2p/message-protocol.d.ts +1 -49
- package/dist/p2p/message-protocol.d.ts.map +1 -1
- package/dist/p2p/message-protocol.js +2 -125
- package/dist/p2p/message-protocol.js.map +1 -1
- package/dist/p2p/payment-codec.d.ts +1 -21
- package/dist/p2p/payment-codec.d.ts.map +1 -1
- package/dist/p2p/payment-codec.js +2 -220
- package/dist/p2p/payment-codec.js.map +1 -1
- package/dist/p2p/payment-mux.d.ts +1 -51
- package/dist/p2p/payment-mux.d.ts.map +1 -1
- package/dist/p2p/payment-mux.js +2 -159
- package/dist/p2p/payment-mux.js.map +1 -1
- package/dist/payments/buyer-free-usage-manager.d.ts +1 -43
- package/dist/payments/buyer-free-usage-manager.d.ts.map +1 -1
- package/dist/payments/buyer-free-usage-manager.js +2 -298
- package/dist/payments/buyer-free-usage-manager.js.map +1 -1
- package/dist/payments/buyer-payment-manager.d.ts +1 -277
- package/dist/payments/buyer-payment-manager.d.ts.map +1 -1
- package/dist/payments/buyer-payment-manager.js +2 -1039
- package/dist/payments/buyer-payment-manager.js.map +1 -1
- package/dist/payments/buyer-payment-negotiator.d.ts +1 -130
- package/dist/payments/buyer-payment-negotiator.d.ts.map +1 -1
- package/dist/payments/buyer-payment-negotiator.js +2 -950
- package/dist/payments/buyer-payment-negotiator.js.map +1 -1
- package/dist/payments/chain-config.d.ts.map +1 -1
- package/dist/payments/chain-config.js +13 -2
- package/dist/payments/chain-config.js.map +1 -1
- package/dist/payments/channel-session-state.d.ts +1 -13
- package/dist/payments/channel-session-state.d.ts.map +1 -1
- package/dist/payments/channel-session-state.js +2 -25
- package/dist/payments/channel-session-state.js.map +1 -1
- package/dist/payments/channel-store.d.ts +2 -51
- package/dist/payments/channel-store.d.ts.map +1 -1
- package/dist/payments/channel-store.js +3 -14
- package/dist/payments/channel-store.js.map +1 -1
- package/dist/payments/channel-usage-accounting.d.ts +1 -17
- package/dist/payments/channel-usage-accounting.d.ts.map +1 -1
- package/dist/payments/channel-usage-accounting.js +2 -65
- package/dist/payments/channel-usage-accounting.js.map +1 -1
- package/dist/payments/evm/base-evm-client.d.ts +1 -26
- package/dist/payments/evm/base-evm-client.d.ts.map +1 -1
- package/dist/payments/evm/base-evm-client.js +2 -115
- package/dist/payments/evm/base-evm-client.js.map +1 -1
- package/dist/payments/evm/channels-client.d.ts +1 -85
- package/dist/payments/evm/channels-client.d.ts.map +1 -1
- package/dist/payments/evm/channels-client.js +2 -193
- package/dist/payments/evm/channels-client.js.map +1 -1
- package/dist/payments/evm/deposits-client.d.ts +1 -29
- package/dist/payments/evm/deposits-client.d.ts.map +1 -1
- package/dist/payments/evm/deposits-client.js +2 -67
- package/dist/payments/evm/deposits-client.js.map +1 -1
- package/dist/payments/evm/signatures.d.ts +1 -203
- package/dist/payments/evm/signatures.d.ts.map +1 -1
- package/dist/payments/evm/signatures.js +2 -236
- package/dist/payments/evm/signatures.js.map +1 -1
- package/dist/payments/evm/subpool-client.d.ts +32 -0
- package/dist/payments/evm/subpool-client.d.ts.map +1 -0
- package/dist/payments/evm/subpool-client.js +158 -0
- package/dist/payments/evm/subpool-client.js.map +1 -0
- package/dist/payments/index.d.ts +1 -1
- package/dist/payments/index.d.ts.map +1 -1
- package/dist/payments/index.js +1 -1
- package/dist/payments/index.js.map +1 -1
- package/dist/payments/pricing.d.ts +1 -26
- package/dist/payments/pricing.d.ts.map +1 -1
- package/dist/payments/pricing.js +2 -36
- package/dist/payments/pricing.js.map +1 -1
- package/dist/payments/usdc-utils.d.ts +1 -8
- package/dist/payments/usdc-utils.d.ts.map +1 -1
- package/dist/payments/usdc-utils.js +2 -16
- package/dist/payments/usdc-utils.js.map +1 -1
- package/dist/proxy/proxy-mux.d.ts +1 -69
- package/dist/proxy/proxy-mux.d.ts.map +1 -1
- package/dist/proxy/proxy-mux.js +2 -346
- package/dist/proxy/proxy-mux.js.map +1 -1
- package/dist/proxy/request-codec.d.ts +1 -41
- package/dist/proxy/request-codec.d.ts.map +1 -1
- package/dist/proxy/request-codec.js +2 -280
- package/dist/proxy/request-codec.js.map +1 -1
- package/dist/seller-request-handler.d.ts +10 -3
- package/dist/seller-request-handler.d.ts.map +1 -1
- package/dist/seller-request-handler.js +112 -17
- package/dist/seller-request-handler.js.map +1 -1
- package/dist/types/billing.d.ts +2 -0
- package/dist/types/billing.d.ts.map +1 -0
- package/dist/types/billing.js +2 -0
- package/dist/types/billing.js.map +1 -0
- package/dist/types/capability.d.ts +1 -25
- package/dist/types/capability.d.ts.map +1 -1
- package/dist/types/capability.js +2 -1
- package/dist/types/capability.js.map +1 -1
- package/dist/types/connection.d.ts +1 -26
- package/dist/types/connection.d.ts.map +1 -1
- package/dist/types/connection.js +2 -10
- package/dist/types/connection.js.map +1 -1
- package/dist/types/http.d.ts +1 -39
- package/dist/types/http.d.ts.map +1 -1
- package/dist/types/http.js +2 -16
- package/dist/types/http.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/peer.d.ts +9 -31
- package/dist/types/peer.d.ts.map +1 -1
- package/dist/types/peer.js +2 -14
- package/dist/types/peer.js.map +1 -1
- package/dist/types/protocol.d.ts +1 -306
- package/dist/types/protocol.d.ts.map +1 -1
- package/dist/types/protocol.js +2 -81
- package/dist/types/protocol.js.map +1 -1
- package/dist/types/service-api.d.ts +1 -5
- package/dist/types/service-api.d.ts.map +1 -1
- package/dist/types/service-api.js +2 -12
- package/dist/types/service-api.js.map +1 -1
- package/dist/utils/debug.d.ts +1 -5
- package/dist/utils/debug.d.ts.map +1 -1
- package/dist/utils/debug.js +2 -52
- package/dist/utils/debug.js.map +1 -1
- package/dist/utils/hex.d.ts +1 -2
- package/dist/utils/hex.d.ts.map +1 -1
- package/dist/utils/hex.js +2 -14
- package/dist/utils/hex.js.map +1 -1
- package/dist/utils/json-codec.d.ts +1 -9
- package/dist/utils/json-codec.d.ts.map +1 -1
- package/dist/utils/json-codec.js +2 -51
- package/dist/utils/json-codec.js.map +1 -1
- package/dist/utils/response-usage.d.ts +1 -9
- package/dist/utils/response-usage.d.ts.map +1 -1
- package/dist/utils/response-usage.js +2 -39
- package/dist/utils/response-usage.js.map +1 -1
- package/dist/verification/codec.d.ts +1 -3
- package/dist/verification/codec.d.ts.map +1 -1
- package/dist/verification/codec.js +2 -37
- package/dist/verification/codec.js.map +1 -1
- package/dist/verification/response-auth.d.ts +1 -30
- package/dist/verification/response-auth.d.ts.map +1 -1
- package/dist/verification/response-auth.js +2 -110
- package/dist/verification/response-auth.js.map +1 -1
- package/dist/verification/verification-mux.d.ts +1 -19
- package/dist/verification/verification-mux.d.ts.map +1 -1
- package/dist/verification/verification-mux.js +2 -99
- package/dist/verification/verification-mux.js.map +1 -1
- package/package.json +4 -2
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { SERVICE_CAPABILITY_MODALITIES } from "./peer-metadata.js";
|
|
1
2
|
import { hexToBytes, bytesToHex } from "../utils/hex.js";
|
|
2
3
|
import { toPeerId } from "../types/peer.js";
|
|
3
|
-
import { isKnownServiceApiProtocol } from "../types/service-api.js";
|
|
4
|
+
import { WELL_KNOWN_SERVICE_API_PROTOCOLS, isKnownServiceApiProtocol } from "../types/service-api.js";
|
|
5
|
+
import { UNIT_BILLING_MATCH_KEYS_V1, UNIT_BILLING_UNITS_V1, } from "../types/billing.js";
|
|
4
6
|
const SERVICE_CATEGORIES_METADATA_VERSION = 3;
|
|
5
7
|
const SERVICE_API_PROTOCOLS_METADATA_VERSION = 4;
|
|
6
8
|
const PUBLIC_ADDRESS_METADATA_VERSION = 5;
|
|
@@ -12,15 +14,22 @@ const DOMAIN_VERIFICATION_METHOD_IDS = {
|
|
|
12
14
|
"https-well-known": 1,
|
|
13
15
|
};
|
|
14
16
|
const DOMAIN_VERIFICATION_METHODS_BY_ID = ["dns-txt", "https-well-known"];
|
|
17
|
+
const SERVICE_UNIT_BILLING_METADATA_VERSION = 11;
|
|
18
|
+
const SERVICE_CAPABILITIES_METADATA_VERSION = 12;
|
|
19
|
+
const WIDE_SERVICE_COUNTS_METADATA_VERSION = 12;
|
|
20
|
+
const UNIT_BILLING_UNITS_BY_ID = [...UNIT_BILLING_UNITS_V1];
|
|
21
|
+
const UNIT_BILLING_UNIT_IDS = new Map(UNIT_BILLING_UNITS_BY_ID.map((unit, index) => [unit, index]));
|
|
22
|
+
const UNIT_BILLING_MATCH_KEYS_BY_ID = [...UNIT_BILLING_MATCH_KEYS_V1];
|
|
23
|
+
const UNIT_BILLING_MATCH_KEY_IDS = new Map(UNIT_BILLING_MATCH_KEYS_BY_ID.map((key, index) => [key, index]));
|
|
15
24
|
/**
|
|
16
25
|
* Encode metadata into binary format:
|
|
17
26
|
* [version:1][peerId:20][regionLen:1][region:N][timestamp:8 BigUint64][providerCount:1]
|
|
18
27
|
* for each provider:
|
|
19
|
-
* [providerLen:1][provider:N][serviceCount:1][services...]
|
|
28
|
+
* [providerLen:1][provider:N][serviceCount:1|2][services...]
|
|
20
29
|
* [defaultInputPrice:4][defaultOutputPrice:4][defaultCachedInputPrice:4]
|
|
21
|
-
* [servicePricingCount:1][servicePricingEntries...]
|
|
22
|
-
* [serviceCategoryCount:1][serviceCategoryEntries...] (v3+ only)
|
|
23
|
-
* [serviceApiProtocolCount:1][serviceApiProtocolEntries...] (v4+ only)
|
|
30
|
+
* [servicePricingCount:1|2][servicePricingEntries...]
|
|
31
|
+
* [serviceCategoryCount:1|2][serviceCategoryEntries...] (v3+ only)
|
|
32
|
+
* [serviceApiProtocolCount:1|2][serviceApiProtocolEntries...] (v4+ only)
|
|
24
33
|
* [maxConcurrency:2][currentLoad:2]
|
|
25
34
|
* servicePricingEntry: [serviceLen:1][service:N][inputPrice:4][outputPrice:4][cachedInputPrice:4]
|
|
26
35
|
* serviceCategoryEntry(v3+): [serviceLen:1][service:N][categoryCount:1][categories...]
|
|
@@ -58,6 +67,7 @@ function encodeBody(metadata) {
|
|
|
58
67
|
const parts = [];
|
|
59
68
|
const hasServiceCategoryExtensions = metadata.version >= SERVICE_CATEGORIES_METADATA_VERSION;
|
|
60
69
|
const hasServiceApiProtocolExtensions = metadata.version >= SERVICE_API_PROTOCOLS_METADATA_VERSION;
|
|
70
|
+
const hasWideServiceCounts = metadata.version >= WIDE_SERVICE_COUNTS_METADATA_VERSION;
|
|
61
71
|
// version: 1 byte
|
|
62
72
|
parts.push(new Uint8Array([metadata.version]));
|
|
63
73
|
// peerId: 20 bytes (EVM address)
|
|
@@ -78,8 +88,7 @@ function encodeBody(metadata) {
|
|
|
78
88
|
const providerNameBytes = new TextEncoder().encode(p.provider);
|
|
79
89
|
parts.push(new Uint8Array([providerNameBytes.length]));
|
|
80
90
|
parts.push(providerNameBytes);
|
|
81
|
-
|
|
82
|
-
parts.push(new Uint8Array([p.services.length]));
|
|
91
|
+
pushServiceEntryCount(parts, p.services.length, hasWideServiceCounts);
|
|
83
92
|
// each service: length-prefixed
|
|
84
93
|
for (const service of p.services) {
|
|
85
94
|
const serviceBytes = new TextEncoder().encode(service);
|
|
@@ -100,7 +109,7 @@ function encodeBody(metadata) {
|
|
|
100
109
|
parts.push(new Uint8Array(cachedInputPriceBuf));
|
|
101
110
|
// servicePricing entries
|
|
102
111
|
const servicePricingEntries = Object.entries(p.servicePricing ?? {}).sort(([a], [b]) => a.localeCompare(b));
|
|
103
|
-
parts
|
|
112
|
+
pushServiceEntryCount(parts, servicePricingEntries.length, hasWideServiceCounts);
|
|
104
113
|
for (const [serviceName, pricing] of servicePricingEntries) {
|
|
105
114
|
const serviceNameBytes = new TextEncoder().encode(serviceName);
|
|
106
115
|
parts.push(new Uint8Array([serviceNameBytes.length]));
|
|
@@ -126,7 +135,7 @@ function encodeBody(metadata) {
|
|
|
126
135
|
})
|
|
127
136
|
.filter(([, categories]) => categories.length > 0)
|
|
128
137
|
.sort(([a], [b]) => a.localeCompare(b));
|
|
129
|
-
parts
|
|
138
|
+
pushServiceEntryCount(parts, serviceCategoryEntries.length, hasWideServiceCounts);
|
|
130
139
|
for (const [serviceName, categories] of serviceCategoryEntries) {
|
|
131
140
|
const serviceNameBytes = new TextEncoder().encode(serviceName);
|
|
132
141
|
parts.push(new Uint8Array([serviceNameBytes.length]));
|
|
@@ -149,7 +158,7 @@ function encodeBody(metadata) {
|
|
|
149
158
|
})
|
|
150
159
|
.filter(([, protocols]) => protocols.length > 0)
|
|
151
160
|
.sort(([a], [b]) => a.localeCompare(b));
|
|
152
|
-
parts
|
|
161
|
+
pushServiceEntryCount(parts, serviceApiProtocolEntries.length, hasWideServiceCounts);
|
|
153
162
|
for (const [serviceName, protocols] of serviceApiProtocolEntries) {
|
|
154
163
|
const serviceNameBytes = new TextEncoder().encode(serviceName);
|
|
155
164
|
parts.push(new Uint8Array([serviceNameBytes.length]));
|
|
@@ -162,6 +171,12 @@ function encodeBody(metadata) {
|
|
|
162
171
|
}
|
|
163
172
|
}
|
|
164
173
|
}
|
|
174
|
+
if (metadata.version >= SERVICE_UNIT_BILLING_METADATA_VERSION) {
|
|
175
|
+
encodeServiceUnitBillingModels(parts, p.serviceUnitBillingModels, hasWideServiceCounts);
|
|
176
|
+
}
|
|
177
|
+
if (metadata.version >= SERVICE_CAPABILITIES_METADATA_VERSION) {
|
|
178
|
+
encodeServiceCapabilities(parts, p.serviceCapabilities, hasWideServiceCounts);
|
|
179
|
+
}
|
|
165
180
|
// maxConcurrency: 2 bytes (uint16)
|
|
166
181
|
const maxConcBuf = new ArrayBuffer(2);
|
|
167
182
|
new DataView(maxConcBuf).setUint16(0, p.maxConcurrency, false);
|
|
@@ -335,6 +350,303 @@ function encodeBody(metadata) {
|
|
|
335
350
|
}
|
|
336
351
|
return result;
|
|
337
352
|
}
|
|
353
|
+
function encodeServiceUnitBillingModels(parts, serviceUnitBillingModels, hasWideServiceCounts) {
|
|
354
|
+
const entries = [];
|
|
355
|
+
for (const [serviceName, protocolModels] of Object.entries(serviceUnitBillingModels ?? {})) {
|
|
356
|
+
for (const protocol of WELL_KNOWN_SERVICE_API_PROTOCOLS) {
|
|
357
|
+
const model = protocolModels?.[protocol];
|
|
358
|
+
if (model)
|
|
359
|
+
entries.push([serviceName, protocol, model]);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
entries.sort(([serviceA, protocolA], [serviceB, protocolB]) => serviceA === serviceB
|
|
363
|
+
? WELL_KNOWN_SERVICE_API_PROTOCOLS.indexOf(protocolA) - WELL_KNOWN_SERVICE_API_PROTOCOLS.indexOf(protocolB)
|
|
364
|
+
: serviceA.localeCompare(serviceB));
|
|
365
|
+
pushServiceEntryCount(parts, entries.length, hasWideServiceCounts);
|
|
366
|
+
for (const [serviceName, protocol, model] of entries) {
|
|
367
|
+
pushUtf8(parts, serviceName);
|
|
368
|
+
parts.push(new Uint8Array([WELL_KNOWN_SERVICE_API_PROTOCOLS.indexOf(protocol)]));
|
|
369
|
+
parts.push(new Uint8Array([model.version]));
|
|
370
|
+
parts.push(new Uint8Array([model.components.length]));
|
|
371
|
+
for (const component of model.components) {
|
|
372
|
+
parts.push(new Uint8Array([UNIT_BILLING_UNIT_IDS.get(component.unit) ?? 255]));
|
|
373
|
+
const priceBuf = new ArrayBuffer(4);
|
|
374
|
+
new DataView(priceBuf).setFloat32(0, component.priceUsd, false);
|
|
375
|
+
parts.push(new Uint8Array(priceBuf));
|
|
376
|
+
const matchEntries = Object.entries(component.match ?? {})
|
|
377
|
+
.filter((entry) => UNIT_BILLING_MATCH_KEY_IDS.has(entry[0]))
|
|
378
|
+
.sort(([a], [b]) => (UNIT_BILLING_MATCH_KEY_IDS.get(a) ?? 0) - (UNIT_BILLING_MATCH_KEY_IDS.get(b) ?? 0));
|
|
379
|
+
parts.push(new Uint8Array([matchEntries.length]));
|
|
380
|
+
for (const [key, value] of matchEntries) {
|
|
381
|
+
parts.push(new Uint8Array([UNIT_BILLING_MATCH_KEY_IDS.get(key) ?? 255]));
|
|
382
|
+
pushUtf8(parts, value);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
// Presence bits for the per-service capability entry. A set bit means the
|
|
388
|
+
// field was announced (booleans distinguish "known false" from "unknown").
|
|
389
|
+
const CAP_HAS_CONTEXT_WINDOW = 1 << 0;
|
|
390
|
+
const CAP_HAS_MAX_OUTPUT_TOKENS = 1 << 1;
|
|
391
|
+
const CAP_HAS_INPUTS = 1 << 2;
|
|
392
|
+
const CAP_HAS_REASONING = 1 << 3;
|
|
393
|
+
const CAP_HAS_TOOL_USE = 1 << 4;
|
|
394
|
+
const CAP_HAS_STRUCTURED_OUTPUT = 1 << 5;
|
|
395
|
+
const CAP_HAS_OUTPUTS = 1 << 6;
|
|
396
|
+
const CAP_HAS_SUPPORTED_PARAMETERS = 1 << 7;
|
|
397
|
+
const CAP_PRESENCE_MASK = CAP_HAS_CONTEXT_WINDOW | CAP_HAS_MAX_OUTPUT_TOKENS | CAP_HAS_INPUTS
|
|
398
|
+
| CAP_HAS_REASONING | CAP_HAS_TOOL_USE | CAP_HAS_STRUCTURED_OUTPUT
|
|
399
|
+
| CAP_HAS_OUTPUTS | CAP_HAS_SUPPORTED_PARAMETERS;
|
|
400
|
+
// Value bits for the boolean-values byte. Deliberately a separate namespace
|
|
401
|
+
// from the presence bits: presence says "announced", value says "true".
|
|
402
|
+
const CAP_VAL_REASONING = 1 << 0;
|
|
403
|
+
const CAP_VAL_TOOL_USE = 1 << 1;
|
|
404
|
+
const CAP_VAL_STRUCTURED_OUTPUT = 1 << 2;
|
|
405
|
+
const CAP_VALUE_MASK = CAP_VAL_REASONING | CAP_VAL_TOOL_USE | CAP_VAL_STRUCTURED_OUTPUT;
|
|
406
|
+
const CAP_MODALITY_MASK = (1 << SERVICE_CAPABILITY_MODALITIES.length) - 1;
|
|
407
|
+
function encodeModalityBits(modalities) {
|
|
408
|
+
let bits = 0;
|
|
409
|
+
for (const modality of modalities) {
|
|
410
|
+
const id = SERVICE_CAPABILITY_MODALITIES.indexOf(modality);
|
|
411
|
+
if (id >= 0)
|
|
412
|
+
bits |= 1 << id;
|
|
413
|
+
}
|
|
414
|
+
return bits;
|
|
415
|
+
}
|
|
416
|
+
function decodeModalityBits(bits, label) {
|
|
417
|
+
if (bits & ~CAP_MODALITY_MASK) {
|
|
418
|
+
throw new Error(`Unknown service capability ${label} bits 0x${bits.toString(16)}`);
|
|
419
|
+
}
|
|
420
|
+
const modalities = [];
|
|
421
|
+
for (let id = 0; id < SERVICE_CAPABILITY_MODALITIES.length; id += 1) {
|
|
422
|
+
if (bits & (1 << id))
|
|
423
|
+
modalities.push(SERVICE_CAPABILITY_MODALITIES[id]);
|
|
424
|
+
}
|
|
425
|
+
return modalities;
|
|
426
|
+
}
|
|
427
|
+
function encodeServiceCapabilities(parts, serviceCapabilities, hasWideServiceCounts) {
|
|
428
|
+
// Code-unit sort, not localeCompare: buyers verify signatures by re-encoding
|
|
429
|
+
// decoded metadata, so entry order must not depend on the verifier's locale.
|
|
430
|
+
const entries = Object.entries(serviceCapabilities ?? {})
|
|
431
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
432
|
+
pushServiceEntryCount(parts, entries.length, hasWideServiceCounts);
|
|
433
|
+
for (const [serviceName, caps] of entries) {
|
|
434
|
+
pushUtf8(parts, serviceName);
|
|
435
|
+
let presence = 0;
|
|
436
|
+
if (caps.contextWindow !== undefined)
|
|
437
|
+
presence |= CAP_HAS_CONTEXT_WINDOW;
|
|
438
|
+
if (caps.maxOutputTokens !== undefined)
|
|
439
|
+
presence |= CAP_HAS_MAX_OUTPUT_TOKENS;
|
|
440
|
+
if (caps.inputs !== undefined)
|
|
441
|
+
presence |= CAP_HAS_INPUTS;
|
|
442
|
+
if (caps.outputs !== undefined)
|
|
443
|
+
presence |= CAP_HAS_OUTPUTS;
|
|
444
|
+
if (caps.reasoning !== undefined)
|
|
445
|
+
presence |= CAP_HAS_REASONING;
|
|
446
|
+
if (caps.toolUse !== undefined)
|
|
447
|
+
presence |= CAP_HAS_TOOL_USE;
|
|
448
|
+
if (caps.structuredOutput !== undefined)
|
|
449
|
+
presence |= CAP_HAS_STRUCTURED_OUTPUT;
|
|
450
|
+
if (caps.supportedParameters !== undefined)
|
|
451
|
+
presence |= CAP_HAS_SUPPORTED_PARAMETERS;
|
|
452
|
+
parts.push(new Uint8Array([presence]));
|
|
453
|
+
if (caps.contextWindow !== undefined) {
|
|
454
|
+
const buf = new ArrayBuffer(4);
|
|
455
|
+
new DataView(buf).setUint32(0, caps.contextWindow, false);
|
|
456
|
+
parts.push(new Uint8Array(buf));
|
|
457
|
+
}
|
|
458
|
+
if (caps.maxOutputTokens !== undefined) {
|
|
459
|
+
const buf = new ArrayBuffer(4);
|
|
460
|
+
new DataView(buf).setUint32(0, caps.maxOutputTokens, false);
|
|
461
|
+
parts.push(new Uint8Array(buf));
|
|
462
|
+
}
|
|
463
|
+
if (caps.inputs !== undefined) {
|
|
464
|
+
parts.push(new Uint8Array([encodeModalityBits(caps.inputs)]));
|
|
465
|
+
}
|
|
466
|
+
if (caps.outputs !== undefined) {
|
|
467
|
+
parts.push(new Uint8Array([encodeModalityBits(caps.outputs)]));
|
|
468
|
+
}
|
|
469
|
+
let boolBits = 0;
|
|
470
|
+
if (caps.reasoning === true)
|
|
471
|
+
boolBits |= CAP_VAL_REASONING;
|
|
472
|
+
if (caps.toolUse === true)
|
|
473
|
+
boolBits |= CAP_VAL_TOOL_USE;
|
|
474
|
+
if (caps.structuredOutput === true)
|
|
475
|
+
boolBits |= CAP_VAL_STRUCTURED_OUTPUT;
|
|
476
|
+
parts.push(new Uint8Array([boolBits]));
|
|
477
|
+
if (caps.supportedParameters !== undefined) {
|
|
478
|
+
// Code-unit sort for the same reason as the entry sort above: buyers
|
|
479
|
+
// verify signatures by re-encoding decoded metadata.
|
|
480
|
+
const parameters = [...caps.supportedParameters].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
481
|
+
if (parameters.length > 255) {
|
|
482
|
+
throw new Error(`Too many supported parameters (${parameters.length})`);
|
|
483
|
+
}
|
|
484
|
+
parts.push(new Uint8Array([parameters.length]));
|
|
485
|
+
for (const parameter of parameters) {
|
|
486
|
+
pushUtf8(parts, parameter);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
function decodeServiceCapabilities(data, getOffset, setOffset, checkBounds, hasWideServiceCounts) {
|
|
492
|
+
let offset = getOffset();
|
|
493
|
+
const [entryCount, nextOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
|
|
494
|
+
offset = nextOffset;
|
|
495
|
+
const serviceCapabilities = {};
|
|
496
|
+
for (let i = 0; i < entryCount; i += 1) {
|
|
497
|
+
const [serviceName, serviceOffset] = readUtf8(data, offset, checkBounds);
|
|
498
|
+
offset = serviceOffset;
|
|
499
|
+
checkBounds(offset, 1, data.length);
|
|
500
|
+
const presence = data[offset];
|
|
501
|
+
offset += 1;
|
|
502
|
+
if (presence & ~CAP_PRESENCE_MASK) {
|
|
503
|
+
// Unknown bits would decode into a struct that re-encodes to different
|
|
504
|
+
// bytes and fails signature verification anyway — reject explicitly so
|
|
505
|
+
// additive extensions are forced through a metadata version bump.
|
|
506
|
+
throw new Error(`Unknown service capability presence bits 0x${presence.toString(16)}`);
|
|
507
|
+
}
|
|
508
|
+
const caps = {};
|
|
509
|
+
if (presence & CAP_HAS_CONTEXT_WINDOW) {
|
|
510
|
+
checkBounds(offset, 4, data.length);
|
|
511
|
+
caps.contextWindow = new DataView(data.buffer, data.byteOffset + offset, 4).getUint32(0, false);
|
|
512
|
+
offset += 4;
|
|
513
|
+
}
|
|
514
|
+
if (presence & CAP_HAS_MAX_OUTPUT_TOKENS) {
|
|
515
|
+
checkBounds(offset, 4, data.length);
|
|
516
|
+
caps.maxOutputTokens = new DataView(data.buffer, data.byteOffset + offset, 4).getUint32(0, false);
|
|
517
|
+
offset += 4;
|
|
518
|
+
}
|
|
519
|
+
if (presence & CAP_HAS_INPUTS) {
|
|
520
|
+
checkBounds(offset, 1, data.length);
|
|
521
|
+
caps.inputs = decodeModalityBits(data[offset], "input");
|
|
522
|
+
offset += 1;
|
|
523
|
+
}
|
|
524
|
+
if (presence & CAP_HAS_OUTPUTS) {
|
|
525
|
+
checkBounds(offset, 1, data.length);
|
|
526
|
+
caps.outputs = decodeModalityBits(data[offset], "output");
|
|
527
|
+
offset += 1;
|
|
528
|
+
}
|
|
529
|
+
checkBounds(offset, 1, data.length);
|
|
530
|
+
const boolBits = data[offset];
|
|
531
|
+
offset += 1;
|
|
532
|
+
if (boolBits & ~CAP_VALUE_MASK) {
|
|
533
|
+
throw new Error(`Unknown service capability value bits 0x${boolBits.toString(16)}`);
|
|
534
|
+
}
|
|
535
|
+
if (presence & CAP_HAS_REASONING)
|
|
536
|
+
caps.reasoning = (boolBits & CAP_VAL_REASONING) !== 0;
|
|
537
|
+
if (presence & CAP_HAS_TOOL_USE)
|
|
538
|
+
caps.toolUse = (boolBits & CAP_VAL_TOOL_USE) !== 0;
|
|
539
|
+
if (presence & CAP_HAS_STRUCTURED_OUTPUT)
|
|
540
|
+
caps.structuredOutput = (boolBits & CAP_VAL_STRUCTURED_OUTPUT) !== 0;
|
|
541
|
+
if (presence & CAP_HAS_SUPPORTED_PARAMETERS) {
|
|
542
|
+
checkBounds(offset, 1, data.length);
|
|
543
|
+
const parameterCount = data[offset];
|
|
544
|
+
offset += 1;
|
|
545
|
+
const parameters = [];
|
|
546
|
+
for (let p = 0; p < parameterCount; p += 1) {
|
|
547
|
+
const [parameter, parameterOffset] = readUtf8(data, offset, checkBounds);
|
|
548
|
+
offset = parameterOffset;
|
|
549
|
+
parameters.push(parameter);
|
|
550
|
+
}
|
|
551
|
+
caps.supportedParameters = parameters;
|
|
552
|
+
}
|
|
553
|
+
serviceCapabilities[serviceName] = caps;
|
|
554
|
+
}
|
|
555
|
+
setOffset(offset);
|
|
556
|
+
return Object.keys(serviceCapabilities).length > 0 ? serviceCapabilities : undefined;
|
|
557
|
+
}
|
|
558
|
+
function pushUtf8(parts, value) {
|
|
559
|
+
const bytes = new TextEncoder().encode(value);
|
|
560
|
+
if (bytes.length > 255) {
|
|
561
|
+
throw new Error(`Metadata string too long (${bytes.length} bytes)`);
|
|
562
|
+
}
|
|
563
|
+
parts.push(new Uint8Array([bytes.length]));
|
|
564
|
+
parts.push(bytes);
|
|
565
|
+
}
|
|
566
|
+
function pushServiceEntryCount(parts, count, hasWideServiceCounts) {
|
|
567
|
+
if (hasWideServiceCounts) {
|
|
568
|
+
if (count > 0xffff)
|
|
569
|
+
throw new Error(`Service entry count ${count} exceeds uint16`);
|
|
570
|
+
const countBuffer = new ArrayBuffer(2);
|
|
571
|
+
new DataView(countBuffer).setUint16(0, count, false);
|
|
572
|
+
parts.push(new Uint8Array(countBuffer));
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
if (count > 0xff)
|
|
576
|
+
throw new Error(`Service entry count ${count} requires metadata v${WIDE_SERVICE_COUNTS_METADATA_VERSION}`);
|
|
577
|
+
parts.push(new Uint8Array([count]));
|
|
578
|
+
}
|
|
579
|
+
function readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts) {
|
|
580
|
+
const width = hasWideServiceCounts ? 2 : 1;
|
|
581
|
+
checkBounds(offset, width, data.length);
|
|
582
|
+
if (!hasWideServiceCounts)
|
|
583
|
+
return [data[offset], offset + 1];
|
|
584
|
+
return [new DataView(data.buffer, data.byteOffset + offset, 2).getUint16(0, false), offset + 2];
|
|
585
|
+
}
|
|
586
|
+
function decodeServiceUnitBillingModels(data, getOffset, setOffset, checkBounds, hasWideServiceCounts) {
|
|
587
|
+
let offset = getOffset();
|
|
588
|
+
const [entryCount, nextOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
|
|
589
|
+
offset = nextOffset;
|
|
590
|
+
const serviceUnitBillingModels = {};
|
|
591
|
+
for (let i = 0; i < entryCount; i += 1) {
|
|
592
|
+
const [serviceName, serviceOffset] = readUtf8(data, offset, checkBounds);
|
|
593
|
+
offset = serviceOffset;
|
|
594
|
+
checkBounds(offset, 1, data.length);
|
|
595
|
+
const protocol = WELL_KNOWN_SERVICE_API_PROTOCOLS[data[offset]];
|
|
596
|
+
offset += 1;
|
|
597
|
+
if (!protocol) {
|
|
598
|
+
throw new Error("Unsupported service unit billing protocol id");
|
|
599
|
+
}
|
|
600
|
+
checkBounds(offset, 2, data.length);
|
|
601
|
+
const version = data[offset];
|
|
602
|
+
offset += 1;
|
|
603
|
+
if (version !== 1) {
|
|
604
|
+
throw new Error(`Unsupported service unit billing model version ${version}`);
|
|
605
|
+
}
|
|
606
|
+
const componentCount = data[offset];
|
|
607
|
+
offset += 1;
|
|
608
|
+
const components = [];
|
|
609
|
+
for (let j = 0; j < componentCount; j += 1) {
|
|
610
|
+
checkBounds(offset, 6, data.length);
|
|
611
|
+
const unit = UNIT_BILLING_UNITS_BY_ID[data[offset]];
|
|
612
|
+
offset += 1;
|
|
613
|
+
if (!unit) {
|
|
614
|
+
throw new Error("Unsupported service unit billing component unit");
|
|
615
|
+
}
|
|
616
|
+
const priceUsd = new DataView(data.buffer, data.byteOffset + offset, 4).getFloat32(0, false);
|
|
617
|
+
offset += 4;
|
|
618
|
+
const matchCount = data[offset];
|
|
619
|
+
offset += 1;
|
|
620
|
+
const match = {};
|
|
621
|
+
for (let k = 0; k < matchCount; k += 1) {
|
|
622
|
+
checkBounds(offset, 1, data.length);
|
|
623
|
+
const key = UNIT_BILLING_MATCH_KEYS_BY_ID[data[offset]];
|
|
624
|
+
offset += 1;
|
|
625
|
+
if (!key) {
|
|
626
|
+
throw new Error("Unsupported service unit billing match key");
|
|
627
|
+
}
|
|
628
|
+
const [value, valueOffset] = readUtf8(data, offset, checkBounds);
|
|
629
|
+
offset = valueOffset;
|
|
630
|
+
match[key] = value;
|
|
631
|
+
}
|
|
632
|
+
const base = { unit, priceUsd, ...(Object.keys(match).length > 0 ? { match } : {}) };
|
|
633
|
+
components.push(base);
|
|
634
|
+
}
|
|
635
|
+
serviceUnitBillingModels[serviceName] = {
|
|
636
|
+
...(serviceUnitBillingModels[serviceName] ?? {}),
|
|
637
|
+
[protocol]: { version: 1, components },
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
setOffset(offset);
|
|
641
|
+
return Object.keys(serviceUnitBillingModels).length > 0 ? serviceUnitBillingModels : undefined;
|
|
642
|
+
}
|
|
643
|
+
function readUtf8(data, offset, checkBounds) {
|
|
644
|
+
checkBounds(offset, 1, data.length);
|
|
645
|
+
const length = data[offset];
|
|
646
|
+
const valueOffset = offset + 1;
|
|
647
|
+
checkBounds(valueOffset, length, data.length);
|
|
648
|
+
return [new TextDecoder().decode(data.slice(valueOffset, valueOffset + length)), valueOffset + length];
|
|
649
|
+
}
|
|
338
650
|
/**
|
|
339
651
|
* Decode binary metadata back into PeerMetadata.
|
|
340
652
|
*/
|
|
@@ -353,6 +665,7 @@ export function decodeMetadata(data) {
|
|
|
353
665
|
const hasServiceCategoryExtensions = version >= SERVICE_CATEGORIES_METADATA_VERSION;
|
|
354
666
|
const hasServiceApiProtocolExtensions = version >= SERVICE_API_PROTOCOLS_METADATA_VERSION;
|
|
355
667
|
const hasPublicAddressExtension = version >= PUBLIC_ADDRESS_METADATA_VERSION;
|
|
668
|
+
const hasWideServiceCounts = version >= WIDE_SERVICE_COUNTS_METADATA_VERSION;
|
|
356
669
|
offset += 1;
|
|
357
670
|
// peerId: 20 bytes (EVM address)
|
|
358
671
|
checkBounds(offset, 20, data.length);
|
|
@@ -384,10 +697,8 @@ export function decodeMetadata(data) {
|
|
|
384
697
|
checkBounds(offset, providerLen, data.length);
|
|
385
698
|
const provider = new TextDecoder().decode(data.slice(offset, offset + providerLen));
|
|
386
699
|
offset += providerLen;
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
const serviceCount = data[offset];
|
|
390
|
-
offset += 1;
|
|
700
|
+
const [serviceCount, serviceCountOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
|
|
701
|
+
offset = serviceCountOffset;
|
|
391
702
|
const services = [];
|
|
392
703
|
for (let j = 0; j < serviceCount; j++) {
|
|
393
704
|
checkBounds(offset, 1, data.length);
|
|
@@ -414,9 +725,8 @@ export function decodeMetadata(data) {
|
|
|
414
725
|
const defaultCachedInputUsdPerMillion = cachedInputPriceView.getFloat32(0, false);
|
|
415
726
|
offset += 4;
|
|
416
727
|
// servicePricing entries
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
offset += 1;
|
|
728
|
+
const [servicePricingCount, servicePricingOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
|
|
729
|
+
offset = servicePricingOffset;
|
|
420
730
|
const servicePricing = {};
|
|
421
731
|
for (let j = 0; j < servicePricingCount; j++) {
|
|
422
732
|
checkBounds(offset, 1, data.length);
|
|
@@ -446,9 +756,8 @@ export function decodeMetadata(data) {
|
|
|
446
756
|
}
|
|
447
757
|
let serviceCategories;
|
|
448
758
|
if (hasServiceCategoryExtensions) {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
offset += 1;
|
|
759
|
+
const [serviceCategoryCount, serviceCategoryOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
|
|
760
|
+
offset = serviceCategoryOffset;
|
|
452
761
|
if (serviceCategoryCount > 0) {
|
|
453
762
|
serviceCategories = {};
|
|
454
763
|
for (let j = 0; j < serviceCategoryCount; j++) {
|
|
@@ -477,9 +786,8 @@ export function decodeMetadata(data) {
|
|
|
477
786
|
}
|
|
478
787
|
let serviceApiProtocols;
|
|
479
788
|
if (hasServiceApiProtocolExtensions) {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
offset += 1;
|
|
789
|
+
const [serviceApiProtocolCount, serviceApiProtocolOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
|
|
790
|
+
offset = serviceApiProtocolOffset;
|
|
483
791
|
if (serviceApiProtocolCount > 0) {
|
|
484
792
|
serviceApiProtocols = {};
|
|
485
793
|
for (let j = 0; j < serviceApiProtocolCount; j++) {
|
|
@@ -506,6 +814,12 @@ export function decodeMetadata(data) {
|
|
|
506
814
|
}
|
|
507
815
|
}
|
|
508
816
|
}
|
|
817
|
+
const serviceUnitBillingModels = version >= SERVICE_UNIT_BILLING_METADATA_VERSION
|
|
818
|
+
? decodeServiceUnitBillingModels(data, () => offset, (next) => { offset = next; }, checkBounds, hasWideServiceCounts)
|
|
819
|
+
: undefined;
|
|
820
|
+
const serviceCapabilities = version >= SERVICE_CAPABILITIES_METADATA_VERSION
|
|
821
|
+
? decodeServiceCapabilities(data, () => offset, (next) => { offset = next; }, checkBounds, hasWideServiceCounts)
|
|
822
|
+
: undefined;
|
|
509
823
|
// maxConcurrency: 2 bytes uint16
|
|
510
824
|
checkBounds(offset, 2, data.length);
|
|
511
825
|
const maxConcView = new DataView(data.buffer, data.byteOffset + offset, 2);
|
|
@@ -527,6 +841,8 @@ export function decodeMetadata(data) {
|
|
|
527
841
|
...(servicePricingCount > 0 ? { servicePricing } : {}),
|
|
528
842
|
...(serviceCategories && Object.keys(serviceCategories).length > 0 ? { serviceCategories } : {}),
|
|
529
843
|
...(serviceApiProtocols && Object.keys(serviceApiProtocols).length > 0 ? { serviceApiProtocols } : {}),
|
|
844
|
+
...(serviceUnitBillingModels && Object.keys(serviceUnitBillingModels).length > 0 ? { serviceUnitBillingModels } : {}),
|
|
845
|
+
...(serviceCapabilities && Object.keys(serviceCapabilities).length > 0 ? { serviceCapabilities } : {}),
|
|
530
846
|
maxConcurrency,
|
|
531
847
|
currentLoad,
|
|
532
848
|
});
|