@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.node.js
CHANGED
|
@@ -1358,6 +1358,57 @@ var LineageReadError = class extends VanaError {
|
|
|
1358
1358
|
errorCode;
|
|
1359
1359
|
details;
|
|
1360
1360
|
};
|
|
1361
|
+
var DerivativeQuestionRejectedError = class extends PersonalServerWriteError {
|
|
1362
|
+
constructor(message, status, errorCode = null, details) {
|
|
1363
|
+
super(message, "DERIVATIVE_QUESTION_REJECTED", status, errorCode, details);
|
|
1364
|
+
}
|
|
1365
|
+
};
|
|
1366
|
+
var DerivativeQuestionInvalidError = class extends PersonalServerWriteError {
|
|
1367
|
+
constructor(message, status = 400, errorCode = null, details) {
|
|
1368
|
+
super(message, "DERIVATIVE_QUESTION_INVALID", status, errorCode, details);
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
var DerivativeQuestionNotFoundError = class extends PersonalServerWriteError {
|
|
1372
|
+
constructor(message, errorCode = null, details) {
|
|
1373
|
+
super(message, "DERIVATIVE_QUESTION_NOT_FOUND", 404, errorCode, details);
|
|
1374
|
+
}
|
|
1375
|
+
};
|
|
1376
|
+
var DerivativeDerivedScopeRequiredError = class extends PersonalServerWriteError {
|
|
1377
|
+
constructor(message, errorCode = null, details) {
|
|
1378
|
+
super(
|
|
1379
|
+
message,
|
|
1380
|
+
"DERIVATIVE_DERIVED_SCOPE_REQUIRED",
|
|
1381
|
+
400,
|
|
1382
|
+
errorCode,
|
|
1383
|
+
details
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1387
|
+
var DerivativeSourceNotGrantedError = class extends PersonalServerWriteError {
|
|
1388
|
+
constructor(message, errorCode = null, details) {
|
|
1389
|
+
super(message, "DERIVATIVE_SOURCE_NOT_GRANTED", 403, errorCode, details);
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
var DerivativeCycleError = class extends PersonalServerWriteError {
|
|
1393
|
+
constructor(message, errorCode = null, details) {
|
|
1394
|
+
super(message, "DERIVATIVE_CYCLE", 409, errorCode, details);
|
|
1395
|
+
}
|
|
1396
|
+
};
|
|
1397
|
+
var DerivativeComputeUnavailableError = class extends PersonalServerWriteError {
|
|
1398
|
+
constructor(message, errorCode = null, details) {
|
|
1399
|
+
super(message, "DERIVATIVE_COMPUTE_UNAVAILABLE", 503, errorCode, details);
|
|
1400
|
+
}
|
|
1401
|
+
};
|
|
1402
|
+
var DerivativeQuestionTimeoutError = class extends PersonalServerWriteError {
|
|
1403
|
+
constructor(message, details) {
|
|
1404
|
+
super(message, "DERIVATIVE_QUESTION_TIMEOUT", void 0, null, details);
|
|
1405
|
+
}
|
|
1406
|
+
};
|
|
1407
|
+
var DerivativeQuestionFailedError = class extends PersonalServerWriteError {
|
|
1408
|
+
constructor(message, details) {
|
|
1409
|
+
super(message, "DERIVATIVE_QUESTION_FAILED", void 0, null, details);
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1361
1412
|
var DataPointDeletedError = class extends VanaError {
|
|
1362
1413
|
constructor(message, details = {}) {
|
|
1363
1414
|
super(message, "DATA_POINT_DELETED");
|
|
@@ -29115,6 +29166,9 @@ async function buildWeb3SignedHeader(params) {
|
|
|
29115
29166
|
if (params.grantId !== void 0) {
|
|
29116
29167
|
payload["grantId"] = params.grantId;
|
|
29117
29168
|
}
|
|
29169
|
+
if (params.nonce !== void 0) {
|
|
29170
|
+
payload["nonce"] = params.nonce;
|
|
29171
|
+
}
|
|
29118
29172
|
const sortedPayload = Object.keys(payload).sort().reduce((acc, key) => {
|
|
29119
29173
|
acc[key] = payload[key];
|
|
29120
29174
|
return acc;
|
|
@@ -34391,32 +34445,13 @@ function tryGrantPermissions(scopes) {
|
|
|
34391
34445
|
}
|
|
34392
34446
|
|
|
34393
34447
|
// src/protocol/personal-server-write.ts
|
|
34394
|
-
import { sha256 as
|
|
34395
|
-
import { bytesToHex as
|
|
34448
|
+
import { sha256 as sha2566 } from "@noble/hashes/sha2";
|
|
34449
|
+
import { bytesToHex as bytesToHex3, isAddress as isAddress6 } from "viem";
|
|
34396
34450
|
import { z as z4 } from "zod";
|
|
34397
|
-
|
|
34398
|
-
|
|
34399
|
-
|
|
34400
|
-
|
|
34401
|
-
var MAX_LINEAGE_SOURCES = 256;
|
|
34402
|
-
var WRITE_FILENAME_HEADER = "X-Filename";
|
|
34403
|
-
var WRITE_CONTENT_DISPOSITION_HEADER = "Content-Disposition";
|
|
34404
|
-
var WRITER_ATTRIBUTION_KEY = "$writtenBy";
|
|
34405
|
-
var LINEAGE_KEY = "$lineage";
|
|
34406
|
-
var RESERVED_WRITE_KEYS = [
|
|
34407
|
-
WRITER_ATTRIBUTION_KEY,
|
|
34408
|
-
LINEAGE_KEY
|
|
34409
|
-
];
|
|
34410
|
-
var WriteDataResultSchema = IngestResponseSchema.extend({
|
|
34411
|
-
// Present when the write carried lineage: the validated, lowercased ids.
|
|
34412
|
-
lineage: z4.object({ sources: z4.array(z4.string()) }).optional()
|
|
34413
|
-
});
|
|
34414
|
-
var WriteSessionResponseSchema = z4.object({
|
|
34415
|
-
access_token: z4.string().min(1),
|
|
34416
|
-
token_type: z4.string(),
|
|
34417
|
-
expires_in: z4.number().nonnegative(),
|
|
34418
|
-
scope: z4.string()
|
|
34419
|
-
});
|
|
34451
|
+
|
|
34452
|
+
// src/protocol/write-request.ts
|
|
34453
|
+
import { sha256 as sha2565 } from "@noble/hashes/sha2";
|
|
34454
|
+
import { bytesToHex as bytesToHex2 } from "viem";
|
|
34420
34455
|
function normalizeBaseUrl2(url) {
|
|
34421
34456
|
return url.replace(/\/+$/, "");
|
|
34422
34457
|
}
|
|
@@ -34427,9 +34462,6 @@ function resolveFetch2(fetchFn) {
|
|
|
34427
34462
|
}
|
|
34428
34463
|
return resolved;
|
|
34429
34464
|
}
|
|
34430
|
-
function dataPath(scope) {
|
|
34431
|
-
return `/v1/data/${encodeURIComponent(scope)}`;
|
|
34432
|
-
}
|
|
34433
34465
|
function errorMessage(err) {
|
|
34434
34466
|
return err instanceof Error ? err.message : String(err);
|
|
34435
34467
|
}
|
|
@@ -34480,6 +34512,18 @@ function nextProofIat(proofKey) {
|
|
|
34480
34512
|
if (waitSec <= 0) return Promise.resolve(iat);
|
|
34481
34513
|
return sleep2(waitSec * 1e3).then(() => iat);
|
|
34482
34514
|
}
|
|
34515
|
+
function freshProofNonce() {
|
|
34516
|
+
const webCrypto = globalThis.crypto;
|
|
34517
|
+
if (typeof webCrypto?.randomUUID === "function") {
|
|
34518
|
+
return webCrypto.randomUUID();
|
|
34519
|
+
}
|
|
34520
|
+
if (typeof webCrypto?.getRandomValues === "function") {
|
|
34521
|
+
return bytesToHex2(webCrypto.getRandomValues(new Uint8Array(16)));
|
|
34522
|
+
}
|
|
34523
|
+
throw new WriteRequestError(
|
|
34524
|
+
"No secure random source available to build a proof nonce; provide a crypto global"
|
|
34525
|
+
);
|
|
34526
|
+
}
|
|
34483
34527
|
function proofKeyFor(parts) {
|
|
34484
34528
|
return bytesToHex2(
|
|
34485
34529
|
sha2565(
|
|
@@ -34517,6 +34561,34 @@ async function sendWithFreshProof(label, fetchFn, options, proofKey, build) {
|
|
|
34517
34561
|
lastError
|
|
34518
34562
|
);
|
|
34519
34563
|
}
|
|
34564
|
+
|
|
34565
|
+
// src/protocol/personal-server-write.ts
|
|
34566
|
+
var WRITE_SESSION_PATH = "/v1/write/session";
|
|
34567
|
+
var WRITE_SIGNATURE_HEADER = "X-Vana-Write-Signature";
|
|
34568
|
+
var WRITE_METADATA_HEADER = "X-Vana-Metadata";
|
|
34569
|
+
var LINEAGE_FIELD = "lineage";
|
|
34570
|
+
var MAX_LINEAGE_SOURCES = 256;
|
|
34571
|
+
var WRITE_FILENAME_HEADER = "X-Filename";
|
|
34572
|
+
var WRITE_CONTENT_DISPOSITION_HEADER = "Content-Disposition";
|
|
34573
|
+
var WRITER_ATTRIBUTION_KEY = "$writtenBy";
|
|
34574
|
+
var LINEAGE_KEY = "$lineage";
|
|
34575
|
+
var RESERVED_WRITE_KEYS = [
|
|
34576
|
+
WRITER_ATTRIBUTION_KEY,
|
|
34577
|
+
LINEAGE_KEY
|
|
34578
|
+
];
|
|
34579
|
+
var WriteDataResultSchema = IngestResponseSchema.extend({
|
|
34580
|
+
// Present when the write carried lineage: the validated, lowercased ids.
|
|
34581
|
+
lineage: z4.object({ sources: z4.array(z4.string()) }).optional()
|
|
34582
|
+
});
|
|
34583
|
+
var WriteSessionResponseSchema = z4.object({
|
|
34584
|
+
access_token: z4.string().min(1),
|
|
34585
|
+
token_type: z4.string(),
|
|
34586
|
+
expires_in: z4.number().nonnegative(),
|
|
34587
|
+
scope: z4.string()
|
|
34588
|
+
});
|
|
34589
|
+
function dataPath(scope) {
|
|
34590
|
+
return `/v1/data/${encodeURIComponent(scope)}`;
|
|
34591
|
+
}
|
|
34520
34592
|
async function openWriteSession(params) {
|
|
34521
34593
|
const fetchFn = resolveFetch2(params.fetch);
|
|
34522
34594
|
const personalServerUrl = normalizeBaseUrl2(params.personalServerUrl);
|
|
@@ -34648,7 +34720,7 @@ function binaryWriteSignedBytes(input) {
|
|
|
34648
34720
|
mimeType: normalizeBinaryMimeType(input.contentType),
|
|
34649
34721
|
...input.filename ? { filename: input.filename } : {},
|
|
34650
34722
|
sizeBytes: input.bytes.length,
|
|
34651
|
-
contentHash:
|
|
34723
|
+
contentHash: bytesToHex3(sha2566(input.bytes)),
|
|
34652
34724
|
encoding: "base64",
|
|
34653
34725
|
content: toBase64(input.bytes),
|
|
34654
34726
|
...metadata !== void 0 ? { metadata } : {}
|
|
@@ -34945,6 +35017,454 @@ async function writePersonalServerData(params) {
|
|
|
34945
35017
|
return { ...result, session };
|
|
34946
35018
|
}
|
|
34947
35019
|
|
|
35020
|
+
// src/protocol/derivative-questions.ts
|
|
35021
|
+
import { z as z5 } from "zod";
|
|
35022
|
+
var DERIVATIVE_QUESTIONS_PATH = "/v1/derivatives/questions";
|
|
35023
|
+
var MAX_QUESTION_SOURCE_SCOPES = 16;
|
|
35024
|
+
var MAX_QUESTION_CHARS = 8e3;
|
|
35025
|
+
var MAX_QUESTION_MODEL_CHARS = 128;
|
|
35026
|
+
var MODEL_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/;
|
|
35027
|
+
var DEFAULT_QUESTION_TIMEOUT_MS = 12e4;
|
|
35028
|
+
var DEFAULT_QUESTION_POLL_INTERVAL_MS = 2e3;
|
|
35029
|
+
var SESSION_REFRESH_SKEW_MS = 3e4;
|
|
35030
|
+
var QUESTION_STATUSES = [
|
|
35031
|
+
"pending",
|
|
35032
|
+
"ready",
|
|
35033
|
+
"failed",
|
|
35034
|
+
"stale"
|
|
35035
|
+
];
|
|
35036
|
+
var QuestionStatusSchema = z5.enum(QUESTION_STATUSES);
|
|
35037
|
+
var QuestionRegisteredBySchema = z5.union([
|
|
35038
|
+
z5.object({ kind: z5.literal("owner") }),
|
|
35039
|
+
z5.object({
|
|
35040
|
+
kind: z5.literal("builder"),
|
|
35041
|
+
builder: z5.string(),
|
|
35042
|
+
grantId: z5.string()
|
|
35043
|
+
})
|
|
35044
|
+
]);
|
|
35045
|
+
var nullableString = z5.string().nullish().transform((value) => value ?? null);
|
|
35046
|
+
var DerivativeQuestionSchema = z5.object({
|
|
35047
|
+
questionId: z5.string().min(1),
|
|
35048
|
+
derivedScope: z5.string().min(1),
|
|
35049
|
+
sourceScopes: z5.array(z5.string()),
|
|
35050
|
+
question: z5.string(),
|
|
35051
|
+
/** The model override, or `null` for the server's default. */
|
|
35052
|
+
model: nullableString,
|
|
35053
|
+
registeredBy: QuestionRegisteredBySchema,
|
|
35054
|
+
status: QuestionStatusSchema,
|
|
35055
|
+
/** A short reason, set only while `status` is `failed`. */
|
|
35056
|
+
error: nullableString,
|
|
35057
|
+
createdAt: z5.string(),
|
|
35058
|
+
updatedAt: nullableString,
|
|
35059
|
+
/** When the last compute finished, or `null` while `pending`. */
|
|
35060
|
+
lastComputedAt: nullableString,
|
|
35061
|
+
/** Local version of the derived record the last compute wrote. */
|
|
35062
|
+
derivedVersion: z5.number().nullish().transform((value) => value ?? null),
|
|
35063
|
+
derivedCollectedAt: nullableString
|
|
35064
|
+
});
|
|
35065
|
+
var QuestionListSchema = z5.object({
|
|
35066
|
+
questions: z5.array(DerivativeQuestionSchema)
|
|
35067
|
+
});
|
|
35068
|
+
var QuestionRecomputeResultSchema = DerivativeQuestionSchema;
|
|
35069
|
+
var QuestionDeleteResultSchema = z5.object({
|
|
35070
|
+
questionId: z5.string().min(1),
|
|
35071
|
+
deleted: z5.literal(true)
|
|
35072
|
+
});
|
|
35073
|
+
var sessionsBySigner = /* @__PURE__ */ new WeakMap();
|
|
35074
|
+
function sessionCacheKey(personalServerUrl, audience, grantId, fetchFn) {
|
|
35075
|
+
return JSON.stringify([personalServerUrl, audience, grantId]) + fetchIdOf(fetchFn);
|
|
35076
|
+
}
|
|
35077
|
+
var fetchIds = /* @__PURE__ */ new WeakMap();
|
|
35078
|
+
var nextFetchId = 0;
|
|
35079
|
+
function fetchIdOf(fetchFn) {
|
|
35080
|
+
let id = fetchIds.get(fetchFn);
|
|
35081
|
+
if (id === void 0) {
|
|
35082
|
+
id = ++nextFetchId;
|
|
35083
|
+
fetchIds.set(fetchFn, id);
|
|
35084
|
+
}
|
|
35085
|
+
return `#${id}`;
|
|
35086
|
+
}
|
|
35087
|
+
function resolveRequest(params) {
|
|
35088
|
+
if (typeof params.personalServerUrl !== "string" || params.personalServerUrl.length === 0) {
|
|
35089
|
+
throw new WriteRequestError("personalServerUrl is required");
|
|
35090
|
+
}
|
|
35091
|
+
if (typeof params.grantId !== "string" || params.grantId.length === 0) {
|
|
35092
|
+
throw new WriteRequestError(
|
|
35093
|
+
"grantId is required; a question call runs under the grant carrying write:<derivedScope>"
|
|
35094
|
+
);
|
|
35095
|
+
}
|
|
35096
|
+
if (params.signer === null || typeof params.signer !== "object") {
|
|
35097
|
+
throw new WriteRequestError(
|
|
35098
|
+
"signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
|
|
35099
|
+
);
|
|
35100
|
+
}
|
|
35101
|
+
const fetchFn = resolveFetch2(params.fetch);
|
|
35102
|
+
const baseUrl = normalizeBaseUrl2(params.personalServerUrl);
|
|
35103
|
+
const audience = params.audience ?? baseUrl;
|
|
35104
|
+
return {
|
|
35105
|
+
baseUrl,
|
|
35106
|
+
audience,
|
|
35107
|
+
fetchFn,
|
|
35108
|
+
cacheKey: sessionCacheKey(baseUrl, audience, params.grantId, fetchFn),
|
|
35109
|
+
signerKey: params.signer
|
|
35110
|
+
};
|
|
35111
|
+
}
|
|
35112
|
+
async function resolveSession(params, resolved, force) {
|
|
35113
|
+
let cache = sessionsBySigner.get(resolved.signerKey);
|
|
35114
|
+
if (cache === void 0) {
|
|
35115
|
+
cache = /* @__PURE__ */ new Map();
|
|
35116
|
+
sessionsBySigner.set(resolved.signerKey, cache);
|
|
35117
|
+
}
|
|
35118
|
+
const cached = cache.get(resolved.cacheKey);
|
|
35119
|
+
if (!force && cached !== void 0 && cached.expiresAt > Date.now() + SESSION_REFRESH_SKEW_MS) {
|
|
35120
|
+
return cached;
|
|
35121
|
+
}
|
|
35122
|
+
if (force) cache.delete(resolved.cacheKey);
|
|
35123
|
+
const session = await openWriteSession({
|
|
35124
|
+
personalServerUrl: resolved.baseUrl,
|
|
35125
|
+
signer: params.signer,
|
|
35126
|
+
grantId: params.grantId,
|
|
35127
|
+
account: params.account,
|
|
35128
|
+
audience: resolved.audience,
|
|
35129
|
+
fetch: resolved.fetchFn,
|
|
35130
|
+
headers: params.headers,
|
|
35131
|
+
retry: params.retry
|
|
35132
|
+
});
|
|
35133
|
+
cache.set(resolved.cacheKey, session);
|
|
35134
|
+
return session;
|
|
35135
|
+
}
|
|
35136
|
+
var PROOF_FAILURE_CODES = /* @__PURE__ */ new Set([
|
|
35137
|
+
"WRITE_ATTRIBUTION_REQUIRED",
|
|
35138
|
+
"WRITE_ATTRIBUTION_INVALID",
|
|
35139
|
+
"WRITE_ATTRIBUTION_SIGNER_MISMATCH",
|
|
35140
|
+
"WRITE_ATTRIBUTION_GRANT_MISMATCH",
|
|
35141
|
+
"WRITE_ATTRIBUTION_REPLAY"
|
|
35142
|
+
]);
|
|
35143
|
+
function isStaleSession(errorCode) {
|
|
35144
|
+
return errorCode === null || !PROOF_FAILURE_CODES.has(errorCode);
|
|
35145
|
+
}
|
|
35146
|
+
async function questionErrorFromResponse(response, body) {
|
|
35147
|
+
const { errorCode, message, details } = body ?? await readPersonalServerErrorBody(response);
|
|
35148
|
+
const text = message ?? `Derivative question request failed: ${response.status} ${response.statusText}`;
|
|
35149
|
+
switch (errorCode) {
|
|
35150
|
+
case "DERIVATIVE_SOURCE_NOT_GRANTED":
|
|
35151
|
+
return new DerivativeSourceNotGrantedError(text, errorCode, details);
|
|
35152
|
+
case "DERIVATIVE_CYCLE":
|
|
35153
|
+
return new DerivativeCycleError(text, errorCode, details);
|
|
35154
|
+
case "DERIVATIVE_COMPUTE_UNAVAILABLE":
|
|
35155
|
+
return new DerivativeComputeUnavailableError(text, errorCode, details);
|
|
35156
|
+
case "DERIVATIVE_QUESTION_INVALID":
|
|
35157
|
+
case "LINEAGE_SCOPE_UNDER_SOURCE_PREFIX":
|
|
35158
|
+
return new DerivativeQuestionInvalidError(
|
|
35159
|
+
text,
|
|
35160
|
+
response.status,
|
|
35161
|
+
errorCode,
|
|
35162
|
+
details
|
|
35163
|
+
);
|
|
35164
|
+
case "DERIVATIVE_QUESTION_NOT_FOUND":
|
|
35165
|
+
return new DerivativeQuestionNotFoundError(text, errorCode, details);
|
|
35166
|
+
case "DERIVATIVE_DERIVED_SCOPE_REQUIRED":
|
|
35167
|
+
return new DerivativeDerivedScopeRequiredError(text, errorCode, details);
|
|
35168
|
+
default:
|
|
35169
|
+
break;
|
|
35170
|
+
}
|
|
35171
|
+
switch (response.status) {
|
|
35172
|
+
case 401:
|
|
35173
|
+
return new WriteUnauthorizedError(text, errorCode, details);
|
|
35174
|
+
case 403:
|
|
35175
|
+
return new WriteForbiddenError(text, errorCode, details);
|
|
35176
|
+
case 404:
|
|
35177
|
+
return new DerivativeQuestionNotFoundError(text, errorCode, details);
|
|
35178
|
+
case 409:
|
|
35179
|
+
return new WriteConflictError(text, errorCode, details);
|
|
35180
|
+
default:
|
|
35181
|
+
return new DerivativeQuestionRejectedError(
|
|
35182
|
+
text,
|
|
35183
|
+
response.status,
|
|
35184
|
+
errorCode,
|
|
35185
|
+
details
|
|
35186
|
+
);
|
|
35187
|
+
}
|
|
35188
|
+
}
|
|
35189
|
+
async function sendOnce(params, resolved, session, spec, bodyBytes) {
|
|
35190
|
+
return sendWithFreshProof(
|
|
35191
|
+
spec.label,
|
|
35192
|
+
resolved.fetchFn,
|
|
35193
|
+
params.retry,
|
|
35194
|
+
proofKeyFor({
|
|
35195
|
+
aud: session.audience,
|
|
35196
|
+
method: spec.method,
|
|
35197
|
+
uri: spec.target,
|
|
35198
|
+
grantId: session.grantId,
|
|
35199
|
+
signedBytes: bodyBytes
|
|
35200
|
+
}),
|
|
35201
|
+
async (iat) => {
|
|
35202
|
+
const headers = new Headers(params.headers);
|
|
35203
|
+
headers.set("Accept", "application/json");
|
|
35204
|
+
headers.set("Authorization", `Bearer ${session.accessToken}`);
|
|
35205
|
+
if (bodyBytes !== void 0) {
|
|
35206
|
+
headers.set("Content-Type", "application/json");
|
|
35207
|
+
}
|
|
35208
|
+
headers.set(
|
|
35209
|
+
WRITE_SIGNATURE_HEADER,
|
|
35210
|
+
await buildWeb3SignedHeader({
|
|
35211
|
+
signMessage: session.signer.signMessage,
|
|
35212
|
+
aud: session.audience,
|
|
35213
|
+
// The proof commits to the whole request target, query included:
|
|
35214
|
+
// `?derivedScope=` is what the list route authorizes against, and a
|
|
35215
|
+
// proof that did not cover it would authorize any other scope.
|
|
35216
|
+
uri: spec.target,
|
|
35217
|
+
method: spec.method,
|
|
35218
|
+
body: bodyBytes,
|
|
35219
|
+
grantId: session.grantId,
|
|
35220
|
+
// Fresh per attempt, so a retry after a thrown `fetch` is never the
|
|
35221
|
+
// proof the server may already have consumed, and so two identical
|
|
35222
|
+
// polls inside one second stay distinct.
|
|
35223
|
+
nonce: freshProofNonce(),
|
|
35224
|
+
iat
|
|
35225
|
+
})
|
|
35226
|
+
);
|
|
35227
|
+
return {
|
|
35228
|
+
url: `${resolved.baseUrl}${spec.target}`,
|
|
35229
|
+
init: {
|
|
35230
|
+
method: spec.method,
|
|
35231
|
+
headers,
|
|
35232
|
+
...bodyBytes === void 0 ? {} : { body: bodyBytes },
|
|
35233
|
+
...params.signal ? { signal: params.signal } : {}
|
|
35234
|
+
}
|
|
35235
|
+
};
|
|
35236
|
+
}
|
|
35237
|
+
);
|
|
35238
|
+
}
|
|
35239
|
+
async function sendQuestionRequest(params, spec, schema) {
|
|
35240
|
+
const resolved = resolveRequest(params);
|
|
35241
|
+
const bodyBytes = spec.body === void 0 ? void 0 : new TextEncoder().encode(JSON.stringify(spec.body));
|
|
35242
|
+
let session = await resolveSession(params, resolved, false);
|
|
35243
|
+
let response = await sendOnce(params, resolved, session, spec, bodyBytes);
|
|
35244
|
+
let errorBody;
|
|
35245
|
+
if (response.status === 401) {
|
|
35246
|
+
errorBody = await readPersonalServerErrorBody(response);
|
|
35247
|
+
if (isStaleSession(errorBody.errorCode)) {
|
|
35248
|
+
session = await resolveSession(params, resolved, true);
|
|
35249
|
+
response = await sendOnce(params, resolved, session, spec, bodyBytes);
|
|
35250
|
+
errorBody = void 0;
|
|
35251
|
+
}
|
|
35252
|
+
}
|
|
35253
|
+
if (!response.ok) {
|
|
35254
|
+
throw await questionErrorFromResponse(response, errorBody);
|
|
35255
|
+
}
|
|
35256
|
+
let body;
|
|
35257
|
+
try {
|
|
35258
|
+
body = await response.json();
|
|
35259
|
+
} catch (err) {
|
|
35260
|
+
throw new DerivativeQuestionRejectedError(
|
|
35261
|
+
`${spec.label} response is not JSON`,
|
|
35262
|
+
response.status,
|
|
35263
|
+
null,
|
|
35264
|
+
{ cause: errorMessage(err) }
|
|
35265
|
+
);
|
|
35266
|
+
}
|
|
35267
|
+
const parsed = schema.safeParse(body);
|
|
35268
|
+
if (!parsed.success) {
|
|
35269
|
+
throw new DerivativeQuestionRejectedError(
|
|
35270
|
+
`${spec.label} response is not a derivative question answer`,
|
|
35271
|
+
response.status,
|
|
35272
|
+
null,
|
|
35273
|
+
{ issues: parsed.error.issues }
|
|
35274
|
+
);
|
|
35275
|
+
}
|
|
35276
|
+
return parsed.data;
|
|
35277
|
+
}
|
|
35278
|
+
function assertQuestionId(questionId) {
|
|
35279
|
+
if (typeof questionId !== "string" || questionId.length === 0) {
|
|
35280
|
+
throw new WriteRequestError("questionId is required");
|
|
35281
|
+
}
|
|
35282
|
+
return `${DERIVATIVE_QUESTIONS_PATH}/${encodeURIComponent(questionId)}`;
|
|
35283
|
+
}
|
|
35284
|
+
function registrationBody(params) {
|
|
35285
|
+
const { derivedScope, question } = params;
|
|
35286
|
+
if (typeof derivedScope !== "string" || derivedScope.length === 0) {
|
|
35287
|
+
throw new WriteRequestError("derivedScope is required");
|
|
35288
|
+
}
|
|
35289
|
+
if (!Array.isArray(params.sourceScopes) || params.sourceScopes.length === 0) {
|
|
35290
|
+
throw new WriteRequestError(
|
|
35291
|
+
"sourceScopes must be a non-empty array of scopes"
|
|
35292
|
+
);
|
|
35293
|
+
}
|
|
35294
|
+
if (params.sourceScopes.length > MAX_QUESTION_SOURCE_SCOPES) {
|
|
35295
|
+
throw new WriteRequestError(
|
|
35296
|
+
`sourceScopes lists ${params.sourceScopes.length} scopes; the maximum is ${MAX_QUESTION_SOURCE_SCOPES}`,
|
|
35297
|
+
{ max: MAX_QUESTION_SOURCE_SCOPES, count: params.sourceScopes.length }
|
|
35298
|
+
);
|
|
35299
|
+
}
|
|
35300
|
+
const sourceScopes = [];
|
|
35301
|
+
for (const scope of params.sourceScopes) {
|
|
35302
|
+
if (typeof scope !== "string" || scope.length === 0) {
|
|
35303
|
+
throw new WriteRequestError("sourceScopes entries must be scope strings");
|
|
35304
|
+
}
|
|
35305
|
+
if (sourceScopes.includes(scope)) {
|
|
35306
|
+
throw new WriteRequestError("sourceScopes must not repeat a scope", {
|
|
35307
|
+
duplicate: scope
|
|
35308
|
+
});
|
|
35309
|
+
}
|
|
35310
|
+
if (scope === derivedScope) {
|
|
35311
|
+
throw new WriteRequestError(
|
|
35312
|
+
"derivedScope cannot be one of its own sources",
|
|
35313
|
+
{ scope }
|
|
35314
|
+
);
|
|
35315
|
+
}
|
|
35316
|
+
sourceScopes.push(scope);
|
|
35317
|
+
}
|
|
35318
|
+
if (typeof question !== "string" || question.trim() === "") {
|
|
35319
|
+
throw new WriteRequestError("question must be a non-empty string");
|
|
35320
|
+
}
|
|
35321
|
+
if (question.length > MAX_QUESTION_CHARS) {
|
|
35322
|
+
throw new WriteRequestError(
|
|
35323
|
+
`question is ${question.length} characters; the maximum is ${MAX_QUESTION_CHARS}`,
|
|
35324
|
+
{ max: MAX_QUESTION_CHARS, length: question.length }
|
|
35325
|
+
);
|
|
35326
|
+
}
|
|
35327
|
+
if (params.model !== void 0) {
|
|
35328
|
+
if (typeof params.model !== "string" || params.model.length > MAX_QUESTION_MODEL_CHARS || !MODEL_ID_PATTERN.test(params.model)) {
|
|
35329
|
+
throw new WriteRequestError("model must be a provider model id", {
|
|
35330
|
+
model: params.model
|
|
35331
|
+
});
|
|
35332
|
+
}
|
|
35333
|
+
}
|
|
35334
|
+
assertDerivedScopeNaming(derivedScope, sourceScopes);
|
|
35335
|
+
return {
|
|
35336
|
+
derivedScope,
|
|
35337
|
+
sourceScopes,
|
|
35338
|
+
question,
|
|
35339
|
+
...params.model === void 0 ? {} : { model: params.model }
|
|
35340
|
+
};
|
|
35341
|
+
}
|
|
35342
|
+
async function registerQuestion(params) {
|
|
35343
|
+
const body = registrationBody(params);
|
|
35344
|
+
return sendQuestionRequest(
|
|
35345
|
+
params,
|
|
35346
|
+
{
|
|
35347
|
+
method: "POST",
|
|
35348
|
+
target: DERIVATIVE_QUESTIONS_PATH,
|
|
35349
|
+
body,
|
|
35350
|
+
label: "Register derivative question"
|
|
35351
|
+
},
|
|
35352
|
+
DerivativeQuestionSchema
|
|
35353
|
+
);
|
|
35354
|
+
}
|
|
35355
|
+
async function getQuestion(params) {
|
|
35356
|
+
const target = assertQuestionId(params.questionId);
|
|
35357
|
+
return sendQuestionRequest(
|
|
35358
|
+
params,
|
|
35359
|
+
{ method: "GET", target, label: "Read derivative question" },
|
|
35360
|
+
DerivativeQuestionSchema
|
|
35361
|
+
);
|
|
35362
|
+
}
|
|
35363
|
+
async function listQuestions(params) {
|
|
35364
|
+
if (typeof params.derivedScope !== "string" || params.derivedScope.length === 0) {
|
|
35365
|
+
throw new WriteRequestError(
|
|
35366
|
+
"derivedScope is required; a builder may only list its own questions on a scope it may write"
|
|
35367
|
+
);
|
|
35368
|
+
}
|
|
35369
|
+
const target = `${DERIVATIVE_QUESTIONS_PATH}?derivedScope=${encodeURIComponent(params.derivedScope)}`;
|
|
35370
|
+
const { questions } = await sendQuestionRequest(
|
|
35371
|
+
params,
|
|
35372
|
+
{
|
|
35373
|
+
method: "GET",
|
|
35374
|
+
target,
|
|
35375
|
+
label: "List derivative questions"
|
|
35376
|
+
},
|
|
35377
|
+
QuestionListSchema
|
|
35378
|
+
);
|
|
35379
|
+
return questions;
|
|
35380
|
+
}
|
|
35381
|
+
async function recomputeQuestion(params) {
|
|
35382
|
+
const target = `${assertQuestionId(params.questionId)}/recompute`;
|
|
35383
|
+
return sendQuestionRequest(
|
|
35384
|
+
params,
|
|
35385
|
+
{ method: "POST", target, label: "Recompute derivative question" },
|
|
35386
|
+
QuestionRecomputeResultSchema
|
|
35387
|
+
);
|
|
35388
|
+
}
|
|
35389
|
+
async function deleteQuestion(params) {
|
|
35390
|
+
const target = assertQuestionId(params.questionId);
|
|
35391
|
+
return sendQuestionRequest(
|
|
35392
|
+
params,
|
|
35393
|
+
{ method: "DELETE", target, label: "Delete derivative question" },
|
|
35394
|
+
QuestionDeleteResultSchema
|
|
35395
|
+
);
|
|
35396
|
+
}
|
|
35397
|
+
function isSettled(status) {
|
|
35398
|
+
return status === "ready" || status === "failed";
|
|
35399
|
+
}
|
|
35400
|
+
function abortError(signal) {
|
|
35401
|
+
const reason = signal.reason;
|
|
35402
|
+
if (reason instanceof Error) return reason;
|
|
35403
|
+
const error = new Error("The operation was aborted");
|
|
35404
|
+
error.name = "AbortError";
|
|
35405
|
+
return error;
|
|
35406
|
+
}
|
|
35407
|
+
async function waitForQuestion(params) {
|
|
35408
|
+
const timeoutMs = Math.max(
|
|
35409
|
+
0,
|
|
35410
|
+
params.timeoutMs ?? DEFAULT_QUESTION_TIMEOUT_MS
|
|
35411
|
+
);
|
|
35412
|
+
const pollIntervalMs = Math.max(
|
|
35413
|
+
0,
|
|
35414
|
+
params.pollIntervalMs ?? DEFAULT_QUESTION_POLL_INTERVAL_MS
|
|
35415
|
+
);
|
|
35416
|
+
const deadline = Date.now() + timeoutMs;
|
|
35417
|
+
for (; ; ) {
|
|
35418
|
+
if (params.signal?.aborted) throw abortError(params.signal);
|
|
35419
|
+
const latest = await getQuestion(params);
|
|
35420
|
+
if (isSettled(latest.status)) return latest;
|
|
35421
|
+
const remaining = deadline - Date.now();
|
|
35422
|
+
if (remaining <= 0) {
|
|
35423
|
+
throw new DerivativeQuestionTimeoutError(
|
|
35424
|
+
`Derivative question ${latest.questionId} was still ${latest.status} after ${timeoutMs}ms`,
|
|
35425
|
+
{
|
|
35426
|
+
questionId: latest.questionId,
|
|
35427
|
+
derivedScope: latest.derivedScope,
|
|
35428
|
+
status: latest.status,
|
|
35429
|
+
timeoutMs
|
|
35430
|
+
}
|
|
35431
|
+
);
|
|
35432
|
+
}
|
|
35433
|
+
await sleep2(Math.min(pollIntervalMs, remaining));
|
|
35434
|
+
}
|
|
35435
|
+
}
|
|
35436
|
+
async function askPersonalServer(params) {
|
|
35437
|
+
const registered = await registerQuestion(params);
|
|
35438
|
+
const registration = await waitForQuestion({
|
|
35439
|
+
...params,
|
|
35440
|
+
questionId: registered.questionId
|
|
35441
|
+
});
|
|
35442
|
+
if (registration.status !== "ready") {
|
|
35443
|
+
throw new DerivativeQuestionFailedError(
|
|
35444
|
+
`Derivative question ${registration.questionId} failed: ${registration.error ?? "no reason given"}`,
|
|
35445
|
+
{
|
|
35446
|
+
questionId: registration.questionId,
|
|
35447
|
+
derivedScope: registration.derivedScope,
|
|
35448
|
+
error: registration.error
|
|
35449
|
+
}
|
|
35450
|
+
);
|
|
35451
|
+
}
|
|
35452
|
+
const signer = resolveWriteSigner(params.signer, {
|
|
35453
|
+
account: params.account
|
|
35454
|
+
});
|
|
35455
|
+
const readParams = {
|
|
35456
|
+
personalServerUrl: normalizeBaseUrl2(params.personalServerUrl),
|
|
35457
|
+
scope: params.derivedScope,
|
|
35458
|
+
grantId: params.grantId,
|
|
35459
|
+
signMessage: signer.signMessage,
|
|
35460
|
+
...params.audience === void 0 ? {} : { audience: params.audience },
|
|
35461
|
+
...params.headers === void 0 ? {} : { headers: params.headers },
|
|
35462
|
+
...params.fetch === void 0 ? {} : { fetch: params.fetch }
|
|
35463
|
+
};
|
|
35464
|
+
const record = await readPersonalServerData(readParams);
|
|
35465
|
+
return { registration, record };
|
|
35466
|
+
}
|
|
35467
|
+
|
|
34948
35468
|
// src/protocol/gateway.ts
|
|
34949
35469
|
function withGrantPermissions(grant) {
|
|
34950
35470
|
const stripped = { ...grant };
|
|
@@ -36025,11 +36545,24 @@ export {
|
|
|
36025
36545
|
ContractNotFoundError,
|
|
36026
36546
|
DATA_ACCESS_OP_TYPE,
|
|
36027
36547
|
DATA_REGISTRY_STATUS_ABI,
|
|
36548
|
+
DEFAULT_QUESTION_POLL_INTERVAL_MS,
|
|
36549
|
+
DEFAULT_QUESTION_TIMEOUT_MS,
|
|
36550
|
+
DERIVATIVE_QUESTIONS_PATH,
|
|
36028
36551
|
DataFileEnvelopeSchema,
|
|
36029
36552
|
DataPointDeletedError,
|
|
36030
36553
|
DataPointNotFoundError,
|
|
36031
36554
|
DataPointStatus,
|
|
36032
36555
|
DataPointVersionConflictError,
|
|
36556
|
+
DerivativeComputeUnavailableError,
|
|
36557
|
+
DerivativeCycleError,
|
|
36558
|
+
DerivativeDerivedScopeRequiredError,
|
|
36559
|
+
DerivativeQuestionFailedError,
|
|
36560
|
+
DerivativeQuestionInvalidError,
|
|
36561
|
+
DerivativeQuestionNotFoundError,
|
|
36562
|
+
DerivativeQuestionRejectedError,
|
|
36563
|
+
DerivativeQuestionSchema,
|
|
36564
|
+
DerivativeQuestionTimeoutError,
|
|
36565
|
+
DerivativeSourceNotGrantedError,
|
|
36033
36566
|
DropboxStorage,
|
|
36034
36567
|
ECIESError,
|
|
36035
36568
|
ESCROW_DEPOSIT_ABI2 as ESCROW_DEPOSIT_ABI,
|
|
@@ -36054,6 +36587,9 @@ export {
|
|
|
36054
36587
|
LineageReadError,
|
|
36055
36588
|
MASTER_KEY_MESSAGE,
|
|
36056
36589
|
MAX_LINEAGE_SOURCES,
|
|
36590
|
+
MAX_QUESTION_CHARS,
|
|
36591
|
+
MAX_QUESTION_MODEL_CHARS,
|
|
36592
|
+
MAX_QUESTION_SOURCE_SCOPES,
|
|
36057
36593
|
MissingAuthError,
|
|
36058
36594
|
NATIVE_ASSET_ADDRESS,
|
|
36059
36595
|
NATIVE_VANA_ASSET,
|
|
@@ -36074,6 +36610,11 @@ export {
|
|
|
36074
36610
|
PersonalServerError,
|
|
36075
36611
|
PersonalServerWriteError,
|
|
36076
36612
|
PinataStorage,
|
|
36613
|
+
QUESTION_STATUSES,
|
|
36614
|
+
QuestionDeleteResultSchema,
|
|
36615
|
+
QuestionRecomputeResultSchema,
|
|
36616
|
+
QuestionRegisteredBySchema,
|
|
36617
|
+
QuestionStatusSchema,
|
|
36077
36618
|
R2Storage,
|
|
36078
36619
|
RECORD_DATA_ACCESS_TYPES,
|
|
36079
36620
|
REGISTRATION_KIND_FOR_OP,
|
|
@@ -36112,6 +36653,7 @@ export {
|
|
|
36112
36653
|
WriteSessionExpiredError,
|
|
36113
36654
|
WriteTransportError,
|
|
36114
36655
|
WriteUnauthorizedError,
|
|
36656
|
+
askPersonalServer,
|
|
36115
36657
|
assertDerivedScopeNaming,
|
|
36116
36658
|
assertValidPkceVerifier,
|
|
36117
36659
|
authorizeEscrowPayment,
|
|
@@ -36155,6 +36697,7 @@ export {
|
|
|
36155
36697
|
dataRegistryDomain,
|
|
36156
36698
|
decryptWithPassword,
|
|
36157
36699
|
deleteDataPoint,
|
|
36700
|
+
deleteQuestion,
|
|
36158
36701
|
deriveDataPointId,
|
|
36159
36702
|
deriveMasterKey,
|
|
36160
36703
|
deriveScopeKey,
|
|
@@ -36184,6 +36727,7 @@ export {
|
|
|
36184
36727
|
getOpFee,
|
|
36185
36728
|
getPersonalServerLineage,
|
|
36186
36729
|
getPlatformCapabilities,
|
|
36730
|
+
getQuestion,
|
|
36187
36731
|
getServiceEndpoints,
|
|
36188
36732
|
grantPermissions,
|
|
36189
36733
|
grantRegistrationDomain,
|
|
@@ -36196,6 +36740,7 @@ export {
|
|
|
36196
36740
|
isPlatformSupported,
|
|
36197
36741
|
isRedactedLineageNode,
|
|
36198
36742
|
isTombstoneHashes,
|
|
36743
|
+
listQuestions,
|
|
36199
36744
|
mainnetServices,
|
|
36200
36745
|
moksha,
|
|
36201
36746
|
mokshaServices,
|
|
@@ -36215,8 +36760,10 @@ export {
|
|
|
36215
36760
|
personalServerLineagePath,
|
|
36216
36761
|
personalServerRegistrationDomain,
|
|
36217
36762
|
readPersonalServerData,
|
|
36763
|
+
recomputeQuestion,
|
|
36218
36764
|
recoverServerOwner,
|
|
36219
36765
|
registerPersonalServerSignature,
|
|
36766
|
+
registerQuestion,
|
|
36220
36767
|
resolveWriteSigner,
|
|
36221
36768
|
scopeCoveredByGrant,
|
|
36222
36769
|
scopeMatchesPattern,
|
|
@@ -36236,6 +36783,7 @@ export {
|
|
|
36236
36783
|
verifyGrantRegistration,
|
|
36237
36784
|
verifyPkceChallenge,
|
|
36238
36785
|
verifyWeb3Signed,
|
|
36786
|
+
waitForQuestion,
|
|
36239
36787
|
writeData,
|
|
36240
36788
|
writePersonalServerData
|
|
36241
36789
|
};
|