hindsight-api 0.4.7__py3-none-any.whl → 0.4.8__py3-none-any.whl
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/__init__.py +1 -1
- hindsight_api/alembic/versions/5a366d414dce_initial_schema.py +16 -2
- hindsight_api/api/http.py +39 -1
- hindsight_api/banner.py +3 -0
- hindsight_api/config.py +44 -6
- hindsight_api/daemon.py +17 -111
- hindsight_api/engine/llm_interface.py +146 -0
- hindsight_api/engine/llm_wrapper.py +304 -1327
- hindsight_api/engine/memory_engine.py +71 -37
- hindsight_api/engine/providers/__init__.py +14 -0
- hindsight_api/engine/providers/anthropic_llm.py +434 -0
- hindsight_api/engine/providers/claude_code_llm.py +352 -0
- hindsight_api/engine/providers/codex_llm.py +527 -0
- hindsight_api/engine/providers/gemini_llm.py +502 -0
- hindsight_api/engine/providers/mock_llm.py +234 -0
- hindsight_api/engine/providers/openai_compatible_llm.py +745 -0
- hindsight_api/extensions/__init__.py +2 -0
- hindsight_api/extensions/builtin/tenant.py +36 -0
- hindsight_api/extensions/operation_validator.py +26 -0
- hindsight_api/main.py +6 -21
- hindsight_api/migrations.py +75 -0
- hindsight_api/worker/main.py +35 -10
- hindsight_api/worker/poller.py +15 -11
- {hindsight_api-0.4.7.dist-info → hindsight_api-0.4.8.dist-info}/METADATA +2 -1
- {hindsight_api-0.4.7.dist-info → hindsight_api-0.4.8.dist-info}/RECORD +27 -19
- {hindsight_api-0.4.7.dist-info → hindsight_api-0.4.8.dist-info}/WHEEL +0 -0
- {hindsight_api-0.4.7.dist-info → hindsight_api-0.4.8.dist-info}/entry_points.txt +0 -0
|
@@ -27,6 +27,7 @@ from hindsight_api.extensions.operation_validator import (
|
|
|
27
27
|
# Mental Model operations
|
|
28
28
|
MentalModelGetContext,
|
|
29
29
|
MentalModelGetResult,
|
|
30
|
+
MentalModelRefreshContext,
|
|
30
31
|
MentalModelRefreshResult,
|
|
31
32
|
# Core operations
|
|
32
33
|
OperationValidationError,
|
|
@@ -72,6 +73,7 @@ __all__ = [
|
|
|
72
73
|
# Operation Validator - Mental Model
|
|
73
74
|
"MentalModelGetContext",
|
|
74
75
|
"MentalModelGetResult",
|
|
76
|
+
"MentalModelRefreshContext",
|
|
75
77
|
"MentalModelRefreshResult",
|
|
76
78
|
# Tenant/Auth
|
|
77
79
|
"ApiKeyTenantExtension",
|
|
@@ -5,6 +5,42 @@ from hindsight_api.extensions.tenant import AuthenticationError, Tenant, TenantC
|
|
|
5
5
|
from hindsight_api.models import RequestContext
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
class DefaultTenantExtension(TenantExtension):
|
|
9
|
+
"""
|
|
10
|
+
Default single-tenant extension with no authentication.
|
|
11
|
+
|
|
12
|
+
This is the default extension used when no tenant extension is configured.
|
|
13
|
+
It provides single-tenant behavior using the configured schema from
|
|
14
|
+
HINDSIGHT_API_DATABASE_SCHEMA (defaults to 'public').
|
|
15
|
+
|
|
16
|
+
Features:
|
|
17
|
+
- No authentication required (passes all requests)
|
|
18
|
+
- Uses configured schema from environment
|
|
19
|
+
- Perfect for single-tenant deployments without auth
|
|
20
|
+
|
|
21
|
+
Configuration:
|
|
22
|
+
HINDSIGHT_API_DATABASE_SCHEMA=your-schema (optional, defaults to 'public')
|
|
23
|
+
|
|
24
|
+
This is automatically enabled by default. To use custom authentication,
|
|
25
|
+
configure a different tenant extension:
|
|
26
|
+
HINDSIGHT_API_TENANT_EXTENSION=hindsight_api.extensions.builtin.tenant:ApiKeyTenantExtension
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, config: dict[str, str]):
|
|
30
|
+
super().__init__(config)
|
|
31
|
+
# Cache the schema at initialization for consistency
|
|
32
|
+
# Support explicit schema override via config, otherwise use environment
|
|
33
|
+
self._schema = config.get("schema", get_config().database_schema)
|
|
34
|
+
|
|
35
|
+
async def authenticate(self, context: RequestContext) -> TenantContext:
|
|
36
|
+
"""Return configured schema without any authentication."""
|
|
37
|
+
return TenantContext(schema_name=self._schema)
|
|
38
|
+
|
|
39
|
+
async def list_tenants(self) -> list[Tenant]:
|
|
40
|
+
"""Return configured schema for single-tenant setup."""
|
|
41
|
+
return [Tenant(schema=self._schema)]
|
|
42
|
+
|
|
43
|
+
|
|
8
44
|
class ApiKeyTenantExtension(TenantExtension):
|
|
9
45
|
"""
|
|
10
46
|
Built-in tenant extension that validates API key against an environment variable.
|
|
@@ -210,6 +210,15 @@ class MentalModelGetContext:
|
|
|
210
210
|
request_context: "RequestContext"
|
|
211
211
|
|
|
212
212
|
|
|
213
|
+
@dataclass
|
|
214
|
+
class MentalModelRefreshContext:
|
|
215
|
+
"""Context for a mental model refresh/create operation validation (pre-operation)."""
|
|
216
|
+
|
|
217
|
+
bank_id: str
|
|
218
|
+
mental_model_id: str | None # None for create (not yet assigned)
|
|
219
|
+
request_context: "RequestContext"
|
|
220
|
+
|
|
221
|
+
|
|
213
222
|
@dataclass
|
|
214
223
|
class MentalModelGetResult:
|
|
215
224
|
"""Result context for post-mental-model-GET hook."""
|
|
@@ -466,6 +475,23 @@ class OperationValidatorExtension(Extension, ABC):
|
|
|
466
475
|
"""
|
|
467
476
|
return ValidationResult.accept()
|
|
468
477
|
|
|
478
|
+
async def validate_mental_model_refresh(self, ctx: MentalModelRefreshContext) -> ValidationResult:
|
|
479
|
+
"""
|
|
480
|
+
Validate a mental model refresh/create operation before execution.
|
|
481
|
+
|
|
482
|
+
Override to implement custom validation logic for mental model refresh.
|
|
483
|
+
|
|
484
|
+
Args:
|
|
485
|
+
ctx: Context containing:
|
|
486
|
+
- bank_id: Bank identifier
|
|
487
|
+
- mental_model_id: Mental model identifier (None for create)
|
|
488
|
+
- request_context: Request context with auth info
|
|
489
|
+
|
|
490
|
+
Returns:
|
|
491
|
+
ValidationResult indicating whether the operation is allowed.
|
|
492
|
+
"""
|
|
493
|
+
return ValidationResult.accept()
|
|
494
|
+
|
|
469
495
|
# =========================================================================
|
|
470
496
|
# Mental Model - Post-operation hooks (optional - override to implement)
|
|
471
497
|
# =========================================================================
|
hindsight_api/main.py
CHANGED
|
@@ -20,14 +20,13 @@ import warnings
|
|
|
20
20
|
|
|
21
21
|
import uvicorn
|
|
22
22
|
|
|
23
|
-
from . import MemoryEngine
|
|
23
|
+
from . import MemoryEngine, __version__
|
|
24
24
|
from .api import create_app
|
|
25
25
|
from .banner import print_banner
|
|
26
26
|
from .config import DEFAULT_WORKERS, ENV_WORKERS, HindsightConfig, get_config
|
|
27
27
|
from .daemon import (
|
|
28
28
|
DEFAULT_DAEMON_PORT,
|
|
29
29
|
DEFAULT_IDLE_TIMEOUT,
|
|
30
|
-
DaemonLock,
|
|
31
30
|
IdleTimeoutMiddleware,
|
|
32
31
|
daemonize,
|
|
33
32
|
)
|
|
@@ -136,30 +135,15 @@ def main():
|
|
|
136
135
|
|
|
137
136
|
# Daemon mode handling
|
|
138
137
|
if args.daemon:
|
|
139
|
-
# Use
|
|
140
|
-
args.port
|
|
138
|
+
# Use port from args (may be custom for profiles)
|
|
139
|
+
if args.port == config.port: # No custom port specified
|
|
140
|
+
args.port = DEFAULT_DAEMON_PORT
|
|
141
141
|
args.host = "127.0.0.1" # Only bind to localhost for security
|
|
142
142
|
|
|
143
|
-
# Check if another daemon is already running
|
|
144
|
-
daemon_lock = DaemonLock()
|
|
145
|
-
if not daemon_lock.acquire():
|
|
146
|
-
print(f"Daemon already running (PID: {daemon_lock.get_pid()})", file=sys.stderr)
|
|
147
|
-
sys.exit(1)
|
|
148
|
-
|
|
149
143
|
# Fork into background
|
|
144
|
+
# No lockfile needed - port binding prevents duplicate daemons
|
|
150
145
|
daemonize()
|
|
151
146
|
|
|
152
|
-
# Re-acquire lock in child process
|
|
153
|
-
daemon_lock = DaemonLock()
|
|
154
|
-
if not daemon_lock.acquire():
|
|
155
|
-
sys.exit(1)
|
|
156
|
-
|
|
157
|
-
# Register cleanup to release lock
|
|
158
|
-
def release_lock():
|
|
159
|
-
daemon_lock.release()
|
|
160
|
-
|
|
161
|
-
atexit.register(release_lock)
|
|
162
|
-
|
|
163
147
|
# Print banner (not in daemon mode)
|
|
164
148
|
if not args.daemon:
|
|
165
149
|
print()
|
|
@@ -362,6 +346,7 @@ def main():
|
|
|
362
346
|
embeddings_provider=config.embeddings_provider,
|
|
363
347
|
reranker_provider=config.reranker_provider,
|
|
364
348
|
mcp_enabled=config.mcp_enabled,
|
|
349
|
+
version=__version__,
|
|
365
350
|
)
|
|
366
351
|
|
|
367
352
|
# Start idle checker in daemon mode
|
hindsight_api/migrations.py
CHANGED
|
@@ -165,6 +165,81 @@ def run_migrations(
|
|
|
165
165
|
logger.debug("Migration advisory lock acquired")
|
|
166
166
|
|
|
167
167
|
try:
|
|
168
|
+
# Ensure pgvector extension is installed globally BEFORE schema migrations
|
|
169
|
+
# This is critical: the extension must exist database-wide before any schema
|
|
170
|
+
# migrations run, otherwise custom schemas won't have access to vector types
|
|
171
|
+
logger.debug("Checking pgvector extension availability...")
|
|
172
|
+
|
|
173
|
+
# First, check if extension already exists
|
|
174
|
+
ext_check = conn.execute(
|
|
175
|
+
text(
|
|
176
|
+
"SELECT extname, nspname FROM pg_extension e "
|
|
177
|
+
"JOIN pg_namespace n ON e.extnamespace = n.oid "
|
|
178
|
+
"WHERE extname = 'vector'"
|
|
179
|
+
)
|
|
180
|
+
).fetchone()
|
|
181
|
+
|
|
182
|
+
if ext_check:
|
|
183
|
+
# Extension exists - check if in correct schema
|
|
184
|
+
ext_schema = ext_check[1]
|
|
185
|
+
if ext_schema == "public":
|
|
186
|
+
logger.info("pgvector extension found in public schema - ready to use")
|
|
187
|
+
else:
|
|
188
|
+
# Extension in wrong schema - try to fix if we have permissions
|
|
189
|
+
logger.warning(
|
|
190
|
+
f"pgvector extension found in schema '{ext_schema}' instead of 'public'. "
|
|
191
|
+
f"Attempting to relocate..."
|
|
192
|
+
)
|
|
193
|
+
try:
|
|
194
|
+
conn.execute(text("DROP EXTENSION vector CASCADE"))
|
|
195
|
+
conn.execute(text("SET search_path TO public"))
|
|
196
|
+
conn.execute(text("CREATE EXTENSION vector"))
|
|
197
|
+
conn.commit()
|
|
198
|
+
logger.info("pgvector extension relocated to public schema")
|
|
199
|
+
except Exception as e:
|
|
200
|
+
# Failed to relocate - log but don't fail if extension exists somewhere
|
|
201
|
+
logger.warning(
|
|
202
|
+
f"Could not relocate pgvector extension to public schema: {e}. "
|
|
203
|
+
f"Continuing with extension in '{ext_schema}' schema."
|
|
204
|
+
)
|
|
205
|
+
conn.rollback()
|
|
206
|
+
else:
|
|
207
|
+
# Extension doesn't exist - try to install
|
|
208
|
+
logger.info("pgvector extension not found, attempting to install...")
|
|
209
|
+
try:
|
|
210
|
+
conn.execute(text("SET search_path TO public"))
|
|
211
|
+
conn.execute(text("CREATE EXTENSION vector"))
|
|
212
|
+
conn.commit()
|
|
213
|
+
logger.info("pgvector extension installed in public schema")
|
|
214
|
+
except Exception as e:
|
|
215
|
+
# Installation failed - this is only fatal if extension truly doesn't exist
|
|
216
|
+
# Check one more time in case another process installed it
|
|
217
|
+
conn.rollback()
|
|
218
|
+
ext_recheck = conn.execute(
|
|
219
|
+
text(
|
|
220
|
+
"SELECT nspname FROM pg_extension e "
|
|
221
|
+
"JOIN pg_namespace n ON e.extnamespace = n.oid "
|
|
222
|
+
"WHERE extname = 'vector'"
|
|
223
|
+
)
|
|
224
|
+
).fetchone()
|
|
225
|
+
|
|
226
|
+
if ext_recheck:
|
|
227
|
+
logger.warning(
|
|
228
|
+
f"Could not install pgvector extension (permission denied?), "
|
|
229
|
+
f"but extension exists in '{ext_recheck[0]}' schema. Continuing..."
|
|
230
|
+
)
|
|
231
|
+
else:
|
|
232
|
+
# Extension truly doesn't exist and we can't install it
|
|
233
|
+
logger.error(
|
|
234
|
+
f"pgvector extension is not installed and cannot be installed: {e}. "
|
|
235
|
+
f"Please ensure pgvector is installed by a database administrator. "
|
|
236
|
+
f"See: https://github.com/pgvector/pgvector#installation"
|
|
237
|
+
)
|
|
238
|
+
raise RuntimeError(
|
|
239
|
+
"pgvector extension is required but not installed. "
|
|
240
|
+
"Please install it with: CREATE EXTENSION vector;"
|
|
241
|
+
) from e
|
|
242
|
+
|
|
168
243
|
# Run migrations while holding the lock
|
|
169
244
|
_run_migrations_internal(database_url, script_location, schema=schema)
|
|
170
245
|
finally:
|
hindsight_api/worker/main.py
CHANGED
|
@@ -176,7 +176,7 @@ def main():
|
|
|
176
176
|
nonlocal memory, poller
|
|
177
177
|
import uvicorn
|
|
178
178
|
|
|
179
|
-
from ..extensions import TenantExtension, load_extension
|
|
179
|
+
from ..extensions import OperationValidatorExtension, TenantExtension, load_extension
|
|
180
180
|
|
|
181
181
|
# Load tenant extension BEFORE creating MemoryEngine so it can
|
|
182
182
|
# set correct schema context during task execution. Without this,
|
|
@@ -184,6 +184,12 @@ def main():
|
|
|
184
184
|
# causing worker writes to land in the wrong schema.
|
|
185
185
|
tenant_extension = load_extension("TENANT", TenantExtension)
|
|
186
186
|
|
|
187
|
+
# Load operation validator so workers can record usage metering
|
|
188
|
+
# for async operations (e.g. refresh_mental_model after consolidation)
|
|
189
|
+
operation_validator = load_extension("OPERATION_VALIDATOR", OperationValidatorExtension)
|
|
190
|
+
if operation_validator:
|
|
191
|
+
logger.info(f"Loaded operation validator: {operation_validator.__class__.__name__}")
|
|
192
|
+
|
|
187
193
|
# Initialize MemoryEngine
|
|
188
194
|
# Workers use SyncTaskBackend because they execute tasks directly,
|
|
189
195
|
# they don't need to store tasks (they poll from DB)
|
|
@@ -191,6 +197,7 @@ def main():
|
|
|
191
197
|
run_migrations=False, # Workers don't run migrations
|
|
192
198
|
task_backend=SyncTaskBackend(),
|
|
193
199
|
tenant_extension=tenant_extension,
|
|
200
|
+
operation_validator=operation_validator,
|
|
194
201
|
)
|
|
195
202
|
|
|
196
203
|
await memory.initialize()
|
|
@@ -222,15 +229,30 @@ def main():
|
|
|
222
229
|
# Create the HTTP app for metrics/health
|
|
223
230
|
app = create_worker_app(poller, memory)
|
|
224
231
|
|
|
225
|
-
# Setup signal handlers for graceful shutdown
|
|
232
|
+
# Setup signal handlers for graceful shutdown using asyncio
|
|
226
233
|
shutdown_requested = asyncio.Event()
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
+
force_exit = False
|
|
235
|
+
|
|
236
|
+
loop = asyncio.get_event_loop()
|
|
237
|
+
|
|
238
|
+
def signal_handler():
|
|
239
|
+
nonlocal force_exit
|
|
240
|
+
if shutdown_requested.is_set():
|
|
241
|
+
# Second signal = force exit
|
|
242
|
+
print("\nReceived second signal, forcing immediate exit...")
|
|
243
|
+
force_exit = True
|
|
244
|
+
# Restore default handler so third signal kills process
|
|
245
|
+
loop.remove_signal_handler(signal.SIGINT)
|
|
246
|
+
loop.remove_signal_handler(signal.SIGTERM)
|
|
247
|
+
sys.exit(1)
|
|
248
|
+
else:
|
|
249
|
+
print("\nReceived shutdown signal, initiating graceful shutdown...")
|
|
250
|
+
print("(Press Ctrl+C again to force immediate exit)")
|
|
251
|
+
shutdown_requested.set()
|
|
252
|
+
|
|
253
|
+
# Use asyncio's signal handlers which work properly with the event loop
|
|
254
|
+
loop.add_signal_handler(signal.SIGINT, signal_handler)
|
|
255
|
+
loop.add_signal_handler(signal.SIGTERM, signal_handler)
|
|
234
256
|
|
|
235
257
|
# Create uvicorn config and server
|
|
236
258
|
uvicorn_config = uvicorn.Config(
|
|
@@ -249,7 +271,10 @@ def main():
|
|
|
249
271
|
print(f"Worker started. Metrics available at http://{args.http_host}:{args.http_port}/metrics")
|
|
250
272
|
|
|
251
273
|
# Wait for shutdown signal
|
|
252
|
-
|
|
274
|
+
try:
|
|
275
|
+
await shutdown_requested.wait()
|
|
276
|
+
except KeyboardInterrupt:
|
|
277
|
+
print("\nReceived interrupt, initiating graceful shutdown...")
|
|
253
278
|
|
|
254
279
|
# Graceful shutdown
|
|
255
280
|
print("Shutting down HTTP server...")
|
hindsight_api/worker/poller.py
CHANGED
|
@@ -72,9 +72,9 @@ class WorkerPoller:
|
|
|
72
72
|
executor: Async function to execute tasks (typically MemoryEngine.execute_task)
|
|
73
73
|
poll_interval_ms: Interval between polls when no tasks found (milliseconds)
|
|
74
74
|
max_retries: Maximum retry attempts before marking task as failed
|
|
75
|
-
schema: Database schema for single-tenant support (
|
|
76
|
-
tenant_extension: Extension for dynamic multi-tenant discovery. If
|
|
77
|
-
|
|
75
|
+
schema: Database schema for single-tenant support (deprecated, use tenant_extension)
|
|
76
|
+
tenant_extension: Extension for dynamic multi-tenant discovery. If None, creates a
|
|
77
|
+
DefaultTenantExtension with the configured schema.
|
|
78
78
|
max_slots: Maximum concurrent tasks per worker
|
|
79
79
|
consolidation_max_slots: Maximum concurrent consolidation tasks per worker
|
|
80
80
|
"""
|
|
@@ -84,6 +84,13 @@ class WorkerPoller:
|
|
|
84
84
|
self._poll_interval_ms = poll_interval_ms
|
|
85
85
|
self._max_retries = max_retries
|
|
86
86
|
self._schema = schema
|
|
87
|
+
# Always set tenant extension (use DefaultTenantExtension if none provided)
|
|
88
|
+
if tenant_extension is None:
|
|
89
|
+
from ..extensions.builtin.tenant import DefaultTenantExtension
|
|
90
|
+
|
|
91
|
+
# Pass schema parameter to DefaultTenantExtension if explicitly provided
|
|
92
|
+
config = {"schema": schema} if schema else {}
|
|
93
|
+
tenant_extension = DefaultTenantExtension(config=config)
|
|
87
94
|
self._tenant_extension = tenant_extension
|
|
88
95
|
self._max_slots = max_slots
|
|
89
96
|
self._consolidation_max_slots = consolidation_max_slots
|
|
@@ -100,14 +107,11 @@ class WorkerPoller:
|
|
|
100
107
|
|
|
101
108
|
async def _get_schemas(self) -> list[str | None]:
|
|
102
109
|
"""Get list of schemas to poll. Returns [None] for default schema (no prefix)."""
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return [t.schema if t.schema != DEFAULT_DATABASE_SCHEMA else None for t in tenants]
|
|
109
|
-
# Single schema mode
|
|
110
|
-
return [self._schema]
|
|
110
|
+
from ..config import DEFAULT_DATABASE_SCHEMA
|
|
111
|
+
|
|
112
|
+
tenants = await self._tenant_extension.list_tenants()
|
|
113
|
+
# Convert default schema to None for SQL compatibility (no prefix), keep others as-is
|
|
114
|
+
return [t.schema if t.schema != DEFAULT_DATABASE_SCHEMA else None for t in tenants]
|
|
111
115
|
|
|
112
116
|
async def _get_available_slots(self) -> tuple[int, int]:
|
|
113
117
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hindsight-api
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.8
|
|
4
4
|
Summary: Hindsight: Agent Memory That Works Like Human Memory
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Requires-Dist: aiohttp>=3.13.3
|
|
@@ -8,6 +8,7 @@ Requires-Dist: alembic>=1.17.1
|
|
|
8
8
|
Requires-Dist: anthropic>=0.40.0
|
|
9
9
|
Requires-Dist: asyncpg>=0.29.0
|
|
10
10
|
Requires-Dist: authlib>=1.6.6
|
|
11
|
+
Requires-Dist: claude-agent-sdk>=0.1.27
|
|
11
12
|
Requires-Dist: cohere>=5.0.0
|
|
12
13
|
Requires-Dist: dateparser>=1.2.2
|
|
13
14
|
Requires-Dist: fastapi[standard]>=0.120.3
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
hindsight_api/__init__.py,sha256=
|
|
2
|
-
hindsight_api/banner.py,sha256=
|
|
3
|
-
hindsight_api/config.py,sha256=
|
|
4
|
-
hindsight_api/daemon.py,sha256=
|
|
5
|
-
hindsight_api/main.py,sha256
|
|
1
|
+
hindsight_api/__init__.py,sha256=H-lLDWXpU46uwagO3PyvShBWmpzixxlFVIKjj6scuwI,1197
|
|
2
|
+
hindsight_api/banner.py,sha256=eQeafvnm95eCbWPRjPBmGsIyBXF59SuL9For9unIEyM,4705
|
|
3
|
+
hindsight_api/config.py,sha256=eYorL_NBGSGWkENwuGaW4CH8h-91aJ1jETM4HbVoBlA,33878
|
|
4
|
+
hindsight_api/daemon.py,sha256=LMddRz7h5dg37YcyjjnquNF-Y9zkndN31OaUeNEWBSE,3423
|
|
5
|
+
hindsight_api/main.py,sha256=M2b0sO7SkGgUo6sR1WZDe0VGNfisi28bfnVMek8mgW4,14909
|
|
6
6
|
hindsight_api/mcp_local.py,sha256=fJnCxMBc79GlBZrma94Ux6g-GVuh-W66194cqQdkKJQ,5613
|
|
7
7
|
hindsight_api/mcp_tools.py,sha256=cLQ9Bdu8FoL2DscO_Z1pAGpNiCeFY2PHBvIPLZXkwE8,20493
|
|
8
8
|
hindsight_api/metrics.py,sha256=zgOh_UFTT8ZtqnLaZuyErRtoPZ9SGP3mbmiHT3wX3v4,20677
|
|
9
|
-
hindsight_api/migrations.py,sha256=
|
|
9
|
+
hindsight_api/migrations.py,sha256=sDg2nMLBifZMpfORiKC_Xxp359a5vNk4Hz0BOUuk7zM,18955
|
|
10
10
|
hindsight_api/models.py,sha256=SzJ8uM2nGr3D6X-UEfE8VIT-PbS9J4DmRT_4lv5n9T8,12831
|
|
11
11
|
hindsight_api/pg0.py,sha256=Ntj3FYPLfmQTskG4gHoz_NTlQ4A3DqCm2PbbXm-ivGQ,6337
|
|
12
12
|
hindsight_api/server.py,sha256=MU2ZvKe3KWfxKYZq8EEJPgKMmq5diPkRqfQBaz-yOQI,2483
|
|
@@ -15,7 +15,7 @@ hindsight_api/admin/cli.py,sha256=A1qkZ_9GWjz1qOIQYnmj-qUN005cIIlpFsvYH7tZdyc,11
|
|
|
15
15
|
hindsight_api/alembic/README,sha256=MVlc9TYmr57RbhXET6QxgyCcwWP7w-vLkEsirENqiIQ,38
|
|
16
16
|
hindsight_api/alembic/env.py,sha256=I4sGdtUo8xcXe95MyD36JQeMod_Bvp9JUkW64Ve4XSM,5808
|
|
17
17
|
hindsight_api/alembic/script.py.mako,sha256=04kgeBtNMa4cCnG8CfQcKt6P6rnloIfj8wy0u_DBydM,704
|
|
18
|
-
hindsight_api/alembic/versions/5a366d414dce_initial_schema.py,sha256=
|
|
18
|
+
hindsight_api/alembic/versions/5a366d414dce_initial_schema.py,sha256=JhRzHjGhVo70K840l1rr554aA2N5rTNWPvHQIl114xM,18385
|
|
19
19
|
hindsight_api/alembic/versions/b7c4d8e9f1a2_add_chunks_table.py,sha256=MaHFU4JczUIFLeUMBTKIV3ocuclil55N9fPPim-HRfk,2599
|
|
20
20
|
hindsight_api/alembic/versions/c8e5f2a3b4d1_add_retain_params_to_documents.py,sha256=ChqkHANauZb4-nBt2uepoZN3q0vRzN6aRsWTGueULiA,1146
|
|
21
21
|
hindsight_api/alembic/versions/d9f6a3b4c5e2_rename_bank_to_interactions.py,sha256=s5_B2D0JdaxO7WM-vWC5Yt6hAtTsAUzJhFGLFSkfuQU,1808
|
|
@@ -39,7 +39,7 @@ hindsight_api/alembic/versions/t5o6p7q8r9s0_rename_mental_models_to_observations
|
|
|
39
39
|
hindsight_api/alembic/versions/u6p7q8r9s0t1_mental_models_text_id.py,sha256=uvil81f-4ag2dIxBXUGKZ5vxkqdNQRpxCWj_iVih09w,1355
|
|
40
40
|
hindsight_api/alembic/versions/v7q8r9s0t1u2_add_max_tokens_to_mental_models.py,sha256=Mw68uW8PK-SaHcYcqb41vWI0R22t70SSasNS2Myeoec,1656
|
|
41
41
|
hindsight_api/api/__init__.py,sha256=npF0AAy8WJhHF5a9ehkNn9_iYLk7RQOk2gdkdFb49Hk,3840
|
|
42
|
-
hindsight_api/api/http.py,sha256=
|
|
42
|
+
hindsight_api/api/http.py,sha256=yIdoTpg3TOHGOnKrYuMWhQ3L-3OpTtNxEyMc02iYcRw,136567
|
|
43
43
|
hindsight_api/api/mcp.py,sha256=4ZxeEa_LHcyFRf1jK60hr4JDLXObOQdnpc3bTLJCdVI,8647
|
|
44
44
|
hindsight_api/engine/__init__.py,sha256=-BwaSwG9fTT_BBO0c_2MBkxG6-tGdclSzIqsgHw4cnw,1633
|
|
45
45
|
hindsight_api/engine/cross_encoder.py,sha256=Q1s-C-JOOJ246Twl1FyYbeXAJnfdXnfhcDpntScYFvQ,32301
|
|
@@ -48,8 +48,9 @@ hindsight_api/engine/db_utils.py,sha256=Fq1pXETt8ZPhkWYjrcGbgL6glrwmCGWh3_lYJgHq
|
|
|
48
48
|
hindsight_api/engine/embeddings.py,sha256=KvK65y89E4Hxz8gvQR4G6qSGNlGoai6NBIaWdMzoV_A,27054
|
|
49
49
|
hindsight_api/engine/entity_resolver.py,sha256=qVvWJHnbGEfh0iUFtc1dbM3IUNwPMsQsmg2rMgiX2DY,23794
|
|
50
50
|
hindsight_api/engine/interface.py,sha256=wpJUIN-64RFJ_iYNtYWlyR4L-mDO2xijXUFqLD4tkeg,15821
|
|
51
|
-
hindsight_api/engine/
|
|
52
|
-
hindsight_api/engine/
|
|
51
|
+
hindsight_api/engine/llm_interface.py,sha256=mdeEJxv-f8f79wIULUctFTkNs6Snvy2w53o9Ygdo0_Y,4950
|
|
52
|
+
hindsight_api/engine/llm_wrapper.py,sha256=QKggTADJB1b0-qtWlXxtNIKgoh14rIzCkUyWSZKWHPg,22662
|
|
53
|
+
hindsight_api/engine/memory_engine.py,sha256=I-7Bbud8u3ShMn-AjaIG_lfgvjZldRVGJINCJ9mNfsk,231550
|
|
53
54
|
hindsight_api/engine/query_analyzer.py,sha256=7APe0MjBcUxjivcMlM03PmMk_w5FjWvlEe20yAJlHlc,19741
|
|
54
55
|
hindsight_api/engine/response_models.py,sha256=ZPP80NmEP205erz5qEE8IJ9-c622UHqYo17e5UOiXAE,15578
|
|
55
56
|
hindsight_api/engine/task_backend.py,sha256=FFZnjUsjXrrZwww16ow--J61QIpUFwxLdcmeF1NPoYk,8500
|
|
@@ -61,6 +62,13 @@ hindsight_api/engine/directives/__init__.py,sha256=5ZxaRqZVyJckbGElaI2DMRMBtnj-q
|
|
|
61
62
|
hindsight_api/engine/directives/models.py,sha256=PKxvmhW1-fjBITAOBu7RKX5Lj61c2jdsTaX8ADelKag,1523
|
|
62
63
|
hindsight_api/engine/mental_models/__init__.py,sha256=TU6dSPyIsevFDgY6PLYctDsk5K4SA4pFSQnmQvbdRlA,488
|
|
63
64
|
hindsight_api/engine/mental_models/models.py,sha256=DjgumJE7LvbMVpv90aMkGhIWOZ3ZrXM2DFAqHuGerAs,2102
|
|
65
|
+
hindsight_api/engine/providers/__init__.py,sha256=UEoVUTzQGGFe_A8jUmnbQINmwZ7L3P-PLpnh38w2tI8,468
|
|
66
|
+
hindsight_api/engine/providers/anthropic_llm.py,sha256=xv5r4p0HwzKyhcTj0cTLp_kMnW4HuAiIGWtU-PfWhBw,17228
|
|
67
|
+
hindsight_api/engine/providers/claude_code_llm.py,sha256=Cd9TJvO0Tl1Ql-bxU6qjTfw5nYItsxnPPepbZhLdjwQ,14386
|
|
68
|
+
hindsight_api/engine/providers/codex_llm.py,sha256=xdsrCXH38I7DLtEN0zKeLDaoM6h9XwzjCqU3G-Mryd0,19254
|
|
69
|
+
hindsight_api/engine/providers/gemini_llm.py,sha256=51peFrDYVBqhZTOoyZMQp5aMANvikVQrAwRJTSJzHkk,20175
|
|
70
|
+
hindsight_api/engine/providers/mock_llm.py,sha256=h2wF8oVNdqSOpDljolKgXUY-wqjYQhpxVvA3RThY1Qk,8217
|
|
71
|
+
hindsight_api/engine/providers/openai_compatible_llm.py,sha256=ls2XAWTjUsVzPo-KiYSR_20WJ0s2RFXbPFy7waDPFZE,33309
|
|
64
72
|
hindsight_api/engine/reflect/__init__.py,sha256=r70r-Y9LElHIL3EsvImO1KIL1sT_ubr1lC0IH5kH6O0,484
|
|
65
73
|
hindsight_api/engine/reflect/agent.py,sha256=mr0rUrwdnDISt9iyuspI_ZhL4qfyLTWAzJO9EAIEctM,37610
|
|
66
74
|
hindsight_api/engine/reflect/models.py,sha256=ZnMCi4sta5bSVGRRNatTA2jNSun59mWEVVq6Dkmjq1Q,5185
|
|
@@ -94,19 +102,19 @@ hindsight_api/engine/search/think_utils.py,sha256=k2NBmb1eczTiDHuQZ7-VW4lsvlGt20
|
|
|
94
102
|
hindsight_api/engine/search/trace.py,sha256=RjvbkKBK-_MZBcVhVlaDTLD0yg6krngMNyC0_zLK05Y,11748
|
|
95
103
|
hindsight_api/engine/search/tracer.py,sha256=B75CZQjdoheN2UpNgqKbJkdXlDVKJjzVTdUhvBUFaLY,16212
|
|
96
104
|
hindsight_api/engine/search/types.py,sha256=meIoT8Q1coal1TmV_UiCqo9emjQI6af27EXPWVZL4h4,6418
|
|
97
|
-
hindsight_api/extensions/__init__.py,sha256=
|
|
105
|
+
hindsight_api/extensions/__init__.py,sha256=Tl2ZZsReYF4mdZ2ZxebekB8zJduMeFuMIcZ09WTHIqE,2458
|
|
98
106
|
hindsight_api/extensions/base.py,sha256=M7zXuM-tbqDnUwXX1mxAxiFs1eXOzNqIJutKLiUE4mU,2357
|
|
99
107
|
hindsight_api/extensions/context.py,sha256=Qq-uy3hhxO6ioDmf6dPXdnIjs_pdm7lTspDiEhJJmPU,4469
|
|
100
108
|
hindsight_api/extensions/http.py,sha256=c-a1g6R6rzibyReyR-WHz8DjRRGr4rVSyV9KB4UxVVU,2907
|
|
101
109
|
hindsight_api/extensions/loader.py,sha256=UwGM0XH7zHGng_xfHUY0VbOQemj9DmjuDaMst1TrFi8,4170
|
|
102
|
-
hindsight_api/extensions/operation_validator.py,sha256=
|
|
110
|
+
hindsight_api/extensions/operation_validator.py,sha256=ukGjgFZuh_pze917sAhd_d_oq_ysPJH80FwVY-6kzJg,18094
|
|
103
111
|
hindsight_api/extensions/tenant.py,sha256=0LraksQ1gzsOYLEGrx2q2F0or596Ywfo_MqD1FJMNRM,2617
|
|
104
112
|
hindsight_api/extensions/builtin/__init__.py,sha256=hLx2oFYZ1JtZhTWfab6AYcR02SWP2gIdbEqnZezT8ek,526
|
|
105
|
-
hindsight_api/extensions/builtin/tenant.py,sha256=
|
|
113
|
+
hindsight_api/extensions/builtin/tenant.py,sha256=hAB88q9wuMT1Fqolq22HyP3QrBdICOfLZ1Xo7au1LxU,3325
|
|
106
114
|
hindsight_api/worker/__init__.py,sha256=hzpMLvOfgL2KKrrik_9ouvEzCdvJSrH-pj5UdFK63J0,256
|
|
107
|
-
hindsight_api/worker/main.py,sha256=
|
|
108
|
-
hindsight_api/worker/poller.py,sha256=
|
|
109
|
-
hindsight_api-0.4.
|
|
110
|
-
hindsight_api-0.4.
|
|
111
|
-
hindsight_api-0.4.
|
|
112
|
-
hindsight_api-0.4.
|
|
115
|
+
hindsight_api/worker/main.py,sha256=wF0c19CqXnECK4NHrUGU9zle8N8QrhuxcvaE3byOID0,11349
|
|
116
|
+
hindsight_api/worker/poller.py,sha256=C3IEbIN-LNgTxW0zhViZxORQotftYIDeNTYD4Bqn2jw,25912
|
|
117
|
+
hindsight_api-0.4.8.dist-info/METADATA,sha256=iK2IIlna5dXjiIlQ5lg055uo7-HGfu7E-hR8WS1QTZk,5834
|
|
118
|
+
hindsight_api-0.4.8.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
119
|
+
hindsight_api-0.4.8.dist-info/entry_points.txt,sha256=1-mxPbRGL_Byf9ZrHYkPW-TEgLYFcwCiSFCxOgI_3vM,206
|
|
120
|
+
hindsight_api-0.4.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|