@cotal-ai/connector-hermes 0.8.2 → 0.9.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
CHANGED
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,SAuC7B,CAAC"}
|
package/dist/extension.js
CHANGED
|
@@ -28,6 +28,11 @@ export const hermesConnector = {
|
|
|
28
28
|
// the manager can't drive (no Windows named-pipe bridge, no cooperative shutdown). No fallback.
|
|
29
29
|
if (process.platform === "win32")
|
|
30
30
|
throw new Error("the Hermes connector is Unix-only (AF_UNIX bridge + Python sidecar) — not supported on Windows");
|
|
31
|
+
// Resuming an existing session isn't supported by Hermes (no fork-from-transcript primitive in
|
|
32
|
+
// the gateway launcher). Throw rather than spawn fresh silently — this connector otherwise
|
|
33
|
+
// ignores opts it doesn't render, so without this guard `resume` would be dropped without a word.
|
|
34
|
+
if (opts.resume)
|
|
35
|
+
throw new Error("the Hermes connector does not support resuming an existing session (resume)");
|
|
31
36
|
// OS allow-list + the named model-provider key (Hermes is model-agnostic; any one unlocks a
|
|
32
37
|
// provider), forwarded BY NAME — never `...process.env` — so the operator's unrelated secrets
|
|
33
38
|
// don't reach the gateway child (P3).
|
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,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,8FAA8F;QAC9F,gGAAgG;QAChG,gGAAgG;QAChG,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC9B,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;QACpH,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"}
|
|
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,8FAA8F;QAC9F,gGAAgG;QAChG,gGAAgG;QAChG,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC9B,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;QACpH,+FAA+F;QAC/F,2FAA2F;QAC3F,kGAAkG;QAClG,IAAI,IAAI,CAAC,MAAM;YACb,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;QACjG,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/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.9.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.9.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.9.0"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
36
|
"bin",
|
|
@@ -17067,6 +17067,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
17067
17067
|
ttlMs;
|
|
17068
17068
|
doRegister;
|
|
17069
17069
|
doWatch;
|
|
17070
|
+
doWatchChannels;
|
|
17070
17071
|
doConsume;
|
|
17071
17072
|
ackWaitMs;
|
|
17072
17073
|
inactiveThresholdMs;
|
|
@@ -17182,6 +17183,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
17182
17183
|
this.ttlMs = opts.ttlMs ?? 6e3;
|
|
17183
17184
|
this.doRegister = opts.registerPresence ?? true;
|
|
17184
17185
|
this.doWatch = opts.watchPresence ?? true;
|
|
17186
|
+
this.doWatchChannels = opts.watchChannels ?? true;
|
|
17185
17187
|
this.doConsume = opts.consume ?? true;
|
|
17186
17188
|
this.channelModes = opts.channelModes && Object.keys(opts.channelModes).length ? opts.channelModes : void 0;
|
|
17187
17189
|
this.ackWaitMs = opts.ackWaitMs ?? 6e4;
|
|
@@ -17221,9 +17223,10 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
17221
17223
|
await this.startPresenceWatch();
|
|
17222
17224
|
this.sweepTimer = setInterval(() => this.sweep(), Math.max(500, Math.floor(this.ttlMs / 3)));
|
|
17223
17225
|
}
|
|
17224
|
-
|
|
17226
|
+
const watchChannels = this.doWatch && this.doWatchChannels;
|
|
17227
|
+
if (watchChannels || this.doConsume) {
|
|
17225
17228
|
this.channelKv = await openChannelRegistry(this.nc, this.space, { create: !this.creds });
|
|
17226
|
-
if (
|
|
17229
|
+
if (watchChannels)
|
|
17227
17230
|
await this.startChannelWatch();
|
|
17228
17231
|
}
|
|
17229
17232
|
if (this.doRegister) {
|
|
@@ -17514,8 +17517,10 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
17514
17517
|
* PEER's reply lane (`ctl.delivery.<victim>.reply.<n>`) and turn the responder into a confused
|
|
17515
17518
|
* deputy — the broker does NOT permission-check the requester's embedded reply subject. With it, a
|
|
17516
17519
|
* reply is published only when `m.reply` is under the AUTHENTICATED request subject
|
|
17517
|
-
* (`${m.subject}.reply.…`), binding the reply to the broker-policed sender token.
|
|
17518
|
-
* tiers
|
|
17520
|
+
* (`${m.subject}.reply.…`), binding the reply to the broker-policed sender token. The manager's three
|
|
17521
|
+
* lifecycle tiers ALSO require it as of closure (i): they reply on bounded `ctl.<tier>.<caller>.reply.…`
|
|
17522
|
+
* (the manager cred holds the wildcard `ctl.<tier>.*.reply.>` pub — exactly the confused-deputy
|
|
17523
|
+
* condition above), so do NOT drop `boundReply` on them. */
|
|
17519
17524
|
serveControl(service, handler, opts = {}) {
|
|
17520
17525
|
if (!this.nc)
|
|
17521
17526
|
throw new Error("endpoint not started");
|
|
@@ -17550,12 +17555,25 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
17550
17555
|
})().catch((e) => this.emit("error", e));
|
|
17551
17556
|
return sub;
|
|
17552
17557
|
}
|
|
17553
|
-
/** Send a control request to a service and await its reply (client side).
|
|
17558
|
+
/** Send a control request to a service and await its reply (client side). Like {@link requestDelivery},
|
|
17559
|
+
* the reply rides a BOUNDED subject UNDER the request subject (`ctl.<service>.<id>.reply.<uuid>`), not
|
|
17560
|
+
* the per-id `_INBOX` — closure (i): this frees the manager's permission set from needing a position-1
|
|
17561
|
+
* inbox wildcard, so its publish surface can be an exact self-scoped allow-list (no message forging).
|
|
17562
|
+
* `noMux` lets us name the reply subject while keeping NoResponders detection. The random suffix is
|
|
17563
|
+
* defense-in-depth (a predictable suffix would let a peer target an in-flight named reply sub). The
|
|
17564
|
+
* reply sits under the sender's OWN request subject, so the responder's `boundReply` guard accepts it.
|
|
17565
|
+
*
|
|
17566
|
+
* CUTOVER (not backward-compatible): an agent cred minted BEFORE closure (i) lacks the
|
|
17567
|
+
* `ctl.<tier>.<id>.reply.>` sub grant — it can still publish the request but cannot subscribe the
|
|
17568
|
+
* reply, so its control calls (spawn/despawn/purge/definePersona, self-stop) hang. The per-user-auth
|
|
17569
|
+
* atomic cutover re-mints every agent; if this change ships ahead of that, agents must be RESPAWNED. */
|
|
17554
17570
|
async requestControl(service, req, timeoutMs = 5e3) {
|
|
17555
17571
|
if (!this.nc)
|
|
17556
17572
|
throw new Error(this.notLiveMsg());
|
|
17573
|
+
const reqSubject = controlServiceSubject(this.space, service, this.card.id);
|
|
17574
|
+
const reply = `${reqSubject}.reply.${(0, import_node_crypto.randomUUID)()}`;
|
|
17557
17575
|
const body = { ...req, from: req.from ?? this.ref() };
|
|
17558
|
-
const m = await this.nc.request(
|
|
17576
|
+
const m = await this.nc.request(reqSubject, JSON.stringify(body), { timeout: timeoutMs, noMux: true, reply });
|
|
17559
17577
|
return m.json();
|
|
17560
17578
|
}
|
|
17561
17579
|
/** Send a durable-membership request to the SERVER-SIDE delivery daemon (`ctl.delivery`) and await its
|
|
@@ -18010,23 +18028,29 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
18010
18028
|
return void 0;
|
|
18011
18029
|
}
|
|
18012
18030
|
}
|
|
18013
|
-
/** Ensure + bind the manager singleton-lease bucket.
|
|
18014
|
-
*
|
|
18015
|
-
*
|
|
18016
|
-
*
|
|
18017
|
-
*
|
|
18018
|
-
*
|
|
18019
|
-
*
|
|
18031
|
+
/** Ensure + bind the manager singleton-lease bucket. Mirrors the presence-bucket pattern (connectAndBind):
|
|
18032
|
+
* AUTH mode OPENs the bucket pre-created at `cotal up` (the scoped `supervisor` cred holds no
|
|
18033
|
+
* STREAM.CREATE — and `open` binds direct=false, so the CAS-conflict `kv.get` inside `acquire` rides
|
|
18034
|
+
* STREAM.MSG.GET, the verb the supervisor grants, never DIRECT.GET). OPEN mode (no creds) create-firsts:
|
|
18035
|
+
* `Kvm.open` binds LAZILY — it does NOT verify the stream exists or throw when it's missing (a fresh
|
|
18036
|
+
* bucket then fails 'stream not found' on the first write), so `create` is the ensure-exists call (it
|
|
18037
|
+
* makes the bucket or, when another endpoint already did, throws and we bind the existing one). Either
|
|
18038
|
+
* way the per-KEY CAS create stays the only single-flight gate, so a lost bucket-create race never reads
|
|
18039
|
+
* as "lease held". */
|
|
18020
18040
|
async managerLeaseRegistry() {
|
|
18021
18041
|
if (!this.nc)
|
|
18022
18042
|
throw new Error("endpoint not started");
|
|
18023
18043
|
if (this.managerLeaseKv)
|
|
18024
18044
|
return this.managerLeaseKv;
|
|
18025
18045
|
const kvm = new import_kv7.Kvm(this.nc);
|
|
18026
|
-
|
|
18027
|
-
this.managerLeaseKv = await kvm.create(managerBucket(this.space), { ttl: MANAGER_LEASE_TTL_MS });
|
|
18028
|
-
} catch {
|
|
18046
|
+
if (this.creds) {
|
|
18029
18047
|
this.managerLeaseKv = await kvm.open(managerBucket(this.space));
|
|
18048
|
+
} else {
|
|
18049
|
+
try {
|
|
18050
|
+
this.managerLeaseKv = await kvm.create(managerBucket(this.space), { ttl: MANAGER_LEASE_TTL_MS });
|
|
18051
|
+
} catch {
|
|
18052
|
+
this.managerLeaseKv = await kvm.open(managerBucket(this.space));
|
|
18053
|
+
}
|
|
18030
18054
|
}
|
|
18031
18055
|
return this.managerLeaseKv;
|
|
18032
18056
|
}
|
|
@@ -19153,6 +19177,8 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
19153
19177
|
this.applyPresence(e.key, p);
|
|
19154
19178
|
}
|
|
19155
19179
|
applyPresence(id, raw) {
|
|
19180
|
+
if (raw.card?.id !== id)
|
|
19181
|
+
return;
|
|
19156
19182
|
const prev = this.roster.get(id);
|
|
19157
19183
|
const stale = Date.now() - raw.ts > this.ttlMs;
|
|
19158
19184
|
const p = stale || raw.status === "offline" ? this.toOffline(raw) : raw;
|
|
@@ -19323,7 +19349,7 @@ function configFromEnv(env = process.env) {
|
|
|
19323
19349
|
description: def?.description,
|
|
19324
19350
|
tags: def?.tags,
|
|
19325
19351
|
meta: def?.meta,
|
|
19326
|
-
capabilities: def?.capabilities,
|
|
19352
|
+
capabilities: splitList(env.COTAL_CAPABILITIES).length ? splitList(env.COTAL_CAPABILITIES) : def?.capabilities,
|
|
19327
19353
|
model: env.COTAL_MODEL?.trim() || def?.model || void 0,
|
|
19328
19354
|
servers: env.COTAL_SERVERS?.trim() || link?.servers || DEFAULT_SERVER,
|
|
19329
19355
|
subscribe: resolvedSubscribe,
|
|
@@ -19711,7 +19737,9 @@ var MeshAgent = class extends import_node_events2.EventEmitter {
|
|
|
19711
19737
|
* the harness (default the manager's `cotal`/Claude), `opts.model` overrides the
|
|
19712
19738
|
* persona file's `model:`, and `opts.cwd` roots the new peer at a different folder/repo
|
|
19713
19739
|
* than the manager's workspace — the same knobs the operator's `cotal start` carries, so
|
|
19714
|
-
* the agent and operator spawn doors share one control-op contract.
|
|
19740
|
+
* the agent and operator spawn doors share one control-op contract. (Session `resume` is
|
|
19741
|
+
* intentionally NOT forwarded here: forking a host-local `~/.claude` transcript is an
|
|
19742
|
+
* operator-local intent, kept off the peer-facing spawn door — see #159.) */
|
|
19715
19743
|
async spawn(name, role, opts) {
|
|
19716
19744
|
this.assertConnected();
|
|
19717
19745
|
return this.ep.requestControl(CONTROL_PRIVILEGED, {
|
|
@@ -34481,8 +34509,6 @@ function controlFailure(action, e) {
|
|
|
34481
34509
|
function statusGlyph(s) {
|
|
34482
34510
|
return s === "working" ? "\u25CF" : s === "waiting" ? "\u25D0" : s === "idle" ? "\u25CB" : "\xB7";
|
|
34483
34511
|
}
|
|
34484
|
-
var FACE_TAG_RE = /\[\[\s*face\s*:\s*[\w-]+\s*\]\]\s?/gi;
|
|
34485
|
-
var stripFaceTags = (text) => text.replace(FACE_TAG_RE, "");
|
|
34486
34512
|
var ATTENTION_DESC = {
|
|
34487
34513
|
open: "open \u2014 you receive everything; untagged channel chatter wakes you when idle",
|
|
34488
34514
|
dnd: "dnd \u2014 channel chatter no longer wakes you (it still arrives in your next turn); DMs, anycast, and @mentions still wake you",
|
|
@@ -34613,7 +34639,7 @@ ${all.map(fmtItem).join("\n")}`);
|
|
|
34613
34639
|
},
|
|
34614
34640
|
async run(agent, _config, { text: msg, channel, mentions }) {
|
|
34615
34641
|
try {
|
|
34616
|
-
const m = await agent.send(
|
|
34642
|
+
const m = await agent.send(msg, channel, mentions);
|
|
34617
34643
|
return ok(`Sent to #${m.channel}${m.mentions?.length ? ` (mentioned @${m.mentions.join(", @")})` : ""}.`);
|
|
34618
34644
|
} catch (e) {
|
|
34619
34645
|
return err(`Couldn't send: ${e.message}`);
|
|
@@ -34630,7 +34656,7 @@ ${all.map(fmtItem).join("\n")}`);
|
|
|
34630
34656
|
},
|
|
34631
34657
|
async run(agent, _config, { to, text: msg }) {
|
|
34632
34658
|
try {
|
|
34633
|
-
const { peer } = await agent.dm(to,
|
|
34659
|
+
const { peer } = await agent.dm(to, msg);
|
|
34634
34660
|
return ok(`DM sent to ${peer.card.name}.`);
|
|
34635
34661
|
} catch (e) {
|
|
34636
34662
|
if (e instanceof AmbiguousPeerError) {
|
|
@@ -34652,7 +34678,7 @@ ${who}`);
|
|
|
34652
34678
|
},
|
|
34653
34679
|
async run(agent, _config, { role, text: msg }) {
|
|
34654
34680
|
try {
|
|
34655
|
-
await agent.anycast(role,
|
|
34681
|
+
await agent.anycast(role, msg);
|
|
34656
34682
|
return ok(`Sent to one @${role}.`);
|
|
34657
34683
|
} catch (e) {
|
|
34658
34684
|
return err(`Couldn't send: ${e.message}`);
|
|
@@ -34794,6 +34820,11 @@ ${info}${caught}`);
|
|
|
34794
34820
|
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)."),
|
|
34795
34821
|
model: external_exports.string().optional().describe("Optional model override (e.g. opus, sonnet) \u2014 wins over the persona file's model:."),
|
|
34796
34822
|
cwd: external_exports.string().optional().describe("Optional working directory to root the new peer at (e.g. a different repo). A relative path resolves against the manager's workspace; omitted \u2192 it shares the manager's workspace.")
|
|
34823
|
+
// NOTE: session `resume` is deliberately NOT exposed here. Forking a host-local `~/.claude`
|
|
34824
|
+
// transcript is an operator-local intent; letting a spawn-capable mesh PEER name a host
|
|
34825
|
+
// session id would expand `spawn` into host-transcript disclosure with no broker-enforced
|
|
34826
|
+
// boundary. Resume lives only on the operator CLI (`cotal spawn --resume` / `cotal start
|
|
34827
|
+
// --resume`); a peer-facing, capability-gated resume is deferred (see #159).
|
|
34797
34828
|
},
|
|
34798
34829
|
async run(agent, _config, { name, role, agent: agentType, model, cwd }) {
|
|
34799
34830
|
try {
|