mirror of
https://github.com/obra/episodic-memory.git
synced 2026-09-14 13:43:14 +08:00
f156416c49
Claude-Session: https://claude.ai/code/session_0112vdwZphiWzfCYfaXMes4C
132 lines
3.9 KiB
JavaScript
132 lines
3.9 KiB
JavaScript
import { searchConversations, formatResults, searchMultipleConcepts, formatMultiConceptResults } from './search.js';
|
|
const args = process.argv.slice(2);
|
|
// Parse arguments
|
|
let mode = 'both';
|
|
let after;
|
|
let before;
|
|
let project;
|
|
let sessionId;
|
|
let gitBranch;
|
|
let includeSidechains = true;
|
|
let limit = 10;
|
|
const queries = [];
|
|
for (let i = 0; i < args.length; i++) {
|
|
const arg = args[i];
|
|
if (arg === '--help' || arg === '-h') {
|
|
console.log(`
|
|
Usage: episodic-memory search [OPTIONS] <query>
|
|
|
|
Search indexed conversations using semantic similarity or exact text matching.
|
|
|
|
MODES:
|
|
(default) Combined vector + text search
|
|
--vector Vector similarity only (semantic)
|
|
--text Exact substring matching only (whole query matched verbatim;
|
|
best for git SHAs, error codes — not natural language)
|
|
|
|
OPTIONS:
|
|
--after DATE Only conversations after YYYY-MM-DD
|
|
--before DATE Only conversations before YYYY-MM-DD
|
|
--project NAME Filter by project name (exact match)
|
|
--session-id ID Filter by session ID (exact match)
|
|
--git-branch BRANCH Filter by git branch name (exact match)
|
|
--exclude-sidechains Search only the main thread; omit subagent/workflow
|
|
conversations (included and de-ranked by default)
|
|
--limit N Max results (default: 10)
|
|
--help, -h Show this help
|
|
|
|
EXAMPLES:
|
|
# Semantic search
|
|
episodic-memory search "React Router authentication errors"
|
|
|
|
# Find exact string
|
|
episodic-memory search --text "a1b2c3d4e5f6"
|
|
|
|
# Time filtering
|
|
episodic-memory search --after 2025-09-01 "refactoring"
|
|
|
|
# Filter to one project
|
|
episodic-memory search --project my-app "auth flow"
|
|
|
|
# Filter to one git branch
|
|
episodic-memory search --git-branch feature/login "validation"
|
|
|
|
# Combine modes
|
|
episodic-memory search --both "React Router data loading"
|
|
|
|
# Multi-concept search (AND - all concepts must match)
|
|
episodic-memory search "React Router" "authentication" "JWT"
|
|
`);
|
|
process.exit(0);
|
|
}
|
|
else if (arg === '--vector') {
|
|
mode = 'vector';
|
|
}
|
|
else if (arg === '--text') {
|
|
mode = 'text';
|
|
}
|
|
else if (arg === '--after') {
|
|
after = args[++i];
|
|
}
|
|
else if (arg === '--before') {
|
|
before = args[++i];
|
|
}
|
|
else if (arg === '--project') {
|
|
project = args[++i];
|
|
}
|
|
else if (arg === '--session-id') {
|
|
sessionId = args[++i];
|
|
}
|
|
else if (arg === '--git-branch') {
|
|
gitBranch = args[++i];
|
|
}
|
|
else if (arg === '--exclude-sidechains') {
|
|
includeSidechains = false;
|
|
}
|
|
else if (arg === '--limit') {
|
|
limit = parseInt(args[++i]);
|
|
}
|
|
else {
|
|
// All non-flag args are query terms
|
|
queries.push(arg);
|
|
}
|
|
}
|
|
if (queries.length === 0) {
|
|
console.error('Usage: episodic-memory search [OPTIONS] <query> [query2] [query3]...');
|
|
console.error('Try: episodic-memory search --help');
|
|
process.exit(1);
|
|
}
|
|
// Multi-concept search if multiple queries provided
|
|
if (queries.length > 1) {
|
|
const options = { limit, after, before, project, session_id: sessionId, git_branch: gitBranch, include_sidechains: includeSidechains };
|
|
searchMultipleConcepts(queries, options)
|
|
.then(async (results) => {
|
|
console.log(await formatMultiConceptResults(results, queries));
|
|
})
|
|
.catch(error => {
|
|
console.error('Error searching:', error);
|
|
process.exit(1);
|
|
});
|
|
}
|
|
else {
|
|
// Single query - use regular search
|
|
const options = {
|
|
mode,
|
|
limit,
|
|
after,
|
|
before,
|
|
project,
|
|
session_id: sessionId,
|
|
git_branch: gitBranch,
|
|
include_sidechains: includeSidechains,
|
|
};
|
|
searchConversations(queries[0], options)
|
|
.then(async (results) => {
|
|
console.log(await formatResults(results));
|
|
})
|
|
.catch(error => {
|
|
console.error('Error searching:', error);
|
|
process.exit(1);
|
|
});
|
|
}
|