@productbrain/mcp 0.0.1-beta.11 → 0.0.1-beta.13
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-B56TXWX2.js → chunk-4ETXQ24K.js} +300 -62
- package/dist/chunk-4ETXQ24K.js.map +1 -0
- package/dist/chunk-JIJC25ZP.js +4530 -0
- package/dist/chunk-JIJC25ZP.js.map +1 -0
- package/dist/cli/index.js +1 -1
- package/dist/http.js +374 -0
- package/dist/http.js.map +1 -0
- package/dist/index.js +10 -4440
- package/dist/index.js.map +1 -1
- package/dist/{setup-XXUPPFF2.js → setup-GZ5OZ5OP.js} +3 -5
- package/dist/{setup-XXUPPFF2.js.map → setup-GZ5OZ5OP.js.map} +1 -1
- package/dist/{smart-capture-LIEVNQJV.js → smart-capture-LD5DEUCX.js} +2 -2
- package/package.json +4 -1
- package/dist/chunk-B56TXWX2.js.map +0 -1
- /package/dist/{smart-capture-LIEVNQJV.js.map → smart-capture-LD5DEUCX.js.map} +0 -0
|
@@ -5,79 +5,149 @@ import {
|
|
|
5
5
|
// src/tools/smart-capture.ts
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
|
|
8
|
+
// src/auth.ts
|
|
9
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
10
|
+
var requestStore = new AsyncLocalStorage();
|
|
11
|
+
function runWithAuth(auth, fn) {
|
|
12
|
+
return requestStore.run(auth, fn);
|
|
13
|
+
}
|
|
14
|
+
function getRequestApiKey() {
|
|
15
|
+
return requestStore.getStore()?.apiKey;
|
|
16
|
+
}
|
|
17
|
+
var SESSION_TTL_MS = 30 * 60 * 1e3;
|
|
18
|
+
var MAX_KEYS = 100;
|
|
19
|
+
var keyStateMap = /* @__PURE__ */ new Map();
|
|
20
|
+
function newKeyState() {
|
|
21
|
+
return {
|
|
22
|
+
workspaceId: null,
|
|
23
|
+
workspaceSlug: null,
|
|
24
|
+
workspaceName: null,
|
|
25
|
+
workspaceCreatedAt: null,
|
|
26
|
+
agentSessionId: null,
|
|
27
|
+
apiKeyId: null,
|
|
28
|
+
apiKeyScope: "readwrite",
|
|
29
|
+
sessionOriented: false,
|
|
30
|
+
sessionClosed: false,
|
|
31
|
+
lastAccess: Date.now()
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function getKeyState(apiKey) {
|
|
35
|
+
let s = keyStateMap.get(apiKey);
|
|
36
|
+
if (!s) {
|
|
37
|
+
s = newKeyState();
|
|
38
|
+
keyStateMap.set(apiKey, s);
|
|
39
|
+
evictStale();
|
|
40
|
+
}
|
|
41
|
+
s.lastAccess = Date.now();
|
|
42
|
+
return s;
|
|
43
|
+
}
|
|
44
|
+
function evictStale() {
|
|
45
|
+
if (keyStateMap.size <= MAX_KEYS) return;
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
for (const [key, s] of keyStateMap) {
|
|
48
|
+
if (now - s.lastAccess > SESSION_TTL_MS) keyStateMap.delete(key);
|
|
49
|
+
}
|
|
50
|
+
if (keyStateMap.size > MAX_KEYS) {
|
|
51
|
+
const sorted = [...keyStateMap.entries()].sort((a, b) => a[1].lastAccess - b[1].lastAccess);
|
|
52
|
+
for (let i = 0; i < sorted.length - MAX_KEYS; i++) {
|
|
53
|
+
keyStateMap.delete(sorted[i][0]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
8
58
|
// src/client.ts
|
|
9
59
|
var DEFAULT_CLOUD_URL = "https://trustworthy-kangaroo-277.convex.site";
|
|
10
|
-
var
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
60
|
+
var _stdioState = {
|
|
61
|
+
workspaceId: null,
|
|
62
|
+
workspaceSlug: null,
|
|
63
|
+
workspaceName: null,
|
|
64
|
+
workspaceCreatedAt: null,
|
|
65
|
+
agentSessionId: null,
|
|
66
|
+
apiKeyId: null,
|
|
67
|
+
apiKeyScope: "readwrite",
|
|
68
|
+
sessionOriented: false,
|
|
69
|
+
sessionClosed: false,
|
|
70
|
+
lastAccess: 0
|
|
71
|
+
};
|
|
72
|
+
function state() {
|
|
73
|
+
const reqKey = getRequestApiKey();
|
|
74
|
+
if (reqKey) return getKeyState(reqKey);
|
|
75
|
+
return _stdioState;
|
|
76
|
+
}
|
|
77
|
+
function getActiveApiKey() {
|
|
78
|
+
const fromRequest = getRequestApiKey();
|
|
79
|
+
if (fromRequest) return fromRequest;
|
|
80
|
+
const fromEnv = process.env.PRODUCTBRAIN_API_KEY;
|
|
81
|
+
if (!fromEnv) throw new Error("No API key available \u2014 set PRODUCTBRAIN_API_KEY or provide Bearer token");
|
|
82
|
+
return fromEnv;
|
|
83
|
+
}
|
|
19
84
|
function getAgentSessionId() {
|
|
20
|
-
return
|
|
85
|
+
return state().agentSessionId;
|
|
21
86
|
}
|
|
22
87
|
function isSessionOriented() {
|
|
23
|
-
return sessionOriented;
|
|
88
|
+
return state().sessionOriented;
|
|
24
89
|
}
|
|
25
90
|
function setSessionOriented(value) {
|
|
26
|
-
sessionOriented = value;
|
|
91
|
+
state().sessionOriented = value;
|
|
27
92
|
}
|
|
28
93
|
async function startAgentSession() {
|
|
29
94
|
const workspaceId = await getWorkspaceId();
|
|
30
|
-
|
|
95
|
+
const s = state();
|
|
96
|
+
if (!s.apiKeyId) {
|
|
31
97
|
throw new Error("Cannot start session: API key ID not resolved. Ensure workspace resolution completed.");
|
|
32
98
|
}
|
|
33
99
|
const result = await mcpCall("agent.startSession", {
|
|
34
100
|
workspaceId,
|
|
35
|
-
apiKeyId:
|
|
101
|
+
apiKeyId: s.apiKeyId
|
|
36
102
|
});
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
sessionOriented = false;
|
|
40
|
-
sessionClosed = false;
|
|
103
|
+
s.agentSessionId = result.sessionId;
|
|
104
|
+
s.apiKeyScope = result.toolsScope;
|
|
105
|
+
s.sessionOriented = false;
|
|
106
|
+
s.sessionClosed = false;
|
|
41
107
|
return result;
|
|
42
108
|
}
|
|
43
109
|
async function closeAgentSession() {
|
|
44
|
-
|
|
110
|
+
const s = state();
|
|
111
|
+
if (!s.agentSessionId) return;
|
|
45
112
|
try {
|
|
46
113
|
await mcpCall("agent.closeSession", {
|
|
47
|
-
sessionId:
|
|
114
|
+
sessionId: s.agentSessionId,
|
|
48
115
|
status: "closed"
|
|
49
116
|
});
|
|
50
117
|
} finally {
|
|
51
|
-
sessionClosed = true;
|
|
52
|
-
|
|
53
|
-
sessionOriented = false;
|
|
118
|
+
s.sessionClosed = true;
|
|
119
|
+
s.agentSessionId = null;
|
|
120
|
+
s.sessionOriented = false;
|
|
54
121
|
}
|
|
55
122
|
}
|
|
56
123
|
async function orphanAgentSession() {
|
|
57
|
-
|
|
124
|
+
const s = state();
|
|
125
|
+
if (!s.agentSessionId) return;
|
|
58
126
|
try {
|
|
59
127
|
await mcpCall("agent.closeSession", {
|
|
60
|
-
sessionId:
|
|
128
|
+
sessionId: s.agentSessionId,
|
|
61
129
|
status: "orphaned"
|
|
62
130
|
});
|
|
63
131
|
} catch {
|
|
64
132
|
} finally {
|
|
65
|
-
|
|
66
|
-
sessionOriented = false;
|
|
133
|
+
s.agentSessionId = null;
|
|
134
|
+
s.sessionOriented = false;
|
|
67
135
|
}
|
|
68
136
|
}
|
|
69
137
|
function touchSessionActivity() {
|
|
70
|
-
|
|
138
|
+
const s = state();
|
|
139
|
+
if (!s.agentSessionId) return;
|
|
71
140
|
mcpCall("agent.touchSession", {
|
|
72
|
-
sessionId:
|
|
141
|
+
sessionId: s.agentSessionId
|
|
73
142
|
}).catch(() => {
|
|
74
143
|
});
|
|
75
144
|
}
|
|
76
145
|
async function recordSessionActivity(activity) {
|
|
77
|
-
|
|
146
|
+
const s = state();
|
|
147
|
+
if (!s.agentSessionId) return;
|
|
78
148
|
try {
|
|
79
149
|
await mcpCall("agent.recordActivity", {
|
|
80
|
-
sessionId:
|
|
150
|
+
sessionId: s.agentSessionId,
|
|
81
151
|
...activity
|
|
82
152
|
});
|
|
83
153
|
} catch {
|
|
@@ -94,6 +164,9 @@ function bootstrap() {
|
|
|
94
164
|
}
|
|
95
165
|
process.env.CONVEX_SITE_URL ??= process.env.PRODUCTBRAIN_URL ?? DEFAULT_CLOUD_URL;
|
|
96
166
|
}
|
|
167
|
+
function bootstrapHttp() {
|
|
168
|
+
process.env.CONVEX_SITE_URL ??= process.env.PRODUCTBRAIN_URL ?? DEFAULT_CLOUD_URL;
|
|
169
|
+
}
|
|
97
170
|
function getEnv(key) {
|
|
98
171
|
const value = process.env[key];
|
|
99
172
|
if (!value) throw new Error(`${key} environment variable is required`);
|
|
@@ -104,7 +177,7 @@ function shouldLogAudit(status) {
|
|
|
104
177
|
}
|
|
105
178
|
function audit(fn, status, durationMs, errorMsg) {
|
|
106
179
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
107
|
-
const workspace =
|
|
180
|
+
const workspace = state().workspaceId ?? "unresolved";
|
|
108
181
|
const entry = { ts, fn, workspace, status, durationMs };
|
|
109
182
|
if (errorMsg) entry.error = errorMsg;
|
|
110
183
|
auditBuffer.push(entry);
|
|
@@ -125,7 +198,7 @@ function getAuditLog() {
|
|
|
125
198
|
}
|
|
126
199
|
async function mcpCall(fn, args = {}) {
|
|
127
200
|
const siteUrl = getEnv("CONVEX_SITE_URL").replace(/\/$/, "");
|
|
128
|
-
const apiKey =
|
|
201
|
+
const apiKey = getActiveApiKey();
|
|
129
202
|
const start = Date.now();
|
|
130
203
|
let res;
|
|
131
204
|
try {
|
|
@@ -147,19 +220,22 @@ async function mcpCall(fn, args = {}) {
|
|
|
147
220
|
throw new Error(`MCP call "${fn}" failed (${res.status}): ${json.error ?? "unknown error"}`);
|
|
148
221
|
}
|
|
149
222
|
audit(fn, "ok", Date.now() - start);
|
|
150
|
-
|
|
223
|
+
const s = state();
|
|
224
|
+
if (s.agentSessionId && fn !== "agent.touchSession" && fn !== "agent.startSession") {
|
|
151
225
|
touchSessionActivity();
|
|
152
226
|
}
|
|
153
227
|
return json.data;
|
|
154
228
|
}
|
|
155
|
-
var
|
|
229
|
+
var resolveInFlightMap = /* @__PURE__ */ new Map();
|
|
156
230
|
async function getWorkspaceId() {
|
|
157
|
-
|
|
158
|
-
if (
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
231
|
+
const s = state();
|
|
232
|
+
if (s.workspaceId) return s.workspaceId;
|
|
233
|
+
const apiKey = getActiveApiKey();
|
|
234
|
+
const existing = resolveInFlightMap.get(apiKey);
|
|
235
|
+
if (existing) return existing;
|
|
236
|
+
const promise = resolveWorkspaceWithRetry().finally(() => resolveInFlightMap.delete(apiKey));
|
|
237
|
+
resolveInFlightMap.set(apiKey, promise);
|
|
238
|
+
return promise;
|
|
163
239
|
}
|
|
164
240
|
async function resolveWorkspaceWithRetry(maxRetries = 2) {
|
|
165
241
|
let lastError = null;
|
|
@@ -171,13 +247,14 @@ async function resolveWorkspaceWithRetry(maxRetries = 2) {
|
|
|
171
247
|
"API key is valid but no workspace is associated. Run `npx productbrain setup` or regenerate your key."
|
|
172
248
|
);
|
|
173
249
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (workspace.
|
|
180
|
-
|
|
250
|
+
const s = state();
|
|
251
|
+
s.workspaceId = workspace._id;
|
|
252
|
+
s.workspaceSlug = workspace.slug;
|
|
253
|
+
s.workspaceName = workspace.name;
|
|
254
|
+
s.workspaceCreatedAt = workspace.createdAt ?? null;
|
|
255
|
+
if (workspace.keyScope) s.apiKeyScope = workspace.keyScope;
|
|
256
|
+
if (workspace.keyId) s.apiKeyId = workspace.keyId;
|
|
257
|
+
return s.workspaceId;
|
|
181
258
|
} catch (err) {
|
|
182
259
|
lastError = err;
|
|
183
260
|
const isTransient = /network error|fetch failed|ECONNREFUSED|ETIMEDOUT/i.test(err.message);
|
|
@@ -194,11 +271,12 @@ async function resolveWorkspaceWithRetry(maxRetries = 2) {
|
|
|
194
271
|
}
|
|
195
272
|
async function getWorkspaceContext() {
|
|
196
273
|
const workspaceId = await getWorkspaceId();
|
|
274
|
+
const s = state();
|
|
197
275
|
return {
|
|
198
276
|
workspaceId,
|
|
199
|
-
workspaceSlug:
|
|
200
|
-
workspaceName:
|
|
201
|
-
createdAt:
|
|
277
|
+
workspaceSlug: s.workspaceSlug ?? "unknown",
|
|
278
|
+
workspaceName: s.workspaceName ?? "unknown",
|
|
279
|
+
createdAt: s.workspaceCreatedAt
|
|
202
280
|
};
|
|
203
281
|
}
|
|
204
282
|
async function mcpQuery(fn, args = {}) {
|
|
@@ -210,36 +288,38 @@ async function mcpMutation(fn, args = {}) {
|
|
|
210
288
|
return mcpCall(fn, { ...args, workspaceId });
|
|
211
289
|
}
|
|
212
290
|
function requireWriteAccess() {
|
|
213
|
-
|
|
291
|
+
const s = state();
|
|
292
|
+
if (!s.agentSessionId) {
|
|
214
293
|
throw new Error(
|
|
215
294
|
"Agent session required for write operations. Call `agent-start` first."
|
|
216
295
|
);
|
|
217
296
|
}
|
|
218
|
-
if (sessionClosed) {
|
|
297
|
+
if (s.sessionClosed) {
|
|
219
298
|
throw new Error(
|
|
220
299
|
"Agent session has been closed. Write tools are no longer available."
|
|
221
300
|
);
|
|
222
301
|
}
|
|
223
|
-
if (!sessionOriented) {
|
|
302
|
+
if (!s.sessionOriented) {
|
|
224
303
|
throw new Error(
|
|
225
304
|
"Orientation required before writing to the Chain. Call 'orient' first."
|
|
226
305
|
);
|
|
227
306
|
}
|
|
228
|
-
if (
|
|
307
|
+
if (s.apiKeyScope === "read") {
|
|
229
308
|
throw new Error(
|
|
230
309
|
"This API key has read-only scope. Write tools are not available."
|
|
231
310
|
);
|
|
232
311
|
}
|
|
233
312
|
}
|
|
234
313
|
async function recoverSessionState() {
|
|
235
|
-
|
|
314
|
+
const s = state();
|
|
315
|
+
if (!s.workspaceId) return;
|
|
236
316
|
try {
|
|
237
|
-
const session = await mcpCall("agent.getActiveSession", { workspaceId:
|
|
317
|
+
const session = await mcpCall("agent.getActiveSession", { workspaceId: s.workspaceId });
|
|
238
318
|
if (session && session.status === "active") {
|
|
239
|
-
|
|
240
|
-
sessionOriented = session.oriented;
|
|
241
|
-
|
|
242
|
-
sessionClosed = false;
|
|
319
|
+
s.agentSessionId = session._id;
|
|
320
|
+
s.sessionOriented = session.oriented;
|
|
321
|
+
s.apiKeyScope = session.toolsScope;
|
|
322
|
+
s.sessionClosed = false;
|
|
243
323
|
}
|
|
244
324
|
} catch {
|
|
245
325
|
}
|
|
@@ -961,6 +1041,162 @@ Use \`get-entry\` to inspect the existing entry, or \`update-entry\` to modify i
|
|
|
961
1041
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
962
1042
|
}
|
|
963
1043
|
);
|
|
1044
|
+
server.registerTool(
|
|
1045
|
+
"batch-capture",
|
|
1046
|
+
{
|
|
1047
|
+
title: "Batch Capture",
|
|
1048
|
+
description: "Create multiple knowledge entries in one call. Ideal for workspace setup, document ingestion, or any scenario where you need to capture many entries at once.\n\nEach entry is created independently \u2014 if one fails, the others still succeed. Returns a compact summary instead of per-entry quality scorecards.\n\nAuto-linking runs per entry but contradiction checks and readiness hints are skipped for speed. Use `quality-check` on individual entries afterward if needed.",
|
|
1049
|
+
inputSchema: {
|
|
1050
|
+
entries: z.array(z.object({
|
|
1051
|
+
collection: z.string().describe("Collection slug"),
|
|
1052
|
+
name: z.string().describe("Display name"),
|
|
1053
|
+
description: z.string().describe("Full context / definition"),
|
|
1054
|
+
entryId: z.string().optional().describe("Optional custom entry ID")
|
|
1055
|
+
})).min(1).max(50).describe("Array of entries to capture")
|
|
1056
|
+
},
|
|
1057
|
+
annotations: { destructiveHint: false }
|
|
1058
|
+
},
|
|
1059
|
+
async ({ entries }) => {
|
|
1060
|
+
requireWriteAccess();
|
|
1061
|
+
const agentId = getAgentSessionId();
|
|
1062
|
+
const createdBy = agentId ? `agent:${agentId}` : "capture";
|
|
1063
|
+
const results = [];
|
|
1064
|
+
const allCollections = await mcpQuery("chain.listCollections");
|
|
1065
|
+
const collCache = /* @__PURE__ */ new Map();
|
|
1066
|
+
for (const c of allCollections) collCache.set(c.slug, c);
|
|
1067
|
+
const collIdToSlug = /* @__PURE__ */ new Map();
|
|
1068
|
+
for (const c of allCollections) collIdToSlug.set(c._id, c.slug);
|
|
1069
|
+
for (const entry of entries) {
|
|
1070
|
+
const profile = PROFILES.get(entry.collection) ?? FALLBACK_PROFILE;
|
|
1071
|
+
const col = collCache.get(entry.collection);
|
|
1072
|
+
if (!col) {
|
|
1073
|
+
results.push({ name: entry.name, collection: entry.collection, entryId: "", ok: false, autoLinks: 0, error: `Collection "${entry.collection}" not found` });
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
1076
|
+
const finalEntryId = entry.entryId ?? generateEntryId(profile.idPrefix);
|
|
1077
|
+
const data = {};
|
|
1078
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1079
|
+
for (const field of col.fields ?? []) {
|
|
1080
|
+
const key = field.key;
|
|
1081
|
+
if (key === profile.descriptionField) {
|
|
1082
|
+
data[key] = entry.description;
|
|
1083
|
+
} else if (field.type === "array" || field.type === "multi-select") {
|
|
1084
|
+
data[key] = [];
|
|
1085
|
+
} else {
|
|
1086
|
+
data[key] = "";
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
for (const def of profile.defaults) {
|
|
1090
|
+
if (def.value === "today") data[def.key] = today;
|
|
1091
|
+
else if (def.value !== "infer") data[def.key] = def.value;
|
|
1092
|
+
}
|
|
1093
|
+
if (profile.inferField) {
|
|
1094
|
+
const inferred = profile.inferField({
|
|
1095
|
+
collection: entry.collection,
|
|
1096
|
+
name: entry.name,
|
|
1097
|
+
description: entry.description,
|
|
1098
|
+
data,
|
|
1099
|
+
entryId: "",
|
|
1100
|
+
linksCreated: [],
|
|
1101
|
+
linksSuggested: [],
|
|
1102
|
+
collectionFields: col.fields ?? []
|
|
1103
|
+
});
|
|
1104
|
+
for (const [key, val] of Object.entries(inferred)) {
|
|
1105
|
+
if (val !== void 0 && val !== "") data[key] = val;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
if (!data[profile.descriptionField] && !data.description && !data.canonical) {
|
|
1109
|
+
data[profile.descriptionField || "description"] = entry.description;
|
|
1110
|
+
}
|
|
1111
|
+
try {
|
|
1112
|
+
await mcpMutation("chain.createEntry", {
|
|
1113
|
+
collectionSlug: entry.collection,
|
|
1114
|
+
entryId: finalEntryId,
|
|
1115
|
+
name: entry.name,
|
|
1116
|
+
status: "draft",
|
|
1117
|
+
data,
|
|
1118
|
+
createdBy
|
|
1119
|
+
});
|
|
1120
|
+
let autoLinkCount = 0;
|
|
1121
|
+
const searchQuery = extractSearchTerms(entry.name, entry.description);
|
|
1122
|
+
if (searchQuery) {
|
|
1123
|
+
try {
|
|
1124
|
+
const searchResults = await mcpQuery("chain.searchEntries", { query: searchQuery });
|
|
1125
|
+
const candidates = (searchResults ?? []).filter((r) => r.entryId !== finalEntryId).map((r) => ({
|
|
1126
|
+
...r,
|
|
1127
|
+
collSlug: collIdToSlug.get(r.collectionId) ?? "unknown",
|
|
1128
|
+
confidence: computeLinkConfidence(r, entry.name, entry.description, entry.collection, collIdToSlug.get(r.collectionId) ?? "unknown")
|
|
1129
|
+
})).sort((a, b) => b.confidence - a.confidence);
|
|
1130
|
+
for (const c of candidates) {
|
|
1131
|
+
if (autoLinkCount >= MAX_AUTO_LINKS) break;
|
|
1132
|
+
if (c.confidence < AUTO_LINK_CONFIDENCE_THRESHOLD) break;
|
|
1133
|
+
if (!c.entryId) continue;
|
|
1134
|
+
const relationType = inferRelationType(entry.collection, c.collSlug, profile);
|
|
1135
|
+
try {
|
|
1136
|
+
await mcpMutation("chain.createEntryRelation", {
|
|
1137
|
+
fromEntryId: finalEntryId,
|
|
1138
|
+
toEntryId: c.entryId,
|
|
1139
|
+
type: relationType
|
|
1140
|
+
});
|
|
1141
|
+
autoLinkCount++;
|
|
1142
|
+
} catch {
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
} catch {
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
results.push({ name: entry.name, collection: entry.collection, entryId: finalEntryId, ok: true, autoLinks: autoLinkCount });
|
|
1149
|
+
await recordSessionActivity({ entryCreated: finalEntryId });
|
|
1150
|
+
} catch (error) {
|
|
1151
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
1152
|
+
results.push({ name: entry.name, collection: entry.collection, entryId: finalEntryId, ok: false, autoLinks: 0, error: msg });
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
const created = results.filter((r) => r.ok);
|
|
1156
|
+
const failed = results.filter((r) => !r.ok);
|
|
1157
|
+
const totalAutoLinks = created.reduce((sum, r) => sum + r.autoLinks, 0);
|
|
1158
|
+
const byCollection = /* @__PURE__ */ new Map();
|
|
1159
|
+
for (const r of created) {
|
|
1160
|
+
byCollection.set(r.collection, (byCollection.get(r.collection) ?? 0) + 1);
|
|
1161
|
+
}
|
|
1162
|
+
const lines = [
|
|
1163
|
+
`# Batch Capture Complete`,
|
|
1164
|
+
`**${created.length}** created, **${failed.length}** failed out of ${entries.length} total.`,
|
|
1165
|
+
`**Auto-links created:** ${totalAutoLinks}`,
|
|
1166
|
+
""
|
|
1167
|
+
];
|
|
1168
|
+
if (byCollection.size > 0) {
|
|
1169
|
+
lines.push("## By Collection");
|
|
1170
|
+
for (const [col, count] of byCollection) {
|
|
1171
|
+
lines.push(`- \`${col}\`: ${count} entries`);
|
|
1172
|
+
}
|
|
1173
|
+
lines.push("");
|
|
1174
|
+
}
|
|
1175
|
+
if (created.length > 0) {
|
|
1176
|
+
lines.push("## Created");
|
|
1177
|
+
for (const r of created) {
|
|
1178
|
+
const linkNote = r.autoLinks > 0 ? ` (${r.autoLinks} auto-links)` : "";
|
|
1179
|
+
lines.push(`- **${r.entryId}**: ${r.name} [${r.collection}]${linkNote}`);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
if (failed.length > 0) {
|
|
1183
|
+
lines.push("");
|
|
1184
|
+
lines.push("## Failed");
|
|
1185
|
+
for (const r of failed) {
|
|
1186
|
+
lines.push(`- ${r.name} [${r.collection}]: _${r.error}_`);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
const entryIds = created.map((r) => r.entryId);
|
|
1190
|
+
if (entryIds.length > 0) {
|
|
1191
|
+
lines.push("");
|
|
1192
|
+
lines.push("## Next Steps");
|
|
1193
|
+
lines.push(`- **Connect:** Run \`suggest-links\` on key entries to build the knowledge graph`);
|
|
1194
|
+
lines.push(`- **Commit:** Use \`commit-entry\` to promote drafts to SSOT`);
|
|
1195
|
+
lines.push(`- **Quality:** Run \`quality-check\` on individual entries to assess completeness`);
|
|
1196
|
+
}
|
|
1197
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
1198
|
+
}
|
|
1199
|
+
);
|
|
964
1200
|
server.registerTool(
|
|
965
1201
|
"quality-check",
|
|
966
1202
|
{
|
|
@@ -1123,6 +1359,7 @@ async function runContradictionCheck(name, description) {
|
|
|
1123
1359
|
}
|
|
1124
1360
|
|
|
1125
1361
|
export {
|
|
1362
|
+
runWithAuth,
|
|
1126
1363
|
getAgentSessionId,
|
|
1127
1364
|
isSessionOriented,
|
|
1128
1365
|
setSessionOriented,
|
|
@@ -1131,6 +1368,7 @@ export {
|
|
|
1131
1368
|
orphanAgentSession,
|
|
1132
1369
|
recordSessionActivity,
|
|
1133
1370
|
bootstrap,
|
|
1371
|
+
bootstrapHttp,
|
|
1134
1372
|
getAuditLog,
|
|
1135
1373
|
mcpCall,
|
|
1136
1374
|
getWorkspaceId,
|
|
@@ -1144,4 +1382,4 @@ export {
|
|
|
1144
1382
|
registerSmartCaptureTools,
|
|
1145
1383
|
runContradictionCheck
|
|
1146
1384
|
};
|
|
1147
|
-
//# sourceMappingURL=chunk-
|
|
1385
|
+
//# sourceMappingURL=chunk-4ETXQ24K.js.map
|