@kaddo/mcp 3.113.0 → 3.114.0

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.
Files changed (2) hide show
  1. package/dist/index.js +26 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -17319,6 +17319,14 @@ ${body}`);
17319
17319
  ${out.join("\n\n")}
17320
17320
  `.replace(/\n{3,}/g, "\n\n");
17321
17321
  }
17322
+ function ensureH1(body, title) {
17323
+ const trimmed = body.trim();
17324
+ const firstMeaningful = trimmed.split(/\r?\n/).find((l2) => l2.trim());
17325
+ if (firstMeaningful && /^#\s+/.test(firstMeaningful.trim())) return trimmed;
17326
+ return `# ${title}
17327
+
17328
+ ${trimmed}`;
17329
+ }
17322
17330
  function serialize(data, body) {
17323
17331
  return matter82.stringify(`
17324
17332
  ${body.trim()}
@@ -17354,6 +17362,7 @@ function createWorkItem(dir, opts) {
17354
17362
  const id = nextWorkItemId(dir);
17355
17363
  const title = intent.split(/\r?\n/)[0].trim().slice(0, 120);
17356
17364
  const today22 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
17365
+ const summary = opts.summary?.trim() || intent;
17357
17366
  const source = opts.source ? { ...opts.source, inferred: false } : { type: "manual", inferred: false };
17358
17367
  const data = {
17359
17368
  type,
@@ -17365,15 +17374,16 @@ function createWorkItem(dir, opts) {
17365
17374
  source,
17366
17375
  generated_by: "kaddo-admin",
17367
17376
  affected_modules: [],
17368
- summary: intent
17377
+ summary
17369
17378
  };
17370
17379
  if (opts.originalSnapshot) data.original_snapshot = opts.originalSnapshot;
17371
17380
  const answers = opts.answers ?? {};
17372
17381
  const hasAnswers = Object.values(answers).some((v) => v?.trim());
17373
- const body = hasAnswers ? captureBody(title, type, answers) : freshBody({
17382
+ const providedBody = opts.body?.trim();
17383
+ const body = providedBody ? ensureH1(providedBody, title) : hasAnswers ? captureBody(title, type, answers) : freshBody({
17374
17384
  title,
17375
17385
  type,
17376
- summary: intent,
17386
+ summary,
17377
17387
  scopeUnknowns: [],
17378
17388
  affectedModules: [],
17379
17389
  moduleCoverage: [],
@@ -18151,15 +18161,21 @@ function extractSections(body) {
18151
18161
  flush();
18152
18162
  return sections;
18153
18163
  }
18164
+ function deriveShortSummary(parsed) {
18165
+ const paragraph = parsed.body.split(/\n{2,}/).map((p) => p.trim()).find((p) => p && !/^#{1,6}\s/.test(p) && !/^>/.test(p) && p !== parsed.title);
18166
+ const base = paragraph ? paragraph.replace(/\s+/g, " ") : parsed.title;
18167
+ return base.length > 280 ? `${base.slice(0, 277).trimEnd()}\u2026` : base;
18168
+ }
18154
18169
  function normalizeImportFields(parsed, opts) {
18155
18170
  const discardedFields = [];
18156
18171
  for (const key of Object.keys(parsed.candidateFields)) {
18157
18172
  if (LIFECYCLE_FIELDS.has(key)) discardedFields.push(key);
18158
18173
  }
18159
18174
  const type = opts.userType ? normalizeType(opts.userType) ?? "feature" : parsed.type ?? "feature";
18160
- const intent = parsed.body && parsed.body !== parsed.title ? `${parsed.title}
18161
-
18162
- ${parsed.body}` : parsed.title;
18175
+ const hasRealBody = !!parsed.body && parsed.body !== parsed.title;
18176
+ const intent = parsed.title;
18177
+ const body = hasRealBody ? parsed.body : void 0;
18178
+ const summary = hasRealBody ? deriveShortSummary(parsed) : parsed.title;
18163
18179
  const source = {
18164
18180
  type: opts.importSource === "chat" ? "chat" : "external",
18165
18181
  imported_at: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
@@ -18167,14 +18183,14 @@ ${parsed.body}` : parsed.title;
18167
18183
  source.source_format = opts.sourceFormat;
18168
18184
  source.source_hash = opts.sourceHash;
18169
18185
  const snapshot = { title: parsed.title };
18170
- if (parsed.summary !== parsed.title) snapshot.description = parsed.summary;
18186
+ if (summary !== parsed.title) snapshot.description = summary;
18171
18187
  if (typeof parsed.candidateFields.type === "string") snapshot.type = parsed.candidateFields.type;
18172
18188
  if (typeof parsed.candidateFields.status === "string") snapshot.status = parsed.candidateFields.status;
18173
18189
  if (Array.isArray(parsed.candidateFields.labels)) {
18174
18190
  const labels = parsed.candidateFields.labels.filter((l2) => typeof l2 === "string");
18175
18191
  if (labels.length > 0) snapshot.labels = labels;
18176
18192
  }
18177
- return { type, intent, source, snapshot, discardedFields };
18193
+ return { type, intent, summary, body, source, snapshot, discardedFields };
18178
18194
  }
18179
18195
  function computeContentHash(raw) {
18180
18196
  return crypto3.createHash("sha256").update(raw.trim(), "utf-8").digest("hex");
@@ -18260,6 +18276,8 @@ function importWorkItem(dir, opts) {
18260
18276
  const result = createWorkItem(dir, {
18261
18277
  intent: normalized.intent,
18262
18278
  type: normalized.type,
18279
+ summary: normalized.summary,
18280
+ body: normalized.body,
18263
18281
  source: normalized.source,
18264
18282
  originalSnapshot: normalized.snapshot
18265
18283
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaddo/mcp",
3
- "version": "3.113.0",
3
+ "version": "3.114.0",
4
4
  "description": "MCP server for Kaddo project knowledge: read-only resources/tools/prompts plus safe derived generation under .kaddo/.",
5
5
  "license": "MIT",
6
6
  "repository": {