Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license

This commit is contained in:
2026-09-05 13:26:46 +03:00
commit 03634b1ca3
11340 changed files with 3442369 additions and 0 deletions
+150
View File
@@ -0,0 +1,150 @@
# Hindsight Memory Provider
Long-term memory with knowledge graph, entity resolution, and multi-strategy retrieval. Supports cloud, local embedded, and local external modes.
## Requirements
- **Cloud:** API key from [ui.hindsight.vectorize.io](https://ui.hindsight.vectorize.io)
- **Local Embedded:** API key for a supported LLM provider (OpenAI, Anthropic, Gemini, Groq, OpenRouter, MiniMax, Ollama, or any OpenAI-compatible endpoint). Embeddings and reranking run locally — no additional API keys needed.
- **Local External:** A running Hindsight instance (Docker or self-hosted) reachable over HTTP.
## Setup
```bash
hermes memory setup # select "hindsight"
```
The setup wizard installs dependencies automatically via `uv`, walks you through configuration, and offers to seed the bank with a **starter memory template** (a curated set of dispositions/instructions for common agent roles) — you can skip it, and it warns before overwriting an already-configured bank.
Or manually (cloud mode with defaults):
```bash
hermes config set memory.provider hindsight
echo "HINDSIGHT_API_KEY=your-key" >> ~/.hermes/.env
```
### Cloud
Connects to the Hindsight Cloud API. Requires an API key from [ui.hindsight.vectorize.io](https://ui.hindsight.vectorize.io).
### Local Embedded
Hermes spins up a local Hindsight daemon with built-in PostgreSQL. Requires an LLM API key for memory extraction and synthesis. The daemon starts automatically in the background on first use and stops after 5 minutes of inactivity.
Supports any OpenAI-compatible LLM endpoint (llama.cpp, vLLM, LM Studio, etc.) — pick `openai_compatible` as the provider and enter the base URL.
Daemon startup logs: `~/.hermes/logs/hindsight-embed.log`
Daemon runtime logs: `~/.hindsight/profiles/<profile>.log`
To open the Hindsight web UI (local embedded mode only):
```bash
hindsight-embed -p hermes ui start
```
### Local External
Points the plugin at an existing Hindsight instance you're already running (Docker, self-hosted, etc.). No daemon management — just a URL and an optional API key.
## Config
Config file: `~/.hermes/hindsight/config.json`
### Connection
| Key | Default | Description |
|-----|---------|-------------|
| `mode` | `cloud` | `cloud`, `local_embedded`, or `local_external` |
| `api_url` | `https://api.hindsight.vectorize.io` | API URL (cloud and local_external modes) |
### Memory Bank
| Key | Default | Description |
|-----|---------|-------------|
| `bank_id` | `hermes` | Memory bank name (static fallback used when `bank_id_template` is unset or resolves empty) |
| `bank_id_template` | — | Optional template to derive the bank name dynamically. Placeholders: `{profile}`, `{workspace}`, `{platform}`, `{user}`, `{session}`. Example: `hermes-{profile}` isolates memory per active Hermes profile. Empty placeholders collapse cleanly (e.g. `hermes-{user}` with no user becomes `hermes`). |
| `bank_mission` | — | Reflect mission (identity/framing for reflect reasoning). Applied via Banks API. |
| `bank_retain_mission` | — | Retain mission (steers what gets extracted). Applied via Banks API. |
### Recall
| Key | Default | Description |
|-----|---------|-------------|
| `recall_budget` | `mid` | Recall thoroughness: `low` / `mid` / `high` |
| `recall_prefetch_method` | `recall` | Auto-recall method: `recall` (raw facts) or `reflect` (LLM synthesis) |
| `recall_max_tokens` | `4096` | Maximum tokens for recall results |
| `recall_max_input_chars` | `800` | Maximum input query length for auto-recall |
| `recall_prompt_preamble` | — | Custom preamble for recalled memories in context |
| `recall_tags` | — | Tags to filter when searching memories |
| `recall_tags_match` | `any` | Tag matching mode: `any` / `all` / `any_strict` / `all_strict` |
| `recall_types` | `observation` | Fact types surfaced by recall (both auto-recall and the `hindsight_recall` tool). Comma-separated string or JSON list. **Default narrowed to `observation` only** (see "Behavior change" below). Set to `observation,world,experience` to also include raw facts. |
| `auto_recall` | `true` | Automatically recall memories before each turn |
| `recall_sync` | `false` | Recall synchronously against the *current* message each turn (higher relevance, adds recall latency). Default off: recall runs in the background and is injected on the next turn. |
| `recall_indicator` | `true` | Show a `👁️ Hindsight — recalled N memories` status line when auto-recall injects memory. Turn off for customer-facing agents. |
> **Behavior change — `recall_types` defaults to `observation` only.**
>
> Previously recall returned all three fact types. It now returns only observations.
>
> Per [Hindsight's docs](https://hindsight.vectorize.io/developer/observations), observations are the **consolidated** knowledge layer Hindsight builds on top of raw facts: deduplicated beliefs grounded in evidence, refined as new facts arrive, with proof counts and freshness signals. Raw `world` / `experience` facts are the individual supporting evidence that feeds them. For per-turn context injection, observations are denser per token and avoid feeding the model multiple raw facts that one observation already summarizes.
>
> Restore the broad recall with `"recall_types": "observation,world,experience"` (string or JSON list) in `~/.hermes/hindsight/config.json`. This applies to **both** auto-recall and the `hindsight_recall` tool — both read the same `recall_types` setting (the tool schema has no per-call `types` argument), so narrowing the default narrows both paths.
### Retain
| Key | Default | Description |
|-----|---------|-------------|
| `auto_retain` | `true` | Automatically retain conversation turns |
| `retain_async` | `true` | Process retain asynchronously on the Hindsight server |
| `retain_every_n_turns` | `1` | Retain every N turns (1 = every turn) |
| `retain_context` | `conversation between Hermes Agent and the User` | Context label for retained memories |
| `retain_tags` | — | Default tags applied to retained memories; merged with per-call tool tags |
| `retain_source` | — | Opt-in `metadata.source` attached to retained memories (identifies the storing client, e.g. `hermes`). Empty by default — no attribution tag ships unless you set it. |
| `retain_indicator` | `true` | Show a `👁️ Hindsight — saving to memory…` status line when a turn is saved. Turn off for customer-facing agents. |
| `retain_user_prefix` | `User` | Label used before user turns in auto-retained transcripts |
| `retain_assistant_prefix` | `Assistant` | Label used before assistant turns in auto-retained transcripts |
### Integration
| Key | Default | Description |
|-----|---------|-------------|
| `memory_mode` | `hybrid` | How memories are integrated into the agent |
**memory_mode:**
- `hybrid` — automatic context injection + tools available to the LLM
- `context` — automatic injection only, no tools exposed
- `tools` — tools only, no automatic injection
### Local Embedded LLM
| Key | Default | Description |
|-----|---------|-------------|
| `llm_provider` | `openai` | `openai`, `anthropic`, `gemini`, `groq`, `openrouter`, `minimax`, `ollama`, `lmstudio`, `openai_compatible` |
| `llm_model` | per-provider | Model name (e.g. `gpt-4o-mini`, `qwen/qwen3.5-9b`) |
| `llm_base_url` | — | Endpoint URL for `openai_compatible` (e.g. `http://192.168.1.10:8080/v1`) |
The LLM API key is stored in `~/.hermes/.env` as `HINDSIGHT_LLM_API_KEY`.
## Tools
Available in `hybrid` and `tools` memory modes:
| Tool | Description |
|------|-------------|
| `hindsight_retain` | Store information with auto entity extraction; supports optional per-call `tags` |
| `hindsight_recall` | Multi-strategy search (semantic + entity graph) |
| `hindsight_reflect` | Cross-memory synthesis (LLM-powered) |
## Environment Variables
| Variable | Description |
|----------|-------------|
| `HINDSIGHT_API_KEY` | API key for Hindsight Cloud |
| `HINDSIGHT_LLM_API_KEY` | LLM API key for local mode |
| `HINDSIGHT_API_LLM_BASE_URL` | LLM Base URL for local mode (e.g. OpenRouter) |
| `HINDSIGHT_API_URL` | Override API endpoint |
| `HINDSIGHT_BANK_ID` | Override bank name |
| `HINDSIGHT_BUDGET` | Override recall budget |
| `HINDSIGHT_MODE` | Override mode (`cloud`, `local_embedded`, `local_external`) |
## Client Version
Requires `hindsight-client >= 0.6.1`. The plugin auto-upgrades on session start if an older version is detected.
File diff suppressed because it is too large Load Diff
+76
View File
@@ -0,0 +1,76 @@
"""Hindsight's declared config surface — rendered by the generic desktop panel."""
from plugins.memory.config_schema import (
KIND_SECRET,
KIND_SELECT,
KIND_TEXT,
ProviderConfigSchema,
ProviderField,
ProviderFieldOption,
)
CONFIG_SCHEMA = ProviderConfigSchema(
name="hindsight",
label="Hindsight",
fields=(
ProviderField(
key="mode",
label="Mode",
kind=KIND_SELECT,
default="cloud",
description="How Hermes connects to Hindsight.",
options=(
ProviderFieldOption(
"cloud",
"Cloud",
"Hindsight Cloud API (lightweight, just needs an API key)",
),
ProviderFieldOption(
"local_external",
"Local External",
"Connect to an existing Hindsight instance",
),
),
inline=True,
),
ProviderField(
key="api_key",
label="API key",
kind=KIND_SECRET,
env_key="HINDSIGHT_API_KEY",
description="Used to authenticate with the Hindsight API.",
placeholder="Enter Hindsight API key",
inline=True,
),
ProviderField(
key="api_url",
label="API URL",
kind=KIND_TEXT,
default="https://api.hindsight.vectorize.io",
aliases=("apiUrl",),
env_fallbacks=("HINDSIGHT_API_URL",),
inline=True,
),
ProviderField(
key="bank_id",
label="Bank ID",
kind=KIND_TEXT,
default="hermes",
aliases=("bankId",),
inline=True,
),
ProviderField(
key="recall_budget",
label="Recall budget",
kind=KIND_SELECT,
default="mid",
aliases=("budget",),
options=(
ProviderFieldOption("low", "low"),
ProviderFieldOption("mid", "mid"),
ProviderFieldOption("high", "high"),
),
inline=True,
),
),
)
+8
View File
@@ -0,0 +1,8 @@
name: hindsight
version: 1.0.0
description: "Hindsight — long-term memory with knowledge graph, entity resolution, and multi-strategy retrieval."
pip_dependencies:
- "hindsight-client>=0.6.1"
requires_env: []
hooks:
- on_session_end
+153
View File
@@ -0,0 +1,153 @@
"""Starter bank templates for the Hindsight memory-provider setup wizard.
Fetches the Hindsight Bank Templates catalog, filters to templates tagged for
the ``hermes`` integration, and applies a chosen manifest to the user's bank
via the import API (``POST /v1/default/banks/{bank}/import``, which creates the
bank if it doesn't exist).
Kept out of ``__init__`` so the wizard logic stays small and testable. The
catalog source is overridable with ``HINDSIGHT_TEMPLATES_URL`` (e.g. to pin a
version or point at a mirror).
"""
from __future__ import annotations
import json
import logging
import os
import urllib.request
from urllib.parse import urljoin
from hermes_cli.urllib_security import open_credentialed_url
logger = logging.getLogger(__name__)
# The Bank Templates catalog lives in the Hindsight docs repo and is the same
# file that powers hindsight.vectorize.io/templates.
_DEFAULT_CATALOG_URL = (
"https://raw.githubusercontent.com/vectorize-io/hindsight/main/"
"hindsight-docs/src/data/templates.json"
)
_HTTP_TIMEOUT = 15
# The starter-template step needs the API reachable during setup. A
# local_embedded daemon isn't running yet at that point, so it's skipped there.
SUPPORTED_MODES = ("cloud", "local_external")
def supported_for_mode(mode: str) -> bool:
return mode in SUPPORTED_MODES
def catalog_url() -> str:
return os.environ.get("HINDSIGHT_TEMPLATES_URL", _DEFAULT_CATALOG_URL)
def _get_json(url: str) -> dict:
req = urllib.request.Request(url, headers={"Accept": "application/json"})
with urllib.request.urlopen(req, timeout=_HTTP_TIMEOUT) as resp: # noqa: S310 - fixed https catalog
return json.loads(resp.read().decode("utf-8"))
def fetch_hermes_templates(url: str | None = None) -> list[dict]:
"""Return catalog entries tagged for the ``hermes`` integration."""
catalog = _get_json(url or catalog_url())
entries = catalog.get("templates", []) if isinstance(catalog, dict) else []
return [e for e in entries if "hermes" in (e.get("integrations") or [])]
def fetch_manifest(entry: dict, url: str | None = None) -> dict:
"""Fetch the BankTemplateManifest JSON for a catalog entry."""
# manifest_file is relative to the catalog (e.g. "templates/foo.json").
manifest_url = urljoin(url or catalog_url(), entry["manifest_file"])
return _get_json(manifest_url)
def apply_template(api_url: str, bank_id: str, api_key: str | None, manifest: dict) -> None:
"""Apply a manifest to a bank via the import endpoint. Raises on failure."""
endpoint = f"{api_url.rstrip('/')}/v1/default/banks/{bank_id}/import"
data = json.dumps(manifest).encode("utf-8")
headers = {"Content-Type": "application/json"}
if api_key:
headers["Authorization"] = f"Bearer {api_key}"
req = urllib.request.Request(endpoint, data=data, headers=headers, method="POST") # noqa: S310
with open_credentialed_url(req, timeout=_HTTP_TIMEOUT) as resp:
resp.read() # drain; open_credentialed_url raises HTTPError on non-2xx
def probe_existing_customization(api_url: str, bank_id: str, api_key: str | None) -> bool:
"""Best-effort: True if the bank already has template-level config, mental
models, or directives — i.e. applying a template would overwrite settings.
A missing bank, or any error, is treated as "not customized": the step must
never block on this probe.
"""
endpoint = f"{api_url.rstrip('/')}/v1/default/banks/{bank_id}/export"
headers = {"Accept": "application/json"}
if api_key:
headers["Authorization"] = f"Bearer {api_key}"
req = urllib.request.Request(endpoint, headers=headers) # noqa: S310
try:
with open_credentialed_url(req, timeout=_HTTP_TIMEOUT) as resp:
data = json.loads(resp.read().decode("utf-8"))
except Exception as e: # missing bank / network — treat as not customized
logger.debug("Hindsight: bank customization probe skipped: %s", e)
return False
return bool(data.get("bank") or data.get("mental_models") or data.get("directives"))
def run_template_step(
*,
api_url: str,
bank_id: str,
api_key: str | None,
select,
cancelled,
log=print,
) -> str | None:
"""Drive the wizard's starter-template step.
``select(title, items, default, cancel_returns)`` is the picker (injected so
this is testable without curses). Returns the applied template id, or None
if skipped/blank/failed. Never raises — the template is a nice-to-have.
"""
try:
entries = fetch_hermes_templates()
except Exception as e: # network/parse — non-fatal
logger.debug("Hindsight: could not fetch templates: %s", e)
return None
if not entries:
return None
items = [(e.get("name", e["id"]), (e.get("description") or "")[:72]) for e in entries]
items.append(("Blank", "Start with an empty memory bank"))
idx = select(" Starter memory template", items, default=0, cancel_returns=cancelled)
if idx == cancelled or idx >= len(entries):
return None # blank or cancelled
entry = entries[idx]
# If the bank is already configured (re-running setup on an existing bank),
# applying a template overwrites its config and upserts its models/directives.
# Confirm before clobbering.
if probe_existing_customization(api_url, bank_id, api_key):
confirm = select(
f" Bank '{bank_id}' already has memory settings — apply this template on top?",
[("Apply", "Overwrite config; add/update mental models & directives"),
("Keep existing", "Leave the bank as-is")],
default=1,
cancel_returns=cancelled,
)
if confirm != 0:
log(f" Kept existing settings for bank '{bank_id}'.")
return None
try:
manifest = fetch_manifest(entry)
apply_template(api_url, bank_id, api_key, manifest)
log(f" ✓ Applied '{entry.get('name', entry['id'])}' template to bank '{bank_id}'")
return entry["id"]
except Exception as e:
log(f" ⚠ Could not apply template ({e}). You can apply one later from "
f"hindsight.vectorize.io/templates.")
return None