@opendatalabs/vana-sdk 3.18.1 → 3.19.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/README.md +141 -0
- package/dist/auth/web3-signed-builder.cjs +3 -0
- package/dist/auth/web3-signed-builder.cjs.map +1 -1
- package/dist/auth/web3-signed-builder.d.ts +14 -0
- package/dist/auth/web3-signed-builder.js +3 -0
- package/dist/auth/web3-signed-builder.js.map +1 -1
- package/dist/errors.cjs +69 -0
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +117 -2
- package/dist/errors.js +60 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.js +577 -29
- package/dist/index.browser.js.map +4 -4
- package/dist/index.node.cjs +605 -29
- package/dist/index.node.cjs.map +4 -4
- package/dist/index.node.d.ts +1 -0
- package/dist/index.node.js +577 -29
- package/dist/index.node.js.map +4 -4
- package/dist/protocol/derivative-questions.cjs +518 -0
- package/dist/protocol/derivative-questions.cjs.map +1 -0
- package/dist/protocol/derivative-questions.d.ts +396 -0
- package/dist/protocol/derivative-questions.js +507 -0
- package/dist/protocol/derivative-questions.js.map +1 -0
- package/dist/protocol/derivative-questions.test.d.ts +1 -0
- package/dist/protocol/personal-server-write.cjs +12 -108
- package/dist/protocol/personal-server-write.cjs.map +1 -1
- package/dist/protocol/personal-server-write.d.ts +2 -17
- package/dist/protocol/personal-server-write.js +7 -98
- package/dist/protocol/personal-server-write.js.map +1 -1
- package/dist/protocol/write-request.cjs +156 -0
- package/dist/protocol/write-request.cjs.map +1 -0
- package/dist/protocol/write-request.d.ts +75 -0
- package/dist/protocol/write-request.js +124 -0
- package/dist/protocol/write-request.js.map +1 -0
- package/dist/tests/mock-personal-server.d.ts +54 -0
- package/package.json +1 -1
package/dist/index.browser.js
CHANGED
|
@@ -1349,6 +1349,57 @@ var LineageReadError = class extends VanaError {
|
|
|
1349
1349
|
errorCode;
|
|
1350
1350
|
details;
|
|
1351
1351
|
};
|
|
1352
|
+
var DerivativeQuestionRejectedError = class extends PersonalServerWriteError {
|
|
1353
|
+
constructor(message, status, errorCode = null, details) {
|
|
1354
|
+
super(message, "DERIVATIVE_QUESTION_REJECTED", status, errorCode, details);
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
var DerivativeQuestionInvalidError = class extends PersonalServerWriteError {
|
|
1358
|
+
constructor(message, status = 400, errorCode = null, details) {
|
|
1359
|
+
super(message, "DERIVATIVE_QUESTION_INVALID", status, errorCode, details);
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1362
|
+
var DerivativeQuestionNotFoundError = class extends PersonalServerWriteError {
|
|
1363
|
+
constructor(message, errorCode = null, details) {
|
|
1364
|
+
super(message, "DERIVATIVE_QUESTION_NOT_FOUND", 404, errorCode, details);
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
var DerivativeDerivedScopeRequiredError = class extends PersonalServerWriteError {
|
|
1368
|
+
constructor(message, errorCode = null, details) {
|
|
1369
|
+
super(
|
|
1370
|
+
message,
|
|
1371
|
+
"DERIVATIVE_DERIVED_SCOPE_REQUIRED",
|
|
1372
|
+
400,
|
|
1373
|
+
errorCode,
|
|
1374
|
+
details
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
};
|
|
1378
|
+
var DerivativeSourceNotGrantedError = class extends PersonalServerWriteError {
|
|
1379
|
+
constructor(message, errorCode = null, details) {
|
|
1380
|
+
super(message, "DERIVATIVE_SOURCE_NOT_GRANTED", 403, errorCode, details);
|
|
1381
|
+
}
|
|
1382
|
+
};
|
|
1383
|
+
var DerivativeCycleError = class extends PersonalServerWriteError {
|
|
1384
|
+
constructor(message, errorCode = null, details) {
|
|
1385
|
+
super(message, "DERIVATIVE_CYCLE", 409, errorCode, details);
|
|
1386
|
+
}
|
|
1387
|
+
};
|
|
1388
|
+
var DerivativeComputeUnavailableError = class extends PersonalServerWriteError {
|
|
1389
|
+
constructor(message, errorCode = null, details) {
|
|
1390
|
+
super(message, "DERIVATIVE_COMPUTE_UNAVAILABLE", 503, errorCode, details);
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1393
|
+
var DerivativeQuestionTimeoutError = class extends PersonalServerWriteError {
|
|
1394
|
+
constructor(message, details) {
|
|
1395
|
+
super(message, "DERIVATIVE_QUESTION_TIMEOUT", void 0, null, details);
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
var DerivativeQuestionFailedError = class extends PersonalServerWriteError {
|
|
1399
|
+
constructor(message, details) {
|
|
1400
|
+
super(message, "DERIVATIVE_QUESTION_FAILED", void 0, null, details);
|
|
1401
|
+
}
|
|
1402
|
+
};
|
|
1352
1403
|
var DataPointDeletedError = class extends VanaError {
|
|
1353
1404
|
constructor(message, details = {}) {
|
|
1354
1405
|
super(message, "DATA_POINT_DELETED");
|
|
@@ -29106,6 +29157,9 @@ async function buildWeb3SignedHeader(params) {
|
|
|
29106
29157
|
if (params.grantId !== void 0) {
|
|
29107
29158
|
payload["grantId"] = params.grantId;
|
|
29108
29159
|
}
|
|
29160
|
+
if (params.nonce !== void 0) {
|
|
29161
|
+
payload["nonce"] = params.nonce;
|
|
29162
|
+
}
|
|
29109
29163
|
const sortedPayload = Object.keys(payload).sort().reduce((acc, key) => {
|
|
29110
29164
|
acc[key] = payload[key];
|
|
29111
29165
|
return acc;
|
|
@@ -33764,32 +33818,13 @@ function tryGrantPermissions(scopes) {
|
|
|
33764
33818
|
}
|
|
33765
33819
|
|
|
33766
33820
|
// src/protocol/personal-server-write.ts
|
|
33767
|
-
import { sha256 as
|
|
33768
|
-
import { bytesToHex as
|
|
33821
|
+
import { sha256 as sha2566 } from "@noble/hashes/sha2";
|
|
33822
|
+
import { bytesToHex as bytesToHex3, isAddress as isAddress6 } from "viem";
|
|
33769
33823
|
import { z as z4 } from "zod";
|
|
33770
|
-
|
|
33771
|
-
|
|
33772
|
-
|
|
33773
|
-
|
|
33774
|
-
var MAX_LINEAGE_SOURCES = 256;
|
|
33775
|
-
var WRITE_FILENAME_HEADER = "X-Filename";
|
|
33776
|
-
var WRITE_CONTENT_DISPOSITION_HEADER = "Content-Disposition";
|
|
33777
|
-
var WRITER_ATTRIBUTION_KEY = "$writtenBy";
|
|
33778
|
-
var LINEAGE_KEY = "$lineage";
|
|
33779
|
-
var RESERVED_WRITE_KEYS = [
|
|
33780
|
-
WRITER_ATTRIBUTION_KEY,
|
|
33781
|
-
LINEAGE_KEY
|
|
33782
|
-
];
|
|
33783
|
-
var WriteDataResultSchema = IngestResponseSchema.extend({
|
|
33784
|
-
// Present when the write carried lineage: the validated, lowercased ids.
|
|
33785
|
-
lineage: z4.object({ sources: z4.array(z4.string()) }).optional()
|
|
33786
|
-
});
|
|
33787
|
-
var WriteSessionResponseSchema = z4.object({
|
|
33788
|
-
access_token: z4.string().min(1),
|
|
33789
|
-
token_type: z4.string(),
|
|
33790
|
-
expires_in: z4.number().nonnegative(),
|
|
33791
|
-
scope: z4.string()
|
|
33792
|
-
});
|
|
33824
|
+
|
|
33825
|
+
// src/protocol/write-request.ts
|
|
33826
|
+
import { sha256 as sha2565 } from "@noble/hashes/sha2";
|
|
33827
|
+
import { bytesToHex as bytesToHex2 } from "viem";
|
|
33793
33828
|
function normalizeBaseUrl2(url) {
|
|
33794
33829
|
return url.replace(/\/+$/, "");
|
|
33795
33830
|
}
|
|
@@ -33800,9 +33835,6 @@ function resolveFetch2(fetchFn) {
|
|
|
33800
33835
|
}
|
|
33801
33836
|
return resolved;
|
|
33802
33837
|
}
|
|
33803
|
-
function dataPath(scope) {
|
|
33804
|
-
return `/v1/data/${encodeURIComponent(scope)}`;
|
|
33805
|
-
}
|
|
33806
33838
|
function errorMessage(err) {
|
|
33807
33839
|
return err instanceof Error ? err.message : String(err);
|
|
33808
33840
|
}
|
|
@@ -33853,6 +33885,18 @@ function nextProofIat(proofKey) {
|
|
|
33853
33885
|
if (waitSec <= 0) return Promise.resolve(iat);
|
|
33854
33886
|
return sleep2(waitSec * 1e3).then(() => iat);
|
|
33855
33887
|
}
|
|
33888
|
+
function freshProofNonce() {
|
|
33889
|
+
const webCrypto = globalThis.crypto;
|
|
33890
|
+
if (typeof webCrypto?.randomUUID === "function") {
|
|
33891
|
+
return webCrypto.randomUUID();
|
|
33892
|
+
}
|
|
33893
|
+
if (typeof webCrypto?.getRandomValues === "function") {
|
|
33894
|
+
return bytesToHex2(webCrypto.getRandomValues(new Uint8Array(16)));
|
|
33895
|
+
}
|
|
33896
|
+
throw new WriteRequestError(
|
|
33897
|
+
"No secure random source available to build a proof nonce; provide a crypto global"
|
|
33898
|
+
);
|
|
33899
|
+
}
|
|
33856
33900
|
function proofKeyFor(parts) {
|
|
33857
33901
|
return bytesToHex2(
|
|
33858
33902
|
sha2565(
|
|
@@ -33890,6 +33934,34 @@ async function sendWithFreshProof(label, fetchFn, options, proofKey, build) {
|
|
|
33890
33934
|
lastError
|
|
33891
33935
|
);
|
|
33892
33936
|
}
|
|
33937
|
+
|
|
33938
|
+
// src/protocol/personal-server-write.ts
|
|
33939
|
+
var WRITE_SESSION_PATH = "/v1/write/session";
|
|
33940
|
+
var WRITE_SIGNATURE_HEADER = "X-Vana-Write-Signature";
|
|
33941
|
+
var WRITE_METADATA_HEADER = "X-Vana-Metadata";
|
|
33942
|
+
var LINEAGE_FIELD = "lineage";
|
|
33943
|
+
var MAX_LINEAGE_SOURCES = 256;
|
|
33944
|
+
var WRITE_FILENAME_HEADER = "X-Filename";
|
|
33945
|
+
var WRITE_CONTENT_DISPOSITION_HEADER = "Content-Disposition";
|
|
33946
|
+
var WRITER_ATTRIBUTION_KEY = "$writtenBy";
|
|
33947
|
+
var LINEAGE_KEY = "$lineage";
|
|
33948
|
+
var RESERVED_WRITE_KEYS = [
|
|
33949
|
+
WRITER_ATTRIBUTION_KEY,
|
|
33950
|
+
LINEAGE_KEY
|
|
33951
|
+
];
|
|
33952
|
+
var WriteDataResultSchema = IngestResponseSchema.extend({
|
|
33953
|
+
// Present when the write carried lineage: the validated, lowercased ids.
|
|
33954
|
+
lineage: z4.object({ sources: z4.array(z4.string()) }).optional()
|
|
33955
|
+
});
|
|
33956
|
+
var WriteSessionResponseSchema = z4.object({
|
|
33957
|
+
access_token: z4.string().min(1),
|
|
33958
|
+
token_type: z4.string(),
|
|
33959
|
+
expires_in: z4.number().nonnegative(),
|
|
33960
|
+
scope: z4.string()
|
|
33961
|
+
});
|
|
33962
|
+
function dataPath(scope) {
|
|
33963
|
+
return `/v1/data/${encodeURIComponent(scope)}`;
|
|
33964
|
+
}
|
|
33893
33965
|
async function openWriteSession(params) {
|
|
33894
33966
|
const fetchFn = resolveFetch2(params.fetch);
|
|
33895
33967
|
const personalServerUrl = normalizeBaseUrl2(params.personalServerUrl);
|
|
@@ -34021,7 +34093,7 @@ function binaryWriteSignedBytes(input) {
|
|
|
34021
34093
|
mimeType: normalizeBinaryMimeType(input.contentType),
|
|
34022
34094
|
...input.filename ? { filename: input.filename } : {},
|
|
34023
34095
|
sizeBytes: input.bytes.length,
|
|
34024
|
-
contentHash:
|
|
34096
|
+
contentHash: bytesToHex3(sha2566(input.bytes)),
|
|
34025
34097
|
encoding: "base64",
|
|
34026
34098
|
content: toBase64(input.bytes),
|
|
34027
34099
|
...metadata !== void 0 ? { metadata } : {}
|
|
@@ -34318,6 +34390,454 @@ async function writePersonalServerData(params) {
|
|
|
34318
34390
|
return { ...result, session };
|
|
34319
34391
|
}
|
|
34320
34392
|
|
|
34393
|
+
// src/protocol/derivative-questions.ts
|
|
34394
|
+
import { z as z5 } from "zod";
|
|
34395
|
+
var DERIVATIVE_QUESTIONS_PATH = "/v1/derivatives/questions";
|
|
34396
|
+
var MAX_QUESTION_SOURCE_SCOPES = 16;
|
|
34397
|
+
var MAX_QUESTION_CHARS = 8e3;
|
|
34398
|
+
var MAX_QUESTION_MODEL_CHARS = 128;
|
|
34399
|
+
var MODEL_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/;
|
|
34400
|
+
var DEFAULT_QUESTION_TIMEOUT_MS = 12e4;
|
|
34401
|
+
var DEFAULT_QUESTION_POLL_INTERVAL_MS = 2e3;
|
|
34402
|
+
var SESSION_REFRESH_SKEW_MS = 3e4;
|
|
34403
|
+
var QUESTION_STATUSES = [
|
|
34404
|
+
"pending",
|
|
34405
|
+
"ready",
|
|
34406
|
+
"failed",
|
|
34407
|
+
"stale"
|
|
34408
|
+
];
|
|
34409
|
+
var QuestionStatusSchema = z5.enum(QUESTION_STATUSES);
|
|
34410
|
+
var QuestionRegisteredBySchema = z5.union([
|
|
34411
|
+
z5.object({ kind: z5.literal("owner") }),
|
|
34412
|
+
z5.object({
|
|
34413
|
+
kind: z5.literal("builder"),
|
|
34414
|
+
builder: z5.string(),
|
|
34415
|
+
grantId: z5.string()
|
|
34416
|
+
})
|
|
34417
|
+
]);
|
|
34418
|
+
var nullableString = z5.string().nullish().transform((value) => value ?? null);
|
|
34419
|
+
var DerivativeQuestionSchema = z5.object({
|
|
34420
|
+
questionId: z5.string().min(1),
|
|
34421
|
+
derivedScope: z5.string().min(1),
|
|
34422
|
+
sourceScopes: z5.array(z5.string()),
|
|
34423
|
+
question: z5.string(),
|
|
34424
|
+
/** The model override, or `null` for the server's default. */
|
|
34425
|
+
model: nullableString,
|
|
34426
|
+
registeredBy: QuestionRegisteredBySchema,
|
|
34427
|
+
status: QuestionStatusSchema,
|
|
34428
|
+
/** A short reason, set only while `status` is `failed`. */
|
|
34429
|
+
error: nullableString,
|
|
34430
|
+
createdAt: z5.string(),
|
|
34431
|
+
updatedAt: nullableString,
|
|
34432
|
+
/** When the last compute finished, or `null` while `pending`. */
|
|
34433
|
+
lastComputedAt: nullableString,
|
|
34434
|
+
/** Local version of the derived record the last compute wrote. */
|
|
34435
|
+
derivedVersion: z5.number().nullish().transform((value) => value ?? null),
|
|
34436
|
+
derivedCollectedAt: nullableString
|
|
34437
|
+
});
|
|
34438
|
+
var QuestionListSchema = z5.object({
|
|
34439
|
+
questions: z5.array(DerivativeQuestionSchema)
|
|
34440
|
+
});
|
|
34441
|
+
var QuestionRecomputeResultSchema = DerivativeQuestionSchema;
|
|
34442
|
+
var QuestionDeleteResultSchema = z5.object({
|
|
34443
|
+
questionId: z5.string().min(1),
|
|
34444
|
+
deleted: z5.literal(true)
|
|
34445
|
+
});
|
|
34446
|
+
var sessionsBySigner = /* @__PURE__ */ new WeakMap();
|
|
34447
|
+
function sessionCacheKey(personalServerUrl, audience, grantId, fetchFn) {
|
|
34448
|
+
return JSON.stringify([personalServerUrl, audience, grantId]) + fetchIdOf(fetchFn);
|
|
34449
|
+
}
|
|
34450
|
+
var fetchIds = /* @__PURE__ */ new WeakMap();
|
|
34451
|
+
var nextFetchId = 0;
|
|
34452
|
+
function fetchIdOf(fetchFn) {
|
|
34453
|
+
let id = fetchIds.get(fetchFn);
|
|
34454
|
+
if (id === void 0) {
|
|
34455
|
+
id = ++nextFetchId;
|
|
34456
|
+
fetchIds.set(fetchFn, id);
|
|
34457
|
+
}
|
|
34458
|
+
return `#${id}`;
|
|
34459
|
+
}
|
|
34460
|
+
function resolveRequest(params) {
|
|
34461
|
+
if (typeof params.personalServerUrl !== "string" || params.personalServerUrl.length === 0) {
|
|
34462
|
+
throw new WriteRequestError("personalServerUrl is required");
|
|
34463
|
+
}
|
|
34464
|
+
if (typeof params.grantId !== "string" || params.grantId.length === 0) {
|
|
34465
|
+
throw new WriteRequestError(
|
|
34466
|
+
"grantId is required; a question call runs under the grant carrying write:<derivedScope>"
|
|
34467
|
+
);
|
|
34468
|
+
}
|
|
34469
|
+
if (params.signer === null || typeof params.signer !== "object") {
|
|
34470
|
+
throw new WriteRequestError(
|
|
34471
|
+
"signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
|
|
34472
|
+
);
|
|
34473
|
+
}
|
|
34474
|
+
const fetchFn = resolveFetch2(params.fetch);
|
|
34475
|
+
const baseUrl = normalizeBaseUrl2(params.personalServerUrl);
|
|
34476
|
+
const audience = params.audience ?? baseUrl;
|
|
34477
|
+
return {
|
|
34478
|
+
baseUrl,
|
|
34479
|
+
audience,
|
|
34480
|
+
fetchFn,
|
|
34481
|
+
cacheKey: sessionCacheKey(baseUrl, audience, params.grantId, fetchFn),
|
|
34482
|
+
signerKey: params.signer
|
|
34483
|
+
};
|
|
34484
|
+
}
|
|
34485
|
+
async function resolveSession(params, resolved, force) {
|
|
34486
|
+
let cache = sessionsBySigner.get(resolved.signerKey);
|
|
34487
|
+
if (cache === void 0) {
|
|
34488
|
+
cache = /* @__PURE__ */ new Map();
|
|
34489
|
+
sessionsBySigner.set(resolved.signerKey, cache);
|
|
34490
|
+
}
|
|
34491
|
+
const cached = cache.get(resolved.cacheKey);
|
|
34492
|
+
if (!force && cached !== void 0 && cached.expiresAt > Date.now() + SESSION_REFRESH_SKEW_MS) {
|
|
34493
|
+
return cached;
|
|
34494
|
+
}
|
|
34495
|
+
if (force) cache.delete(resolved.cacheKey);
|
|
34496
|
+
const session = await openWriteSession({
|
|
34497
|
+
personalServerUrl: resolved.baseUrl,
|
|
34498
|
+
signer: params.signer,
|
|
34499
|
+
grantId: params.grantId,
|
|
34500
|
+
account: params.account,
|
|
34501
|
+
audience: resolved.audience,
|
|
34502
|
+
fetch: resolved.fetchFn,
|
|
34503
|
+
headers: params.headers,
|
|
34504
|
+
retry: params.retry
|
|
34505
|
+
});
|
|
34506
|
+
cache.set(resolved.cacheKey, session);
|
|
34507
|
+
return session;
|
|
34508
|
+
}
|
|
34509
|
+
var PROOF_FAILURE_CODES = /* @__PURE__ */ new Set([
|
|
34510
|
+
"WRITE_ATTRIBUTION_REQUIRED",
|
|
34511
|
+
"WRITE_ATTRIBUTION_INVALID",
|
|
34512
|
+
"WRITE_ATTRIBUTION_SIGNER_MISMATCH",
|
|
34513
|
+
"WRITE_ATTRIBUTION_GRANT_MISMATCH",
|
|
34514
|
+
"WRITE_ATTRIBUTION_REPLAY"
|
|
34515
|
+
]);
|
|
34516
|
+
function isStaleSession(errorCode) {
|
|
34517
|
+
return errorCode === null || !PROOF_FAILURE_CODES.has(errorCode);
|
|
34518
|
+
}
|
|
34519
|
+
async function questionErrorFromResponse(response, body) {
|
|
34520
|
+
const { errorCode, message, details } = body ?? await readPersonalServerErrorBody(response);
|
|
34521
|
+
const text = message ?? `Derivative question request failed: ${response.status} ${response.statusText}`;
|
|
34522
|
+
switch (errorCode) {
|
|
34523
|
+
case "DERIVATIVE_SOURCE_NOT_GRANTED":
|
|
34524
|
+
return new DerivativeSourceNotGrantedError(text, errorCode, details);
|
|
34525
|
+
case "DERIVATIVE_CYCLE":
|
|
34526
|
+
return new DerivativeCycleError(text, errorCode, details);
|
|
34527
|
+
case "DERIVATIVE_COMPUTE_UNAVAILABLE":
|
|
34528
|
+
return new DerivativeComputeUnavailableError(text, errorCode, details);
|
|
34529
|
+
case "DERIVATIVE_QUESTION_INVALID":
|
|
34530
|
+
case "LINEAGE_SCOPE_UNDER_SOURCE_PREFIX":
|
|
34531
|
+
return new DerivativeQuestionInvalidError(
|
|
34532
|
+
text,
|
|
34533
|
+
response.status,
|
|
34534
|
+
errorCode,
|
|
34535
|
+
details
|
|
34536
|
+
);
|
|
34537
|
+
case "DERIVATIVE_QUESTION_NOT_FOUND":
|
|
34538
|
+
return new DerivativeQuestionNotFoundError(text, errorCode, details);
|
|
34539
|
+
case "DERIVATIVE_DERIVED_SCOPE_REQUIRED":
|
|
34540
|
+
return new DerivativeDerivedScopeRequiredError(text, errorCode, details);
|
|
34541
|
+
default:
|
|
34542
|
+
break;
|
|
34543
|
+
}
|
|
34544
|
+
switch (response.status) {
|
|
34545
|
+
case 401:
|
|
34546
|
+
return new WriteUnauthorizedError(text, errorCode, details);
|
|
34547
|
+
case 403:
|
|
34548
|
+
return new WriteForbiddenError(text, errorCode, details);
|
|
34549
|
+
case 404:
|
|
34550
|
+
return new DerivativeQuestionNotFoundError(text, errorCode, details);
|
|
34551
|
+
case 409:
|
|
34552
|
+
return new WriteConflictError(text, errorCode, details);
|
|
34553
|
+
default:
|
|
34554
|
+
return new DerivativeQuestionRejectedError(
|
|
34555
|
+
text,
|
|
34556
|
+
response.status,
|
|
34557
|
+
errorCode,
|
|
34558
|
+
details
|
|
34559
|
+
);
|
|
34560
|
+
}
|
|
34561
|
+
}
|
|
34562
|
+
async function sendOnce(params, resolved, session, spec, bodyBytes) {
|
|
34563
|
+
return sendWithFreshProof(
|
|
34564
|
+
spec.label,
|
|
34565
|
+
resolved.fetchFn,
|
|
34566
|
+
params.retry,
|
|
34567
|
+
proofKeyFor({
|
|
34568
|
+
aud: session.audience,
|
|
34569
|
+
method: spec.method,
|
|
34570
|
+
uri: spec.target,
|
|
34571
|
+
grantId: session.grantId,
|
|
34572
|
+
signedBytes: bodyBytes
|
|
34573
|
+
}),
|
|
34574
|
+
async (iat) => {
|
|
34575
|
+
const headers = new Headers(params.headers);
|
|
34576
|
+
headers.set("Accept", "application/json");
|
|
34577
|
+
headers.set("Authorization", `Bearer ${session.accessToken}`);
|
|
34578
|
+
if (bodyBytes !== void 0) {
|
|
34579
|
+
headers.set("Content-Type", "application/json");
|
|
34580
|
+
}
|
|
34581
|
+
headers.set(
|
|
34582
|
+
WRITE_SIGNATURE_HEADER,
|
|
34583
|
+
await buildWeb3SignedHeader({
|
|
34584
|
+
signMessage: session.signer.signMessage,
|
|
34585
|
+
aud: session.audience,
|
|
34586
|
+
// The proof commits to the whole request target, query included:
|
|
34587
|
+
// `?derivedScope=` is what the list route authorizes against, and a
|
|
34588
|
+
// proof that did not cover it would authorize any other scope.
|
|
34589
|
+
uri: spec.target,
|
|
34590
|
+
method: spec.method,
|
|
34591
|
+
body: bodyBytes,
|
|
34592
|
+
grantId: session.grantId,
|
|
34593
|
+
// Fresh per attempt, so a retry after a thrown `fetch` is never the
|
|
34594
|
+
// proof the server may already have consumed, and so two identical
|
|
34595
|
+
// polls inside one second stay distinct.
|
|
34596
|
+
nonce: freshProofNonce(),
|
|
34597
|
+
iat
|
|
34598
|
+
})
|
|
34599
|
+
);
|
|
34600
|
+
return {
|
|
34601
|
+
url: `${resolved.baseUrl}${spec.target}`,
|
|
34602
|
+
init: {
|
|
34603
|
+
method: spec.method,
|
|
34604
|
+
headers,
|
|
34605
|
+
...bodyBytes === void 0 ? {} : { body: bodyBytes },
|
|
34606
|
+
...params.signal ? { signal: params.signal } : {}
|
|
34607
|
+
}
|
|
34608
|
+
};
|
|
34609
|
+
}
|
|
34610
|
+
);
|
|
34611
|
+
}
|
|
34612
|
+
async function sendQuestionRequest(params, spec, schema) {
|
|
34613
|
+
const resolved = resolveRequest(params);
|
|
34614
|
+
const bodyBytes = spec.body === void 0 ? void 0 : new TextEncoder().encode(JSON.stringify(spec.body));
|
|
34615
|
+
let session = await resolveSession(params, resolved, false);
|
|
34616
|
+
let response = await sendOnce(params, resolved, session, spec, bodyBytes);
|
|
34617
|
+
let errorBody;
|
|
34618
|
+
if (response.status === 401) {
|
|
34619
|
+
errorBody = await readPersonalServerErrorBody(response);
|
|
34620
|
+
if (isStaleSession(errorBody.errorCode)) {
|
|
34621
|
+
session = await resolveSession(params, resolved, true);
|
|
34622
|
+
response = await sendOnce(params, resolved, session, spec, bodyBytes);
|
|
34623
|
+
errorBody = void 0;
|
|
34624
|
+
}
|
|
34625
|
+
}
|
|
34626
|
+
if (!response.ok) {
|
|
34627
|
+
throw await questionErrorFromResponse(response, errorBody);
|
|
34628
|
+
}
|
|
34629
|
+
let body;
|
|
34630
|
+
try {
|
|
34631
|
+
body = await response.json();
|
|
34632
|
+
} catch (err) {
|
|
34633
|
+
throw new DerivativeQuestionRejectedError(
|
|
34634
|
+
`${spec.label} response is not JSON`,
|
|
34635
|
+
response.status,
|
|
34636
|
+
null,
|
|
34637
|
+
{ cause: errorMessage(err) }
|
|
34638
|
+
);
|
|
34639
|
+
}
|
|
34640
|
+
const parsed = schema.safeParse(body);
|
|
34641
|
+
if (!parsed.success) {
|
|
34642
|
+
throw new DerivativeQuestionRejectedError(
|
|
34643
|
+
`${spec.label} response is not a derivative question answer`,
|
|
34644
|
+
response.status,
|
|
34645
|
+
null,
|
|
34646
|
+
{ issues: parsed.error.issues }
|
|
34647
|
+
);
|
|
34648
|
+
}
|
|
34649
|
+
return parsed.data;
|
|
34650
|
+
}
|
|
34651
|
+
function assertQuestionId(questionId) {
|
|
34652
|
+
if (typeof questionId !== "string" || questionId.length === 0) {
|
|
34653
|
+
throw new WriteRequestError("questionId is required");
|
|
34654
|
+
}
|
|
34655
|
+
return `${DERIVATIVE_QUESTIONS_PATH}/${encodeURIComponent(questionId)}`;
|
|
34656
|
+
}
|
|
34657
|
+
function registrationBody(params) {
|
|
34658
|
+
const { derivedScope, question } = params;
|
|
34659
|
+
if (typeof derivedScope !== "string" || derivedScope.length === 0) {
|
|
34660
|
+
throw new WriteRequestError("derivedScope is required");
|
|
34661
|
+
}
|
|
34662
|
+
if (!Array.isArray(params.sourceScopes) || params.sourceScopes.length === 0) {
|
|
34663
|
+
throw new WriteRequestError(
|
|
34664
|
+
"sourceScopes must be a non-empty array of scopes"
|
|
34665
|
+
);
|
|
34666
|
+
}
|
|
34667
|
+
if (params.sourceScopes.length > MAX_QUESTION_SOURCE_SCOPES) {
|
|
34668
|
+
throw new WriteRequestError(
|
|
34669
|
+
`sourceScopes lists ${params.sourceScopes.length} scopes; the maximum is ${MAX_QUESTION_SOURCE_SCOPES}`,
|
|
34670
|
+
{ max: MAX_QUESTION_SOURCE_SCOPES, count: params.sourceScopes.length }
|
|
34671
|
+
);
|
|
34672
|
+
}
|
|
34673
|
+
const sourceScopes = [];
|
|
34674
|
+
for (const scope of params.sourceScopes) {
|
|
34675
|
+
if (typeof scope !== "string" || scope.length === 0) {
|
|
34676
|
+
throw new WriteRequestError("sourceScopes entries must be scope strings");
|
|
34677
|
+
}
|
|
34678
|
+
if (sourceScopes.includes(scope)) {
|
|
34679
|
+
throw new WriteRequestError("sourceScopes must not repeat a scope", {
|
|
34680
|
+
duplicate: scope
|
|
34681
|
+
});
|
|
34682
|
+
}
|
|
34683
|
+
if (scope === derivedScope) {
|
|
34684
|
+
throw new WriteRequestError(
|
|
34685
|
+
"derivedScope cannot be one of its own sources",
|
|
34686
|
+
{ scope }
|
|
34687
|
+
);
|
|
34688
|
+
}
|
|
34689
|
+
sourceScopes.push(scope);
|
|
34690
|
+
}
|
|
34691
|
+
if (typeof question !== "string" || question.trim() === "") {
|
|
34692
|
+
throw new WriteRequestError("question must be a non-empty string");
|
|
34693
|
+
}
|
|
34694
|
+
if (question.length > MAX_QUESTION_CHARS) {
|
|
34695
|
+
throw new WriteRequestError(
|
|
34696
|
+
`question is ${question.length} characters; the maximum is ${MAX_QUESTION_CHARS}`,
|
|
34697
|
+
{ max: MAX_QUESTION_CHARS, length: question.length }
|
|
34698
|
+
);
|
|
34699
|
+
}
|
|
34700
|
+
if (params.model !== void 0) {
|
|
34701
|
+
if (typeof params.model !== "string" || params.model.length > MAX_QUESTION_MODEL_CHARS || !MODEL_ID_PATTERN.test(params.model)) {
|
|
34702
|
+
throw new WriteRequestError("model must be a provider model id", {
|
|
34703
|
+
model: params.model
|
|
34704
|
+
});
|
|
34705
|
+
}
|
|
34706
|
+
}
|
|
34707
|
+
assertDerivedScopeNaming(derivedScope, sourceScopes);
|
|
34708
|
+
return {
|
|
34709
|
+
derivedScope,
|
|
34710
|
+
sourceScopes,
|
|
34711
|
+
question,
|
|
34712
|
+
...params.model === void 0 ? {} : { model: params.model }
|
|
34713
|
+
};
|
|
34714
|
+
}
|
|
34715
|
+
async function registerQuestion(params) {
|
|
34716
|
+
const body = registrationBody(params);
|
|
34717
|
+
return sendQuestionRequest(
|
|
34718
|
+
params,
|
|
34719
|
+
{
|
|
34720
|
+
method: "POST",
|
|
34721
|
+
target: DERIVATIVE_QUESTIONS_PATH,
|
|
34722
|
+
body,
|
|
34723
|
+
label: "Register derivative question"
|
|
34724
|
+
},
|
|
34725
|
+
DerivativeQuestionSchema
|
|
34726
|
+
);
|
|
34727
|
+
}
|
|
34728
|
+
async function getQuestion(params) {
|
|
34729
|
+
const target = assertQuestionId(params.questionId);
|
|
34730
|
+
return sendQuestionRequest(
|
|
34731
|
+
params,
|
|
34732
|
+
{ method: "GET", target, label: "Read derivative question" },
|
|
34733
|
+
DerivativeQuestionSchema
|
|
34734
|
+
);
|
|
34735
|
+
}
|
|
34736
|
+
async function listQuestions(params) {
|
|
34737
|
+
if (typeof params.derivedScope !== "string" || params.derivedScope.length === 0) {
|
|
34738
|
+
throw new WriteRequestError(
|
|
34739
|
+
"derivedScope is required; a builder may only list its own questions on a scope it may write"
|
|
34740
|
+
);
|
|
34741
|
+
}
|
|
34742
|
+
const target = `${DERIVATIVE_QUESTIONS_PATH}?derivedScope=${encodeURIComponent(params.derivedScope)}`;
|
|
34743
|
+
const { questions } = await sendQuestionRequest(
|
|
34744
|
+
params,
|
|
34745
|
+
{
|
|
34746
|
+
method: "GET",
|
|
34747
|
+
target,
|
|
34748
|
+
label: "List derivative questions"
|
|
34749
|
+
},
|
|
34750
|
+
QuestionListSchema
|
|
34751
|
+
);
|
|
34752
|
+
return questions;
|
|
34753
|
+
}
|
|
34754
|
+
async function recomputeQuestion(params) {
|
|
34755
|
+
const target = `${assertQuestionId(params.questionId)}/recompute`;
|
|
34756
|
+
return sendQuestionRequest(
|
|
34757
|
+
params,
|
|
34758
|
+
{ method: "POST", target, label: "Recompute derivative question" },
|
|
34759
|
+
QuestionRecomputeResultSchema
|
|
34760
|
+
);
|
|
34761
|
+
}
|
|
34762
|
+
async function deleteQuestion(params) {
|
|
34763
|
+
const target = assertQuestionId(params.questionId);
|
|
34764
|
+
return sendQuestionRequest(
|
|
34765
|
+
params,
|
|
34766
|
+
{ method: "DELETE", target, label: "Delete derivative question" },
|
|
34767
|
+
QuestionDeleteResultSchema
|
|
34768
|
+
);
|
|
34769
|
+
}
|
|
34770
|
+
function isSettled(status) {
|
|
34771
|
+
return status === "ready" || status === "failed";
|
|
34772
|
+
}
|
|
34773
|
+
function abortError(signal) {
|
|
34774
|
+
const reason = signal.reason;
|
|
34775
|
+
if (reason instanceof Error) return reason;
|
|
34776
|
+
const error = new Error("The operation was aborted");
|
|
34777
|
+
error.name = "AbortError";
|
|
34778
|
+
return error;
|
|
34779
|
+
}
|
|
34780
|
+
async function waitForQuestion(params) {
|
|
34781
|
+
const timeoutMs = Math.max(
|
|
34782
|
+
0,
|
|
34783
|
+
params.timeoutMs ?? DEFAULT_QUESTION_TIMEOUT_MS
|
|
34784
|
+
);
|
|
34785
|
+
const pollIntervalMs = Math.max(
|
|
34786
|
+
0,
|
|
34787
|
+
params.pollIntervalMs ?? DEFAULT_QUESTION_POLL_INTERVAL_MS
|
|
34788
|
+
);
|
|
34789
|
+
const deadline = Date.now() + timeoutMs;
|
|
34790
|
+
for (; ; ) {
|
|
34791
|
+
if (params.signal?.aborted) throw abortError(params.signal);
|
|
34792
|
+
const latest = await getQuestion(params);
|
|
34793
|
+
if (isSettled(latest.status)) return latest;
|
|
34794
|
+
const remaining = deadline - Date.now();
|
|
34795
|
+
if (remaining <= 0) {
|
|
34796
|
+
throw new DerivativeQuestionTimeoutError(
|
|
34797
|
+
`Derivative question ${latest.questionId} was still ${latest.status} after ${timeoutMs}ms`,
|
|
34798
|
+
{
|
|
34799
|
+
questionId: latest.questionId,
|
|
34800
|
+
derivedScope: latest.derivedScope,
|
|
34801
|
+
status: latest.status,
|
|
34802
|
+
timeoutMs
|
|
34803
|
+
}
|
|
34804
|
+
);
|
|
34805
|
+
}
|
|
34806
|
+
await sleep2(Math.min(pollIntervalMs, remaining));
|
|
34807
|
+
}
|
|
34808
|
+
}
|
|
34809
|
+
async function askPersonalServer(params) {
|
|
34810
|
+
const registered = await registerQuestion(params);
|
|
34811
|
+
const registration = await waitForQuestion({
|
|
34812
|
+
...params,
|
|
34813
|
+
questionId: registered.questionId
|
|
34814
|
+
});
|
|
34815
|
+
if (registration.status !== "ready") {
|
|
34816
|
+
throw new DerivativeQuestionFailedError(
|
|
34817
|
+
`Derivative question ${registration.questionId} failed: ${registration.error ?? "no reason given"}`,
|
|
34818
|
+
{
|
|
34819
|
+
questionId: registration.questionId,
|
|
34820
|
+
derivedScope: registration.derivedScope,
|
|
34821
|
+
error: registration.error
|
|
34822
|
+
}
|
|
34823
|
+
);
|
|
34824
|
+
}
|
|
34825
|
+
const signer = resolveWriteSigner(params.signer, {
|
|
34826
|
+
account: params.account
|
|
34827
|
+
});
|
|
34828
|
+
const readParams = {
|
|
34829
|
+
personalServerUrl: normalizeBaseUrl2(params.personalServerUrl),
|
|
34830
|
+
scope: params.derivedScope,
|
|
34831
|
+
grantId: params.grantId,
|
|
34832
|
+
signMessage: signer.signMessage,
|
|
34833
|
+
...params.audience === void 0 ? {} : { audience: params.audience },
|
|
34834
|
+
...params.headers === void 0 ? {} : { headers: params.headers },
|
|
34835
|
+
...params.fetch === void 0 ? {} : { fetch: params.fetch }
|
|
34836
|
+
};
|
|
34837
|
+
const record = await readPersonalServerData(readParams);
|
|
34838
|
+
return { registration, record };
|
|
34839
|
+
}
|
|
34840
|
+
|
|
34321
34841
|
// src/protocol/gateway.ts
|
|
34322
34842
|
function withGrantPermissions(grant) {
|
|
34323
34843
|
const stripped = { ...grant };
|
|
@@ -34930,11 +35450,24 @@ export {
|
|
|
34930
35450
|
ContractFactory,
|
|
34931
35451
|
ContractNotFoundError,
|
|
34932
35452
|
DATA_REGISTRY_STATUS_ABI,
|
|
35453
|
+
DEFAULT_QUESTION_POLL_INTERVAL_MS,
|
|
35454
|
+
DEFAULT_QUESTION_TIMEOUT_MS,
|
|
35455
|
+
DERIVATIVE_QUESTIONS_PATH,
|
|
34933
35456
|
DataFileEnvelopeSchema,
|
|
34934
35457
|
DataPointDeletedError,
|
|
34935
35458
|
DataPointNotFoundError,
|
|
34936
35459
|
DataPointStatus,
|
|
34937
35460
|
DataPointVersionConflictError,
|
|
35461
|
+
DerivativeComputeUnavailableError,
|
|
35462
|
+
DerivativeCycleError,
|
|
35463
|
+
DerivativeDerivedScopeRequiredError,
|
|
35464
|
+
DerivativeQuestionFailedError,
|
|
35465
|
+
DerivativeQuestionInvalidError,
|
|
35466
|
+
DerivativeQuestionNotFoundError,
|
|
35467
|
+
DerivativeQuestionRejectedError,
|
|
35468
|
+
DerivativeQuestionSchema,
|
|
35469
|
+
DerivativeQuestionTimeoutError,
|
|
35470
|
+
DerivativeSourceNotGrantedError,
|
|
34938
35471
|
DropboxStorage,
|
|
34939
35472
|
ECIESError,
|
|
34940
35473
|
ESCROW_DEPOSIT_ABI2 as ESCROW_DEPOSIT_ABI,
|
|
@@ -34958,6 +35491,9 @@ export {
|
|
|
34958
35491
|
LineageReadError,
|
|
34959
35492
|
MASTER_KEY_MESSAGE,
|
|
34960
35493
|
MAX_LINEAGE_SOURCES,
|
|
35494
|
+
MAX_QUESTION_CHARS,
|
|
35495
|
+
MAX_QUESTION_MODEL_CHARS,
|
|
35496
|
+
MAX_QUESTION_SOURCE_SCOPES,
|
|
34961
35497
|
MissingAuthError,
|
|
34962
35498
|
NATIVE_ASSET_ADDRESS,
|
|
34963
35499
|
NATIVE_VANA_ASSET,
|
|
@@ -34976,6 +35512,11 @@ export {
|
|
|
34976
35512
|
PersonalServerError,
|
|
34977
35513
|
PersonalServerWriteError,
|
|
34978
35514
|
PinataStorage,
|
|
35515
|
+
QUESTION_STATUSES,
|
|
35516
|
+
QuestionDeleteResultSchema,
|
|
35517
|
+
QuestionRecomputeResultSchema,
|
|
35518
|
+
QuestionRegisteredBySchema,
|
|
35519
|
+
QuestionStatusSchema,
|
|
34979
35520
|
R2Storage,
|
|
34980
35521
|
RECORD_DATA_ACCESS_TYPES,
|
|
34981
35522
|
REGISTRATION_KIND_FOR_OP,
|
|
@@ -35014,6 +35555,7 @@ export {
|
|
|
35014
35555
|
WriteSessionExpiredError,
|
|
35015
35556
|
WriteTransportError,
|
|
35016
35557
|
WriteUnauthorizedError,
|
|
35558
|
+
askPersonalServer,
|
|
35017
35559
|
assertDerivedScopeNaming,
|
|
35018
35560
|
assertValidPkceVerifier,
|
|
35019
35561
|
binaryWriteSignedBytes,
|
|
@@ -35049,6 +35591,7 @@ export {
|
|
|
35049
35591
|
dataRegistryDomain,
|
|
35050
35592
|
decryptWithPassword,
|
|
35051
35593
|
deleteDataPoint,
|
|
35594
|
+
deleteQuestion,
|
|
35052
35595
|
deriveDataPointId,
|
|
35053
35596
|
deriveMasterKey,
|
|
35054
35597
|
deriveScopeKey,
|
|
@@ -35078,6 +35621,7 @@ export {
|
|
|
35078
35621
|
getOpFee,
|
|
35079
35622
|
getPersonalServerLineage,
|
|
35080
35623
|
getPlatformCapabilities,
|
|
35624
|
+
getQuestion,
|
|
35081
35625
|
getServiceEndpoints,
|
|
35082
35626
|
grantPermissions,
|
|
35083
35627
|
grantRegistrationDomain,
|
|
@@ -35090,6 +35634,7 @@ export {
|
|
|
35090
35634
|
isPlatformSupported,
|
|
35091
35635
|
isRedactedLineageNode,
|
|
35092
35636
|
isTombstoneHashes,
|
|
35637
|
+
listQuestions,
|
|
35093
35638
|
mainnetServices,
|
|
35094
35639
|
moksha,
|
|
35095
35640
|
mokshaServices,
|
|
@@ -35106,8 +35651,10 @@ export {
|
|
|
35106
35651
|
personalServerLineagePath,
|
|
35107
35652
|
personalServerRegistrationDomain,
|
|
35108
35653
|
readPersonalServerData,
|
|
35654
|
+
recomputeQuestion,
|
|
35109
35655
|
recoverServerOwner,
|
|
35110
35656
|
registerPersonalServerSignature,
|
|
35657
|
+
registerQuestion,
|
|
35111
35658
|
resolveWriteSigner,
|
|
35112
35659
|
scopeCoveredByGrant,
|
|
35113
35660
|
scopeMatchesPattern,
|
|
@@ -35125,6 +35672,7 @@ export {
|
|
|
35125
35672
|
verifyGrantRegistration,
|
|
35126
35673
|
verifyPkceChallenge,
|
|
35127
35674
|
verifyWeb3Signed,
|
|
35675
|
+
waitForQuestion,
|
|
35128
35676
|
writeData,
|
|
35129
35677
|
writePersonalServerData
|
|
35130
35678
|
};
|