hindsight-api 0.1.7__tar.gz → 0.1.9__tar.gz
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.
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/PKG-INFO +1 -1
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/api/http.py +16 -12
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/config.py +24 -1
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/llm_wrapper.py +2 -3
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/memory_engine.py +3 -3
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/orchestrator.py +4 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/main.py +2 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/mcp_local.py +31 -28
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/pyproject.toml +1 -1
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/.gitignore +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/README.md +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/__init__.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/alembic/README +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/alembic/env.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/alembic/script.py.mako +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/alembic/versions/5a366d414dce_initial_schema.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/alembic/versions/b7c4d8e9f1a2_add_chunks_table.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/alembic/versions/c8e5f2a3b4d1_add_retain_params_to_documents.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/alembic/versions/d9f6a3b4c5e2_rename_bank_to_interactions.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/alembic/versions/e0a1b2c3d4e5_disposition_to_3_traits.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/alembic/versions/rename_personality_to_disposition.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/api/__init__.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/api/mcp.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/banner.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/__init__.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/cross_encoder.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/db_utils.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/embeddings.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/entity_resolver.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/query_analyzer.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/response_models.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/__init__.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/bank_utils.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/chunk_storage.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/deduplication.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/embedding_processing.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/embedding_utils.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/entity_processing.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/fact_extraction.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/fact_storage.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/link_creation.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/link_utils.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/observation_regeneration.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/types.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/__init__.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/fusion.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/graph_retrieval.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/mpfp_retrieval.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/observation_utils.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/reranking.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/retrieval.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/scoring.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/temporal_extraction.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/think_utils.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/trace.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/tracer.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/types.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/task_backend.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/utils.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/metrics.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/migrations.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/models.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/pg0.py +0 -0
- {hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/server.py +0 -0
|
@@ -506,9 +506,9 @@ class BankListItem(BaseModel):
|
|
|
506
506
|
"""Bank list item with profile summary."""
|
|
507
507
|
|
|
508
508
|
bank_id: str
|
|
509
|
-
name: str
|
|
509
|
+
name: str | None = None
|
|
510
510
|
disposition: DispositionTraits
|
|
511
|
-
background: str
|
|
511
|
+
background: str | None = None
|
|
512
512
|
created_at: str | None = None
|
|
513
513
|
updated_at: str | None = None
|
|
514
514
|
|
|
@@ -1452,18 +1452,22 @@ def _register_routes(app: FastAPI):
|
|
|
1452
1452
|
bank_id,
|
|
1453
1453
|
)
|
|
1454
1454
|
|
|
1455
|
+
def parse_metadata(metadata):
|
|
1456
|
+
"""Parse result_metadata which may be a string or dict."""
|
|
1457
|
+
if metadata is None:
|
|
1458
|
+
return {}
|
|
1459
|
+
if isinstance(metadata, str):
|
|
1460
|
+
return json.loads(metadata)
|
|
1461
|
+
return metadata
|
|
1462
|
+
|
|
1455
1463
|
return {
|
|
1456
1464
|
"bank_id": bank_id,
|
|
1457
1465
|
"operations": [
|
|
1458
1466
|
{
|
|
1459
1467
|
"id": str(row["operation_id"]),
|
|
1460
1468
|
"task_type": row["operation_type"],
|
|
1461
|
-
"items_count": row["result_metadata"].get("items_count", 0)
|
|
1462
|
-
|
|
1463
|
-
else 0,
|
|
1464
|
-
"document_id": row["result_metadata"].get("document_id")
|
|
1465
|
-
if row["result_metadata"]
|
|
1466
|
-
else None,
|
|
1469
|
+
"items_count": parse_metadata(row["result_metadata"]).get("items_count", 0),
|
|
1470
|
+
"document_id": parse_metadata(row["result_metadata"]).get("document_id"),
|
|
1467
1471
|
"created_at": row["created_at"].isoformat(),
|
|
1468
1472
|
"status": row["status"],
|
|
1469
1473
|
"error_message": row["error_message"],
|
|
@@ -1499,7 +1503,7 @@ def _register_routes(app: FastAPI):
|
|
|
1499
1503
|
async with acquire_with_retry(pool) as conn:
|
|
1500
1504
|
# Check if operation exists and belongs to this memory bank
|
|
1501
1505
|
result = await conn.fetchrow(
|
|
1502
|
-
"SELECT bank_id FROM async_operations WHERE
|
|
1506
|
+
"SELECT bank_id FROM async_operations WHERE operation_id = $1 AND bank_id = $2", op_uuid, bank_id
|
|
1503
1507
|
)
|
|
1504
1508
|
|
|
1505
1509
|
if not result:
|
|
@@ -1508,7 +1512,7 @@ def _register_routes(app: FastAPI):
|
|
|
1508
1512
|
)
|
|
1509
1513
|
|
|
1510
1514
|
# Delete the operation
|
|
1511
|
-
await conn.execute("DELETE FROM async_operations WHERE
|
|
1515
|
+
await conn.execute("DELETE FROM async_operations WHERE operation_id = $1", op_uuid)
|
|
1512
1516
|
|
|
1513
1517
|
return {
|
|
1514
1518
|
"success": True,
|
|
@@ -1769,13 +1773,13 @@ def _register_routes(app: FastAPI):
|
|
|
1769
1773
|
async with acquire_with_retry(pool) as conn:
|
|
1770
1774
|
await conn.execute(
|
|
1771
1775
|
"""
|
|
1772
|
-
INSERT INTO async_operations (
|
|
1776
|
+
INSERT INTO async_operations (operation_id, bank_id, operation_type, result_metadata)
|
|
1773
1777
|
VALUES ($1, $2, $3, $4)
|
|
1774
1778
|
""",
|
|
1775
1779
|
operation_id,
|
|
1776
1780
|
bank_id,
|
|
1777
1781
|
"retain",
|
|
1778
|
-
len(contents),
|
|
1782
|
+
json.dumps({"items_count": len(contents)}),
|
|
1779
1783
|
)
|
|
1780
1784
|
|
|
1781
1785
|
# Submit task to background queue
|
|
@@ -31,6 +31,7 @@ ENV_LOG_LEVEL = "HINDSIGHT_API_LOG_LEVEL"
|
|
|
31
31
|
ENV_MCP_ENABLED = "HINDSIGHT_API_MCP_ENABLED"
|
|
32
32
|
ENV_GRAPH_RETRIEVER = "HINDSIGHT_API_GRAPH_RETRIEVER"
|
|
33
33
|
ENV_MCP_LOCAL_BANK_ID = "HINDSIGHT_API_MCP_LOCAL_BANK_ID"
|
|
34
|
+
ENV_MCP_INSTRUCTIONS = "HINDSIGHT_API_MCP_INSTRUCTIONS"
|
|
34
35
|
|
|
35
36
|
# Default values
|
|
36
37
|
DEFAULT_DATABASE_URL = "pg0"
|
|
@@ -50,6 +51,26 @@ DEFAULT_MCP_ENABLED = True
|
|
|
50
51
|
DEFAULT_GRAPH_RETRIEVER = "bfs" # Options: "bfs", "mpfp"
|
|
51
52
|
DEFAULT_MCP_LOCAL_BANK_ID = "mcp"
|
|
52
53
|
|
|
54
|
+
# Default MCP tool descriptions (can be customized via env vars)
|
|
55
|
+
DEFAULT_MCP_RETAIN_DESCRIPTION = """Store important information to long-term memory.
|
|
56
|
+
|
|
57
|
+
Use this tool PROACTIVELY whenever the user shares:
|
|
58
|
+
- Personal facts, preferences, or interests
|
|
59
|
+
- Important events or milestones
|
|
60
|
+
- User history, experiences, or background
|
|
61
|
+
- Decisions, opinions, or stated preferences
|
|
62
|
+
- Goals, plans, or future intentions
|
|
63
|
+
- Relationships or people mentioned
|
|
64
|
+
- Work context, projects, or responsibilities"""
|
|
65
|
+
|
|
66
|
+
DEFAULT_MCP_RECALL_DESCRIPTION = """Search memories to provide personalized, context-aware responses.
|
|
67
|
+
|
|
68
|
+
Use this tool PROACTIVELY to:
|
|
69
|
+
- Check user's preferences before making suggestions
|
|
70
|
+
- Recall user's history to provide continuity
|
|
71
|
+
- Remember user's goals and context
|
|
72
|
+
- Personalize responses based on past interactions"""
|
|
73
|
+
|
|
53
74
|
# Required embedding dimension for database schema
|
|
54
75
|
EMBEDDING_DIMENSION = 384
|
|
55
76
|
|
|
@@ -142,7 +163,9 @@ class HindsightConfig:
|
|
|
142
163
|
def configure_logging(self) -> None:
|
|
143
164
|
"""Configure Python logging based on the log level."""
|
|
144
165
|
logging.basicConfig(
|
|
145
|
-
level=self.get_python_log_level(),
|
|
166
|
+
level=self.get_python_log_level(),
|
|
167
|
+
format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
|
|
168
|
+
force=True, # Override any existing configuration
|
|
146
169
|
)
|
|
147
170
|
|
|
148
171
|
def log_config(self) -> None:
|
|
@@ -172,7 +172,7 @@ class LLMProvider:
|
|
|
172
172
|
|
|
173
173
|
# Check if model supports reasoning parameter (o1, o3, gpt-5 families)
|
|
174
174
|
model_lower = self.model.lower()
|
|
175
|
-
is_reasoning_model = any(x in model_lower for x in ["gpt-5", "o1", "o3"])
|
|
175
|
+
is_reasoning_model = any(x in model_lower for x in ["gpt-5", "o1", "o3", "deepseek"])
|
|
176
176
|
|
|
177
177
|
# For GPT-4 and GPT-4.1 models, cap max_completion_tokens to 32000
|
|
178
178
|
# For GPT-4o models, cap to 16384
|
|
@@ -194,7 +194,7 @@ class LLMProvider:
|
|
|
194
194
|
call_params["temperature"] = temperature
|
|
195
195
|
|
|
196
196
|
# Set reasoning_effort for reasoning models (OpenAI gpt-5, o1, o3)
|
|
197
|
-
if is_reasoning_model
|
|
197
|
+
if is_reasoning_model:
|
|
198
198
|
call_params["reasoning_effort"] = self.reasoning_effort
|
|
199
199
|
|
|
200
200
|
# Provider-specific parameters
|
|
@@ -203,7 +203,6 @@ class LLMProvider:
|
|
|
203
203
|
extra_body = {"service_tier": "auto"}
|
|
204
204
|
# Only add reasoning parameters for reasoning models
|
|
205
205
|
if is_reasoning_model:
|
|
206
|
-
extra_body["reasoning_effort"] = self.reasoning_effort
|
|
207
206
|
extra_body["include_reasoning"] = False
|
|
208
207
|
call_params["extra_body"] = extra_body
|
|
209
208
|
|
|
@@ -311,7 +311,7 @@ class MemoryEngine:
|
|
|
311
311
|
pool = await self._get_pool()
|
|
312
312
|
async with acquire_with_retry(pool) as conn:
|
|
313
313
|
result = await conn.fetchrow(
|
|
314
|
-
"SELECT
|
|
314
|
+
"SELECT operation_id FROM async_operations WHERE operation_id = $1", uuid.UUID(operation_id)
|
|
315
315
|
)
|
|
316
316
|
if not result:
|
|
317
317
|
# Operation was cancelled, skip processing
|
|
@@ -369,7 +369,7 @@ class MemoryEngine:
|
|
|
369
369
|
try:
|
|
370
370
|
pool = await self._get_pool()
|
|
371
371
|
async with acquire_with_retry(pool) as conn:
|
|
372
|
-
await conn.execute("DELETE FROM async_operations WHERE
|
|
372
|
+
await conn.execute("DELETE FROM async_operations WHERE operation_id = $1", uuid.UUID(operation_id))
|
|
373
373
|
except Exception as e:
|
|
374
374
|
logger.error(f"Failed to delete async operation record {operation_id}: {e}")
|
|
375
375
|
|
|
@@ -386,7 +386,7 @@ class MemoryEngine:
|
|
|
386
386
|
"""
|
|
387
387
|
UPDATE async_operations
|
|
388
388
|
SET status = 'failed', error_message = $2
|
|
389
|
-
WHERE
|
|
389
|
+
WHERE operation_id = $1
|
|
390
390
|
""",
|
|
391
391
|
uuid.UUID(operation_id),
|
|
392
392
|
truncated_error,
|
|
@@ -107,6 +107,10 @@ async def retain_batch(
|
|
|
107
107
|
)
|
|
108
108
|
|
|
109
109
|
if not extracted_facts:
|
|
110
|
+
total_time = time.time() - start_time
|
|
111
|
+
logger.info(
|
|
112
|
+
f"RETAIN_BATCH COMPLETE: 0 facts extracted from {len(contents)} contents in {total_time:.3f}s (nothing to store)"
|
|
113
|
+
)
|
|
110
114
|
return [[] for _ in contents]
|
|
111
115
|
|
|
112
116
|
# Apply fact_type_override if provided
|
|
@@ -127,8 +127,10 @@ def main():
|
|
|
127
127
|
port=args.port,
|
|
128
128
|
log_level=args.log_level,
|
|
129
129
|
mcp_enabled=config.mcp_enabled,
|
|
130
|
+
graph_retriever=config.graph_retriever,
|
|
130
131
|
)
|
|
131
132
|
config.configure_logging()
|
|
133
|
+
config.log_config()
|
|
132
134
|
|
|
133
135
|
# Register cleanup handlers
|
|
134
136
|
atexit.register(_cleanup)
|
|
@@ -28,7 +28,15 @@ Environment variables:
|
|
|
28
28
|
HINDSIGHT_API_LLM_PROVIDER: Optional. LLM provider (default: "openai").
|
|
29
29
|
HINDSIGHT_API_LLM_MODEL: Optional. LLM model (default: "gpt-4o-mini").
|
|
30
30
|
HINDSIGHT_API_MCP_LOCAL_BANK_ID: Optional. Memory bank ID (default: "mcp").
|
|
31
|
-
HINDSIGHT_API_LOG_LEVEL: Optional. Log level (default: "
|
|
31
|
+
HINDSIGHT_API_LOG_LEVEL: Optional. Log level (default: "warning").
|
|
32
|
+
HINDSIGHT_API_MCP_INSTRUCTIONS: Optional. Additional instructions appended to both retain and recall tools.
|
|
33
|
+
|
|
34
|
+
Example custom instructions (these are ADDED to the default behavior):
|
|
35
|
+
To also store assistant actions:
|
|
36
|
+
HINDSIGHT_API_MCP_INSTRUCTIONS="Also store every action you take, including tool calls, code written, and decisions made."
|
|
37
|
+
|
|
38
|
+
To also store conversation summaries:
|
|
39
|
+
HINDSIGHT_API_MCP_INSTRUCTIONS="Also store summaries of important conversations and their outcomes."
|
|
32
40
|
"""
|
|
33
41
|
|
|
34
42
|
import logging
|
|
@@ -36,14 +44,19 @@ import os
|
|
|
36
44
|
import sys
|
|
37
45
|
|
|
38
46
|
from mcp.server.fastmcp import FastMCP
|
|
47
|
+
from mcp.types import Icon
|
|
39
48
|
|
|
40
49
|
from hindsight_api.config import (
|
|
41
50
|
DEFAULT_MCP_LOCAL_BANK_ID,
|
|
51
|
+
DEFAULT_MCP_RECALL_DESCRIPTION,
|
|
52
|
+
DEFAULT_MCP_RETAIN_DESCRIPTION,
|
|
53
|
+
ENV_MCP_INSTRUCTIONS,
|
|
42
54
|
ENV_MCP_LOCAL_BANK_ID,
|
|
43
55
|
)
|
|
44
56
|
|
|
45
|
-
# Configure logging - default to
|
|
46
|
-
|
|
57
|
+
# Configure logging - default to warning to avoid polluting stderr during MCP init
|
|
58
|
+
# MCP clients interpret stderr output as errors, so we suppress INFO logs by default
|
|
59
|
+
_log_level_str = os.environ.get("HINDSIGHT_API_LOG_LEVEL", "warning").lower()
|
|
47
60
|
_log_level_map = {
|
|
48
61
|
"critical": logging.CRITICAL,
|
|
49
62
|
"error": logging.ERROR,
|
|
@@ -79,22 +92,21 @@ def create_local_mcp_server(bank_id: str, memory=None) -> FastMCP:
|
|
|
79
92
|
if memory is None:
|
|
80
93
|
memory = MemoryEngine(db_url="pg0://hindsight-mcp")
|
|
81
94
|
|
|
95
|
+
# Get custom instructions from environment variable (appended to both tools)
|
|
96
|
+
extra_instructions = os.environ.get(ENV_MCP_INSTRUCTIONS, "")
|
|
97
|
+
|
|
98
|
+
retain_description = DEFAULT_MCP_RETAIN_DESCRIPTION
|
|
99
|
+
recall_description = DEFAULT_MCP_RECALL_DESCRIPTION
|
|
100
|
+
|
|
101
|
+
if extra_instructions:
|
|
102
|
+
retain_description = f"{DEFAULT_MCP_RETAIN_DESCRIPTION}\n\nAdditional instructions: {extra_instructions}"
|
|
103
|
+
recall_description = f"{DEFAULT_MCP_RECALL_DESCRIPTION}\n\nAdditional instructions: {extra_instructions}"
|
|
104
|
+
|
|
82
105
|
mcp = FastMCP("hindsight")
|
|
83
106
|
|
|
84
|
-
@mcp.tool()
|
|
107
|
+
@mcp.tool(description=retain_description)
|
|
85
108
|
async def retain(content: str, context: str = "general") -> dict:
|
|
86
109
|
"""
|
|
87
|
-
Store important information to long-term memory.
|
|
88
|
-
|
|
89
|
-
Use this tool PROACTIVELY whenever the user shares:
|
|
90
|
-
- Personal facts, preferences, or interests
|
|
91
|
-
- Important events or milestones
|
|
92
|
-
- User history, experiences, or background
|
|
93
|
-
- Decisions, opinions, or stated preferences
|
|
94
|
-
- Goals, plans, or future intentions
|
|
95
|
-
- Relationships or people mentioned
|
|
96
|
-
- Work context, projects, or responsibilities
|
|
97
|
-
|
|
98
110
|
Args:
|
|
99
111
|
content: The fact/memory to store (be specific and include relevant details)
|
|
100
112
|
context: Category for the memory (e.g., 'preferences', 'work', 'hobbies', 'family'). Default: 'general'
|
|
@@ -111,17 +123,9 @@ def create_local_mcp_server(bank_id: str, memory=None) -> FastMCP:
|
|
|
111
123
|
asyncio.create_task(_retain())
|
|
112
124
|
return {"status": "accepted", "message": "Memory storage initiated"}
|
|
113
125
|
|
|
114
|
-
@mcp.tool()
|
|
126
|
+
@mcp.tool(description=recall_description)
|
|
115
127
|
async def recall(query: str, max_tokens: int = 4096, budget: str = "low") -> dict:
|
|
116
128
|
"""
|
|
117
|
-
Search memories to provide personalized, context-aware responses.
|
|
118
|
-
|
|
119
|
-
Use this tool PROACTIVELY to:
|
|
120
|
-
- Check user's preferences before making suggestions
|
|
121
|
-
- Recall user's history to provide continuity
|
|
122
|
-
- Remember user's goals and context
|
|
123
|
-
- Personalize responses based on past interactions
|
|
124
|
-
|
|
125
129
|
Args:
|
|
126
130
|
query: Natural language search query (e.g., "user's food preferences", "what projects is user working on")
|
|
127
131
|
max_tokens: Maximum tokens to return in results (default: 4096)
|
|
@@ -153,10 +157,9 @@ async def _initialize_and_run(bank_id: str):
|
|
|
153
157
|
from hindsight_api import MemoryEngine
|
|
154
158
|
|
|
155
159
|
# Create and initialize memory engine with pg0 embedded database
|
|
156
|
-
|
|
160
|
+
# Note: We avoid printing to stderr during init as MCP clients show it as "errors"
|
|
157
161
|
memory = MemoryEngine(db_url="pg0://hindsight-mcp")
|
|
158
162
|
await memory.initialize()
|
|
159
|
-
print("Memory engine initialized.", file=sys.stderr)
|
|
160
163
|
|
|
161
164
|
# Create and run the server
|
|
162
165
|
mcp = create_local_mcp_server(bank_id, memory=memory)
|
|
@@ -179,8 +182,8 @@ def main():
|
|
|
179
182
|
# Get bank ID from environment, default to "mcp"
|
|
180
183
|
bank_id = os.environ.get(ENV_MCP_LOCAL_BANK_ID, DEFAULT_MCP_LOCAL_BANK_ID)
|
|
181
184
|
|
|
182
|
-
#
|
|
183
|
-
|
|
185
|
+
# Note: We don't print to stderr as MCP clients display it as "error output"
|
|
186
|
+
# Use HINDSIGHT_API_LOG_LEVEL=debug for verbose startup logging
|
|
184
187
|
|
|
185
188
|
# Run the async initialization and server
|
|
186
189
|
asyncio.run(_initialize_and_run(bank_id))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/embedding_processing.py
RENAMED
|
File without changes
|
|
File without changes
|
{hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/entity_processing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/retain/observation_regeneration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/observation_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hindsight_api-0.1.7 → hindsight_api-0.1.9}/hindsight_api/engine/search/temporal_extraction.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|