@cotal-ai/connector-claude-code 0.8.3 → 0.9.1
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 +8 -0
- package/dist/extension.js.map +1 -1
- package/dist/hook.cjs +6 -4
- package/dist/mcp.cjs +106 -73
- package/package.json +3 -3
package/dist/extension.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAIA,OAAO,EAA2D,KAAK,SAAS,EAAoC,MAAM,gBAAgB,CAAC;AAoB3I;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAIA,OAAO,EAA2D,KAAK,SAAS,EAAoC,MAAM,gBAAgB,CAAC;AAoB3I;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,SAmH7B,CAAC"}
|
package/dist/extension.js
CHANGED
|
@@ -31,6 +31,7 @@ export const claudeConnector = {
|
|
|
31
31
|
transcriptChannel, // the shared `tr-<name>` convention (connector-core), exposed via the contract
|
|
32
32
|
pluginRoot: PLUGIN_ROOT,
|
|
33
33
|
requires: ["claude"],
|
|
34
|
+
supportsResume: true, // renders `--resume <id> --fork-session` (fork-from, never hijack) — see buildLaunch
|
|
34
35
|
buildLaunch(opts) {
|
|
35
36
|
// Operator MCP servers shared with this agent (default none — see the --mcp-config block).
|
|
36
37
|
const shared = opts.mcpServers ?? {};
|
|
@@ -124,6 +125,13 @@ export const claudeConnector = {
|
|
|
124
125
|
// The `--model` flag wins over the agent file, and applies even with no agent file.
|
|
125
126
|
if (model)
|
|
126
127
|
args.push("--model", model);
|
|
128
|
+
// Fork an existing session INTO the mesh (opts.resume, an opaque host-local id). `--fork-session`
|
|
129
|
+
// is pushed in the SAME branch — resume here is fork-only, never a hijack: claude mints a NEW
|
|
130
|
+
// session id from that transcript and leaves the original untouched. The id is a single argv
|
|
131
|
+
// token (no shell), so a hostile-looking id can't inject. The persona `--append-system-prompt`
|
|
132
|
+
// above still applies, so the forked context runs under the current mesh persona.
|
|
133
|
+
if (opts.resume)
|
|
134
|
+
args.push("--resume", opts.resume, "--fork-session");
|
|
127
135
|
return {
|
|
128
136
|
command: "claude",
|
|
129
137
|
args,
|
package/dist/extension.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
|
package/dist/hook.cjs
CHANGED
|
@@ -16332,18 +16332,20 @@ var SYS_LIMITS = { ...BASE_LIMITS, mem_storage: 0, disk_storage: 0 };
|
|
|
16332
16332
|
// ../../packages/core/dist/streams.js
|
|
16333
16333
|
var import_jetstream = __toESM(require_mod4(), 1);
|
|
16334
16334
|
var import_transport_node = __toESM(require_transport_node(), 1);
|
|
16335
|
+
var import_kv2 = __toESM(require_mod6(), 1);
|
|
16336
|
+
|
|
16337
|
+
// ../../packages/core/dist/acls.js
|
|
16335
16338
|
var import_kv = __toESM(require_mod6(), 1);
|
|
16339
|
+
|
|
16340
|
+
// ../../packages/core/dist/streams.js
|
|
16336
16341
|
var PLANE3_DEDUP_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
16337
16342
|
var MEMBERSHIP_MAX_BYTES = 64 * 1024 * 1024;
|
|
16338
16343
|
|
|
16339
16344
|
// ../../packages/core/dist/channels.js
|
|
16340
|
-
var
|
|
16345
|
+
var import_kv3 = __toESM(require_mod6(), 1);
|
|
16341
16346
|
var import_transport_node2 = __toESM(require_transport_node(), 1);
|
|
16342
16347
|
|
|
16343
16348
|
// ../../packages/core/dist/members.js
|
|
16344
|
-
var import_kv3 = __toESM(require_mod6(), 1);
|
|
16345
|
-
|
|
16346
|
-
// ../../packages/core/dist/acls.js
|
|
16347
16349
|
var import_kv4 = __toESM(require_mod6(), 1);
|
|
16348
16350
|
|
|
16349
16351
|
// ../../packages/core/dist/membership-feed.js
|
package/dist/mcp.cjs
CHANGED
|
@@ -47533,7 +47533,56 @@ var SYS_LIMITS = { ...BASE_LIMITS, mem_storage: 0, disk_storage: 0 };
|
|
|
47533
47533
|
// ../../packages/core/dist/streams.js
|
|
47534
47534
|
var import_jetstream = __toESM(require_mod4(), 1);
|
|
47535
47535
|
var import_transport_node = __toESM(require_transport_node(), 1);
|
|
47536
|
+
var import_kv2 = __toESM(require_mod6(), 1);
|
|
47537
|
+
|
|
47538
|
+
// ../../packages/core/dist/acls.js
|
|
47536
47539
|
var import_kv = __toESM(require_mod6(), 1);
|
|
47540
|
+
async function openAclRegistry(nc, space, opts = {}) {
|
|
47541
|
+
const kvm = new import_kv.Kvm(nc);
|
|
47542
|
+
return opts.create ? kvm.create(aclBucket(space)) : kvm.open(aclBucket(space));
|
|
47543
|
+
}
|
|
47544
|
+
async function readAcl(kv, owner) {
|
|
47545
|
+
const e = await kv.get(aclKey(owner));
|
|
47546
|
+
if (!e || e.operation === "DEL" || e.operation === "PURGE")
|
|
47547
|
+
return void 0;
|
|
47548
|
+
try {
|
|
47549
|
+
const record2 = e.json();
|
|
47550
|
+
if (!Array.isArray(record2.allowSubscribe))
|
|
47551
|
+
return void 0;
|
|
47552
|
+
return { record: record2, revision: e.revision };
|
|
47553
|
+
} catch {
|
|
47554
|
+
return void 0;
|
|
47555
|
+
}
|
|
47556
|
+
}
|
|
47557
|
+
async function commitAcl(kv, owner, allowSubscribe) {
|
|
47558
|
+
const key = aclKey(owner);
|
|
47559
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
47560
|
+
const cur = await readAcl(kv, owner);
|
|
47561
|
+
const next = {
|
|
47562
|
+
allowSubscribe: [...allowSubscribe],
|
|
47563
|
+
revision: (cur?.record.revision ?? 0) + 1,
|
|
47564
|
+
updatedAt: Date.now()
|
|
47565
|
+
};
|
|
47566
|
+
const data = new TextEncoder().encode(JSON.stringify(next));
|
|
47567
|
+
if (!cur) {
|
|
47568
|
+
try {
|
|
47569
|
+
await kv.create(key, data);
|
|
47570
|
+
return next;
|
|
47571
|
+
} catch {
|
|
47572
|
+
continue;
|
|
47573
|
+
}
|
|
47574
|
+
}
|
|
47575
|
+
try {
|
|
47576
|
+
await kv.update(key, data, cur.revision);
|
|
47577
|
+
return next;
|
|
47578
|
+
} catch {
|
|
47579
|
+
continue;
|
|
47580
|
+
}
|
|
47581
|
+
}
|
|
47582
|
+
throw new Error(`acl CAS exhausted retries for ${owner}`);
|
|
47583
|
+
}
|
|
47584
|
+
|
|
47585
|
+
// ../../packages/core/dist/streams.js
|
|
47537
47586
|
var MAX_MSGS_PER_SUBJECT = 1e3;
|
|
47538
47587
|
var PLANE3_DEDUP_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
47539
47588
|
var DINBOX_MAX_ACK_PENDING = 1e3;
|
|
@@ -47639,7 +47688,7 @@ function fanoutDurableConfig(space, opts = {}) {
|
|
|
47639
47688
|
}
|
|
47640
47689
|
|
|
47641
47690
|
// ../../packages/core/dist/channels.js
|
|
47642
|
-
var
|
|
47691
|
+
var import_kv3 = __toESM(require_mod6(), 1);
|
|
47643
47692
|
var import_transport_node2 = __toESM(require_transport_node(), 1);
|
|
47644
47693
|
function parseDuration(s) {
|
|
47645
47694
|
const m = /^(\d+)(s|m|h|d)$/.exec(s.trim());
|
|
@@ -47660,7 +47709,7 @@ function effectiveDeliveryClass(cfg, defaults) {
|
|
|
47660
47709
|
return cfg?.deliveryClass ?? defaults?.deliveryClass ?? "durable";
|
|
47661
47710
|
}
|
|
47662
47711
|
async function openChannelRegistry(nc, space, opts = {}) {
|
|
47663
|
-
const kvm = new
|
|
47712
|
+
const kvm = new import_kv3.Kvm(nc);
|
|
47664
47713
|
return opts.create ? kvm.create(channelBucket(space)) : kvm.open(channelBucket(space));
|
|
47665
47714
|
}
|
|
47666
47715
|
async function readChannelConfig(kv, channel) {
|
|
@@ -47681,7 +47730,7 @@ async function decode3(kv, key) {
|
|
|
47681
47730
|
}
|
|
47682
47731
|
|
|
47683
47732
|
// ../../packages/core/dist/members.js
|
|
47684
|
-
var
|
|
47733
|
+
var import_kv4 = __toESM(require_mod6(), 1);
|
|
47685
47734
|
var StaleMembershipWrite = class extends Error {
|
|
47686
47735
|
constructor(channel, owner, attempted, current) {
|
|
47687
47736
|
super(`stale membership write for ${channel}/${owner}: generation ${attempted} < current ${current}`);
|
|
@@ -47689,7 +47738,7 @@ var StaleMembershipWrite = class extends Error {
|
|
|
47689
47738
|
}
|
|
47690
47739
|
};
|
|
47691
47740
|
async function openMembersRegistry(nc, space, opts = {}) {
|
|
47692
|
-
const kvm = new
|
|
47741
|
+
const kvm = new import_kv4.Kvm(nc);
|
|
47693
47742
|
return opts.create ? kvm.create(membersBucket(space)) : kvm.open(membersBucket(space));
|
|
47694
47743
|
}
|
|
47695
47744
|
async function readMember(kv, channel, owner) {
|
|
@@ -47788,53 +47837,6 @@ function durableEligible(rec, seq) {
|
|
|
47788
47837
|
return true;
|
|
47789
47838
|
}
|
|
47790
47839
|
|
|
47791
|
-
// ../../packages/core/dist/acls.js
|
|
47792
|
-
var import_kv4 = __toESM(require_mod6(), 1);
|
|
47793
|
-
async function openAclRegistry(nc, space, opts = {}) {
|
|
47794
|
-
const kvm = new import_kv4.Kvm(nc);
|
|
47795
|
-
return opts.create ? kvm.create(aclBucket(space)) : kvm.open(aclBucket(space));
|
|
47796
|
-
}
|
|
47797
|
-
async function readAcl(kv, owner) {
|
|
47798
|
-
const e = await kv.get(aclKey(owner));
|
|
47799
|
-
if (!e || e.operation === "DEL" || e.operation === "PURGE")
|
|
47800
|
-
return void 0;
|
|
47801
|
-
try {
|
|
47802
|
-
const record2 = e.json();
|
|
47803
|
-
if (!Array.isArray(record2.allowSubscribe))
|
|
47804
|
-
return void 0;
|
|
47805
|
-
return { record: record2, revision: e.revision };
|
|
47806
|
-
} catch {
|
|
47807
|
-
return void 0;
|
|
47808
|
-
}
|
|
47809
|
-
}
|
|
47810
|
-
async function commitAcl(kv, owner, allowSubscribe) {
|
|
47811
|
-
const key = aclKey(owner);
|
|
47812
|
-
for (let attempt = 0; attempt < 5; attempt++) {
|
|
47813
|
-
const cur = await readAcl(kv, owner);
|
|
47814
|
-
const next = {
|
|
47815
|
-
allowSubscribe: [...allowSubscribe],
|
|
47816
|
-
revision: (cur?.record.revision ?? 0) + 1,
|
|
47817
|
-
updatedAt: Date.now()
|
|
47818
|
-
};
|
|
47819
|
-
const data = new TextEncoder().encode(JSON.stringify(next));
|
|
47820
|
-
if (!cur) {
|
|
47821
|
-
try {
|
|
47822
|
-
await kv.create(key, data);
|
|
47823
|
-
return next;
|
|
47824
|
-
} catch {
|
|
47825
|
-
continue;
|
|
47826
|
-
}
|
|
47827
|
-
}
|
|
47828
|
-
try {
|
|
47829
|
-
await kv.update(key, data, cur.revision);
|
|
47830
|
-
return next;
|
|
47831
|
-
} catch {
|
|
47832
|
-
continue;
|
|
47833
|
-
}
|
|
47834
|
-
}
|
|
47835
|
-
throw new Error(`acl CAS exhausted retries for ${owner}`);
|
|
47836
|
-
}
|
|
47837
|
-
|
|
47838
47840
|
// ../../packages/core/dist/membership-feed.js
|
|
47839
47841
|
var import_transport_node3 = __toESM(require_transport_node(), 1);
|
|
47840
47842
|
var import_kv5 = __toESM(require_mod6(), 1);
|
|
@@ -47983,6 +47985,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
47983
47985
|
ttlMs;
|
|
47984
47986
|
doRegister;
|
|
47985
47987
|
doWatch;
|
|
47988
|
+
doWatchChannels;
|
|
47986
47989
|
doConsume;
|
|
47987
47990
|
ackWaitMs;
|
|
47988
47991
|
inactiveThresholdMs;
|
|
@@ -48098,6 +48101,7 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
48098
48101
|
this.ttlMs = opts.ttlMs ?? 6e3;
|
|
48099
48102
|
this.doRegister = opts.registerPresence ?? true;
|
|
48100
48103
|
this.doWatch = opts.watchPresence ?? true;
|
|
48104
|
+
this.doWatchChannels = opts.watchChannels ?? true;
|
|
48101
48105
|
this.doConsume = opts.consume ?? true;
|
|
48102
48106
|
this.channelModes = opts.channelModes && Object.keys(opts.channelModes).length ? opts.channelModes : void 0;
|
|
48103
48107
|
this.ackWaitMs = opts.ackWaitMs ?? 6e4;
|
|
@@ -48137,9 +48141,10 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
48137
48141
|
await this.startPresenceWatch();
|
|
48138
48142
|
this.sweepTimer = setInterval(() => this.sweep(), Math.max(500, Math.floor(this.ttlMs / 3)));
|
|
48139
48143
|
}
|
|
48140
|
-
|
|
48144
|
+
const watchChannels = this.doWatch && this.doWatchChannels;
|
|
48145
|
+
if (watchChannels || this.doConsume) {
|
|
48141
48146
|
this.channelKv = await openChannelRegistry(this.nc, this.space, { create: !this.creds });
|
|
48142
|
-
if (
|
|
48147
|
+
if (watchChannels)
|
|
48143
48148
|
await this.startChannelWatch();
|
|
48144
48149
|
}
|
|
48145
48150
|
if (this.doRegister) {
|
|
@@ -48430,8 +48435,10 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
48430
48435
|
* PEER's reply lane (`ctl.delivery.<victim>.reply.<n>`) and turn the responder into a confused
|
|
48431
48436
|
* deputy — the broker does NOT permission-check the requester's embedded reply subject. With it, a
|
|
48432
48437
|
* reply is published only when `m.reply` is under the AUTHENTICATED request subject
|
|
48433
|
-
* (`${m.subject}.reply.…`), binding the reply to the broker-policed sender token.
|
|
48434
|
-
* tiers
|
|
48438
|
+
* (`${m.subject}.reply.…`), binding the reply to the broker-policed sender token. The manager's three
|
|
48439
|
+
* lifecycle tiers ALSO require it as of closure (i): they reply on bounded `ctl.<tier>.<caller>.reply.…`
|
|
48440
|
+
* (the manager cred holds the wildcard `ctl.<tier>.*.reply.>` pub — exactly the confused-deputy
|
|
48441
|
+
* condition above), so do NOT drop `boundReply` on them. */
|
|
48435
48442
|
serveControl(service, handler, opts = {}) {
|
|
48436
48443
|
if (!this.nc)
|
|
48437
48444
|
throw new Error("endpoint not started");
|
|
@@ -48466,12 +48473,25 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
48466
48473
|
})().catch((e) => this.emit("error", e));
|
|
48467
48474
|
return sub;
|
|
48468
48475
|
}
|
|
48469
|
-
/** Send a control request to a service and await its reply (client side).
|
|
48476
|
+
/** Send a control request to a service and await its reply (client side). Like {@link requestDelivery},
|
|
48477
|
+
* the reply rides a BOUNDED subject UNDER the request subject (`ctl.<service>.<id>.reply.<uuid>`), not
|
|
48478
|
+
* the per-id `_INBOX` — closure (i): this frees the manager's permission set from needing a position-1
|
|
48479
|
+
* inbox wildcard, so its publish surface can be an exact self-scoped allow-list (no message forging).
|
|
48480
|
+
* `noMux` lets us name the reply subject while keeping NoResponders detection. The random suffix is
|
|
48481
|
+
* defense-in-depth (a predictable suffix would let a peer target an in-flight named reply sub). The
|
|
48482
|
+
* reply sits under the sender's OWN request subject, so the responder's `boundReply` guard accepts it.
|
|
48483
|
+
*
|
|
48484
|
+
* CUTOVER (not backward-compatible): an agent cred minted BEFORE closure (i) lacks the
|
|
48485
|
+
* `ctl.<tier>.<id>.reply.>` sub grant — it can still publish the request but cannot subscribe the
|
|
48486
|
+
* reply, so its control calls (spawn/despawn/purge/definePersona, self-stop) hang. The per-user-auth
|
|
48487
|
+
* atomic cutover re-mints every agent; if this change ships ahead of that, agents must be RESPAWNED. */
|
|
48470
48488
|
async requestControl(service, req, timeoutMs = 5e3) {
|
|
48471
48489
|
if (!this.nc)
|
|
48472
48490
|
throw new Error(this.notLiveMsg());
|
|
48491
|
+
const reqSubject = controlServiceSubject(this.space, service, this.card.id);
|
|
48492
|
+
const reply = `${reqSubject}.reply.${(0, import_node_crypto.randomUUID)()}`;
|
|
48473
48493
|
const body = { ...req, from: req.from ?? this.ref() };
|
|
48474
|
-
const m = await this.nc.request(
|
|
48494
|
+
const m = await this.nc.request(reqSubject, JSON.stringify(body), { timeout: timeoutMs, noMux: true, reply });
|
|
48475
48495
|
return m.json();
|
|
48476
48496
|
}
|
|
48477
48497
|
/** Send a durable-membership request to the SERVER-SIDE delivery daemon (`ctl.delivery`) and await its
|
|
@@ -48926,23 +48946,29 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
48926
48946
|
return void 0;
|
|
48927
48947
|
}
|
|
48928
48948
|
}
|
|
48929
|
-
/** Ensure + bind the manager singleton-lease bucket.
|
|
48930
|
-
*
|
|
48931
|
-
*
|
|
48932
|
-
*
|
|
48933
|
-
*
|
|
48934
|
-
*
|
|
48935
|
-
*
|
|
48949
|
+
/** Ensure + bind the manager singleton-lease bucket. Mirrors the presence-bucket pattern (connectAndBind):
|
|
48950
|
+
* AUTH mode OPENs the bucket pre-created at `cotal up` (the scoped `supervisor` cred holds no
|
|
48951
|
+
* STREAM.CREATE — and `open` binds direct=false, so the CAS-conflict `kv.get` inside `acquire` rides
|
|
48952
|
+
* STREAM.MSG.GET, the verb the supervisor grants, never DIRECT.GET). OPEN mode (no creds) create-firsts:
|
|
48953
|
+
* `Kvm.open` binds LAZILY — it does NOT verify the stream exists or throw when it's missing (a fresh
|
|
48954
|
+
* bucket then fails 'stream not found' on the first write), so `create` is the ensure-exists call (it
|
|
48955
|
+
* makes the bucket or, when another endpoint already did, throws and we bind the existing one). Either
|
|
48956
|
+
* way the per-KEY CAS create stays the only single-flight gate, so a lost bucket-create race never reads
|
|
48957
|
+
* as "lease held". */
|
|
48936
48958
|
async managerLeaseRegistry() {
|
|
48937
48959
|
if (!this.nc)
|
|
48938
48960
|
throw new Error("endpoint not started");
|
|
48939
48961
|
if (this.managerLeaseKv)
|
|
48940
48962
|
return this.managerLeaseKv;
|
|
48941
48963
|
const kvm = new import_kv7.Kvm(this.nc);
|
|
48942
|
-
|
|
48943
|
-
this.managerLeaseKv = await kvm.create(managerBucket(this.space), { ttl: MANAGER_LEASE_TTL_MS });
|
|
48944
|
-
} catch {
|
|
48964
|
+
if (this.creds) {
|
|
48945
48965
|
this.managerLeaseKv = await kvm.open(managerBucket(this.space));
|
|
48966
|
+
} else {
|
|
48967
|
+
try {
|
|
48968
|
+
this.managerLeaseKv = await kvm.create(managerBucket(this.space), { ttl: MANAGER_LEASE_TTL_MS });
|
|
48969
|
+
} catch {
|
|
48970
|
+
this.managerLeaseKv = await kvm.open(managerBucket(this.space));
|
|
48971
|
+
}
|
|
48946
48972
|
}
|
|
48947
48973
|
return this.managerLeaseKv;
|
|
48948
48974
|
}
|
|
@@ -50069,6 +50095,8 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
50069
50095
|
this.applyPresence(e.key, p);
|
|
50070
50096
|
}
|
|
50071
50097
|
applyPresence(id, raw) {
|
|
50098
|
+
if (raw.card?.id !== id)
|
|
50099
|
+
return;
|
|
50072
50100
|
const prev = this.roster.get(id);
|
|
50073
50101
|
const stale = Date.now() - raw.ts > this.ttlMs;
|
|
50074
50102
|
const p = stale || raw.status === "offline" ? this.toOffline(raw) : raw;
|
|
@@ -50634,7 +50662,9 @@ var MeshAgent = class extends import_node_events2.EventEmitter {
|
|
|
50634
50662
|
* the harness (default the manager's `cotal`/Claude), `opts.model` overrides the
|
|
50635
50663
|
* persona file's `model:`, and `opts.cwd` roots the new peer at a different folder/repo
|
|
50636
50664
|
* than the manager's workspace — the same knobs the operator's `cotal start` carries, so
|
|
50637
|
-
* the agent and operator spawn doors share one control-op contract.
|
|
50665
|
+
* the agent and operator spawn doors share one control-op contract. (Session `resume` is
|
|
50666
|
+
* intentionally NOT forwarded here: forking a host-local `~/.claude` transcript is an
|
|
50667
|
+
* operator-local intent, kept off the peer-facing spawn door — see #159.) */
|
|
50638
50668
|
async spawn(name, role, opts) {
|
|
50639
50669
|
this.assertConnected();
|
|
50640
50670
|
return this.ep.requestControl(CONTROL_PRIVILEGED, {
|
|
@@ -50896,8 +50926,6 @@ function controlFailure(action, e) {
|
|
|
50896
50926
|
function statusGlyph(s) {
|
|
50897
50927
|
return s === "working" ? "\u25CF" : s === "waiting" ? "\u25D0" : s === "idle" ? "\u25CB" : "\xB7";
|
|
50898
50928
|
}
|
|
50899
|
-
var FACE_TAG_RE = /\[\[\s*face\s*:\s*[\w-]+\s*\]\]\s?/gi;
|
|
50900
|
-
var stripFaceTags = (text) => text.replace(FACE_TAG_RE, "");
|
|
50901
50929
|
var ATTENTION_DESC = {
|
|
50902
50930
|
open: "open \u2014 you receive everything; untagged channel chatter wakes you when idle",
|
|
50903
50931
|
dnd: "dnd \u2014 channel chatter no longer wakes you (it still arrives in your next turn); DMs, anycast, and @mentions still wake you",
|
|
@@ -51042,7 +51070,7 @@ ${all.map(fmtItem).join("\n")}`);
|
|
|
51042
51070
|
},
|
|
51043
51071
|
async run(agent, _config, { text: msg, channel, mentions }) {
|
|
51044
51072
|
try {
|
|
51045
|
-
const m = await agent.send(
|
|
51073
|
+
const m = await agent.send(msg, channel, mentions);
|
|
51046
51074
|
return ok(`Sent to #${m.channel}${m.mentions?.length ? ` (mentioned @${m.mentions.join(", @")})` : ""}.`);
|
|
51047
51075
|
} catch (e) {
|
|
51048
51076
|
return err(`Couldn't send: ${e.message}`);
|
|
@@ -51059,7 +51087,7 @@ ${all.map(fmtItem).join("\n")}`);
|
|
|
51059
51087
|
},
|
|
51060
51088
|
async run(agent, _config, { to, text: msg }) {
|
|
51061
51089
|
try {
|
|
51062
|
-
const { peer } = await agent.dm(to,
|
|
51090
|
+
const { peer } = await agent.dm(to, msg);
|
|
51063
51091
|
return ok(`DM sent to ${peer.card.name}.`);
|
|
51064
51092
|
} catch (e) {
|
|
51065
51093
|
if (e instanceof AmbiguousPeerError) {
|
|
@@ -51081,7 +51109,7 @@ ${who2}`);
|
|
|
51081
51109
|
},
|
|
51082
51110
|
async run(agent, _config, { role, text: msg }) {
|
|
51083
51111
|
try {
|
|
51084
|
-
await agent.anycast(role,
|
|
51112
|
+
await agent.anycast(role, msg);
|
|
51085
51113
|
return ok(`Sent to one @${role}.`);
|
|
51086
51114
|
} catch (e) {
|
|
51087
51115
|
return err(`Couldn't send: ${e.message}`);
|
|
@@ -51223,6 +51251,11 @@ ${info}${caught}`);
|
|
|
51223
51251
|
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)."),
|
|
51224
51252
|
model: external_exports.string().optional().describe("Optional model override (e.g. opus, sonnet) \u2014 wins over the persona file's model:."),
|
|
51225
51253
|
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.")
|
|
51254
|
+
// NOTE: session `resume` is deliberately NOT exposed here. Forking a host-local `~/.claude`
|
|
51255
|
+
// transcript is an operator-local intent; letting a spawn-capable mesh PEER name a host
|
|
51256
|
+
// session id would expand `spawn` into host-transcript disclosure with no broker-enforced
|
|
51257
|
+
// boundary. Resume lives only on the operator CLI (`cotal spawn --resume` / `cotal start
|
|
51258
|
+
// --resume`); a peer-facing, capability-gated resume is deferred (see #159).
|
|
51226
51259
|
},
|
|
51227
51260
|
async run(agent, _config, { name, role, agent: agentType, model, cwd }) {
|
|
51228
51261
|
try {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cotal-ai/connector-claude-code",
|
|
3
3
|
"description": "Cotal connector for Claude Code: an installed plugin that joins a session to the mesh.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.1",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
22
|
-
"@cotal-ai/connector-core": "0.
|
|
22
|
+
"@cotal-ai/connector-core": "0.9.1"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"@cotal-ai/core": ">=0.1.0"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"esbuild": "^0.28.0",
|
|
29
29
|
"tsx": "^4.22.4",
|
|
30
|
-
"@cotal-ai/core": "0.
|
|
30
|
+
"@cotal-ai/core": "0.9.1"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"dist",
|