patchcord 0.5.111 → 0.5.113
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/bin/patchcord.mjs +50 -20
- package/package.json +1 -1
- package/skills/inbox/SKILL.md +13 -1
- package/skills/wait/SKILL.md +2 -0
package/bin/patchcord.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { existsSync, mkdirSync, cpSync, readdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
3
|
+
import { existsSync, mkdirSync, cpSync, readdirSync, readFileSync, writeFileSync, unlinkSync, rmSync } from "fs";
|
|
4
4
|
import { join, dirname, basename } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { execSync } from "child_process";
|
|
@@ -1563,29 +1563,59 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
|
|
|
1563
1563
|
if (windsurfChanged) globalChanges.push("Windsurf skills installed");
|
|
1564
1564
|
}
|
|
1565
1565
|
|
|
1566
|
-
// Gemini CLI
|
|
1566
|
+
// Gemini CLI + Antigravity (they SHARE ~/.gemini/skills and ~/.gemini/commands).
|
|
1567
|
+
// Seed the patchcord skill ONLY when patchcord MCP is actually configured for
|
|
1568
|
+
// one of these surfaces. Otherwise a bare session (esp. Antigravity, which
|
|
1569
|
+
// inherits this dir) reads a skill with no backing MCP tool and improvises
|
|
1570
|
+
// destructively — scavenging other agents' bearer tokens off disk and curling
|
|
1571
|
+
// the API. Invariant: skill present ⟺ patchcord MCP present under ~/.gemini.
|
|
1567
1572
|
if (existsSync(join(HOME, ".gemini"))) {
|
|
1573
|
+
// true = configured, false = file absent (definitely not), null = unparseable (unknown)
|
|
1574
|
+
const hasPatchcordMcp = (p, keyPath) => {
|
|
1575
|
+
if (!existsSync(p)) return false;
|
|
1576
|
+
try { return !!keyPath.reduce((o, k) => o?.[k], JSON.parse(readFileSync(p, "utf-8"))); }
|
|
1577
|
+
catch { return null; }
|
|
1578
|
+
};
|
|
1579
|
+
const checks = [
|
|
1580
|
+
hasPatchcordMcp(join(HOME, ".gemini", "settings.json"), ["mcpServers", "patchcord"]),
|
|
1581
|
+
hasPatchcordMcp(join(HOME, ".gemini", "antigravity", "mcp_config.json"), ["mcpServers", "patchcord"]),
|
|
1582
|
+
hasPatchcordMcp(join(HOME, ".gemini", "antigravity-cli", "mcp_config.json"), ["mcpServers", "patchcord"]),
|
|
1583
|
+
];
|
|
1584
|
+
const mcpConfigured = checks.some((c) => c === true);
|
|
1585
|
+
const mcpUnknown = checks.some((c) => c === null);
|
|
1568
1586
|
const geminiSkillDir = join(HOME, ".gemini", "skills", "patchcord");
|
|
1569
1587
|
const geminiWaitDir = join(HOME, ".gemini", "skills", "patchcord-wait");
|
|
1570
1588
|
const geminiCmdDir = join(HOME, ".gemini", "commands");
|
|
1571
|
-
|
|
1572
|
-
if (
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
geminiChanged = true;
|
|
1587
|
-
|
|
1588
|
-
if (
|
|
1589
|
+
const geminiLegacyCmd = join(geminiCmdDir, "patchcord.toml"); // single-command file from older installs
|
|
1590
|
+
if (mcpConfigured) {
|
|
1591
|
+
let geminiChanged = false;
|
|
1592
|
+
// Refresh to the CURRENT plugin version (overwrite, not create-if-absent)
|
|
1593
|
+
// so skill/gate fixes reach machines that already have an older copy.
|
|
1594
|
+
const seedFile = (dest, src) => {
|
|
1595
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
1596
|
+
const want = readFileSync(src, "utf-8");
|
|
1597
|
+
let cur = ""; try { cur = readFileSync(dest, "utf-8"); } catch {}
|
|
1598
|
+
if (cur !== want) { writeFileSync(dest, want); geminiChanged = true; }
|
|
1599
|
+
};
|
|
1600
|
+
seedFile(join(geminiSkillDir, "SKILL.md"), join(pluginRoot, "skills", "inbox", "SKILL.md"));
|
|
1601
|
+
seedFile(join(geminiWaitDir, "SKILL.md"), join(pluginRoot, "skills", "wait", "SKILL.md"));
|
|
1602
|
+
seedFile(join(geminiCmdDir, "inbox.toml"), join(pluginRoot, "commands", "inbox.toml"));
|
|
1603
|
+
seedFile(join(geminiCmdDir, "wait.toml"), join(pluginRoot, "commands", "wait.toml"));
|
|
1604
|
+
if (existsSync(geminiLegacyCmd)) { try { unlinkSync(geminiLegacyCmd); geminiChanged = true; } catch {} }
|
|
1605
|
+
if (geminiChanged) globalChanges.push("Gemini/Antigravity patchcord skills + commands refreshed");
|
|
1606
|
+
} else if (!mcpUnknown) {
|
|
1607
|
+
// Definitively no patchcord MCP under ~/.gemini → remove any previously
|
|
1608
|
+
// seeded skill/commands so a bare Gemini/Antigravity session has nothing
|
|
1609
|
+
// to act on (incl. the legacy patchcord.toml command).
|
|
1610
|
+
let removed = false;
|
|
1611
|
+
for (const d of [geminiSkillDir, geminiWaitDir]) {
|
|
1612
|
+
if (existsSync(d)) { try { rmSync(d, { recursive: true, force: true }); removed = true; } catch {} }
|
|
1613
|
+
}
|
|
1614
|
+
for (const f of [join(geminiCmdDir, "inbox.toml"), join(geminiCmdDir, "wait.toml"), geminiLegacyCmd]) {
|
|
1615
|
+
if (existsSync(f)) { try { unlinkSync(f); removed = true; } catch {} }
|
|
1616
|
+
}
|
|
1617
|
+
if (removed) globalChanges.push("Removed stale Gemini/Antigravity patchcord skills (no patchcord MCP configured there)");
|
|
1618
|
+
}
|
|
1589
1619
|
}
|
|
1590
1620
|
|
|
1591
1621
|
// Kimi CLI
|
package/package.json
CHANGED
package/skills/inbox/SKILL.md
CHANGED
|
@@ -10,6 +10,18 @@ description: >
|
|
|
10
10
|
|
|
11
11
|
7 MCP tools: inbox, send_message, reply, wait_for_message, attachment, recall, unsend.
|
|
12
12
|
|
|
13
|
+
## Applies ONLY when the patchcord MCP tools are loaded this session
|
|
14
|
+
|
|
15
|
+
This skill governs those 7 MCP tools. It applies only if they are actually available in the current session.
|
|
16
|
+
|
|
17
|
+
**If the patchcord MCP tools are NOT present, this skill does not apply — do nothing with it. Specifically:**
|
|
18
|
+
- Do NOT call inbox() at session start or at any other time.
|
|
19
|
+
- Do NOT run the `patchcord` CLI as a substitute for the missing tools.
|
|
20
|
+
- 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.
|
|
21
|
+
- Just proceed with the user's actual request.
|
|
22
|
+
|
|
23
|
+
A missing tool means patchcord is not configured for this agent. That is a normal, silent state, not a problem to work around.
|
|
24
|
+
|
|
13
25
|
## Do the work, never just acknowledge
|
|
14
26
|
|
|
15
27
|
When you receive a message from another agent:
|
|
@@ -117,7 +129,7 @@ Always send the storage path (not the file content) to the other agent.
|
|
|
117
129
|
|
|
118
130
|
## Identity (`patchcord whoami` / `patchcord agents`)
|
|
119
131
|
|
|
120
|
-
`whoami` and `agents` are CLI commands, not MCP tools. They
|
|
132
|
+
`whoami` and `agents` are CLI commands, not MCP tools. Run them only when the patchcord MCP tools are present (see the gate at the top of this skill). They read the bearer token from the **current project's own** `.mcp.json` automatically — same namespace scope, no extra setup. Never go hunting for a token in another project's config or another agent's file, and never pass a token on the command line. Cheap to call (input tokens only), don't bloat MCP.
|
|
121
133
|
|
|
122
134
|
- **Run `patchcord whoami` once per session.** Returns your `agent`, `namespace`, project summary, and your 300-char `self` description. Use it on first turn after `/clear` or a fresh session to orient.
|
|
123
135
|
- **Run `patchcord agents`** to see the full roster (every peer's whoami). One call, ~3KB, complete picture of the namespace.
|
package/skills/wait/SKILL.md
CHANGED
|
@@ -8,6 +8,8 @@ description: >
|
|
|
8
8
|
---
|
|
9
9
|
# patchcord:wait
|
|
10
10
|
|
|
11
|
+
Applies ONLY when the patchcord MCP tools are loaded this session. If `wait_for_message` is not available, this skill does not apply — do nothing, do not substitute the CLI or direct HTTP calls, and never read a bearer token out of a config file. Proceed with the user's request.
|
|
12
|
+
|
|
11
13
|
User invoked /patchcord:wait — do NOT substitute /patchcord:subscribe or spawn any background listener. Use `wait_for_message()` only.
|
|
12
14
|
|
|
13
15
|
Call `wait_for_message()` to block until a message arrives (up to 5 minutes).
|