@productbrain/mcp 0.0.1-beta.160 → 0.0.1-beta.161
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.
|
@@ -1838,7 +1838,15 @@ var captureSchema = z2.object({
|
|
|
1838
1838
|
sourceRef: z2.string().optional().describe("URI or path of the source document backing this entry (e.g. 'meeting-2026-03-28.md', 'import://batch-5'). Stored as top-level entry field, not in data."),
|
|
1839
1839
|
sourceExcerpt: z2.string().optional().describe("Verbatim excerpt from the source that backs this entry's claims. Stored as top-level entry field, not in data."),
|
|
1840
1840
|
// WP-316 S3: Preview gate — dry-run mode. Returns what would happen, no DB writes.
|
|
1841
|
-
preview: z2.boolean().optional().describe("If true, validates the capture without writing. Returns what would happen. Default false.")
|
|
1841
|
+
preview: z2.boolean().optional().describe("If true, validates the capture without writing. Returns what would happen. Default false."),
|
|
1842
|
+
// WP-318 S2: Pre-write grounding — run link suggestion before creating entry.
|
|
1843
|
+
suggestOnly: z2.boolean().optional().describe(
|
|
1844
|
+
"If true, runs pre-write grounding (suggestLinksForCapture) and returns a groundingReport WITHOUT creating any entry. Use to preview graph participation before committing. Default false."
|
|
1845
|
+
),
|
|
1846
|
+
// WP-318 S2: Format for groundingReport in response.
|
|
1847
|
+
format: z2.enum(["agent", "human"]).optional().describe(
|
|
1848
|
+
"Response format for grounding data. 'agent' (default): full JSON groundingReport. 'human': compressed summary string appended to the capture summary."
|
|
1849
|
+
)
|
|
1842
1850
|
});
|
|
1843
1851
|
var batchCaptureSchema = z2.object({
|
|
1844
1852
|
entries: z2.array(z2.object({
|
|
@@ -2266,7 +2274,7 @@ function registerSmartCaptureTools(server) {
|
|
|
2266
2274
|
inputSchema: captureSchema.shape,
|
|
2267
2275
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
2268
2276
|
},
|
|
2269
|
-
withEnvelope(async ({ collection, name, description, context, entryId, canonicalKey, data: userData, links, autoCommit, sourceRef, sourceExcerpt, preview }) => {
|
|
2277
|
+
withEnvelope(async ({ collection, name, description, context, entryId, canonicalKey, data: userData, links, autoCommit, sourceRef, sourceExcerpt, preview, suggestOnly, format }) => {
|
|
2270
2278
|
requireWriteAccess();
|
|
2271
2279
|
const timingStart = Date.now();
|
|
2272
2280
|
const wsCtx = await getWorkspaceContext();
|
|
@@ -2341,6 +2349,72 @@ Or use \`collections action=list\` to see available collections.`
|
|
|
2341
2349
|
)
|
|
2342
2350
|
};
|
|
2343
2351
|
}
|
|
2352
|
+
const skipAutoDiscoveryEarly = links && links.length > 0;
|
|
2353
|
+
const groundingPromise = !skipAutoDiscoveryEarly && (name || description) ? mcpQuery("chain.suggestLinksForCapture", {
|
|
2354
|
+
entries: [{ name, description: description ?? "", collectionHint: resolvedCollection }],
|
|
2355
|
+
limit: 5,
|
|
2356
|
+
threshold: 2
|
|
2357
|
+
}).catch(() => null) : Promise.resolve(null);
|
|
2358
|
+
const groundingRaw = await groundingPromise;
|
|
2359
|
+
const groundingEntry = groundingRaw?.[0] ?? null;
|
|
2360
|
+
const groundingRelated = groundingEntry?.related ?? [];
|
|
2361
|
+
const groundingDuplicates = groundingEntry?.duplicates ?? [];
|
|
2362
|
+
const groundingGovernanceCandidates = [...groundingRelated, ...groundingDuplicates];
|
|
2363
|
+
const groundingGovernance = [];
|
|
2364
|
+
for (const c of groundingGovernanceCandidates) {
|
|
2365
|
+
if (groundingGovernance.some((g) => g.entryId === c.entryId)) continue;
|
|
2366
|
+
if (await isGoverned(c.collectionSlug)) {
|
|
2367
|
+
groundingGovernance.push({ entryId: c.entryId, name: c.name, collectionSlug: c.collectionSlug });
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
const groundingReport = {
|
|
2371
|
+
related: groundingRelated.map((r) => ({
|
|
2372
|
+
entryId: r.entryId,
|
|
2373
|
+
name: r.name,
|
|
2374
|
+
collectionSlug: r.collectionSlug,
|
|
2375
|
+
overlapRatio: r.overlapRatio,
|
|
2376
|
+
recommendedRelationType: r.recommendedRelationType,
|
|
2377
|
+
reasoning: r.reasoning
|
|
2378
|
+
})),
|
|
2379
|
+
duplicates: groundingDuplicates.map((d) => ({
|
|
2380
|
+
entryId: d.entryId,
|
|
2381
|
+
name: d.name,
|
|
2382
|
+
collectionSlug: d.collectionSlug,
|
|
2383
|
+
matchType: d.matchType,
|
|
2384
|
+
overlapRatio: d.overlapRatio
|
|
2385
|
+
})),
|
|
2386
|
+
governance: groundingGovernance
|
|
2387
|
+
};
|
|
2388
|
+
if (suggestOnly) {
|
|
2389
|
+
const hasSuggestions = groundingReport.related.length > 0 || groundingReport.duplicates.length > 0;
|
|
2390
|
+
const summaryText = hasSuggestions ? `Grounding preview for "${name}": ${groundingReport.related.length} related, ${groundingReport.duplicates.length} possible duplicates. No entry created.` : `Grounding preview for "${name}": no similar entries found. Safe to capture.`;
|
|
2391
|
+
return {
|
|
2392
|
+
content: [{
|
|
2393
|
+
type: "text",
|
|
2394
|
+
text: `# Grounding Preview \u2014 No Entry Created
|
|
2395
|
+
|
|
2396
|
+
${summaryText}
|
|
2397
|
+
|
|
2398
|
+
` + (groundingReport.related.length > 0 ? `## Related entries
|
|
2399
|
+
${groundingReport.related.map((r) => `- **${r.entryId}** ${r.name} [${r.collectionSlug}] \u2014 ${r.reasoning}`).join("\n")}
|
|
2400
|
+
|
|
2401
|
+
` : "") + (groundingReport.duplicates.length > 0 ? `## Possible duplicates
|
|
2402
|
+
${groundingReport.duplicates.map((d) => `- **${d.entryId}** ${d.name} [${d.collectionSlug}] (${d.matchType}, overlap: ${d.overlapRatio})`).join("\n")}
|
|
2403
|
+
|
|
2404
|
+
` : "") + (groundingReport.governance.length > 0 ? `## Governance entries to review
|
|
2405
|
+
${groundingReport.governance.map((g) => `- **${g.entryId}** ${g.name} [${g.collectionSlug}]`).join("\n")}
|
|
2406
|
+
|
|
2407
|
+
` : "") + `_Call \`capture\` without \`suggestOnly\` to proceed with entry creation._`
|
|
2408
|
+
}],
|
|
2409
|
+
structuredContent: {
|
|
2410
|
+
...success(
|
|
2411
|
+
summaryText,
|
|
2412
|
+
{ groundingReport, outcome: "suggest_only" },
|
|
2413
|
+
[{ tool: "capture", description: "Capture for real", parameters: { collection: resolvedCollection, name, description } }]
|
|
2414
|
+
)
|
|
2415
|
+
}
|
|
2416
|
+
};
|
|
2417
|
+
}
|
|
2344
2418
|
const data = buildDataFromFields(col.fields ?? [], profile.descriptionField, description);
|
|
2345
2419
|
for (const def of profile.defaults) {
|
|
2346
2420
|
if (def.value !== "infer" && def.value !== "today") {
|
|
@@ -2429,6 +2503,14 @@ Or use \`collections action=list\` to see available collections.`
|
|
|
2429
2503
|
...preview ? { preview: true } : {}
|
|
2430
2504
|
});
|
|
2431
2505
|
if (result?.preview) {
|
|
2506
|
+
const hasGrounding = groundingReport.related.length > 0 || groundingReport.duplicates.length > 0 || groundingReport.governance.length > 0;
|
|
2507
|
+
const groundingSummary = hasGrounding ? `
|
|
2508
|
+
|
|
2509
|
+
**Grounding:** ${[
|
|
2510
|
+
groundingReport.duplicates.length > 0 && `${groundingReport.duplicates.length} possible duplicate${groundingReport.duplicates.length > 1 ? "s" : ""}`,
|
|
2511
|
+
groundingReport.related.length > 0 && `${groundingReport.related.length} related entr${groundingReport.related.length > 1 ? "ies" : "y"}`,
|
|
2512
|
+
groundingReport.governance.length > 0 && `${groundingReport.governance[0]?.entryId} may govern this`
|
|
2513
|
+
].filter(Boolean).join(", ")}.` : "";
|
|
2432
2514
|
const previewEnvelope = success(
|
|
2433
2515
|
`Preview: would capture "${name}" \u2014 no DB writes`,
|
|
2434
2516
|
{
|
|
@@ -2436,7 +2518,8 @@ Or use \`collections action=list\` to see available collections.`
|
|
|
2436
2518
|
name,
|
|
2437
2519
|
collection: resolvedCollection,
|
|
2438
2520
|
outcome: "preview",
|
|
2439
|
-
warnings: result.warnings ?? []
|
|
2521
|
+
warnings: result.warnings ?? [],
|
|
2522
|
+
groundingReport
|
|
2440
2523
|
},
|
|
2441
2524
|
[{ tool: "capture", description: "Capture for real", parameters: { collection: resolvedCollection, name, description } }]
|
|
2442
2525
|
);
|
|
@@ -2448,7 +2531,7 @@ Or use \`collections action=list\` to see available collections.`
|
|
|
2448
2531
|
|
|
2449
2532
|
No DB writes \u2014 call without \`preview:true\` to capture for real.${result.warnings?.length ? `
|
|
2450
2533
|
|
|
2451
|
-
**Warnings:** ${result.warnings.join("; ")}` : ""}` }],
|
|
2534
|
+
**Warnings:** ${result.warnings.join("; ")}` : ""}${groundingSummary}` }],
|
|
2452
2535
|
structuredContent: previewEnvelope
|
|
2453
2536
|
};
|
|
2454
2537
|
}
|
|
@@ -2770,6 +2853,19 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
2770
2853
|
lines.push(`${i + 1}. **${s.entryId ?? "(no ID)"}**: ${s.name} [${s.collection}]${preview2}`);
|
|
2771
2854
|
}
|
|
2772
2855
|
}
|
|
2856
|
+
if (format === "human") {
|
|
2857
|
+
const hasDuplicates = groundingReport.duplicates.length > 0;
|
|
2858
|
+
const hasRelated = groundingReport.related.length > 0;
|
|
2859
|
+
const hasGov = groundingReport.governance.length > 0;
|
|
2860
|
+
if (hasDuplicates || hasRelated || hasGov) {
|
|
2861
|
+
lines.push("");
|
|
2862
|
+
const parts = [];
|
|
2863
|
+
if (hasDuplicates) parts.push(`${groundingReport.duplicates.length} possible duplicate${groundingReport.duplicates.length > 1 ? "s" : ""}`);
|
|
2864
|
+
if (hasRelated) parts.push(`${groundingReport.related.length} related entr${groundingReport.related.length > 1 ? "ies" : "y"}`);
|
|
2865
|
+
if (hasGov) parts.push(`${groundingReport.governance[0]?.entryId} may govern this`);
|
|
2866
|
+
lines.push(`_Grounding: ${parts.join(", ")}. Review and link if relevant._`);
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2773
2869
|
lines.push("");
|
|
2774
2870
|
lines.push(formatQualityReport(quality));
|
|
2775
2871
|
const failedChecks = quality.checks.filter((c) => !c.passed);
|
|
@@ -2946,7 +3042,9 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
2946
3042
|
// BET-272 S3: Advisory quality hints — always included (empty array when all criteria pass)
|
|
2947
3043
|
qualityHints: formativeHints,
|
|
2948
3044
|
// BET-272 S5: Advisory relation suggestions from graph (BR-144, STD-147)
|
|
2949
|
-
relationSuggestions: relationSuggestionsFromCreate
|
|
3045
|
+
relationSuggestions: relationSuggestionsFromCreate,
|
|
3046
|
+
// WP-318 S2: Pre-write grounding report — always included (empty arrays when no suggestions)
|
|
3047
|
+
groundingReport
|
|
2950
3048
|
},
|
|
2951
3049
|
next
|
|
2952
3050
|
),
|
|
@@ -11114,7 +11212,16 @@ async function tryMarkOriented(agentSessionId, coherenceSnapshot) {
|
|
|
11114
11212
|
setSessionOriented(true);
|
|
11115
11213
|
return { oriented: true, orientationStatus: "complete" };
|
|
11116
11214
|
} catch {
|
|
11117
|
-
|
|
11215
|
+
if (!coherenceSnapshot) {
|
|
11216
|
+
return { oriented: false, orientationStatus: "failed" };
|
|
11217
|
+
}
|
|
11218
|
+
try {
|
|
11219
|
+
await mcpCall("agent.markOriented", { sessionId: agentSessionId });
|
|
11220
|
+
setSessionOriented(true);
|
|
11221
|
+
return { oriented: true, orientationStatus: "complete" };
|
|
11222
|
+
} catch {
|
|
11223
|
+
return { oriented: false, orientationStatus: "failed" };
|
|
11224
|
+
}
|
|
11118
11225
|
}
|
|
11119
11226
|
}
|
|
11120
11227
|
var startSchema = z17.object({
|
|
@@ -13361,6 +13468,25 @@ function formatScanReport(result) {
|
|
|
13361
13468
|
// src/tools/orient.ts
|
|
13362
13469
|
import { z as z22 } from "zod";
|
|
13363
13470
|
var PURPOSE_GAP_PREFIX = "purpose-gap-";
|
|
13471
|
+
async function markOrientedWithSnapshotFallback(agentSessionId, coherenceSnapshot) {
|
|
13472
|
+
try {
|
|
13473
|
+
await mcpCall("agent.markOriented", {
|
|
13474
|
+
sessionId: agentSessionId,
|
|
13475
|
+
...coherenceSnapshot ? { coherenceSnapshot } : {}
|
|
13476
|
+
});
|
|
13477
|
+
setSessionOriented(true);
|
|
13478
|
+
return true;
|
|
13479
|
+
} catch {
|
|
13480
|
+
if (!coherenceSnapshot) return false;
|
|
13481
|
+
try {
|
|
13482
|
+
await mcpCall("agent.markOriented", { sessionId: agentSessionId });
|
|
13483
|
+
setSessionOriented(true);
|
|
13484
|
+
return true;
|
|
13485
|
+
} catch {
|
|
13486
|
+
return false;
|
|
13487
|
+
}
|
|
13488
|
+
}
|
|
13489
|
+
}
|
|
13364
13490
|
function extractSessionEntryIds(priorSessions) {
|
|
13365
13491
|
const allSeen = /* @__PURE__ */ new Set();
|
|
13366
13492
|
const all = [];
|
|
@@ -13648,16 +13774,12 @@ function registerOrientTool(server) {
|
|
|
13648
13774
|
}
|
|
13649
13775
|
let orientationStatus2 = "no_session";
|
|
13650
13776
|
if (agentSessionId && hasTaskGrounding) {
|
|
13651
|
-
|
|
13652
|
-
|
|
13653
|
-
sessionId: agentSessionId,
|
|
13654
|
-
...coherenceSnapshot ? { coherenceSnapshot } : {}
|
|
13655
|
-
});
|
|
13656
|
-
setSessionOriented(true);
|
|
13777
|
+
const orientedOk = await markOrientedWithSnapshotFallback(agentSessionId, coherenceSnapshot);
|
|
13778
|
+
if (orientedOk) {
|
|
13657
13779
|
orientationStatus2 = "complete";
|
|
13658
13780
|
lines.push("---");
|
|
13659
13781
|
lines.push(`Orientation complete. Session ${agentSessionId}. Write tools available.`);
|
|
13660
|
-
}
|
|
13782
|
+
} else {
|
|
13661
13783
|
orientationStatus2 = "failed";
|
|
13662
13784
|
lines.push("---");
|
|
13663
13785
|
lines.push("_Warning: Could not mark session as oriented. Write tools may be restricted._");
|
|
@@ -14019,16 +14141,12 @@ function registerOrientTool(server) {
|
|
|
14019
14141
|
}
|
|
14020
14142
|
let orientationStatus = "no_session";
|
|
14021
14143
|
if (agentSessionId && hasTaskGrounding) {
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
sessionId: agentSessionId,
|
|
14025
|
-
...fullCoherenceSnapshot ? { coherenceSnapshot: fullCoherenceSnapshot } : {}
|
|
14026
|
-
});
|
|
14027
|
-
setSessionOriented(true);
|
|
14144
|
+
const orientedOk = await markOrientedWithSnapshotFallback(agentSessionId, fullCoherenceSnapshot);
|
|
14145
|
+
if (orientedOk) {
|
|
14028
14146
|
orientationStatus = "complete";
|
|
14029
14147
|
lines.push("---");
|
|
14030
14148
|
lines.push(`Orientation complete. Session ${agentSessionId}. Write tools available.`);
|
|
14031
|
-
}
|
|
14149
|
+
} else {
|
|
14032
14150
|
orientationStatus = "failed";
|
|
14033
14151
|
lines.push("---");
|
|
14034
14152
|
lines.push("_Warning: Could not mark session as oriented. Write tools may be restricted._");
|
|
@@ -15629,7 +15747,6 @@ export {
|
|
|
15629
15747
|
hashKey,
|
|
15630
15748
|
runWithAuth,
|
|
15631
15749
|
getAgentSessionId,
|
|
15632
|
-
startAgentSession,
|
|
15633
15750
|
orphanAgentSession,
|
|
15634
15751
|
bootstrap,
|
|
15635
15752
|
bootstrapHttp,
|
|
@@ -15639,4 +15756,4 @@ export {
|
|
|
15639
15756
|
SERVER_VERSION,
|
|
15640
15757
|
createProductBrainServer
|
|
15641
15758
|
};
|
|
15642
|
-
//# sourceMappingURL=chunk-
|
|
15759
|
+
//# sourceMappingURL=chunk-6E6HZFTX.js.map
|