@cotal-ai/connector-hermes 0.6.0 → 0.8.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.
@@ -1 +1 @@
1
- {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,SAAS,EAAoC,MAAM,gBAAgB,CAAC;AAW5F;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,SAsB7B,CAAC"}
1
+ {"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AACA,OAAO,EAA2B,KAAK,SAAS,EAAoC,MAAM,gBAAgB,CAAC;AAW3G;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,SA6B7B,CAAC"}
package/dist/extension.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { fileURLToPath } from "node:url";
2
- import { registry } from "@cotal-ai/core";
3
- import { launchEnv, MODEL_PROVIDER_KEYS } from "@cotal-ai/connector-core";
2
+ import { loadAgentFile, registry } from "@cotal-ai/core";
3
+ import { aclEnv, launchEnv, MODEL_PROVIDER_KEYS } from "@cotal-ai/connector-core";
4
4
  /** The launcher (run via tsx, which loads both) owns the mesh endpoint and supervises the Hermes
5
5
  * gateway as a child — see launch.ts. Resolve `.ts` when this module loads from source (dev) and
6
6
  * `.js` when it loads from the build: the package's `import` resolves to dist/, so a hardcoded
@@ -21,12 +21,14 @@ const LAUNCH_ENTRY = fileURLToPath(new URL(`./launch.${ENTRY_EXT}`, import.meta.
21
21
  export const hermesConnector = {
22
22
  kind: "connector",
23
23
  name: "hermes",
24
+ requires: ["hermes"],
24
25
  buildLaunch(opts) {
25
26
  // OS allow-list + the named model-provider key (Hermes is model-agnostic; any one unlocks a
26
27
  // provider), forwarded BY NAME — never `...process.env` — so the operator's unrelated secrets
27
28
  // don't reach the gateway child (P3).
28
29
  const env = {
29
30
  ...launchEnv({ providerKeys: MODEL_PROVIDER_KEYS }),
31
+ ...aclEnv(opts),
30
32
  COTAL_SPACE: opts.space,
31
33
  COTAL_NAME: opts.name,
32
34
  };
@@ -42,8 +44,13 @@ export const hermesConnector = {
42
44
  // Hermes' SOUL.md (system prompt) at gateway startup, the one place it can be set.
43
45
  if (opts.configPath)
44
46
  env.COTAL_AGENT_FILE = opts.configPath;
45
- if (process.env.HERMES_MODEL)
46
- env.HERMES_MODEL = process.env.HERMES_MODEL;
47
+ // Model precedence, at parity with the Claude/OpenCode connectors: the `--model` flag, else the
48
+ // agent file's `model:`, else an ambient HERMES_MODEL. The launcher reads HERMES_MODEL as the
49
+ // gateway model — resolving here is the one place that honors the file's model for Hermes.
50
+ const fileModel = opts.configPath ? loadAgentFile(opts.configPath).model : undefined;
51
+ const model = opts.model ?? fileModel ?? process.env.HERMES_MODEL;
52
+ if (model)
53
+ env.HERMES_MODEL = model;
47
54
  return { command: TSX, args: [LAUNCH_ENTRY], env };
48
55
  },
49
56
  };
@@ -1 +1 @@
1
- {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAoD,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE1E;;;2DAG2D;AAC3D,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACnE,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAChF,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,YAAY,SAAS,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEtF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAc;IACxC,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,QAAQ;IACd,WAAW,CAAC,IAAgB;QAC1B,4FAA4F;QAC5F,8FAA8F;QAC9F,sCAAsC;QACtC,MAAM,GAAG,GAA2B;YAClC,GAAG,SAAS,CAAC,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC;YACnD,WAAW,EAAE,IAAI,CAAC,KAAK;YACvB,UAAU,EAAE,IAAI,CAAC,IAAI;SACtB,CAAC;QACF,IAAI,IAAI,CAAC,IAAI;YAAE,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC;QAC1C,IAAI,IAAI,CAAC,EAAE;YAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,KAAK;YAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7C,IAAI,IAAI,CAAC,OAAO;YAAE,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC;QACnD,wFAAwF;QACxF,mFAAmF;QACnF,IAAI,IAAI,CAAC,UAAU;YAAE,GAAG,CAAC,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC;QAC5D,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY;YAAE,GAAG,CAAC,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAa,CAAC;QAC3E,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;IACrD,CAAC;CACF,CAAC;AAEF,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC"}
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAoD,MAAM,gBAAgB,CAAC;AAC3G,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAElF;;;2DAG2D;AAC3D,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACnE,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAChF,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,YAAY,SAAS,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEtF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAc;IACxC,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACpB,WAAW,CAAC,IAAgB;QAC1B,4FAA4F;QAC5F,8FAA8F;QAC9F,sCAAsC;QACtC,MAAM,GAAG,GAA2B;YAClC,GAAG,SAAS,CAAC,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC;YACnD,GAAG,MAAM,CAAC,IAAI,CAAC;YACf,WAAW,EAAE,IAAI,CAAC,KAAK;YACvB,UAAU,EAAE,IAAI,CAAC,IAAI;SACtB,CAAC;QACF,IAAI,IAAI,CAAC,IAAI;YAAE,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC;QAC1C,IAAI,IAAI,CAAC,EAAE;YAAE,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,KAAK;YAAE,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7C,IAAI,IAAI,CAAC,OAAO;YAAE,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC;QACnD,wFAAwF;QACxF,mFAAmF;QACnF,IAAI,IAAI,CAAC,UAAU;YAAE,GAAG,CAAC,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC;QAC5D,gGAAgG;QAChG,8FAA8F;QAC9F,2FAA2F;QAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QACrF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAClE,IAAI,KAAK;YAAE,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;IACrD,CAAC;CACF,CAAC;AAEF,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC"}
package/dist/launch.js CHANGED
@@ -19,7 +19,7 @@ import { tmpdir } from "node:os";
19
19
  import { join } from "node:path";
20
20
  import { fileURLToPath } from "node:url";
21
21
  import { loadAgentFile } from "@cotal-ai/core";
22
- import { hasIdentity, configFromEnv, controlSocketPath } from "@cotal-ai/connector-core";
22
+ import { hasIdentity, configFromEnv, controlSocketPath, ORIENTATION_BOOTSTRAP } from "@cotal-ai/connector-core";
23
23
  import { startSidecar } from "./sidecar.js";
24
24
  /** Hermes API line this connector is written + pinned against (see pyproject.toml). A different
25
25
  * major.minor may move the plugin/platform/hook signatures, so we assert and fail loudly. */
@@ -62,9 +62,10 @@ function setupProfile(home, opts) {
62
62
  if (opts.model)
63
63
  lines.push(`model: ${yamlStr(opts.model)}`);
64
64
  writeFileSync(join(home, "config.yaml"), lines.join("\n") + "\n");
65
- // Persona → SOUL.md (Hermes' identity file) — the one place a system prompt can be set.
65
+ // Persona → SOUL.md (Hermes' identity file) — the one place a system prompt can be set. Append the
66
+ // orientation bootstrap so the agent orients first; gated on persona so we don't clobber the default SOUL.
66
67
  if (opts.persona)
67
- writeFileSync(join(home, "SOUL.md"), opts.persona.trim() + "\n");
68
+ writeFileSync(join(home, "SOUL.md"), `${opts.persona.trim()}\n\n${ORIENTATION_BOOTSTRAP}\n`);
68
69
  }
69
70
  /** Assert the installed hermes-agent is on the pinned API line, or throw. No silent degrade: a
70
71
  * different major.minor can shift the plugin/platform/hook contract this connector depends on. */
@@ -1 +1 @@
1
- {"version":3,"file":"launch.js","sourceRoot":"","sources":["../src/launch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"launch.js","sourceRoot":"","sources":["../src/launch.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cotal-ai/connector-hermes",
3
3
  "description": "Cotal connector for the Hermes (Nous Research) agent.",
4
- "version": "0.6.0",
4
+ "version": "0.8.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -23,14 +23,14 @@
23
23
  "dependencies": {
24
24
  "tsx": "^4.22.4",
25
25
  "zod": "^4.4.3",
26
- "@cotal-ai/connector-core": "0.6.0"
26
+ "@cotal-ai/connector-core": "0.8.0"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "@cotal-ai/core": ">=0.1.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "esbuild": "^0.28.0",
33
- "@cotal-ai/core": "0.6.0"
33
+ "@cotal-ai/core": "0.8.0"
34
34
  },
35
35
  "files": [
36
36
  "bin",
@@ -6425,7 +6425,7 @@ var require_authenticator = __commonJS({
6425
6425
  exports2.tokenAuthenticator = tokenAuthenticator;
6426
6426
  exports2.nkeyAuthenticator = nkeyAuthenticator;
6427
6427
  exports2.jwtAuthenticator = jwtAuthenticator;
6428
- exports2.credsAuthenticator = credsAuthenticator6;
6428
+ exports2.credsAuthenticator = credsAuthenticator7;
6429
6429
  var nkeys_1 = require_nkeys2();
6430
6430
  var encoders_1 = require_encoders();
6431
6431
  function multiAuthenticator(authenticators) {
@@ -6475,7 +6475,7 @@ var require_authenticator = __commonJS({
6475
6475
  return { jwt: jwt2, nkey, sig };
6476
6476
  };
6477
6477
  }
6478
- function credsAuthenticator6(creds) {
6478
+ function credsAuthenticator7(creds) {
6479
6479
  const fn = typeof creds !== "function" ? () => creds : creds;
6480
6480
  const parse3 = () => {
6481
6481
  const CREDS = /\s*(?:(?:[-]{3,}[^\n]*[-]{3,}\n)(.+)(?:\n\s*[-]{3,}[^\n]*[-]{3,}\n))/ig;
@@ -13605,11 +13605,11 @@ var require_connect = __commonJS({
13605
13605
  "../../node_modules/.pnpm/@nats-io+transport-node@3.4.0/node_modules/@nats-io/transport-node/lib/connect.js"(exports2) {
13606
13606
  "use strict";
13607
13607
  Object.defineProperty(exports2, "__esModule", { value: true });
13608
- exports2.connect = connect6;
13608
+ exports2.connect = connect7;
13609
13609
  var node_transport_1 = require_node_transport();
13610
13610
  var nats_base_client_1 = require_nats_base_client();
13611
13611
  var nats_base_client_2 = require_nats_base_client();
13612
- function connect6(opts = {}) {
13612
+ function connect7(opts = {}) {
13613
13613
  if ((0, nats_base_client_2.hasWsProtocol)(opts)) {
13614
13614
  return Promise.reject(nats_base_client_2.errors.InvalidArgumentError.format(`servers`, `node client doesn't support websockets, use the 'wsconnect' function instead`));
13615
13615
  }
@@ -13801,7 +13801,7 @@ var require_kv = __commonJS({
13801
13801
  throw new Error(`invalid bucket name: ${name}`);
13802
13802
  }
13803
13803
  }
13804
- var Kvm8 = class {
13804
+ var Kvm9 = class {
13805
13805
  js;
13806
13806
  /**
13807
13807
  * Creates an instance of the Kv that allows you to create and access KV stores.
@@ -13867,7 +13867,7 @@ var require_kv = __commonJS({
13867
13867
  return new internal_2.ListerImpl(subj, filter, this.js);
13868
13868
  }
13869
13869
  };
13870
- exports2.Kvm = Kvm8;
13870
+ exports2.Kvm = Kvm9;
13871
13871
  var Bucket = class _Bucket {
13872
13872
  js;
13873
13873
  jsm;
@@ -14848,6 +14848,10 @@ function aclBucket(space) {
14848
14848
  function aclKey(owner) {
14849
14849
  return token(owner);
14850
14850
  }
14851
+ function membershipBucket(space) {
14852
+ return `cotal_membership_${token(space)}`;
14853
+ }
14854
+ var MEMBERSHIP_FEED_KEY = "=feed";
14851
14855
  function deliveryBucket(space) {
14852
14856
  return `cotal_delivery_${token(space)}`;
14853
14857
  }
@@ -16611,6 +16615,7 @@ var import_kv = __toESM(require_mod6(), 1);
16611
16615
  var MAX_MSGS_PER_SUBJECT = 1e3;
16612
16616
  var PLANE3_DEDUP_WINDOW_MS = 2 * 60 * 60 * 1e3;
16613
16617
  var DINBOX_MAX_ACK_PENDING = 1e3;
16618
+ var MEMBERSHIP_MAX_BYTES = 64 * 1024 * 1024;
16614
16619
  async function createSpaceStreams(jsm, space) {
16615
16620
  const p = spacePrefix(space);
16616
16621
  await jsm.streams.add({
@@ -16907,11 +16912,15 @@ async function commitAcl(kv, owner, allowSubscribe) {
16907
16912
  throw new Error(`acl CAS exhausted retries for ${owner}`);
16908
16913
  }
16909
16914
 
16910
- // ../../packages/core/dist/lease.js
16911
- var import_kv5 = __toESM(require_mod6(), 1);
16915
+ // ../../packages/core/dist/membership-feed.js
16912
16916
  var import_transport_node3 = __toESM(require_transport_node(), 1);
16917
+ var import_kv5 = __toESM(require_mod6(), 1);
16918
+
16919
+ // ../../packages/core/dist/lease.js
16920
+ var import_kv6 = __toESM(require_mod6(), 1);
16921
+ var import_transport_node4 = __toESM(require_transport_node(), 1);
16913
16922
  async function openDeliveryRegistry(nc, space) {
16914
- return new import_kv5.Kvm(nc).open(deliveryBucket(space));
16923
+ return new import_kv6.Kvm(nc).open(deliveryBucket(space));
16915
16924
  }
16916
16925
 
16917
16926
  // ../../packages/core/dist/agent-file.js
@@ -17029,9 +17038,9 @@ function loadAgentFile(path) {
17029
17038
  // ../../packages/core/dist/endpoint.js
17030
17039
  var import_node_events = require("node:events");
17031
17040
  var import_node_crypto = require("node:crypto");
17032
- var import_transport_node4 = __toESM(require_transport_node(), 1);
17041
+ var import_transport_node5 = __toESM(require_transport_node(), 1);
17033
17042
  var import_jetstream2 = __toESM(require_mod4(), 1);
17034
- var import_kv6 = __toESM(require_mod6(), 1);
17043
+ var import_kv7 = __toESM(require_mod6(), 1);
17035
17044
  var DEFAULT_SERVER = "nats://127.0.0.1:4222";
17036
17045
  var READER_MAX_REDELIVERIES = 10;
17037
17046
  var CotalEndpoint = class extends import_node_events.EventEmitter {
@@ -17061,6 +17070,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
17061
17070
  membersKv;
17062
17071
  aclKv;
17063
17072
  deliveryKv;
17073
+ membershipKv;
17064
17074
  /** The live `ctl.delivery` serve subscription (delivery daemon) — re-created on every (re)connect by
17065
17075
  * {@link armDeliveryControl}; tracked so the stale one is dropped on reconnect. */
17066
17076
  deliveryServeSub;
@@ -17179,7 +17189,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
17179
17189
  * idempotent (durables bind by name, JetStream dedups by msgID, KV opens are idempotent). */
17180
17190
  async connectAndBind() {
17181
17191
  this.clearConnectionScoped();
17182
- this.nc = await (0, import_transport_node4.connect)({
17192
+ this.nc = await (0, import_transport_node5.connect)({
17183
17193
  servers: this.servers,
17184
17194
  name: `cotal:${this.card.name}`,
17185
17195
  // Per-identity inbox namespace (the "Private Inbox" pattern). nats.js routes ALL
@@ -17193,7 +17203,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
17193
17203
  this.watchStatus();
17194
17204
  this.js = (0, import_jetstream2.jetstream)(this.nc);
17195
17205
  if (this.doWatch || this.doRegister) {
17196
- const kvm = new import_kv6.Kvm(this.nc);
17206
+ const kvm = new import_kv7.Kvm(this.nc);
17197
17207
  this.kv = this.creds ? await kvm.open(presenceBucket(this.space)) : await kvm.create(presenceBucket(this.space), { ttl: this.ttlMs });
17198
17208
  }
17199
17209
  if (this.doWatch) {
@@ -17735,6 +17745,57 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
17735
17745
  arr.sort(byName);
17736
17746
  return map2;
17737
17747
  }
17748
+ /** Lazily open the derived membership feed KV (admin/observer read; the delivery daemon writes it).
17749
+ * Read-only here — the dashboard consumes it; agents hold no grant and never call this. */
17750
+ async membershipRegistry() {
17751
+ if (!this.nc)
17752
+ throw new Error("endpoint not started");
17753
+ this.membershipKv ??= await new import_kv7.Kvm(this.nc).open(membershipBucket(this.space));
17754
+ return this.membershipKv;
17755
+ }
17756
+ /**
17757
+ * Snapshot the broker-sourced channel-membership feed (admin/observer read): every agent's
17758
+ * `{live, durable}` record plus `asOf` — the feed's freshness heartbeat (epoch ms of the daemon's last
17759
+ * successful poll, from the reserved {@link MEMBERSHIP_FEED_KEY}). `live` patterns are kept as-is
17760
+ * (wildcards preserved); the consumer expands them against the channel registry. `asOf` is undefined
17761
+ * when the feed has never been written (no daemon → the dashboard degrades to traffic-only).
17762
+ */
17763
+ async readMembership() {
17764
+ const kv = await this.membershipRegistry();
17765
+ const members = [];
17766
+ let asOf;
17767
+ for await (const key of await kv.keys()) {
17768
+ const e = await kv.get(key);
17769
+ if (!e || e.operation === "DEL" || e.operation === "PURGE")
17770
+ continue;
17771
+ if (key === MEMBERSHIP_FEED_KEY) {
17772
+ try {
17773
+ asOf = e.json().observedAt;
17774
+ } catch {
17775
+ }
17776
+ continue;
17777
+ }
17778
+ try {
17779
+ const rec = e.json();
17780
+ members.push({ id: key, live: rec.live ?? [], durable: rec.durable ?? [], observedAt: rec.observedAt });
17781
+ } catch {
17782
+ }
17783
+ }
17784
+ return { asOf, members };
17785
+ }
17786
+ /** Watch the membership feed for changes (admin/observer): `onChange` fires on every KV entry,
17787
+ * including the initial replay — the caller debounces + re-reads {@link readMembership}. Returns a
17788
+ * stop handle. Best-effort: a feed the cred can't read (or absent) surfaces as an `error` event and
17789
+ * the dashboard keeps its last snapshot. */
17790
+ async watchMembership(onChange) {
17791
+ const kv = await this.membershipRegistry();
17792
+ const iter = await kv.watch();
17793
+ void (async () => {
17794
+ for await (const _ of iter)
17795
+ onChange();
17796
+ })().catch((err2) => this.emit("error", err2));
17797
+ return { stop: () => iter.stop() };
17798
+ }
17738
17799
  /** Fetch recent messages from a channel's JetStream backlog. */
17739
17800
  async channelHistory(channel, opts) {
17740
17801
  return this.streamHistory(chatStream(this.space), chatSubject(this.space, "*", channel), opts?.limit ?? 100);
@@ -17785,7 +17846,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
17785
17846
  for await (const s of this.nc.status()) {
17786
17847
  if (s.type !== "error")
17787
17848
  continue;
17788
- if (s.error instanceof import_transport_node4.PermissionViolationError && this.confirmingChatSubs.has(s.error.subject))
17849
+ if (s.error instanceof import_transport_node5.PermissionViolationError && this.confirmingChatSubs.has(s.error.subject))
17789
17850
  continue;
17790
17851
  this.emit("error", describeStatusError(s.error));
17791
17852
  }
@@ -18058,7 +18119,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
18058
18119
  filter_subject: subject,
18059
18120
  ack_policy: import_jetstream2.AckPolicy.None,
18060
18121
  mem_storage: true,
18061
- inactive_threshold: (0, import_transport_node4.nanos)(3e4),
18122
+ inactive_threshold: (0, import_transport_node5.nanos)(3e4),
18062
18123
  deliver_policy: import_jetstream2.DeliverPolicy.StartSequence,
18063
18124
  opt_start_seq: fromSeqExcl + 1
18064
18125
  });
@@ -18458,7 +18519,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
18458
18519
  * distinct from a responder that errored. nats.js surfaces it as NoRespondersError, or a RequestError
18459
18520
  * whose `isNoResponders()` is true. */
18460
18521
  isNoResponders(e) {
18461
- return e instanceof import_transport_node4.NoRespondersError || e instanceof import_transport_node4.RequestError && e.isNoResponders();
18522
+ return e instanceof import_transport_node5.NoRespondersError || e instanceof import_transport_node5.RequestError && e.isNoResponders();
18462
18523
  }
18463
18524
  /** Agent-side: this session's CURRENT durable memberships (channel + join generation) from the
18464
18525
  * manager — the agent holds no read on the privileged members KV. `undefined` ⇒ NO control responder
@@ -18801,7 +18862,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
18801
18862
  filter_subject: subject,
18802
18863
  ack_policy: import_jetstream2.AckPolicy.None,
18803
18864
  mem_storage: true,
18804
- inactive_threshold: (0, import_transport_node4.nanos)(3e4),
18865
+ inactive_threshold: (0, import_transport_node5.nanos)(3e4),
18805
18866
  ..."time" in start ? { deliver_policy: import_jetstream2.DeliverPolicy.StartTime, opt_start_time: start.time.toISOString() } : { deliver_policy: import_jetstream2.DeliverPolicy.StartSequence, opt_start_seq: start.seq }
18806
18867
  });
18807
18868
  try {
@@ -18950,7 +19011,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
18950
19011
  }
18951
19012
  }
18952
19013
  async publishPresence() {
18953
- if (!this.kv)
19014
+ if (!this.doRegister || !this.kv)
18954
19015
  return;
18955
19016
  const p = {
18956
19017
  card: this.card,
@@ -19091,28 +19152,28 @@ function authOpts(a) {
19091
19152
  if (a.creds) {
19092
19153
  if (a.token || a.user || a.pass)
19093
19154
  throw new Error("creds are mutually exclusive with token/user/pass auth");
19094
- return { authenticator: (0, import_transport_node4.credsAuthenticator)(new TextEncoder().encode(a.creds)), tls };
19155
+ return { authenticator: (0, import_transport_node5.credsAuthenticator)(new TextEncoder().encode(a.creds)), tls };
19095
19156
  }
19096
19157
  return { token: a.token, user: a.user, pass: a.pass, tls };
19097
19158
  }
19098
19159
  function describeStatusError(err2) {
19099
- if (err2 instanceof import_transport_node4.PermissionViolationError) {
19160
+ if (err2 instanceof import_transport_node5.PermissionViolationError) {
19100
19161
  return new Error(`NATS permission denied: cannot ${err2.operation} "${err2.subject}" \u2014 check this endpoint's ACLs (a denied peer looks "absent" rather than blocked)`, { cause: err2 });
19101
19162
  }
19102
19163
  return err2;
19103
19164
  }
19104
19165
  function isPermissionDenied(e) {
19105
- if (e instanceof import_transport_node4.PermissionViolationError)
19166
+ if (e instanceof import_transport_node5.PermissionViolationError)
19106
19167
  return true;
19107
- if (e?.cause instanceof import_transport_node4.PermissionViolationError)
19168
+ if (e?.cause instanceof import_transport_node5.PermissionViolationError)
19108
19169
  return true;
19109
19170
  return /permissions?\s+violation/i.test(String(e?.message ?? ""));
19110
19171
  }
19111
19172
 
19112
19173
  // ../../packages/core/dist/spaces.js
19113
- var import_transport_node5 = __toESM(require_transport_node(), 1);
19174
+ var import_transport_node6 = __toESM(require_transport_node(), 1);
19114
19175
  var import_jetstream3 = __toESM(require_mod4(), 1);
19115
- var import_kv7 = __toESM(require_mod6(), 1);
19176
+ var import_kv8 = __toESM(require_mod6(), 1);
19116
19177
 
19117
19178
  // ../../packages/core/dist/registry.js
19118
19179
  var Registry = class {
@@ -19195,7 +19256,7 @@ function configFromEnv(env = process.env) {
19195
19256
  subscribe: resolvedSubscribe,
19196
19257
  allowSubscribe: resolvedAllowSub,
19197
19258
  // Post ACL is default-DENY: only what's explicitly declared (env > agent-file). The broker
19198
- // enforces it under auth; in open mode posting is unrestricted regardless (see laneLine).
19259
+ // enforces it under auth; in open mode posting is unrestricted regardless.
19199
19260
  allowPublish: resolvedAllowPub,
19200
19261
  quiet: resolvedQuiet,
19201
19262
  muted: resolvedMuted,
@@ -19573,10 +19634,16 @@ var MeshAgent = class extends import_node_events2.EventEmitter {
19573
19634
  // ---- supervision ---------------------------------------------------------
19574
19635
  /** Ask the manager to spawn a new teammate into this space (its `start` op).
19575
19636
  * How it lands — a detached PTY, a tmux window, a cmux tab — is the manager's
19576
- * runtime; from here it just joins the mesh as a lateral peer. */
19577
- async spawn(name, role) {
19637
+ * runtime; from here it just joins the mesh as a lateral peer. `opts.agent` picks
19638
+ * the harness (default the manager's `cotal`/Claude) and `opts.model` overrides the
19639
+ * persona file's `model:` — the same knobs the operator's `cotal start` carries, so
19640
+ * the agent and operator spawn doors share one control-op contract. */
19641
+ async spawn(name, role, opts) {
19578
19642
  this.assertConnected();
19579
- return this.ep.requestControl(CONTROL_PRIVILEGED, { op: "start", args: { name, role } });
19643
+ return this.ep.requestControl(CONTROL_PRIVILEGED, {
19644
+ op: "start",
19645
+ args: { name, role, agent: opts?.agent, model: opts?.model }
19646
+ });
19580
19647
  }
19581
19648
  /** Ask the manager to tear a teammate down (its `stop` op). Graceful by default —
19582
19649
  * the session is told to exit cleanly (so it leaves the mesh) before the
@@ -34267,6 +34334,66 @@ function date4(params) {
34267
34334
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
34268
34335
  config(en_default());
34269
34336
 
34337
+ // ../connector-core/dist/orientation.js
34338
+ var CORE_TOOLS = /* @__PURE__ */ new Set([
34339
+ "cotal_inbox",
34340
+ "cotal_send",
34341
+ "cotal_dm",
34342
+ "cotal_anycast",
34343
+ "cotal_roster",
34344
+ "cotal_status"
34345
+ ]);
34346
+ function buildOrientation(agent, config2, visibleTools, generatedAt) {
34347
+ const core = [];
34348
+ const more = [];
34349
+ for (const t of visibleTools) {
34350
+ if (t.name === "cotal_orientation")
34351
+ continue;
34352
+ (CORE_TOOLS.has(t.name) ? core : more).push(t);
34353
+ }
34354
+ const peers = agent.roster().filter((p) => p.card.id !== agent.id);
34355
+ const shown = peers.slice(0, 8).map((p) => `${p.card.role ? `${p.card.name}/${p.card.role}` : p.card.name} (${p.status})`);
34356
+ const summary = peers.length ? shown.join(", ") + (peers.length > shown.length ? `, +${peers.length - shown.length} more` : "") : "no other peers present";
34357
+ return {
34358
+ v: 1,
34359
+ generatedAt,
34360
+ identity: { name: config2.name, role: config2.role, space: config2.space, id: agent.id },
34361
+ access: {
34362
+ authMode: !!config2.creds,
34363
+ read: config2.subscribe,
34364
+ readAcl: config2.allowSubscribe,
34365
+ post: config2.allowPublish
34366
+ },
34367
+ capabilities: config2.capabilities ?? [],
34368
+ tools: { core, more },
34369
+ peers: { present: peers.length, summary },
34370
+ status: agent.status,
34371
+ attention: agent.attention,
34372
+ unread: { total: agent.inboxCount() },
34373
+ actions: {
34374
+ read: "cotal_inbox",
34375
+ replyChannel: "cotal_send",
34376
+ replyPrivate: "cotal_dm",
34377
+ askRole: "cotal_anycast"
34378
+ }
34379
+ };
34380
+ }
34381
+ function renderOrientation(o) {
34382
+ const fmt = (cs) => cs.length ? cs.map((c) => `#${c}`).join(", ") : "\u2014";
34383
+ const who = o.identity.role ? `${o.identity.name}/${o.identity.role}` : o.identity.name;
34384
+ const aclDiffers = o.access.readAcl.length !== o.access.read.length || o.access.readAcl.some((c) => !o.access.read.includes(c));
34385
+ const lines = [
34386
+ `You are ${who} in space "${o.identity.space}" (id ${o.identity.id.slice(0, 8)}\u2026).`,
34387
+ "",
34388
+ `Access \u2014 ${o.access.authMode ? "auth mode (grants are broker-enforced)" : "open mode (grants advisory, host-trusted)"}:`,
34389
+ ` \u2022 read: ${fmt(o.access.read)}`
34390
+ ];
34391
+ if (aclDiffers)
34392
+ lines.push(` \u2022 may join (read ACL): ${fmt(o.access.readAcl)}`);
34393
+ lines.push(` \u2022 post: ${o.access.post.length ? fmt(o.access.post) : "\u2014 (read-only; no post channels)"}`, ` \u2022 capabilities: ${o.capabilities.length ? o.capabilities.join(", ") : "none beyond defaults"}`, "", `Tools \u2014 core loop: ${o.tools.core.map((t) => t.name).join(", ") || "\u2014"}`, `Tools \u2014 more: ${o.tools.more.map((t) => t.name).join(", ") || "\u2014"}`, "", `Right now (snapshot @ ${new Date(o.generatedAt).toISOString()}):`, ` \u2022 status: ${o.status} \xB7 attention: ${o.attention}`, ` \u2022 peers present: ${o.peers.present} \u2014 ${o.peers.summary}`, ` \u2022 unread: ${o.unread.total}`, "", `Act \u2192 read: ${o.actions.read} \xB7 reply on a channel: ${o.actions.replyChannel} \xB7 private: ${o.actions.replyPrivate} \xB7 ask a role: ${o.actions.askRole}`);
34394
+ return lines.join("\n");
34395
+ }
34396
+
34270
34397
  // ../connector-core/dist/tool-specs.js
34271
34398
  var ok = (text) => ({ text });
34272
34399
  var err = (text) => ({ text, isError: true });
@@ -34326,6 +34453,21 @@ function resolveFeedbackEmail(explicit) {
34326
34453
  function cotalToolSpecs(config2, source = "connector") {
34327
34454
  const canSpawn = !config2.creds || (config2.capabilities?.includes("spawn") ?? false);
34328
34455
  const specs = [
34456
+ {
34457
+ name: "cotal_orientation",
34458
+ title: "Cotal: orient \u2014 who you are & what you can do",
34459
+ description: "Your orientation card: who you are (name/role/space), the channels you can read and post to, your capabilities, the tools available to you (grouped into a core loop plus the rest), who's present, your status/attention, and how many messages are unread. Call this first to get your bearings; it's read-only and safe to re-check anytime.",
34460
+ run(agent) {
34461
+ const visible = cotalToolSpecs(config2, source).map((s) => ({
34462
+ name: s.name,
34463
+ title: s.title
34464
+ }));
34465
+ const card = renderOrientation(buildOrientation(agent, config2, visible, Date.now()));
34466
+ return ok(agent.connected ? card : `(not connected to the mesh yet \u2014 the live context below is empty)
34467
+
34468
+ ${card}`);
34469
+ }
34470
+ },
34329
34471
  {
34330
34472
  name: "cotal_roster",
34331
34473
  title: "Cotal: who's present",
@@ -34573,12 +34715,14 @@ ${info}${caught}`);
34573
34715
  title: "Cotal: spawn a new teammate",
34574
34716
  description: "Ask the manager to start a new peer endpoint in your space. It joins the mesh as a lateral peer (and, when the manager runs the cmux runtime, appears in its own tab). Use when the team needs another agent.",
34575
34717
  schema: {
34576
- name: external_exports.string().describe("Name for the new peer; auto-numbered (e.g. reviewer-2) if taken."),
34577
- role: external_exports.string().optional().describe("Optional role for the new peer (e.g. worker, reviewer).")
34718
+ name: external_exports.string().describe("Which persona to spawn \u2014 the persona FILENAME in .cotal/agents (e.g. `review-critic`), without the .md. The new peer joins under the persona's own `name:` (auto-numbered, e.g. socrates-2, if that's taken). Fails if no such persona file exists \u2014 spawn an existing persona, don't invent a name."),
34719
+ role: external_exports.string().optional().describe("Optional role for the new peer (e.g. worker, reviewer); overrides the persona file's role."),
34720
+ agent: external_exports.string().optional().describe("Optional harness the new peer runs on \u2014 the agent/connector type (claude, opencode, hermes), NOT the persona to spawn (that's `name`). Defaults to the manager's default (Claude)."),
34721
+ model: external_exports.string().optional().describe("Optional model override (e.g. opus, sonnet) \u2014 wins over the persona file's model:.")
34578
34722
  },
34579
- async run(agent, _config, { name, role }) {
34723
+ async run(agent, _config, { name, role, agent: agentType, model }) {
34580
34724
  try {
34581
- const reply = await agent.spawn(name, role);
34725
+ const reply = await agent.spawn(name, role, { agent: agentType, model });
34582
34726
  if (!reply.ok)
34583
34727
  return err(`Couldn't spawn ${name}: ${reply.error ?? "manager refused"}`);
34584
34728
  const d = reply.data;