@vailent/pulse-mcp 1.7.0 → 1.8.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.
- package/dist/server.js +111 -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}`);
|
|
@@ -42001,20 +42048,21 @@ async function handleBugs(params) {
|
|
|
42001
42048
|
case "update": {
|
|
42002
42049
|
const bugId = params.bugId;
|
|
42003
42050
|
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)
|
|
42051
|
+
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();
|
|
42052
|
+
const raw = { updated_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
42053
|
+
if (params.title !== void 0) raw.title = params.title;
|
|
42054
|
+
if (params.description !== void 0) raw.description = params.description;
|
|
42055
|
+
if (params.priority !== void 0) raw.priority = params.priority;
|
|
42056
|
+
if (params.status !== void 0) raw.status = params.status;
|
|
42057
|
+
if (params.podId !== void 0) raw.pod_id = params.podId;
|
|
42058
|
+
if (params.projectName !== void 0) raw.project_name = params.projectName;
|
|
42012
42059
|
let autoPromoted = false;
|
|
42013
42060
|
if (currentBug?.status === "open" && !currentBug.week_start && !params.status) {
|
|
42014
|
-
|
|
42015
|
-
|
|
42061
|
+
raw.status = "in_progress";
|
|
42062
|
+
raw.week_start = getCurrentWeekStart();
|
|
42016
42063
|
autoPromoted = true;
|
|
42017
42064
|
}
|
|
42065
|
+
const updates = normalizeWorkItemState(raw, currentBug || void 0);
|
|
42018
42066
|
const { error: error2 } = await supabase.from("work_items").update(updates).eq("id", bugId);
|
|
42019
42067
|
if (error2) return err(error2.message);
|
|
42020
42068
|
if (autoPromoted) {
|
|
@@ -47230,6 +47278,45 @@ async function handleTeam(params) {
|
|
|
47230
47278
|
}
|
|
47231
47279
|
}
|
|
47232
47280
|
|
|
47281
|
+
// tools/search.ts
|
|
47282
|
+
async function handleSearch(params) {
|
|
47283
|
+
const text = params.text;
|
|
47284
|
+
if (!text?.trim()) return err("text is required", "MISSING_PARAM");
|
|
47285
|
+
const limit = params.limit || 5;
|
|
47286
|
+
const threshold = params.threshold || 0.78;
|
|
47287
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
47288
|
+
if (!apiKey) return err("OPENAI_API_KEY not configured \u2014 cannot perform similarity search", "CONFIG_ERROR");
|
|
47289
|
+
let embedding;
|
|
47290
|
+
try {
|
|
47291
|
+
const res = await fetch("https://api.openai.com/v1/embeddings", {
|
|
47292
|
+
method: "POST",
|
|
47293
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
47294
|
+
body: JSON.stringify({ model: "text-embedding-3-small", input: text.slice(0, 8e3) })
|
|
47295
|
+
});
|
|
47296
|
+
if (!res.ok) return err(`OpenAI error: ${res.status}`, "API_ERROR");
|
|
47297
|
+
const data2 = await res.json();
|
|
47298
|
+
embedding = data2.data[0].embedding;
|
|
47299
|
+
} catch (e) {
|
|
47300
|
+
return err(`Embedding failed: ${e}`, "API_ERROR");
|
|
47301
|
+
}
|
|
47302
|
+
const supabase = getAdminClient();
|
|
47303
|
+
const { data, error: error2 } = await supabase.rpc("match_work_items", {
|
|
47304
|
+
query_embedding: JSON.stringify(embedding),
|
|
47305
|
+
match_threshold: threshold,
|
|
47306
|
+
match_count: limit
|
|
47307
|
+
});
|
|
47308
|
+
if (error2) return err(error2.message);
|
|
47309
|
+
const results = data || [];
|
|
47310
|
+
return ok(
|
|
47311
|
+
results.map((r) => ({
|
|
47312
|
+
...r,
|
|
47313
|
+
similarity: Math.round(r.similarity * 100) / 100
|
|
47314
|
+
})),
|
|
47315
|
+
`${results.length} similar item(s) found`,
|
|
47316
|
+
results.length
|
|
47317
|
+
);
|
|
47318
|
+
}
|
|
47319
|
+
|
|
47233
47320
|
// server.ts
|
|
47234
47321
|
try {
|
|
47235
47322
|
await import("./config-V5TD57MJ.js");
|
|
@@ -47281,7 +47368,7 @@ server.tool(
|
|
|
47281
47368
|
);
|
|
47282
47369
|
server.tool(
|
|
47283
47370
|
"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
|
|
47371
|
+
"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
47372
|
{
|
|
47286
47373
|
action: external_exports.enum(["list", "get", "create", "update", "delete", "add_note", "reorder"]),
|
|
47287
47374
|
featureId: external_exports.string().optional().describe("Feature ID"),
|
|
@@ -47349,7 +47436,7 @@ server.tool(
|
|
|
47349
47436
|
);
|
|
47350
47437
|
server.tool(
|
|
47351
47438
|
"pulse_bugs",
|
|
47352
|
-
"Track bugs. Actions: list (open/in_progress bugs by pod), create, update (
|
|
47439
|
+
"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
47440
|
{
|
|
47354
47441
|
action: external_exports.enum(["list", "create", "update", "delete", "schedule"]),
|
|
47355
47442
|
bugId: external_exports.string().optional().describe("Bug ID"),
|
|
@@ -47389,6 +47476,16 @@ server.tool(
|
|
|
47389
47476
|
},
|
|
47390
47477
|
async (params) => handleEvents(params)
|
|
47391
47478
|
);
|
|
47479
|
+
server.tool(
|
|
47480
|
+
"pulse_search",
|
|
47481
|
+
"Semantic similarity search across all work items (bugs, features, requests, feedback). Uses embeddings to find related items. Great for checking duplicates before creating.",
|
|
47482
|
+
{
|
|
47483
|
+
text: external_exports.string().describe("Search text \u2014 describe the bug, feature, or issue to find similar items"),
|
|
47484
|
+
limit: external_exports.number().optional().describe("Max results (default 5)"),
|
|
47485
|
+
threshold: external_exports.number().optional().describe("Similarity threshold 0-1 (default 0.78)")
|
|
47486
|
+
},
|
|
47487
|
+
async (params) => handleSearch(params)
|
|
47488
|
+
);
|
|
47392
47489
|
server.tool(
|
|
47393
47490
|
"pulse_history",
|
|
47394
47491
|
"Search historical items (shipped features, closed requests, bugs, feedback). Filters: type, pod, project, days.",
|