@opendatalabs/vana-sdk 3.18.0 → 3.19.0
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 +129 -3
- package/dist/errors.cjs +56 -0
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +98 -2
- package/dist/errors.js +48 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.js +542 -33
- package/dist/index.browser.js.map +4 -4
- package/dist/index.node.cjs +569 -33
- package/dist/index.node.cjs.map +4 -4
- package/dist/index.node.d.ts +1 -0
- package/dist/index.node.js +542 -33
- package/dist/index.node.js.map +4 -4
- package/dist/protocol/derivative-questions.cjs +501 -0
- package/dist/protocol/derivative-questions.cjs.map +1 -0
- package/dist/protocol/derivative-questions.d.ts +355 -0
- package/dist/protocol/derivative-questions.js +486 -0
- package/dist/protocol/derivative-questions.js.map +1 -0
- package/dist/protocol/derivative-questions.test.d.ts +1 -0
- package/dist/protocol/lineage.cjs +9 -4
- package/dist/protocol/lineage.cjs.map +1 -1
- package/dist/protocol/lineage.d.ts +21 -12
- package/dist/protocol/lineage.js +9 -4
- package/dist/protocol/lineage.js.map +1 -1
- 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 +142 -0
- package/dist/protocol/write-request.cjs.map +1 -0
- package/dist/protocol/write-request.d.ts +63 -0
- package/dist/protocol/write-request.js +111 -0
- package/dist/protocol/write-request.js.map +1 -0
- package/dist/tests/mock-personal-server.d.ts +51 -0
- package/package.json +1 -1
package/dist/index.node.js
CHANGED
|
@@ -1358,6 +1358,46 @@ 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 DerivativeSourceNotGrantedError = class extends PersonalServerWriteError {
|
|
1377
|
+
constructor(message, errorCode = null, details) {
|
|
1378
|
+
super(message, "DERIVATIVE_SOURCE_NOT_GRANTED", 403, errorCode, details);
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
var DerivativeCycleError = class extends PersonalServerWriteError {
|
|
1382
|
+
constructor(message, errorCode = null, details) {
|
|
1383
|
+
super(message, "DERIVATIVE_CYCLE", 409, errorCode, details);
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
var DerivativeComputeUnavailableError = class extends PersonalServerWriteError {
|
|
1387
|
+
constructor(message, errorCode = null, details) {
|
|
1388
|
+
super(message, "DERIVATIVE_COMPUTE_UNAVAILABLE", 503, errorCode, details);
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1391
|
+
var DerivativeQuestionTimeoutError = class extends PersonalServerWriteError {
|
|
1392
|
+
constructor(message, details) {
|
|
1393
|
+
super(message, "DERIVATIVE_QUESTION_TIMEOUT", void 0, null, details);
|
|
1394
|
+
}
|
|
1395
|
+
};
|
|
1396
|
+
var DerivativeQuestionFailedError = class extends PersonalServerWriteError {
|
|
1397
|
+
constructor(message, details) {
|
|
1398
|
+
super(message, "DERIVATIVE_QUESTION_FAILED", void 0, null, details);
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1361
1401
|
var DataPointDeletedError = class extends VanaError {
|
|
1362
1402
|
constructor(message, details = {}) {
|
|
1363
1403
|
super(message, "DATA_POINT_DELETED");
|
|
@@ -33776,10 +33816,15 @@ var LineageNodeSchema = z.object({
|
|
|
33776
33816
|
*/
|
|
33777
33817
|
version: VersionSchema,
|
|
33778
33818
|
/** The node's tombstone time, or `null` when live. */
|
|
33779
|
-
deletedAt: z.string().nullable()
|
|
33819
|
+
deletedAt: z.string().nullable(),
|
|
33820
|
+
/**
|
|
33821
|
+
* Never present on a visible node. Declared so a node that carries
|
|
33822
|
+
* `redacted: true` next to an id, scope and version cannot slip through
|
|
33823
|
+
* this branch of {@link LineageEntrySchema} with the key stripped.
|
|
33824
|
+
*/
|
|
33825
|
+
redacted: z.never().optional()
|
|
33780
33826
|
});
|
|
33781
|
-
var RedactedLineageNodeSchema = z.
|
|
33782
|
-
dataPointId: DataPointIdSchema,
|
|
33827
|
+
var RedactedLineageNodeSchema = z.strictObject({
|
|
33783
33828
|
redacted: z.literal(true)
|
|
33784
33829
|
});
|
|
33785
33830
|
var LineageEntrySchema = z.union([
|
|
@@ -33804,7 +33849,7 @@ var LineageGraphSchema = z.object({
|
|
|
33804
33849
|
derivativesTruncated: z.boolean().optional()
|
|
33805
33850
|
});
|
|
33806
33851
|
function isRedactedLineageNode(entry) {
|
|
33807
|
-
return "redacted" in entry && entry.redacted === true;
|
|
33852
|
+
return "redacted" in entry && entry.redacted === true && Object.keys(entry).length === 1;
|
|
33808
33853
|
}
|
|
33809
33854
|
function personalServerLineagePath(scope, version) {
|
|
33810
33855
|
return `/v1/data/${encodeURIComponent(scope)}/lineage${version === void 0 ? "" : `/${String(version)}`}`;
|
|
@@ -34386,32 +34431,13 @@ function tryGrantPermissions(scopes) {
|
|
|
34386
34431
|
}
|
|
34387
34432
|
|
|
34388
34433
|
// src/protocol/personal-server-write.ts
|
|
34389
|
-
import { sha256 as
|
|
34390
|
-
import { bytesToHex as
|
|
34434
|
+
import { sha256 as sha2566 } from "@noble/hashes/sha2";
|
|
34435
|
+
import { bytesToHex as bytesToHex3, isAddress as isAddress6 } from "viem";
|
|
34391
34436
|
import { z as z4 } from "zod";
|
|
34392
|
-
|
|
34393
|
-
|
|
34394
|
-
|
|
34395
|
-
|
|
34396
|
-
var MAX_LINEAGE_SOURCES = 256;
|
|
34397
|
-
var WRITE_FILENAME_HEADER = "X-Filename";
|
|
34398
|
-
var WRITE_CONTENT_DISPOSITION_HEADER = "Content-Disposition";
|
|
34399
|
-
var WRITER_ATTRIBUTION_KEY = "$writtenBy";
|
|
34400
|
-
var LINEAGE_KEY = "$lineage";
|
|
34401
|
-
var RESERVED_WRITE_KEYS = [
|
|
34402
|
-
WRITER_ATTRIBUTION_KEY,
|
|
34403
|
-
LINEAGE_KEY
|
|
34404
|
-
];
|
|
34405
|
-
var WriteDataResultSchema = IngestResponseSchema.extend({
|
|
34406
|
-
// Present when the write carried lineage: the validated, lowercased ids.
|
|
34407
|
-
lineage: z4.object({ sources: z4.array(z4.string()) }).optional()
|
|
34408
|
-
});
|
|
34409
|
-
var WriteSessionResponseSchema = z4.object({
|
|
34410
|
-
access_token: z4.string().min(1),
|
|
34411
|
-
token_type: z4.string(),
|
|
34412
|
-
expires_in: z4.number().nonnegative(),
|
|
34413
|
-
scope: z4.string()
|
|
34414
|
-
});
|
|
34437
|
+
|
|
34438
|
+
// src/protocol/write-request.ts
|
|
34439
|
+
import { sha256 as sha2565 } from "@noble/hashes/sha2";
|
|
34440
|
+
import { bytesToHex as bytesToHex2 } from "viem";
|
|
34415
34441
|
function normalizeBaseUrl2(url) {
|
|
34416
34442
|
return url.replace(/\/+$/, "");
|
|
34417
34443
|
}
|
|
@@ -34422,9 +34448,6 @@ function resolveFetch2(fetchFn) {
|
|
|
34422
34448
|
}
|
|
34423
34449
|
return resolved;
|
|
34424
34450
|
}
|
|
34425
|
-
function dataPath(scope) {
|
|
34426
|
-
return `/v1/data/${encodeURIComponent(scope)}`;
|
|
34427
|
-
}
|
|
34428
34451
|
function errorMessage(err) {
|
|
34429
34452
|
return err instanceof Error ? err.message : String(err);
|
|
34430
34453
|
}
|
|
@@ -34512,6 +34535,34 @@ async function sendWithFreshProof(label, fetchFn, options, proofKey, build) {
|
|
|
34512
34535
|
lastError
|
|
34513
34536
|
);
|
|
34514
34537
|
}
|
|
34538
|
+
|
|
34539
|
+
// src/protocol/personal-server-write.ts
|
|
34540
|
+
var WRITE_SESSION_PATH = "/v1/write/session";
|
|
34541
|
+
var WRITE_SIGNATURE_HEADER = "X-Vana-Write-Signature";
|
|
34542
|
+
var WRITE_METADATA_HEADER = "X-Vana-Metadata";
|
|
34543
|
+
var LINEAGE_FIELD = "lineage";
|
|
34544
|
+
var MAX_LINEAGE_SOURCES = 256;
|
|
34545
|
+
var WRITE_FILENAME_HEADER = "X-Filename";
|
|
34546
|
+
var WRITE_CONTENT_DISPOSITION_HEADER = "Content-Disposition";
|
|
34547
|
+
var WRITER_ATTRIBUTION_KEY = "$writtenBy";
|
|
34548
|
+
var LINEAGE_KEY = "$lineage";
|
|
34549
|
+
var RESERVED_WRITE_KEYS = [
|
|
34550
|
+
WRITER_ATTRIBUTION_KEY,
|
|
34551
|
+
LINEAGE_KEY
|
|
34552
|
+
];
|
|
34553
|
+
var WriteDataResultSchema = IngestResponseSchema.extend({
|
|
34554
|
+
// Present when the write carried lineage: the validated, lowercased ids.
|
|
34555
|
+
lineage: z4.object({ sources: z4.array(z4.string()) }).optional()
|
|
34556
|
+
});
|
|
34557
|
+
var WriteSessionResponseSchema = z4.object({
|
|
34558
|
+
access_token: z4.string().min(1),
|
|
34559
|
+
token_type: z4.string(),
|
|
34560
|
+
expires_in: z4.number().nonnegative(),
|
|
34561
|
+
scope: z4.string()
|
|
34562
|
+
});
|
|
34563
|
+
function dataPath(scope) {
|
|
34564
|
+
return `/v1/data/${encodeURIComponent(scope)}`;
|
|
34565
|
+
}
|
|
34515
34566
|
async function openWriteSession(params) {
|
|
34516
34567
|
const fetchFn = resolveFetch2(params.fetch);
|
|
34517
34568
|
const personalServerUrl = normalizeBaseUrl2(params.personalServerUrl);
|
|
@@ -34643,7 +34694,7 @@ function binaryWriteSignedBytes(input) {
|
|
|
34643
34694
|
mimeType: normalizeBinaryMimeType(input.contentType),
|
|
34644
34695
|
...input.filename ? { filename: input.filename } : {},
|
|
34645
34696
|
sizeBytes: input.bytes.length,
|
|
34646
|
-
contentHash:
|
|
34697
|
+
contentHash: bytesToHex3(sha2566(input.bytes)),
|
|
34647
34698
|
encoding: "base64",
|
|
34648
34699
|
content: toBase64(input.bytes),
|
|
34649
34700
|
...metadata !== void 0 ? { metadata } : {}
|
|
@@ -34940,6 +34991,437 @@ async function writePersonalServerData(params) {
|
|
|
34940
34991
|
return { ...result, session };
|
|
34941
34992
|
}
|
|
34942
34993
|
|
|
34994
|
+
// src/protocol/derivative-questions.ts
|
|
34995
|
+
import { z as z5 } from "zod";
|
|
34996
|
+
var DERIVATIVE_QUESTIONS_PATH = "/v1/derivatives/questions";
|
|
34997
|
+
var MAX_QUESTION_SOURCE_SCOPES = 16;
|
|
34998
|
+
var MAX_QUESTION_CHARS = 8e3;
|
|
34999
|
+
var MAX_QUESTION_MODEL_CHARS = 128;
|
|
35000
|
+
var MODEL_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/;
|
|
35001
|
+
var DEFAULT_QUESTION_TIMEOUT_MS = 12e4;
|
|
35002
|
+
var DEFAULT_QUESTION_POLL_INTERVAL_MS = 2e3;
|
|
35003
|
+
var SESSION_REFRESH_SKEW_MS = 3e4;
|
|
35004
|
+
var QUESTION_STATUSES = [
|
|
35005
|
+
"pending",
|
|
35006
|
+
"ready",
|
|
35007
|
+
"failed",
|
|
35008
|
+
"stale"
|
|
35009
|
+
];
|
|
35010
|
+
var QuestionStatusSchema = z5.enum(QUESTION_STATUSES);
|
|
35011
|
+
var QuestionRegisteredBySchema = z5.union([
|
|
35012
|
+
z5.object({ kind: z5.literal("owner") }),
|
|
35013
|
+
z5.object({
|
|
35014
|
+
kind: z5.literal("builder"),
|
|
35015
|
+
builder: z5.string(),
|
|
35016
|
+
grantId: z5.string()
|
|
35017
|
+
})
|
|
35018
|
+
]);
|
|
35019
|
+
var nullableString = z5.string().nullish().transform((value) => value ?? null);
|
|
35020
|
+
var DerivativeQuestionSchema = z5.object({
|
|
35021
|
+
questionId: z5.string().min(1),
|
|
35022
|
+
derivedScope: z5.string().min(1),
|
|
35023
|
+
sourceScopes: z5.array(z5.string()),
|
|
35024
|
+
question: z5.string(),
|
|
35025
|
+
/** The model override, or `null` for the server's default. */
|
|
35026
|
+
model: nullableString,
|
|
35027
|
+
registeredBy: QuestionRegisteredBySchema,
|
|
35028
|
+
status: QuestionStatusSchema,
|
|
35029
|
+
/** A short reason, set only while `status` is `failed`. */
|
|
35030
|
+
error: nullableString,
|
|
35031
|
+
createdAt: z5.string(),
|
|
35032
|
+
updatedAt: nullableString,
|
|
35033
|
+
/** When the last compute finished, or `null` while `pending`. */
|
|
35034
|
+
lastComputedAt: nullableString,
|
|
35035
|
+
/** Local version of the derived record the last compute wrote. */
|
|
35036
|
+
derivedVersion: z5.number().nullish().transform((value) => value ?? null),
|
|
35037
|
+
derivedCollectedAt: nullableString
|
|
35038
|
+
});
|
|
35039
|
+
var QuestionListSchema = z5.object({
|
|
35040
|
+
questions: z5.array(DerivativeQuestionSchema)
|
|
35041
|
+
});
|
|
35042
|
+
var QuestionRecomputeResultSchema = z5.object({
|
|
35043
|
+
questionId: z5.string().min(1),
|
|
35044
|
+
derivedScope: z5.string().min(1),
|
|
35045
|
+
/** `pending` when the question was never computed, else `stale`. */
|
|
35046
|
+
status: QuestionStatusSchema
|
|
35047
|
+
});
|
|
35048
|
+
var QuestionDeleteResultSchema = z5.object({
|
|
35049
|
+
questionId: z5.string().min(1),
|
|
35050
|
+
deleted: z5.literal(true)
|
|
35051
|
+
});
|
|
35052
|
+
var sessionsBySigner = /* @__PURE__ */ new WeakMap();
|
|
35053
|
+
function sessionCacheKey(personalServerUrl, audience, grantId, fetchFn) {
|
|
35054
|
+
return JSON.stringify([personalServerUrl, audience, grantId]) + fetchIdOf(fetchFn);
|
|
35055
|
+
}
|
|
35056
|
+
var fetchIds = /* @__PURE__ */ new WeakMap();
|
|
35057
|
+
var nextFetchId = 0;
|
|
35058
|
+
function fetchIdOf(fetchFn) {
|
|
35059
|
+
let id = fetchIds.get(fetchFn);
|
|
35060
|
+
if (id === void 0) {
|
|
35061
|
+
id = ++nextFetchId;
|
|
35062
|
+
fetchIds.set(fetchFn, id);
|
|
35063
|
+
}
|
|
35064
|
+
return `#${id}`;
|
|
35065
|
+
}
|
|
35066
|
+
function resolveRequest(params) {
|
|
35067
|
+
if (typeof params.personalServerUrl !== "string" || params.personalServerUrl.length === 0) {
|
|
35068
|
+
throw new WriteRequestError("personalServerUrl is required");
|
|
35069
|
+
}
|
|
35070
|
+
if (typeof params.grantId !== "string" || params.grantId.length === 0) {
|
|
35071
|
+
throw new WriteRequestError(
|
|
35072
|
+
"grantId is required; a question call runs under the grant carrying write:<derivedScope>"
|
|
35073
|
+
);
|
|
35074
|
+
}
|
|
35075
|
+
if (params.signer === null || typeof params.signer !== "object") {
|
|
35076
|
+
throw new WriteRequestError(
|
|
35077
|
+
"signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
|
|
35078
|
+
);
|
|
35079
|
+
}
|
|
35080
|
+
const fetchFn = resolveFetch2(params.fetch);
|
|
35081
|
+
const baseUrl = normalizeBaseUrl2(params.personalServerUrl);
|
|
35082
|
+
const audience = params.audience ?? baseUrl;
|
|
35083
|
+
return {
|
|
35084
|
+
baseUrl,
|
|
35085
|
+
audience,
|
|
35086
|
+
fetchFn,
|
|
35087
|
+
cacheKey: sessionCacheKey(baseUrl, audience, params.grantId, fetchFn),
|
|
35088
|
+
signerKey: params.signer
|
|
35089
|
+
};
|
|
35090
|
+
}
|
|
35091
|
+
async function resolveSession(params, resolved, force) {
|
|
35092
|
+
let cache = sessionsBySigner.get(resolved.signerKey);
|
|
35093
|
+
if (cache === void 0) {
|
|
35094
|
+
cache = /* @__PURE__ */ new Map();
|
|
35095
|
+
sessionsBySigner.set(resolved.signerKey, cache);
|
|
35096
|
+
}
|
|
35097
|
+
const cached = cache.get(resolved.cacheKey);
|
|
35098
|
+
if (!force && cached !== void 0 && cached.expiresAt > Date.now() + SESSION_REFRESH_SKEW_MS) {
|
|
35099
|
+
return cached;
|
|
35100
|
+
}
|
|
35101
|
+
if (force) cache.delete(resolved.cacheKey);
|
|
35102
|
+
const session = await openWriteSession({
|
|
35103
|
+
personalServerUrl: resolved.baseUrl,
|
|
35104
|
+
signer: params.signer,
|
|
35105
|
+
grantId: params.grantId,
|
|
35106
|
+
account: params.account,
|
|
35107
|
+
audience: resolved.audience,
|
|
35108
|
+
fetch: resolved.fetchFn,
|
|
35109
|
+
headers: params.headers,
|
|
35110
|
+
retry: params.retry
|
|
35111
|
+
});
|
|
35112
|
+
cache.set(resolved.cacheKey, session);
|
|
35113
|
+
return session;
|
|
35114
|
+
}
|
|
35115
|
+
async function questionErrorFromResponse(response) {
|
|
35116
|
+
const { errorCode, message, details } = await readPersonalServerErrorBody(response);
|
|
35117
|
+
const text = message ?? `Derivative question request failed: ${response.status} ${response.statusText}`;
|
|
35118
|
+
switch (errorCode) {
|
|
35119
|
+
case "DERIVATIVE_SOURCE_NOT_GRANTED":
|
|
35120
|
+
return new DerivativeSourceNotGrantedError(text, errorCode, details);
|
|
35121
|
+
case "DERIVATIVE_CYCLE":
|
|
35122
|
+
return new DerivativeCycleError(text, errorCode, details);
|
|
35123
|
+
case "DERIVATIVE_COMPUTE_UNAVAILABLE":
|
|
35124
|
+
return new DerivativeComputeUnavailableError(text, errorCode, details);
|
|
35125
|
+
case "DERIVATIVE_QUESTION_INVALID":
|
|
35126
|
+
case "LINEAGE_SCOPE_UNDER_SOURCE_PREFIX":
|
|
35127
|
+
return new DerivativeQuestionInvalidError(
|
|
35128
|
+
text,
|
|
35129
|
+
response.status,
|
|
35130
|
+
errorCode,
|
|
35131
|
+
details
|
|
35132
|
+
);
|
|
35133
|
+
case "DERIVATIVE_QUESTION_NOT_FOUND":
|
|
35134
|
+
return new DerivativeQuestionNotFoundError(text, errorCode, details);
|
|
35135
|
+
default:
|
|
35136
|
+
break;
|
|
35137
|
+
}
|
|
35138
|
+
switch (response.status) {
|
|
35139
|
+
case 401:
|
|
35140
|
+
return new WriteUnauthorizedError(text, errorCode, details);
|
|
35141
|
+
case 403:
|
|
35142
|
+
return new WriteForbiddenError(text, errorCode, details);
|
|
35143
|
+
case 404:
|
|
35144
|
+
return new DerivativeQuestionNotFoundError(text, errorCode, details);
|
|
35145
|
+
case 409:
|
|
35146
|
+
return new WriteConflictError(text, errorCode, details);
|
|
35147
|
+
default:
|
|
35148
|
+
return new DerivativeQuestionRejectedError(
|
|
35149
|
+
text,
|
|
35150
|
+
response.status,
|
|
35151
|
+
errorCode,
|
|
35152
|
+
details
|
|
35153
|
+
);
|
|
35154
|
+
}
|
|
35155
|
+
}
|
|
35156
|
+
async function sendOnce(params, resolved, session, spec, bodyBytes) {
|
|
35157
|
+
return sendWithFreshProof(
|
|
35158
|
+
spec.label,
|
|
35159
|
+
resolved.fetchFn,
|
|
35160
|
+
params.retry,
|
|
35161
|
+
proofKeyFor({
|
|
35162
|
+
aud: session.audience,
|
|
35163
|
+
method: spec.method,
|
|
35164
|
+
uri: spec.path,
|
|
35165
|
+
grantId: session.grantId,
|
|
35166
|
+
signedBytes: bodyBytes
|
|
35167
|
+
}),
|
|
35168
|
+
async (iat) => {
|
|
35169
|
+
const headers = new Headers(params.headers);
|
|
35170
|
+
headers.set("Accept", "application/json");
|
|
35171
|
+
headers.set("Authorization", `Bearer ${session.accessToken}`);
|
|
35172
|
+
if (bodyBytes !== void 0) {
|
|
35173
|
+
headers.set("Content-Type", "application/json");
|
|
35174
|
+
}
|
|
35175
|
+
headers.set(
|
|
35176
|
+
WRITE_SIGNATURE_HEADER,
|
|
35177
|
+
await buildWeb3SignedHeader({
|
|
35178
|
+
signMessage: session.signer.signMessage,
|
|
35179
|
+
aud: session.audience,
|
|
35180
|
+
// The Personal Server verifies the proof against the request's
|
|
35181
|
+
// path only, so the signed `uri` must not carry the query string.
|
|
35182
|
+
uri: spec.path,
|
|
35183
|
+
method: spec.method,
|
|
35184
|
+
body: bodyBytes,
|
|
35185
|
+
grantId: session.grantId,
|
|
35186
|
+
iat
|
|
35187
|
+
})
|
|
35188
|
+
);
|
|
35189
|
+
return {
|
|
35190
|
+
url: `${resolved.baseUrl}${spec.path}${spec.query ?? ""}`,
|
|
35191
|
+
init: {
|
|
35192
|
+
method: spec.method,
|
|
35193
|
+
headers,
|
|
35194
|
+
...bodyBytes === void 0 ? {} : { body: bodyBytes },
|
|
35195
|
+
...params.signal ? { signal: params.signal } : {}
|
|
35196
|
+
}
|
|
35197
|
+
};
|
|
35198
|
+
}
|
|
35199
|
+
);
|
|
35200
|
+
}
|
|
35201
|
+
async function sendQuestionRequest(params, spec, schema) {
|
|
35202
|
+
const resolved = resolveRequest(params);
|
|
35203
|
+
const bodyBytes = spec.body === void 0 ? void 0 : new TextEncoder().encode(JSON.stringify(spec.body));
|
|
35204
|
+
let session = await resolveSession(params, resolved, false);
|
|
35205
|
+
let response = await sendOnce(params, resolved, session, spec, bodyBytes);
|
|
35206
|
+
if (response.status === 401) {
|
|
35207
|
+
session = await resolveSession(params, resolved, true);
|
|
35208
|
+
response = await sendOnce(params, resolved, session, spec, bodyBytes);
|
|
35209
|
+
}
|
|
35210
|
+
if (!response.ok) {
|
|
35211
|
+
throw await questionErrorFromResponse(response);
|
|
35212
|
+
}
|
|
35213
|
+
let body;
|
|
35214
|
+
try {
|
|
35215
|
+
body = await response.json();
|
|
35216
|
+
} catch (err) {
|
|
35217
|
+
throw new DerivativeQuestionRejectedError(
|
|
35218
|
+
`${spec.label} response is not JSON`,
|
|
35219
|
+
response.status,
|
|
35220
|
+
null,
|
|
35221
|
+
{ cause: errorMessage(err) }
|
|
35222
|
+
);
|
|
35223
|
+
}
|
|
35224
|
+
const parsed = schema.safeParse(body);
|
|
35225
|
+
if (!parsed.success) {
|
|
35226
|
+
throw new DerivativeQuestionRejectedError(
|
|
35227
|
+
`${spec.label} response is not a derivative question answer`,
|
|
35228
|
+
response.status,
|
|
35229
|
+
null,
|
|
35230
|
+
{ issues: parsed.error.issues }
|
|
35231
|
+
);
|
|
35232
|
+
}
|
|
35233
|
+
return parsed.data;
|
|
35234
|
+
}
|
|
35235
|
+
function assertQuestionId(questionId) {
|
|
35236
|
+
if (typeof questionId !== "string" || questionId.length === 0) {
|
|
35237
|
+
throw new WriteRequestError("questionId is required");
|
|
35238
|
+
}
|
|
35239
|
+
return `${DERIVATIVE_QUESTIONS_PATH}/${encodeURIComponent(questionId)}`;
|
|
35240
|
+
}
|
|
35241
|
+
function registrationBody(params) {
|
|
35242
|
+
const { derivedScope, question } = params;
|
|
35243
|
+
if (typeof derivedScope !== "string" || derivedScope.length === 0) {
|
|
35244
|
+
throw new WriteRequestError("derivedScope is required");
|
|
35245
|
+
}
|
|
35246
|
+
if (!Array.isArray(params.sourceScopes) || params.sourceScopes.length === 0) {
|
|
35247
|
+
throw new WriteRequestError(
|
|
35248
|
+
"sourceScopes must be a non-empty array of scopes"
|
|
35249
|
+
);
|
|
35250
|
+
}
|
|
35251
|
+
if (params.sourceScopes.length > MAX_QUESTION_SOURCE_SCOPES) {
|
|
35252
|
+
throw new WriteRequestError(
|
|
35253
|
+
`sourceScopes lists ${params.sourceScopes.length} scopes; the maximum is ${MAX_QUESTION_SOURCE_SCOPES}`,
|
|
35254
|
+
{ max: MAX_QUESTION_SOURCE_SCOPES, count: params.sourceScopes.length }
|
|
35255
|
+
);
|
|
35256
|
+
}
|
|
35257
|
+
const sourceScopes = [];
|
|
35258
|
+
for (const scope of params.sourceScopes) {
|
|
35259
|
+
if (typeof scope !== "string" || scope.length === 0) {
|
|
35260
|
+
throw new WriteRequestError("sourceScopes entries must be scope strings");
|
|
35261
|
+
}
|
|
35262
|
+
if (sourceScopes.includes(scope)) {
|
|
35263
|
+
throw new WriteRequestError("sourceScopes must not repeat a scope", {
|
|
35264
|
+
duplicate: scope
|
|
35265
|
+
});
|
|
35266
|
+
}
|
|
35267
|
+
if (scope === derivedScope) {
|
|
35268
|
+
throw new WriteRequestError(
|
|
35269
|
+
"derivedScope cannot be one of its own sources",
|
|
35270
|
+
{ scope }
|
|
35271
|
+
);
|
|
35272
|
+
}
|
|
35273
|
+
sourceScopes.push(scope);
|
|
35274
|
+
}
|
|
35275
|
+
if (typeof question !== "string" || question.trim() === "") {
|
|
35276
|
+
throw new WriteRequestError("question must be a non-empty string");
|
|
35277
|
+
}
|
|
35278
|
+
if (question.length > MAX_QUESTION_CHARS) {
|
|
35279
|
+
throw new WriteRequestError(
|
|
35280
|
+
`question is ${question.length} characters; the maximum is ${MAX_QUESTION_CHARS}`,
|
|
35281
|
+
{ max: MAX_QUESTION_CHARS, length: question.length }
|
|
35282
|
+
);
|
|
35283
|
+
}
|
|
35284
|
+
if (params.model !== void 0) {
|
|
35285
|
+
if (typeof params.model !== "string" || params.model.length > MAX_QUESTION_MODEL_CHARS || !MODEL_ID_PATTERN.test(params.model)) {
|
|
35286
|
+
throw new WriteRequestError("model must be a provider model id", {
|
|
35287
|
+
model: params.model
|
|
35288
|
+
});
|
|
35289
|
+
}
|
|
35290
|
+
}
|
|
35291
|
+
assertDerivedScopeNaming(derivedScope, sourceScopes);
|
|
35292
|
+
return {
|
|
35293
|
+
derivedScope,
|
|
35294
|
+
sourceScopes,
|
|
35295
|
+
question,
|
|
35296
|
+
...params.model === void 0 ? {} : { model: params.model }
|
|
35297
|
+
};
|
|
35298
|
+
}
|
|
35299
|
+
async function registerQuestion(params) {
|
|
35300
|
+
const body = registrationBody(params);
|
|
35301
|
+
return sendQuestionRequest(
|
|
35302
|
+
params,
|
|
35303
|
+
{
|
|
35304
|
+
method: "POST",
|
|
35305
|
+
path: DERIVATIVE_QUESTIONS_PATH,
|
|
35306
|
+
body,
|
|
35307
|
+
label: "Register derivative question"
|
|
35308
|
+
},
|
|
35309
|
+
DerivativeQuestionSchema
|
|
35310
|
+
);
|
|
35311
|
+
}
|
|
35312
|
+
async function getQuestion(params) {
|
|
35313
|
+
const path = assertQuestionId(params.questionId);
|
|
35314
|
+
return sendQuestionRequest(
|
|
35315
|
+
params,
|
|
35316
|
+
{ method: "GET", path, label: "Read derivative question" },
|
|
35317
|
+
DerivativeQuestionSchema
|
|
35318
|
+
);
|
|
35319
|
+
}
|
|
35320
|
+
async function listQuestions(params) {
|
|
35321
|
+
if (typeof params.derivedScope !== "string" || params.derivedScope.length === 0) {
|
|
35322
|
+
throw new WriteRequestError(
|
|
35323
|
+
"derivedScope is required; a builder may only list its own questions on a scope it may write"
|
|
35324
|
+
);
|
|
35325
|
+
}
|
|
35326
|
+
const { questions } = await sendQuestionRequest(
|
|
35327
|
+
params,
|
|
35328
|
+
{
|
|
35329
|
+
method: "GET",
|
|
35330
|
+
path: DERIVATIVE_QUESTIONS_PATH,
|
|
35331
|
+
query: `?derivedScope=${encodeURIComponent(params.derivedScope)}`,
|
|
35332
|
+
label: "List derivative questions"
|
|
35333
|
+
},
|
|
35334
|
+
QuestionListSchema
|
|
35335
|
+
);
|
|
35336
|
+
return questions;
|
|
35337
|
+
}
|
|
35338
|
+
async function recomputeQuestion(params) {
|
|
35339
|
+
const path = `${assertQuestionId(params.questionId)}/recompute`;
|
|
35340
|
+
return sendQuestionRequest(
|
|
35341
|
+
params,
|
|
35342
|
+
{ method: "POST", path, label: "Recompute derivative question" },
|
|
35343
|
+
QuestionRecomputeResultSchema
|
|
35344
|
+
);
|
|
35345
|
+
}
|
|
35346
|
+
async function deleteQuestion(params) {
|
|
35347
|
+
const path = assertQuestionId(params.questionId);
|
|
35348
|
+
return sendQuestionRequest(
|
|
35349
|
+
params,
|
|
35350
|
+
{ method: "DELETE", path, label: "Delete derivative question" },
|
|
35351
|
+
QuestionDeleteResultSchema
|
|
35352
|
+
);
|
|
35353
|
+
}
|
|
35354
|
+
function isSettled(status) {
|
|
35355
|
+
return status === "ready" || status === "failed";
|
|
35356
|
+
}
|
|
35357
|
+
function abortError(signal) {
|
|
35358
|
+
const reason = signal.reason;
|
|
35359
|
+
if (reason instanceof Error) return reason;
|
|
35360
|
+
const error = new Error("The operation was aborted");
|
|
35361
|
+
error.name = "AbortError";
|
|
35362
|
+
return error;
|
|
35363
|
+
}
|
|
35364
|
+
async function waitForQuestion(params) {
|
|
35365
|
+
const timeoutMs = Math.max(
|
|
35366
|
+
0,
|
|
35367
|
+
params.timeoutMs ?? DEFAULT_QUESTION_TIMEOUT_MS
|
|
35368
|
+
);
|
|
35369
|
+
const pollIntervalMs = Math.max(
|
|
35370
|
+
0,
|
|
35371
|
+
params.pollIntervalMs ?? DEFAULT_QUESTION_POLL_INTERVAL_MS
|
|
35372
|
+
);
|
|
35373
|
+
const deadline = Date.now() + timeoutMs;
|
|
35374
|
+
for (; ; ) {
|
|
35375
|
+
if (params.signal?.aborted) throw abortError(params.signal);
|
|
35376
|
+
const latest = await getQuestion(params);
|
|
35377
|
+
if (isSettled(latest.status)) return latest;
|
|
35378
|
+
const remaining = deadline - Date.now();
|
|
35379
|
+
if (remaining <= 0) {
|
|
35380
|
+
throw new DerivativeQuestionTimeoutError(
|
|
35381
|
+
`Derivative question ${latest.questionId} was still ${latest.status} after ${timeoutMs}ms`,
|
|
35382
|
+
{
|
|
35383
|
+
questionId: latest.questionId,
|
|
35384
|
+
derivedScope: latest.derivedScope,
|
|
35385
|
+
status: latest.status,
|
|
35386
|
+
timeoutMs
|
|
35387
|
+
}
|
|
35388
|
+
);
|
|
35389
|
+
}
|
|
35390
|
+
await sleep2(Math.min(pollIntervalMs, remaining));
|
|
35391
|
+
}
|
|
35392
|
+
}
|
|
35393
|
+
async function askPersonalServer(params) {
|
|
35394
|
+
const registered = await registerQuestion(params);
|
|
35395
|
+
const registration = await waitForQuestion({
|
|
35396
|
+
...params,
|
|
35397
|
+
questionId: registered.questionId
|
|
35398
|
+
});
|
|
35399
|
+
if (registration.status !== "ready") {
|
|
35400
|
+
throw new DerivativeQuestionFailedError(
|
|
35401
|
+
`Derivative question ${registration.questionId} failed: ${registration.error ?? "no reason given"}`,
|
|
35402
|
+
{
|
|
35403
|
+
questionId: registration.questionId,
|
|
35404
|
+
derivedScope: registration.derivedScope,
|
|
35405
|
+
error: registration.error
|
|
35406
|
+
}
|
|
35407
|
+
);
|
|
35408
|
+
}
|
|
35409
|
+
const signer = resolveWriteSigner(params.signer, {
|
|
35410
|
+
account: params.account
|
|
35411
|
+
});
|
|
35412
|
+
const readParams = {
|
|
35413
|
+
personalServerUrl: normalizeBaseUrl2(params.personalServerUrl),
|
|
35414
|
+
scope: params.derivedScope,
|
|
35415
|
+
grantId: params.grantId,
|
|
35416
|
+
signMessage: signer.signMessage,
|
|
35417
|
+
...params.audience === void 0 ? {} : { audience: params.audience },
|
|
35418
|
+
...params.headers === void 0 ? {} : { headers: params.headers },
|
|
35419
|
+
...params.fetch === void 0 ? {} : { fetch: params.fetch }
|
|
35420
|
+
};
|
|
35421
|
+
const record = await readPersonalServerData(readParams);
|
|
35422
|
+
return { registration, record };
|
|
35423
|
+
}
|
|
35424
|
+
|
|
34943
35425
|
// src/protocol/gateway.ts
|
|
34944
35426
|
function withGrantPermissions(grant) {
|
|
34945
35427
|
const stripped = { ...grant };
|
|
@@ -36020,11 +36502,23 @@ export {
|
|
|
36020
36502
|
ContractNotFoundError,
|
|
36021
36503
|
DATA_ACCESS_OP_TYPE,
|
|
36022
36504
|
DATA_REGISTRY_STATUS_ABI,
|
|
36505
|
+
DEFAULT_QUESTION_POLL_INTERVAL_MS,
|
|
36506
|
+
DEFAULT_QUESTION_TIMEOUT_MS,
|
|
36507
|
+
DERIVATIVE_QUESTIONS_PATH,
|
|
36023
36508
|
DataFileEnvelopeSchema,
|
|
36024
36509
|
DataPointDeletedError,
|
|
36025
36510
|
DataPointNotFoundError,
|
|
36026
36511
|
DataPointStatus,
|
|
36027
36512
|
DataPointVersionConflictError,
|
|
36513
|
+
DerivativeComputeUnavailableError,
|
|
36514
|
+
DerivativeCycleError,
|
|
36515
|
+
DerivativeQuestionFailedError,
|
|
36516
|
+
DerivativeQuestionInvalidError,
|
|
36517
|
+
DerivativeQuestionNotFoundError,
|
|
36518
|
+
DerivativeQuestionRejectedError,
|
|
36519
|
+
DerivativeQuestionSchema,
|
|
36520
|
+
DerivativeQuestionTimeoutError,
|
|
36521
|
+
DerivativeSourceNotGrantedError,
|
|
36028
36522
|
DropboxStorage,
|
|
36029
36523
|
ECIESError,
|
|
36030
36524
|
ESCROW_DEPOSIT_ABI2 as ESCROW_DEPOSIT_ABI,
|
|
@@ -36049,6 +36543,9 @@ export {
|
|
|
36049
36543
|
LineageReadError,
|
|
36050
36544
|
MASTER_KEY_MESSAGE,
|
|
36051
36545
|
MAX_LINEAGE_SOURCES,
|
|
36546
|
+
MAX_QUESTION_CHARS,
|
|
36547
|
+
MAX_QUESTION_MODEL_CHARS,
|
|
36548
|
+
MAX_QUESTION_SOURCE_SCOPES,
|
|
36052
36549
|
MissingAuthError,
|
|
36053
36550
|
NATIVE_ASSET_ADDRESS,
|
|
36054
36551
|
NATIVE_VANA_ASSET,
|
|
@@ -36069,6 +36566,11 @@ export {
|
|
|
36069
36566
|
PersonalServerError,
|
|
36070
36567
|
PersonalServerWriteError,
|
|
36071
36568
|
PinataStorage,
|
|
36569
|
+
QUESTION_STATUSES,
|
|
36570
|
+
QuestionDeleteResultSchema,
|
|
36571
|
+
QuestionRecomputeResultSchema,
|
|
36572
|
+
QuestionRegisteredBySchema,
|
|
36573
|
+
QuestionStatusSchema,
|
|
36072
36574
|
R2Storage,
|
|
36073
36575
|
RECORD_DATA_ACCESS_TYPES,
|
|
36074
36576
|
REGISTRATION_KIND_FOR_OP,
|
|
@@ -36107,6 +36609,7 @@ export {
|
|
|
36107
36609
|
WriteSessionExpiredError,
|
|
36108
36610
|
WriteTransportError,
|
|
36109
36611
|
WriteUnauthorizedError,
|
|
36612
|
+
askPersonalServer,
|
|
36110
36613
|
assertDerivedScopeNaming,
|
|
36111
36614
|
assertValidPkceVerifier,
|
|
36112
36615
|
authorizeEscrowPayment,
|
|
@@ -36150,6 +36653,7 @@ export {
|
|
|
36150
36653
|
dataRegistryDomain,
|
|
36151
36654
|
decryptWithPassword,
|
|
36152
36655
|
deleteDataPoint,
|
|
36656
|
+
deleteQuestion,
|
|
36153
36657
|
deriveDataPointId,
|
|
36154
36658
|
deriveMasterKey,
|
|
36155
36659
|
deriveScopeKey,
|
|
@@ -36179,6 +36683,7 @@ export {
|
|
|
36179
36683
|
getOpFee,
|
|
36180
36684
|
getPersonalServerLineage,
|
|
36181
36685
|
getPlatformCapabilities,
|
|
36686
|
+
getQuestion,
|
|
36182
36687
|
getServiceEndpoints,
|
|
36183
36688
|
grantPermissions,
|
|
36184
36689
|
grantRegistrationDomain,
|
|
@@ -36191,6 +36696,7 @@ export {
|
|
|
36191
36696
|
isPlatformSupported,
|
|
36192
36697
|
isRedactedLineageNode,
|
|
36193
36698
|
isTombstoneHashes,
|
|
36699
|
+
listQuestions,
|
|
36194
36700
|
mainnetServices,
|
|
36195
36701
|
moksha,
|
|
36196
36702
|
mokshaServices,
|
|
@@ -36210,8 +36716,10 @@ export {
|
|
|
36210
36716
|
personalServerLineagePath,
|
|
36211
36717
|
personalServerRegistrationDomain,
|
|
36212
36718
|
readPersonalServerData,
|
|
36719
|
+
recomputeQuestion,
|
|
36213
36720
|
recoverServerOwner,
|
|
36214
36721
|
registerPersonalServerSignature,
|
|
36722
|
+
registerQuestion,
|
|
36215
36723
|
resolveWriteSigner,
|
|
36216
36724
|
scopeCoveredByGrant,
|
|
36217
36725
|
scopeMatchesPattern,
|
|
@@ -36231,6 +36739,7 @@ export {
|
|
|
36231
36739
|
verifyGrantRegistration,
|
|
36232
36740
|
verifyPkceChallenge,
|
|
36233
36741
|
verifyWeb3Signed,
|
|
36742
|
+
waitForQuestion,
|
|
36234
36743
|
writeData,
|
|
36235
36744
|
writePersonalServerData
|
|
36236
36745
|
};
|