@signetai/connector-hermes-agent 0.182.9 → 0.183.0
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.
- package/dist/index.js +118 -4
- package/hermes-plugin/__init__.py +53 -4
- package/hermes-plugin/client.py +20 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -10451,6 +10451,55 @@ function up114(db) {
|
|
|
10451
10451
|
ON entity_attributes(memory_id, agent_id, status, importance);
|
|
10452
10452
|
`);
|
|
10453
10453
|
}
|
|
10454
|
+
function up115(db) {
|
|
10455
|
+
db.exec(`
|
|
10456
|
+
CREATE TABLE IF NOT EXISTS cross_agent_messages (
|
|
10457
|
+
id TEXT PRIMARY KEY,
|
|
10458
|
+
from_agent_id TEXT NOT NULL,
|
|
10459
|
+
from_session_key TEXT,
|
|
10460
|
+
to_agent_id TEXT,
|
|
10461
|
+
to_session_key TEXT,
|
|
10462
|
+
to_session_agent_id TEXT,
|
|
10463
|
+
broadcast INTEGER NOT NULL DEFAULT 0 CHECK(broadcast IN (0, 1)),
|
|
10464
|
+
message_type TEXT NOT NULL CHECK(message_type IN ('assist_request', 'decision_update', 'info', 'question')),
|
|
10465
|
+
content TEXT NOT NULL,
|
|
10466
|
+
delivery_path TEXT NOT NULL CHECK(delivery_path IN ('local', 'acp')),
|
|
10467
|
+
delivery_status TEXT NOT NULL CHECK(delivery_status IN ('queued', 'delivered', 'failed')),
|
|
10468
|
+
delivery_error TEXT,
|
|
10469
|
+
delivery_receipt_json TEXT,
|
|
10470
|
+
created_at TEXT NOT NULL,
|
|
10471
|
+
expires_at TEXT NOT NULL,
|
|
10472
|
+
CHECK(
|
|
10473
|
+
delivery_path = 'acp'
|
|
10474
|
+
OR (
|
|
10475
|
+
CAST(to_agent_id IS NOT NULL AS INTEGER)
|
|
10476
|
+
+ CAST(to_session_key IS NOT NULL AS INTEGER)
|
|
10477
|
+
+ broadcast = 1
|
|
10478
|
+
)
|
|
10479
|
+
)
|
|
10480
|
+
);
|
|
10481
|
+
|
|
10482
|
+
CREATE TABLE IF NOT EXISTS cross_agent_message_receipts (
|
|
10483
|
+
message_id TEXT NOT NULL REFERENCES cross_agent_messages(id) ON DELETE CASCADE,
|
|
10484
|
+
agent_id TEXT NOT NULL,
|
|
10485
|
+
acknowledged_at TEXT NOT NULL,
|
|
10486
|
+
PRIMARY KEY (message_id, agent_id)
|
|
10487
|
+
);
|
|
10488
|
+
|
|
10489
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_agent
|
|
10490
|
+
ON cross_agent_messages(to_agent_id, expires_at, created_at, id);
|
|
10491
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_session
|
|
10492
|
+
ON cross_agent_messages(to_session_key, expires_at, created_at, id);
|
|
10493
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_session_agent
|
|
10494
|
+
ON cross_agent_messages(to_session_agent_id, expires_at, created_at, id);
|
|
10495
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_broadcast
|
|
10496
|
+
ON cross_agent_messages(broadcast, expires_at, created_at, id);
|
|
10497
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_sender
|
|
10498
|
+
ON cross_agent_messages(from_agent_id, expires_at, created_at, id);
|
|
10499
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_receipts_agent
|
|
10500
|
+
ON cross_agent_message_receipts(agent_id, acknowledged_at, message_id);
|
|
10501
|
+
`);
|
|
10502
|
+
}
|
|
10454
10503
|
var MIGRATIONS = [
|
|
10455
10504
|
{
|
|
10456
10505
|
version: 1,
|
|
@@ -11368,6 +11417,14 @@ var MIGRATIONS = [
|
|
|
11368
11417
|
version: 114,
|
|
11369
11418
|
name: "memory-traversal-hydration-index",
|
|
11370
11419
|
up: up114
|
|
11420
|
+
},
|
|
11421
|
+
{
|
|
11422
|
+
version: 115,
|
|
11423
|
+
name: "cross-agent-message-notifications",
|
|
11424
|
+
up: up115,
|
|
11425
|
+
artifacts: {
|
|
11426
|
+
tables: ["cross_agent_messages", "cross_agent_message_receipts"]
|
|
11427
|
+
}
|
|
11371
11428
|
}
|
|
11372
11429
|
];
|
|
11373
11430
|
var LATEST_SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
|
|
@@ -18635,7 +18692,7 @@ function memoriesFtsNeedsTokenizerRepair2(sql) {
|
|
|
18635
18692
|
return true;
|
|
18636
18693
|
return !normalized.includes(`tokenize='${MEMORIES_FTS_TOKENIZER2}'`);
|
|
18637
18694
|
}
|
|
18638
|
-
function
|
|
18695
|
+
function up116(db) {
|
|
18639
18696
|
db.exec(`
|
|
18640
18697
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
18641
18698
|
version INTEGER PRIMARY KEY,
|
|
@@ -19058,7 +19115,7 @@ function up1010(db) {
|
|
|
19058
19115
|
)
|
|
19059
19116
|
`);
|
|
19060
19117
|
}
|
|
19061
|
-
function
|
|
19118
|
+
function up117(db) {
|
|
19062
19119
|
db.exec(`
|
|
19063
19120
|
CREATE TABLE IF NOT EXISTS session_scores (
|
|
19064
19121
|
id TEXT PRIMARY KEY,
|
|
@@ -22118,11 +22175,60 @@ function up1142(db) {
|
|
|
22118
22175
|
ON entity_attributes(memory_id, agent_id, status, importance);
|
|
22119
22176
|
`);
|
|
22120
22177
|
}
|
|
22178
|
+
function up1152(db) {
|
|
22179
|
+
db.exec(`
|
|
22180
|
+
CREATE TABLE IF NOT EXISTS cross_agent_messages (
|
|
22181
|
+
id TEXT PRIMARY KEY,
|
|
22182
|
+
from_agent_id TEXT NOT NULL,
|
|
22183
|
+
from_session_key TEXT,
|
|
22184
|
+
to_agent_id TEXT,
|
|
22185
|
+
to_session_key TEXT,
|
|
22186
|
+
to_session_agent_id TEXT,
|
|
22187
|
+
broadcast INTEGER NOT NULL DEFAULT 0 CHECK(broadcast IN (0, 1)),
|
|
22188
|
+
message_type TEXT NOT NULL CHECK(message_type IN ('assist_request', 'decision_update', 'info', 'question')),
|
|
22189
|
+
content TEXT NOT NULL,
|
|
22190
|
+
delivery_path TEXT NOT NULL CHECK(delivery_path IN ('local', 'acp')),
|
|
22191
|
+
delivery_status TEXT NOT NULL CHECK(delivery_status IN ('queued', 'delivered', 'failed')),
|
|
22192
|
+
delivery_error TEXT,
|
|
22193
|
+
delivery_receipt_json TEXT,
|
|
22194
|
+
created_at TEXT NOT NULL,
|
|
22195
|
+
expires_at TEXT NOT NULL,
|
|
22196
|
+
CHECK(
|
|
22197
|
+
delivery_path = 'acp'
|
|
22198
|
+
OR (
|
|
22199
|
+
CAST(to_agent_id IS NOT NULL AS INTEGER)
|
|
22200
|
+
+ CAST(to_session_key IS NOT NULL AS INTEGER)
|
|
22201
|
+
+ broadcast = 1
|
|
22202
|
+
)
|
|
22203
|
+
)
|
|
22204
|
+
);
|
|
22205
|
+
|
|
22206
|
+
CREATE TABLE IF NOT EXISTS cross_agent_message_receipts (
|
|
22207
|
+
message_id TEXT NOT NULL REFERENCES cross_agent_messages(id) ON DELETE CASCADE,
|
|
22208
|
+
agent_id TEXT NOT NULL,
|
|
22209
|
+
acknowledged_at TEXT NOT NULL,
|
|
22210
|
+
PRIMARY KEY (message_id, agent_id)
|
|
22211
|
+
);
|
|
22212
|
+
|
|
22213
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_agent
|
|
22214
|
+
ON cross_agent_messages(to_agent_id, expires_at, created_at, id);
|
|
22215
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_session
|
|
22216
|
+
ON cross_agent_messages(to_session_key, expires_at, created_at, id);
|
|
22217
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_session_agent
|
|
22218
|
+
ON cross_agent_messages(to_session_agent_id, expires_at, created_at, id);
|
|
22219
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_broadcast
|
|
22220
|
+
ON cross_agent_messages(broadcast, expires_at, created_at, id);
|
|
22221
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_messages_sender
|
|
22222
|
+
ON cross_agent_messages(from_agent_id, expires_at, created_at, id);
|
|
22223
|
+
CREATE INDEX IF NOT EXISTS idx_cross_agent_receipts_agent
|
|
22224
|
+
ON cross_agent_message_receipts(agent_id, acknowledged_at, message_id);
|
|
22225
|
+
`);
|
|
22226
|
+
}
|
|
22121
22227
|
var MIGRATIONS2 = [
|
|
22122
22228
|
{
|
|
22123
22229
|
version: 1,
|
|
22124
22230
|
name: "baseline",
|
|
22125
|
-
up:
|
|
22231
|
+
up: up116,
|
|
22126
22232
|
artifacts: { tables: ["memories", "conversations", "embeddings"] }
|
|
22127
22233
|
},
|
|
22128
22234
|
{
|
|
@@ -22188,7 +22294,7 @@ var MIGRATIONS2 = [
|
|
|
22188
22294
|
{
|
|
22189
22295
|
version: 11,
|
|
22190
22296
|
name: "session-scores",
|
|
22191
|
-
up:
|
|
22297
|
+
up: up117,
|
|
22192
22298
|
artifacts: { tables: ["session_scores"] }
|
|
22193
22299
|
},
|
|
22194
22300
|
{
|
|
@@ -23035,6 +23141,14 @@ var MIGRATIONS2 = [
|
|
|
23035
23141
|
version: 114,
|
|
23036
23142
|
name: "memory-traversal-hydration-index",
|
|
23037
23143
|
up: up1142
|
|
23144
|
+
},
|
|
23145
|
+
{
|
|
23146
|
+
version: 115,
|
|
23147
|
+
name: "cross-agent-message-notifications",
|
|
23148
|
+
up: up1152,
|
|
23149
|
+
artifacts: {
|
|
23150
|
+
tables: ["cross_agent_messages", "cross_agent_message_receipts"]
|
|
23151
|
+
}
|
|
23038
23152
|
}
|
|
23039
23153
|
];
|
|
23040
23154
|
var LATEST_SCHEMA_VERSION2 = MIGRATIONS2[MIGRATIONS2.length - 1]?.version ?? 0;
|
|
@@ -327,6 +327,7 @@ class SignetMemoryProvider(MemoryProvider):
|
|
|
327
327
|
self._inject_cache = ""
|
|
328
328
|
self._inject_lock = threading.Lock()
|
|
329
329
|
self._prefetch_result = ""
|
|
330
|
+
self._notification_result = ""
|
|
330
331
|
self._prefetch_lock = threading.Lock()
|
|
331
332
|
self._prefetch_thread: Optional[threading.Thread] = None
|
|
332
333
|
self._prefetch_generation = 0
|
|
@@ -485,11 +486,27 @@ class SignetMemoryProvider(MemoryProvider):
|
|
|
485
486
|
if self._prefetch_thread and self._prefetch_thread.is_alive():
|
|
486
487
|
self._prefetch_thread.join(timeout=3.0)
|
|
487
488
|
|
|
489
|
+
client = self._client
|
|
490
|
+
if client:
|
|
491
|
+
try:
|
|
492
|
+
notification = client.notifications(
|
|
493
|
+
self._session_key,
|
|
494
|
+
"prefetch",
|
|
495
|
+
project=self._project,
|
|
496
|
+
)
|
|
497
|
+
if notification is not None:
|
|
498
|
+
notification_inject = notification.get("inject", "")
|
|
499
|
+
with self._prefetch_lock:
|
|
500
|
+
self._notification_result = notification_inject if isinstance(notification_inject, str) else ""
|
|
501
|
+
except Exception as e:
|
|
502
|
+
logger.debug("Signet notification prefetch failed: %s", e)
|
|
503
|
+
|
|
488
504
|
with self._prefetch_lock:
|
|
489
|
-
|
|
505
|
+
parts = [self._prefetch_result, self._notification_result]
|
|
490
506
|
self._prefetch_result = ""
|
|
507
|
+
self._notification_result = ""
|
|
491
508
|
|
|
492
|
-
return
|
|
509
|
+
return "\n".join(part for part in parts if part and part.strip())
|
|
493
510
|
|
|
494
511
|
def queue_prefetch(self, query: str, *, session_id: str = "") -> None:
|
|
495
512
|
"""Fire a background recall via user-prompt-submit hook.
|
|
@@ -513,6 +530,7 @@ class SignetMemoryProvider(MemoryProvider):
|
|
|
513
530
|
with self._prefetch_lock:
|
|
514
531
|
self._prefetch_generation += 1
|
|
515
532
|
self._prefetch_result = ""
|
|
533
|
+
self._notification_result = ""
|
|
516
534
|
session_key = self._session_key
|
|
517
535
|
project = self._project
|
|
518
536
|
prefetch_generation = self._prefetch_generation
|
|
@@ -542,10 +560,16 @@ class SignetMemoryProvider(MemoryProvider):
|
|
|
542
560
|
)
|
|
543
561
|
return
|
|
544
562
|
inject = result.get("inject", "")
|
|
545
|
-
|
|
563
|
+
notification = result.get("notifications")
|
|
564
|
+
notification_inject = notification.get("inject", "") if isinstance(notification, dict) else ""
|
|
565
|
+
recall_inject = inject
|
|
566
|
+
if notification_inject and inject.rstrip().endswith(notification_inject.strip()):
|
|
567
|
+
recall_inject = inject.rstrip()[: -len(notification_inject.strip())].rstrip()
|
|
568
|
+
if (recall_inject and recall_inject.strip()) or (notification_inject and notification_inject.strip()):
|
|
546
569
|
with self._prefetch_lock:
|
|
547
570
|
if prefetch_generation == self._prefetch_generation and session_key == self._session_key:
|
|
548
|
-
self._prefetch_result =
|
|
571
|
+
self._prefetch_result = recall_inject
|
|
572
|
+
self._notification_result = notification_inject
|
|
549
573
|
except Exception as e:
|
|
550
574
|
logger.debug("Signet prefetch failed: %s", e)
|
|
551
575
|
|
|
@@ -584,6 +608,29 @@ class SignetMemoryProvider(MemoryProvider):
|
|
|
584
608
|
if assistant_content:
|
|
585
609
|
with self._transcript_lock:
|
|
586
610
|
self._transcript_lines.append(f"assistant: {assistant_content}")
|
|
611
|
+
self._queue_notification_refresh("sync_turn")
|
|
612
|
+
|
|
613
|
+
def _queue_notification_refresh(self, hook: str) -> None:
|
|
614
|
+
"""Fetch peer notifications without blocking the current Hermes callback."""
|
|
615
|
+
client = self._client
|
|
616
|
+
if not client:
|
|
617
|
+
return
|
|
618
|
+
session_key = self._session_key
|
|
619
|
+
project = self._project
|
|
620
|
+
with self._prefetch_lock:
|
|
621
|
+
generation = self._prefetch_generation
|
|
622
|
+
|
|
623
|
+
def _run():
|
|
624
|
+
try:
|
|
625
|
+
result = client.notifications(session_key, hook, project=project)
|
|
626
|
+
inject = (result or {}).get("inject", "")
|
|
627
|
+
with self._prefetch_lock:
|
|
628
|
+
if generation == self._prefetch_generation and session_key == self._session_key:
|
|
629
|
+
self._notification_result = inject if isinstance(inject, str) else ""
|
|
630
|
+
except Exception as e:
|
|
631
|
+
logger.debug("Signet %s notification refresh failed: %s", hook, e)
|
|
632
|
+
|
|
633
|
+
threading.Thread(target=_run, daemon=True, name=f"signet-notify-{hook}").start()
|
|
587
634
|
|
|
588
635
|
def on_session_switch(
|
|
589
636
|
self,
|
|
@@ -615,6 +662,7 @@ class SignetMemoryProvider(MemoryProvider):
|
|
|
615
662
|
with self._prefetch_lock:
|
|
616
663
|
self._prefetch_generation += 1
|
|
617
664
|
self._prefetch_result = ""
|
|
665
|
+
self._notification_result = ""
|
|
618
666
|
|
|
619
667
|
agent_id = os.environ.get("SIGNET_AGENT_ID", "").strip() or "hermes-agent"
|
|
620
668
|
self._project = _resolve_agent_workspace(agent_id, kwargs)
|
|
@@ -818,6 +866,7 @@ class SignetMemoryProvider(MemoryProvider):
|
|
|
818
866
|
|
|
819
867
|
t = threading.Thread(target=_run, daemon=True, name="signet-delegation")
|
|
820
868
|
t.start()
|
|
869
|
+
self._queue_notification_refresh("on_delegation")
|
|
821
870
|
|
|
822
871
|
def _fire_checkpoint(self) -> None:
|
|
823
872
|
"""Fire a checkpoint-extract for long-running sessions."""
|
package/hermes-plugin/client.py
CHANGED
|
@@ -319,6 +319,26 @@ class SignetClient:
|
|
|
319
319
|
timeout=_RECALL_TIMEOUT_SECS,
|
|
320
320
|
)
|
|
321
321
|
|
|
322
|
+
def notifications(
|
|
323
|
+
self,
|
|
324
|
+
session_key: str,
|
|
325
|
+
hook: str,
|
|
326
|
+
*,
|
|
327
|
+
project: str = "",
|
|
328
|
+
) -> Optional[Dict[str, Any]]:
|
|
329
|
+
"""Fetch pending peer notifications for a compatible Hermes hook."""
|
|
330
|
+
return self._post(
|
|
331
|
+
"/api/hooks/notifications",
|
|
332
|
+
{
|
|
333
|
+
"harness": self._harness,
|
|
334
|
+
"hook": hook,
|
|
335
|
+
"sessionKey": session_key,
|
|
336
|
+
"agentId": self._agent_id,
|
|
337
|
+
"project": project,
|
|
338
|
+
},
|
|
339
|
+
timeout=_RECALL_TIMEOUT_SECS,
|
|
340
|
+
)
|
|
341
|
+
|
|
322
342
|
def session_end(
|
|
323
343
|
self,
|
|
324
344
|
session_key: str,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signetai/connector-hermes-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.183.0",
|
|
4
4
|
"description": "Signet connector for Hermes Agent — installs Signet as a pluggable memory provider",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"typecheck": "tsc --noEmit"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@signetai/connector-base": "0.
|
|
29
|
-
"@signetai/core": "0.
|
|
28
|
+
"@signetai/connector-base": "0.183.0",
|
|
29
|
+
"@signetai/core": "0.183.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.0.0",
|