lithermes-ai 0.8.0 → 0.8.1
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.
|
@@ -133,6 +133,9 @@ def register(ctx) -> None:
|
|
|
133
133
|
ctx.register_hook("pre_llm_call", _pre_llm_call)
|
|
134
134
|
# Record each delegate_task child (review lanes, reviewer gate) to the ledger.
|
|
135
135
|
ctx.register_hook("subagent_stop", core.subagent_stop)
|
|
136
|
+
# Force the LITBURN banner onto a bare-`lit` keyword turn's response (that
|
|
137
|
+
# path has no deterministic display channel; slash commands print it directly).
|
|
138
|
+
ctx.register_hook("transform_llm_output", core.transform_llm_output)
|
|
136
139
|
|
|
137
140
|
# Model-facing litgoal tools (durable criteria/evidence/checkpoint/steering/gate).
|
|
138
141
|
litgoal_tools.register_tools(ctx)
|
|
@@ -38,6 +38,12 @@ _SLUG_PATTERN = re.compile(r"[^a-z0-9]+")
|
|
|
38
38
|
# for the bare-`lit` keyword path (best-effort — that path only reaches the model).
|
|
39
39
|
LITBURN_BANNER = "🔥 LITBURN IGNITED 🔥"
|
|
40
40
|
|
|
41
|
+
# Session ids whose CURRENT turn triggered the litwork keyword path. The bare
|
|
42
|
+
# `lit` keyword has no deterministic display channel (pre_llm_call only reaches
|
|
43
|
+
# the model), so pre_llm_call flags the turn here and transform_llm_output forces
|
|
44
|
+
# the banner onto that turn's response before the user sees it. Consumed once.
|
|
45
|
+
_PENDING_IGNITE: set[str] = set()
|
|
46
|
+
|
|
41
47
|
|
|
42
48
|
LIT_CONTEXT = "\n".join(
|
|
43
49
|
[
|
|
@@ -258,6 +264,10 @@ def ignite(result: str | dict[str, str]) -> str | dict[str, str]:
|
|
|
258
264
|
def pre_llm_call(**kwargs: Any) -> dict[str, str] | None:
|
|
259
265
|
user_message = str(kwargs.get("user_message") or "")
|
|
260
266
|
session_id = str(kwargs.get("session_id") or "")
|
|
267
|
+
# Clear any stale ignite flag from an interrupted previous turn so it can't
|
|
268
|
+
# leak the banner onto this turn's response. Re-added below only if THIS turn
|
|
269
|
+
# is a keyword-lit turn — keeping the flag scoped to the current turn.
|
|
270
|
+
_PENDING_IGNITE.discard(session_id)
|
|
261
271
|
# /litgoal & /lit-plan declare an objective via the bind-goal marker. Bind it
|
|
262
272
|
# (we have session_id here) and stop — those messages are self-contained.
|
|
263
273
|
bind_obj = _extract_bind_goal(user_message)
|
|
@@ -291,9 +301,31 @@ def pre_llm_call(**kwargs: Any) -> dict[str, str] | None:
|
|
|
291
301
|
session_id=session_id,
|
|
292
302
|
platform=str(kwargs.get("platform") or ""),
|
|
293
303
|
)
|
|
304
|
+
# Flag this turn so transform_llm_output forces the banner onto the response
|
|
305
|
+
# (the keyword path has no deterministic display channel like slash commands).
|
|
306
|
+
if session_id:
|
|
307
|
+
_PENDING_IGNITE.add(session_id)
|
|
294
308
|
return {"context": LIT_CONTEXT + run_context}
|
|
295
309
|
|
|
296
310
|
|
|
311
|
+
def transform_llm_output(**kwargs: Any) -> str | None:
|
|
312
|
+
"""Force the LITBURN banner onto a keyword-`lit` turn's response.
|
|
313
|
+
|
|
314
|
+
Hermes replaces the user-visible response with the first non-empty string a
|
|
315
|
+
transform_llm_output hook returns. Returning None leaves the text unchanged.
|
|
316
|
+
We only act on turns pre_llm_call flagged, consume the flag once, and dedup so
|
|
317
|
+
a model that already opened with the banner is not double-bannered.
|
|
318
|
+
"""
|
|
319
|
+
session_id = str(kwargs.get("session_id") or "")
|
|
320
|
+
if session_id not in _PENDING_IGNITE:
|
|
321
|
+
return None
|
|
322
|
+
_PENDING_IGNITE.discard(session_id)
|
|
323
|
+
response_text = str(kwargs.get("response_text") or "")
|
|
324
|
+
if response_text.lstrip().startswith(LITBURN_BANNER):
|
|
325
|
+
return None # model already emitted it — leave unchanged
|
|
326
|
+
return f"{LITBURN_BANNER}\n\n{response_text}"
|
|
327
|
+
|
|
328
|
+
|
|
297
329
|
def subagent_stop(**kwargs: Any) -> None:
|
|
298
330
|
"""Record each delegate_task child (e.g. a review lane) to the LitHermes ledger.
|
|
299
331
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"syncedAt": "2026-06-
|
|
2
|
+
"syncedAt": "2026-06-14T05:53:21.695Z",
|
|
3
3
|
"source": "source-reference",
|
|
4
|
-
"sourceHash": "
|
|
4
|
+
"sourceHash": "f07cf5a5062f904d4eed678ebf24314e773ca3f92e5c2d1f95c981437e0c5a5a",
|
|
5
5
|
"files": [
|
|
6
6
|
{
|
|
7
7
|
"path": "NOTICE.md",
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "__init__.py",
|
|
16
|
-
"sha256": "
|
|
16
|
+
"sha256": "9a0b19060eb12799bf76b15b729fcbab4388d74aac9e888b40369b809fd54669"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"path": "core.py",
|
|
20
|
-
"sha256": "
|
|
20
|
+
"sha256": "6b9d8b488d5905232d170f78943d2b5f9b9a4bde564e01a816c4fcc45098a7df"
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"path": "litgoal/__init__.py",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"path": "plugin.yaml",
|
|
52
|
-
"sha256": "
|
|
52
|
+
"sha256": "e8ab5e17a3812c1caf91d98e2fb3cf72f2c7d4a429723f0887b6eb3abd736648"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"path": "skills/ai-slop-remover/SKILL.md",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name: lithermes
|
|
2
|
-
version: 0.8.
|
|
2
|
+
version: 0.8.1
|
|
3
3
|
description: "Hermes-native workflow toolkit: litgoal durable runtime, 5-lane review orchestrator, Litwork commands, skills, and prompt steering."
|
|
4
4
|
author: "Hermes Agent"
|
|
5
5
|
kind: standalone
|
|
@@ -7,3 +7,4 @@ auto_load: true
|
|
|
7
7
|
hooks:
|
|
8
8
|
- pre_llm_call
|
|
9
9
|
- subagent_stop
|
|
10
|
+
- transform_llm_output
|