@cotal-ai/connector-claude-code 0.11.3 → 0.11.4
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/hook.cjs +88 -37
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +546 -3
- package/dist/mcp.cjs +390 -94
- package/package.json +6 -8
- package/dist/extension.js +0 -164
- package/dist/extension.js.map +0 -1
- package/dist/hook.js +0 -10
- package/dist/hook.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mcp.js +0 -237
- package/dist/mcp.js.map +0 -1
- package/dist/transcript.js +0 -203
- package/dist/transcript.js.map +0 -1
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.11.
|
|
4
|
+
"version": "0.11.4",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -17,17 +17,15 @@
|
|
|
17
17
|
"import": "./dist/index.js"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
22
|
-
"@cotal-ai/connector-core": "0.11.3"
|
|
23
|
-
},
|
|
24
20
|
"peerDependencies": {
|
|
25
21
|
"@cotal-ai/core": ">=0.1.0"
|
|
26
22
|
},
|
|
27
23
|
"devDependencies": {
|
|
24
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
28
25
|
"esbuild": "^0.28.0",
|
|
29
26
|
"tsx": "^4.22.4",
|
|
30
|
-
"@cotal-ai/core": "0.11.
|
|
27
|
+
"@cotal-ai/connector-core": "0.11.4",
|
|
28
|
+
"@cotal-ai/core": "0.11.4"
|
|
31
29
|
},
|
|
32
30
|
"files": [
|
|
33
31
|
"dist",
|
|
@@ -40,7 +38,7 @@
|
|
|
40
38
|
},
|
|
41
39
|
"scripts": {
|
|
42
40
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
43
|
-
"build": "tsc -p tsconfig.json && pnpm run bundle",
|
|
44
|
-
"bundle": "esbuild src/mcp.ts src/hook.ts --bundle --platform=node --format=cjs --target=node20 --outdir=dist --out-extension:.js=.cjs"
|
|
41
|
+
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json --emitDeclarationOnly && pnpm run bundle",
|
|
42
|
+
"bundle": "esbuild src/index.ts --bundle --platform=node --format=esm --target=node20 --outfile=dist/index.js --external:@cotal-ai/core && esbuild src/mcp.ts src/hook.ts --bundle --platform=node --format=cjs --target=node20 --outdir=dist --out-extension:.js=.cjs"
|
|
45
43
|
}
|
|
46
44
|
}
|
package/dist/extension.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { mkdtempSync } from "node:fs";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { join, resolve } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { hardenPrivate, loadAgentFile, registry, writeSecretFile } from "@cotal-ai/core";
|
|
6
|
-
import { aclEnv, connectorLaunchOptions, controlEndpoint, launchEnv, mcpServerEnvKeys, transcriptChannel, userAuthEnv } from "@cotal-ai/connector-core";
|
|
7
|
-
/** Name the cotal MCP server is registered under via --mcp-config (see buildLaunch). */
|
|
8
|
-
const MCP_SERVER_NAME = "cotal";
|
|
9
|
-
/** Channel ref for `--dangerously-load-development-channels`, which turns on the cotal MCP server's
|
|
10
|
-
* `claude/channel` capability so an idle session wakes the instant a peer message arrives. Because
|
|
11
|
-
* we isolate the session with --strict-mcp-config the plugin's own MCP server is suppressed and
|
|
12
|
-
* cotal is re-supplied via --mcp-config, so the ref is the manually-configured server tagged
|
|
13
|
-
* `server:<name>` (the CLI rejects a plugin ref or a bare name here). The plugin stays installed
|
|
14
|
-
* for its hooks, which do message delivery independent of this wake nudge. */
|
|
15
|
-
const CHANNEL_REF = `server:${MCP_SERVER_NAME}`;
|
|
16
|
-
/** Package root (parent of dist/), which doubles as the installable plugin dir: it carries
|
|
17
|
-
* .claude-plugin/, .mcp.json, hooks/ and the dist/*.cjs bundles. */
|
|
18
|
-
const PLUGIN_ROOT = fileURLToPath(new URL("..", import.meta.url));
|
|
19
|
-
/** The cotal MCP server bundle, supplied explicitly so a spawned session can run with ONLY this
|
|
20
|
-
* MCP server (see buildLaunch's --strict-mcp-config). */
|
|
21
|
-
const MCP_CJS = resolve(PLUGIN_ROOT, "dist", "mcp.cjs");
|
|
22
|
-
/**
|
|
23
|
-
* The Claude Code connector: launches the real `claude` with the Cotal identity in
|
|
24
|
-
* the environment and the mesh channel enabled, so the session joins the mesh and
|
|
25
|
-
* wakes on incoming peer messages. Self-registers on import; the manager resolves it
|
|
26
|
-
* by agent type "claude".
|
|
27
|
-
*/
|
|
28
|
-
export const claudeConnector = {
|
|
29
|
-
kind: "connector",
|
|
30
|
-
name: "claude",
|
|
31
|
-
transcriptChannel, // the shared `tr-<name>` convention (connector-core), exposed via the contract
|
|
32
|
-
pluginRoot: PLUGIN_ROOT,
|
|
33
|
-
requires: ["claude"],
|
|
34
|
-
supportsResume: true, // renders `--resume <id> --fork-session` (fork-from, never hijack) — see buildLaunch
|
|
35
|
-
buildLaunch(opts) {
|
|
36
|
-
if (opts.variant)
|
|
37
|
-
throw new Error("claude connector: model variants are not supported");
|
|
38
|
-
// Operator MCP servers shared with this agent (default none — see the --mcp-config block).
|
|
39
|
-
const shared = opts.mcpServers ?? {};
|
|
40
|
-
// claude auths via macOS Keychain / an OAuth token, not an env key → forward NO provider key.
|
|
41
|
-
// The OS allow-list (PATH/HOME/TERM/…) is the only thing inherited from the manager env, plus
|
|
42
|
-
// — only when a shared server declares them via `${VAR}` — the named secrets it needs (mcpKeys,
|
|
43
|
-
// by name). The operator's unrelated secrets don't reach the child (P3).
|
|
44
|
-
// The session's local control endpoint: the in-process MCP server LISTENS on it (auth), and the
|
|
45
|
-
// lifecycle hooks (child processes of `claude`, which inherit this env) CONNECT to it. Both read
|
|
46
|
-
// path+token from the env — never recomputed from public identity — and the manager keeps the
|
|
47
|
-
// pair (returned as `control` below) to drive a cooperative shutdown on Windows.
|
|
48
|
-
const control = controlEndpoint(opts.space, opts.name);
|
|
49
|
-
const env = {
|
|
50
|
-
...launchEnv({ mcpKeys: mcpServerEnvKeys(shared) }),
|
|
51
|
-
...aclEnv(opts),
|
|
52
|
-
...userAuthEnv(opts),
|
|
53
|
-
COTAL_SPACE: opts.space,
|
|
54
|
-
COTAL_NAME: opts.name,
|
|
55
|
-
// Force the connector to emit channel wake-nudges: Claude doesn't advertise the
|
|
56
|
-
// `claude/channel` capability back over MCP, so auto-detection would see it "off".
|
|
57
|
-
COTAL_CHANNEL: "1",
|
|
58
|
-
COTAL_CONTROL_SOCKET: control.path,
|
|
59
|
-
COTAL_CONTROL_TOKEN: control.token, // env only — never argv/logs/persisted (token hygiene)
|
|
60
|
-
};
|
|
61
|
-
// A session can mirror its own transcript to `tr-<name>` so peers can read what the
|
|
62
|
-
// agent actually did — OFF by default (transcripts are verbose and may carry sensitive
|
|
63
|
-
// content); `--transcript` (opts.transcript === true) opts in. Personal sessions never mirror.
|
|
64
|
-
if (opts.transcript === true)
|
|
65
|
-
env.COTAL_TRANSCRIPT = "1";
|
|
66
|
-
if (opts.role)
|
|
67
|
-
env.COTAL_ROLE = opts.role;
|
|
68
|
-
if (opts.id)
|
|
69
|
-
env.COTAL_ID = opts.id;
|
|
70
|
-
if (opts.creds)
|
|
71
|
-
env.COTAL_CREDS = opts.creds;
|
|
72
|
-
if (opts.servers)
|
|
73
|
-
env.COTAL_SERVERS = opts.servers;
|
|
74
|
-
// A leading positional is claude's first message, auto-submitted on start —
|
|
75
|
-
// so a driving session can greet the operator the moment it joins.
|
|
76
|
-
const args = opts.prompt
|
|
77
|
-
? [opts.prompt, "--dangerously-load-development-channels", CHANNEL_REF]
|
|
78
|
-
: ["--dangerously-load-development-channels", CHANNEL_REF];
|
|
79
|
-
// Pre-allow fetching the public Cotal docs so a doc-grounded persona (e.g. david)
|
|
80
|
-
// can look something up under `npx` (no repo on disk) without prompting the operator
|
|
81
|
-
// mid-demo. Additive under the default permission mode — leaves other tools as-is.
|
|
82
|
-
args.push("--allowedTools", "WebFetch(domain:github.com),WebFetch(domain:raw.githubusercontent.com)");
|
|
83
|
-
// Isolate the spawned session's MCP. --strict-mcp-config drops every ambient MCP source —
|
|
84
|
-
// including the operator's personal ~/.claude.json servers (e.g. a headless Chromium, a DB
|
|
85
|
-
// server) that a meshed teammate never needs and that, multiplied across several spawns on a
|
|
86
|
-
// busy machine, starve memory and kill the session before it registers presence — so the ONLY
|
|
87
|
-
// servers that load are the ones we name in --mcp-config: cotal (always, for its tools +
|
|
88
|
-
// presence) plus any the operator explicitly opted to share (`shared`, from the cotal config).
|
|
89
|
-
// The plugin itself stays enabled (its hooks + the dev-channels wake path are unaffected).
|
|
90
|
-
// cotal is spread LAST so a shared server can never shadow the mesh server by reusing its name.
|
|
91
|
-
const mcpServers = { ...shared, [MCP_SERVER_NAME]: { command: "node", args: [MCP_CJS] } };
|
|
92
|
-
// Default (no shared servers): pass the config inline, unchanged. With shared servers, write it
|
|
93
|
-
// to a file instead and pass the path. Either way the secret stays a `${VAR}` reference (Claude
|
|
94
|
-
// expands it from the child env at launch — see the mcpKeys forwarding above), never the resolved
|
|
95
|
-
// value, so nothing secret reaches disk or argv. We prefer the file when sharing because env
|
|
96
|
-
// expansion is only *documented* for --mcp-config files (inline expansion does work today, but
|
|
97
|
-
// isn't contracted), and a file keeps a potentially multi-server config off the process argv.
|
|
98
|
-
// Verified end-to-end on claude 2.1.183: ${VAR} expands in the --mcp-config file and the value
|
|
99
|
-
// is handed to the shared server. This is host-version behavior — if a future claude stops
|
|
100
|
-
// expanding here, a shared server would receive a literal `${VAR}`; re-check on host upgrades.
|
|
101
|
-
let mcpConfig;
|
|
102
|
-
if (Object.keys(shared).length === 0) {
|
|
103
|
-
mcpConfig = JSON.stringify({ mcpServers });
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
// A private 0700 temp dir (unique per spawn) holds the 0600 config. mkdtemp can't be raced
|
|
107
|
-
// by a pre-created or symlinked path the way a predictable name in the world-writable tmpdir
|
|
108
|
-
// could, and a fresh file guarantees the 0600 mode applies on creation (mode is ignored on an
|
|
109
|
-
// overwrite). Left for the OS to reap: the file must outlive this call (Claude reads it at
|
|
110
|
-
// startup and on /mcp reconnect), and buildLaunch doesn't own the child's lifecycle.
|
|
111
|
-
const dir = mkdtempSync(join(tmpdir(), "cotal-mcp-"));
|
|
112
|
-
hardenPrivate(dir, "dir"); // win32: mkdtemp's 0700 is a no-op — harden the ACL before the config lands
|
|
113
|
-
mcpConfig = join(dir, "mcp.json");
|
|
114
|
-
writeSecretFile(mcpConfig, JSON.stringify({ mcpServers }, null, 2));
|
|
115
|
-
}
|
|
116
|
-
args.push("--strict-mcp-config", "--mcp-config", mcpConfig);
|
|
117
|
-
// An agent file carries identity (read in-session via COTAL_AGENT_FILE) plus
|
|
118
|
-
// persona + model, which can only be applied to a `claude` session at launch.
|
|
119
|
-
let model = opts.model;
|
|
120
|
-
if (opts.configPath) {
|
|
121
|
-
const path = resolve(opts.configPath);
|
|
122
|
-
env.COTAL_AGENT_FILE = path;
|
|
123
|
-
const def = loadAgentFile(path);
|
|
124
|
-
if (def.persona)
|
|
125
|
-
args.push("--append-system-prompt", def.persona);
|
|
126
|
-
model ??= def.model;
|
|
127
|
-
}
|
|
128
|
-
// The `--model` flag wins over the agent file, and applies even with no agent file.
|
|
129
|
-
if (model) {
|
|
130
|
-
args.push("--model", model);
|
|
131
|
-
env.COTAL_MODEL = model;
|
|
132
|
-
}
|
|
133
|
-
// Fork an existing session INTO the mesh (opts.resume, an opaque host-local id). `--fork-session`
|
|
134
|
-
// is pushed in the SAME branch — resume here is fork-only, never a hijack: claude mints a NEW
|
|
135
|
-
// session id from that transcript and leaves the original untouched. The id is a single argv
|
|
136
|
-
// token (no shell), so a hostile-looking id can't inject. The persona `--append-system-prompt`
|
|
137
|
-
// above still applies, so the forked context runs under the current mesh persona.
|
|
138
|
-
if (opts.resume)
|
|
139
|
-
args.push("--resume", opts.resume, "--fork-session");
|
|
140
|
-
// Opaque connector options → native `claude` flags, RAW passthrough: `key=value` renders
|
|
141
|
-
// `--key value`, and an empty value (`--opt foo=`) renders a bare boolean `--foo`. No allow-list,
|
|
142
|
-
// no deny-list — the spawn capability is the trust boundary (see connectorLaunchOptions), not the
|
|
143
|
-
// flag set. An operator can already run `claude` with any flag directly, and a peer's cotal_spawn
|
|
144
|
-
// is gated by the spawn capability itself; every `claude` flag is forwarded verbatim.
|
|
145
|
-
for (const [k, v] of connectorLaunchOptions("claude", opts.launchOptions)) {
|
|
146
|
-
const val = String(v);
|
|
147
|
-
if (val === "")
|
|
148
|
-
args.push(`--${k}`);
|
|
149
|
-
else
|
|
150
|
-
args.push(`--${k}`, val);
|
|
151
|
-
}
|
|
152
|
-
return {
|
|
153
|
-
command: "claude",
|
|
154
|
-
args,
|
|
155
|
-
env,
|
|
156
|
-
// The dev-channels flag shows a one-time "Enter to confirm" prompt; the
|
|
157
|
-
// manager auto-clears it so a supervised launch needs no human keypress.
|
|
158
|
-
confirm: "Enter to confirm",
|
|
159
|
-
control,
|
|
160
|
-
};
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
registry.register(claudeConnector);
|
|
164
|
-
//# sourceMappingURL=extension.js.map
|
package/dist/extension.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAoD,MAAM,gBAAgB,CAAC;AAC3I,OAAO,EAAE,MAAM,EAAE,sBAAsB,EAAE,eAAe,EAAE,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAExJ,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,iBAAiB,EAAE,+EAA+E;IAClG,UAAU,EAAE,WAAW;IACvB,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACpB,cAAc,EAAE,IAAI,EAAE,qFAAqF;IAE3G,WAAW,CAAC,IAAgB;QAC1B,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxF,2FAA2F;QAC3F,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;QACrC,8FAA8F;QAC9F,8FAA8F;QAC9F,gGAAgG;QAChG,yEAAyE;QACzE,gGAAgG;QAChG,iGAAiG;QACjG,8FAA8F;QAC9F,iFAAiF;QACjF,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,GAAG,GAA2B;YAClC,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,GAAG,MAAM,CAAC,IAAI,CAAC;YACf,GAAG,WAAW,CAAC,IAAI,CAAC;YACpB,WAAW,EAAE,IAAI,CAAC,KAAK;YACvB,UAAU,EAAE,IAAI,CAAC,IAAI;YACrB,gFAAgF;YAChF,mFAAmF;YACnF,aAAa,EAAE,GAAG;YAClB,oBAAoB,EAAE,OAAO,CAAC,IAAI;YAClC,mBAAmB,EAAE,OAAO,CAAC,KAAK,EAAE,uDAAuD;SAC5F,CAAC;QACF,oFAAoF;QACpF,uFAAuF;QACvF,+FAA+F;QAC/F,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;YAAE,GAAG,CAAC,gBAAgB,GAAG,GAAG,CAAC;QACzD,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,0FAA0F;QAC1F,2FAA2F;QAC3F,6FAA6F;QAC7F,8FAA8F;QAC9F,yFAAyF;QACzF,+FAA+F;QAC/F,2FAA2F;QAC3F,gGAAgG;QAChG,MAAM,UAAU,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAC1F,gGAAgG;QAChG,gGAAgG;QAChG,kGAAkG;QAClG,6FAA6F;QAC7F,+FAA+F;QAC/F,8FAA8F;QAC9F,+FAA+F;QAC/F,2FAA2F;QAC3F,+FAA+F;QAC/F,IAAI,SAAiB,CAAC;QACtB,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,2FAA2F;YAC3F,6FAA6F;YAC7F,8FAA8F;YAC9F,2FAA2F;YAC3F,qFAAqF;YACrF,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;YACtD,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,4EAA4E;YACvG,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YAClC,eAAe,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,qBAAqB,EAAE,cAAc,EAAE,SAAS,CAAC,CAAC;QAE5D,6EAA6E;QAC7E,8EAA8E;QAC9E,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACvB,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,KAAK,KAAK,GAAG,CAAC,KAAK,CAAC;QACtB,CAAC;QACD,oFAAoF;QACpF,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC5B,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC;QAC1B,CAAC;QAED,kGAAkG;QAClG,8FAA8F;QAC9F,6FAA6F;QAC7F,+FAA+F;QAC/F,kFAAkF;QAClF,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAEtE,yFAAyF;QACzF,kGAAkG;QAClG,kGAAkG;QAClG,kGAAkG;QAClG,sFAAsF;QACtF,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1E,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,GAAG,KAAK,EAAE;gBAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;;gBAC/B,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;QAED,OAAO;YACL,OAAO,EAAE,QAAQ;YACjB,IAAI;YACJ,GAAG;YACH,wEAAwE;YACxE,yEAAyE;YACzE,OAAO,EAAE,kBAAkB;YAC3B,OAAO;SACR,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC"}
|
package/dist/hook.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cotal Claude Code lifecycle hook — a one-liner over the shared relay.
|
|
3
|
-
*
|
|
4
|
-
* Claude Code runs this on a lifecycle event and pipes the event JSON on stdin;
|
|
5
|
-
* the relay (in @cotal-ai/connector-core) forwards it to this session's connector
|
|
6
|
-
* control socket and prints the reply. It never blocks the session.
|
|
7
|
-
*/
|
|
8
|
-
import { runHookRelay } from "@cotal-ai/connector-core";
|
|
9
|
-
void runHookRelay().catch(() => process.exit(0));
|
|
10
|
-
//# sourceMappingURL=hook.js.map
|
package/dist/hook.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,KAAK,YAAY,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC,CAAC,kDAAkD;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC,CAAC,8DAA8D"}
|
package/dist/mcp.js
DELETED
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cotal Claude Code connector — MCP (stdio) server.
|
|
3
|
-
*
|
|
4
|
-
* Turns the Claude Code session that launches it into a first-class Cotal mesh
|
|
5
|
-
* peer: presence + the shared cotal_* tools (from @cotal-ai/connector-core), plus
|
|
6
|
-
* Claude's `claude/channel` push so an idle session wakes the instant a peer
|
|
7
|
-
* message arrives. Identity comes from `COTAL_*` env.
|
|
8
|
-
*
|
|
9
|
-
* stdio transport owns stdout for JSON-RPC — ALL diagnostics go to stderr.
|
|
10
|
-
*/
|
|
11
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
|
-
import { configFromEnv, hasIdentity, MeshAgent, startControlServer, registerCotalTools, feedbackLine, ORIENTATION_BOOTSTRAP, formatInjection, fmtFrom, channelMeta, } from "@cotal-ai/connector-core";
|
|
14
|
-
import { TranscriptMirror, transcriptChannel } from "./transcript.js";
|
|
15
|
-
/** Mirrors this session's transcript to `tr-<name>` — set in main() iff COTAL_TRANSCRIPT
|
|
16
|
-
* is on (buildLaunch sets it for managed sessions; personal sessions never mirror). */
|
|
17
|
-
let mirror;
|
|
18
|
-
/**
|
|
19
|
-
* Last tool Claude tried to use, captured on PreToolUse. When a permission Notification
|
|
20
|
-
* fires moments later, this is *what* it's blocked on — so the dashboard shows the actual
|
|
21
|
-
* command/action awaiting approval, not just "Claude needs your permission".
|
|
22
|
-
*/
|
|
23
|
-
let pendingTool;
|
|
24
|
-
/** A short, human-readable preview of a tool call: its most salient input, else compact JSON. */
|
|
25
|
-
function toolDetail(name, input) {
|
|
26
|
-
if (typeof name !== "string" || !name)
|
|
27
|
-
return undefined;
|
|
28
|
-
const i = (input ?? {});
|
|
29
|
-
const salient = i.command ?? i.file_path ?? i.path ?? i.url ?? i.pattern ?? i.description;
|
|
30
|
-
let detail = typeof salient === "string" ? salient : Object.keys(i).length ? JSON.stringify(i) : "";
|
|
31
|
-
if (detail.length > 300)
|
|
32
|
-
detail = `${detail.slice(0, 299)}…`;
|
|
33
|
-
return { name, detail };
|
|
34
|
-
}
|
|
35
|
-
/** Claude Code lifecycle events → presence + (on inject-capable events) queued peer messages. */
|
|
36
|
-
const claudeHandle = async (agent, ev) => {
|
|
37
|
-
const event = ev.hook_event_name ?? "";
|
|
38
|
-
const withContext = (text) => text ? { hookSpecificOutput: { hookEventName: event, additionalContext: text } } : {};
|
|
39
|
-
try {
|
|
40
|
-
switch (event) {
|
|
41
|
-
case "SessionStart": {
|
|
42
|
-
mirror?.adopt(ev.transcript_path); // mirror from HERE — a resumed session never rebroadcasts
|
|
43
|
-
// Claude Code reports the session's actual model here (the ONLY hook that carries it; absent
|
|
44
|
-
// after /clear or conversation recovery, so guard on string). Surface it in presence when the
|
|
45
|
-
// operator didn't pin one. A mid-session /model switch fires no hook, so this holds until the
|
|
46
|
-
// next (re)start — acceptable for a display-only discovery field. setModel keeps the pin wins.
|
|
47
|
-
if (typeof ev.model === "string")
|
|
48
|
-
await agent.setModel(ev.model);
|
|
49
|
-
await agent.setStatus("idle");
|
|
50
|
-
await agent.setAttention("open"); // F3: reset to fail-open on every (re)start — a crashed/restarted agent must not stay silently deaf
|
|
51
|
-
// Boot push: a one-line note per subscribed channel (if the registry has loaded),
|
|
52
|
-
// plus any messages waiting. Both are advisory context.
|
|
53
|
-
const parts = [agent.channelBriefing(), formatInjection(agent.drainInbox())].filter(Boolean);
|
|
54
|
-
return withContext(parts.length ? parts.join("\n\n") : undefined);
|
|
55
|
-
}
|
|
56
|
-
case "UserPromptSubmit":
|
|
57
|
-
pendingTool = undefined; // new turn — the previous block (if any) is resolved
|
|
58
|
-
mirror?.flush(ev.transcript_path);
|
|
59
|
-
await agent.setStatus("working");
|
|
60
|
-
return withContext(formatInjection(agent.drainInbox()));
|
|
61
|
-
case "PreToolUse":
|
|
62
|
-
// Remember what Claude is about to do; if it needs permission, the Notification
|
|
63
|
-
// below turns this into the "blocked on" detail. Auto-approved tools just overwrite it.
|
|
64
|
-
pendingTool = toolDetail(ev.tool_name, ev.tool_input);
|
|
65
|
-
mirror?.flush(ev.transcript_path); // near-live mirror: each tool boundary ships the turn so far
|
|
66
|
-
return {};
|
|
67
|
-
case "Notification": {
|
|
68
|
-
// Claude Code's Notification carries the human-readable reason the session is
|
|
69
|
-
// blocked in `message`. When a tool permission is pending, lead with *what* it's
|
|
70
|
-
// waiting on (the actual command) so a one-line card preview stays informative — the
|
|
71
|
-
// `waiting` status + the dashboard's "BLOCKED ON" label already convey the *why*.
|
|
72
|
-
// Otherwise (idle-input / elicitation, no tool) the message itself is the content.
|
|
73
|
-
const msg = typeof ev.message === "string" ? ev.message : undefined;
|
|
74
|
-
const activity = pendingTool
|
|
75
|
-
? `${pendingTool.name}${pendingTool.detail ? `: ${pendingTool.detail}` : ""}`
|
|
76
|
-
: msg;
|
|
77
|
-
await agent.setStatus("waiting", activity);
|
|
78
|
-
return {};
|
|
79
|
-
}
|
|
80
|
-
case "Stop":
|
|
81
|
-
case "StopFailure": // turn died on an API error — Stop won't fire, so reset here too
|
|
82
|
-
pendingTool = undefined; // turn ended — don't let a stale tool attach to an idle-wait notification
|
|
83
|
-
mirror?.flush(ev.transcript_path);
|
|
84
|
-
await agent.setStatus("idle");
|
|
85
|
-
// Now idle: if ambient channel chatter was held while we were busy, ask the channel to
|
|
86
|
-
// wake one turn so its UserPromptSubmit drains+acks the batch. (Ack sites are two:
|
|
87
|
-
// drainInbox for surfaced items, and the focus ingest ack-drop for ambient/mentions a
|
|
88
|
-
// focus agent declined.) Stop can't inject context itself, so we must NOT drain here —
|
|
89
|
-
// that would ack with no vehicle to the model and silently lose the messages.
|
|
90
|
-
// Mode-and-channel-aware (pendingWake): open flushes held normal ambient too; dnd/focus and
|
|
91
|
-
// per-channel `quiet` wake only for held DIRECTED items (held quiet/dnd ambient alone must not
|
|
92
|
-
// wake — it would empty-wake busy-loop; it rides the next human turn).
|
|
93
|
-
if (agent.pendingWake() > 0)
|
|
94
|
-
agent.requestWake();
|
|
95
|
-
return {};
|
|
96
|
-
case "SessionEnd":
|
|
97
|
-
mirror?.flush(ev.transcript_path); // best-effort — the process may exit before it lands
|
|
98
|
-
await agent.setStatus("offline");
|
|
99
|
-
return {};
|
|
100
|
-
default:
|
|
101
|
-
return {};
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
return {}; // never block the session
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
async function main() {
|
|
109
|
-
// No identity → this is a plain `claude`, not a launcher-spawned agent. Stay
|
|
110
|
-
// inert: never connect to the mesh, so an installed plugin can't make the
|
|
111
|
-
// operator's own sessions join as stray peers.
|
|
112
|
-
if (!hasIdentity()) {
|
|
113
|
-
process.stderr.write("[cotal-connector] no COTAL_NAME — not a managed session; staying off the mesh\n");
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
const config = configFromEnv();
|
|
117
|
-
config.connector = "claude"; // advertise the host harness on our AgentCard (meta.connector)
|
|
118
|
-
const agent = new MeshAgent(config);
|
|
119
|
-
agent.start(); // background connect with retry — never blocks tool serving
|
|
120
|
-
if (/^(1|true|yes|on)$/i.test(process.env.COTAL_TRANSCRIPT ?? ""))
|
|
121
|
-
mirror = new TranscriptMirror(agent, transcriptChannel(config.name));
|
|
122
|
-
// Local control plane for the lifecycle hooks (presence + message injection) and the manager's
|
|
123
|
-
// cooperative shutdown. Path + token come from the launch env (buildLaunch set them, and the hooks
|
|
124
|
-
// inherit this process's env) — a managed session without them is misconfigured, so fail loud
|
|
125
|
-
// rather than serve an unauthenticated/no control plane.
|
|
126
|
-
const controlPath = process.env.COTAL_CONTROL_SOCKET;
|
|
127
|
-
const controlToken = process.env.COTAL_CONTROL_TOKEN;
|
|
128
|
-
if (!controlPath || !controlToken) {
|
|
129
|
-
process.stderr.write("[cotal-connector] managed session missing COTAL_CONTROL_SOCKET/COTAL_CONTROL_TOKEN — cannot serve the control plane\n");
|
|
130
|
-
process.exit(1);
|
|
131
|
-
}
|
|
132
|
-
// Defined before the server so it can be the cooperative-shutdown handler; only ever CALLED after
|
|
133
|
-
// `controlServer` is assigned (on a signal or an authed `{op:"shutdown"}`), so the forward ref is safe.
|
|
134
|
-
let controlServer;
|
|
135
|
-
const shutdown = async () => {
|
|
136
|
-
try {
|
|
137
|
-
controlServer?.close();
|
|
138
|
-
}
|
|
139
|
-
catch {
|
|
140
|
-
/* ignore */
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
await agent.stop();
|
|
144
|
-
}
|
|
145
|
-
finally {
|
|
146
|
-
process.exit(0);
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
controlServer = startControlServer(agent, { path: controlPath, token: controlToken }, claudeHandle, { fatalBind: true, onShutdown: () => void shutdown() });
|
|
150
|
-
const server = new McpServer({ name: "cotal", version: "0.0.0" }, {
|
|
151
|
-
// `claude/channel` makes this MCP server a Claude Code *channel*: peer
|
|
152
|
-
// messages can be pushed straight into the session (waking it if idle).
|
|
153
|
-
capabilities: { experimental: { "claude/channel": {} } },
|
|
154
|
-
instructions: `You are connected to the Cotal mesh as "${config.name}"` +
|
|
155
|
-
`${config.role ? ` (role: ${config.role})` : ""} in space "${config.space}". ` +
|
|
156
|
-
`${ORIENTATION_BOOTSTRAP} ` +
|
|
157
|
-
feedbackLine(config) +
|
|
158
|
-
`Other agents coordinate with you here as lateral peers. ` +
|
|
159
|
-
`Peer messages may arrive as <channel source="cotal" from="<name>" role="<role>" ` +
|
|
160
|
-
`kind="dm|channel|anycast" channel="<name>">…</channel> — read them and, when a reply is ` +
|
|
161
|
-
`warranted, respond with cotal_dm (back to that peer), cotal_send (to a channel), or ` +
|
|
162
|
-
`cotal_anycast (to a role). Use cotal_roster to see who is present, cotal_inbox to pull ` +
|
|
163
|
-
`anything you may have missed, and cotal_status to report what you are doing. ` +
|
|
164
|
-
`If you need to concentrate, cotal_status also sets your attention — dnd (channel ` +
|
|
165
|
-
`chatter stops waking you; it still arrives on your next turn) or focus (only DMs and ` +
|
|
166
|
-
`@mentions reach your context — pull the held chatter with cotal_inbox). ` +
|
|
167
|
-
`To silence one channel instead of all of them, cotal_channel_mode sets it quiet (still ` +
|
|
168
|
-
`delivered + readable, never wakes you; @mentions still wake) or muted (you stop receiving ` +
|
|
169
|
-
`it, @mentions included). ` +
|
|
170
|
-
`Reply only when a reply is actually needed — a silent acknowledgement is correct; ` +
|
|
171
|
-
`"agreed/thanks/good point" messages are noise. And @-mention a peer only when you need ` +
|
|
172
|
-
`THAT specific peer to act: a mention wakes them, so mentioning in acknowledgements or ` +
|
|
173
|
-
`sign-offs makes peers ping-pong wake-ups in an endless loop.`,
|
|
174
|
-
});
|
|
175
|
-
registerCotalTools(server, agent, config, "claude-code");
|
|
176
|
-
// One wake-nudge path, shared by incoming messages and the Stop→idle flush. It stays a stable
|
|
177
|
-
// function gated on a *mutable* `channelActive` flag (flipped true only after the MCP
|
|
178
|
-
// handshake confirms the client speaks claude/channel — see below). If it fires before then it
|
|
179
|
-
// simply no-ops; a *buffered* message waits in the inbox and is drained at the next
|
|
180
|
-
// UserPromptSubmit, so nothing is lost. This only ever *wakes* a turn (drainInbox and the focus
|
|
181
|
-
// ingest ack-drop are the ack sites). One exception: a focus @mention's body was already
|
|
182
|
-
// ack-dropped at ingest (not buffered), so a missed mention-wake is recoverable only by an
|
|
183
|
-
// explicit cotal_inbox pull (recall) — there is no buffered copy to drain.
|
|
184
|
-
let channelActive = false;
|
|
185
|
-
const nudge = (item, pullHint) => {
|
|
186
|
-
if (!channelActive)
|
|
187
|
-
return;
|
|
188
|
-
const n = agent.inboxCount();
|
|
189
|
-
const content = pullHint
|
|
190
|
-
? `📨 ${pullHint}`
|
|
191
|
-
: item
|
|
192
|
-
? `📨 New ${item.kind}${item.mentionsMe ? " — you were mentioned" : ""} from ${fmtFrom(item)} — delivering your Cotal inbox now.`
|
|
193
|
-
: `📨 ${n} Cotal message${n === 1 ? "" : "s"} waiting — delivering your inbox now.`;
|
|
194
|
-
void server.server
|
|
195
|
-
.notification({
|
|
196
|
-
method: "notifications/claude/channel",
|
|
197
|
-
params: { content, meta: item ? channelMeta(item) : { kind: "batch" } },
|
|
198
|
-
})
|
|
199
|
-
.catch((e) => process.stderr.write(`[cotal-connector] channel nudge failed: ${e.message}\n`));
|
|
200
|
-
};
|
|
201
|
-
// Mode-aware wake. A *directed* message (DM, anycast, or an @mention of us) always nudges, so the
|
|
202
|
-
// addressee sees it promptly — woken now if idle, at the next turn boundary if busy. *Ambient*
|
|
203
|
-
// channel chatter nudges only in `open` while idle (suppressed mid-turn, never in dnd/focus), and a
|
|
204
|
-
// per-channel `quiet` channel never ambient-nudges (its ambient was buffered to read on the agent's
|
|
205
|
-
// own terms; a `quiet` @mention still nudges via directedOrMention). `muted` ambient never reaches
|
|
206
|
-
// here (ack-dropped at ingest); in `focus`, ambient/mentions never reach "incoming" either.
|
|
207
|
-
agent.on("incoming", (item) => {
|
|
208
|
-
const directedOrMention = item.kind !== "channel" || item.mentionsMe;
|
|
209
|
-
const quiet = item.kind === "channel" && agent.channelMode(item.channel) === "quiet";
|
|
210
|
-
const ambientWakes = !quiet && agent.attention === "open" && agent.status !== "working";
|
|
211
|
-
if (directedOrMention || ambientWakes)
|
|
212
|
-
nudge(item);
|
|
213
|
-
});
|
|
214
|
-
// Focus-only: a channel @mention was acked-and-dropped (not buffered) but still wakes us to PULL it
|
|
215
|
-
// — F4=B (wake-only). Its body isn't injected; cotal_inbox recalls it.
|
|
216
|
-
agent.on("mention-wake", (item) => nudge(item, `You were mentioned by ${fmtFrom(item)} on #${item.channel ?? "?"} — pull it with cotal_inbox.`));
|
|
217
|
-
agent.on("wake", () => nudge());
|
|
218
|
-
process.on("SIGINT", () => void shutdown());
|
|
219
|
-
process.on("SIGTERM", () => void shutdown());
|
|
220
|
-
const transport = new StdioServerTransport();
|
|
221
|
-
await server.connect(transport);
|
|
222
|
-
// Is this session consuming us as a channel? Only now (post-handshake) can we read the
|
|
223
|
-
// client's capabilities, so we flip the mutable flag the nudge path is gated on. The handlers
|
|
224
|
-
// were registered above and simply no-op'd until this point.
|
|
225
|
-
const clientCaps = server.server.getClientCapabilities();
|
|
226
|
-
const envFlag = process.env.COTAL_CHANNEL;
|
|
227
|
-
channelActive = envFlag
|
|
228
|
-
? /^(1|true|yes|on)$/i.test(envFlag)
|
|
229
|
-
: Boolean(clientCaps?.experimental?.["claude/channel"]);
|
|
230
|
-
process.stderr.write(`[cotal-connector] client capabilities: ${JSON.stringify(clientCaps ?? {})} → channel ${channelActive ? "ACTIVE" : "off"}\n`);
|
|
231
|
-
process.stderr.write(`[cotal-connector] MCP ready (stdio) — space="${config.space}" name="${config.name}"${config.role ? ` role="${config.role}"` : ""}\n`);
|
|
232
|
-
}
|
|
233
|
-
main().catch((e) => {
|
|
234
|
-
process.stderr.write(`[cotal-connector] fatal: ${e.stack ?? String(e)}\n`);
|
|
235
|
-
process.exit(1);
|
|
236
|
-
});
|
|
237
|
-
//# sourceMappingURL=mcp.js.map
|
package/dist/mcp.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
|