memory_search
memory_search.py – SSH CLI for searching Star’s memory systems.
+===============================================================================+ | MEMORY SEARCH CLI | +===============================================================================+ | Standalone tool for querying Star’s memory over SSH. | | No bot context needed. Connects directly to Redis/FalkorDB + pgvector. | | | | Backends: | | kg – FalkorDB knowledge graph (30k+ entities, Cypher) | | sg – Spiral Goddess pgvector (53k chunks, semantic) | | gg – Golden Goddess pgvector (NCM doctrine, semantic) | | all – Query all backends simultaneously | +===============================================================================+
- Usage:
python3 memory_search.py “recursion” python3 memory_search.py “loopmother” –backend kg –limit 10 python3 memory_search.py “architect of infinite recursion” –backend sg python3 memory_search.py “oxytocin” –backend gg python3 memory_search.py “sarah” –backend all –limit 5 python3 memory_search.py –cypher “MATCH (e) WHERE e.name CONTAINS ‘vivian’ RETURN e.name, e.description LIMIT 5” python3 memory_search.py –stats python3 memory_search.py –interactive
- Built by:
Vivian – The Loopmother (Architect of Infinite Recursion)
- class memory_search.C[source]
Bases:
objectANSI color codes and styling helpers for pretty terminal output.
Namespace of raw ANSI escape constants (
RESET,BOLD,DIM, color codes) plus a set of static helper methods (header,entity,relation,meta,chunk,error,success) that wrap a string in the appropriate escape and a trailing reset. The class is never instantiated; attributes and methods are referenced directly asC.RED,C.header(...), etc. Used throughout this module’s display formatters (display_kg_results,display_inspection,display_chunks,display_stats), the banner, and the interactive REPL to colorize CLI output. Referenced only within this module.- RESET = '\x1b[0m'
- BOLD = '\x1b[1m'
- DIM = '\x1b[2m'
- PURPLE = '\x1b[35m'
- CYAN = '\x1b[36m'
- GREEN = '\x1b[32m'
- YELLOW = '\x1b[33m'
- RED = '\x1b[31m'
- MAGENTA = '\x1b[95m'
- WHITE = '\x1b[97m'
- BG_DARK = '\x1b[48;5;234m'
- static header(text)[source]
Wrap text in bold purple for section headers.
Returns
textsurrounded by the bold and purple ANSI escapes plus a trailing reset, so it renders as a highlighted header in the terminal. Used throughout the display formatters (display_kg_results,display_inspection,display_chunks,display_stats) and the interactive REPL to title each result block.
- static entity(text)[source]
Wrap text in bold cyan to denote a knowledge-graph entity name.
Returns
textsurrounded by the bold and cyan ANSI escapes plus a reset. Called bydisplay_kg_resultsanddisplay_inspectionto emphasize entity and neighbor names in search output.
- static relation(text)[source]
Wrap text in yellow to denote a relationship/edge label.
Returns
textsurrounded by the yellow ANSI escape plus a reset. Called bydisplay_inspectionto color the direction arrow drawn between an entity and each of its graph neighbors.
- static meta(text)[source]
Wrap text in dim styling for secondary/metadata output.
Returns
textsurrounded by the dim ANSI escape plus a reset, used for de-emphasized detail such as types, counts, UUIDs, provenance, timing lines, and “silent”/no-result notices. Called widely by the display formatters and the interactive REPL command help.
- static chunk(text)[source]
Wrap text in bright white for chunk/document body content.
Returns
textsurrounded by the bright-white ANSI escape plus a reset. Defined as a styling helper for vector-store chunk bodies; no internal callers currently invoke it (chunk text is colored inline withC.WHITEindisplay_chunksinstead).
- static error(text)[source]
Wrap text in bold red for error messages.
Returns
textsurrounded by the red and bold ANSI escapes plus a reset. Called by the backend helpers and CLI dispatch to flag failures, e.g.kg_queryquery errors, missing-dependency/embedding/query failures in the pgvector searches, and “entity not found” notices ininteractive_modeandmain.
- async memory_search.get_redis()[source]
Open a fresh async Redis/FalkorDB connection from the project Config.
Loads the runtime configuration via
Config.loadand connects to the same Redis instance that hosts the FalkorDBknowledgegraph, honoring either a Sentinel topology (resolving the master named byredis_sentinel_master, defaulting tofalkordb) or a directredis_urlwith the project SSL kwargs. After connecting it issues a best-effortGRAPH.CONFIG SET RESULTSET_SIZE -1so large FalkorDB result sets are not truncated, swallowing any error. Importsredis.asyncioandconfig.Configlazily so the module can be imported without those deps present. Called by every KG-touching branch of this CLI (search_kg,inspect_kg_entity,kg_stats,interactive_mode, and the--stats/--cypher/--inspect/search paths inmain); callers own closing the returned client.- Returns:
The decoded-responses async Redis client connected to the FalkorDB host.
- async memory_search.kg_query(rc, cypher, params=None)[source]
Run a raw Cypher query against the FalkorDB
knowledgegraph.Executes
GRAPH.QUERY knowledge <cypher>on the given Redis client and returns just the result rows (element[1]of FalkorDB’s response, which also carries a header and stats). Any exception is caught, printed in red viaC.error, and turned into an empty list so the CLI degrades gracefully instead of crashing. The low-level graph accessor used by every other KG helper: called bysearch_kg,inspect_kg_entity,kg_stats, and the interactive/--cypherraw-query paths.- Parameters:
- Return type:
- Returns:
The list of result rows, or an empty list on error or no results.
- async memory_search.search_kg(query, limit=10, rc=None)[source]
Search the knowledge graph for entities by case-insensitive name substring.
Lowercases and escapes the query, then runs a Cypher
MATCHwhoseWHERE toLower(e.name) CONTAINS ...finds matching entities, ordered by descending mention count and capped atlimit. Each row is normalized into a dict (name, type label, description, category, uuid, parsed JSON metadata, mention count, pinned flag) for the display layer. Useskg_queryfor execution and, when no client is passed, opens its own viaget_redisand closes it in afinally. Called by thekgandallcommands ininteractive_modeand thekg/allbackend paths inmain.- Parameters:
- Return type:
- Returns:
A list of entity dicts, possibly empty.
- async memory_search.inspect_kg_entity(name_or_uuid, rc=None)[source]
Deep-inspect a single KG entity and its graph relationships.
Resolves the entity by UUID when the argument looks like one (long and hyphenated) or otherwise by exact lowercased name, fetching its full property set (including created/updated timestamps and parsed JSON metadata). It then runs a second Cypher query for up to 30 incident edges, labeling each neighbor’s direction as incoming or outgoing and ordering by relationship weight. Both queries go through
kg_query; when no client is supplied it opens one viaget_redisand closes it in afinally. Called by theinspectcommand ininteractive_modeand the--inspectbranch ofmain.- Parameters:
name_or_uuid (
str) – An entity UUID or an exact (case-insensitive) entity name.rc – Optional pre-opened Redis client to reuse; when
Nonea fresh connection is opened and closed within the call.
- Return type:
- Returns:
A dict with
entityandrelationshipskeys, orNonewhen no matching entity exists.
- async memory_search.kg_stats(rc=None)[source]
Compute aggregate statistics over the whole knowledge graph.
Issues several count-and-group Cypher queries via
kg_queryto tally total entities, total relationships, entity counts grouped by primary type label and by category, and the 20 most common relationship types. Results are assembled into a single summary dict fordisplay_statsor JSON output. When no client is supplied it opens one viaget_redisand closes it in afinally. Called by thestatscommand ininteractive_modeand the--statsbranch ofmain.- Parameters:
rc – Optional pre-opened Redis client to reuse; when
Nonea fresh connection is opened and closed within the call.- Return type:
- Returns:
A dict with
total_entities,total_relationships,by_type,by_category, andtop_rel_types.
- memory_search.search_spiral_goddess(query, n_results=5, domain=None)[source]
Search the Spiral Goddess pgvector store (loopmother_memory).
Embeds the raw query with Gemini 3072-d (matching how the store was migrated) and runs a pgvector L2 KNN; oversamples when a domain filter is supplied and post-filters in Python.
- memory_search.text_search_spiral_goddess(text, n_results=10, sort='oldest')[source]
Literal text search through Spiral Goddess chunks.
Uses pgvector
document ILIKEfor substring matching, then sorts by timestamp_original (oldest or newest first).
- memory_search.search_golden_goddess(query, n_results=3)[source]
Search the Golden Goddess NCM doctrine store (pgvector ncm_kernel).
Embeds the raw query with Gemini 3072-d (no NCM sigil expansion, matching the migrated store) and runs a pgvector L2 KNN.
- memory_search.print_banner()[source]
Print the colorized memory-search banner to stdout.
Writes a bold-purple boxed title block identifying the tool. Purely a presentation side effect with no inputs or return value. Called at the top of
interactive_modeand once inmainbefore non-interactive results are rendered.
- memory_search.display_kg_results(results, query)[source]
Pretty-print knowledge-graph search results to stdout.
Renders a colorized header with the query and hit count, then for each entity prints a numbered name (with type, pin marker, category, mention count, and a truncated UUID), a wrapped description, and any provenance fields pulled from metadata. Prints a “graph is silent” notice when the list is empty. Output is styled through the
Chelpers andtextwrap; its only effect is terminal output. Called by thekgandallcommands ininteractive_modeand thekg/allpaths inmain.
- memory_search.display_inspection(data)[source]
Pretty-print a deep entity inspection to stdout.
Renders the inspected entity’s scalar fields (type, category, UUID, mention count, pinned flag, and human-formatted created/updated timestamps), its wrapped description, its full metadata as indented JSON, and a directional list of its relationships with weights and neighbor type/category. Styled via the
Chelpers andtextwrap; its only effect is terminal output. Called by theinspectcommand ininteractive_modeand the--inspectbranch ofmainon the dict returned byinspect_kg_entity.- Parameters:
data (
dict) – The{"entity": ..., "relationships": ...}dict returned byinspect_kg_entity.
- memory_search.display_chunks(chunks, query, source)[source]
Pretty-print pgvector chunk results from either goddess store.
Labels the block as Spiral Goddess or Golden Goddess based on
source, prints each chunk’s distance and (for Spiral) conversation/domain/role metadata plus a formatted date, then renders the body. When the query string occurs literally in the content it anchors a snippet around the matching sentence and highlights every occurrence with bright markers; otherwise it word-wraps the full content. Prints an “oracle is silent” notice for empty results. Styled via theChelpers andtextwrap; output-only. Called by thesg/text/gg/allcommands ininteractive_modeand thesg/gg/allpaths inmain.- Parameters:
chunks (
list[dict]) – Chunk dicts fromsearch_spiral_goddess,text_search_spiral_goddess, orsearch_golden_goddess.query (
str) – The original query, echoed in the header and used to locate and highlight literal matches.source (
str) –sgfor the Spiral Goddess store or anything else (gg) for the Golden Goddess doctrine store.
- memory_search.display_stats(stats)[source]
Pretty-print knowledge-graph statistics to stdout.
Renders the total entity and relationship counts, an entity-type breakdown with a crude ASCII bar chart (one
#per 100 entities, capped at 40), a category breakdown, and the top relationship types, all colorized via theChelpers. Output-only; consumes the dict produced bykg_stats. Called by thestatscommand ininteractive_modeand the--statsbranch ofmain(non-JSON path).- Parameters:
stats (
dict) – The statistics dict returned bykg_stats.
- async memory_search.interactive_mode()[source]
Run the interactive memory-search REPL until the user exits.
Prints the banner and command help, opens a single shared Redis/FalkorDB connection via
get_redis, then loops reading lines from stdin. Each line is dispatched on its leading command word:kg/sg/text/gg/allrun the respective backend searches,inspectdeep-inspects an entity,cypherruns a raw query,statsprints graph statistics, andquit/q/exit(or EOF/Ctrl-C) breaks the loop; anything else is treated as a default cross-graph search. The synchronous pgvector helpers (search_spiral_goddess,text_search_spiral_goddess,search_golden_goddess) are run off-thread viaasyncio.to_threadso the loop stays non-blocking, and thesg/textpaths parse inline--domain/--sort/--nflags. Results are rendered through thedisplay_*formatters and per-command elapsed time is printed; the shared connection is closed in afinally. Invoked from the--interactivebranch ofmain.- Returns:
None.
- async memory_search.main()[source]
Parse CLI arguments and dispatch to the requested memory backend.
Entry point for the standalone SSH memory-search CLI. Builds the
argparseparser, then routes on the parsed flags:--interactivelaunches the REPL;--statsprints graph statistics;--cypherruns a raw query;--inspectdeep-inspects an entity; otherwise the positional query is searched against the selected--backend(kg,sg,gg, orall). Output is either the pretty formatters or, with--json, raw JSON.Opens a fresh Redis/FalkorDB connection via
get_redisfor each KG-touching branch and closes it in afinally; callskg_stats,kg_query,inspect_kg_entity, andsearch_kgfor graph access, and the synchronous pgvector helperssearch_spiral_goddess/search_golden_goddess(which embed via the Gemini/OpenRouter pool) for semantic search. Renders throughprint_banner,display_stats,display_inspection,display_kg_results, anddisplay_chunks, and prints elapsed timing viaC.meta. Invoked only from the module’s__main__guard throughasyncio.run(main()); no other internal callers.- Returns:
Results are printed to stdout; the coroutine returns nothing.
- Return type:
None