@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.
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +11 -4
- package/dist/extension.js.map +1 -1
- package/dist/launch.js +4 -3
- package/dist/launch.js.map +1 -1
- package/package.json +3 -3
- package/plugin/cotal/_sidecar/standalone.cjs +176 -32
package/dist/extension.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
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
|
-
|
|
46
|
-
|
|
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
|
};
|
package/dist/extension.js.map
CHANGED
|
@@ -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;
|
|
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()
|
|
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. */
|
package/dist/launch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../src/launch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;
|
|
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.
|
|
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.
|
|
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.
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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/
|
|
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
|
|
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
|
|
17041
|
+
var import_transport_node5 = __toESM(require_transport_node(), 1);
|
|
17033
17042
|
var import_jetstream2 = __toESM(require_mod4(), 1);
|
|
17034
|
-
var
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
19166
|
+
if (e instanceof import_transport_node5.PermissionViolationError)
|
|
19106
19167
|
return true;
|
|
19107
|
-
if (e?.cause instanceof
|
|
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
|
|
19174
|
+
var import_transport_node6 = __toESM(require_transport_node(), 1);
|
|
19114
19175
|
var import_jetstream3 = __toESM(require_mod4(), 1);
|
|
19115
|
-
var
|
|
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
|
|
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
|
-
|
|
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, {
|
|
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("
|
|
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;
|