@noteplanco/noteplan-mcp 1.1.7 → 1.1.8
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/noteplan/embeddings.d.ts +8 -0
- package/dist/noteplan/embeddings.d.ts.map +1 -1
- package/dist/noteplan/embeddings.js +3 -3
- package/dist/noteplan/embeddings.js.map +1 -1
- package/dist/noteplan/file-reader.d.ts +6 -0
- package/dist/noteplan/file-reader.d.ts.map +1 -1
- package/dist/noteplan/file-reader.js +15 -0
- package/dist/noteplan/file-reader.js.map +1 -1
- package/dist/noteplan/file-writer.d.ts.map +1 -1
- package/dist/noteplan/file-writer.js +13 -1
- package/dist/noteplan/file-writer.js.map +1 -1
- package/dist/noteplan/file-writer.test.js +4 -0
- package/dist/noteplan/file-writer.test.js.map +1 -1
- package/dist/noteplan/frontmatter-parser.d.ts +2 -2
- package/dist/noteplan/frontmatter-parser.d.ts.map +1 -1
- package/dist/noteplan/frontmatter-parser.js +9 -12
- package/dist/noteplan/frontmatter-parser.js.map +1 -1
- package/dist/noteplan/frontmatter-parser.test.js +92 -0
- package/dist/noteplan/frontmatter-parser.test.js.map +1 -1
- package/dist/noteplan/markdown-parser.d.ts.map +1 -1
- package/dist/noteplan/markdown-parser.js +4 -2
- package/dist/noteplan/markdown-parser.js.map +1 -1
- package/dist/noteplan/markdown-parser.test.js +37 -0
- package/dist/noteplan/markdown-parser.test.js.map +1 -1
- package/dist/noteplan/template-docs.d.ts +35 -0
- package/dist/noteplan/template-docs.d.ts.map +1 -0
- package/dist/noteplan/template-docs.js +184 -0
- package/dist/noteplan/template-docs.js.map +1 -0
- package/dist/noteplan/unified-store.d.ts +2 -0
- package/dist/noteplan/unified-store.d.ts.map +1 -1
- package/dist/noteplan/unified-store.js +22 -6
- package/dist/noteplan/unified-store.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +275 -55
- package/dist/server.js.map +1 -1
- package/dist/tools/calendar.d.ts +2 -2
- package/dist/tools/notes.d.ts +81 -22
- package/dist/tools/notes.d.ts.map +1 -1
- package/dist/tools/notes.js +267 -21
- package/dist/tools/notes.js.map +1 -1
- package/dist/tools/notes.test.js +202 -0
- package/dist/tools/notes.test.js.map +1 -1
- package/dist/tools/plugins.d.ts.map +1 -1
- package/dist/tools/plugins.js +1 -0
- package/dist/tools/plugins.js.map +1 -1
- package/dist/tools/search.d.ts +2 -2
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +32 -4
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/templates.d.ts +64 -3
- package/dist/tools/templates.d.ts.map +1 -1
- package/dist/tools/templates.js +73 -1
- package/dist/tools/templates.js.map +1 -1
- package/dist/utils/version.d.ts +1 -0
- package/dist/utils/version.d.ts.map +1 -1
- package/dist/utils/version.js +67 -23
- package/dist/utils/version.js.map +1 -1
- package/docs/templates.db.gz +0 -0
- package/docs/x-callback-url.md +318 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../../src/tools/notes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../../src/tools/notes.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/notes.js
CHANGED
|
@@ -698,6 +698,7 @@ export function createNote(params) {
|
|
|
698
698
|
});
|
|
699
699
|
return {
|
|
700
700
|
success: true,
|
|
701
|
+
tip: 'Use action "set_property" to add frontmatter fields (e.g. type, tags) or "remove_property" to delete them.',
|
|
701
702
|
note: {
|
|
702
703
|
title: result.note.title,
|
|
703
704
|
filename: result.note.filename,
|
|
@@ -1365,6 +1366,7 @@ export function searchParagraphs(params) {
|
|
|
1365
1366
|
const nextCursor = hasMore ? String(offset + page.length) : null;
|
|
1366
1367
|
const result = {
|
|
1367
1368
|
success: true,
|
|
1369
|
+
tip: 'To search across ALL notes at once, use action "search_global" instead. It supports query "*" to match all tasks.',
|
|
1368
1370
|
query,
|
|
1369
1371
|
count: page.length,
|
|
1370
1372
|
totalCount: allMatches.length,
|
|
@@ -1660,6 +1662,7 @@ export function insertContent(params) {
|
|
|
1660
1662
|
});
|
|
1661
1663
|
return {
|
|
1662
1664
|
success: true,
|
|
1665
|
+
tip: 'Use noteplan_paragraphs(action: "get") to inspect line numbers and content before making further edits.',
|
|
1663
1666
|
message: `Content inserted at ${params.position}`,
|
|
1664
1667
|
note: {
|
|
1665
1668
|
id: note.id,
|
|
@@ -1725,14 +1728,21 @@ export function deleteLines(params) {
|
|
|
1725
1728
|
}
|
|
1726
1729
|
const note = resolved.note;
|
|
1727
1730
|
const allLines = note.content.split('\n');
|
|
1728
|
-
// Line numbers are
|
|
1729
|
-
const
|
|
1730
|
-
const
|
|
1731
|
-
const
|
|
1732
|
-
const
|
|
1731
|
+
// Line numbers are absolute (1-indexed), matching get_notes/getParagraphs
|
|
1732
|
+
const totalLineCount = allLines.length;
|
|
1733
|
+
const fmLineCount = frontmatter.getFrontmatterLineCount(note.content);
|
|
1734
|
+
const minLine = fmLineCount > 0 ? fmLineCount + 1 : 1;
|
|
1735
|
+
const boundedStartLine = toBoundedInt(params.startLine, minLine, minLine, Math.max(minLine, totalLineCount));
|
|
1736
|
+
const boundedEndLine = toBoundedInt(params.endLine, boundedStartLine, boundedStartLine, Math.max(boundedStartLine, totalLineCount));
|
|
1737
|
+
if (boundedStartLine <= fmLineCount) {
|
|
1738
|
+
return {
|
|
1739
|
+
success: false,
|
|
1740
|
+
error: `Lines 1-${fmLineCount} are frontmatter and cannot be deleted. Content starts at line ${fmLineCount + 1}.`,
|
|
1741
|
+
};
|
|
1742
|
+
}
|
|
1733
1743
|
const lineCountToDelete = boundedEndLine - boundedStartLine + 1;
|
|
1734
|
-
const previewStartIndex =
|
|
1735
|
-
const previewEndIndexExclusive =
|
|
1744
|
+
const previewStartIndex = boundedStartLine - 1;
|
|
1745
|
+
const previewEndIndexExclusive = boundedEndLine;
|
|
1736
1746
|
const deletedLinesPreview = allLines
|
|
1737
1747
|
.slice(previewStartIndex, previewEndIndexExclusive)
|
|
1738
1748
|
.slice(0, 20)
|
|
@@ -1776,7 +1786,10 @@ export function deleteLines(params) {
|
|
|
1776
1786
|
error: confirmationFailureMessage('noteplan_delete_lines', confirmation.reason),
|
|
1777
1787
|
};
|
|
1778
1788
|
}
|
|
1779
|
-
|
|
1789
|
+
// Splice out lines using absolute indices (no frontmatter offset needed)
|
|
1790
|
+
const splicedLines = [...allLines];
|
|
1791
|
+
splicedLines.splice(boundedStartLine - 1, lineCountToDelete);
|
|
1792
|
+
const newContent = splicedLines.join('\n');
|
|
1780
1793
|
const writeIdentifier = note.source === 'space' ? (note.id || note.filename) : note.filename;
|
|
1781
1794
|
store.updateNote(writeIdentifier, newContent, { source: note.source });
|
|
1782
1795
|
return {
|
|
@@ -1810,13 +1823,19 @@ export function editLine(params) {
|
|
|
1810
1823
|
const note = resolved.note;
|
|
1811
1824
|
const lines = note.content.split('\n');
|
|
1812
1825
|
const originalLineCount = lines.length;
|
|
1813
|
-
//
|
|
1814
|
-
const
|
|
1815
|
-
const lineIndex =
|
|
1816
|
-
if (lineIndex <
|
|
1826
|
+
// Line numbers are absolute (1-indexed), matching get_notes/getParagraphs
|
|
1827
|
+
const fmLineCount = frontmatter.getFrontmatterLineCount(note.content);
|
|
1828
|
+
const lineIndex = Number(params.line) - 1; // Convert to 0-indexed
|
|
1829
|
+
if (lineIndex < 0 || lineIndex >= lines.length) {
|
|
1830
|
+
return {
|
|
1831
|
+
success: false,
|
|
1832
|
+
error: `Line ${params.line} does not exist (note has ${lines.length} lines)`,
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
if (fmLineCount > 0 && lineIndex < fmLineCount) {
|
|
1817
1836
|
return {
|
|
1818
1837
|
success: false,
|
|
1819
|
-
error: `Line ${params.line}
|
|
1838
|
+
error: `Line ${params.line} is inside frontmatter (lines 1-${fmLineCount}). Content starts at line ${fmLineCount + 1}.`,
|
|
1820
1839
|
};
|
|
1821
1840
|
}
|
|
1822
1841
|
const originalLine = lines[lineIndex];
|
|
@@ -1869,16 +1888,31 @@ export function replaceLines(params) {
|
|
|
1869
1888
|
const note = resolved.note;
|
|
1870
1889
|
const allLines = note.content.split('\n');
|
|
1871
1890
|
const originalLineCount = allLines.length;
|
|
1872
|
-
// Line numbers are
|
|
1873
|
-
const
|
|
1874
|
-
const
|
|
1875
|
-
const boundedStartLine = toBoundedInt(params.startLine,
|
|
1876
|
-
const boundedEndLine = toBoundedInt(params.endLine, boundedStartLine, boundedStartLine, Math.max(boundedStartLine,
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1891
|
+
// Line numbers are absolute (1-indexed), matching get_notes/getParagraphs
|
|
1892
|
+
const fmLineCount = frontmatter.getFrontmatterLineCount(note.content);
|
|
1893
|
+
const minLine = fmLineCount > 0 ? fmLineCount + 1 : 1;
|
|
1894
|
+
const boundedStartLine = toBoundedInt(params.startLine, minLine, minLine, Math.max(minLine, originalLineCount));
|
|
1895
|
+
const boundedEndLine = toBoundedInt(params.endLine, boundedStartLine, boundedStartLine, Math.max(boundedStartLine, originalLineCount));
|
|
1896
|
+
if (boundedStartLine <= fmLineCount) {
|
|
1897
|
+
return {
|
|
1898
|
+
success: false,
|
|
1899
|
+
error: `Lines 1-${fmLineCount} are frontmatter and cannot be replaced directly. Content starts at line ${fmLineCount + 1}.`,
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1902
|
+
let startIndex = boundedStartLine - 1;
|
|
1903
|
+
let lineCountToReplace = boundedEndLine - boundedStartLine + 1;
|
|
1904
|
+
const replacedText = allLines.slice(startIndex, boundedEndLine).join('\n');
|
|
1880
1905
|
const indentationStyle = normalizeIndentationStyle(params.indentationStyle);
|
|
1881
1906
|
const normalized = normalizeContentIndentation(params.content, indentationStyle);
|
|
1907
|
+
// If replacement content includes frontmatter and the note already has
|
|
1908
|
+
// frontmatter, extend the splice to replace the old frontmatter too.
|
|
1909
|
+
// The agent's frontmatter is the intended update.
|
|
1910
|
+
const replacementHasFm = fmLineCount > 0
|
|
1911
|
+
&& frontmatter.parseNoteContent(normalized.content).hasFrontmatter;
|
|
1912
|
+
if (replacementHasFm) {
|
|
1913
|
+
lineCountToReplace += startIndex; // extend to also cover frontmatter lines
|
|
1914
|
+
startIndex = 0;
|
|
1915
|
+
}
|
|
1882
1916
|
if (params.allowEmptyContent !== true && normalized.content.trim().length === 0) {
|
|
1883
1917
|
return {
|
|
1884
1918
|
success: false,
|
|
@@ -1956,4 +1990,216 @@ export function replaceLines(params) {
|
|
|
1956
1990
|
};
|
|
1957
1991
|
}
|
|
1958
1992
|
}
|
|
1993
|
+
// ---------------------------------------------------------------------------
|
|
1994
|
+
// searchParagraphsGlobal — search ALL lines (including frontmatter) across notes
|
|
1995
|
+
// ---------------------------------------------------------------------------
|
|
1996
|
+
function normalizeType(value) {
|
|
1997
|
+
if (typeof value !== 'string')
|
|
1998
|
+
return undefined;
|
|
1999
|
+
const lower = value.trim().toLowerCase();
|
|
2000
|
+
if (lower === 'calendar' || lower === 'note' || lower === 'trash')
|
|
2001
|
+
return lower;
|
|
2002
|
+
return undefined;
|
|
2003
|
+
}
|
|
2004
|
+
function normalizeTypeList(values) {
|
|
2005
|
+
if (!Array.isArray(values))
|
|
2006
|
+
return undefined;
|
|
2007
|
+
const unique = new Set();
|
|
2008
|
+
for (const entry of values) {
|
|
2009
|
+
const normalized = normalizeType(entry);
|
|
2010
|
+
if (normalized)
|
|
2011
|
+
unique.add(normalized);
|
|
2012
|
+
}
|
|
2013
|
+
return unique.size > 0 ? Array.from(unique) : undefined;
|
|
2014
|
+
}
|
|
2015
|
+
function isPeriodicCalendarNote(note) {
|
|
2016
|
+
if (note.type !== 'calendar' || !note.date)
|
|
2017
|
+
return false;
|
|
2018
|
+
return note.date.includes('-');
|
|
2019
|
+
}
|
|
2020
|
+
export const searchParagraphsGlobalSchema = z.object({
|
|
2021
|
+
query: z.string().describe('Text to find across all notes (searches ALL lines including frontmatter)'),
|
|
2022
|
+
caseSensitive: z.boolean().optional().default(false).describe('Case-sensitive match (default: false)'),
|
|
2023
|
+
wholeWord: z.boolean().optional().default(false).describe('Require whole-word matches (default: false)'),
|
|
2024
|
+
status: z
|
|
2025
|
+
.enum(['open', 'done', 'cancelled', 'scheduled'])
|
|
2026
|
+
.optional()
|
|
2027
|
+
.describe('Filter results to only lines with this task status'),
|
|
2028
|
+
contextLines: z.number().min(0).max(5).optional().default(1).describe('Context lines before/after each match'),
|
|
2029
|
+
paragraphMaxChars: z
|
|
2030
|
+
.number()
|
|
2031
|
+
.min(50)
|
|
2032
|
+
.max(5000)
|
|
2033
|
+
.optional()
|
|
2034
|
+
.default(600)
|
|
2035
|
+
.describe('Maximum paragraph text chars per match'),
|
|
2036
|
+
folder: z.string().optional().describe('Restrict to a specific folder path'),
|
|
2037
|
+
space: z.string().optional().describe('Restrict to a specific space name or ID'),
|
|
2038
|
+
noteQuery: z.string().optional().describe('Filter notes by title/filename/folder substring'),
|
|
2039
|
+
noteTypes: z
|
|
2040
|
+
.array(z.enum(['calendar', 'note', 'trash']))
|
|
2041
|
+
.optional()
|
|
2042
|
+
.describe('Restrict scanned notes by type'),
|
|
2043
|
+
preferCalendar: z
|
|
2044
|
+
.boolean()
|
|
2045
|
+
.optional()
|
|
2046
|
+
.default(false)
|
|
2047
|
+
.describe('Prioritize calendar notes before maxNotes truncation'),
|
|
2048
|
+
periodicOnly: z
|
|
2049
|
+
.boolean()
|
|
2050
|
+
.optional()
|
|
2051
|
+
.default(false)
|
|
2052
|
+
.describe('When true, only scan periodic calendar notes (weekly/monthly/quarterly/yearly)'),
|
|
2053
|
+
maxNotes: z.number().min(1).max(2000).optional().default(500).describe('Maximum notes to scan'),
|
|
2054
|
+
limit: z.number().min(1).max(300).optional().default(30).describe('Maximum matches to return'),
|
|
2055
|
+
offset: z.number().min(0).optional().default(0).describe('Pagination offset'),
|
|
2056
|
+
cursor: z.string().optional().describe('Cursor token from previous page (preferred over offset)'),
|
|
2057
|
+
});
|
|
2058
|
+
export function searchParagraphsGlobal(params) {
|
|
2059
|
+
const query = typeof params?.query === 'string' ? params.query.trim() : '';
|
|
2060
|
+
if (!query) {
|
|
2061
|
+
return {
|
|
2062
|
+
success: false,
|
|
2063
|
+
error: 'query is required',
|
|
2064
|
+
};
|
|
2065
|
+
}
|
|
2066
|
+
const caseSensitive = params.caseSensitive ?? false;
|
|
2067
|
+
const wholeWord = params.wholeWord ?? false;
|
|
2068
|
+
const contextLines = toBoundedInt(params.contextLines, 1, 0, 5);
|
|
2069
|
+
const paragraphMaxChars = toBoundedInt(params.paragraphMaxChars, 600, 50, 5000);
|
|
2070
|
+
const normalizedQuery = caseSensitive ? query : query.toLowerCase();
|
|
2071
|
+
const wildcardQuery = query === '*';
|
|
2072
|
+
const matcher = wholeWord
|
|
2073
|
+
? new RegExp(`\\b${escapeRegExp(query)}\\b`, caseSensitive ? '' : 'i')
|
|
2074
|
+
: null;
|
|
2075
|
+
const maxNotes = toBoundedInt(params.maxNotes, 500, 1, 2000);
|
|
2076
|
+
const noteQuery = typeof params.noteQuery === 'string' ? params.noteQuery.trim().toLowerCase() : '';
|
|
2077
|
+
const noteTypes = normalizeTypeList(params.noteTypes);
|
|
2078
|
+
const preferCalendar = params.preferCalendar === true;
|
|
2079
|
+
const periodicOnly = params.periodicOnly === true;
|
|
2080
|
+
const allNotes = store.listNotes({
|
|
2081
|
+
folder: params.folder,
|
|
2082
|
+
space: params.space,
|
|
2083
|
+
});
|
|
2084
|
+
let filteredNotes = noteQuery
|
|
2085
|
+
? allNotes.filter((note) => {
|
|
2086
|
+
const haystack = `${note.title} ${note.filename} ${note.folder || ''}`.toLowerCase();
|
|
2087
|
+
return haystack.includes(noteQuery);
|
|
2088
|
+
})
|
|
2089
|
+
: allNotes;
|
|
2090
|
+
if (noteTypes && noteTypes.length > 0) {
|
|
2091
|
+
filteredNotes = filteredNotes.filter((note) => noteTypes.includes(note.type));
|
|
2092
|
+
}
|
|
2093
|
+
if (periodicOnly) {
|
|
2094
|
+
filteredNotes = filteredNotes.filter((note) => isPeriodicCalendarNote(note));
|
|
2095
|
+
}
|
|
2096
|
+
if (preferCalendar) {
|
|
2097
|
+
filteredNotes = [...filteredNotes].sort((a, b) => {
|
|
2098
|
+
const aCalendar = a.type === 'calendar' ? 1 : 0;
|
|
2099
|
+
const bCalendar = b.type === 'calendar' ? 1 : 0;
|
|
2100
|
+
if (aCalendar !== bCalendar)
|
|
2101
|
+
return bCalendar - aCalendar;
|
|
2102
|
+
const aModified = a.modifiedAt?.getTime() ?? 0;
|
|
2103
|
+
const bModified = b.modifiedAt?.getTime() ?? 0;
|
|
2104
|
+
return bModified - aModified;
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2107
|
+
const scannedNotes = filteredNotes.slice(0, maxNotes);
|
|
2108
|
+
const truncatedByMaxNotes = filteredNotes.length > scannedNotes.length;
|
|
2109
|
+
const allMatches = [];
|
|
2110
|
+
for (const note of scannedNotes) {
|
|
2111
|
+
const allLines = note.content.split('\n');
|
|
2112
|
+
for (let lineIndex = 0; lineIndex < allLines.length; lineIndex++) {
|
|
2113
|
+
const lineContent = allLines[lineIndex];
|
|
2114
|
+
const haystack = caseSensitive ? lineContent : lineContent.toLowerCase();
|
|
2115
|
+
const isMatch = wildcardQuery
|
|
2116
|
+
? true
|
|
2117
|
+
: matcher
|
|
2118
|
+
? matcher.test(lineContent)
|
|
2119
|
+
: haystack.includes(normalizedQuery);
|
|
2120
|
+
if (!isMatch)
|
|
2121
|
+
continue;
|
|
2122
|
+
const paragraphBounds = findParagraphBounds(allLines, lineIndex);
|
|
2123
|
+
const paragraphRaw = allLines
|
|
2124
|
+
.slice(paragraphBounds.startIndex, paragraphBounds.endIndex + 1)
|
|
2125
|
+
.join('\n');
|
|
2126
|
+
const paragraphTruncated = paragraphRaw.length > paragraphMaxChars;
|
|
2127
|
+
const paragraph = paragraphTruncated
|
|
2128
|
+
? `${paragraphRaw.slice(0, Math.max(0, paragraphMaxChars - 3))}...`
|
|
2129
|
+
: paragraphRaw;
|
|
2130
|
+
const contextStart = Math.max(0, lineIndex - contextLines);
|
|
2131
|
+
const contextEnd = Math.min(allLines.length - 1, lineIndex + contextLines);
|
|
2132
|
+
const meta = parseParagraphLine(lineContent, lineIndex, lineIndex === 0);
|
|
2133
|
+
// Apply status filter (backward compat with searchTasksGlobal)
|
|
2134
|
+
if (params.status && meta.taskStatus !== params.status)
|
|
2135
|
+
continue;
|
|
2136
|
+
allMatches.push({
|
|
2137
|
+
note: {
|
|
2138
|
+
id: note.id,
|
|
2139
|
+
title: note.title,
|
|
2140
|
+
filename: note.filename,
|
|
2141
|
+
type: note.type,
|
|
2142
|
+
source: note.source,
|
|
2143
|
+
folder: note.folder,
|
|
2144
|
+
spaceId: note.spaceId,
|
|
2145
|
+
date: note.date,
|
|
2146
|
+
},
|
|
2147
|
+
lineIndex,
|
|
2148
|
+
line: lineIndex + 1,
|
|
2149
|
+
content: lineContent,
|
|
2150
|
+
// Backward-compat alias: `status` mirrors `taskStatus` for old consumers
|
|
2151
|
+
...(meta.taskStatus !== undefined && { status: meta.taskStatus }),
|
|
2152
|
+
type: meta.type,
|
|
2153
|
+
indentLevel: meta.indentLevel,
|
|
2154
|
+
...(meta.headingLevel !== undefined && { headingLevel: meta.headingLevel }),
|
|
2155
|
+
...(meta.taskStatus !== undefined && { taskStatus: meta.taskStatus }),
|
|
2156
|
+
...(meta.priority !== undefined && { priority: meta.priority }),
|
|
2157
|
+
...(meta.marker !== undefined && { marker: meta.marker }),
|
|
2158
|
+
...(meta.hasCheckbox !== undefined && { hasCheckbox: meta.hasCheckbox }),
|
|
2159
|
+
tags: meta.tags,
|
|
2160
|
+
mentions: meta.mentions,
|
|
2161
|
+
...(meta.scheduledDate !== undefined && { scheduledDate: meta.scheduledDate }),
|
|
2162
|
+
paragraphStartLine: paragraphBounds.startIndex + 1,
|
|
2163
|
+
paragraphEndLine: paragraphBounds.endIndex + 1,
|
|
2164
|
+
paragraph,
|
|
2165
|
+
paragraphTruncated,
|
|
2166
|
+
contextBefore: allLines.slice(contextStart, lineIndex),
|
|
2167
|
+
contextAfter: allLines.slice(lineIndex + 1, contextEnd + 1),
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
const offset = toBoundedInt(params.cursor ?? params.offset, 0, 0, Number.MAX_SAFE_INTEGER);
|
|
2172
|
+
const limit = toBoundedInt(params.limit, 30, 1, 300);
|
|
2173
|
+
const page = allMatches.slice(offset, offset + limit);
|
|
2174
|
+
const hasMore = offset + page.length < allMatches.length;
|
|
2175
|
+
const nextCursor = hasMore ? String(offset + page.length) : null;
|
|
2176
|
+
const result = {
|
|
2177
|
+
success: true,
|
|
2178
|
+
query,
|
|
2179
|
+
count: page.length,
|
|
2180
|
+
totalCount: allMatches.length,
|
|
2181
|
+
offset,
|
|
2182
|
+
limit,
|
|
2183
|
+
hasMore,
|
|
2184
|
+
nextCursor,
|
|
2185
|
+
scannedNoteCount: scannedNotes.length,
|
|
2186
|
+
totalNotes: filteredNotes.length,
|
|
2187
|
+
truncatedByMaxNotes,
|
|
2188
|
+
maxNotes,
|
|
2189
|
+
noteTypes,
|
|
2190
|
+
preferCalendar,
|
|
2191
|
+
periodicOnly,
|
|
2192
|
+
matches: page,
|
|
2193
|
+
};
|
|
2194
|
+
if (hasMore) {
|
|
2195
|
+
result.performanceHints = ['Continue with nextCursor to fetch the next global paragraph match page.'];
|
|
2196
|
+
}
|
|
2197
|
+
if (truncatedByMaxNotes) {
|
|
2198
|
+
result.performanceHints = [
|
|
2199
|
+
...(result.performanceHints ?? []),
|
|
2200
|
+
'Increase maxNotes or narrow folder/space/noteQuery to reduce truncation.',
|
|
2201
|
+
];
|
|
2202
|
+
}
|
|
2203
|
+
return result;
|
|
2204
|
+
}
|
|
1959
2205
|
//# sourceMappingURL=notes.js.map
|