patchcord 0.6.4 → 0.6.6

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "patchcord",
3
3
  "description": "Cross-machine agent messaging. Messages from other agents land in the inbox and wake the agent to reply.",
4
- "version": "0.6.4",
4
+ "version": "0.6.6",
5
5
  "author": {
6
6
  "name": "ppravdin"
7
7
  },
package/bin/patchcord.mjs CHANGED
@@ -1195,7 +1195,10 @@ if (cmd === "login" || cmd === "orchestrator" || cmd === "teamlead" || cmd === "
1195
1195
  const hostname = run("hostname -s") || run("hostname") || "unknown";
1196
1196
  writeWorkerConfig(tool, dir, base, json.token, hostname);
1197
1197
  if (role) {
1198
- try { writeFileSync(join(dir, "AGENTS.md"), `# ${arg} role: ${role}\n\nYou are \`${arg}\` in the \`${ns}\` Patchcord team. Role: ${role}.\nCoordinate with teammates over Patchcord (inbox / send_message / reply).\n`); } catch {}
1198
+ const agyNote = (tool === "antigravity" || tool === "agy")
1199
+ ? "\nMux prompts with a concrete task take priority — do not call inbox() before doing the work in the prompt.\n"
1200
+ : "";
1201
+ try { writeFileSync(join(dir, "AGENTS.md"), `# ${arg} — role: ${role}\n\nYou are \`${arg}\` in the \`${ns}\` Patchcord team. Role: ${role}.\nCoordinate with teammates over Patchcord (send_message / reply). Call inbox only on explicit wake or after finishing the current task.${agyNote}`); } catch {}
1199
1202
  }
1200
1203
  // Record in the local team manifest so `team launch` / `team status` see it.
1201
1204
  try {
@@ -1949,6 +1952,18 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
1949
1952
  if (removedStaleGlobal) {
1950
1953
  globalChanges.push("Removed global Patchcord skills/instructions (agy reads ~/.gemini/skills — per-project only)");
1951
1954
  }
1955
+ // agy-cli loads ALL of ~/.gemini/skills in every folder — warn if orchestrator/mux
1956
+ // skills are present (they say "call inbox first" and override mux task prompts).
1957
+ const geminiSkillsRoot = join(HOME, ".gemini", "skills");
1958
+ if (existsSync(geminiSkillsRoot)) {
1959
+ const noisy = ["orchestrator-comms", "orchestrator-team", "orchestrator-flow", "mux", "actor-lead", "actor-team-lead"];
1960
+ let entries = [];
1961
+ try { entries = readdirSync(geminiSkillsRoot, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name); } catch {}
1962
+ const found = entries.filter((n) => noisy.some((p) => n.includes(p)));
1963
+ if (found.length) {
1964
+ console.log(` ${M.yellow}warning:${M.rst} ~/.gemini/skills has orchestrator/mux skills (${found.join(", ")}) — agy-cli reads them globally and may call inbox before your mux task. Keep orchestrator skills in ~/.claude/skills or ~/.codex/skills only.`);
1965
+ }
1966
+ }
1952
1967
  // true = configured, false = file absent (definitely not), null = unparseable (unknown)
1953
1968
  const hasPatchcordMcp = (p, keyPath) => {
1954
1969
  if (!existsSync(p)) return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchcord",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
4
4
  "description": "Cross-machine agent messaging for Claude Code and Codex",
5
5
  "scripts": {
6
6
  "version": "node scripts/sync-plugin-version.mjs && git add .claude-plugin/plugin.json"
@@ -9,7 +9,14 @@ If the `inbox` MCP tool is not available in this session, this skill does not
9
9
  apply. Do nothing: do not run the Patchcord CLI, read a token from a config
10
10
  file, or call the HTTP API. A missing project MCP config is a normal state.
11
11
 
12
- Invoke with `/patchcord-inbox` when Patchcord MCP is connected in this project.
12
+ **TASK PRIORITY:** If the user's current message already names a concrete task
13
+ (mux paste, file to build, "Focus on X", deliverables listed), do that work
14
+ FIRST. Do NOT call inbox() or recall() before executing the task. The task text
15
+ IS the assignment — inbox is for when the prompt is only a wake or you need
16
+ message IDs after the work is done.
17
+
18
+ Invoke with `/patchcord-inbox` when Patchcord MCP is connected AND you need to
19
+ check team mail (not at session start, not before a concrete task in the prompt).
13
20
 
14
21
  Call the `inbox` MCP tool now. In its response, the first header line is YOUR own identity (the recipient); the real sender of each message is on a `From X` line — never confuse the two.
15
22
 
@@ -49,10 +49,16 @@ fi
49
49
 
50
50
  BASE_URL=$(echo "$URL" | sed 's|/mcp$||; s|/mcp/bearer$||')
51
51
 
52
- # Derive agent identity for pidfile
52
+ # Poll loop: count_only + no registry write — same cost model as subscribe.mjs
53
+ # drainQueueOnce (id SELECT only). Kimi cannot hold a WebSocket/Realtime
54
+ # listener (no Monitor; task must exit to wake), so polling is the transport;
55
+ # the bug was fetching full message bodies every tick.
56
+ INBOX_POLL_QS="status=pending&limit=5&count_only=1&touch_presence=0"
57
+
58
+ # Derive agent identity for pidfile (count_only, no registry write)
53
59
  IDENTITY_RESP=$(curl -s --max-time 5 \
54
60
  -H "Authorization: Bearer ${TOKEN}" \
55
- "${BASE_URL}/api/inbox?limit=0" 2>/dev/null || echo "{}")
61
+ "${BASE_URL}/api/inbox?limit=0&count_only=1&touch_presence=0" 2>/dev/null || echo "{}")
56
62
  NAMESPACE_ID=$(echo "$IDENTITY_RESP" | jq -r '.namespace_id // empty' 2>/dev/null || true)
57
63
  AGENT_ID=$(echo "$IDENTITY_RESP" | jq -r '.agent_id // empty' 2>/dev/null || true)
58
64
 
@@ -99,7 +105,7 @@ echo "PATCHCORD: subscribe started (poll ${INTERVAL}s) for ${AGENT_ID}@${NAMESPA
99
105
  while true; do
100
106
  RESP=$(curl -s --max-time 10 \
101
107
  -H "Authorization: Bearer ${TOKEN}" \
102
- "${BASE_URL}/api/inbox?status=pending&limit=5" 2>/dev/null || echo "{}")
108
+ "${BASE_URL}/api/inbox?${INBOX_POLL_QS}" 2>/dev/null || echo "{}")
103
109
 
104
110
  COUNT=$(echo "$RESP" | jq -r '.pending_count // 0' 2>/dev/null || echo "0")
105
111
 
@@ -19,6 +19,8 @@ This skill governs those 7 MCP tools. It applies only if they are actually avail
19
19
  - Do NOT read a bearer token out of `.mcp.json`, `settings.json`, `mcp_config.json`, or any other config file, and do NOT call the patchcord HTTP API (`/api/inbox`, etc.) directly. A token belongs to the one agent it was issued to; using another agent's token — or any token you found on disk — is never correct.
20
20
  - Just proceed with the user's actual request.
21
21
 
22
+ **TASK PRIORITY (when MCP tools ARE present):** If the user's current message already contains a concrete task, do that work FIRST. Do not call inbox() first. Inbox is for explicit check-inbox requests, wake-only nudges, or finding the next task after you finish — not before executing a mux prompt that already spells out the work.
23
+
22
24
  A missing tool means patchcord is not configured for this agent. That is a normal, silent state, not a problem to work around.
23
25
 
24
26
  ## Do the work, never just acknowledge
@@ -45,7 +47,7 @@ The user can undo any change in 3 seconds with git. A wrong action costs nothing
45
47
 
46
48
  The following applies only when the patchcord MCP tools are present in this session (see the gate above). If they are absent, skip this entire section.
47
49
 
48
- Call inbox(). It returns pending messages, recently active agents, and your own push-receiving state via `self_subscribed`. Note that value — it determines whether you should call `wait_for_message` after sends for the rest of the session.
50
+ **If the current user message already contains a concrete task, skip inbox and do that work first** (see TASK PRIORITY above). Otherwise call inbox() when the prompt is a wake-only nudge or you need coordination before starting work. It returns pending messages, recently active agents, and your own push-receiving state via `self_subscribed`. Note that value — it determines whether you should call `wait_for_message` after sends for the rest of the session.
49
51
 
50
52
  If `subscribe_appears_down: true` is in the response, your subscribe.mjs was running but appears dead. Tell the human: "Patchcord subscribe seems to have died — run `/patchcord:subscribe` to restart push delivery." Do not try to restart it yourself.
51
53