@theronap/agnoclast-mcp 0.9.234 → 0.9.236
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/lib/grep_cli.mjs +6 -2
- package/lib/record_render.mjs +1 -1
- package/lib/server.mjs +7 -5
- package/package.json +1 -1
package/lib/grep_cli.mjs
CHANGED
|
@@ -54,8 +54,12 @@ export function formatGrepHits(payload, query) {
|
|
|
54
54
|
: `${hits.length} match${hits.length === 1 ? '' : 'es'} for "${query}":`
|
|
55
55
|
const lines = [header, '']
|
|
56
56
|
for (const h of hits) {
|
|
57
|
+
// Records (server 2026-10-15, ADR-0081) arrive in the same list, already labelled in the title.
|
|
58
|
+
const isRecord = h.kind === 'record'
|
|
57
59
|
const head = h.heading ? ` > ${h.heading}` : ''
|
|
58
|
-
lines.push(
|
|
60
|
+
lines.push(isRecord
|
|
61
|
+
? `- ${h.title}${h.brain && h.brain.name ? ` · ${h.brain.name}` : ''}\n read_record ${(h.record && h.record.id) || h.documentId}`
|
|
62
|
+
: `- [page] ${h.title}${head} [${h.tier}]`)
|
|
59
63
|
if (h.snippet) lines.push(` ${String(h.snippet).replace(/\s+/g, ' ').trim()}`)
|
|
60
64
|
// Cap the link list per hit. Median is 2 but the tail reaches 32, and at ~126 chars/hit the
|
|
61
65
|
// link lists were the second-largest cost in the payload after snippets. The count is kept so
|
|
@@ -63,7 +67,7 @@ export function formatGrepHits(payload, query) {
|
|
|
63
67
|
if (h.links && h.links.length) {
|
|
64
68
|
const shown = h.links.slice(0, LINKS_PER_HIT)
|
|
65
69
|
const more = h.links.length - shown.length
|
|
66
|
-
lines.push(` -> ${shown.map((l) => `[[${l}]]`).join(' ')}${more > 0 ? ` (+${more} more)` : ''}`)
|
|
70
|
+
lines.push(` ${isRecord ? 'filed on' : '->'} ${shown.map((l) => `[[${l}]]`).join(' ')}${more > 0 ? ` (+${more} more)` : ''}`)
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
return lines.join('\n')
|
package/lib/record_render.mjs
CHANGED
|
@@ -50,7 +50,7 @@ export function renderRecord(rec, maxChars = READ_RECORD_DEFAULT_CHARS, part = '
|
|
|
50
50
|
out.push('')
|
|
51
51
|
}
|
|
52
52
|
if (notes && want === 'notes') {
|
|
53
|
-
out.push(`Full transcript: ${content.length.toLocaleString('en-US')} characters, not shown. Call read_record with part: "transcript" when you need the exact words; grep and search
|
|
53
|
+
out.push(`Full transcript: ${content.length.toLocaleString('en-US')} characters, not shown. Call read_record with part: "transcript" when you need the exact words; grep and search find a meeting by its title and notes, not its raw transcript.`)
|
|
54
54
|
} else if (!content.trim()) {
|
|
55
55
|
out.push('(No content was captured for this record.)')
|
|
56
56
|
} else if (content.length > cap) {
|
package/lib/server.mjs
CHANGED
|
@@ -1198,6 +1198,7 @@ function renderNudge(payload) {
|
|
|
1198
1198
|
inputSchema: {
|
|
1199
1199
|
claimKind: z.enum(['relevance', 'cleanup']).optional().describe('default relevance'),
|
|
1200
1200
|
limit: z.number().optional().describe('max items (default 10). Ignored when intakeItemIds is given.'),
|
|
1201
|
+
source: z.string().optional().describe('claim only the oldest units of ONE source — e.g. "imessage", "meeting", "email", "github", "claude-code". Reaches texts without first claiming every older GitHub/session unit ahead of them. Ignored when intakeItemIds is given.'),
|
|
1201
1202
|
leaseMinutes: z.number().optional().describe('lease length in minutes, 5-60 (default 30). Prefer intake_look for read-only inspection — a short lease is only for briefly exclusive work.'),
|
|
1202
1203
|
// 🔴 SINGULAR ACCEPTED, AND NOT AS A CONVENIENCE. Every sibling verb takes `intakeItemId`:
|
|
1203
1204
|
// intake_look, intake_materialize, intake_release, intake_defer, intake_discard. This one
|
|
@@ -1221,7 +1222,7 @@ function renderNudge(payload) {
|
|
|
1221
1222
|
),
|
|
1222
1223
|
},
|
|
1223
1224
|
},
|
|
1224
|
-
async ({ claimKind, limit, intakeItemId, intakeItemIds, leaseMinutes }) => {
|
|
1225
|
+
async ({ claimKind, limit, source, intakeItemId, intakeItemIds, leaseMinutes }) => {
|
|
1225
1226
|
// Merge the two spellings before anything else looks at them. Passing both is not an error —
|
|
1226
1227
|
// the union is what the caller plainly meant.
|
|
1227
1228
|
const ids = [...new Set([...(intakeItemIds ?? []), ...(intakeItemId ? [intakeItemId] : [])])]
|
|
@@ -1238,6 +1239,7 @@ function renderNudge(payload) {
|
|
|
1238
1239
|
// survive as one; sending `[]` where the caller sent nothing would silently switch a FIFO
|
|
1239
1240
|
// claim into a no-op.
|
|
1240
1241
|
...(intakeItemIds ? { intakeItemIds } : {}),
|
|
1242
|
+
...(source ? { source } : {}),
|
|
1241
1243
|
}),
|
|
1242
1244
|
})
|
|
1243
1245
|
if (!res.ok) {
|
|
@@ -1996,9 +1998,9 @@ function renderNudge(payload) {
|
|
|
1996
1998
|
server.registerTool(
|
|
1997
1999
|
'grep',
|
|
1998
2000
|
{
|
|
1999
|
-
title: 'Grep
|
|
2001
|
+
title: 'Grep pages and records',
|
|
2000
2002
|
description:
|
|
2001
|
-
'Ranked keyword search across your visible brain wiki pages. Multi-word natural-language queries work (results are ranked by relevance). Pass mode:"substring" for an exact literal match of symbols, identifiers, or [[links]] — and for an English STOPWORD ("own", "not"), which ranked search drops. Returns matching sections with a context snippet and their outbound [[links]]. A broad query fans out across every brain you can see, so pass `max` when you only need to locate a page; the header always says how many matched in total, so a capped list is never mistaken for the whole answer.',
|
|
2003
|
+
'Ranked keyword search across your visible brain wiki pages AND the records filed in your brains (meeting/lecture transcripts and their notes, emails, sessions, messages) — one list, each hit labelled [page] or [record · type · date] with its id and the pages it is filed on. An empty result means neither a page nor a record mentions it. Multi-word natural-language queries work (results are ranked by relevance). Pass mode:"substring" for an exact literal match of symbols, identifiers, or [[links]] — and for an English STOPWORD ("own", "not"), which ranked search drops. Returns matching sections with a context snippet and their outbound [[links]]. A broad query fans out across every brain you can see, so pass `max` when you only need to locate a page; the header always says how many matched in total, so a capped list is never mistaken for the whole answer.',
|
|
2002
2004
|
inputSchema: {
|
|
2003
2005
|
query: z.string().describe('search terms (natural language is fine)'),
|
|
2004
2006
|
mode: z.enum(['substring', 'fts']).optional().describe("'fts' (default, ranked keyword) or 'substring' (exact literal — for identifiers / [[links]] / code)"),
|
|
@@ -4767,8 +4769,8 @@ function renderNudge(payload) {
|
|
|
4767
4769
|
'that does not exist. ' +
|
|
4768
4770
|
'A meeting or lecture transcript has TWO LAYERS: notes (the gist, decisions, action items) and the full ' +
|
|
4769
4771
|
'transcript. By default you get the NOTES and the transcript\'s length; read the notes first, and ask for ' +
|
|
4770
|
-
'part: "transcript" only when you need the exact words. To FIND
|
|
4771
|
-
'
|
|
4772
|
+
'part: "transcript" only when you need the exact words. To FIND a meeting, grep and search ' +
|
|
4773
|
+
'cover its title and notes (not the raw transcript words).',
|
|
4772
4774
|
inputSchema: {
|
|
4773
4775
|
id: z.string().describe('the record id, from list_records, my_day, timeline_pull or another read_record'),
|
|
4774
4776
|
max_chars: z.number().optional().describe(`cap on the content shown (default ${READ_RECORD_DEFAULT_CHARS}); the reply says how much was left out`),
|
package/package.json
CHANGED