@vailent/pulse-mcp 1.7.0 → 1.8.1
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/server.js +113 -14
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -41675,6 +41675,51 @@ function cleanEscapedString(input) {
|
|
|
41675
41675
|
return matched[1].replace(doubleQuoteRegExp, "'");
|
|
41676
41676
|
}
|
|
41677
41677
|
|
|
41678
|
+
// lib/work-item-state.ts
|
|
41679
|
+
var PRE_DEV_PHASES = ["discovery", "framing", "prototyping", "deep_design"];
|
|
41680
|
+
function normalizeWorkItemState(updates, current) {
|
|
41681
|
+
const result = { ...updates };
|
|
41682
|
+
const status = result.status ?? current?.status;
|
|
41683
|
+
const phase = result.phase ?? current?.phase;
|
|
41684
|
+
const track = result.track ?? current?.track;
|
|
41685
|
+
const step = result.implementation_step ?? current?.implementation_step;
|
|
41686
|
+
const hasBlocker = result.has_blocker ?? current?.has_blocker;
|
|
41687
|
+
if (result.status === "shipped") {
|
|
41688
|
+
result.track = "dev";
|
|
41689
|
+
result.phase = "implementation";
|
|
41690
|
+
result.implementation_step = "deploy";
|
|
41691
|
+
result.has_blocker = false;
|
|
41692
|
+
result.blocker_text = null;
|
|
41693
|
+
}
|
|
41694
|
+
if (result.status === "missed" || result.status === "killed" || result.status === "resolved") {
|
|
41695
|
+
result.has_blocker = false;
|
|
41696
|
+
result.blocker_text = null;
|
|
41697
|
+
}
|
|
41698
|
+
if ("phase" in result && result.phase !== "implementation") {
|
|
41699
|
+
result.implementation_step = null;
|
|
41700
|
+
if (PRE_DEV_PHASES.includes(result.phase)) {
|
|
41701
|
+
result.track = "pre_dev";
|
|
41702
|
+
}
|
|
41703
|
+
}
|
|
41704
|
+
if (result.phase === "implementation") {
|
|
41705
|
+
result.track = "dev";
|
|
41706
|
+
const effectiveStep = result.implementation_step ?? current?.implementation_step;
|
|
41707
|
+
if (!effectiveStep && !("implementation_step" in result)) {
|
|
41708
|
+
result.implementation_step = "build";
|
|
41709
|
+
}
|
|
41710
|
+
}
|
|
41711
|
+
if ("implementation_step" in result && result.implementation_step != null) {
|
|
41712
|
+
result.phase = "implementation";
|
|
41713
|
+
result.track = "dev";
|
|
41714
|
+
}
|
|
41715
|
+
if (result.has_blocker === true) {
|
|
41716
|
+
if (status === "shipped" || status === "missed") {
|
|
41717
|
+
result.status = "in_progress";
|
|
41718
|
+
}
|
|
41719
|
+
}
|
|
41720
|
+
return result;
|
|
41721
|
+
}
|
|
41722
|
+
|
|
41678
41723
|
// tools/features.ts
|
|
41679
41724
|
async function handleFeatures(params) {
|
|
41680
41725
|
const supabase = getAdminClient();
|
|
@@ -41758,10 +41803,12 @@ async function handleFeatures(params) {
|
|
|
41758
41803
|
prdFileName: "prd_file_name",
|
|
41759
41804
|
prdSummary: "prd_summary"
|
|
41760
41805
|
};
|
|
41761
|
-
const
|
|
41806
|
+
const raw = { updated_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
41762
41807
|
for (const [key, col] of Object.entries(allowedFields)) {
|
|
41763
|
-
if (params[key] !== void 0)
|
|
41808
|
+
if (params[key] !== void 0) raw[col] = params[key];
|
|
41764
41809
|
}
|
|
41810
|
+
const { data: current } = await supabase.from("work_items").select("status, phase, track, implementation_step, has_blocker").eq("id", featureId).single();
|
|
41811
|
+
const updates = normalizeWorkItemState(raw, current || void 0);
|
|
41765
41812
|
const { error: error2 } = await supabase.from("work_items").update(updates).eq("id", featureId);
|
|
41766
41813
|
if (error2) return err(error2.message);
|
|
41767
41814
|
return ok({ id: featureId, ...updates }, `Updated feature ${featureId}`);
|
|
@@ -41907,6 +41954,7 @@ async function handleRequests(params) {
|
|
|
41907
41954
|
const title = params.title;
|
|
41908
41955
|
if (!podId || !title?.trim()) return err("podId and title are required", "MISSING_PARAM");
|
|
41909
41956
|
const { data, error: error2 } = await supabase.from("work_items").insert({
|
|
41957
|
+
id: `f-${Date.now().toString(36)}`,
|
|
41910
41958
|
title: title.trim(),
|
|
41911
41959
|
description: params.description || null,
|
|
41912
41960
|
pod_id: podId,
|
|
@@ -41986,6 +42034,7 @@ async function handleBugs(params) {
|
|
|
41986
42034
|
const title = params.title;
|
|
41987
42035
|
if (!podId || !title?.trim()) return err("podId and title are required", "MISSING_PARAM");
|
|
41988
42036
|
const { data, error: error2 } = await supabase.from("work_items").insert({
|
|
42037
|
+
id: `f-${Date.now().toString(36)}`,
|
|
41989
42038
|
title: title.trim(),
|
|
41990
42039
|
description: params.description || null,
|
|
41991
42040
|
pod_id: podId,
|
|
@@ -42001,20 +42050,21 @@ async function handleBugs(params) {
|
|
|
42001
42050
|
case "update": {
|
|
42002
42051
|
const bugId = params.bugId;
|
|
42003
42052
|
if (!bugId) return err("bugId is required", "MISSING_PARAM");
|
|
42004
|
-
const { data: currentBug } = await supabase.from("work_items").select("status, week_start, title, pod_id").eq("id", bugId).single();
|
|
42005
|
-
const
|
|
42006
|
-
if (params.title !== void 0)
|
|
42007
|
-
if (params.description !== void 0)
|
|
42008
|
-
if (params.priority !== void 0)
|
|
42009
|
-
if (params.status !== void 0)
|
|
42010
|
-
if (params.podId !== void 0)
|
|
42011
|
-
if (params.projectName !== void 0)
|
|
42053
|
+
const { data: currentBug } = await supabase.from("work_items").select("status, phase, track, implementation_step, has_blocker, week_start, title, pod_id").eq("id", bugId).single();
|
|
42054
|
+
const raw = { updated_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
42055
|
+
if (params.title !== void 0) raw.title = params.title;
|
|
42056
|
+
if (params.description !== void 0) raw.description = params.description;
|
|
42057
|
+
if (params.priority !== void 0) raw.priority = params.priority;
|
|
42058
|
+
if (params.status !== void 0) raw.status = params.status;
|
|
42059
|
+
if (params.podId !== void 0) raw.pod_id = params.podId;
|
|
42060
|
+
if (params.projectName !== void 0) raw.project_name = params.projectName;
|
|
42012
42061
|
let autoPromoted = false;
|
|
42013
42062
|
if (currentBug?.status === "open" && !currentBug.week_start && !params.status) {
|
|
42014
|
-
|
|
42015
|
-
|
|
42063
|
+
raw.status = "in_progress";
|
|
42064
|
+
raw.week_start = getCurrentWeekStart();
|
|
42016
42065
|
autoPromoted = true;
|
|
42017
42066
|
}
|
|
42067
|
+
const updates = normalizeWorkItemState(raw, currentBug || void 0);
|
|
42018
42068
|
const { error: error2 } = await supabase.from("work_items").update(updates).eq("id", bugId);
|
|
42019
42069
|
if (error2) return err(error2.message);
|
|
42020
42070
|
if (autoPromoted) {
|
|
@@ -47230,6 +47280,45 @@ async function handleTeam(params) {
|
|
|
47230
47280
|
}
|
|
47231
47281
|
}
|
|
47232
47282
|
|
|
47283
|
+
// tools/search.ts
|
|
47284
|
+
async function handleSearch(params) {
|
|
47285
|
+
const text = params.text;
|
|
47286
|
+
if (!text?.trim()) return err("text is required", "MISSING_PARAM");
|
|
47287
|
+
const limit = params.limit || 5;
|
|
47288
|
+
const threshold = params.threshold || 0.78;
|
|
47289
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
47290
|
+
if (!apiKey) return err("OPENAI_API_KEY not configured \u2014 cannot perform similarity search", "CONFIG_ERROR");
|
|
47291
|
+
let embedding;
|
|
47292
|
+
try {
|
|
47293
|
+
const res = await fetch("https://api.openai.com/v1/embeddings", {
|
|
47294
|
+
method: "POST",
|
|
47295
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
47296
|
+
body: JSON.stringify({ model: "text-embedding-3-small", input: text.slice(0, 8e3) })
|
|
47297
|
+
});
|
|
47298
|
+
if (!res.ok) return err(`OpenAI error: ${res.status}`, "API_ERROR");
|
|
47299
|
+
const data2 = await res.json();
|
|
47300
|
+
embedding = data2.data[0].embedding;
|
|
47301
|
+
} catch (e) {
|
|
47302
|
+
return err(`Embedding failed: ${e}`, "API_ERROR");
|
|
47303
|
+
}
|
|
47304
|
+
const supabase = getAdminClient();
|
|
47305
|
+
const { data, error: error2 } = await supabase.rpc("match_work_items", {
|
|
47306
|
+
query_embedding: JSON.stringify(embedding),
|
|
47307
|
+
match_threshold: threshold,
|
|
47308
|
+
match_count: limit
|
|
47309
|
+
});
|
|
47310
|
+
if (error2) return err(error2.message);
|
|
47311
|
+
const results = data || [];
|
|
47312
|
+
return ok(
|
|
47313
|
+
results.map((r) => ({
|
|
47314
|
+
...r,
|
|
47315
|
+
similarity: Math.round(r.similarity * 100) / 100
|
|
47316
|
+
})),
|
|
47317
|
+
`${results.length} similar item(s) found`,
|
|
47318
|
+
results.length
|
|
47319
|
+
);
|
|
47320
|
+
}
|
|
47321
|
+
|
|
47233
47322
|
// server.ts
|
|
47234
47323
|
try {
|
|
47235
47324
|
await import("./config-V5TD57MJ.js");
|
|
@@ -47281,7 +47370,7 @@ server.tool(
|
|
|
47281
47370
|
);
|
|
47282
47371
|
server.tool(
|
|
47283
47372
|
"pulse_features",
|
|
47284
|
-
"Manage features and tasks. Actions: list (filter by pod/workstream/week/status/size), get, create (feature or task via size param), update (phase/step
|
|
47373
|
+
"Manage features and tasks. Actions: list (filter by pod/workstream/week/status/size), get, create (feature or task via size param), update (auto-corrects state: shipped\u2192dev/implementation/deploy, phase changes update track/step), delete, add_note (auto-promotes backlog bugs to this week), reorder.",
|
|
47285
47374
|
{
|
|
47286
47375
|
action: external_exports.enum(["list", "get", "create", "update", "delete", "add_note", "reorder"]),
|
|
47287
47376
|
featureId: external_exports.string().optional().describe("Feature ID"),
|
|
@@ -47349,7 +47438,7 @@ server.tool(
|
|
|
47349
47438
|
);
|
|
47350
47439
|
server.tool(
|
|
47351
47440
|
"pulse_bugs",
|
|
47352
|
-
"Track bugs. Actions: list (open/in_progress bugs by pod), create, update (
|
|
47441
|
+
"Track bugs. Actions: list (open/in_progress bugs by pod), create, update (auto-promotes backlog bugs to this week, auto-corrects state consistency), delete, schedule (set week_start \u2014 auto-promotes open\u2192in_progress).",
|
|
47353
47442
|
{
|
|
47354
47443
|
action: external_exports.enum(["list", "create", "update", "delete", "schedule"]),
|
|
47355
47444
|
bugId: external_exports.string().optional().describe("Bug ID"),
|
|
@@ -47389,6 +47478,16 @@ server.tool(
|
|
|
47389
47478
|
},
|
|
47390
47479
|
async (params) => handleEvents(params)
|
|
47391
47480
|
);
|
|
47481
|
+
server.tool(
|
|
47482
|
+
"pulse_search",
|
|
47483
|
+
"Semantic similarity search across all work items (bugs, features, requests, feedback). Uses embeddings to find related items. Great for checking duplicates before creating.",
|
|
47484
|
+
{
|
|
47485
|
+
text: external_exports.string().describe("Search text \u2014 describe the bug, feature, or issue to find similar items"),
|
|
47486
|
+
limit: external_exports.number().optional().describe("Max results (default 5)"),
|
|
47487
|
+
threshold: external_exports.number().optional().describe("Similarity threshold 0-1 (default 0.78)")
|
|
47488
|
+
},
|
|
47489
|
+
async (params) => handleSearch(params)
|
|
47490
|
+
);
|
|
47392
47491
|
server.tool(
|
|
47393
47492
|
"pulse_history",
|
|
47394
47493
|
"Search historical items (shipped features, closed requests, bugs, feedback). Filters: type, pod, project, days.",
|