@opendatalabs/personal-server-ts-server 1.14.0 → 1.15.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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"question-store.d.ts","sourceRoot":"","sources":["../../src/storage/question-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"question-store.d.ts","sourceRoot":"","sources":["../../src/storage/question-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAML,KAAK,aAAa,EACnB,MAAM,mDAAmD,CAAC;AAkG3D,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GACpB,aAAa,CAwGf"}
|
|
@@ -11,6 +11,7 @@ CREATE TABLE IF NOT EXISTS derivative_questions (
|
|
|
11
11
|
source_scopes TEXT NOT NULL,
|
|
12
12
|
question TEXT NOT NULL,
|
|
13
13
|
model TEXT,
|
|
14
|
+
answer_shape TEXT,
|
|
14
15
|
recompute TEXT NOT NULL DEFAULT 'on-change',
|
|
15
16
|
registered_by TEXT NOT NULL,
|
|
16
17
|
status TEXT NOT NULL,
|
|
@@ -35,6 +36,19 @@ function ensureErrorCodeColumn(db) {
|
|
|
35
36
|
return;
|
|
36
37
|
db.exec("ALTER TABLE derivative_questions ADD COLUMN error_code TEXT");
|
|
37
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Same in-place migration for the declared answer shape (stored as its
|
|
41
|
+
* JSON): rows written before it existed read back as null, which is the
|
|
42
|
+
* free-text answer the question was registered with.
|
|
43
|
+
*/
|
|
44
|
+
function ensureAnswerShapeColumn(db) {
|
|
45
|
+
const columns = db
|
|
46
|
+
.prepare("PRAGMA table_info(derivative_questions)")
|
|
47
|
+
.all();
|
|
48
|
+
if (columns.some((column) => column.name === "answer_shape"))
|
|
49
|
+
return;
|
|
50
|
+
db.exec("ALTER TABLE derivative_questions ADD COLUMN answer_shape TEXT");
|
|
51
|
+
}
|
|
38
52
|
const CREATE_INDEX_SQL = "CREATE INDEX IF NOT EXISTS idx_derivative_questions_derived_scope ON derivative_questions (derived_scope)";
|
|
39
53
|
// Databases created before the recompute policy existed migrate in place;
|
|
40
54
|
// their registrations keep the old follow-every-change behavior.
|
|
@@ -46,6 +60,9 @@ function toRegistration(row) {
|
|
|
46
60
|
sourceScopes: JSON.parse(row.source_scopes),
|
|
47
61
|
question: row.question,
|
|
48
62
|
model: row.model,
|
|
63
|
+
answerShape: row.answer_shape
|
|
64
|
+
? JSON.parse(row.answer_shape)
|
|
65
|
+
: null,
|
|
49
66
|
recompute: row.recompute,
|
|
50
67
|
registeredBy: JSON.parse(row.registered_by),
|
|
51
68
|
status: row.status,
|
|
@@ -61,6 +78,7 @@ function toRegistration(row) {
|
|
|
61
78
|
export function createSqliteQuestionStore(db) {
|
|
62
79
|
db.exec(CREATE_TABLE_SQL);
|
|
63
80
|
ensureErrorCodeColumn(db);
|
|
81
|
+
ensureAnswerShapeColumn(db);
|
|
64
82
|
db.exec(CREATE_INDEX_SQL);
|
|
65
83
|
const columns = db
|
|
66
84
|
.prepare("PRAGMA table_info(derivative_questions)")
|
|
@@ -75,12 +93,13 @@ export function createSqliteQuestionStore(db) {
|
|
|
75
93
|
const getOne = db.prepare("SELECT * FROM derivative_questions WHERE question_id = ?");
|
|
76
94
|
const insertOne = db.prepare(`
|
|
77
95
|
INSERT INTO derivative_questions (
|
|
78
|
-
question_id, derived_scope, source_scopes, question, model,
|
|
79
|
-
registered_by, status, error, error_code, created_at, updated_at,
|
|
96
|
+
question_id, derived_scope, source_scopes, question, model, answer_shape,
|
|
97
|
+
recompute, registered_by, status, error, error_code, created_at, updated_at,
|
|
80
98
|
last_computed_at, derived_version, derived_collected_at
|
|
81
99
|
) VALUES (
|
|
82
100
|
@question_id, @derived_scope, @source_scopes, @question, @model,
|
|
83
|
-
@recompute, @registered_by, @status, @error, @error_code,
|
|
101
|
+
@answer_shape, @recompute, @registered_by, @status, @error, @error_code,
|
|
102
|
+
@created_at, @updated_at,
|
|
84
103
|
@last_computed_at, @derived_version, @derived_collected_at
|
|
85
104
|
)`);
|
|
86
105
|
const updateOne = db.prepare(`
|
|
@@ -114,6 +133,9 @@ export function createSqliteQuestionStore(db) {
|
|
|
114
133
|
source_scopes: JSON.stringify(registration.sourceScopes),
|
|
115
134
|
question: registration.question,
|
|
116
135
|
model: registration.model,
|
|
136
|
+
answer_shape: registration.answerShape
|
|
137
|
+
? JSON.stringify(registration.answerShape)
|
|
138
|
+
: null,
|
|
117
139
|
recompute: registration.recompute,
|
|
118
140
|
registered_by: JSON.stringify(registration.registeredBy),
|
|
119
141
|
status: registration.status,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"question-store.js","sourceRoot":"","sources":["../../src/storage/question-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,qBAAqB,
|
|
1
|
+
{"version":3,"file":"question-store.js","sourceRoot":"","sources":["../../src/storage/question-store.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/ps-lite-debug.js
CHANGED
|
@@ -61644,8 +61644,8 @@ var require_multipleOf = __commonJS({
|
|
|
61644
61644
|
const { gen: gen2, data, schemaCode, it: it3 } = cxt;
|
|
61645
61645
|
const prec = it3.opts.multipleOfPrecision;
|
|
61646
61646
|
const res = gen2.let("res");
|
|
61647
|
-
const
|
|
61648
|
-
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${
|
|
61647
|
+
const invalid2 = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
|
|
61648
|
+
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid2}))`);
|
|
61649
61649
|
}
|
|
61650
61650
|
};
|
|
61651
61651
|
exports.default = def;
|
|
@@ -67542,8 +67542,8 @@ var require_multipleOf2 = __commonJS({
|
|
|
67542
67542
|
const { gen: gen2, data, schemaCode, it: it3 } = cxt;
|
|
67543
67543
|
const prec = it3.opts.multipleOfPrecision;
|
|
67544
67544
|
const res = gen2.let("res");
|
|
67545
|
-
const
|
|
67546
|
-
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${
|
|
67545
|
+
const invalid2 = prec ? (0, codegen_1._)`Math.abs(Math.round(${res}) - ${res}) > 1e-${prec}` : (0, codegen_1._)`${res} !== parseInt(${res})`;
|
|
67546
|
+
cxt.fail$data((0, codegen_1._)`(${schemaCode} === 0 || (${res} = ${data}/${schemaCode}, ${invalid2}))`);
|
|
67547
67547
|
}
|
|
67548
67548
|
};
|
|
67549
67549
|
exports.default = def;
|
|
@@ -114031,6 +114031,258 @@ async function loadOrCreatePsLiteServerIdentity(params) {
|
|
|
114031
114031
|
return { persisted, account };
|
|
114032
114032
|
}
|
|
114033
114033
|
|
|
114034
|
+
// ../core/dist/derivatives/answer-shape.js
|
|
114035
|
+
var MAX_ANSWER_SHAPE_FIELDS = 16;
|
|
114036
|
+
var MAX_ANSWER_FIELD_NAME_CHARS = 64;
|
|
114037
|
+
var MAX_ANSWER_STRING_CHARS = 4e3;
|
|
114038
|
+
var MAX_ANSWER_ENUM_VALUES = 32;
|
|
114039
|
+
var MAX_ANSWER_ENUM_VALUE_CHARS = 64;
|
|
114040
|
+
var FIELD_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
114041
|
+
var FIELD_TYPES = [
|
|
114042
|
+
"string",
|
|
114043
|
+
"number",
|
|
114044
|
+
"integer",
|
|
114045
|
+
"boolean",
|
|
114046
|
+
"enum"
|
|
114047
|
+
];
|
|
114048
|
+
var KEYS_BY_TYPE = {
|
|
114049
|
+
string: ["name", "type", "required", "maxLength"],
|
|
114050
|
+
number: ["name", "type", "required", "min", "max"],
|
|
114051
|
+
integer: ["name", "type", "required", "min", "max"],
|
|
114052
|
+
boolean: ["name", "type", "required"],
|
|
114053
|
+
enum: ["name", "type", "required", "values"]
|
|
114054
|
+
};
|
|
114055
|
+
function isRecord4(value) {
|
|
114056
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
114057
|
+
}
|
|
114058
|
+
function invalid(message, details) {
|
|
114059
|
+
throw new DerivativeQuestionInvalidError(message, {
|
|
114060
|
+
field: "answerShape",
|
|
114061
|
+
...details
|
|
114062
|
+
});
|
|
114063
|
+
}
|
|
114064
|
+
function parseFieldName(value, index) {
|
|
114065
|
+
if (typeof value !== "string" || value === "") {
|
|
114066
|
+
invalid(`answerShape.fields[${index}].name must be a non-empty string`, {
|
|
114067
|
+
index
|
|
114068
|
+
});
|
|
114069
|
+
}
|
|
114070
|
+
if (value.length > MAX_ANSWER_FIELD_NAME_CHARS) {
|
|
114071
|
+
invalid(`answerShape.fields[${index}].name is ${value.length} characters; the maximum is ${MAX_ANSWER_FIELD_NAME_CHARS}`, { index, max: MAX_ANSWER_FIELD_NAME_CHARS });
|
|
114072
|
+
}
|
|
114073
|
+
if (!FIELD_NAME.test(value)) {
|
|
114074
|
+
invalid(`answerShape.fields[${index}].name must start with a letter and hold only letters, digits and underscores`, { index });
|
|
114075
|
+
}
|
|
114076
|
+
return value;
|
|
114077
|
+
}
|
|
114078
|
+
function parseBound(value, index, key, integer2) {
|
|
114079
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
114080
|
+
invalid(`answerShape.fields[${index}].${key} must be a finite number`, {
|
|
114081
|
+
index,
|
|
114082
|
+
key
|
|
114083
|
+
});
|
|
114084
|
+
}
|
|
114085
|
+
if (integer2 && !Number.isSafeInteger(value)) {
|
|
114086
|
+
invalid(`answerShape.fields[${index}].${key} must be a safe integer for an integer field`, { index, key });
|
|
114087
|
+
}
|
|
114088
|
+
return value;
|
|
114089
|
+
}
|
|
114090
|
+
function parseEnumValues(value, index) {
|
|
114091
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
114092
|
+
invalid(`answerShape.fields[${index}].values must be a non-empty array of strings`, { index });
|
|
114093
|
+
}
|
|
114094
|
+
if (value.length > MAX_ANSWER_ENUM_VALUES) {
|
|
114095
|
+
invalid(`answerShape.fields[${index}].values lists ${value.length} values; the maximum is ${MAX_ANSWER_ENUM_VALUES}`, { index, max: MAX_ANSWER_ENUM_VALUES });
|
|
114096
|
+
}
|
|
114097
|
+
const values = [];
|
|
114098
|
+
for (const entry of value) {
|
|
114099
|
+
if (typeof entry !== "string" || entry === "") {
|
|
114100
|
+
invalid(`answerShape.fields[${index}].values must hold non-empty strings`, { index });
|
|
114101
|
+
}
|
|
114102
|
+
if (entry.length > MAX_ANSWER_ENUM_VALUE_CHARS) {
|
|
114103
|
+
invalid(`answerShape.fields[${index}].values holds a ${entry.length} character value; the maximum is ${MAX_ANSWER_ENUM_VALUE_CHARS}`, { index, max: MAX_ANSWER_ENUM_VALUE_CHARS });
|
|
114104
|
+
}
|
|
114105
|
+
if (/[\n\r\t]/.test(entry)) {
|
|
114106
|
+
invalid(`answerShape.fields[${index}].values must not hold line breaks or tabs`, { index });
|
|
114107
|
+
}
|
|
114108
|
+
if (values.includes(entry)) {
|
|
114109
|
+
invalid(`answerShape.fields[${index}].values lists the same value twice`, { index });
|
|
114110
|
+
}
|
|
114111
|
+
values.push(entry);
|
|
114112
|
+
}
|
|
114113
|
+
return values;
|
|
114114
|
+
}
|
|
114115
|
+
function parseField(value, index) {
|
|
114116
|
+
if (!isRecord4(value)) {
|
|
114117
|
+
invalid(`answerShape.fields[${index}] must be an object`, { index });
|
|
114118
|
+
}
|
|
114119
|
+
const name = parseFieldName(value.name, index);
|
|
114120
|
+
if (typeof value.type !== "string" || !FIELD_TYPES.includes(value.type)) {
|
|
114121
|
+
invalid(`answerShape.fields[${index}].type must be one of ${FIELD_TYPES.join(", ")}`, { index });
|
|
114122
|
+
}
|
|
114123
|
+
const type = value.type;
|
|
114124
|
+
const allowed = KEYS_BY_TYPE[type];
|
|
114125
|
+
for (const key of Object.keys(value)) {
|
|
114126
|
+
if (!allowed.includes(key)) {
|
|
114127
|
+
invalid(`answerShape.fields[${index}] does not accept "${key}" on a ${type} field`, { index, key: key.slice(0, MAX_ANSWER_FIELD_NAME_CHARS) });
|
|
114128
|
+
}
|
|
114129
|
+
}
|
|
114130
|
+
let required2 = true;
|
|
114131
|
+
if (value.required !== void 0 && value.required !== null) {
|
|
114132
|
+
if (typeof value.required !== "boolean") {
|
|
114133
|
+
invalid(`answerShape.fields[${index}].required must be a boolean`, {
|
|
114134
|
+
index
|
|
114135
|
+
});
|
|
114136
|
+
}
|
|
114137
|
+
required2 = value.required;
|
|
114138
|
+
}
|
|
114139
|
+
const field = { name, type, required: required2 };
|
|
114140
|
+
if (type === "string") {
|
|
114141
|
+
let maxLength = MAX_ANSWER_STRING_CHARS;
|
|
114142
|
+
if (value.maxLength !== void 0 && value.maxLength !== null) {
|
|
114143
|
+
if (typeof value.maxLength !== "number" || !Number.isSafeInteger(value.maxLength) || value.maxLength < 1 || value.maxLength > MAX_ANSWER_STRING_CHARS) {
|
|
114144
|
+
invalid(`answerShape.fields[${index}].maxLength must be an integer between 1 and ${MAX_ANSWER_STRING_CHARS}`, { index, max: MAX_ANSWER_STRING_CHARS });
|
|
114145
|
+
}
|
|
114146
|
+
maxLength = value.maxLength;
|
|
114147
|
+
}
|
|
114148
|
+
field.maxLength = maxLength;
|
|
114149
|
+
}
|
|
114150
|
+
if (type === "number" || type === "integer") {
|
|
114151
|
+
const integer2 = type === "integer";
|
|
114152
|
+
if (value.min !== void 0 && value.min !== null) {
|
|
114153
|
+
field.min = parseBound(value.min, index, "min", integer2);
|
|
114154
|
+
}
|
|
114155
|
+
if (value.max !== void 0 && value.max !== null) {
|
|
114156
|
+
field.max = parseBound(value.max, index, "max", integer2);
|
|
114157
|
+
}
|
|
114158
|
+
if (field.min !== void 0 && field.max !== void 0 && field.min > field.max) {
|
|
114159
|
+
invalid(`answerShape.fields[${index}].min is greater than its max`, {
|
|
114160
|
+
index
|
|
114161
|
+
});
|
|
114162
|
+
}
|
|
114163
|
+
}
|
|
114164
|
+
if (type === "enum") {
|
|
114165
|
+
field.values = parseEnumValues(value.values, index);
|
|
114166
|
+
}
|
|
114167
|
+
return field;
|
|
114168
|
+
}
|
|
114169
|
+
function parseAnswerShapeInput(value) {
|
|
114170
|
+
if (value === void 0 || value === null)
|
|
114171
|
+
return null;
|
|
114172
|
+
if (!isRecord4(value)) {
|
|
114173
|
+
invalid("answerShape must be an object with a fields array", {});
|
|
114174
|
+
}
|
|
114175
|
+
for (const key of Object.keys(value)) {
|
|
114176
|
+
if (key !== "fields") {
|
|
114177
|
+
invalid(`answerShape does not accept "${key}"`, {
|
|
114178
|
+
key: key.slice(0, MAX_ANSWER_FIELD_NAME_CHARS)
|
|
114179
|
+
});
|
|
114180
|
+
}
|
|
114181
|
+
}
|
|
114182
|
+
if (!Array.isArray(value.fields) || value.fields.length === 0) {
|
|
114183
|
+
invalid("answerShape.fields must be a non-empty array", {});
|
|
114184
|
+
}
|
|
114185
|
+
if (value.fields.length > MAX_ANSWER_SHAPE_FIELDS) {
|
|
114186
|
+
invalid(`answerShape.fields lists ${value.fields.length} fields; the maximum is ${MAX_ANSWER_SHAPE_FIELDS}`, { max: MAX_ANSWER_SHAPE_FIELDS });
|
|
114187
|
+
}
|
|
114188
|
+
const fields = [];
|
|
114189
|
+
const names = /* @__PURE__ */ new Set();
|
|
114190
|
+
value.fields.forEach((entry, index) => {
|
|
114191
|
+
const field = parseField(entry, index);
|
|
114192
|
+
if (names.has(field.name)) {
|
|
114193
|
+
invalid(`answerShape.fields names "${field.name}" twice`, { index });
|
|
114194
|
+
}
|
|
114195
|
+
names.add(field.name);
|
|
114196
|
+
fields.push(field);
|
|
114197
|
+
});
|
|
114198
|
+
return { fields };
|
|
114199
|
+
}
|
|
114200
|
+
function compileAnswerShape(shape) {
|
|
114201
|
+
const entries = {};
|
|
114202
|
+
for (const field of shape.fields) {
|
|
114203
|
+
let schema;
|
|
114204
|
+
switch (field.type) {
|
|
114205
|
+
case "string":
|
|
114206
|
+
schema = external_exports.string().max(field.maxLength ?? MAX_ANSWER_STRING_CHARS);
|
|
114207
|
+
break;
|
|
114208
|
+
case "number":
|
|
114209
|
+
case "integer": {
|
|
114210
|
+
let numeric = field.type === "integer" ? external_exports.int() : external_exports.number();
|
|
114211
|
+
if (field.min !== void 0)
|
|
114212
|
+
numeric = numeric.min(field.min);
|
|
114213
|
+
if (field.max !== void 0)
|
|
114214
|
+
numeric = numeric.max(field.max);
|
|
114215
|
+
schema = numeric;
|
|
114216
|
+
break;
|
|
114217
|
+
}
|
|
114218
|
+
case "boolean":
|
|
114219
|
+
schema = external_exports.boolean();
|
|
114220
|
+
break;
|
|
114221
|
+
case "enum":
|
|
114222
|
+
schema = external_exports.enum(field.values ?? []);
|
|
114223
|
+
break;
|
|
114224
|
+
}
|
|
114225
|
+
entries[field.name] = field.required ? schema : schema.nullish();
|
|
114226
|
+
}
|
|
114227
|
+
return external_exports.object(entries);
|
|
114228
|
+
}
|
|
114229
|
+
function validateAnswerShape(shape, compiled, candidate) {
|
|
114230
|
+
const parsed = compiled.safeParse(candidate);
|
|
114231
|
+
if (!parsed.success) {
|
|
114232
|
+
return {
|
|
114233
|
+
ok: false,
|
|
114234
|
+
// zod's messages state the constraint ("expected int", "<=5") and
|
|
114235
|
+
// never echo the received value, so they are safe to hand back to
|
|
114236
|
+
// the model in the corrective turn.
|
|
114237
|
+
issues: parsed.error.issues.map((issue2) => {
|
|
114238
|
+
const path = issue2.path.join(".");
|
|
114239
|
+
return path ? `${path}: ${issue2.message}` : issue2.message;
|
|
114240
|
+
})
|
|
114241
|
+
};
|
|
114242
|
+
}
|
|
114243
|
+
const value = {};
|
|
114244
|
+
for (const field of shape.fields) {
|
|
114245
|
+
const entry = parsed.data[field.name];
|
|
114246
|
+
if (entry === void 0 || entry === null)
|
|
114247
|
+
continue;
|
|
114248
|
+
value[field.name] = entry;
|
|
114249
|
+
}
|
|
114250
|
+
return { ok: true, value };
|
|
114251
|
+
}
|
|
114252
|
+
function describeField(field) {
|
|
114253
|
+
const requirement = field.required ? "required" : "optional";
|
|
114254
|
+
switch (field.type) {
|
|
114255
|
+
case "string":
|
|
114256
|
+
return `"${field.name}": string, at most ${field.maxLength ?? MAX_ANSWER_STRING_CHARS} characters (${requirement})`;
|
|
114257
|
+
case "number":
|
|
114258
|
+
case "integer": {
|
|
114259
|
+
const kind = field.type === "integer" ? "integer" : "number";
|
|
114260
|
+
const range = field.min !== void 0 && field.max !== void 0 ? ` between ${field.min} and ${field.max}` : field.min !== void 0 ? ` of at least ${field.min}` : field.max !== void 0 ? ` of at most ${field.max}` : "";
|
|
114261
|
+
return `"${field.name}": ${kind}${range} (${requirement})`;
|
|
114262
|
+
}
|
|
114263
|
+
case "boolean":
|
|
114264
|
+
return `"${field.name}": true or false (${requirement})`;
|
|
114265
|
+
case "enum":
|
|
114266
|
+
return `"${field.name}": exactly one of ${(field.values ?? []).map((entry) => JSON.stringify(entry)).join(", ")} (${requirement})`;
|
|
114267
|
+
}
|
|
114268
|
+
}
|
|
114269
|
+
function describeAnswerShape(shape) {
|
|
114270
|
+
return shape.fields.map((field) => ` ${describeField(field)}`);
|
|
114271
|
+
}
|
|
114272
|
+
function renderShapedAnswer(shape, value) {
|
|
114273
|
+
return shape.fields.filter((field) => value[field.name] !== void 0).map((field) => `${field.name}: ${String(value[field.name])}`).join("\n");
|
|
114274
|
+
}
|
|
114275
|
+
function cloneAnswerShape(shape) {
|
|
114276
|
+
if (!shape)
|
|
114277
|
+
return null;
|
|
114278
|
+
return {
|
|
114279
|
+
fields: shape.fields.map((field) => ({
|
|
114280
|
+
...field,
|
|
114281
|
+
...field.values ? { values: [...field.values] } : {}
|
|
114282
|
+
}))
|
|
114283
|
+
};
|
|
114284
|
+
}
|
|
114285
|
+
|
|
114034
114286
|
// ../core/dist/derivatives/types.js
|
|
114035
114287
|
function questionRegistrationView(registration) {
|
|
114036
114288
|
return {
|
|
@@ -114039,6 +114291,7 @@ function questionRegistrationView(registration) {
|
|
|
114039
114291
|
sourceScopes: [...registration.sourceScopes],
|
|
114040
114292
|
question: registration.question,
|
|
114041
114293
|
model: registration.model,
|
|
114294
|
+
answerShape: cloneAnswerShape(registration.answerShape),
|
|
114042
114295
|
recompute: registration.recompute,
|
|
114043
114296
|
registeredBy: registration.registeredBy,
|
|
114044
114297
|
status: registration.status,
|
|
@@ -114058,6 +114311,7 @@ function clone2(registration) {
|
|
|
114058
114311
|
...registration,
|
|
114059
114312
|
// Registrations persisted before the field existed load as null.
|
|
114060
114313
|
errorCode: registration.errorCode ?? null,
|
|
114314
|
+
answerShape: cloneAnswerShape(registration.answerShape ?? null),
|
|
114061
114315
|
sourceScopes: [...registration.sourceScopes],
|
|
114062
114316
|
registeredBy: { ...registration.registeredBy }
|
|
114063
114317
|
};
|
|
@@ -114128,7 +114382,7 @@ var MAX_QUESTION_CHARS = 8e3;
|
|
|
114128
114382
|
var MAX_MODEL_CHARS = 128;
|
|
114129
114383
|
var MAX_ECHOED_SCOPE_CHARS = 128;
|
|
114130
114384
|
var MODEL_ID = /^[A-Za-z0-9][A-Za-z0-9._:/-]*$/;
|
|
114131
|
-
function
|
|
114385
|
+
function isRecord5(value) {
|
|
114132
114386
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
114133
114387
|
}
|
|
114134
114388
|
function parseScope(value, field) {
|
|
@@ -114144,7 +114398,7 @@ function parseScope(value, field) {
|
|
|
114144
114398
|
return parsed.scope;
|
|
114145
114399
|
}
|
|
114146
114400
|
function parseQuestionInput(body) {
|
|
114147
|
-
if (!
|
|
114401
|
+
if (!isRecord5(body)) {
|
|
114148
114402
|
throw new DerivativeQuestionInvalidError("Body must be a JSON object");
|
|
114149
114403
|
}
|
|
114150
114404
|
const derivedScope = parseScope(body.derivedScope, "derivedScope");
|
|
@@ -114178,6 +114432,7 @@ function parseQuestionInput(body) {
|
|
|
114178
114432
|
}
|
|
114179
114433
|
model = body.model;
|
|
114180
114434
|
}
|
|
114435
|
+
const answerShape = parseAnswerShapeInput(body.answerShape);
|
|
114181
114436
|
let recompute = "on-change";
|
|
114182
114437
|
if (body.recompute !== void 0 && body.recompute !== null) {
|
|
114183
114438
|
if (body.recompute !== "snapshot" && body.recompute !== "on-change") {
|
|
@@ -114191,6 +114446,7 @@ function parseQuestionInput(body) {
|
|
|
114191
114446
|
sourceScopes,
|
|
114192
114447
|
question: body.question,
|
|
114193
114448
|
model,
|
|
114449
|
+
answerShape,
|
|
114194
114450
|
recompute
|
|
114195
114451
|
};
|
|
114196
114452
|
}
|
|
@@ -114240,6 +114496,7 @@ async function createQuestionRegistration(input) {
|
|
|
114240
114496
|
sourceScopes: parsed.sourceScopes,
|
|
114241
114497
|
question: parsed.question,
|
|
114242
114498
|
model: parsed.model,
|
|
114499
|
+
answerShape: parsed.answerShape,
|
|
114243
114500
|
recompute: parsed.recompute,
|
|
114244
114501
|
registeredBy: input.registeredBy,
|
|
114245
114502
|
status: "pending",
|
|
@@ -114277,11 +114534,11 @@ var TIMESTAMP_KEYS = [
|
|
|
114277
114534
|
"published_at"
|
|
114278
114535
|
];
|
|
114279
114536
|
var RESERVED_KEYS = /* @__PURE__ */ new Set(["$lineage", "$writtenBy", "$binary"]);
|
|
114280
|
-
function
|
|
114537
|
+
function isRecord6(value) {
|
|
114281
114538
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
114282
114539
|
}
|
|
114283
114540
|
function timestampOf(item) {
|
|
114284
|
-
if (!
|
|
114541
|
+
if (!isRecord6(item))
|
|
114285
114542
|
return null;
|
|
114286
114543
|
for (const key of TIMESTAMP_KEYS) {
|
|
114287
114544
|
const value = item[key];
|
|
@@ -114322,7 +114579,7 @@ function trimSourceData(data, options = {}) {
|
|
|
114322
114579
|
total = 0;
|
|
114323
114580
|
if (Array.isArray(data))
|
|
114324
114581
|
return trimArray(data, limit2);
|
|
114325
|
-
if (
|
|
114582
|
+
if (isRecord6(data)) {
|
|
114326
114583
|
const stamped = "$lineage" in data;
|
|
114327
114584
|
const out = {};
|
|
114328
114585
|
for (const [key, value] of Object.entries(data)) {
|
|
@@ -114354,13 +114611,28 @@ function trimSourceData(data, options = {}) {
|
|
|
114354
114611
|
}
|
|
114355
114612
|
return { data: result, kept, total, truncated: false };
|
|
114356
114613
|
}
|
|
114357
|
-
var
|
|
114614
|
+
var GROUNDING = [
|
|
114358
114615
|
"You answer a question about a person using ONLY the user data provided in the message.",
|
|
114359
|
-
"Do not use outside knowledge and do not guess; if the data does not support an answer, say so in the answer."
|
|
114616
|
+
"Do not use outside knowledge and do not guess; if the data does not support an answer, say so in the answer."
|
|
114617
|
+
];
|
|
114618
|
+
var SYSTEM_PROMPT = [
|
|
114619
|
+
...GROUNDING,
|
|
114360
114620
|
"Respond with a single JSON object and nothing else, with exactly these fields:",
|
|
114361
114621
|
' "answer": string, the answer to the question, written for the person the data belongs to;',
|
|
114362
114622
|
' "evidence": string, a short summary of which parts of the data support the answer.'
|
|
114363
114623
|
].join("\n");
|
|
114624
|
+
function shapedSystemPrompt(shape) {
|
|
114625
|
+
return [
|
|
114626
|
+
...GROUNDING,
|
|
114627
|
+
"Respond with a single JSON object and nothing else, with exactly these fields:",
|
|
114628
|
+
' "answer": object, holding exactly the fields listed below and no others;',
|
|
114629
|
+
' "evidence": string, a short summary of which parts of the data support the answer.',
|
|
114630
|
+
'The "answer" object holds:',
|
|
114631
|
+
...describeAnswerShape(shape),
|
|
114632
|
+
"Use the declared type for every field: a number field is a JSON number, not a string.",
|
|
114633
|
+
"Do not add fields, do not rename them and do not put prose outside them."
|
|
114634
|
+
].join("\n");
|
|
114635
|
+
}
|
|
114364
114636
|
function buildQuestionMessages(input) {
|
|
114365
114637
|
const sections = input.sources.map((source) => {
|
|
114366
114638
|
const note = source.total > source.kept ? ` (newest ${source.kept} of ${source.total} items)` : "";
|
|
@@ -114378,14 +114650,34 @@ function buildQuestionMessages(input) {
|
|
|
114378
114650
|
"## User data",
|
|
114379
114651
|
...sections,
|
|
114380
114652
|
"",
|
|
114381
|
-
"Answer the question as a JSON object with the fields answer and evidence."
|
|
114653
|
+
input.answerShape ? "Answer the question as a JSON object with the fields answer and evidence, where answer holds exactly the declared fields." : "Answer the question as a JSON object with the fields answer and evidence."
|
|
114382
114654
|
].join("\n");
|
|
114383
114655
|
return [
|
|
114384
|
-
{
|
|
114656
|
+
{
|
|
114657
|
+
role: "system",
|
|
114658
|
+
content: input.answerShape ? shapedSystemPrompt(input.answerShape) : SYSTEM_PROMPT
|
|
114659
|
+
},
|
|
114385
114660
|
{ role: "user", content: user }
|
|
114386
114661
|
];
|
|
114387
114662
|
}
|
|
114388
|
-
function
|
|
114663
|
+
function buildShapeRetryMessages(input) {
|
|
114664
|
+
return [
|
|
114665
|
+
...input.messages,
|
|
114666
|
+
{ role: "assistant", content: input.reply },
|
|
114667
|
+
{
|
|
114668
|
+
role: "user",
|
|
114669
|
+
content: [
|
|
114670
|
+
"That reply did not match the required answer shape:",
|
|
114671
|
+
...input.issues.map((issue2) => `- ${issue2}`),
|
|
114672
|
+
"",
|
|
114673
|
+
'Answer again as a single JSON object with the fields answer and evidence, where "answer" holds:',
|
|
114674
|
+
...describeAnswerShape(input.answerShape),
|
|
114675
|
+
"Return the JSON object and nothing else."
|
|
114676
|
+
].join("\n")
|
|
114677
|
+
}
|
|
114678
|
+
];
|
|
114679
|
+
}
|
|
114680
|
+
function jsonFramings(content) {
|
|
114389
114681
|
const candidates = [content.trim()];
|
|
114390
114682
|
const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(content);
|
|
114391
114683
|
if (fenced?.[1])
|
|
@@ -114395,10 +114687,13 @@ function parseAnswer(content) {
|
|
|
114395
114687
|
if (first !== -1 && last2 > first) {
|
|
114396
114688
|
candidates.push(content.slice(first, last2 + 1));
|
|
114397
114689
|
}
|
|
114398
|
-
|
|
114690
|
+
return [...new Set(candidates)];
|
|
114691
|
+
}
|
|
114692
|
+
function parseAnswer(content) {
|
|
114693
|
+
for (const candidate of jsonFramings(content)) {
|
|
114399
114694
|
try {
|
|
114400
114695
|
const parsed = JSON.parse(candidate);
|
|
114401
|
-
if (
|
|
114696
|
+
if (isRecord6(parsed) && typeof parsed.answer === "string") {
|
|
114402
114697
|
return {
|
|
114403
114698
|
answer: parsed.answer,
|
|
114404
114699
|
evidence: typeof parsed.evidence === "string" ? parsed.evidence : null
|
|
@@ -114409,6 +114704,25 @@ function parseAnswer(content) {
|
|
|
114409
114704
|
}
|
|
114410
114705
|
return { answer: content.trim(), evidence: null };
|
|
114411
114706
|
}
|
|
114707
|
+
function parseShapedAnswer(content) {
|
|
114708
|
+
const found = [];
|
|
114709
|
+
for (const candidate of jsonFramings(content)) {
|
|
114710
|
+
let parsed;
|
|
114711
|
+
try {
|
|
114712
|
+
parsed = JSON.parse(candidate);
|
|
114713
|
+
} catch {
|
|
114714
|
+
continue;
|
|
114715
|
+
}
|
|
114716
|
+
if (!isRecord6(parsed))
|
|
114717
|
+
continue;
|
|
114718
|
+
const evidence = typeof parsed.evidence === "string" ? parsed.evidence : null;
|
|
114719
|
+
if (isRecord6(parsed.answer)) {
|
|
114720
|
+
found.push({ answer: parsed.answer, evidence });
|
|
114721
|
+
}
|
|
114722
|
+
found.push({ answer: parsed, evidence });
|
|
114723
|
+
}
|
|
114724
|
+
return found;
|
|
114725
|
+
}
|
|
114412
114726
|
|
|
114413
114727
|
// ../core/dist/derivatives/inference.js
|
|
114414
114728
|
var DEFAULT_INFERENCE_BASE_URL = "https://inference.phala.com/v1";
|
|
@@ -114435,11 +114749,11 @@ var InferenceRequestError = class extends Error {
|
|
|
114435
114749
|
this.retryable = options.retryable;
|
|
114436
114750
|
}
|
|
114437
114751
|
};
|
|
114438
|
-
function
|
|
114752
|
+
function isRecord7(value) {
|
|
114439
114753
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
114440
114754
|
}
|
|
114441
114755
|
function readUsage(value) {
|
|
114442
|
-
if (!
|
|
114756
|
+
if (!isRecord7(value))
|
|
114443
114757
|
return void 0;
|
|
114444
114758
|
const num2 = (v10) => typeof v10 === "number" ? v10 : void 0;
|
|
114445
114759
|
const usage = {
|
|
@@ -114450,10 +114764,10 @@ function readUsage(value) {
|
|
|
114450
114764
|
return usage;
|
|
114451
114765
|
}
|
|
114452
114766
|
function readContent(body) {
|
|
114453
|
-
if (!
|
|
114767
|
+
if (!isRecord7(body) || !Array.isArray(body.choices))
|
|
114454
114768
|
return null;
|
|
114455
114769
|
const first = body.choices[0];
|
|
114456
|
-
if (!
|
|
114770
|
+
if (!isRecord7(first) || !isRecord7(first.message))
|
|
114457
114771
|
return null;
|
|
114458
114772
|
const index = typeof first.index === "number" ? first.index : 0;
|
|
114459
114773
|
const field = `choices.${index}.message.content`;
|
|
@@ -114462,7 +114776,7 @@ function readContent(body) {
|
|
|
114462
114776
|
if (typeof content === "string")
|
|
114463
114777
|
return { content, field, id: id2 };
|
|
114464
114778
|
if (Array.isArray(content)) {
|
|
114465
|
-
const text = content.map((part) =>
|
|
114779
|
+
const text = content.map((part) => isRecord7(part) && typeof part.text === "string" ? part.text : "").join("");
|
|
114466
114780
|
return { content: text, field, id: id2 };
|
|
114467
114781
|
}
|
|
114468
114782
|
return null;
|
|
@@ -114470,7 +114784,7 @@ function readContent(body) {
|
|
|
114470
114784
|
async function readErrorType(response) {
|
|
114471
114785
|
try {
|
|
114472
114786
|
const body = await response.json();
|
|
114473
|
-
if (
|
|
114787
|
+
if (isRecord7(body) && isRecord7(body.error)) {
|
|
114474
114788
|
return typeof body.error.type === "string" ? body.error.type : null;
|
|
114475
114789
|
}
|
|
114476
114790
|
} catch {
|
|
@@ -114578,7 +114892,7 @@ function createOpenAiCompatibleInferenceProvider(options = {}) {
|
|
|
114578
114892
|
ok: true,
|
|
114579
114893
|
result: {
|
|
114580
114894
|
content,
|
|
114581
|
-
usage: readUsage(
|
|
114895
|
+
usage: readUsage(isRecord7(parsed) ? parsed.usage : void 0),
|
|
114582
114896
|
...receiptId ? { receiptId } : {},
|
|
114583
114897
|
...aciIdentity ? { aciIdentity } : {}
|
|
114584
114898
|
}
|
|
@@ -114651,6 +114965,53 @@ function shortError(err2) {
|
|
|
114651
114965
|
return `${err2.errorCode}: ${err2.message}`;
|
|
114652
114966
|
return `compute failed (${err2 instanceof Error ? err2.name : "Error"})`;
|
|
114653
114967
|
}
|
|
114968
|
+
async function produceAnswer(deps, registration, model, messages) {
|
|
114969
|
+
const ask = (turns2) => withRetries(deps, () => deps.provider.chat({
|
|
114970
|
+
model,
|
|
114971
|
+
messages: turns2,
|
|
114972
|
+
maxTokens: deps.maxTokens
|
|
114973
|
+
}), isRetryableInferenceError);
|
|
114974
|
+
const shape = registration.answerShape;
|
|
114975
|
+
if (!shape) {
|
|
114976
|
+
const reply = await ask(messages);
|
|
114977
|
+
const parsed = parseAnswer(reply.content);
|
|
114978
|
+
return {
|
|
114979
|
+
reply,
|
|
114980
|
+
answer: parsed.answer,
|
|
114981
|
+
evidence: parsed.evidence,
|
|
114982
|
+
answerData: null
|
|
114983
|
+
};
|
|
114984
|
+
}
|
|
114985
|
+
const compiled = compileAnswerShape(shape);
|
|
114986
|
+
let turns = messages;
|
|
114987
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
114988
|
+
const reply = await ask(turns);
|
|
114989
|
+
const candidates = parseShapedAnswer(reply.content);
|
|
114990
|
+
let issues = ["the reply was not a JSON object"];
|
|
114991
|
+
for (const [index, candidate] of candidates.entries()) {
|
|
114992
|
+
const checked = validateAnswerShape(shape, compiled, candidate.answer);
|
|
114993
|
+
if (checked.ok) {
|
|
114994
|
+
return {
|
|
114995
|
+
reply,
|
|
114996
|
+
answer: renderShapedAnswer(shape, checked.value),
|
|
114997
|
+
evidence: candidate.evidence,
|
|
114998
|
+
answerData: checked.value
|
|
114999
|
+
};
|
|
115000
|
+
}
|
|
115001
|
+
if (index === 0)
|
|
115002
|
+
issues = checked.issues;
|
|
115003
|
+
}
|
|
115004
|
+
if (attempt >= 1)
|
|
115005
|
+
break;
|
|
115006
|
+
turns = buildShapeRetryMessages({
|
|
115007
|
+
messages,
|
|
115008
|
+
reply: reply.content,
|
|
115009
|
+
issues,
|
|
115010
|
+
answerShape: shape
|
|
115011
|
+
});
|
|
115012
|
+
}
|
|
115013
|
+
throw new ComputeFailure(`answer did not match the declared shape (fields: ${shape.fields.map((field) => field.name).join(", ")})`, "internal");
|
|
115014
|
+
}
|
|
114654
115015
|
function collectedAtStamp(now, isTaken) {
|
|
114655
115016
|
const base = now();
|
|
114656
115017
|
base.setUTCMilliseconds(0);
|
|
@@ -114811,18 +115172,20 @@ async function computeQuestion(questionId, deps) {
|
|
|
114811
115172
|
await assertNoLineageCycle(deps, registration, serverOwner, sourceLineage);
|
|
114812
115173
|
const messages = buildQuestionMessages({
|
|
114813
115174
|
question: registration.question,
|
|
114814
|
-
sources
|
|
115175
|
+
sources,
|
|
115176
|
+
answerShape: registration.answerShape
|
|
114815
115177
|
});
|
|
114816
115178
|
const model = registration.model ?? deps.provider.defaultModel;
|
|
114817
|
-
const
|
|
114818
|
-
const
|
|
115179
|
+
const produced = await produceAnswer(deps, registration, model, messages);
|
|
115180
|
+
const reply = produced.reply;
|
|
114819
115181
|
const computedAt = now().toISOString();
|
|
114820
115182
|
const lineageIds = registration.sourceScopes.map((scope) => computeDataPointId(serverOwner, scope));
|
|
114821
115183
|
const record2 = {
|
|
114822
115184
|
questionId: registration.questionId,
|
|
114823
115185
|
question: registration.question,
|
|
114824
|
-
answer:
|
|
114825
|
-
|
|
115186
|
+
answer: produced.answer,
|
|
115187
|
+
...produced.answerData ? { answerData: produced.answerData } : {},
|
|
115188
|
+
evidence: produced.evidence,
|
|
114826
115189
|
model,
|
|
114827
115190
|
computedAt,
|
|
114828
115191
|
sources: sources.map((source) => ({
|
|
@@ -115583,7 +115946,7 @@ var E2eeAttestationError = class extends Error {
|
|
|
115583
115946
|
this.name = "E2eeAttestationError";
|
|
115584
115947
|
}
|
|
115585
115948
|
};
|
|
115586
|
-
function
|
|
115949
|
+
function isRecord8(value) {
|
|
115587
115950
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
115588
115951
|
}
|
|
115589
115952
|
async function sha256Hex2(bytes2) {
|
|
@@ -115601,7 +115964,7 @@ async function reportDataFor(keysetDigest, nonce) {
|
|
|
115601
115964
|
return sha256Hex2(new TextEncoder().encode(statement));
|
|
115602
115965
|
}
|
|
115603
115966
|
function parseReport(body) {
|
|
115604
|
-
if (!
|
|
115967
|
+
if (!isRecord8(body) || typeof body.api_version !== "string" || typeof body.workload_keyset_digest !== "string" || !isRecord8(body.attestation) || typeof body.attestation.tee_type !== "string" || typeof body.attestation.report_data !== "string" || !isRecord8(body.attestation.workload_keyset)) {
|
|
115605
115968
|
throw new E2eeAttestationError("malformed_report", "attestation report is missing required fields");
|
|
115606
115969
|
}
|
|
115607
115970
|
const keyset = body.attestation.workload_keyset;
|
|
@@ -115648,7 +116011,7 @@ async function verifyAciReportBinding(report, nonce, nowSeconds) {
|
|
|
115648
116011
|
}
|
|
115649
116012
|
function selectX25519Key(keyset, expectedKeyId) {
|
|
115650
116013
|
for (const entry of keyset.e2ee_public_keys) {
|
|
115651
|
-
if (!
|
|
116014
|
+
if (!isRecord8(entry) || entry.algo !== E2EE_ALGO_X25519)
|
|
115652
116015
|
continue;
|
|
115653
116016
|
if (typeof entry.public_key !== "string")
|
|
115654
116017
|
continue;
|
|
@@ -133246,7 +133609,8 @@ async function createPsLiteQuestionStore(stateStore) {
|
|
|
133246
133609
|
const saved = await stateStore.get(QUESTIONS_KEY);
|
|
133247
133610
|
const initial = (saved?.version === 1 ? saved.questions : []).map((question) => ({
|
|
133248
133611
|
...question,
|
|
133249
|
-
recompute: question.recompute ?? "on-change"
|
|
133612
|
+
recompute: question.recompute ?? "on-change",
|
|
133613
|
+
answerShape: question.answerShape ?? null
|
|
133250
133614
|
}));
|
|
133251
133615
|
return createInMemoryQuestionStore({
|
|
133252
133616
|
initial,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendatalabs/personal-server-ts-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "Hono HTTP server for the Vana Personal Server — routes, middleware, composition root",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@hono/node-server": "^1.19.13",
|
|
47
|
-
"@opendatalabs/personal-server-ts-core": "1.
|
|
48
|
-
"@opendatalabs/personal-server-ts-lite": "1.
|
|
47
|
+
"@opendatalabs/personal-server-ts-core": "1.15.0",
|
|
48
|
+
"@opendatalabs/personal-server-ts-lite": "1.15.0",
|
|
49
49
|
"@opendatalabs/vana-sdk": "3.14.0",
|
|
50
50
|
"better-sqlite3": "^12.11.1",
|
|
51
51
|
"hono": "^4.12.27",
|