@productbrain/mcp 0.0.1-beta.2087 → 0.0.1-beta.2093
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.
|
@@ -203,22 +203,19 @@ import { z } from "zod/v3";
|
|
|
203
203
|
// src/errors.ts
|
|
204
204
|
var MCP_CALL_ERROR_RE = /^MCP call "([^"]+)" failed \(\d+\): (.+)$/s;
|
|
205
205
|
function asKernelCallError(err) {
|
|
206
|
-
if (err instanceof Error
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return void 0;
|
|
206
|
+
if (!(err instanceof Error)) return void 0;
|
|
207
|
+
const e = err;
|
|
208
|
+
if (typeof e.code !== "string") return void 0;
|
|
209
|
+
const match = MCP_CALL_ERROR_RE.exec(e.message);
|
|
210
|
+
if (!match) return void 0;
|
|
211
|
+
return {
|
|
212
|
+
code: e.code,
|
|
213
|
+
fn: match[1],
|
|
214
|
+
cleanMessage: match[2],
|
|
215
|
+
// NOTE: match[2] not match[1] — group 1 is now fn scope (DEC-798)
|
|
216
|
+
missingRequiredFields: Array.isArray(e.missingRequiredFields) ? e.missingRequiredFields : void 0,
|
|
217
|
+
fieldErrors: Array.isArray(e.fieldErrors) ? e.fieldErrors : void 0
|
|
218
|
+
};
|
|
222
219
|
}
|
|
223
220
|
var GateError = class extends Error {
|
|
224
221
|
constructor(message) {
|
|
@@ -751,7 +748,10 @@ function buildFieldQualityChecks(col) {
|
|
|
751
748
|
addCheck({
|
|
752
749
|
id: `field-${field.key}-min-length`,
|
|
753
750
|
label: `${field.key} min ${field.minLength} chars`,
|
|
754
|
-
check: (ctx) =>
|
|
751
|
+
check: (ctx) => {
|
|
752
|
+
const value = ctx.data[field.key];
|
|
753
|
+
return typeof value === "string" && value.length >= field.minLength;
|
|
754
|
+
},
|
|
755
755
|
suggestion: () => `Add more detail to ${labelFor(field.key)} (minimum ${field.minLength} characters).`
|
|
756
756
|
});
|
|
757
757
|
}
|
|
@@ -759,7 +759,10 @@ function buildFieldQualityChecks(col) {
|
|
|
759
759
|
addCheck({
|
|
760
760
|
id: `field-${field.key}-max-length`,
|
|
761
761
|
label: `${field.key} max ${field.maxLength} chars`,
|
|
762
|
-
check: (ctx) =>
|
|
762
|
+
check: (ctx) => {
|
|
763
|
+
const value = ctx.data[field.key];
|
|
764
|
+
return typeof value !== "string" || value.length <= field.maxLength;
|
|
765
|
+
},
|
|
763
766
|
suggestion: () => `Shorten ${labelFor(field.key)} to ${field.maxLength} characters or fewer.`
|
|
764
767
|
});
|
|
765
768
|
}
|
|
@@ -4818,25 +4821,26 @@ async function handleGather(server, entryId, task, mode, maxHops, maxResults, st
|
|
|
4818
4821
|
if (!result2?.root) {
|
|
4819
4822
|
return notFoundResult(entryId, `Entry '${entryId}' not found. Try search to find the right ID.`);
|
|
4820
4823
|
}
|
|
4824
|
+
const root2 = result2.root;
|
|
4821
4825
|
if (result2.context.length === 0) {
|
|
4822
|
-
const recorded = recordGap({ query:
|
|
4826
|
+
const recorded = recordGap({ query: root2.entryId, tool: "context", action: "gather", gapType: "context_graph_empty" });
|
|
4823
4827
|
if (recorded) {
|
|
4824
|
-
getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query:
|
|
4828
|
+
getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query: root2.entryId, tool: "context", action: "gather", gap_type: "context_graph_empty" })).catch(() => {
|
|
4825
4829
|
});
|
|
4826
4830
|
}
|
|
4827
4831
|
return {
|
|
4828
4832
|
content: [{
|
|
4829
4833
|
type: "text",
|
|
4830
|
-
text: `# Context for ${
|
|
4834
|
+
text: `# Context for ${root2.entryId}: ${root2.name}
|
|
4831
4835
|
|
|
4832
4836
|
_No relations found._ This entry is not yet connected to the knowledge graph.
|
|
4833
4837
|
|
|
4834
4838
|
Use \`graph action=suggest\` to discover potential connections.`
|
|
4835
4839
|
}],
|
|
4836
4840
|
structuredContent: success(
|
|
4837
|
-
`No relations found for ${
|
|
4838
|
-
{ root:
|
|
4839
|
-
[{ tool: "graph", description: "Discover connections", parameters: { action: "suggest", entryId:
|
|
4841
|
+
`No relations found for ${root2.entryId}. Entry not yet connected.`,
|
|
4842
|
+
{ root: root2, context: [], totalFound: 0 },
|
|
4843
|
+
[{ tool: "graph", description: "Discover connections", parameters: { action: "suggest", entryId: root2.entryId } }]
|
|
4840
4844
|
)
|
|
4841
4845
|
};
|
|
4842
4846
|
}
|
|
@@ -4847,7 +4851,7 @@ Use \`graph action=suggest\` to discover potential connections.`
|
|
|
4847
4851
|
byCollection2.get(key).push(entry);
|
|
4848
4852
|
}
|
|
4849
4853
|
const lines2 = [
|
|
4850
|
-
`# Context for ${
|
|
4854
|
+
`# Context for ${root2.entryId}: ${root2.name} (graph mode)`,
|
|
4851
4855
|
`_${result2.totalFound} related entries across ${byCollection2.size} collections (${result2.hopsTraversed} hops)_`,
|
|
4852
4856
|
""
|
|
4853
4857
|
];
|
|
@@ -4868,9 +4872,9 @@ Use \`graph action=suggest\` to discover potential connections.`
|
|
|
4868
4872
|
}
|
|
4869
4873
|
lines2.push("");
|
|
4870
4874
|
}
|
|
4871
|
-
const rootId2 =
|
|
4875
|
+
const rootId2 = root2.entryId ?? "root";
|
|
4872
4876
|
const nodes2 = [
|
|
4873
|
-
{ id: rootId2, name:
|
|
4877
|
+
{ id: rootId2, name: root2.name, collectionName: "" },
|
|
4874
4878
|
...result2.context.map((e) => ({
|
|
4875
4879
|
id: e.entryId ?? String(Math.random()),
|
|
4876
4880
|
name: e.name,
|
|
@@ -4885,8 +4889,8 @@ Use \`graph action=suggest\` to discover potential connections.`
|
|
|
4885
4889
|
return {
|
|
4886
4890
|
content: [{ type: "text", text: lines2.join("\n") }],
|
|
4887
4891
|
structuredContent: success(
|
|
4888
|
-
`Gathered ${result2.totalFound} related entries for ${
|
|
4889
|
-
{ nodes: nodes2, edges: edges2, root:
|
|
4892
|
+
`Gathered ${result2.totalFound} related entries for ${root2.entryId} (${result2.hopsTraversed} hops, graph mode).`,
|
|
4893
|
+
{ nodes: nodes2, edges: edges2, root: root2, totalFound: result2.totalFound }
|
|
4890
4894
|
)
|
|
4891
4895
|
};
|
|
4892
4896
|
}
|
|
@@ -5088,25 +5092,26 @@ _This helps future sessions start with better constraints and context._`
|
|
|
5088
5092
|
if (!result?.root) {
|
|
5089
5093
|
return notFoundResult(entryId, `Entry '${entryId}' not found. Try search to find the right ID.`);
|
|
5090
5094
|
}
|
|
5095
|
+
const root = result.root;
|
|
5091
5096
|
if (result.related.length === 0) {
|
|
5092
|
-
const recorded = recordGap({ query:
|
|
5097
|
+
const recorded = recordGap({ query: root.entryId, tool: "context", action: "gather", gapType: "context_entry_isolated" });
|
|
5093
5098
|
if (recorded) {
|
|
5094
|
-
getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query:
|
|
5099
|
+
getWorkspaceId().then((wsId) => trackKnowledgeGap(wsId, { query: root.entryId, tool: "context", action: "gather", gap_type: "context_entry_isolated" })).catch(() => {
|
|
5095
5100
|
});
|
|
5096
5101
|
}
|
|
5097
5102
|
return {
|
|
5098
5103
|
content: [{
|
|
5099
5104
|
type: "text",
|
|
5100
|
-
text: `# Context for ${
|
|
5105
|
+
text: `# Context for ${root.entryId}: ${root.name}
|
|
5101
5106
|
|
|
5102
5107
|
_No relations found._ This entry is not yet connected to the knowledge graph.
|
|
5103
5108
|
|
|
5104
5109
|
Use \`graph action=suggest\` to discover potential connections, or \`relations action=create\` to link manually.`
|
|
5105
5110
|
}],
|
|
5106
5111
|
structuredContent: success(
|
|
5107
|
-
`No relations found for ${
|
|
5108
|
-
{ root
|
|
5109
|
-
[{ tool: "graph", description: "Discover connections", parameters: { action: "suggest", entryId:
|
|
5112
|
+
`No relations found for ${root.entryId}. Entry not yet connected.`,
|
|
5113
|
+
{ root, related: [], totalRelations: 0 },
|
|
5114
|
+
[{ tool: "graph", description: "Discover connections", parameters: { action: "suggest", entryId: root.entryId } }]
|
|
5110
5115
|
)
|
|
5111
5116
|
};
|
|
5112
5117
|
}
|
|
@@ -5117,7 +5122,7 @@ Use \`graph action=suggest\` to discover potential connections, or \`relations a
|
|
|
5117
5122
|
byCollection.get(key).push(entry);
|
|
5118
5123
|
}
|
|
5119
5124
|
const lines = [
|
|
5120
|
-
`# Context for ${
|
|
5125
|
+
`# Context for ${root.entryId}: ${root.name}`,
|
|
5121
5126
|
`_${result.totalRelations} related entries across ${byCollection.size} collections (${result.hopsTraversed} hops traversed)_`,
|
|
5122
5127
|
""
|
|
5123
5128
|
];
|
|
@@ -5131,9 +5136,9 @@ Use \`graph action=suggest\` to discover potential connections, or \`relations a
|
|
|
5131
5136
|
}
|
|
5132
5137
|
lines.push("");
|
|
5133
5138
|
}
|
|
5134
|
-
const rootId =
|
|
5139
|
+
const rootId = root.entryId ?? "root";
|
|
5135
5140
|
const nodes = [
|
|
5136
|
-
{ id: rootId, name:
|
|
5141
|
+
{ id: rootId, name: root.name, collectionName: "" },
|
|
5137
5142
|
...result.related.map((e) => ({
|
|
5138
5143
|
id: e.entryId ?? String(Math.random()),
|
|
5139
5144
|
name: e.name,
|
|
@@ -5148,8 +5153,8 @@ Use \`graph action=suggest\` to discover potential connections, or \`relations a
|
|
|
5148
5153
|
return {
|
|
5149
5154
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
5150
5155
|
structuredContent: success(
|
|
5151
|
-
`Gathered ${result.totalRelations} related entries for ${
|
|
5152
|
-
{ nodes, edges, root
|
|
5156
|
+
`Gathered ${result.totalRelations} related entries for ${root.entryId} (${result.hopsTraversed} hops).`,
|
|
5157
|
+
{ nodes, edges, root, totalRelations: result.totalRelations }
|
|
5153
5158
|
)
|
|
5154
5159
|
};
|
|
5155
5160
|
}
|
|
@@ -10214,7 +10219,7 @@ function buildPlannedWorkSection(work, priorSessions, recoveryBlock) {
|
|
|
10214
10219
|
}
|
|
10215
10220
|
if (priorSessions.length > 0 && !hasPlannedWork(work) && !recoveryBlock) {
|
|
10216
10221
|
const last = priorSessions[0];
|
|
10217
|
-
const date = new Date(last.startedAt).toISOString().split("T")[0];
|
|
10222
|
+
const date = last.startedAt !== void 0 ? new Date(last.startedAt).toISOString().split("T")[0] : "unknown date";
|
|
10218
10223
|
const created = Array.isArray(last.entriesCreated) ? last.entriesCreated.length : last.entriesCreated ?? 0;
|
|
10219
10224
|
const modified = Array.isArray(last.entriesModified) ? last.entriesModified.length : last.entriesModified ?? 0;
|
|
10220
10225
|
if (created > 0 || modified > 0) {
|
|
@@ -12241,7 +12246,7 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
|
|
|
12241
12246
|
priorSessions = orientView.priorSessions ?? [];
|
|
12242
12247
|
recoveryBlock = orientView.recoveryBlock ?? null;
|
|
12243
12248
|
}
|
|
12244
|
-
const hasTaskGrounding = Boolean(task && orientView?.taskContext?.context?.length > 0);
|
|
12249
|
+
const hasTaskGrounding = Boolean(task && (orientView?.taskContext?.context?.length ?? 0) > 0);
|
|
12245
12250
|
if (wsCtx && hasTaskGrounding && orientView?.writeBackHints) {
|
|
12246
12251
|
const hints = Array.isArray(orientView.writeBackHints) ? orientView.writeBackHints : [];
|
|
12247
12252
|
if (hints.length > 0) {
|
|
@@ -12362,8 +12367,9 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
|
|
|
12362
12367
|
lines.push(` ${h.collectionSlug}: ${h.hint}`);
|
|
12363
12368
|
}
|
|
12364
12369
|
}
|
|
12365
|
-
|
|
12366
|
-
|
|
12370
|
+
const briefActiveWps = orientView?.activeWorkPackages ?? [];
|
|
12371
|
+
if (briefActiveWps.length > 0) {
|
|
12372
|
+
for (const e of briefActiveWps) {
|
|
12367
12373
|
const tensions = e.linkedTensions;
|
|
12368
12374
|
const tensionPart = tensions?.length ? ` \u2014 ${tensions.map((t) => `${t.entryId ?? t.name} (${t.severity ?? "\u2014"})`).join(", ")}` : "";
|
|
12369
12375
|
const originPart = e.origin ? ` (origin: ${e.origin})` : "";
|
|
@@ -12635,13 +12641,18 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
|
|
|
12635
12641
|
const coll = e.collectionSlug ? ` [${e.collectionSlug}]` : "";
|
|
12636
12642
|
const originTag = e.origin ? ` (origin: ${e.origin})` : "";
|
|
12637
12643
|
lines.push(`- \`${id}\` (score ${e.score})${coll}${originTag}${e.name !== id ? ` \u2014 ${e.name}` : ""}`);
|
|
12638
|
-
if (e.preview) lines.push(` _${e.preview}_`);
|
|
12639
12644
|
}
|
|
12640
12645
|
lines.push("");
|
|
12641
12646
|
}
|
|
12642
12647
|
if (orientView?.taskContext?.constellationEntries && orientView.taskContext.constellationEntries.length > 0) {
|
|
12648
|
+
const constellationEntries = orientView.taskContext.constellationEntries.map((e) => ({
|
|
12649
|
+
entryId: e.entryId ?? e.name,
|
|
12650
|
+
name: e.name,
|
|
12651
|
+
collectionSlug: e.collectionSlug ?? "unclassified",
|
|
12652
|
+
canonicalKey: e.canonicalKey
|
|
12653
|
+
}));
|
|
12643
12654
|
lines.push(...formatBetConstellationLines(
|
|
12644
|
-
|
|
12655
|
+
constellationEntries,
|
|
12645
12656
|
orientView.taskContext.constellationBetName
|
|
12646
12657
|
));
|
|
12647
12658
|
}
|
|
@@ -12685,11 +12696,12 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
|
|
|
12685
12696
|
}
|
|
12686
12697
|
}
|
|
12687
12698
|
if (orientView) {
|
|
12688
|
-
|
|
12699
|
+
const fullActiveWps = orientView.activeWorkPackages ?? [];
|
|
12700
|
+
if (fullActiveWps.length > 0) {
|
|
12689
12701
|
lines.push("## Active work packages \u2014 current scope");
|
|
12690
12702
|
lines.push("_Work outside these work packages requires explicit user confirmation._");
|
|
12691
12703
|
lines.push("");
|
|
12692
|
-
for (const e of
|
|
12704
|
+
for (const e of fullActiveWps) {
|
|
12693
12705
|
lines.push(fmt(e));
|
|
12694
12706
|
const tensions = e.linkedTensions;
|
|
12695
12707
|
if (tensions?.length) {
|
|
@@ -12702,44 +12714,51 @@ async function _handleOrient({ mode = "full", tier, task, scope }) {
|
|
|
12702
12714
|
}
|
|
12703
12715
|
lines.push("");
|
|
12704
12716
|
}
|
|
12705
|
-
|
|
12717
|
+
const fullActiveGoals = orientView.activeGoals ?? [];
|
|
12718
|
+
if (fullActiveGoals.length > 0) {
|
|
12706
12719
|
lines.push("## Active goals");
|
|
12707
|
-
|
|
12720
|
+
fullActiveGoals.forEach((e) => lines.push(fmt(e)));
|
|
12708
12721
|
lines.push("");
|
|
12709
12722
|
}
|
|
12710
|
-
|
|
12723
|
+
const fullStrategyHighlights = orientView.strategyHighlights ?? [];
|
|
12724
|
+
if (fullStrategyHighlights.length > 0) {
|
|
12711
12725
|
lines.push("## Strategy highlights");
|
|
12712
12726
|
lines.push("_One-sentence strategy, positioning, moat, business model, GTM \u2014 high-level strategic context._");
|
|
12713
12727
|
lines.push("");
|
|
12714
|
-
|
|
12728
|
+
fullStrategyHighlights.forEach((e) => lines.push(fmt(e)));
|
|
12715
12729
|
lines.push("");
|
|
12716
12730
|
}
|
|
12717
|
-
|
|
12731
|
+
const fullPlayingField = orientView.playingField ?? [];
|
|
12732
|
+
if (fullPlayingField.length > 0) {
|
|
12718
12733
|
lines.push("## Playing field");
|
|
12719
12734
|
lines.push("_Products and opportunities in the strategic landscape._");
|
|
12720
12735
|
lines.push("");
|
|
12721
|
-
|
|
12736
|
+
fullPlayingField.forEach((e) => lines.push(fmt(e)));
|
|
12722
12737
|
lines.push("");
|
|
12723
12738
|
}
|
|
12724
|
-
|
|
12739
|
+
const fullRecentDecisions = orientView.recentDecisions ?? [];
|
|
12740
|
+
if (fullRecentDecisions.length > 0) {
|
|
12725
12741
|
lines.push("## Recent decisions");
|
|
12726
|
-
|
|
12742
|
+
fullRecentDecisions.forEach((e) => lines.push(fmt(e)));
|
|
12727
12743
|
lines.push("");
|
|
12728
12744
|
}
|
|
12729
|
-
|
|
12745
|
+
const fullRecentlySuperseded = orientView.recentlySuperseded ?? [];
|
|
12746
|
+
if (fullRecentlySuperseded.length > 0) {
|
|
12730
12747
|
lines.push("## Recently superseded");
|
|
12731
|
-
|
|
12748
|
+
fullRecentlySuperseded.forEach((e) => lines.push(fmt(e)));
|
|
12732
12749
|
lines.push("");
|
|
12733
12750
|
}
|
|
12734
|
-
|
|
12751
|
+
const fullStaleEntries = orientView.staleEntries ?? [];
|
|
12752
|
+
if (fullStaleEntries.length > 0) {
|
|
12735
12753
|
lines.push("## Needs confirmation");
|
|
12736
12754
|
lines.push(`_Domain stratum entries not confirmed in ${orientView.stalenessThresholdDays} days._`);
|
|
12737
|
-
|
|
12755
|
+
fullStaleEntries.forEach((e) => lines.push(fmt(e)));
|
|
12738
12756
|
lines.push("");
|
|
12739
12757
|
}
|
|
12740
|
-
|
|
12758
|
+
const fullArchitectureNotes = orientView.architectureNotes ?? [];
|
|
12759
|
+
if (fullArchitectureNotes.length > 0) {
|
|
12741
12760
|
lines.push("## Architecture notes");
|
|
12742
|
-
|
|
12761
|
+
fullArchitectureNotes.forEach((e) => lines.push(fmt(e)));
|
|
12743
12762
|
lines.push("");
|
|
12744
12763
|
}
|
|
12745
12764
|
const mapGovernanceEntry = (e) => ({
|
|
@@ -14181,6 +14200,7 @@ ${lines.join("\n")}`, mimeType: "text/markdown" }]
|
|
|
14181
14200
|
server.resource(
|
|
14182
14201
|
"chain-entry",
|
|
14183
14202
|
new ResourceTemplate("productbrain://entries/{entryId}", {
|
|
14203
|
+
list: void 0,
|
|
14184
14204
|
complete: {
|
|
14185
14205
|
entryId: async (value) => {
|
|
14186
14206
|
if (!value || value.length < 1) return [];
|
|
@@ -14238,6 +14258,7 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
|
|
|
14238
14258
|
server.resource(
|
|
14239
14259
|
"chain-context",
|
|
14240
14260
|
new ResourceTemplate("productbrain://context/{entryId}", {
|
|
14261
|
+
list: void 0,
|
|
14241
14262
|
complete: {
|
|
14242
14263
|
entryId: async (value) => {
|
|
14243
14264
|
if (!value || value.length < 1) return [];
|
|
@@ -14344,6 +14365,7 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
|
|
|
14344
14365
|
server.resource(
|
|
14345
14366
|
"chain-search",
|
|
14346
14367
|
new ResourceTemplate("productbrain://search/{query}", {
|
|
14368
|
+
list: void 0,
|
|
14347
14369
|
complete: {
|
|
14348
14370
|
query: async (value) => {
|
|
14349
14371
|
if (!value) return ["glossary:", "business-rules:", "decisions:", "tensions:"];
|
|
@@ -14791,4 +14813,4 @@ export {
|
|
|
14791
14813
|
createProductBrainServer,
|
|
14792
14814
|
initFeatureFlags
|
|
14793
14815
|
};
|
|
14794
|
-
//# sourceMappingURL=chunk-
|
|
14816
|
+
//# sourceMappingURL=chunk-QTY3D7P4.js.map
|