@opendatalabs/personal-server-ts-core 1.8.0 → 1.10.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/dist/api/index.d.ts +19 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +23 -0
- package/dist/api/index.js.map +1 -1
- package/dist/derivatives/api.d.ts +33 -0
- package/dist/derivatives/api.d.ts.map +1 -0
- package/dist/derivatives/api.js +216 -0
- package/dist/derivatives/api.js.map +1 -0
- package/dist/derivatives/compute.d.ts +106 -0
- package/dist/derivatives/compute.d.ts.map +1 -0
- package/dist/derivatives/compute.js +380 -0
- package/dist/derivatives/compute.js.map +1 -0
- package/dist/derivatives/e2ee/aad.d.ts +22 -0
- package/dist/derivatives/e2ee/aad.d.ts.map +1 -0
- package/dist/derivatives/e2ee/aad.js +32 -0
- package/dist/derivatives/e2ee/aad.js.map +1 -0
- package/dist/derivatives/e2ee/attestation.d.ts +122 -0
- package/dist/derivatives/e2ee/attestation.d.ts.map +1 -0
- package/dist/derivatives/e2ee/attestation.js +217 -0
- package/dist/derivatives/e2ee/attestation.js.map +1 -0
- package/dist/derivatives/e2ee/index.d.ts +6 -0
- package/dist/derivatives/e2ee/index.d.ts.map +1 -0
- package/dist/derivatives/e2ee/index.js +6 -0
- package/dist/derivatives/e2ee/index.js.map +1 -0
- package/dist/derivatives/e2ee/jcs.d.ts +17 -0
- package/dist/derivatives/e2ee/jcs.d.ts.map +1 -0
- package/dist/derivatives/e2ee/jcs.js +55 -0
- package/dist/derivatives/e2ee/jcs.js.map +1 -0
- package/dist/derivatives/e2ee/phala.d.ts +55 -0
- package/dist/derivatives/e2ee/phala.d.ts.map +1 -0
- package/dist/derivatives/e2ee/phala.js +167 -0
- package/dist/derivatives/e2ee/phala.js.map +1 -0
- package/dist/derivatives/e2ee/suite.d.ts +56 -0
- package/dist/derivatives/e2ee/suite.d.ts.map +1 -0
- package/dist/derivatives/e2ee/suite.js +164 -0
- package/dist/derivatives/e2ee/suite.js.map +1 -0
- package/dist/derivatives/index.d.ts +10 -0
- package/dist/derivatives/index.d.ts.map +1 -0
- package/dist/derivatives/index.js +10 -0
- package/dist/derivatives/index.js.map +1 -0
- package/dist/derivatives/inference.d.ts +134 -0
- package/dist/derivatives/inference.d.ts.map +1 -0
- package/dist/derivatives/inference.js +223 -0
- package/dist/derivatives/inference.js.map +1 -0
- package/dist/derivatives/prompt.d.ts +64 -0
- package/dist/derivatives/prompt.d.ts.map +1 -0
- package/dist/derivatives/prompt.js +186 -0
- package/dist/derivatives/prompt.js.map +1 -0
- package/dist/derivatives/registration.d.ts +53 -0
- package/dist/derivatives/registration.d.ts.map +1 -0
- package/dist/derivatives/registration.js +163 -0
- package/dist/derivatives/registration.js.map +1 -0
- package/dist/derivatives/scheduler.d.ts +56 -0
- package/dist/derivatives/scheduler.d.ts.map +1 -0
- package/dist/derivatives/scheduler.js +151 -0
- package/dist/derivatives/scheduler.js.map +1 -0
- package/dist/derivatives/store.d.ts +14 -0
- package/dist/derivatives/store.d.ts.map +1 -0
- package/dist/derivatives/store.js +75 -0
- package/dist/derivatives/store.js.map +1 -0
- package/dist/derivatives/types.d.ts +72 -0
- package/dist/derivatives/types.d.ts.map +1 -0
- package/dist/derivatives/types.js +25 -0
- package/dist/derivatives/types.js.map +1 -0
- package/dist/errors/catalog.d.ts +20 -0
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/catalog.js +26 -0
- package/dist/errors/catalog.js.map +1 -1
- package/dist/schemas/server-config.d.ts +14 -0
- package/dist/schemas/server-config.d.ts.map +1 -1
- package/dist/schemas/server-config.js +34 -0
- package/dist/schemas/server-config.js.map +1 -1
- package/dist/sync/workers/download.d.ts +14 -0
- package/dist/sync/workers/download.d.ts.map +1 -1
- package/dist/sync/workers/download.js +23 -0
- package/dist/sync/workers/download.js.map +1 -1
- package/dist/test-utils/e2ee-fixtures.d.ts +94 -0
- package/dist/test-utils/e2ee-fixtures.d.ts.map +1 -0
- package/dist/test-utils/e2ee-fixtures.js +116 -0
- package/dist/test-utils/e2ee-fixtures.js.map +1 -0
- package/dist/test-utils/e2ee-gateway.d.ts +61 -0
- package/dist/test-utils/e2ee-gateway.d.ts.map +1 -0
- package/dist/test-utils/e2ee-gateway.js +248 -0
- package/dist/test-utils/e2ee-gateway.js.map +1 -0
- package/dist/test-utils/index.d.ts +3 -0
- package/dist/test-utils/index.d.ts.map +1 -1
- package/dist/test-utils/index.js +3 -0
- package/dist/test-utils/index.js.map +1 -1
- package/dist/test-utils/memory-storage.d.ts +12 -0
- package/dist/test-utils/memory-storage.d.ts.map +1 -0
- package/dist/test-utils/memory-storage.js +146 -0
- package/dist/test-utils/memory-storage.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Question registration: input validation, the naming rule (shared with the
|
|
3
|
+
* lineage write path) and the cycle guard that keeps recompute-on-refresh
|
|
4
|
+
* bounded.
|
|
5
|
+
*/
|
|
6
|
+
import { DerivativeCycleError, DerivativeQuestionInvalidError, } from "../errors/catalog.js";
|
|
7
|
+
import { parseDataScopeContract } from "../contracts/data.js";
|
|
8
|
+
import { assertDerivedScopeNaming } from "../lineage/lineage.js";
|
|
9
|
+
import { isWriteScopeEntry } from "../policy/data-write.js";
|
|
10
|
+
import { scopeCoveredByGrant } from "@opendatalabs/vana-sdk/browser";
|
|
11
|
+
export const MAX_QUESTION_SOURCE_SCOPES = 16;
|
|
12
|
+
export const MAX_QUESTION_CHARS = 8_000;
|
|
13
|
+
export const MAX_MODEL_CHARS = 128;
|
|
14
|
+
/** Unvalidated scope strings echoed in 400 details are cut to this. */
|
|
15
|
+
export const MAX_ECHOED_SCOPE_CHARS = 128;
|
|
16
|
+
/** Model ids as providers spell them (`z-ai/glm-5.2`, `gpt-4o-mini`, ...). */
|
|
17
|
+
const MODEL_ID = /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/;
|
|
18
|
+
function isRecord(value) {
|
|
19
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
20
|
+
}
|
|
21
|
+
function parseScope(value, field) {
|
|
22
|
+
if (typeof value !== "string") {
|
|
23
|
+
throw new DerivativeQuestionInvalidError(`${field} must be a scope string`, {
|
|
24
|
+
field,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
const parsed = parseDataScopeContract(value);
|
|
28
|
+
if (!parsed.ok) {
|
|
29
|
+
throw new DerivativeQuestionInvalidError(`${field} is not a valid scope: ${parsed.body.message}`, { field, scope: value.slice(0, MAX_ECHOED_SCOPE_CHARS) });
|
|
30
|
+
}
|
|
31
|
+
return parsed.scope;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validate the POST body of a question registration. Throws 400
|
|
35
|
+
* DERIVATIVE_QUESTION_INVALID on shape errors and 400
|
|
36
|
+
* LINEAGE_SCOPE_UNDER_SOURCE_PREFIX when the derived scope shares its
|
|
37
|
+
* first segment with a source (the lineage naming rule, applied up front
|
|
38
|
+
* so a registration that could never be written is refused here).
|
|
39
|
+
*/
|
|
40
|
+
export function parseQuestionInput(body) {
|
|
41
|
+
if (!isRecord(body)) {
|
|
42
|
+
throw new DerivativeQuestionInvalidError("Body must be a JSON object");
|
|
43
|
+
}
|
|
44
|
+
const derivedScope = parseScope(body.derivedScope, "derivedScope");
|
|
45
|
+
if (!Array.isArray(body.sourceScopes) || body.sourceScopes.length === 0) {
|
|
46
|
+
throw new DerivativeQuestionInvalidError("sourceScopes must be a non-empty array of scopes", { field: "sourceScopes" });
|
|
47
|
+
}
|
|
48
|
+
if (body.sourceScopes.length > MAX_QUESTION_SOURCE_SCOPES) {
|
|
49
|
+
throw new DerivativeQuestionInvalidError(`sourceScopes lists ${body.sourceScopes.length} scopes; the maximum is ${MAX_QUESTION_SOURCE_SCOPES}`, { field: "sourceScopes", max: MAX_QUESTION_SOURCE_SCOPES });
|
|
50
|
+
}
|
|
51
|
+
const sourceScopes = [];
|
|
52
|
+
for (const entry of body.sourceScopes) {
|
|
53
|
+
const scope = parseScope(entry, "sourceScopes[]");
|
|
54
|
+
if (sourceScopes.includes(scope)) {
|
|
55
|
+
throw new DerivativeQuestionInvalidError("sourceScopes lists the same scope twice", { field: "sourceScopes", duplicate: scope });
|
|
56
|
+
}
|
|
57
|
+
if (scope === derivedScope) {
|
|
58
|
+
throw new DerivativeQuestionInvalidError("derivedScope cannot be one of its own sources", { field: "sourceScopes", scope });
|
|
59
|
+
}
|
|
60
|
+
sourceScopes.push(scope);
|
|
61
|
+
}
|
|
62
|
+
if (typeof body.question !== "string" || body.question.trim() === "") {
|
|
63
|
+
throw new DerivativeQuestionInvalidError("question must be a non-empty string", { field: "question" });
|
|
64
|
+
}
|
|
65
|
+
if (body.question.length > MAX_QUESTION_CHARS) {
|
|
66
|
+
throw new DerivativeQuestionInvalidError(`question is ${body.question.length} characters; the maximum is ${MAX_QUESTION_CHARS}`, { field: "question", max: MAX_QUESTION_CHARS });
|
|
67
|
+
}
|
|
68
|
+
let model = null;
|
|
69
|
+
if (body.model !== undefined && body.model !== null) {
|
|
70
|
+
if (typeof body.model !== "string" ||
|
|
71
|
+
body.model.length > MAX_MODEL_CHARS ||
|
|
72
|
+
!MODEL_ID.test(body.model)) {
|
|
73
|
+
throw new DerivativeQuestionInvalidError("model must be a provider model id", { field: "model" });
|
|
74
|
+
}
|
|
75
|
+
model = body.model;
|
|
76
|
+
}
|
|
77
|
+
assertDerivedScopeNaming(derivedScope, sourceScopes);
|
|
78
|
+
return { derivedScope, sourceScopes, question: body.question, model };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Recompute-on-refresh follows edges source -> derived. A registration whose
|
|
82
|
+
* derived scope can reach one of its own sources through other
|
|
83
|
+
* registrations would recompute forever (A from B, B from A). Refuse it.
|
|
84
|
+
* Returns the offending path (derived scope back to itself) or null.
|
|
85
|
+
*/
|
|
86
|
+
export function findDerivationCycle(candidate, existing) {
|
|
87
|
+
// derived scope -> the scopes it is computed from
|
|
88
|
+
const sourcesOf = new Map();
|
|
89
|
+
const add = (derived, sources) => {
|
|
90
|
+
const set = sourcesOf.get(derived) ?? new Set();
|
|
91
|
+
for (const source of sources)
|
|
92
|
+
set.add(source);
|
|
93
|
+
sourcesOf.set(derived, set);
|
|
94
|
+
};
|
|
95
|
+
for (const registration of existing) {
|
|
96
|
+
add(registration.derivedScope, registration.sourceScopes);
|
|
97
|
+
}
|
|
98
|
+
add(candidate.derivedScope, candidate.sourceScopes);
|
|
99
|
+
// Depth-first from the candidate's derived scope through the sources it
|
|
100
|
+
// depends on; reaching the derived scope again is a cycle. Bounded by the
|
|
101
|
+
// number of distinct scopes (visited set), so no unbounded walk.
|
|
102
|
+
const target = candidate.derivedScope;
|
|
103
|
+
const visited = new Set();
|
|
104
|
+
const stack = [
|
|
105
|
+
{ scope: target, path: [target] },
|
|
106
|
+
];
|
|
107
|
+
while (stack.length > 0) {
|
|
108
|
+
const { scope, path } = stack.pop();
|
|
109
|
+
for (const source of sourcesOf.get(scope) ?? []) {
|
|
110
|
+
if (source === target)
|
|
111
|
+
return [...path, source];
|
|
112
|
+
if (visited.has(source))
|
|
113
|
+
continue;
|
|
114
|
+
visited.add(source);
|
|
115
|
+
stack.push({ scope: source, path: [...path, source] });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Validate, guard against cycles and persist a registration in `pending`.
|
|
122
|
+
* The caller has already authorized the write on `derivedScope`.
|
|
123
|
+
*/
|
|
124
|
+
export async function createQuestionRegistration(input) {
|
|
125
|
+
const parsed = parseQuestionInput(input.body);
|
|
126
|
+
const cycle = findDerivationCycle(parsed, await input.store.list());
|
|
127
|
+
if (cycle) {
|
|
128
|
+
throw new DerivativeCycleError({
|
|
129
|
+
derivedScope: parsed.derivedScope,
|
|
130
|
+
path: cycle,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const at = input.now().toISOString();
|
|
134
|
+
const registration = {
|
|
135
|
+
questionId: input.questionId,
|
|
136
|
+
derivedScope: parsed.derivedScope,
|
|
137
|
+
sourceScopes: parsed.sourceScopes,
|
|
138
|
+
question: parsed.question,
|
|
139
|
+
model: parsed.model,
|
|
140
|
+
registeredBy: input.registeredBy,
|
|
141
|
+
status: "pending",
|
|
142
|
+
error: null,
|
|
143
|
+
createdAt: at,
|
|
144
|
+
updatedAt: at,
|
|
145
|
+
lastComputedAt: null,
|
|
146
|
+
derivedVersion: null,
|
|
147
|
+
derivedCollectedAt: null,
|
|
148
|
+
};
|
|
149
|
+
await input.store.insert(registration);
|
|
150
|
+
return registration;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Consent check for a builder question: the sources feed a prompt whose
|
|
154
|
+
* answer the builder reads, so every source scope must be covered by a READ
|
|
155
|
+
* entry of the builder's grant (bare entries; `write:` entries confer
|
|
156
|
+
* nothing). Returns the uncovered scopes; empty = all covered. The system
|
|
157
|
+
* prompt is not a security boundary, this is.
|
|
158
|
+
*/
|
|
159
|
+
export function uncoveredSourceScopes(sourceScopes, grantScopes) {
|
|
160
|
+
const readEntries = (grantScopes ?? []).filter((entry) => !isWriteScopeEntry(entry));
|
|
161
|
+
return sourceScopes.filter((scope) => !scopeCoveredByGrant(scope, readEntries));
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=registration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registration.js","sourceRoot":"","sources":["../../src/derivatives/registration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recompute scheduler: marks registrations stale when one of their source
|
|
3
|
+
* scopes changes and runs the compute after a quiet period, one in flight
|
|
4
|
+
* per question. Timers and the clock are injectable so tests drive it
|
|
5
|
+
* deterministically.
|
|
6
|
+
*/
|
|
7
|
+
import type { QuestionStore } from "./types.js";
|
|
8
|
+
export interface SchedulerTimers {
|
|
9
|
+
setTimeout(callback: () => void, ms: number): unknown;
|
|
10
|
+
clearTimeout(handle: unknown): void;
|
|
11
|
+
}
|
|
12
|
+
export interface RecomputeSchedulerOptions {
|
|
13
|
+
store: QuestionStore;
|
|
14
|
+
/** Runs one compute; must not throw for compute failures. */
|
|
15
|
+
compute(questionId: string): Promise<unknown>;
|
|
16
|
+
/** Quiet period after a source change (default 5s). */
|
|
17
|
+
debounceMs?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Lets `markSourceChanged` recognise a new version that was computed FROM
|
|
20
|
+
* a question's own derived scope (its `$lineage` names the derived data
|
|
21
|
+
* point id) and skip that question: a cross-replica cycle then settles
|
|
22
|
+
* instead of ping-ponging through sync. Without it every change counts.
|
|
23
|
+
*/
|
|
24
|
+
serverOwner?: `0x${string}`;
|
|
25
|
+
timers?: SchedulerTimers;
|
|
26
|
+
now?: () => Date;
|
|
27
|
+
logger?: {
|
|
28
|
+
warn?(payload: Record<string, unknown>, message: string): void;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface RecomputeScheduler {
|
|
32
|
+
/**
|
|
33
|
+
* A scope got a new local version (ingest or sync). Every registration
|
|
34
|
+
* that lists it as a source is marked `stale` (if it had a result) and
|
|
35
|
+
* scheduled. Fire and forget; failures are logged.
|
|
36
|
+
*/
|
|
37
|
+
markSourceChanged(scope: string, options?: {
|
|
38
|
+
/** `$lineage.sources` of the new version, when it is a derivative. */
|
|
39
|
+
lineageSources?: readonly string[];
|
|
40
|
+
}): void;
|
|
41
|
+
/** Schedule one question; `immediate` skips the debounce (owner recompute). */
|
|
42
|
+
requestRecompute(questionId: string, options?: {
|
|
43
|
+
immediate?: boolean;
|
|
44
|
+
}): void;
|
|
45
|
+
/** Resolves once no compute or store lookup is pending or timed. */
|
|
46
|
+
whenIdle(): Promise<void>;
|
|
47
|
+
/** Cancel pending timers. In-flight computes finish on their own. */
|
|
48
|
+
stop(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Resume after `stop()`: questions left `pending` or `stale` are
|
|
51
|
+
* scheduled again (immediately). Idempotent while running.
|
|
52
|
+
*/
|
|
53
|
+
start(): void;
|
|
54
|
+
}
|
|
55
|
+
export declare function createRecomputeScheduler(options: RecomputeSchedulerOptions): RecomputeScheduler;
|
|
56
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../src/derivatives/scheduler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACtD,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,aAAa,CAAC;IACrB,6DAA6D;IAC7D,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;KAChE,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,iBAAiB,CACf,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QACR,sEAAsE;QACtE,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KACpC,GACA,IAAI,CAAC;IACR,+EAA+E;IAC/E,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC9E,oEAAoE;IACpE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,qEAAqE;IACrE,IAAI,IAAI,IAAI,CAAC;IACb;;;OAGG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAcD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,yBAAyB,GACjC,kBAAkB,CAmLpB"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recompute scheduler: marks registrations stale when one of their source
|
|
3
|
+
* scopes changes and runs the compute after a quiet period, one in flight
|
|
4
|
+
* per question. Timers and the clock are injectable so tests drive it
|
|
5
|
+
* deterministically.
|
|
6
|
+
*/
|
|
7
|
+
import { computeDataPointId } from "../sync/data-point-id.js";
|
|
8
|
+
const defaultTimers = {
|
|
9
|
+
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
10
|
+
clearTimeout: (handle) => clearTimeout(handle),
|
|
11
|
+
};
|
|
12
|
+
export function createRecomputeScheduler(options) {
|
|
13
|
+
const debounceMs = options.debounceMs ?? 5_000;
|
|
14
|
+
const timers = options.timers ?? defaultTimers;
|
|
15
|
+
const now = options.now ?? (() => new Date());
|
|
16
|
+
const states = new Map();
|
|
17
|
+
const pending = new Set();
|
|
18
|
+
let stopped = false;
|
|
19
|
+
function track(promise) {
|
|
20
|
+
pending.add(promise);
|
|
21
|
+
const done = () => pending.delete(promise);
|
|
22
|
+
promise.then(done, done);
|
|
23
|
+
return promise;
|
|
24
|
+
}
|
|
25
|
+
function warn(payload, message) {
|
|
26
|
+
options.logger?.warn?.(payload, message);
|
|
27
|
+
}
|
|
28
|
+
function stateFor(questionId) {
|
|
29
|
+
let state = states.get(questionId);
|
|
30
|
+
if (!state) {
|
|
31
|
+
state = { timer: null, running: null, rerun: false };
|
|
32
|
+
states.set(questionId, state);
|
|
33
|
+
}
|
|
34
|
+
return state;
|
|
35
|
+
}
|
|
36
|
+
function run(questionId) {
|
|
37
|
+
if (stopped)
|
|
38
|
+
return;
|
|
39
|
+
const state = stateFor(questionId);
|
|
40
|
+
if (state.running) {
|
|
41
|
+
// One in flight per question; a change during the run means the
|
|
42
|
+
// result is already stale, so run once more when it finishes.
|
|
43
|
+
state.rerun = true;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
state.running = track(Promise.resolve()
|
|
47
|
+
.then(() => options.compute(questionId))
|
|
48
|
+
.then(() => undefined, (err) => warn({
|
|
49
|
+
questionId,
|
|
50
|
+
error: err instanceof Error ? err.name : String(err),
|
|
51
|
+
}, "Derivative compute threw"))
|
|
52
|
+
.then(async () => {
|
|
53
|
+
state.running = null;
|
|
54
|
+
if (state.rerun) {
|
|
55
|
+
state.rerun = false;
|
|
56
|
+
await markStale(questionId);
|
|
57
|
+
schedule(questionId, 0);
|
|
58
|
+
}
|
|
59
|
+
else if (!states.get(questionId)?.timer) {
|
|
60
|
+
states.delete(questionId);
|
|
61
|
+
}
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
function schedule(questionId, delayMs) {
|
|
65
|
+
if (stopped)
|
|
66
|
+
return;
|
|
67
|
+
const state = stateFor(questionId);
|
|
68
|
+
if (state.timer !== null)
|
|
69
|
+
timers.clearTimeout(state.timer);
|
|
70
|
+
state.timer = timers.setTimeout(() => {
|
|
71
|
+
state.timer = null;
|
|
72
|
+
run(questionId);
|
|
73
|
+
}, delayMs);
|
|
74
|
+
}
|
|
75
|
+
async function markStale(questionId) {
|
|
76
|
+
const registration = await options.store.get(questionId);
|
|
77
|
+
if (!registration)
|
|
78
|
+
return;
|
|
79
|
+
if (registration.status === "ready" || registration.status === "failed") {
|
|
80
|
+
await options.store.update(questionId, {
|
|
81
|
+
status: "stale",
|
|
82
|
+
updatedAt: now().toISOString(),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
markSourceChanged(scope, opts) {
|
|
88
|
+
if (stopped)
|
|
89
|
+
return;
|
|
90
|
+
const lineage = new Set((opts?.lineageSources ?? []).map((id) => id.toLowerCase()));
|
|
91
|
+
void track((async () => {
|
|
92
|
+
const affected = await options.store.list({ sourceScope: scope });
|
|
93
|
+
for (const registration of affected) {
|
|
94
|
+
if (options.serverOwner &&
|
|
95
|
+
lineage.has(computeDataPointId(options.serverOwner, registration.derivedScope))) {
|
|
96
|
+
// The new version descends from this question's own output.
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
await markStale(registration.questionId);
|
|
100
|
+
schedule(registration.questionId, debounceMs);
|
|
101
|
+
}
|
|
102
|
+
})().catch((err) => warn({ scope, error: err instanceof Error ? err.name : String(err) }, "Could not mark derivative questions stale")));
|
|
103
|
+
},
|
|
104
|
+
requestRecompute(questionId, opts) {
|
|
105
|
+
if (stopped)
|
|
106
|
+
return;
|
|
107
|
+
void track(markStale(questionId)
|
|
108
|
+
.catch((err) => warn({
|
|
109
|
+
questionId,
|
|
110
|
+
error: err instanceof Error ? err.name : String(err),
|
|
111
|
+
}, "Could not mark derivative question stale"))
|
|
112
|
+
.then(() => schedule(questionId, opts?.immediate ? 0 : debounceMs)));
|
|
113
|
+
},
|
|
114
|
+
async whenIdle() {
|
|
115
|
+
// Waits for store lookups and in-flight computes. Real timers are
|
|
116
|
+
// polled too; injected timers are the caller's to fire.
|
|
117
|
+
const waitForTimers = !options.timers;
|
|
118
|
+
for (;;) {
|
|
119
|
+
while (pending.size > 0) {
|
|
120
|
+
await Promise.allSettled([...pending]);
|
|
121
|
+
}
|
|
122
|
+
const busy = [...states.values()].some((state) => state.running !== null || (waitForTimers && state.timer !== null));
|
|
123
|
+
if (!busy)
|
|
124
|
+
return;
|
|
125
|
+
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
stop() {
|
|
129
|
+
stopped = true;
|
|
130
|
+
for (const state of states.values()) {
|
|
131
|
+
if (state.timer !== null)
|
|
132
|
+
timers.clearTimeout(state.timer);
|
|
133
|
+
state.timer = null;
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
start() {
|
|
137
|
+
if (!stopped)
|
|
138
|
+
return;
|
|
139
|
+
stopped = false;
|
|
140
|
+
void track((async () => {
|
|
141
|
+
for (const registration of await options.store.list()) {
|
|
142
|
+
if (registration.status === "pending" ||
|
|
143
|
+
registration.status === "stale") {
|
|
144
|
+
schedule(registration.questionId, 0);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
})().catch((err) => warn({ error: err instanceof Error ? err.name : String(err) }, "Could not reschedule derivative questions")));
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/derivatives/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { QuestionRegistration, QuestionStore, QuestionStoreListFilter } from "./types.js";
|
|
2
|
+
export declare function matchesQuestionFilter(registration: QuestionRegistration, filter: QuestionStoreListFilter | undefined): boolean;
|
|
3
|
+
/** Oldest first, the order every store lists in. */
|
|
4
|
+
export declare function sortQuestions(registrations: QuestionRegistration[]): QuestionRegistration[];
|
|
5
|
+
/**
|
|
6
|
+
* Map-backed store. The PS-Lite store wraps it with persistence; tests use
|
|
7
|
+
* it as is.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createInMemoryQuestionStore(options?: {
|
|
10
|
+
/** Called after every mutation with the full current list. */
|
|
11
|
+
onChange?: (registrations: QuestionRegistration[]) => Promise<void>;
|
|
12
|
+
initial?: QuestionRegistration[];
|
|
13
|
+
}): QuestionStore;
|
|
14
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/derivatives/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAEpB,aAAa,EACb,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAUpB,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,oBAAoB,EAClC,MAAM,EAAE,uBAAuB,GAAG,SAAS,GAC1C,OAAO,CAkBT;AAED,oDAAoD;AACpD,wBAAgB,aAAa,CAC3B,aAAa,EAAE,oBAAoB,EAAE,GACpC,oBAAoB,EAAE,CAMxB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,GAAE;IACP,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,oBAAoB,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAC7B,GACL,aAAa,CA4Cf"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
function clone(registration) {
|
|
2
|
+
return {
|
|
3
|
+
...registration,
|
|
4
|
+
sourceScopes: [...registration.sourceScopes],
|
|
5
|
+
registeredBy: { ...registration.registeredBy },
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export function matchesQuestionFilter(registration, filter) {
|
|
9
|
+
if (!filter)
|
|
10
|
+
return true;
|
|
11
|
+
if (filter.derivedScope && registration.derivedScope !== filter.derivedScope)
|
|
12
|
+
return false;
|
|
13
|
+
if (filter.sourceScope &&
|
|
14
|
+
!registration.sourceScopes.includes(filter.sourceScope))
|
|
15
|
+
return false;
|
|
16
|
+
if (filter.builder) {
|
|
17
|
+
const by = registration.registeredBy;
|
|
18
|
+
if (by.kind !== "builder" ||
|
|
19
|
+
by.builder.toLowerCase() !== filter.builder.toLowerCase())
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
/** Oldest first, the order every store lists in. */
|
|
25
|
+
export function sortQuestions(registrations) {
|
|
26
|
+
return [...registrations].sort((a, b) => a.createdAt.localeCompare(b.createdAt) ||
|
|
27
|
+
a.questionId.localeCompare(b.questionId));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Map-backed store. The PS-Lite store wraps it with persistence; tests use
|
|
31
|
+
* it as is.
|
|
32
|
+
*/
|
|
33
|
+
export function createInMemoryQuestionStore(options = {}) {
|
|
34
|
+
const byId = new Map();
|
|
35
|
+
for (const registration of options.initial ?? []) {
|
|
36
|
+
byId.set(registration.questionId, clone(registration));
|
|
37
|
+
}
|
|
38
|
+
async function changed() {
|
|
39
|
+
if (!options.onChange)
|
|
40
|
+
return;
|
|
41
|
+
await options.onChange(sortQuestions([...byId.values()]).map(clone));
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
async list(filter) {
|
|
45
|
+
return sortQuestions([...byId.values()].filter((registration) => matchesQuestionFilter(registration, filter))).map(clone);
|
|
46
|
+
},
|
|
47
|
+
async get(questionId) {
|
|
48
|
+
const registration = byId.get(questionId);
|
|
49
|
+
return registration ? clone(registration) : null;
|
|
50
|
+
},
|
|
51
|
+
async insert(registration) {
|
|
52
|
+
if (byId.has(registration.questionId)) {
|
|
53
|
+
throw new Error(`Question ${registration.questionId} is already registered`);
|
|
54
|
+
}
|
|
55
|
+
byId.set(registration.questionId, clone(registration));
|
|
56
|
+
await changed();
|
|
57
|
+
},
|
|
58
|
+
async update(questionId, patch) {
|
|
59
|
+
const current = byId.get(questionId);
|
|
60
|
+
if (!current)
|
|
61
|
+
return null;
|
|
62
|
+
const next = { ...current, ...patch };
|
|
63
|
+
byId.set(questionId, next);
|
|
64
|
+
await changed();
|
|
65
|
+
return clone(next);
|
|
66
|
+
},
|
|
67
|
+
async delete(questionId) {
|
|
68
|
+
const existed = byId.delete(questionId);
|
|
69
|
+
if (existed)
|
|
70
|
+
await changed();
|
|
71
|
+
return existed;
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/derivatives/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derivative compute layer: a builder registers a QUESTION over the owner's
|
|
3
|
+
* source scopes; the Personal Server answers it locally with an inference
|
|
4
|
+
* provider and writes the answer as an ordinary derivative record (lineage
|
|
5
|
+
* = the source data points) into the derived scope. See
|
|
6
|
+
* docs/derivative-data-api.md, "Compute (question to derivative)".
|
|
7
|
+
*/
|
|
8
|
+
export type QuestionStatus = "pending" | "ready" | "failed" | "stale";
|
|
9
|
+
/** Who registered the question; a builder is bound to the write grant. */
|
|
10
|
+
export type QuestionRegisteredBy = {
|
|
11
|
+
kind: "owner";
|
|
12
|
+
} | {
|
|
13
|
+
kind: "builder";
|
|
14
|
+
builder: `0x${string}`;
|
|
15
|
+
grantId: string;
|
|
16
|
+
};
|
|
17
|
+
export interface QuestionRegistration {
|
|
18
|
+
questionId: string;
|
|
19
|
+
derivedScope: string;
|
|
20
|
+
sourceScopes: string[];
|
|
21
|
+
/** The prompt template text (the builder's question). */
|
|
22
|
+
question: string;
|
|
23
|
+
/** Model override; null = the provider's default. */
|
|
24
|
+
model: string | null;
|
|
25
|
+
registeredBy: QuestionRegisteredBy;
|
|
26
|
+
status: QuestionStatus;
|
|
27
|
+
/** Short failure reason (never the prompt or the data). Null unless failed. */
|
|
28
|
+
error: string | null;
|
|
29
|
+
createdAt: string;
|
|
30
|
+
updatedAt: string;
|
|
31
|
+
lastComputedAt: string | null;
|
|
32
|
+
/** Local index version of the derived record the last compute wrote. */
|
|
33
|
+
derivedVersion: number | null;
|
|
34
|
+
derivedCollectedAt: string | null;
|
|
35
|
+
}
|
|
36
|
+
export type QuestionRegistrationPatch = Partial<Pick<QuestionRegistration, "status" | "error" | "updatedAt" | "lastComputedAt" | "derivedVersion" | "derivedCollectedAt">>;
|
|
37
|
+
export interface QuestionStoreListFilter {
|
|
38
|
+
derivedScope?: string;
|
|
39
|
+
sourceScope?: string;
|
|
40
|
+
builder?: `0x${string}`;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Persistence for question registrations. Small and local: registrations
|
|
44
|
+
* never sync (the replica that holds them computes them). Implementations:
|
|
45
|
+
* sqlite (server), a state-store backed map (PS-Lite), in-memory (tests).
|
|
46
|
+
*/
|
|
47
|
+
export interface QuestionStore {
|
|
48
|
+
list(filter?: QuestionStoreListFilter): Promise<QuestionRegistration[]>;
|
|
49
|
+
get(questionId: string): Promise<QuestionRegistration | null>;
|
|
50
|
+
insert(registration: QuestionRegistration): Promise<void>;
|
|
51
|
+
/** Returns the updated row, or null when the id is unknown. */
|
|
52
|
+
update(questionId: string, patch: QuestionRegistrationPatch): Promise<QuestionRegistration | null>;
|
|
53
|
+
delete(questionId: string): Promise<boolean>;
|
|
54
|
+
}
|
|
55
|
+
/** Public JSON shape of a registration (GET / list / POST responses). */
|
|
56
|
+
export interface QuestionRegistrationView {
|
|
57
|
+
questionId: string;
|
|
58
|
+
derivedScope: string;
|
|
59
|
+
sourceScopes: string[];
|
|
60
|
+
question: string;
|
|
61
|
+
model: string | null;
|
|
62
|
+
registeredBy: QuestionRegisteredBy;
|
|
63
|
+
status: QuestionStatus;
|
|
64
|
+
error: string | null;
|
|
65
|
+
createdAt: string;
|
|
66
|
+
updatedAt: string;
|
|
67
|
+
lastComputedAt: string | null;
|
|
68
|
+
derivedVersion: number | null;
|
|
69
|
+
derivedCollectedAt: string | null;
|
|
70
|
+
}
|
|
71
|
+
export declare function questionRegistrationView(registration: QuestionRegistration): QuestionRegistrationView;
|
|
72
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/derivatives/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtE,0EAA0E;AAC1E,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,oBAAoB,CAAC;IACnC,MAAM,EAAE,cAAc,CAAC;IACvB,+EAA+E;IAC/E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,wEAAwE;IACxE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAC7C,IAAI,CACF,oBAAoB,EAClB,QAAQ,GACR,OAAO,GACP,WAAW,GACX,gBAAgB,GAChB,gBAAgB,GAChB,oBAAoB,CACvB,CACF,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,MAAM,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACxE,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,YAAY,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,+DAA+D;IAC/D,MAAM,CACJ,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IACxC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9C;AAED,yEAAyE;AACzE,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,oBAAoB,CAAC;IACnC,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,oBAAoB,GACjC,wBAAwB,CAgB1B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derivative compute layer: a builder registers a QUESTION over the owner's
|
|
3
|
+
* source scopes; the Personal Server answers it locally with an inference
|
|
4
|
+
* provider and writes the answer as an ordinary derivative record (lineage
|
|
5
|
+
* = the source data points) into the derived scope. See
|
|
6
|
+
* docs/derivative-data-api.md, "Compute (question to derivative)".
|
|
7
|
+
*/
|
|
8
|
+
export function questionRegistrationView(registration) {
|
|
9
|
+
return {
|
|
10
|
+
questionId: registration.questionId,
|
|
11
|
+
derivedScope: registration.derivedScope,
|
|
12
|
+
sourceScopes: [...registration.sourceScopes],
|
|
13
|
+
question: registration.question,
|
|
14
|
+
model: registration.model,
|
|
15
|
+
registeredBy: registration.registeredBy,
|
|
16
|
+
status: registration.status,
|
|
17
|
+
error: registration.error,
|
|
18
|
+
createdAt: registration.createdAt,
|
|
19
|
+
updatedAt: registration.updatedAt,
|
|
20
|
+
lastComputedAt: registration.lastComputedAt,
|
|
21
|
+
derivedVersion: registration.derivedVersion,
|
|
22
|
+
derivedCollectedAt: registration.derivedCollectedAt,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/derivatives/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiFH,MAAM,UAAU,wBAAwB,CACtC,YAAkC;IAElC,OAAO;QACL,UAAU,EAAE,YAAY,CAAC,UAAU;QACnC,YAAY,EAAE,YAAY,CAAC,YAAY;QACvC,YAAY,EAAE,CAAC,GAAG,YAAY,CAAC,YAAY,CAAC;QAC5C,QAAQ,EAAE,YAAY,CAAC,QAAQ;QAC/B,KAAK,EAAE,YAAY,CAAC,KAAK;QACzB,YAAY,EAAE,YAAY,CAAC,YAAY;QACvC,MAAM,EAAE,YAAY,CAAC,MAAM;QAC3B,KAAK,EAAE,YAAY,CAAC,KAAK;QACzB,SAAS,EAAE,YAAY,CAAC,SAAS;QACjC,SAAS,EAAE,YAAY,CAAC,SAAS;QACjC,cAAc,EAAE,YAAY,CAAC,cAAc;QAC3C,cAAc,EAAE,YAAY,CAAC,cAAc;QAC3C,kBAAkB,EAAE,YAAY,CAAC,kBAAkB;KACpD,CAAC;AACJ,CAAC"}
|
package/dist/errors/catalog.d.ts
CHANGED
|
@@ -90,4 +90,24 @@ export declare class DeleteTombstoneFailedError extends ProtocolError {
|
|
|
90
90
|
export declare class DataDeletedError extends ProtocolError {
|
|
91
91
|
constructor(details?: Record<string, unknown>);
|
|
92
92
|
}
|
|
93
|
+
export declare class DerivativeQuestionInvalidError extends ProtocolError {
|
|
94
|
+
constructor(message: string, details?: Record<string, unknown>);
|
|
95
|
+
}
|
|
96
|
+
export declare class DerivativeQuestionNotFoundError extends ProtocolError {
|
|
97
|
+
constructor(details?: Record<string, unknown>);
|
|
98
|
+
}
|
|
99
|
+
export declare class DerivativeCycleError extends ProtocolError {
|
|
100
|
+
constructor(details: {
|
|
101
|
+
derivedScope: string;
|
|
102
|
+
path: string[];
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
export declare class DerivativeSourceNotGrantedError extends ProtocolError {
|
|
106
|
+
constructor(details: {
|
|
107
|
+
scopes: string[];
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
export declare class DerivativeComputeUnavailableError extends ProtocolError {
|
|
111
|
+
constructor(details?: Record<string, unknown>);
|
|
112
|
+
}
|
|
93
113
|
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/errors/catalog.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/errors/catalog.ts"],"names":[],"mappings":"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"}
|