Skip to content

Commit 8caaf86

Browse files
committed
fix: use searchByMetadata for dashboard tasks/explorations, strip undefined edit_note args
Dashboard: - Switch /api/tasks and /api/explorations from text search to searchByMetadata - Text search for 'type:Task' returned noisy results; metadata filter is exact - Add enrichMetadataResults helper for frontmatter enrichment edit_note: - Strip undefined find_text, section, expected_replacements from payload - BM MCP now rejects payloads with undefined/null optional fields - Fixes 'invalid edit_note payload' error in auto-capture hook
1 parent cca8d3d commit 8caaf86

File tree

2 files changed

+50
-26
lines changed

2 files changed

+50
-26
lines changed

bm-client.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,11 +659,12 @@ export class BmClient {
659659
identifier,
660660
operation,
661661
content,
662-
find_text: options.find_text,
663-
section: options.section,
664-
expected_replacements: options.expected_replacements,
665662
output_format: "json",
666663
}
664+
if (options.find_text) args.find_text = options.find_text
665+
if (options.section) args.section = options.section
666+
if (options.expected_replacements != null)
667+
args.expected_replacements = options.expected_replacements
667668
if (project) args.project = project
668669

669670
const payload = await this.callTool("edit_note", args)

dashboard/server.ts

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import {
66
type ServerResponse,
77
} from "node:http"
88
import { join } from "node:path"
9-
import type { BmClient, SearchResult } from "../bm-client.ts"
9+
import type {
10+
BmClient,
11+
MetadataSearchResult,
12+
SearchResult,
13+
} from "../bm-client.ts"
1014

1115
export interface DashboardServerOptions {
1216
port: number
@@ -34,10 +38,11 @@ export function createDashboardServer(options: DashboardServerOptions): Server {
3438
}
3539

3640
if (path === "/api/tasks" && req.method === "GET") {
37-
const results = await client.search("type:Task", 50, undefined, {
38-
filters: { type: "Task" },
39-
})
40-
const tasks = await enrichWithFrontmatter(client, results)
41+
const metaResults = await client.searchByMetadata(
42+
{ type: "Task" },
43+
50,
44+
)
45+
const tasks = await enrichMetadataResults(client, metaResults)
4146
json(res, tasks)
4247
return
4348
}
@@ -49,15 +54,11 @@ export function createDashboardServer(options: DashboardServerOptions): Server {
4954
}
5055

5156
if (path === "/api/explorations" && req.method === "GET") {
52-
const results = await client.search(
53-
"type:Exploration",
57+
const metaResults = await client.searchByMetadata(
58+
{ type: "Exploration" },
5459
50,
55-
undefined,
56-
{
57-
filters: { type: "Exploration" },
58-
},
5960
)
60-
json(res, results)
61+
json(res, metaResults.results)
6162
return
6263
}
6364

@@ -70,21 +71,17 @@ export function createDashboardServer(options: DashboardServerOptions): Server {
7071
}
7172

7273
if (path === "/api/stats" && req.method === "GET") {
73-
const [allNotes, tasks, explorations] = await Promise.all([
74+
const [allNotes, tasksMeta, explorationsMeta] = await Promise.all([
7475
client.recentActivity("720h").catch(() => []),
7576
client
76-
.search("type:Task", 100, undefined, {
77-
filters: { type: "Task" },
78-
})
79-
.catch(() => []),
77+
.searchByMetadata({ type: "Task" }, 100)
78+
.catch(() => ({ results: [] }) as MetadataSearchResult),
8079
client
81-
.search("type:Exploration", 100, undefined, {
82-
filters: { type: "Exploration" },
83-
})
84-
.catch(() => []),
80+
.searchByMetadata({ type: "Exploration" }, 100)
81+
.catch(() => ({ results: [] }) as MetadataSearchResult),
8582
])
8683

87-
const tasksWithFm = await enrichWithFrontmatter(client, tasks)
84+
const tasksWithFm = await enrichMetadataResults(client, tasksMeta)
8885
const active = tasksWithFm.filter(
8986
(t) => t.frontmatter?.status === "active",
9087
).length
@@ -98,7 +95,7 @@ export function createDashboardServer(options: DashboardServerOptions): Server {
9895
totalNotes: allNotes.length,
9996
activeTasks: active,
10097
completedTasks: completed,
101-
explorations: explorations.length,
98+
explorations: explorationsMeta.results.length,
10299
})
103100
return
104101
}
@@ -144,3 +141,29 @@ async function enrichWithFrontmatter(
144141
)
145142
return enriched
146143
}
144+
145+
async function enrichMetadataResults(
146+
client: BmClient,
147+
metaResults: MetadataSearchResult,
148+
): Promise<
149+
Array<
150+
Record<string, unknown> & {
151+
frontmatter?: Record<string, unknown> | null
152+
}
153+
>
154+
> {
155+
const enriched = await Promise.all(
156+
metaResults.results.map(async (r: Record<string, unknown>) => {
157+
const permalink = (r.permalink ?? r.entity ?? "") as string
158+
try {
159+
const note = await client.readNote(permalink, {
160+
includeFrontmatter: true,
161+
})
162+
return { ...r, frontmatter: note.frontmatter ?? null }
163+
} catch {
164+
return { ...r, frontmatter: null }
165+
}
166+
}),
167+
)
168+
return enriched
169+
}

0 commit comments

Comments
 (0)