@cotal-ai/connector-claude-code 0.2.0 → 0.3.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.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "cotal",
3
+ "version": "0.0.0",
4
+ "description": "Join the Cotal mesh — coordinate with other AI agents as lateral peers (presence, messaging, role requests) over NATS.",
5
+ "author": { "name": "Cotal" }
6
+ }
package/.mcp.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "cotal": {
4
+ "command": "node",
5
+ "args": ["${CLAUDE_PLUGIN_ROOT}/dist/mcp.cjs"]
6
+ }
7
+ }
8
+ }
@@ -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;AAS3G;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,SAwC7B,CAAC"}
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
- /** Channel ref for the locally-installed `cotal` plugin (marketplace `cotal-mesh`).
4
- * `--dangerously-load-development-channels <ref>` turns on the plugin's
5
- * `claude/channel` capability so an idle session wakes the instant a peer message
6
- * arrives. The plugin must be *installed* (not `--plugin-dir`) for the channel to
7
- * bind; the connector's identity guard keeps it inert in non-managed sessions. */
8
- const CHANNEL_REF = "plugin:cotal@cotal-mesh";
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
- const args = ["--dangerously-load-development-channels", CHANNEL_REF];
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) {
@@ -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;;;;mFAImF;AACnF,MAAM,WAAW,GAAG,yBAAyB,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAc;IACxC,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,QAAQ;IACd,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,MAAM,IAAI,GAAG,CAAC,yCAAyC,EAAE,WAAW,CAAC,CAAC;QAEtE,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"}
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
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 m = await this.nc.request(controlServiceSubject(this.space, service, this.card.id), JSON.stringify({ ...req, from: req.from ?? this.ref() }), { timeout: timeoutMs });
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",
@@ -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.2.0",
3
+ "version": "0.3.1",
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.2.0"
21
+ "@cotal-ai/connector-core": "0.3.1"
22
22
  },
23
23
  "peerDependencies": {
24
- "@cotal-ai/core": "0.1.3"
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.1.3"
29
+ "@cotal-ai/core": "0.3.1"
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
  }