65 lines
2.5 KiB
TypeScript
65 lines
2.5 KiB
TypeScript
// Read-only GraphMCP lore lookup for encounter authoring. Lets the
|
|
// mardonar-encounter skill ground NPCs/setting in existing canon without writing
|
|
// to the knowledge graph. Uses the engine's own src/graphmcp/client.js (which
|
|
// already normalizes null / non-array GraphMCP responses).
|
|
//
|
|
// Requires GRAPHMCP_URL reachable from the host (default http://localhost:9000).
|
|
// If GraphMCP is unreachable, the fetch will throw — the skill surfaces that to
|
|
// the user as "GraphMCP unreachable — authoring without canon grounding."
|
|
//
|
|
// Usage (run from the engine repo root):
|
|
// npx tsx scripts/search-lore.ts search "<query>" [limit] # semantic_search
|
|
// npx tsx scripts/search-lore.ts npc "<name>" "<question>" [limit] # query_as_npc
|
|
//
|
|
// Exit 0 with results (or "no matches"); exit 1 on fetch/parse failure; exit 2 on usage error.
|
|
|
|
import { semanticSearch, queryAsNPC, formatNPCMemory } from '../src/graphmcp/client.js';
|
|
|
|
const mode = process.argv[2];
|
|
|
|
async function main(): Promise<void> {
|
|
if (mode === 'search') {
|
|
const query = process.argv[3];
|
|
const limit = Number(process.argv[4] ?? 5);
|
|
if (!query) {
|
|
console.error('Usage: npx tsx scripts/search-lore.ts search "<query>" [limit]');
|
|
process.exit(2);
|
|
}
|
|
try {
|
|
const r = await semanticSearch(query, limit);
|
|
if (r.chunks.length === 0) {
|
|
console.log('No lore chunks matched.');
|
|
return;
|
|
}
|
|
for (const c of r.chunks) {
|
|
const snippet = c.content.length > 300 ? c.content.slice(0, 297) + '…' : c.content;
|
|
console.log(`[${c.score.toFixed(3)}] ${c.source ?? '?'}: ${snippet}`);
|
|
}
|
|
} catch (err) {
|
|
console.error(`GraphMCP search failed: ${String((err as Error)?.message ?? err)}`);
|
|
process.exit(1);
|
|
}
|
|
} else if (mode === 'npc') {
|
|
const name = process.argv[3];
|
|
const question = process.argv[4];
|
|
const limit = Number(process.argv[5] ?? 5);
|
|
if (!name || !question) {
|
|
console.error('Usage: npx tsx scripts/search-lore.ts npc "<name>" "<question>" [limit]');
|
|
process.exit(2);
|
|
}
|
|
try {
|
|
const r = await queryAsNPC(name, question, limit);
|
|
console.log(formatNPCMemory(r));
|
|
} catch (err) {
|
|
console.error(`GraphMCP npc query failed: ${String((err as Error)?.message ?? err)}`);
|
|
process.exit(1);
|
|
}
|
|
} else {
|
|
console.error('Usage: npx tsx scripts/search-lore.ts search|npc ...');
|
|
console.error(' search "<query>" [limit]');
|
|
console.error(' npc "<name>" "<question>" [limit]');
|
|
process.exit(2);
|
|
}
|
|
}
|
|
|
|
await main(); |