@theronap/cortex-mcp 0.9.43 → 0.9.44
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/bin/cortex-mcp.mjs +1 -1
- package/lib/grep_cli.mjs +8 -4
- package/lib/grep_cli.test.mjs +8 -4
- package/lib/server.mjs +4 -4
- package/package.json +1 -1
package/bin/cortex-mcp.mjs
CHANGED
|
@@ -115,7 +115,7 @@ if (cmd === 'setup') {
|
|
|
115
115
|
const { closeFetch } = await import('../lib/diagnose.mjs')
|
|
116
116
|
await closeFetch()
|
|
117
117
|
} else if (cmd === 'grep') {
|
|
118
|
-
//
|
|
118
|
+
// Ranked keyword (fts) search by default; --substring/--literal for exact lookups. Thin client of /api/grep.
|
|
119
119
|
const { runGrep } = await import('../lib/grep_cli.mjs')
|
|
120
120
|
process.exitCode = await runGrep(rest)
|
|
121
121
|
const { closeFetch } = await import('../lib/diagnose.mjs')
|
package/lib/grep_cli.mjs
CHANGED
|
@@ -5,16 +5,20 @@ import { fetchCortex, classify, resolveBase } from './diagnose.mjs'
|
|
|
5
5
|
// Output is ASCII-only (outbound-message convention).
|
|
6
6
|
|
|
7
7
|
// Pure: parse argv after `grep` → { query, mode, max }.
|
|
8
|
-
// cortex grep <terms...> [--
|
|
8
|
+
// cortex grep <terms...> [--substring | --literal] [--max N]
|
|
9
|
+
// Default mode is 'fts' (ranked keyword — multi-word queries work); pass --substring/--literal for
|
|
10
|
+
// an exact literal match (identifiers, [[links]], code). (#220)
|
|
9
11
|
export function parseGrepArgs(argv = []) {
|
|
10
|
-
const out = { query: '', mode: '
|
|
12
|
+
const out = { query: '', mode: 'fts', max: undefined }
|
|
11
13
|
const terms = []
|
|
12
14
|
for (let i = 0; i < argv.length; i++) {
|
|
13
15
|
const a = argv[i]
|
|
14
16
|
if (a === '--mode') {
|
|
15
|
-
out.mode = argv[++i] === '
|
|
17
|
+
out.mode = argv[++i] === 'substring' ? 'substring' : 'fts'
|
|
16
18
|
} else if (a === '--fts') {
|
|
17
19
|
out.mode = 'fts'
|
|
20
|
+
} else if (a === '--substring' || a === '--literal') {
|
|
21
|
+
out.mode = 'substring'
|
|
18
22
|
} else if (a === '--max') {
|
|
19
23
|
const n = Number(argv[++i])
|
|
20
24
|
if (Number.isFinite(n)) out.max = Math.trunc(n)
|
|
@@ -50,7 +54,7 @@ export async function runGrep(rest = []) {
|
|
|
50
54
|
}
|
|
51
55
|
const { query, mode, max } = parseGrepArgs(rest)
|
|
52
56
|
if (!query) {
|
|
53
|
-
process.stderr.write('usage: cortex grep <query> [--
|
|
57
|
+
process.stderr.write('usage: cortex grep <query> [--substring|--literal] [--max N]\n')
|
|
54
58
|
return 1
|
|
55
59
|
}
|
|
56
60
|
const qs = new URLSearchParams({ q: query, mode })
|
package/lib/grep_cli.test.mjs
CHANGED
|
@@ -2,13 +2,17 @@ import { describe, it, expect } from 'bun:test'
|
|
|
2
2
|
import { parseGrepArgs, formatGrepHits } from './grep_cli.mjs'
|
|
3
3
|
|
|
4
4
|
describe('parseGrepArgs', () => {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
// #220: default is 'fts' (ranked keyword); --substring/--literal opts back into exact matching.
|
|
6
|
+
it('joins free terms into the query, defaults fts', () => {
|
|
7
|
+
expect(parseGrepArgs(['hello', 'world'])).toEqual({ query: 'hello world', mode: 'fts', max: undefined })
|
|
7
8
|
})
|
|
8
|
-
it('honors --
|
|
9
|
+
it('honors --substring/--literal to force exact matching, else fts', () => {
|
|
10
|
+
expect(parseGrepArgs(['q', '--substring']).mode).toBe('substring')
|
|
11
|
+
expect(parseGrepArgs(['q', '--literal']).mode).toBe('substring')
|
|
12
|
+
expect(parseGrepArgs(['q', '--mode', 'substring']).mode).toBe('substring')
|
|
9
13
|
expect(parseGrepArgs(['q', '--mode', 'fts']).mode).toBe('fts')
|
|
10
14
|
expect(parseGrepArgs(['--fts', 'q']).mode).toBe('fts')
|
|
11
|
-
expect(parseGrepArgs(['q', '--mode', 'bogus']).mode).toBe('
|
|
15
|
+
expect(parseGrepArgs(['q', '--mode', 'bogus']).mode).toBe('fts')
|
|
12
16
|
})
|
|
13
17
|
it('parses --max as an integer, ignores non-numeric', () => {
|
|
14
18
|
expect(parseGrepArgs(['q', '--max', '25']).max).toBe(25)
|
package/lib/server.mjs
CHANGED
|
@@ -266,14 +266,14 @@ export async function runServer(version) {
|
|
|
266
266
|
{
|
|
267
267
|
title: 'Grep the brain wiki',
|
|
268
268
|
description:
|
|
269
|
-
'
|
|
269
|
+
'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]]. Returns matching sections with a context snippet and their outbound [[links]].',
|
|
270
270
|
inputSchema: {
|
|
271
|
-
query: z.string().describe('
|
|
272
|
-
mode: z.enum(['substring', 'fts']).optional().describe("'
|
|
271
|
+
query: z.string().describe('search terms (natural language is fine)'),
|
|
272
|
+
mode: z.enum(['substring', 'fts']).optional().describe("'fts' (default, ranked keyword) or 'substring' (exact literal — for identifiers / [[links]] / code)"),
|
|
273
273
|
},
|
|
274
274
|
},
|
|
275
275
|
async ({ query, mode }) => {
|
|
276
|
-
const qs = new URLSearchParams({ q: query, mode: mode === '
|
|
276
|
+
const qs = new URLSearchParams({ q: query, mode: mode === 'substring' ? 'substring' : 'fts' })
|
|
277
277
|
const res = await fetchCortex(`${BASE}/api/grep?${qs.toString()}`, { headers: { Authorization: `Bearer ${TOKEN}` } })
|
|
278
278
|
if (!res.ok) {
|
|
279
279
|
const body = await res.text()
|