@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.
Files changed (37) hide show
  1. package/README.md +129 -3
  2. package/dist/errors.cjs +56 -0
  3. package/dist/errors.cjs.map +1 -1
  4. package/dist/errors.d.ts +98 -2
  5. package/dist/errors.js +48 -0
  6. package/dist/errors.js.map +1 -1
  7. package/dist/index.browser.d.ts +1 -0
  8. package/dist/index.browser.js +542 -33
  9. package/dist/index.browser.js.map +4 -4
  10. package/dist/index.node.cjs +569 -33
  11. package/dist/index.node.cjs.map +4 -4
  12. package/dist/index.node.d.ts +1 -0
  13. package/dist/index.node.js +542 -33
  14. package/dist/index.node.js.map +4 -4
  15. package/dist/protocol/derivative-questions.cjs +501 -0
  16. package/dist/protocol/derivative-questions.cjs.map +1 -0
  17. package/dist/protocol/derivative-questions.d.ts +355 -0
  18. package/dist/protocol/derivative-questions.js +486 -0
  19. package/dist/protocol/derivative-questions.js.map +1 -0
  20. package/dist/protocol/derivative-questions.test.d.ts +1 -0
  21. package/dist/protocol/lineage.cjs +9 -4
  22. package/dist/protocol/lineage.cjs.map +1 -1
  23. package/dist/protocol/lineage.d.ts +21 -12
  24. package/dist/protocol/lineage.js +9 -4
  25. package/dist/protocol/lineage.js.map +1 -1
  26. package/dist/protocol/personal-server-write.cjs +12 -108
  27. package/dist/protocol/personal-server-write.cjs.map +1 -1
  28. package/dist/protocol/personal-server-write.d.ts +2 -17
  29. package/dist/protocol/personal-server-write.js +7 -98
  30. package/dist/protocol/personal-server-write.js.map +1 -1
  31. package/dist/protocol/write-request.cjs +142 -0
  32. package/dist/protocol/write-request.cjs.map +1 -0
  33. package/dist/protocol/write-request.d.ts +63 -0
  34. package/dist/protocol/write-request.js +111 -0
  35. package/dist/protocol/write-request.js.map +1 -0
  36. package/dist/tests/mock-personal-server.d.ts +51 -0
  37. package/package.json +1 -1
@@ -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.object({
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 sha2565 } from "@noble/hashes/sha2";
34390
- import { bytesToHex as bytesToHex2, isAddress as isAddress6 } from "viem";
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
- var WRITE_SESSION_PATH = "/v1/write/session";
34393
- var WRITE_SIGNATURE_HEADER = "X-Vana-Write-Signature";
34394
- var WRITE_METADATA_HEADER = "X-Vana-Metadata";
34395
- var LINEAGE_FIELD = "lineage";
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: bytesToHex2(sha2565(input.bytes)),
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
  };