@cotal-ai/connector-claude-code 0.11.3 → 0.11.5

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/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.3",
4
+ "version": "0.11.5",
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.3"
27
+ "@cotal-ai/core": "0.11.5",
28
+ "@cotal-ai/connector-core": "0.11.5"
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
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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"}