Spaces:
Sleeping
Sleeping
Download cli/commands/memory.py from JuanCS-Dev/twitch-byte-bot: direct link, hf CLI and curl.
- Browser
- Download file 5.16 kB
-
https://huggingface.co/spaces/JuanCS-Dev/twitch-byte-bot/resolve/main/cli/commands/memory.py
- Command line
-
hf download hf://spaces/JuanCS-Dev/twitch-byte-bot/cli/commands/memory.py
-
curl -L -o memory.py https://huggingface.co/spaces/JuanCS-Dev/twitch-byte-bot/resolve/main/cli/commands/memory.py
5.16 kB
| # SPDX-License-Identifier: MIT | |
| """bytecli memory — Semantic memory management (list, search, add).""" | |
| from __future__ import annotations | |
| import argparse | |
| from typing import Any | |
| from cli.client import ByteClient | |
| from cli.config import CLIConfig | |
| from cli.formatters import ( | |
| format_timestamp, | |
| output, | |
| print_header, | |
| print_kv, | |
| print_success, | |
| print_table, | |
| ) | |
| def register(subparsers: argparse._SubParsersAction) -> None: | |
| parser = subparsers.add_parser( | |
| "memory", | |
| help="Semantic memory management (list, search, add)", | |
| description=( | |
| "Manage the agent's long-term semantic memory. The agent stores observations, " | |
| "rules, and facts here to recall them in future conversations.\n\n" | |
| "Endpoints: GET /api/memory, POST /api/memory, GET /api/memory/search" | |
| ), | |
| epilog=( | |
| "Examples:\n" | |
| " bytecli memory list --limit 10\n" | |
| " bytecli memory search 'favorite game'\n" | |
| " bytecli memory add 'Streamer hates backseating' --tags rule,preference\n" | |
| ), | |
| formatter_class=argparse.RawDescriptionHelpFormatter, | |
| ) | |
| sub = parser.add_subparsers(dest="memory_cmd", metavar="<action>") | |
| parser.set_defaults(handler=_handle_list) | |
| # list | |
| p_list = sub.add_parser("list", help="List recent semantic memory entries") | |
| p_list.add_argument("--limit", type=int, default=8, help="Max entries to return (default: 8)") | |
| p_list.set_defaults(handler=_handle_list) | |
| # search | |
| p_search = sub.add_parser( | |
| "search", | |
| help="Search memory by text/similarity", | |
| description="Searches semantic memory using embedding similarity or full-text search.", | |
| ) | |
| p_search.add_argument("query", help="Search query text") | |
| p_search.add_argument("--limit", type=int, default=8, help="Max results (default: 8)") | |
| p_search.set_defaults(handler=_handle_search) | |
| # add | |
| p_add = sub.add_parser( | |
| "add", | |
| help="Add a new manually-authored memory entry", | |
| description="Inserts a new semantic memory entry. The agent will read this context automatically based on relevance.", | |
| ) | |
| p_add.add_argument("content", help="The memory content to store") | |
| p_add.add_argument( | |
| "--type", dest="memory_type", default="manual", help="Memory type (default: manual)" | |
| ) | |
| p_add.add_argument("--tags", default="", help="Comma-separated tags (e.g. 'rule,preference')") | |
| p_add.set_defaults(handler=_handle_add) | |
| def _handle_list(args: argparse.Namespace, client: ByteClient, config: CLIConfig) -> None: | |
| params: dict[str, str] = {"limit": str(args.limit)} | |
| if config.channel != "default": | |
| params["channel"] = config.channel | |
| data = client.get("/api/semantic-memory", params) | |
| output(data, json_mode=config.json_output, human_fn=_human_list) | |
| def _human_list(data: dict[str, Any]) -> None: | |
| entries = data.get("entries", []) | |
| print_header(f"Semantic Memory ({len(entries)} entries)") | |
| if not entries: | |
| return | |
| rows = [] | |
| for e in entries: | |
| content = str(e.get("content", ""))[:50] | |
| mem_type = str(e.get("memory_type", e.get("type", "—"))) | |
| tags = ", ".join(e.get("tags", []) or []) | |
| rows.append([content, mem_type, tags[:30], format_timestamp(e.get("created_at"))]) | |
| print_table(["Content", "Type", "Tags", "Created"], rows) | |
| def _handle_search(args: argparse.Namespace, client: ByteClient, config: CLIConfig) -> None: | |
| params: dict[str, str] = { | |
| "query": args.query, | |
| "limit": str(args.limit), | |
| } | |
| if config.channel != "default": | |
| params["channel"] = config.channel | |
| data = client.get("/api/semantic-memory", params) | |
| output(data, json_mode=config.json_output, human_fn=_human_search) | |
| def _human_search(data: dict[str, Any]) -> None: | |
| matches = data.get("matches", []) | |
| diag = data.get("search_diagnostics", {}) | |
| print_header(f"Search Results ({len(matches)} matches)") | |
| if diag: | |
| print_kv( | |
| { | |
| "Engine": diag.get("engine", "—"), | |
| "Candidates": diag.get("candidate_count", 0), | |
| "Min Similarity": diag.get("min_similarity", "—"), | |
| } | |
| ) | |
| print() | |
| if not matches: | |
| return | |
| rows = [] | |
| for m in matches: | |
| content = str(m.get("content", ""))[:50] | |
| similarity = m.get("similarity", m.get("score", "—")) | |
| if isinstance(similarity, float): | |
| similarity = f"{similarity:.4f}" | |
| rows.append([content, str(similarity)]) | |
| print_table(["Content", "Similarity"], rows) | |
| def _handle_add(args: argparse.Namespace, client: ByteClient, config: CLIConfig) -> None: | |
| payload: dict[str, Any] = { | |
| "content": args.content, | |
| "memory_type": args.memory_type, | |
| "channel_id": config.channel, | |
| } | |
| if args.tags: | |
| payload["tags"] = [t.strip() for t in args.tags.split(",") if t.strip()] | |
| data = client.put("/api/semantic-memory", payload) | |
| output( | |
| data, json_mode=config.json_output, human_fn=lambda d: print_success("Memory entry added.") | |
| ) | |