@productbrain/mcp 0.0.1-beta.6496 → 0.0.1-beta.6499
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.
|
@@ -1000,22 +1000,6 @@ async function captureVersionOrPreview(preview, params) {
|
|
|
1000
1000
|
return preview ? buildVersionPreviewResult(params.groundingEntry, params.name) : runVersionCapture(params);
|
|
1001
1001
|
}
|
|
1002
1002
|
|
|
1003
|
-
// src/lib/fieldTypes.ts
|
|
1004
|
-
var FIELD_TYPE_DEFAULTS = {
|
|
1005
|
-
"string": "",
|
|
1006
|
-
"text": "",
|
|
1007
|
-
"rich-text": "",
|
|
1008
|
-
"number": null,
|
|
1009
|
-
"boolean": false,
|
|
1010
|
-
"select": null,
|
|
1011
|
-
"multi-select": [],
|
|
1012
|
-
"array": [],
|
|
1013
|
-
"json": null,
|
|
1014
|
-
"date": null,
|
|
1015
|
-
"person": null,
|
|
1016
|
-
"role": null
|
|
1017
|
-
};
|
|
1018
|
-
|
|
1019
1003
|
// src/lib/formatFieldGuidance.ts
|
|
1020
1004
|
function formatFieldGuidance(fields) {
|
|
1021
1005
|
const guidedFields = fields.filter((f) => f.writingGuidance);
|
|
@@ -1151,6 +1135,49 @@ function tokenizeText(input) {
|
|
|
1151
1135
|
}
|
|
1152
1136
|
|
|
1153
1137
|
// src/lib/entryDataNormalization.ts
|
|
1138
|
+
function buildDataFromFields(fields, descriptionField, descriptionValue) {
|
|
1139
|
+
if (!descriptionField) return null;
|
|
1140
|
+
const data = {};
|
|
1141
|
+
for (const field of fields) {
|
|
1142
|
+
if (field.key === descriptionField) {
|
|
1143
|
+
data[field.key] = descriptionValue;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
return data;
|
|
1147
|
+
}
|
|
1148
|
+
function resolveDescriptionField(fields, descriptionFieldKey) {
|
|
1149
|
+
const verifiedDescriptionFieldKey = descriptionFieldKey && fields.some((field) => field.key === descriptionFieldKey) ? descriptionFieldKey : void 0;
|
|
1150
|
+
const literalDescriptionField = fields.find(
|
|
1151
|
+
(field) => field.key === "description" && (field.type === "text" || field.type === "string")
|
|
1152
|
+
)?.key;
|
|
1153
|
+
const layoutDescriptionField = fields.find(
|
|
1154
|
+
(field) => field.zone === "body" || field.displayHint === "textarea" || field.displayHint === "section"
|
|
1155
|
+
)?.key;
|
|
1156
|
+
const freeTextCandidates = fields.filter((field) => field.zone !== "meta" && field.zone !== "header");
|
|
1157
|
+
const firstTextField = freeTextCandidates.find((field) => field.type === "text")?.key;
|
|
1158
|
+
const firstStringField = freeTextCandidates.find((field) => field.type === "string")?.key;
|
|
1159
|
+
return verifiedDescriptionFieldKey || literalDescriptionField || layoutDescriptionField || firstTextField || firstStringField || null;
|
|
1160
|
+
}
|
|
1161
|
+
function noDescriptionFieldMessage(collectionSlug) {
|
|
1162
|
+
return `\`${collectionSlug}\` has no field for captured free text \u2014 no descriptionFieldKey is declared, no layout body field, and no text/string field outside its meta/header zone. Ask a platform admin to declare a descriptionFieldKey (or a body-zoned text field) on this collection before capturing into it.`;
|
|
1163
|
+
}
|
|
1164
|
+
function resolveProfileDescriptionField(col, fieldsOverride) {
|
|
1165
|
+
const fields = fieldsOverride ?? col.fields ?? [];
|
|
1166
|
+
return resolveDescriptionField(fields, col.descriptionFieldKey);
|
|
1167
|
+
}
|
|
1168
|
+
function resolveGenericDescriptionField(fieldsOverride) {
|
|
1169
|
+
return fieldsOverride ? resolveDescriptionField(fieldsOverride, void 0) : null;
|
|
1170
|
+
}
|
|
1171
|
+
function buildDataFromFieldsOrRefuse(fields, descriptionField, descriptionValue, collectionSlug) {
|
|
1172
|
+
if (!descriptionField) {
|
|
1173
|
+
const msg = noDescriptionFieldMessage(collectionSlug);
|
|
1174
|
+
const recovery = `Pass the text via an existing field in \`data\` (see \`collections action=get\` for ${collectionSlug}'s field list), or ask a platform admin to declare a descriptionFieldKey (or a body-zoned text field) on ${collectionSlug}.`;
|
|
1175
|
+
return {
|
|
1176
|
+
refusal: failureResult(msg, "VALIDATION_FAILED", `Collection '${collectionSlug}' has no field for free text.`, recovery)
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
return { data: buildDataFromFields(fields, descriptionField, descriptionValue), descriptionField };
|
|
1180
|
+
}
|
|
1154
1181
|
function isEmptyValue(v) {
|
|
1155
1182
|
return v == null || (Array.isArray(v) ? v.length === 0 : String(v).trim() === "");
|
|
1156
1183
|
}
|
|
@@ -1378,18 +1405,15 @@ var READINESS_PROVISIONAL_LINE = "Readiness is provisional: its sample omitted a
|
|
|
1378
1405
|
// src/tools/smart-capture.ts
|
|
1379
1406
|
var GENERIC_PROFILE = {
|
|
1380
1407
|
governedDraft: false,
|
|
1381
|
-
descriptionField:
|
|
1408
|
+
descriptionField: null,
|
|
1409
|
+
// TEN-3704 F4: never a hard-coded "description" — see resolveGenericDescriptionField
|
|
1382
1410
|
defaults: [],
|
|
1383
1411
|
recommendedRelationTypes: ["related_to", "references"]
|
|
1384
1412
|
};
|
|
1385
|
-
async function buildRuntimeProfile(slug) {
|
|
1413
|
+
async function buildRuntimeProfile(slug, fieldsOverride) {
|
|
1386
1414
|
const col = await getCollectionBySlug(slug);
|
|
1387
|
-
if (!col) return GENERIC_PROFILE;
|
|
1388
|
-
const
|
|
1389
|
-
const layoutDescriptionField = fields.find(
|
|
1390
|
-
(field) => field.zone === "body" || field.displayHint === "textarea" || field.displayHint === "section"
|
|
1391
|
-
)?.key;
|
|
1392
|
-
const descriptionField = col.descriptionFieldKey || layoutDescriptionField || "description";
|
|
1415
|
+
if (!col) return { ...GENERIC_PROFILE, descriptionField: resolveGenericDescriptionField(fieldsOverride) };
|
|
1416
|
+
const descriptionField = resolveProfileDescriptionField(col, fieldsOverride);
|
|
1393
1417
|
return {
|
|
1394
1418
|
governedDraft: col.governed === true,
|
|
1395
1419
|
descriptionField,
|
|
@@ -1398,7 +1422,7 @@ async function buildRuntimeProfile(slug) {
|
|
|
1398
1422
|
};
|
|
1399
1423
|
}
|
|
1400
1424
|
var profileCache = new ScopedCache(COLLECTION_CACHE_TTL_MS);
|
|
1401
|
-
async function getProfile(slug) {
|
|
1425
|
+
async function getProfile(slug, fieldsOverride) {
|
|
1402
1426
|
const scope = cacheScope();
|
|
1403
1427
|
let map = profileCache.get(scope);
|
|
1404
1428
|
if (!map) {
|
|
@@ -1407,7 +1431,7 @@ async function getProfile(slug) {
|
|
|
1407
1431
|
}
|
|
1408
1432
|
const cached = map.get(slug);
|
|
1409
1433
|
if (cached) return cached;
|
|
1410
|
-
const profile = await buildRuntimeProfile(slug);
|
|
1434
|
+
const profile = await buildRuntimeProfile(slug, fieldsOverride);
|
|
1411
1435
|
map.set(slug, profile);
|
|
1412
1436
|
return profile;
|
|
1413
1437
|
}
|
|
@@ -1767,17 +1791,6 @@ var captureOutputSchema = z4.union([
|
|
|
1767
1791
|
captureSinglePreviewOutputSchema,
|
|
1768
1792
|
captureClassifierOnlyOutputSchema
|
|
1769
1793
|
]);
|
|
1770
|
-
function buildDataFromFields(fields, descriptionField, descriptionValue) {
|
|
1771
|
-
const data = {};
|
|
1772
|
-
for (const field of fields) {
|
|
1773
|
-
if (field.key === descriptionField) {
|
|
1774
|
-
data[field.key] = descriptionValue;
|
|
1775
|
-
} else {
|
|
1776
|
-
data[field.key] = FIELD_TYPE_DEFAULTS[field.type] ?? null;
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
return data;
|
|
1780
|
-
}
|
|
1781
1794
|
var CAPTURE_ACTIONS = ["capture"];
|
|
1782
1795
|
var captureCompoundSchema = z4.object({
|
|
1783
1796
|
action: z4.enum(CAPTURE_ACTIONS).optional().default("capture").describe("Create a single knowledge entry."),
|
|
@@ -1905,7 +1918,7 @@ async function handleCapture(server, { collection, name, description, context, e
|
|
|
1905
1918
|
)
|
|
1906
1919
|
};
|
|
1907
1920
|
}
|
|
1908
|
-
const profile = await getProfile(resolvedCollection);
|
|
1921
|
+
const profile = await getProfile(resolvedCollection, col.fields);
|
|
1909
1922
|
const groundingStart = Date.now();
|
|
1910
1923
|
const groundingPromise = name || description ? kernelQuery("chain.capture", { name, description: description ?? "", collectionSlug: resolvedCollection }).catch(() => null) : Promise.resolve(null);
|
|
1911
1924
|
const groundingRaw = await Promise.race([groundingPromise, new Promise((r) => setTimeout(() => r(null), 500))]);
|
|
@@ -1980,7 +1993,9 @@ ${groundingReport.duplicates.map((d) => `- **${d.entryId}** ${d.name} [${d.colle
|
|
|
1980
1993
|
};
|
|
1981
1994
|
}
|
|
1982
1995
|
if (groundingEntry?.kind === "version") return captureVersionOrPreview(preview ?? false, { groundingEntry, name, description, data: userData, sourceRef, sourceExcerpt, links, groundingElapsedMs });
|
|
1983
|
-
const
|
|
1996
|
+
const built = buildDataFromFieldsOrRefuse(col.fields ?? [], profile.descriptionField, description, resolvedCollection);
|
|
1997
|
+
if ("refusal" in built) return built.refusal;
|
|
1998
|
+
const { data, descriptionField } = built;
|
|
1984
1999
|
for (const def of profile.defaults) {
|
|
1985
2000
|
if (def.value !== "infer" && def.value !== "today") {
|
|
1986
2001
|
data[def.key] = def.value;
|
|
@@ -2011,7 +2026,7 @@ ${groundingReport.duplicates.map((d) => `- **${d.entryId}** ${d.name} [${d.colle
|
|
|
2011
2026
|
}
|
|
2012
2027
|
}
|
|
2013
2028
|
if (userData && typeof userData === "object") Object.assign(data, userData);
|
|
2014
|
-
data[
|
|
2029
|
+
data[descriptionField] = description;
|
|
2015
2030
|
const colMeta = await getCollectionBySlug(resolvedCollection);
|
|
2016
2031
|
const isWorkPackageCapture = canonicalKey === "work_package" || colMeta?.defaultCanonicalKey === "work_package";
|
|
2017
2032
|
let entryWarnings = [];
|
|
@@ -15630,4 +15645,4 @@ export {
|
|
|
15630
15645
|
createProductBrainServer,
|
|
15631
15646
|
initFeatureFlags
|
|
15632
15647
|
};
|
|
15633
|
-
//# sourceMappingURL=chunk-
|
|
15648
|
+
//# sourceMappingURL=chunk-GBEBTAN6.js.map
|