@productbrain/mcp 0.0.1-beta.158 → 0.0.1-beta.159
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/{chunk-ZZHGJKLF.js → chunk-LKUFRQUO.js} +146 -27
- package/dist/chunk-LKUFRQUO.js.map +1 -0
- package/dist/{chunk-KGGSEIZ3.js → chunk-YMF3IQ5E.js} +18 -1
- package/dist/{chunk-KGGSEIZ3.js.map → chunk-YMF3IQ5E.js.map} +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/http.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{setup-WAJMKE5Y.js → setup-BPZMFI56.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-ZZHGJKLF.js.map +0 -1
- /package/dist/{setup-WAJMKE5Y.js.map → setup-BPZMFI56.js.map} +0 -0
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
trackCaptureQualityHints,
|
|
8
8
|
trackCaptureRelationSuggestions,
|
|
9
9
|
trackChainEntryCommitted,
|
|
10
|
+
trackClassifierDivergence,
|
|
10
11
|
trackCollectionClassified,
|
|
11
12
|
trackCommitErrorByCode,
|
|
12
13
|
trackFieldGuidanceApplied,
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
trackToolCall,
|
|
19
20
|
trackWriteBackHintServed,
|
|
20
21
|
trackZeroCaptureAuditFired
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-YMF3IQ5E.js";
|
|
22
23
|
|
|
23
24
|
// src/auth.ts
|
|
24
25
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -1835,7 +1836,9 @@ var captureSchema = z2.object({
|
|
|
1835
1836
|
"If true, commits the entry immediately after capture + linking. If omitted, Open mode workspaces auto-commit by default and consensus/role modes stay draft-first."
|
|
1836
1837
|
),
|
|
1837
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."),
|
|
1838
|
-
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.")
|
|
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
|
+
// 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.")
|
|
1839
1842
|
});
|
|
1840
1843
|
var batchCaptureSchema = z2.object({
|
|
1841
1844
|
entries: z2.array(z2.object({
|
|
@@ -1850,7 +1853,9 @@ var batchCaptureSchema = z2.object({
|
|
|
1850
1853
|
})).min(1).max(50).describe("Array of entries to capture"),
|
|
1851
1854
|
autoCommit: z2.boolean().optional().describe(
|
|
1852
1855
|
"If true, commits created entries immediately after linking. If omitted, Open mode workspaces commit by default and consensus/role modes stay draft-first."
|
|
1853
|
-
)
|
|
1856
|
+
),
|
|
1857
|
+
// WP-316 S3: Preview gate — dry-run mode. Returns what would happen, no DB writes.
|
|
1858
|
+
preview: z2.boolean().optional().describe("If true, validates all captures without writing. Returns what would happen. Default false.")
|
|
1854
1859
|
});
|
|
1855
1860
|
var captureClassifierSchema = z2.object({
|
|
1856
1861
|
enabled: z2.boolean(),
|
|
@@ -1864,7 +1869,9 @@ var captureClassifierSchema = z2.object({
|
|
|
1864
1869
|
z2.object({
|
|
1865
1870
|
collection: z2.string(),
|
|
1866
1871
|
signalScore: z2.number().optional(),
|
|
1867
|
-
confidence: z2.number()
|
|
1872
|
+
confidence: z2.number(),
|
|
1873
|
+
/** WP-316 S2: required-field cost — how many fields the agent must supply for this collection. */
|
|
1874
|
+
requiredFieldCount: z2.number().optional()
|
|
1868
1875
|
})
|
|
1869
1876
|
),
|
|
1870
1877
|
agentProvidedCollection: z2.string().optional(),
|
|
@@ -1922,7 +1929,17 @@ function buildLowConfidenceResult(resolved, classifierMeta) {
|
|
|
1922
1929
|
{ collection: resolved.collection, confidence: resolved.confidence },
|
|
1923
1930
|
...resolved.alternatives
|
|
1924
1931
|
];
|
|
1925
|
-
const
|
|
1932
|
+
const candidateFieldCounts = /* @__PURE__ */ new Map();
|
|
1933
|
+
for (const c of classifierMeta.candidates) {
|
|
1934
|
+
if (c.requiredFieldCount !== void 0) {
|
|
1935
|
+
candidateFieldCounts.set(c.collection, c.requiredFieldCount);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
const suggestions = allCandidates.map((c) => {
|
|
1939
|
+
const fieldCost = candidateFieldCounts.get(c.collection);
|
|
1940
|
+
const fieldNote = fieldCost !== void 0 ? `, ${fieldCost} required field${fieldCost === 1 ? "" : "s"}` : "";
|
|
1941
|
+
return `- \`${c.collection}\` (${c.confidence}% confidence${fieldNote})`;
|
|
1942
|
+
}).join("\n");
|
|
1926
1943
|
const textBody = `Low confidence classification (${resolved.confidence}%, classified by ${resolved.classifiedBy}).
|
|
1927
1944
|
|
|
1928
1945
|
Predicted: \`${resolved.collection}\`
|
|
@@ -1966,6 +1983,19 @@ function buildClassifierMeta(resolved, overrides = {}) {
|
|
|
1966
1983
|
...overrides
|
|
1967
1984
|
};
|
|
1968
1985
|
}
|
|
1986
|
+
async function enrichCandidatesWithFieldCounts(meta) {
|
|
1987
|
+
try {
|
|
1988
|
+
const cols = await getCollections();
|
|
1989
|
+
const reqBySlug = new Map(
|
|
1990
|
+
cols.map((c) => [c.slug, (c.fields ?? []).filter((f) => f.required === true).length])
|
|
1991
|
+
);
|
|
1992
|
+
meta.candidates = meta.candidates.map((c) => ({
|
|
1993
|
+
...c,
|
|
1994
|
+
requiredFieldCount: reqBySlug.get(c.collection) ?? 0
|
|
1995
|
+
}));
|
|
1996
|
+
} catch {
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1969
1999
|
function emitClassificationTelemetry(resolved, workspaceId, opts) {
|
|
1970
2000
|
const topAlt = resolved.alternatives?.[0] ?? null;
|
|
1971
2001
|
trackCollectionClassified(workspaceId, {
|
|
@@ -2001,6 +2031,7 @@ async function resolveCaptureCollection(params) {
|
|
|
2001
2031
|
overrideCommand: `capture collection="${resolved2.collection}"`
|
|
2002
2032
|
}
|
|
2003
2033
|
});
|
|
2034
|
+
await enrichCandidatesWithFieldCounts(classifierMeta2);
|
|
2004
2035
|
emitClassificationTelemetry(resolved2, workspaceId, {
|
|
2005
2036
|
explicitCollectionProvided: true,
|
|
2006
2037
|
autoRouted: false
|
|
@@ -2015,6 +2046,14 @@ async function resolveCaptureCollection(params) {
|
|
|
2015
2046
|
explicitCollectionProvided: true,
|
|
2016
2047
|
outcome: "fallback"
|
|
2017
2048
|
});
|
|
2049
|
+
const agentInCandidates = resolved2.alternatives.some((a) => a.collection === collection) || resolved2.collection === collection;
|
|
2050
|
+
trackClassifierDivergence(workspaceId, {
|
|
2051
|
+
classifier_collection: resolved2.collection,
|
|
2052
|
+
agent_collection: collection,
|
|
2053
|
+
classifier_confidence: resolved2.confidence,
|
|
2054
|
+
classifier_tier: resolved2.tier,
|
|
2055
|
+
agent_in_candidates: agentInCandidates
|
|
2056
|
+
});
|
|
2018
2057
|
}
|
|
2019
2058
|
return { resolvedCollection: collection, classifierMeta: classifierMeta2 };
|
|
2020
2059
|
}
|
|
@@ -2051,6 +2090,7 @@ async function resolveCaptureCollection(params) {
|
|
|
2051
2090
|
}
|
|
2052
2091
|
const autoRoute = resolved.tier !== "low";
|
|
2053
2092
|
const classifierMeta = buildClassifierMeta(resolved, { autoRouted: autoRoute });
|
|
2093
|
+
await enrichCandidatesWithFieldCounts(classifierMeta);
|
|
2054
2094
|
emitClassificationTelemetry(resolved, workspaceId, {
|
|
2055
2095
|
explicitCollectionProvided,
|
|
2056
2096
|
autoRouted: autoRoute
|
|
@@ -2226,7 +2266,7 @@ function registerSmartCaptureTools(server) {
|
|
|
2226
2266
|
inputSchema: captureSchema.shape,
|
|
2227
2267
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
2228
2268
|
},
|
|
2229
|
-
withEnvelope(async ({ collection, name, description, context, entryId, canonicalKey, data: userData, links, autoCommit, sourceRef, sourceExcerpt }) => {
|
|
2269
|
+
withEnvelope(async ({ collection, name, description, context, entryId, canonicalKey, data: userData, links, autoCommit, sourceRef, sourceExcerpt, preview }) => {
|
|
2230
2270
|
requireWriteAccess();
|
|
2231
2271
|
const timingStart = Date.now();
|
|
2232
2272
|
const wsCtx = await getWorkspaceContext();
|
|
@@ -2385,8 +2425,33 @@ Or use \`collections action=list\` to see available collections.`
|
|
|
2385
2425
|
createdBy: agentId ? `agent:${agentId}` : "capture",
|
|
2386
2426
|
sessionId: agentId ?? void 0,
|
|
2387
2427
|
...sourceRef ? { sourceRef } : {},
|
|
2388
|
-
...sourceExcerpt ? { sourceExcerpt } : {}
|
|
2428
|
+
...sourceExcerpt ? { sourceExcerpt } : {},
|
|
2429
|
+
...preview ? { preview: true } : {}
|
|
2389
2430
|
});
|
|
2431
|
+
if (result?.preview) {
|
|
2432
|
+
const previewEnvelope = success(
|
|
2433
|
+
`Preview: would capture "${name}" \u2014 no DB writes`,
|
|
2434
|
+
{
|
|
2435
|
+
entryId: result.entryId,
|
|
2436
|
+
name,
|
|
2437
|
+
collection: resolvedCollection,
|
|
2438
|
+
outcome: "preview",
|
|
2439
|
+
warnings: result.warnings ?? []
|
|
2440
|
+
},
|
|
2441
|
+
[{ tool: "capture", description: "Capture for real", parameters: { collection: resolvedCollection, name, description } }]
|
|
2442
|
+
);
|
|
2443
|
+
if (result.contract) {
|
|
2444
|
+
previewEnvelope.contract = result.contract;
|
|
2445
|
+
}
|
|
2446
|
+
return {
|
|
2447
|
+
content: [{ type: "text", text: `# Preview: would capture "${name}" [${resolvedCollection}]
|
|
2448
|
+
|
|
2449
|
+
No DB writes \u2014 call without \`preview:true\` to capture for real.${result.warnings?.length ? `
|
|
2450
|
+
|
|
2451
|
+
**Warnings:** ${result.warnings.join("; ")}` : ""}` }],
|
|
2452
|
+
structuredContent: previewEnvelope
|
|
2453
|
+
};
|
|
2454
|
+
}
|
|
2390
2455
|
internalId = result.docId;
|
|
2391
2456
|
finalEntryId = result.entryId;
|
|
2392
2457
|
entryWarnings.push(...result.warnings ?? []);
|
|
@@ -2468,9 +2533,9 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
2468
2533
|
if (linksSuggested.length >= MAX_SUGGESTIONS) break;
|
|
2469
2534
|
if (autoTargetIds.has(c.entryId)) continue;
|
|
2470
2535
|
if (c.confidence < 10) continue;
|
|
2471
|
-
const
|
|
2536
|
+
const preview2 = extractPreview(c.data, 80);
|
|
2472
2537
|
const reason = c.confidence >= AUTO_LINK_CONFIDENCE_THRESHOLD ? "high relevance (already linked)" : `"${c.name.toLowerCase().split(/\s+/).filter((w) => `${name} ${description}`.toLowerCase().includes(w) && w.length > 3).slice(0, 2).join('", "')}" appears in content`;
|
|
2473
|
-
linksSuggested.push({ entryId: c.entryId, name: c.name, collection: c.collSlug, reason, preview });
|
|
2538
|
+
linksSuggested.push({ entryId: c.entryId, name: c.name, collection: c.collSlug, reason, preview: preview2 });
|
|
2474
2539
|
}
|
|
2475
2540
|
conflictCandidates = candidates.filter((c) => c.entryId && c.entryId !== finalEntryId).slice(0, 3).map((c) => ({ entryId: c.entryId, name: c.name, collection: c.collSlug }));
|
|
2476
2541
|
}
|
|
@@ -2701,8 +2766,8 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
2701
2766
|
lines.push("## Suggested links (review and use `relations action=create`)");
|
|
2702
2767
|
for (let i = 0; i < linksSuggested.length; i++) {
|
|
2703
2768
|
const s = linksSuggested[i];
|
|
2704
|
-
const
|
|
2705
|
-
lines.push(`${i + 1}. **${s.entryId ?? "(no ID)"}**: ${s.name} [${s.collection}]${
|
|
2769
|
+
const preview2 = s.preview ? ` \u2014 ${s.preview}` : "";
|
|
2770
|
+
lines.push(`${i + 1}. **${s.entryId ?? "(no ID)"}**: ${s.name} [${s.collection}]${preview2}`);
|
|
2706
2771
|
}
|
|
2707
2772
|
}
|
|
2708
2773
|
lines.push("");
|
|
@@ -2902,7 +2967,7 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
2902
2967
|
inputSchema: batchCaptureSchema.shape,
|
|
2903
2968
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
2904
2969
|
},
|
|
2905
|
-
withEnvelope(async ({ entries, autoCommit }) => {
|
|
2970
|
+
withEnvelope(async ({ entries, autoCommit, preview }) => {
|
|
2906
2971
|
requireWriteAccess();
|
|
2907
2972
|
const batchTimingStart = Date.now();
|
|
2908
2973
|
const agentId = getAgentSessionId();
|
|
@@ -3082,7 +3147,8 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
|
|
|
3082
3147
|
sessionId: agentId ?? void 0,
|
|
3083
3148
|
canonicalKey: entry.canonicalKey ?? void 0,
|
|
3084
3149
|
...entry.sourceRef ? { sourceRef: entry.sourceRef } : {},
|
|
3085
|
-
...entry.sourceExcerpt ? { sourceExcerpt: entry.sourceExcerpt } : {}
|
|
3150
|
+
...entry.sourceExcerpt ? { sourceExcerpt: entry.sourceExcerpt } : {},
|
|
3151
|
+
...preview ? { preview: true } : {}
|
|
3086
3152
|
});
|
|
3087
3153
|
const internalId = result.docId;
|
|
3088
3154
|
const finalEntryId = result.entryId;
|
|
@@ -3669,7 +3735,9 @@ var getHistorySchema = z3.object({
|
|
|
3669
3735
|
entryId: z3.string().describe("Entry ID, e.g. 'T-SUPPLIER', 'BR-001'")
|
|
3670
3736
|
});
|
|
3671
3737
|
var commitEntrySchema = z3.object({
|
|
3672
|
-
entryId: z3.string().describe("Entry ID to commit, e.g. 'TEN-abc123', 'GT-019'")
|
|
3738
|
+
entryId: z3.string().describe("Entry ID to commit, e.g. 'TEN-abc123', 'GT-019'"),
|
|
3739
|
+
// WP-316 S3: Preview gate — dry-run mode. Returns would-succeed result, no DB writes.
|
|
3740
|
+
preview: z3.boolean().optional().describe("If true, validates the commit without writing. Returns what would happen. Default false.")
|
|
3673
3741
|
});
|
|
3674
3742
|
function registerKnowledgeTools(server) {
|
|
3675
3743
|
const updateTool = server.registerTool(
|
|
@@ -3838,7 +3906,7 @@ ${formatted}` }],
|
|
|
3838
3906
|
inputSchema: commitEntrySchema,
|
|
3839
3907
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
3840
3908
|
},
|
|
3841
|
-
withEnvelope(async ({ entryId }) => {
|
|
3909
|
+
withEnvelope(async ({ entryId, preview }) => {
|
|
3842
3910
|
requireWriteAccess();
|
|
3843
3911
|
const entry = await mcpQuery("chain.getEntry", { entryId });
|
|
3844
3912
|
if (!entry) {
|
|
@@ -3901,7 +3969,8 @@ ${formatted}` }],
|
|
|
3901
3969
|
result = await mcpMutation("chain.commitEntry", {
|
|
3902
3970
|
entryId,
|
|
3903
3971
|
author: getAgentSessionId() ? `agent:${getAgentSessionId()}` : void 0,
|
|
3904
|
-
sessionId: getAgentSessionId() ?? void 0
|
|
3972
|
+
sessionId: getAgentSessionId() ?? void 0,
|
|
3973
|
+
...preview ? { preview: true } : {}
|
|
3905
3974
|
});
|
|
3906
3975
|
} catch (commitErr) {
|
|
3907
3976
|
const errCode = commitErr?.code;
|
|
@@ -3920,6 +3989,30 @@ ${formatted}` }],
|
|
|
3920
3989
|
}
|
|
3921
3990
|
throw commitErr;
|
|
3922
3991
|
}
|
|
3992
|
+
if (result?.preview) {
|
|
3993
|
+
const previewEnvelope = success(
|
|
3994
|
+
`Preview: would commit ${entryId} \u2014 no DB writes`,
|
|
3995
|
+
{
|
|
3996
|
+
entryId,
|
|
3997
|
+
name: entry.name,
|
|
3998
|
+
outcome: "preview",
|
|
3999
|
+
currentStatus: result.currentStatus,
|
|
4000
|
+
wouldSetStatus: result.wouldSetStatus
|
|
4001
|
+
},
|
|
4002
|
+
[{ tool: "commit-entry", description: "Commit for real", parameters: { entryId } }]
|
|
4003
|
+
);
|
|
4004
|
+
if (result.contract) {
|
|
4005
|
+
previewEnvelope.contract = result.contract;
|
|
4006
|
+
}
|
|
4007
|
+
return {
|
|
4008
|
+
content: [{ type: "text", text: `# Preview: would commit ${entryId}
|
|
4009
|
+
|
|
4010
|
+
Current status: \`${result.currentStatus}\` \u2192 would become \`${result.wouldSetStatus}\`.
|
|
4011
|
+
|
|
4012
|
+
No DB writes \u2014 call without \`preview:true\` to commit for real.` }],
|
|
4013
|
+
structuredContent: previewEnvelope
|
|
4014
|
+
};
|
|
4015
|
+
}
|
|
3923
4016
|
const docId = result?._id ?? entry._id;
|
|
3924
4017
|
const wsCtx = await getWorkspaceContext();
|
|
3925
4018
|
const isProposal = result?.status === "proposal_created";
|
|
@@ -4794,7 +4887,9 @@ var relationsSchema = z6.object({
|
|
|
4794
4887
|
from: z6.string(),
|
|
4795
4888
|
to: z6.string(),
|
|
4796
4889
|
type: z6.string()
|
|
4797
|
-
})).min(1).max(20).optional().describe("Array of relations for batch-create")
|
|
4890
|
+
})).min(1).max(20).optional().describe("Array of relations for batch-create"),
|
|
4891
|
+
// WP-316 S3: Preview gate — dry-run mode for action=create.
|
|
4892
|
+
preview: z6.boolean().optional().describe("If true, validates the relation without writing. Returns what would happen. Default false. Only applies to action=create.")
|
|
4798
4893
|
});
|
|
4799
4894
|
function registerRelationsTools(server) {
|
|
4800
4895
|
const tool = server.registerTool(
|
|
@@ -4808,13 +4903,13 @@ function registerRelationsTools(server) {
|
|
|
4808
4903
|
withEnvelope(async (args) => {
|
|
4809
4904
|
const parsed = parseOrFail(relationsSchema, args);
|
|
4810
4905
|
if (!parsed.ok) return parsed.result;
|
|
4811
|
-
const { action, from, to, type, score, relations } = parsed.data;
|
|
4906
|
+
const { action, from, to, type, score, relations, preview } = parsed.data;
|
|
4812
4907
|
return runWithToolContext({ tool: "relations", action }, async () => {
|
|
4813
4908
|
if (action === "create") {
|
|
4814
4909
|
if (!from || !to || !type) {
|
|
4815
4910
|
return validationResult("from, to, and type are required when action is 'create'.");
|
|
4816
4911
|
}
|
|
4817
|
-
return handleCreate(from, to, type, score);
|
|
4912
|
+
return handleCreate(from, to, type, score, preview);
|
|
4818
4913
|
}
|
|
4819
4914
|
if (action === "batch-create") {
|
|
4820
4915
|
if (!relations || relations.length === 0) {
|
|
@@ -4840,7 +4935,7 @@ function registerRelationsTools(server) {
|
|
|
4840
4935
|
);
|
|
4841
4936
|
trackWriteTool(tool);
|
|
4842
4937
|
}
|
|
4843
|
-
async function handleCreate(from, to, type, score) {
|
|
4938
|
+
async function handleCreate(from, to, type, score, preview) {
|
|
4844
4939
|
requireWriteAccess();
|
|
4845
4940
|
const agentSessionId = getAgentSessionId();
|
|
4846
4941
|
const result = await mcpMutation("chain.createEntryRelation", {
|
|
@@ -4848,8 +4943,31 @@ async function handleCreate(from, to, type, score) {
|
|
|
4848
4943
|
toEntryId: to,
|
|
4849
4944
|
type,
|
|
4850
4945
|
suggestionScore: score ?? void 0,
|
|
4851
|
-
sessionId: agentSessionId ?? void 0
|
|
4946
|
+
sessionId: agentSessionId ?? void 0,
|
|
4947
|
+
...preview ? { preview: true } : {}
|
|
4852
4948
|
});
|
|
4949
|
+
if (result?.preview) {
|
|
4950
|
+
const suggested2 = result.suggestedType;
|
|
4951
|
+
const suggestedWithPosture2 = suggested2 ? { ...suggested2, governancePosture: suggested2.type === "governs" ? "requires_consent" : "direct" } : void 0;
|
|
4952
|
+
return {
|
|
4953
|
+
content: [{ type: "text", text: `# Preview: would relate ${from} \u2192 ${to} (${type})
|
|
4954
|
+
|
|
4955
|
+
No DB writes \u2014 call without \`preview:true\` to create for real.${suggestedWithPosture2 ? `
|
|
4956
|
+
|
|
4957
|
+
**Type suggestion:** \`${suggestedWithPosture2.type}\` may be more precise (${suggestedWithPosture2.confidence}% confidence). Governance: ${suggestedWithPosture2.governancePosture}.` : ""}` }],
|
|
4958
|
+
structuredContent: success(
|
|
4959
|
+
`Preview: would relate ${from} \u2192 ${to} (${type}) \u2014 no DB writes`,
|
|
4960
|
+
{
|
|
4961
|
+
status: "preview",
|
|
4962
|
+
from,
|
|
4963
|
+
to,
|
|
4964
|
+
type,
|
|
4965
|
+
...suggestedWithPosture2 && { suggestedType: suggestedWithPosture2 }
|
|
4966
|
+
},
|
|
4967
|
+
[{ tool: "relations", description: "Create for real", parameters: { action: "create", from, to, type } }]
|
|
4968
|
+
)
|
|
4969
|
+
};
|
|
4970
|
+
}
|
|
4853
4971
|
const wsCtx = await getWorkspaceContext();
|
|
4854
4972
|
if (result?.status === "proposal_created") {
|
|
4855
4973
|
const existingNote = result.existing ? " (existing proposal reused)" : "";
|
|
@@ -4880,11 +4998,12 @@ The relation was **not applied** \u2014 it will be created when the proposal is
|
|
|
4880
4998
|
`**Workspace:** ${wsCtx.workspaceSlug} (${wsCtx.workspaceId})`
|
|
4881
4999
|
];
|
|
4882
5000
|
const suggested = result?.suggestedType;
|
|
4883
|
-
|
|
5001
|
+
const suggestedWithPosture = suggested ? { ...suggested, governancePosture: suggested.type === "governs" ? "requires_consent" : "direct" } : void 0;
|
|
5002
|
+
if (suggestedWithPosture) {
|
|
4884
5003
|
lines.push("");
|
|
4885
|
-
lines.push(`**Type suggestion:** \`${
|
|
4886
|
-
lines.push(`_${
|
|
4887
|
-
lines.push(`To use instead: \`relations action=create from="${from}" to="${to}" type="${
|
|
5004
|
+
lines.push(`**Type suggestion:** \`${suggestedWithPosture.type}\` may be more precise (${suggestedWithPosture.confidence}% confidence). Governance: ${suggestedWithPosture.governancePosture}.`);
|
|
5005
|
+
lines.push(`_${suggestedWithPosture.reasoning}_`);
|
|
5006
|
+
lines.push(`To use instead: \`relations action=create from="${from}" to="${to}" type="${suggestedWithPosture.type}"\``);
|
|
4888
5007
|
}
|
|
4889
5008
|
return {
|
|
4890
5009
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
@@ -4895,7 +5014,7 @@ The relation was **not applied** \u2014 it will be created when the proposal is
|
|
|
4895
5014
|
from,
|
|
4896
5015
|
to,
|
|
4897
5016
|
type,
|
|
4898
|
-
...
|
|
5017
|
+
...suggestedWithPosture && { suggestedType: suggestedWithPosture }
|
|
4899
5018
|
},
|
|
4900
5019
|
[{ tool: "graph", description: "See connections", parameters: { action: "find", entryId: from } }]
|
|
4901
5020
|
)
|
|
@@ -15520,4 +15639,4 @@ export {
|
|
|
15520
15639
|
SERVER_VERSION,
|
|
15521
15640
|
createProductBrainServer
|
|
15522
15641
|
};
|
|
15523
|
-
//# sourceMappingURL=chunk-
|
|
15642
|
+
//# sourceMappingURL=chunk-LKUFRQUO.js.map
|