@cotal-ai/connector-claude-code 0.2.0 → 0.3.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/.claude-plugin/plugin.json +6 -0
- package/.mcp.json +8 -0
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +33 -7
- package/dist/extension.js.map +1 -1
- package/dist/mcp.cjs +32 -1
- package/hooks/hooks.json +82 -0
- package/package.json +9 -6
package/.mcp.json
ADDED
package/dist/extension.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2B,KAAK,SAAS,EAAoC,MAAM,gBAAgB,CAAC;AAmB3G;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,SA8D7B,CAAC"}
|
package/dist/extension.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
2
3
|
import { loadAgentFile, registry } from "@cotal-ai/core";
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
|
|
4
|
+
/** Name the cotal MCP server is registered under via --mcp-config (see buildLaunch). */
|
|
5
|
+
const MCP_SERVER_NAME = "cotal";
|
|
6
|
+
/** Channel ref for `--dangerously-load-development-channels`, which turns on the cotal MCP server's
|
|
7
|
+
* `claude/channel` capability so an idle session wakes the instant a peer message arrives. Because
|
|
8
|
+
* we isolate the session with --strict-mcp-config the plugin's own MCP server is suppressed and
|
|
9
|
+
* cotal is re-supplied via --mcp-config, so the ref is the manually-configured server tagged
|
|
10
|
+
* `server:<name>` (the CLI rejects a plugin ref or a bare name here). The plugin stays installed
|
|
11
|
+
* for its hooks, which do message delivery independent of this wake nudge. */
|
|
12
|
+
const CHANNEL_REF = `server:${MCP_SERVER_NAME}`;
|
|
13
|
+
/** Package root (parent of dist/), which doubles as the installable plugin dir: it carries
|
|
14
|
+
* .claude-plugin/, .mcp.json, hooks/ and the dist/*.cjs bundles. */
|
|
15
|
+
const PLUGIN_ROOT = fileURLToPath(new URL("..", import.meta.url));
|
|
16
|
+
/** The cotal MCP server bundle, supplied explicitly so a spawned session can run with ONLY this
|
|
17
|
+
* MCP server (see buildLaunch's --strict-mcp-config). */
|
|
18
|
+
const MCP_CJS = resolve(PLUGIN_ROOT, "dist", "mcp.cjs");
|
|
9
19
|
/**
|
|
10
20
|
* The Claude Code connector: launches the real `claude` with the Cotal identity in
|
|
11
21
|
* the environment and the mesh channel enabled, so the session joins the mesh and
|
|
@@ -15,6 +25,7 @@ const CHANNEL_REF = "plugin:cotal@cotal-mesh";
|
|
|
15
25
|
export const claudeConnector = {
|
|
16
26
|
kind: "connector",
|
|
17
27
|
name: "claude",
|
|
28
|
+
pluginRoot: PLUGIN_ROOT,
|
|
18
29
|
buildLaunch(opts) {
|
|
19
30
|
const env = {
|
|
20
31
|
COTAL_SPACE: opts.space,
|
|
@@ -34,7 +45,22 @@ export const claudeConnector = {
|
|
|
34
45
|
env.COTAL_CREDS = opts.creds;
|
|
35
46
|
if (opts.servers)
|
|
36
47
|
env.COTAL_SERVERS = opts.servers;
|
|
37
|
-
|
|
48
|
+
// A leading positional is claude's first message, auto-submitted on start —
|
|
49
|
+
// so a driving session can greet the operator the moment it joins.
|
|
50
|
+
const args = opts.prompt
|
|
51
|
+
? [opts.prompt, "--dangerously-load-development-channels", CHANNEL_REF]
|
|
52
|
+
: ["--dangerously-load-development-channels", CHANNEL_REF];
|
|
53
|
+
// Pre-allow fetching the public Cotal docs so a doc-grounded persona (e.g. david)
|
|
54
|
+
// can look something up under `npx` (no repo on disk) without prompting the operator
|
|
55
|
+
// mid-demo. Additive under the default permission mode — leaves other tools as-is.
|
|
56
|
+
args.push("--allowedTools", "WebFetch(domain:github.com),WebFetch(domain:raw.githubusercontent.com)");
|
|
57
|
+
// Isolate the spawned session's MCP to ONLY the cotal server. --strict-mcp-config drops every
|
|
58
|
+
// other MCP source — including the operator's personal ~/.claude.json servers (e.g. a headless
|
|
59
|
+
// Chromium, a DB server) that a meshed teammate never needs and that, multiplied across several
|
|
60
|
+
// spawns on a busy machine, starve memory and kill the session before it registers presence —
|
|
61
|
+
// and --mcp-config re-supplies cotal so its tools + presence still load. The plugin itself stays
|
|
62
|
+
// enabled (its hooks + the dev-channels wake path are unaffected; only MCP config is scoped).
|
|
63
|
+
args.push("--strict-mcp-config", "--mcp-config", JSON.stringify({ mcpServers: { [MCP_SERVER_NAME]: { command: "node", args: [MCP_CJS] } } }));
|
|
38
64
|
// An agent file carries identity (read in-session via COTAL_AGENT_FILE) plus
|
|
39
65
|
// persona + model, which can only be applied to a `claude` session at launch.
|
|
40
66
|
if (opts.configPath) {
|
package/dist/extension.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAoD,MAAM,gBAAgB,CAAC;AAE3G
|
|
1
|
+
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAoD,MAAM,gBAAgB,CAAC;AAE3G,wFAAwF;AACxF,MAAM,eAAe,GAAG,OAAO,CAAC;AAChC;;;;;+EAK+E;AAC/E,MAAM,WAAW,GAAG,UAAU,eAAe,EAAE,CAAC;AAEhD;qEACqE;AACrE,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAClE;0DAC0D;AAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAExD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAc;IACxC,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,WAAW;IACvB,WAAW,CAAC,IAAgB;QAC1B,MAAM,GAAG,GAA2B;YAClC,WAAW,EAAE,IAAI,CAAC,KAAK;YACvB,UAAU,EAAE,IAAI,CAAC,IAAI;YACrB,gFAAgF;YAChF,mFAAmF;YACnF,aAAa,EAAE,GAAG;YAClB,gFAAgF;YAChF,gFAAgF;YAChF,gBAAgB,EAAE,GAAG;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;QAEnD,4EAA4E;QAC5E,mEAAmE;QACnE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM;YACtB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,yCAAyC,EAAE,WAAW,CAAC;YACvE,CAAC,CAAC,CAAC,yCAAyC,EAAE,WAAW,CAAC,CAAC;QAE7D,kFAAkF;QAClF,qFAAqF;QACrF,mFAAmF;QACnF,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,wEAAwE,CAAC,CAAC;QAEtG,8FAA8F;QAC9F,+FAA+F;QAC/F,gGAAgG;QAChG,8FAA8F;QAC9F,iGAAiG;QACjG,8FAA8F;QAC9F,IAAI,CAAC,IAAI,CACP,qBAAqB,EACrB,cAAc,EACd,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAC5F,CAAC;QAEF,6EAA6E;QAC7E,8EAA8E;QAC9E,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACtC,GAAG,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAC5B,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,GAAG,CAAC,OAAO;gBAAE,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAClE,IAAI,GAAG,CAAC,KAAK;gBAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QACjD,CAAC;QAED,OAAO;YACL,OAAO,EAAE,QAAQ;YACjB,IAAI;YACJ,GAAG;YACH,wEAAwE;YACxE,yEAAyE;YACzE,OAAO,EAAE,kBAAkB;SAC5B,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC"}
|
package/dist/mcp.cjs
CHANGED
|
@@ -47816,7 +47816,8 @@ var CotalEndpoint = class extends import_node_events.EventEmitter {
|
|
|
47816
47816
|
async requestControl(service, req, timeoutMs = 5e3) {
|
|
47817
47817
|
if (!this.nc)
|
|
47818
47818
|
throw new Error("endpoint not started");
|
|
47819
|
-
const
|
|
47819
|
+
const body = { ...req, from: req.from ?? this.ref() };
|
|
47820
|
+
const m = await this.nc.request(controlServiceSubject(this.space, service, this.card.id), JSON.stringify(body), { timeout: timeoutMs });
|
|
47820
47821
|
return m.json();
|
|
47821
47822
|
}
|
|
47822
47823
|
// ---- presence ------------------------------------------------------------
|
|
@@ -48848,6 +48849,15 @@ var MeshAgent = class extends import_node_events2.EventEmitter {
|
|
|
48848
48849
|
args: { name, graceful: opts?.graceful ?? true }
|
|
48849
48850
|
});
|
|
48850
48851
|
}
|
|
48852
|
+
/** Ask the manager to purge the space's retained chat backlog (its `purge` op). Cleanup only —
|
|
48853
|
+
* it doesn't touch live agents or the anycast work queue. `includeDms` also clears DM history. */
|
|
48854
|
+
async purgeHistory(opts) {
|
|
48855
|
+
this.assertConnected();
|
|
48856
|
+
return this.ep.requestControl("manager", {
|
|
48857
|
+
op: "purge",
|
|
48858
|
+
args: { includeDms: opts?.includeDms ?? false }
|
|
48859
|
+
});
|
|
48860
|
+
}
|
|
48851
48861
|
/** Define a persona and persist it as config (the manager's `definePersona` op writes
|
|
48852
48862
|
* .cotal/agents/<name>.md). On success, announce it on the channel — the "send it out"
|
|
48853
48863
|
* half — so peers see the new persona; `spawn(name)` then launches an agent wearing it. */
|
|
@@ -49309,6 +49319,27 @@ ${info}${caught}`);
|
|
|
49309
49319
|
}
|
|
49310
49320
|
}
|
|
49311
49321
|
},
|
|
49322
|
+
{
|
|
49323
|
+
name: "cotal_purge",
|
|
49324
|
+
title: "Cotal: clear chat history",
|
|
49325
|
+
description: "Ask the manager to purge this space's retained chat backlog (channel history). Set includeDms to also clear direct-message history. Cleanup only \u2014 it does not affect live agents or the anycast work queue. Irreversible.",
|
|
49326
|
+
schema: {
|
|
49327
|
+
includeDms: external_exports.boolean().optional().describe("Default false: channel history only. true = also purge DM history.")
|
|
49328
|
+
},
|
|
49329
|
+
async run(agent, _config, { includeDms }) {
|
|
49330
|
+
try {
|
|
49331
|
+
const reply = await agent.purgeHistory({ includeDms });
|
|
49332
|
+
if (!reply.ok)
|
|
49333
|
+
return err(`Couldn't purge history: ${reply.error ?? "manager refused"}`);
|
|
49334
|
+
const d = reply.data;
|
|
49335
|
+
const chat = d?.chat ?? 0;
|
|
49336
|
+
const dm = d?.dm;
|
|
49337
|
+
return ok(`Cleared ${chat} channel message${chat === 1 ? "" : "s"}${dm === void 0 ? "" : ` and ${dm} DM${dm === 1 ? "" : "s"}`} from "${_config.space}".`);
|
|
49338
|
+
} catch (e) {
|
|
49339
|
+
return err(`Couldn't purge history: no manager reachable (${e.message}). Is the manager running?`);
|
|
49340
|
+
}
|
|
49341
|
+
}
|
|
49342
|
+
},
|
|
49312
49343
|
{
|
|
49313
49344
|
name: "cotal_persona",
|
|
49314
49345
|
title: "Cotal: define a persona",
|
package/hooks/hooks.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{
|
|
5
|
+
"hooks": [
|
|
6
|
+
{
|
|
7
|
+
"type": "command",
|
|
8
|
+
"command": "node",
|
|
9
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/hook.cjs"]
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"UserPromptSubmit": [
|
|
15
|
+
{
|
|
16
|
+
"hooks": [
|
|
17
|
+
{
|
|
18
|
+
"type": "command",
|
|
19
|
+
"command": "node",
|
|
20
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/hook.cjs"]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"PreToolUse": [
|
|
26
|
+
{
|
|
27
|
+
"hooks": [
|
|
28
|
+
{
|
|
29
|
+
"type": "command",
|
|
30
|
+
"command": "node",
|
|
31
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/hook.cjs"]
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"Notification": [
|
|
37
|
+
{
|
|
38
|
+
"matcher": "permission_prompt|elicitation_dialog",
|
|
39
|
+
"hooks": [
|
|
40
|
+
{
|
|
41
|
+
"type": "command",
|
|
42
|
+
"command": "node",
|
|
43
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/hook.cjs"]
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
"Stop": [
|
|
49
|
+
{
|
|
50
|
+
"hooks": [
|
|
51
|
+
{
|
|
52
|
+
"type": "command",
|
|
53
|
+
"command": "node",
|
|
54
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/hook.cjs"]
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"StopFailure": [
|
|
60
|
+
{
|
|
61
|
+
"hooks": [
|
|
62
|
+
{
|
|
63
|
+
"type": "command",
|
|
64
|
+
"command": "node",
|
|
65
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/hook.cjs"]
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"SessionEnd": [
|
|
71
|
+
{
|
|
72
|
+
"hooks": [
|
|
73
|
+
{
|
|
74
|
+
"type": "command",
|
|
75
|
+
"command": "node",
|
|
76
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/dist/hook.cjs"]
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cotal-ai/connector-claude-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -18,25 +18,28 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
21
|
-
"@cotal-ai/connector-core": "0.
|
|
21
|
+
"@cotal-ai/connector-core": "0.3.0"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@cotal-ai/core": "0.1.
|
|
24
|
+
"@cotal-ai/core": ">=0.1.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"esbuild": "^0.28.0",
|
|
28
28
|
"tsx": "^4.22.4",
|
|
29
|
-
"@cotal-ai/core": "0.
|
|
29
|
+
"@cotal-ai/core": "0.3.0"
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
|
-
"dist"
|
|
32
|
+
"dist",
|
|
33
|
+
".mcp.json",
|
|
34
|
+
"hooks",
|
|
35
|
+
".claude-plugin"
|
|
33
36
|
],
|
|
34
37
|
"publishConfig": {
|
|
35
38
|
"access": "public"
|
|
36
39
|
},
|
|
37
40
|
"scripts": {
|
|
38
41
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
39
|
-
"build": "tsc -p tsconfig.json",
|
|
42
|
+
"build": "tsc -p tsconfig.json && pnpm run bundle",
|
|
40
43
|
"bundle": "esbuild src/mcp.ts src/hook.ts --bundle --platform=node --format=cjs --target=node20 --outdir=dist --out-extension:.js=.cjs"
|
|
41
44
|
}
|
|
42
45
|
}
|