@signetai/connector-hermes-agent 0.206.8 → 0.208.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.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { BaseConnector, type InstallResult, type UninstallResult } from "@signetai/connector-base";
2
+ import { type HermesTarget } from "@signetai/core";
2
3
  export interface HermesDiagnosticCheck {
3
4
  readonly id: string;
4
5
  readonly label: string;
@@ -17,9 +18,36 @@ export interface HermesDoctorReport {
17
18
  readonly checks: readonly HermesDiagnosticCheck[];
18
19
  readonly warnings: readonly string[];
19
20
  }
21
+ type AgentReadPolicy = "isolated" | "shared" | "group";
22
+ export interface AgentRegistrationOptions {
23
+ readonly agentId: string;
24
+ readonly readPolicy?: AgentReadPolicy;
25
+ readonly policyGroup?: string | null;
26
+ /** Requested profile provisioning must fail closed instead of warning. */
27
+ readonly strict?: boolean;
28
+ }
29
+ export type AgentRegistrationResult = {
30
+ readonly ok: true;
31
+ readonly created: boolean;
32
+ readonly agentId: string;
33
+ } | {
34
+ readonly ok: false;
35
+ readonly agentId: string;
36
+ readonly error: string;
37
+ };
38
+ export declare function ensureNamedAgentRegistered(daemonUrl: string, agentIdOrOptions: string | AgentRegistrationOptions, warnings: string[]): Promise<AgentRegistrationResult>;
39
+ export interface HermesConnectorOptions {
40
+ readonly target?: HermesTarget;
41
+ readonly agentId?: string;
42
+ readonly readPolicy?: AgentReadPolicy;
43
+ readonly policyGroup?: string | null;
44
+ }
20
45
  export declare class HermesAgentConnector extends BaseConnector {
21
46
  readonly name = "Hermes Agent";
22
47
  readonly harnessId = "hermes-agent";
48
+ private readonly target?;
49
+ private readonly registration?;
50
+ constructor(options?: HermesTarget | HermesConnectorOptions);
23
51
  private getHermesHome;
24
52
  private getHermesRepo;
25
53
  getConfigPath(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAuB,MAAM,wBAAwB,CAAC;AAoDtH,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAClD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAsrBD,qBAAa,oBAAqB,SAAQ,aAAa;IACtD,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,SAAS,kBAAkB;IAEpC,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,aAAa;IAIrB,aAAa,IAAI,MAAM;IAIjB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAgMjD,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC;IAuD3C,WAAW,IAAI,OAAO;IAQhB,QAAQ,IAAI,OAAO,CAAC,kBAAkB,CAAC;CAS7C;AAED,wBAAsB,yBAAyB,CAAC,IAAI,CAAC,EAAE;IACtD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuG9B;AAED,wBAAgB,eAAe,IAAI,oBAAoB,CAEtD;AAED,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  // src/index.ts
2
2
  import { spawnSync } from "node:child_process";
3
3
  import { createHash as createHash5 } from "node:crypto";
4
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
4
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, realpathSync as realpathSync3, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
5
5
  import { homedir } from "node:os";
6
- import { dirname as dirname6, join as join4 } from "node:path";
6
+ import { dirname as dirname6, isAbsolute as isAbsolute2, join as join4, relative as relative2 } from "node:path";
7
7
  import { fileURLToPath as fileURLToPath3 } from "node:url";
8
8
 
9
9
  // ../../../libs/connector-base/dist/index.js
10
10
  import { randomBytes } from "node:crypto";
11
- import { existsSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
11
+ import { existsSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
12
12
  import { dirname as dirname2, isAbsolute, join as join3, relative, sep } from "node:path";
13
13
  import { createRequire } from "node:module";
14
14
  import { dirname, join } from "node:path";
@@ -15621,6 +15621,120 @@ function up132(db) {
15621
15621
  ON epistemic_assertions(agent_id, subject_entity_id, status, asserted_at DESC, created_at DESC);
15622
15622
  `);
15623
15623
  }
15624
+ function up133(db) {
15625
+ db.exec(`
15626
+ CREATE TABLE IF NOT EXISTS memory_head_revisions (
15627
+ id TEXT PRIMARY KEY,
15628
+ agent_id TEXT NOT NULL,
15629
+ revision INTEGER NOT NULL,
15630
+ content TEXT NOT NULL,
15631
+ content_hash TEXT NOT NULL,
15632
+ rendered_token_count INTEGER NOT NULL,
15633
+ pass_id TEXT NOT NULL,
15634
+ base_revision INTEGER NOT NULL,
15635
+ base_hash TEXT NOT NULL,
15636
+ created_at TEXT NOT NULL,
15637
+ UNIQUE(agent_id, revision)
15638
+ );
15639
+ CREATE INDEX IF NOT EXISTS idx_memory_head_revisions_agent
15640
+ ON memory_head_revisions(agent_id, revision DESC);
15641
+ CREATE TABLE IF NOT EXISTS memory_head_entries (
15642
+ entry_id TEXT PRIMARY KEY,
15643
+ agent_id TEXT NOT NULL,
15644
+ canonical_text TEXT NOT NULL,
15645
+ entry_hash TEXT NOT NULL,
15646
+ status TEXT NOT NULL CHECK(status IN ('active','removed','superseded')),
15647
+ first_revision INTEGER NOT NULL,
15648
+ last_revision INTEGER NOT NULL,
15649
+ created_at TEXT NOT NULL,
15650
+ updated_at TEXT NOT NULL
15651
+ );
15652
+ CREATE INDEX IF NOT EXISTS idx_memory_head_entries_agent
15653
+ ON memory_head_entries(agent_id, entry_id, last_revision DESC);
15654
+ CREATE TABLE IF NOT EXISTS memory_head_revision_entries (
15655
+ agent_id TEXT NOT NULL,
15656
+ revision INTEGER NOT NULL,
15657
+ entry_id TEXT NOT NULL,
15658
+ ordinal INTEGER NOT NULL,
15659
+ operation TEXT NOT NULL CHECK(operation IN ('add','update','remove','retain')),
15660
+ provenance_json TEXT NOT NULL,
15661
+ PRIMARY KEY(agent_id, revision, entry_id),
15662
+ UNIQUE(agent_id, revision, ordinal)
15663
+ );
15664
+ CREATE INDEX IF NOT EXISTS idx_memory_head_revision_entries_entry
15665
+ ON memory_head_revision_entries(agent_id, entry_id, revision DESC);
15666
+ `);
15667
+ const columns = db.prepare("PRAGMA table_info(memory_md_heads)").all();
15668
+ const names = new Set(columns.map((column) => String(column.name)));
15669
+ if (!names.has("revision_id"))
15670
+ db.exec("ALTER TABLE memory_md_heads ADD COLUMN revision_id TEXT");
15671
+ if (!names.has("pass_id"))
15672
+ db.exec("ALTER TABLE memory_md_heads ADD COLUMN pass_id TEXT");
15673
+ if (!names.has("format_version"))
15674
+ db.exec("ALTER TABLE memory_md_heads ADD COLUMN format_version INTEGER NOT NULL DEFAULT 1");
15675
+ }
15676
+ function up134(db) {
15677
+ db.exec(`
15678
+ CREATE TABLE memory_head_entries_v134 (
15679
+ entry_id TEXT NOT NULL, agent_id TEXT NOT NULL, canonical_text TEXT NOT NULL,
15680
+ entry_hash TEXT NOT NULL, status TEXT NOT NULL CHECK(status IN ('active','removed','superseded')),
15681
+ first_revision INTEGER NOT NULL, last_revision INTEGER NOT NULL,
15682
+ created_at TEXT NOT NULL, updated_at TEXT NOT NULL,
15683
+ PRIMARY KEY(agent_id, entry_id)
15684
+ );
15685
+ INSERT INTO memory_head_entries_v134
15686
+ SELECT entry_id, agent_id, canonical_text, entry_hash, status, first_revision, last_revision, created_at, updated_at
15687
+ FROM memory_head_entries;
15688
+ DROP TABLE memory_head_entries;
15689
+ ALTER TABLE memory_head_entries_v134 RENAME TO memory_head_entries;
15690
+ CREATE INDEX idx_memory_head_entries_agent
15691
+ ON memory_head_entries(agent_id, entry_id, last_revision DESC);
15692
+ `);
15693
+ }
15694
+ function up135(db) {
15695
+ db.exec(`
15696
+ CREATE TABLE IF NOT EXISTS memory_head_publications (
15697
+ agent_id TEXT NOT NULL,
15698
+ revision INTEGER NOT NULL,
15699
+ revision_id TEXT NOT NULL,
15700
+ status TEXT NOT NULL CHECK(status IN ('pending', 'completed')),
15701
+ created_at TEXT NOT NULL,
15702
+ completed_at TEXT,
15703
+ PRIMARY KEY(agent_id, revision),
15704
+ UNIQUE(agent_id, revision_id)
15705
+ );
15706
+ CREATE INDEX IF NOT EXISTS idx_memory_head_publications_pending
15707
+ ON memory_head_publications(agent_id, status, revision DESC);
15708
+ `);
15709
+ }
15710
+ function up136(db) {
15711
+ const cols = new Set(db.prepare("PRAGMA table_info(memory_head_revisions)").all().map((r2) => r2.name));
15712
+ for (const [name, type] of [
15713
+ ["entry_id", "TEXT"],
15714
+ ["entry_text", "TEXT"],
15715
+ ["operation", "TEXT"],
15716
+ ["source_refs_json", "TEXT"],
15717
+ ["supporting_quotes_json", "TEXT"]
15718
+ ]) {
15719
+ if (!cols.has(name))
15720
+ db.exec(`ALTER TABLE memory_head_revisions ADD COLUMN ${name} ${type}`);
15721
+ }
15722
+ db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_head_revisions_entry ON memory_head_revisions(agent_id, revision, entry_id)");
15723
+ }
15724
+ function up137(db) {
15725
+ const cols = new Set(db.prepare("PRAGMA table_info(dreaming_passes)").all().map((r2) => r2.name));
15726
+ for (const [name, type] of [
15727
+ ["head_revision", "INTEGER"],
15728
+ ["head_hash", "TEXT"],
15729
+ ["head_added", "INTEGER NOT NULL DEFAULT 0"],
15730
+ ["head_updated", "INTEGER NOT NULL DEFAULT 0"],
15731
+ ["head_removed", "INTEGER NOT NULL DEFAULT 0"],
15732
+ ["head_deferred", "INTEGER NOT NULL DEFAULT 0"],
15733
+ ["head_no_op", "INTEGER NOT NULL DEFAULT 0"]
15734
+ ])
15735
+ if (!cols.has(name))
15736
+ db.exec(`ALTER TABLE dreaming_passes ADD COLUMN ${name} ${type}`);
15737
+ }
15624
15738
  var MIGRATIONS = [
15625
15739
  {
15626
15740
  version: 1,
@@ -16675,6 +16789,41 @@ var MIGRATIONS = [
16675
16789
  name: "observer-scoped-epistemic-assertions",
16676
16790
  up: up132,
16677
16791
  artifacts: { tables: ["epistemic_assertions"] }
16792
+ },
16793
+ {
16794
+ version: 133,
16795
+ name: "dreaming-memory-head",
16796
+ up: up133,
16797
+ artifacts: { tables: ["memory_head_revisions", "memory_head_entries", "memory_head_revision_entries"] }
16798
+ },
16799
+ {
16800
+ version: 134,
16801
+ name: "scope-memory-head-entries",
16802
+ up: up134,
16803
+ artifacts: { tables: ["memory_head_entries"] }
16804
+ },
16805
+ {
16806
+ version: 135,
16807
+ name: "memory-head-publication",
16808
+ up: up135,
16809
+ artifacts: { tables: ["memory_head_publications"] }
16810
+ },
16811
+ {
16812
+ version: 136,
16813
+ name: "memory-head-revisions",
16814
+ up: up136,
16815
+ artifacts: { tables: ["memory_head_revisions"] }
16816
+ },
16817
+ {
16818
+ version: 137,
16819
+ name: "dreaming-head-manifest",
16820
+ up: up137,
16821
+ artifacts: {
16822
+ columns: [
16823
+ { table: "dreaming_passes", column: "head_revision" },
16824
+ { table: "dreaming_passes", column: "head_hash" }
16825
+ ]
16826
+ }
16678
16827
  }
16679
16828
  ];
16680
16829
  var LATEST_SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
@@ -16710,16 +16859,42 @@ function classifyError(error) {
16710
16859
  }
16711
16860
  return { state: "corrupt", message };
16712
16861
  }
16862
+ function tryRequireOverride() {
16863
+ const override = process.env.SIGNET_KEYRING_NATIVE_MODULE_PATH?.trim();
16864
+ if (!override)
16865
+ return null;
16866
+ const isAbsolute2 = override.startsWith("/") || /^\\\\[^\\]+\\[^\\]+/.test(override) || /^[A-Za-z]:[\\/]/.test(override);
16867
+ if (!isAbsolute2)
16868
+ return null;
16869
+ try {
16870
+ return require2(override);
16871
+ } catch {
16872
+ return null;
16873
+ }
16874
+ }
16713
16875
  async function loadModule() {
16714
- modulePromise ??= Promise.resolve().then(() => __toESM2(require_keyring(), 1)).catch(() => null);
16876
+ modulePromise ??= (async () => {
16877
+ const override = process.env.SIGNET_KEYRING_NATIVE_MODULE_PATH?.trim();
16878
+ if (override)
16879
+ return tryRequireOverride();
16880
+ return await Promise.resolve().then(() => __toESM2(require_keyring(), 1)).catch(() => null);
16881
+ })();
16715
16882
  return modulePromise;
16716
16883
  }
16717
16884
  function loadModuleSync() {
16718
16885
  if (syncModule !== undefined)
16719
16886
  return syncModule;
16887
+ if (process.env.SIGNET_KEYRING_NATIVE_MODULE_PATH?.trim()) {
16888
+ syncModule = tryRequireOverride();
16889
+ return syncModule;
16890
+ }
16891
+ const override = tryRequireOverride();
16892
+ if (override) {
16893
+ syncModule = override;
16894
+ return syncModule;
16895
+ }
16720
16896
  try {
16721
- const mod = require2("@napi-rs/keyring");
16722
- syncModule = mod;
16897
+ syncModule = require2("@napi-rs/keyring");
16723
16898
  } catch {
16724
16899
  syncModule = null;
16725
16900
  }
@@ -17044,6 +17219,12 @@ class BaseConnector {
17044
17219
  const cleaned = stripSignetBlock(raw);
17045
17220
  if (cleaned === raw)
17046
17221
  return null;
17222
+ const root = realpathSync(basePath);
17223
+ const parent = realpathSync(dirname2(agentsPath));
17224
+ const rel = relative(root, join3(parent, "AGENTS.md"));
17225
+ if (rel.startsWith("..") || isAbsolute(rel)) {
17226
+ throw new Error(`Target path escapes validated root: ${agentsPath}`);
17227
+ }
17047
17228
  const tmp = join3(basePath, `.${randomBytes(6).toString("hex")}.tmp`);
17048
17229
  try {
17049
17230
  writeFileSync(tmp, cleaned, "utf-8");
@@ -17123,7 +17304,7 @@ import { dirname as dirname42, join as join82, resolve as resolve22 } from "node
17123
17304
  import { homedir as homedir62, platform as platform22 } from "node:os";
17124
17305
  import { basename as basename2, dirname as dirname52, resolve as resolve42 } from "node:path";
17125
17306
  import { execFileSync as execFileSync3 } from "node:child_process";
17126
- import { existsSync as existsSync12, readFileSync as readFileSync10, readdirSync as readdirSync5, realpathSync, statSync as statSync7 } from "node:fs";
17307
+ import { existsSync as existsSync12, readFileSync as readFileSync10, readdirSync as readdirSync5, realpathSync as realpathSync2, statSync as statSync7 } from "node:fs";
17127
17308
  import { homedir as homedir9 } from "node:os";
17128
17309
  import { dirname as dirname8, join as join13 } from "node:path";
17129
17310
  import { homedir as homedir102 } from "node:os";
@@ -28484,7 +28665,7 @@ function memoriesFtsNeedsTokenizerRepair2(sql) {
28484
28665
  return true;
28485
28666
  return !normalized.includes(`tokenize='${MEMORIES_FTS_TOKENIZER2}'`);
28486
28667
  }
28487
- function up133(db) {
28668
+ function up138(db) {
28488
28669
  db.exec(`
28489
28670
  CREATE TABLE IF NOT EXISTS schema_migrations (
28490
28671
  version INTEGER PRIMARY KEY,
@@ -28968,7 +29149,7 @@ function addColumnIfMissing52(db, table, column, definition) {
28968
29149
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
28969
29150
  }
28970
29151
  }
28971
- function up134(db) {
29152
+ function up139(db) {
28972
29153
  db.exec(`
28973
29154
  CREATE TABLE IF NOT EXISTS ingestion_jobs (
28974
29155
  id TEXT PRIMARY KEY,
@@ -32723,11 +32904,125 @@ function up1322(db) {
32723
32904
  ON epistemic_assertions(agent_id, subject_entity_id, status, asserted_at DESC, created_at DESC);
32724
32905
  `);
32725
32906
  }
32907
+ function up1332(db) {
32908
+ db.exec(`
32909
+ CREATE TABLE IF NOT EXISTS memory_head_revisions (
32910
+ id TEXT PRIMARY KEY,
32911
+ agent_id TEXT NOT NULL,
32912
+ revision INTEGER NOT NULL,
32913
+ content TEXT NOT NULL,
32914
+ content_hash TEXT NOT NULL,
32915
+ rendered_token_count INTEGER NOT NULL,
32916
+ pass_id TEXT NOT NULL,
32917
+ base_revision INTEGER NOT NULL,
32918
+ base_hash TEXT NOT NULL,
32919
+ created_at TEXT NOT NULL,
32920
+ UNIQUE(agent_id, revision)
32921
+ );
32922
+ CREATE INDEX IF NOT EXISTS idx_memory_head_revisions_agent
32923
+ ON memory_head_revisions(agent_id, revision DESC);
32924
+ CREATE TABLE IF NOT EXISTS memory_head_entries (
32925
+ entry_id TEXT PRIMARY KEY,
32926
+ agent_id TEXT NOT NULL,
32927
+ canonical_text TEXT NOT NULL,
32928
+ entry_hash TEXT NOT NULL,
32929
+ status TEXT NOT NULL CHECK(status IN ('active','removed','superseded')),
32930
+ first_revision INTEGER NOT NULL,
32931
+ last_revision INTEGER NOT NULL,
32932
+ created_at TEXT NOT NULL,
32933
+ updated_at TEXT NOT NULL
32934
+ );
32935
+ CREATE INDEX IF NOT EXISTS idx_memory_head_entries_agent
32936
+ ON memory_head_entries(agent_id, entry_id, last_revision DESC);
32937
+ CREATE TABLE IF NOT EXISTS memory_head_revision_entries (
32938
+ agent_id TEXT NOT NULL,
32939
+ revision INTEGER NOT NULL,
32940
+ entry_id TEXT NOT NULL,
32941
+ ordinal INTEGER NOT NULL,
32942
+ operation TEXT NOT NULL CHECK(operation IN ('add','update','remove','retain')),
32943
+ provenance_json TEXT NOT NULL,
32944
+ PRIMARY KEY(agent_id, revision, entry_id),
32945
+ UNIQUE(agent_id, revision, ordinal)
32946
+ );
32947
+ CREATE INDEX IF NOT EXISTS idx_memory_head_revision_entries_entry
32948
+ ON memory_head_revision_entries(agent_id, entry_id, revision DESC);
32949
+ `);
32950
+ const columns = db.prepare("PRAGMA table_info(memory_md_heads)").all();
32951
+ const names = new Set(columns.map((column) => String(column.name)));
32952
+ if (!names.has("revision_id"))
32953
+ db.exec("ALTER TABLE memory_md_heads ADD COLUMN revision_id TEXT");
32954
+ if (!names.has("pass_id"))
32955
+ db.exec("ALTER TABLE memory_md_heads ADD COLUMN pass_id TEXT");
32956
+ if (!names.has("format_version"))
32957
+ db.exec("ALTER TABLE memory_md_heads ADD COLUMN format_version INTEGER NOT NULL DEFAULT 1");
32958
+ }
32959
+ function up1342(db) {
32960
+ db.exec(`
32961
+ CREATE TABLE memory_head_entries_v134 (
32962
+ entry_id TEXT NOT NULL, agent_id TEXT NOT NULL, canonical_text TEXT NOT NULL,
32963
+ entry_hash TEXT NOT NULL, status TEXT NOT NULL CHECK(status IN ('active','removed','superseded')),
32964
+ first_revision INTEGER NOT NULL, last_revision INTEGER NOT NULL,
32965
+ created_at TEXT NOT NULL, updated_at TEXT NOT NULL,
32966
+ PRIMARY KEY(agent_id, entry_id)
32967
+ );
32968
+ INSERT INTO memory_head_entries_v134
32969
+ SELECT entry_id, agent_id, canonical_text, entry_hash, status, first_revision, last_revision, created_at, updated_at
32970
+ FROM memory_head_entries;
32971
+ DROP TABLE memory_head_entries;
32972
+ ALTER TABLE memory_head_entries_v134 RENAME TO memory_head_entries;
32973
+ CREATE INDEX idx_memory_head_entries_agent
32974
+ ON memory_head_entries(agent_id, entry_id, last_revision DESC);
32975
+ `);
32976
+ }
32977
+ function up1352(db) {
32978
+ db.exec(`
32979
+ CREATE TABLE IF NOT EXISTS memory_head_publications (
32980
+ agent_id TEXT NOT NULL,
32981
+ revision INTEGER NOT NULL,
32982
+ revision_id TEXT NOT NULL,
32983
+ status TEXT NOT NULL CHECK(status IN ('pending', 'completed')),
32984
+ created_at TEXT NOT NULL,
32985
+ completed_at TEXT,
32986
+ PRIMARY KEY(agent_id, revision),
32987
+ UNIQUE(agent_id, revision_id)
32988
+ );
32989
+ CREATE INDEX IF NOT EXISTS idx_memory_head_publications_pending
32990
+ ON memory_head_publications(agent_id, status, revision DESC);
32991
+ `);
32992
+ }
32993
+ function up1362(db) {
32994
+ const cols = new Set(db.prepare("PRAGMA table_info(memory_head_revisions)").all().map((r3) => r3.name));
32995
+ for (const [name, type] of [
32996
+ ["entry_id", "TEXT"],
32997
+ ["entry_text", "TEXT"],
32998
+ ["operation", "TEXT"],
32999
+ ["source_refs_json", "TEXT"],
33000
+ ["supporting_quotes_json", "TEXT"]
33001
+ ]) {
33002
+ if (!cols.has(name))
33003
+ db.exec(`ALTER TABLE memory_head_revisions ADD COLUMN ${name} ${type}`);
33004
+ }
33005
+ db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_head_revisions_entry ON memory_head_revisions(agent_id, revision, entry_id)");
33006
+ }
33007
+ function up1372(db) {
33008
+ const cols = new Set(db.prepare("PRAGMA table_info(dreaming_passes)").all().map((r3) => r3.name));
33009
+ for (const [name, type] of [
33010
+ ["head_revision", "INTEGER"],
33011
+ ["head_hash", "TEXT"],
33012
+ ["head_added", "INTEGER NOT NULL DEFAULT 0"],
33013
+ ["head_updated", "INTEGER NOT NULL DEFAULT 0"],
33014
+ ["head_removed", "INTEGER NOT NULL DEFAULT 0"],
33015
+ ["head_deferred", "INTEGER NOT NULL DEFAULT 0"],
33016
+ ["head_no_op", "INTEGER NOT NULL DEFAULT 0"]
33017
+ ])
33018
+ if (!cols.has(name))
33019
+ db.exec(`ALTER TABLE dreaming_passes ADD COLUMN ${name} ${type}`);
33020
+ }
32726
33021
  var MIGRATIONS2 = [
32727
33022
  {
32728
33023
  version: 1,
32729
33024
  name: "baseline",
32730
- up: up133,
33025
+ up: up138,
32731
33026
  artifacts: { tables: ["memories", "conversations", "embeddings"] }
32732
33027
  },
32733
33028
  {
@@ -32805,7 +33100,7 @@ var MIGRATIONS2 = [
32805
33100
  {
32806
33101
  version: 13,
32807
33102
  name: "ingestion-tracking",
32808
- up: up134,
33103
+ up: up139,
32809
33104
  artifacts: {
32810
33105
  columns: [
32811
33106
  { table: "memories", column: "source_path" },
@@ -33777,6 +34072,41 @@ var MIGRATIONS2 = [
33777
34072
  name: "observer-scoped-epistemic-assertions",
33778
34073
  up: up1322,
33779
34074
  artifacts: { tables: ["epistemic_assertions"] }
34075
+ },
34076
+ {
34077
+ version: 133,
34078
+ name: "dreaming-memory-head",
34079
+ up: up1332,
34080
+ artifacts: { tables: ["memory_head_revisions", "memory_head_entries", "memory_head_revision_entries"] }
34081
+ },
34082
+ {
34083
+ version: 134,
34084
+ name: "scope-memory-head-entries",
34085
+ up: up1342,
34086
+ artifacts: { tables: ["memory_head_entries"] }
34087
+ },
34088
+ {
34089
+ version: 135,
34090
+ name: "memory-head-publication",
34091
+ up: up1352,
34092
+ artifacts: { tables: ["memory_head_publications"] }
34093
+ },
34094
+ {
34095
+ version: 136,
34096
+ name: "memory-head-revisions",
34097
+ up: up1362,
34098
+ artifacts: { tables: ["memory_head_revisions"] }
34099
+ },
34100
+ {
34101
+ version: 137,
34102
+ name: "dreaming-head-manifest",
34103
+ up: up1372,
34104
+ artifacts: {
34105
+ columns: [
34106
+ { table: "dreaming_passes", column: "head_revision" },
34107
+ { table: "dreaming_passes", column: "head_hash" }
34108
+ ]
34109
+ }
33780
34110
  }
33781
34111
  ];
33782
34112
  var LATEST_SCHEMA_VERSION2 = MIGRATIONS2[MIGRATIONS2.length - 1]?.version ?? 0;
@@ -33819,16 +34149,42 @@ function classifyError2(error) {
33819
34149
  }
33820
34150
  return { state: "corrupt", message };
33821
34151
  }
34152
+ function tryRequireOverride2() {
34153
+ const override = process.env.SIGNET_KEYRING_NATIVE_MODULE_PATH?.trim();
34154
+ if (!override)
34155
+ return null;
34156
+ const isAbsolute2 = override.startsWith("/") || /^\\\\[^\\]+\\[^\\]+/.test(override) || /^[A-Za-z]:[\\/]/.test(override);
34157
+ if (!isAbsolute2)
34158
+ return null;
34159
+ try {
34160
+ return require22(override);
34161
+ } catch {
34162
+ return null;
34163
+ }
34164
+ }
33822
34165
  async function loadModule2() {
33823
- modulePromise2 ??= Promise.resolve().then(() => __toESM(require_keyring2(), 1)).catch(() => null);
34166
+ modulePromise2 ??= (async () => {
34167
+ const override = process.env.SIGNET_KEYRING_NATIVE_MODULE_PATH?.trim();
34168
+ if (override)
34169
+ return tryRequireOverride2();
34170
+ return await Promise.resolve().then(() => __toESM(require_keyring2(), 1)).catch(() => null);
34171
+ })();
33824
34172
  return modulePromise2;
33825
34173
  }
33826
34174
  function loadModuleSync2() {
33827
34175
  if (syncModule2 !== undefined)
33828
34176
  return syncModule2;
34177
+ if (process.env.SIGNET_KEYRING_NATIVE_MODULE_PATH?.trim()) {
34178
+ syncModule2 = tryRequireOverride2();
34179
+ return syncModule2;
34180
+ }
34181
+ const override = tryRequireOverride2();
34182
+ if (override) {
34183
+ syncModule2 = override;
34184
+ return syncModule2;
34185
+ }
33829
34186
  try {
33830
- const mod = require22("@napi-rs/keyring");
33831
- syncModule2 = mod;
34187
+ syncModule2 = require22("@napi-rs/keyring");
33832
34188
  } catch {
33833
34189
  syncModule2 = null;
33834
34190
  }
@@ -34092,7 +34448,7 @@ function resolveHermesRepoPath() {
34092
34448
  timeout: 3000
34093
34449
  }).trim();
34094
34450
  if (hermesPath) {
34095
- const repoDir = dirname8(realpathSync(hermesPath));
34451
+ const repoDir = dirname8(realpathSync2(hermesPath));
34096
34452
  if (existsSync12(join13(repoDir, "plugins", "memory")))
34097
34453
  return repoDir;
34098
34454
  }
@@ -34138,6 +34494,44 @@ var REQUIRED_TOOL_NAMES = [
34138
34494
  "recall",
34139
34495
  "remember"
34140
34496
  ];
34497
+ function resolveContainedWritePath(targetPath, targetRoot) {
34498
+ let rootPath = targetRoot;
34499
+ while (!existsSync2(rootPath)) {
34500
+ const parent = dirname6(rootPath);
34501
+ if (parent === rootPath)
34502
+ throw new Error(`Hermes target root does not exist: ${targetRoot}`);
34503
+ rootPath = parent;
34504
+ }
34505
+ if (realpathSync3(rootPath) !== rootPath) {
34506
+ throw new Error(`Hermes target root is symlinked and cannot be used for writes: ${targetRoot}`);
34507
+ }
34508
+ rootPath = targetRoot;
34509
+ while (!existsSync2(rootPath)) {
34510
+ const parent = dirname6(rootPath);
34511
+ if (parent === rootPath)
34512
+ throw new Error(`Hermes target root does not exist: ${targetRoot}`);
34513
+ rootPath = parent;
34514
+ }
34515
+ const root = realpathSync3(rootPath);
34516
+ let existing = targetPath;
34517
+ const missing = [];
34518
+ while (!existsSync2(existing)) {
34519
+ const parent = dirname6(existing);
34520
+ if (parent === existing)
34521
+ throw new Error(`Hermes target path does not have an existing ancestor: ${targetPath}`);
34522
+ missing.unshift(existing.slice(parent.length + 1));
34523
+ existing = parent;
34524
+ }
34525
+ const candidate = join4(realpathSync3(existing), ...missing);
34526
+ const rel = relative2(root, candidate);
34527
+ if (rel.startsWith("..") || isAbsolute2(rel)) {
34528
+ throw new Error(`Hermes target path escapes validated root: ${targetPath}`);
34529
+ }
34530
+ return candidate;
34531
+ }
34532
+ function assertContainedTargetPath(targetPath, targetRoot) {
34533
+ resolveContainedWritePath(targetPath, targetRoot);
34534
+ }
34141
34535
  function getRepoPluginTargetDir(hermesRepo) {
34142
34536
  return join4(hermesRepo, "plugins", "memory", "signet");
34143
34537
  }
@@ -34147,28 +34541,31 @@ function getUserPluginTargetDir(hermesHome) {
34147
34541
  function getProviderBackupPath(hermesHome) {
34148
34542
  return join4(hermesHome, PROVIDER_BACKUP_FILE);
34149
34543
  }
34150
- function installPlugin(targetDir, targetKind) {
34544
+ function installPlugin(targetDir, targetKind, targetRoot) {
34545
+ const writeDir = targetRoot ? resolveContainedWritePath(targetDir, targetRoot) : targetDir;
34151
34546
  const sourceDir = getPluginSourceDir();
34152
- mkdirSync(targetDir, { recursive: true });
34547
+ mkdirSync(writeDir, { recursive: true });
34153
34548
  const written = [];
34154
34549
  for (const file of PLUGIN_FILES) {
34155
34550
  const src = join4(sourceDir, file);
34156
- const dst = join4(targetDir, file);
34551
+ const dst = join4(writeDir, file);
34157
34552
  if (existsSync2(src)) {
34158
34553
  writeFileSync2(dst, readFileSync2(src));
34159
34554
  written.push(dst);
34160
34555
  }
34161
34556
  }
34162
- written.push(writeInstallMarker(targetDir, targetKind));
34557
+ written.push(writeInstallMarker(writeDir, targetKind));
34163
34558
  return written;
34164
34559
  }
34165
- function uninstallPlugin(targetDir) {
34166
- const removed = [];
34167
- if (existsSync2(targetDir)) {
34168
- rmSync(targetDir, { recursive: true, force: true });
34169
- removed.push(targetDir);
34560
+ function uninstallPlugin(targetDir, targetRoot) {
34561
+ if (!existsSync2(targetDir))
34562
+ return [];
34563
+ const safeTargetDir = targetRoot ? resolveContainedWritePath(targetDir, targetRoot) : targetDir;
34564
+ if (!readInstallMarker(safeTargetDir)) {
34565
+ throw new Error(`Refusing to uninstall unowned Hermes plugin path: ${targetDir} (missing or invalid ${INSTALL_MARKER_FILE})`);
34170
34566
  }
34171
- return removed;
34567
+ rmSync(safeTargetDir, { recursive: true, force: true });
34568
+ return [targetDir];
34172
34569
  }
34173
34570
  function getConfigCandidates(hermesHome) {
34174
34571
  return [join4(hermesHome, "config.yaml"), join4(hermesHome, "cli-config.yaml")];
@@ -34287,10 +34684,10 @@ function parseDottedProviderLine(line) {
34287
34684
  function setDottedProviderLine(lines, line, value) {
34288
34685
  lines[line] = `memory.provider: ${value}`;
34289
34686
  }
34290
- function writeProviderBackup(hermesHome, configPath, providerKind, previousProvider) {
34687
+ function writeProviderBackup(hermesHome, targetRoot, configPath, providerKind, previousProvider) {
34291
34688
  if (previousProvider === "signet")
34292
34689
  return null;
34293
- const backupPath = getProviderBackupPath(hermesHome);
34690
+ const backupPath = resolveContainedWritePath(getProviderBackupPath(hermesHome), targetRoot);
34294
34691
  if (existsSync2(backupPath))
34295
34692
  return null;
34296
34693
  const backup = {
@@ -34319,8 +34716,8 @@ function readProviderBackup(hermesHome) {
34319
34716
  return null;
34320
34717
  }
34321
34718
  }
34322
- function removeProviderBackup(hermesHome) {
34323
- const backupPath = getProviderBackupPath(hermesHome);
34719
+ function removeProviderBackup(hermesHome, targetRoot) {
34720
+ const backupPath = targetRoot ? resolveContainedWritePath(getProviderBackupPath(hermesHome), targetRoot) : getProviderBackupPath(hermesHome);
34324
34721
  if (!existsSync2(backupPath))
34325
34722
  return null;
34326
34723
  rmSync(backupPath, { force: true });
@@ -34347,8 +34744,8 @@ function isProviderConfigured(hermesHome) {
34347
34744
  }
34348
34745
  return false;
34349
34746
  }
34350
- function configureProvider(hermesHome, warnings) {
34351
- const configPath = resolveConfigPath(hermesHome);
34747
+ function configureProvider(hermesHome, warnings, targetRoot = hermesHome) {
34748
+ const configPath = resolveContainedWritePath(resolveConfigPath(hermesHome), targetRoot);
34352
34749
  let content = "";
34353
34750
  if (existsSync2(configPath)) {
34354
34751
  try {
@@ -34369,13 +34766,13 @@ function configureProvider(hermesHome, warnings) {
34369
34766
  let changed = false;
34370
34767
  const dottedWasSignet = dottedProviderLineIsSignet(lines[dottedProvider] ?? "");
34371
34768
  if (!dottedWasSignet) {
34372
- backupPath = writeProviderBackup(hermesHome, configPath, "dotted", parseDottedProviderLine(lines[dottedProvider] ?? "") ?? "");
34769
+ backupPath = writeProviderBackup(hermesHome, targetRoot, configPath, "dotted", parseDottedProviderLine(lines[dottedProvider] ?? "") ?? "");
34373
34770
  setDottedProviderLine(lines, dottedProvider, "signet");
34374
34771
  changed = true;
34375
34772
  }
34376
34773
  if (block !== null && typeof block === "object" && block.provider !== null && block.provider !== undefined) {
34377
34774
  if (dottedWasSignet) {
34378
- const nestedBackupPath = writeProviderBackup(hermesHome, configPath, "nested", parseProviderLine(lines[block.provider] ?? "") ?? "");
34775
+ const nestedBackupPath = writeProviderBackup(hermesHome, targetRoot, configPath, "nested", parseProviderLine(lines[block.provider] ?? "") ?? "");
34379
34776
  backupPath = nestedBackupPath ?? backupPath;
34380
34777
  }
34381
34778
  lines.splice(block.provider, 1);
@@ -34396,7 +34793,7 @@ function configureProvider(hermesHome, warnings) {
34396
34793
  if (block !== null && typeof block === "object" && block.provider !== null && block.provider !== undefined) {
34397
34794
  if (providerLineIsSignet(lines[block.provider] ?? ""))
34398
34795
  return { configPath: null, backupPath: null };
34399
- backupPath = writeProviderBackup(hermesHome, configPath, "nested", parseProviderLine(lines[block.provider] ?? "") ?? "");
34796
+ backupPath = writeProviderBackup(hermesHome, targetRoot, configPath, "nested", parseProviderLine(lines[block.provider] ?? "") ?? "");
34400
34797
  lines[block.provider] = `${(lines[block.provider] ?? "").match(/^\s*/)?.[0] ?? " "}provider: signet`;
34401
34798
  } else if (block !== null && typeof block === "object") {
34402
34799
  lines.splice(block.start + 1, 0, `${" ".repeat(block.indent)}provider: signet`);
@@ -34411,10 +34808,12 @@ function configureProvider(hermesHome, warnings) {
34411
34808
  `);
34412
34809
  return { configPath, backupPath };
34413
34810
  }
34414
- function restoreOrClearProvider(hermesHome) {
34811
+ function restoreOrClearProvider(hermesHome, targetRoot) {
34812
+ const safeConfigPath = targetRoot ? resolveContainedWritePath(resolveConfigPath(hermesHome), targetRoot) : resolveConfigPath(hermesHome);
34415
34813
  const config = readConfigYaml(hermesHome);
34416
34814
  if (!config)
34417
- return { configPath: null, backupPath: removeProviderBackup(hermesHome) };
34815
+ return { configPath: null, backupPath: removeProviderBackup(hermesHome, targetRoot) };
34816
+ resolveContainedWritePath(config.path, targetRoot ?? hermesHome);
34418
34817
  const lines = config.content.replace(/\r\n/g, `
34419
34818
  `).split(`
34420
34819
  `);
@@ -34439,13 +34838,13 @@ function restoreOrClearProvider(hermesHome) {
34439
34838
  configChanged = true;
34440
34839
  }
34441
34840
  if (configChanged) {
34442
- writeFileSync2(config.path, `${lines.join(`
34841
+ writeFileSync2(safeConfigPath, `${lines.join(`
34443
34842
  `).replace(/\n+$/g, "")}
34444
34843
  `);
34445
34844
  }
34446
34845
  return {
34447
- configPath: configChanged ? config.path : null,
34448
- backupPath: removeProviderBackup(hermesHome)
34846
+ configPath: configChanged ? safeConfigPath : null,
34847
+ backupPath: removeProviderBackup(hermesHome, targetRoot)
34449
34848
  };
34450
34849
  }
34451
34850
  function pluginHasStaticToolSchemas(pluginFile) {
@@ -34608,13 +35007,16 @@ function trustedOriginForDaemonUrl(daemonUrl) {
34608
35007
  return null;
34609
35008
  }
34610
35009
  }
34611
- function configuredAgentReadPolicy(warnings) {
35010
+ function configuredAgentReadPolicy(warnings, strict = false) {
34612
35011
  const raw = sanitizedEnv("SIGNET_AGENT_READ_POLICY") || sanitizedEnv("SIGNET_AGENT_MEMORY_POLICY");
34613
35012
  if (!raw)
34614
35013
  return "shared";
34615
35014
  if (raw === "isolated" || raw === "shared" || raw === "group")
34616
35015
  return raw;
34617
- warnings.push(`Ignoring unsupported SIGNET_AGENT_READ_POLICY '${raw}'. Expected one of: isolated, shared, group.`);
35016
+ const error = `Unsupported SIGNET_AGENT_READ_POLICY '${raw}'. Expected one of: isolated, shared, group.`;
35017
+ if (strict)
35018
+ return null;
35019
+ warnings.push(`Ignoring ${error}`);
34618
35020
  return "shared";
34619
35021
  }
34620
35022
  async function resolveDaemonAgentId(daemonUrl) {
@@ -34638,11 +35040,20 @@ async function resolveDaemonAgentId(daemonUrl) {
34638
35040
  return null;
34639
35041
  }
34640
35042
  }
34641
- async function ensureNamedAgentRegistered(daemonUrl, agentId, warnings) {
34642
- if (!agentId || agentId === "default" || agentId === "hermes-agent")
34643
- return;
35043
+ async function ensureNamedAgentRegistered(daemonUrl, agentIdOrOptions, warnings) {
35044
+ const options = typeof agentIdOrOptions === "string" ? { agentId: agentIdOrOptions } : agentIdOrOptions;
35045
+ const { agentId } = options;
35046
+ const strict = options.strict === true;
35047
+ const fail = (error) => {
35048
+ if (!strict)
35049
+ warnings.push(error);
35050
+ return { ok: false, agentId, error };
35051
+ };
35052
+ if (!agentId || agentId === "default" || agentId === "hermes-agent") {
35053
+ return { ok: true, created: false, agentId };
35054
+ }
34644
35055
  if (process.env.SIGNET_SKIP_AGENT_REGISTER === "1")
34645
- return;
35056
+ return { ok: true, created: false, agentId };
34646
35057
  const baseUrl = trimTrailingSlashes(daemonUrl);
34647
35058
  const token = sanitizedAuthTokenEnv();
34648
35059
  const headers = {};
@@ -34655,16 +35066,24 @@ async function ensureNamedAgentRegistered(daemonUrl, agentId, warnings) {
34655
35066
  signal: AbortSignal.timeout(1000)
34656
35067
  });
34657
35068
  if (getResp.ok)
34658
- return;
35069
+ return { ok: true, created: false, agentId };
34659
35070
  if (getResp.status !== 404) {
34660
35071
  const body = await getResp.text();
34661
- warnings.push(`Could not check Signet agent '${agentId}' before registration: HTTP ${getResp.status} ${body.slice(0, 200)}`);
34662
- return;
35072
+ return fail(`Could not check Signet agent '${agentId}' before registration: HTTP ${getResp.status} ${body.slice(0, 200)}`);
34663
35073
  }
34664
- } catch {}
34665
- const readPolicy = configuredAgentReadPolicy(warnings);
34666
- const policyGroup = readPolicy === "group" ? sanitizedEnv("SIGNET_AGENT_POLICY_GROUP") || null : null;
35074
+ } catch (e) {
35075
+ if (strict) {
35076
+ const msg = e instanceof Error ? e.message : String(e);
35077
+ return fail(`Could not check Signet agent '${agentId}' because the daemon was unreachable. (${msg})`);
35078
+ }
35079
+ }
35080
+ const readPolicy = options.readPolicy ?? configuredAgentReadPolicy(warnings, strict);
35081
+ if (readPolicy === null)
35082
+ return fail(`Could not register Signet agent '${agentId}' because its read policy is invalid.`);
35083
+ const policyGroup = options.policyGroup !== undefined ? options.policyGroup : readPolicy === "group" ? sanitizedEnv("SIGNET_AGENT_POLICY_GROUP") || null : null;
34667
35084
  if (readPolicy === "group" && !policyGroup) {
35085
+ if (strict)
35086
+ return fail(`Agent '${agentId}' requested group policy but no policy group was provided.`);
34668
35087
  warnings.push(`SIGNET_AGENT_READ_POLICY=group requires SIGNET_AGENT_POLICY_GROUP. Registering '${agentId}' with isolated memory instead.`);
34669
35088
  }
34670
35089
  const effectiveReadPolicy = readPolicy === "group" && !policyGroup ? "isolated" : readPolicy;
@@ -34682,21 +35101,41 @@ async function ensureNamedAgentRegistered(daemonUrl, agentId, warnings) {
34682
35101
  });
34683
35102
  if (!resp.ok) {
34684
35103
  const body = await resp.text();
34685
- warnings.push(`Could not register Signet agent '${agentId}' with ${effectiveReadPolicy} memory policy: ${body.slice(0, 200)}. ${policyHint}`);
35104
+ return fail(`Could not register Signet agent '${agentId}' with ${effectiveReadPolicy} memory policy: ${body.slice(0, 200)}. ${policyHint}`);
34686
35105
  }
35106
+ return { ok: true, created: true, agentId };
34687
35107
  } catch (e) {
34688
35108
  const msg = e instanceof Error ? e.message : String(e);
34689
- warnings.push(`Could not register Signet agent '${agentId}' because the daemon was unreachable. ` + `${policyHint} (${msg})`);
35109
+ return fail(`Could not register Signet agent '${agentId}' because the daemon was unreachable. ${policyHint} (${msg})`);
34690
35110
  }
34691
35111
  }
34692
35112
 
34693
35113
  class HermesAgentConnector extends BaseConnector {
34694
35114
  name = "Hermes Agent";
34695
35115
  harnessId = "hermes-agent";
35116
+ target;
35117
+ registration;
35118
+ constructor(options) {
35119
+ super();
35120
+ if (options && "home" in options) {
35121
+ this.target = options;
35122
+ this.registration = { agentId: "", strict: options.kind === "profile" };
35123
+ } else {
35124
+ this.target = options?.target;
35125
+ this.registration = options ? {
35126
+ agentId: options.agentId ?? "",
35127
+ readPolicy: options.readPolicy,
35128
+ policyGroup: options.policyGroup,
35129
+ strict: options.target?.kind === "profile"
35130
+ } : undefined;
35131
+ }
35132
+ }
34696
35133
  getHermesHome() {
34697
- return resolveHermesHomePath();
35134
+ return this.target?.home ?? resolveHermesHomePath();
34698
35135
  }
34699
35136
  getHermesRepo() {
35137
+ if (this.target?.kind === "profile")
35138
+ return null;
34700
35139
  return resolveHermesRepoPath();
34701
35140
  }
34702
35141
  getConfigPath() {
@@ -34707,16 +35146,19 @@ class HermesAgentConnector extends BaseConnector {
34707
35146
  const configsPatched = [];
34708
35147
  const warnings = [];
34709
35148
  const expandedBasePath = expandHome(basePath || join4(homedir(), ".agents"));
34710
- const strippedAgentsPath = this.stripLegacySignetBlock(expandedBasePath);
35149
+ const hermesHome = this.getHermesHome();
35150
+ const legacyAgentsBasePath = this.target?.kind === "profile" ? hermesHome : expandedBasePath;
35151
+ const strippedAgentsPath = this.stripLegacySignetBlock(legacyAgentsBasePath);
34711
35152
  if (strippedAgentsPath !== null) {
34712
35153
  filesWritten.push(strippedAgentsPath);
34713
35154
  }
34714
- const hermesHome = this.getHermesHome();
35155
+ if (this.target?.kind === "profile")
35156
+ assertContainedTargetPath(hermesHome, this.target.home);
34715
35157
  const hermesRepo = this.getHermesRepo();
34716
35158
  let userPluginInstalled = false;
34717
35159
  let repoPluginInstalled = false;
34718
35160
  try {
34719
- const pluginFiles = installPlugin(getUserPluginTargetDir(hermesHome), "user");
35161
+ const pluginFiles = installPlugin(getUserPluginTargetDir(hermesHome), "user", hermesHome);
34720
35162
  filesWritten.push(...pluginFiles);
34721
35163
  userPluginInstalled = true;
34722
35164
  } catch (e) {
@@ -34725,7 +35167,7 @@ class HermesAgentConnector extends BaseConnector {
34725
35167
  }
34726
35168
  if (hermesRepo) {
34727
35169
  try {
34728
- const pluginFiles = installPlugin(getRepoPluginTargetDir(hermesRepo), "repo");
35170
+ const pluginFiles = installPlugin(getRepoPluginTargetDir(hermesRepo), "repo", hermesRepo);
34729
35171
  filesWritten.push(...pluginFiles);
34730
35172
  repoPluginInstalled = true;
34731
35173
  } catch (e) {
@@ -34743,7 +35185,7 @@ class HermesAgentConnector extends BaseConnector {
34743
35185
  warnings
34744
35186
  };
34745
35187
  }
34746
- const envPath = join4(hermesHome, ".env");
35188
+ const envPath = this.target?.kind === "profile" ? resolveContainedWritePath(join4(hermesHome, ".env"), this.target.home) : join4(hermesHome, ".env");
34747
35189
  let configuredSignetAgentId = "default";
34748
35190
  const configuredDaemonUrl = (process.env.SIGNET_DAEMON_URL?.trim() || "http://127.0.0.1:3850").replace(/[\r\n]+/g, "");
34749
35191
  try {
@@ -34758,7 +35200,7 @@ class HermesAgentConnector extends BaseConnector {
34758
35200
  if (process.env.SIGNET_TRUSTED_DAEMON_ORIGINS) {
34759
35201
  signetVars.SIGNET_TRUSTED_DAEMON_ORIGINS = sanitizedEnv("SIGNET_TRUSTED_DAEMON_ORIGINS");
34760
35202
  }
34761
- let signetAgentId = sanitizedEnv("SIGNET_AGENT_ID");
35203
+ let signetAgentId = this.registration?.agentId || sanitizedEnv("SIGNET_AGENT_ID");
34762
35204
  if (signetAgentId === "hermes-agent") {
34763
35205
  warnings.push("SIGNET_AGENT_ID='hermes-agent' is the harness name, not an agent scope. Re-resolving from the daemon.");
34764
35206
  signetAgentId = "";
@@ -34813,8 +35255,18 @@ ${key}=${value}
34813
35255
  const msg = e instanceof Error ? e.message : String(e);
34814
35256
  warnings.push(`Failed to update .env: ${msg}`);
34815
35257
  }
34816
- await ensureNamedAgentRegistered(configuredDaemonUrl, configuredSignetAgentId, warnings);
34817
- const providerConfig = configureProvider(hermesHome, warnings);
35258
+ const registration = this.registration ? { ...this.registration, agentId: this.registration.agentId || configuredSignetAgentId } : configuredSignetAgentId;
35259
+ const registrationResult = await ensureNamedAgentRegistered(configuredDaemonUrl, registration, warnings);
35260
+ if (!registrationResult.ok && this.target?.kind === "profile") {
35261
+ return {
35262
+ success: false,
35263
+ message: registrationResult.error,
35264
+ filesWritten,
35265
+ configsPatched,
35266
+ warnings
35267
+ };
35268
+ }
35269
+ const providerConfig = configureProvider(hermesHome, warnings, this.target?.kind === "profile" ? this.target.home : hermesHome);
34818
35270
  if (providerConfig.configPath) {
34819
35271
  configsPatched.push(providerConfig.configPath);
34820
35272
  }
@@ -34852,20 +35304,23 @@ ${key}=${value}
34852
35304
  const configsPatched = [];
34853
35305
  const hermesRepo = this.getHermesRepo();
34854
35306
  if (hermesRepo) {
34855
- const removed = uninstallPlugin(getRepoPluginTargetDir(hermesRepo));
35307
+ const removed = uninstallPlugin(getRepoPluginTargetDir(hermesRepo), hermesRepo);
34856
35308
  filesRemoved.push(...removed);
34857
35309
  }
34858
35310
  const hermesHome = this.getHermesHome();
34859
- const userPluginRemoved = uninstallPlugin(getUserPluginTargetDir(hermesHome));
35311
+ const targetRoot = this.target?.kind === "profile" ? this.target.home : undefined;
35312
+ if (targetRoot)
35313
+ assertContainedTargetPath(hermesHome, targetRoot);
35314
+ const userPluginRemoved = uninstallPlugin(getUserPluginTargetDir(hermesHome), targetRoot);
34860
35315
  filesRemoved.push(...userPluginRemoved);
34861
- const providerConfig = restoreOrClearProvider(hermesHome);
35316
+ const providerConfig = restoreOrClearProvider(hermesHome, targetRoot);
34862
35317
  if (providerConfig.configPath) {
34863
35318
  configsPatched.push(providerConfig.configPath);
34864
35319
  }
34865
35320
  if (providerConfig.backupPath) {
34866
35321
  filesRemoved.push(providerConfig.backupPath);
34867
35322
  }
34868
- const envPath = join4(hermesHome, ".env");
35323
+ const envPath = targetRoot ? resolveContainedWritePath(join4(hermesHome, ".env"), targetRoot) : join4(hermesHome, ".env");
34869
35324
  if (existsSync2(envPath)) {
34870
35325
  try {
34871
35326
  let envContent = readFileSync2(envPath, "utf-8");
@@ -34999,6 +35454,7 @@ function createConnector() {
34999
35454
  }
35000
35455
  var src_default = HermesAgentConnector;
35001
35456
  export {
35457
+ ensureNamedAgentRegistered,
35002
35458
  diagnoseHermesIntegration,
35003
35459
  src_default as default,
35004
35460
  createConnector,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signetai/connector-hermes-agent",
3
- "version": "0.206.8",
3
+ "version": "0.208.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.206.8",
29
- "@signetai/core": "0.206.8"
28
+ "@signetai/connector-base": "0.208.0",
29
+ "@signetai/core": "0.208.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.0.0",