Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,12 @@

logger = logging.getLogger(__name__)

# Canonical profile-home resolver (hermes_constants), with the legacy
# hermes_cli.config location as fallback; both guarded so the plugin still
# imports outside a Hermes install.
# Canonical profile-home resolver (hermes_constants); guarded so the plugin
# still imports outside a Hermes install.
try:
from hermes_constants import get_hermes_home as _hermes_get_hermes_home
except Exception:
try:
from hermes_cli.config import get_hermes_home as _hermes_get_hermes_home
except Exception:
_hermes_get_hermes_home = None
_hermes_get_hermes_home = None

# Canonical config read/write path for provider save_config(); guarded for
# use outside Hermes (raw-YAML fallback below).
Expand Down Expand Up @@ -97,31 +93,12 @@ def _resolve_auxiliary_client(agent=None):
if name.startswith(_FACT_STORE_ROUTE_PREFIX)
}

# Hermes' legacy fixed-action memory wire (`fact_add`, `fact_search`, ...)
# still dispatches, translated onto the exact fact-store routes. It is not
# advertised as schemas any more; the collapsed `fact_store(action=...)`
# surface is.
MEMORY_FACT_ACTIONS = {
"fact_add": "add",
"fact_search": "search",
"fact_probe": "probe",
"fact_related": "related",
"fact_reason": "reason",
"fact_contradict": "contradict",
"fact_update": "update",
"fact_remove": "remove",
"fact_list": "list",
MEMORY_TOOL_MAP = {
"fact_store": {"resolve_action": True},
"fact_feedback": {"tracedecay_name": "tracedecay_fact_feedback"},
"memory_status": {"tracedecay_name": "tracedecay_memory_status"},
}

MEMORY_TOOL_MAP = {"fact_store": {"resolve_action": True}}
for _hermes_name, _action in MEMORY_FACT_ACTIONS.items():
MEMORY_TOOL_MAP[_hermes_name] = {
"tracedecay_name": _FACT_STORE_ROUTE_PREFIX + _action,
"legacy_alias": True,
}
MEMORY_TOOL_MAP["fact_feedback"] = {"tracedecay_name": "tracedecay_fact_feedback"}
MEMORY_TOOL_MAP["memory_status"] = {"tracedecay_name": "tracedecay_memory_status"}

# Canonical tools the memory provider must be able to describe. Reported at
# register() time when this install's catalog does not advertise one, instead
# of registering a schema-less stand-in.
Expand Down Expand Up @@ -169,14 +146,6 @@ def _resolve_auxiliary_client(agent=None):
"anyOf": [{"type": "number"}, {"type": "string"}],
"description": "Optional inclusive maximum raw-message timestamp. Accepts Unix seconds, RFC3339, YYYY-MM-DD, or relative time like 'last hour'.",
},
"since": {
"anyOf": [{"type": "number"}, {"type": "string"}],
"description": "Alias for time_from.",
},
"until": {
"anyOf": [{"type": "number"}, {"type": "string"}],
"description": "Alias for time_to.",
},
},
"required": ["query"],
},
Expand Down Expand Up @@ -2567,10 +2536,8 @@ def save_config(self, values, hermes_home):
logger.warning("tracedecay memory provider save_config failed: %s", exc)

def get_tool_schemas(self):
# Collapsed surface (12 -> 3): fact_store(action=...) covers the nine
# fixed-action fact_* aliases, which remain dispatchable through
# handle_tool_call for compatibility with older transcripts/configs
# but no longer cost per-call schema footprint.
# Collapsed surface: fact_store(action=...) covers every fact-store
# operation without a per-action schema footprint.
# A required canonical tool this catalog does not advertise is left
# out (reported by register()) rather than described by a stand-in.
described = (
Expand Down Expand Up @@ -2599,27 +2566,6 @@ def handle_tool_call(self, name, arguments=None, **kwargs) -> str:
return tools.error_payload(
f"{tool_name} routes to {tracedecay_name}, which this install's tool catalog does not advertise"
)
resolved_action = next(
(
action
for action, route in FACT_STORE_EXACT_ROUTES.items()
if route == tracedecay_name
),
"",
)
if mapping.get("legacy_alias") and "fact_type" in tool_args:
# Hermes' legacy fixed-action provider wire calls the taxonomy
# field ``fact_type``. Translate that compatibility field only
# for the fixed aliases; the canonical generic ``fact_store``
# surface remains category-shaped and is passed through as-is.
fact_type = tool_args.pop("fact_type")
category = tool_args.get("category")
if category is not None and str(category) != str(fact_type):
return tools.error_payload(
"fact_type and category must agree when both are provided"
)
if category is None:
tool_args["category"] = fact_type
if "memory_scope" not in tool_args:
category = str(tool_args.get("category") or "")
if not self.project_root or (
Expand Down Expand Up @@ -2693,8 +2639,7 @@ def bound(*args, **kwargs):
config=context_config,
hermes_home=context_hermes_home,
)
if callable(getattr(ctx, "register_context_engine", None)):
ctx.register_context_engine(context_engine)
ctx.register_context_engine(context_engine)

# Direct tool registration is split by capability:
# - Code-graph / memory / transcript tools register UNCONDITIONALLY.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ memory and does not write project LCM data into an arbitrary working directory.

## Memory

- **Recall before external search.** Run `fact_search` (and `lcm_grep` for past
- **Recall before external search.** Run `fact_store(action="search")` (and `lcm_grep` for past
conversations) before reaching for web or external search. Prior sessions
often already answered the question.
- **Calibrate trust; don't default everything high.** Aim for a spread across
Expand All @@ -134,9 +134,9 @@ memory and does not write project LCM data into an arbitrary working directory.
user-stated preferences).
- `~ 0.7`, ordinary well-sourced observations.
- `~ 0.5`, plausible but unverified; prefer not storing over storing noise.
- **Read the add result's diff report.** `fact_add` returns
`diff` / `closest_fact_id` / `similarity` / `reason`:
- `near_duplicate`, a very similar fact exists; prefer `fact_update` on the
- **Read the add result's diff report.** `fact_store(action="add")`
returns `diff` / `closest_fact_id` / `similarity` / `reason`:
- `near_duplicate`, a very similar fact exists; prefer `fact_store(action="update")` on the
existing fact over piling on duplicates.
- `possible_conflict`, a negation/state-change cue suggests supersession;
confirm which fact is current and update or remove the stale one.
Expand Down
16 changes: 0 additions & 16 deletions crates/tracedecay-automation-runtime/src/automation/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1452,23 +1452,7 @@ mod recorded_failure_tests {
.is_none()
);

let old_coordination = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open(
root.path()
.join("automation_locks/session_reflector.lock.lock"),
)
.expect("old publisher coordination");
assert!(matches!(
old_coordination.try_lock(),
Err(std::fs::TryLockError::WouldBlock)
));
drop(settlement_guard);
old_coordination
.try_lock()
.expect("settlement releases old publisher coordination");
old_coordination.unlock().expect("release old publisher");
assert!(
AutomationTaskLock::try_acquire(root.path(), AgentTaskKind::SessionReflector,)
.await
Expand Down
Loading
Loading