patchcord 0.5.102 → 0.5.104
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
CHANGED
|
@@ -1458,21 +1458,7 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
|
|
|
1458
1458
|
// Kimi CLI
|
|
1459
1459
|
const hasKimi = run("which kimi");
|
|
1460
1460
|
if (hasKimi) {
|
|
1461
|
-
// Clean up old skill names: the combined skill AND the colon-named flow
|
|
1462
|
-
// skills (patchcord:inbox …). Kimi requires skill names to be
|
|
1463
|
-
// lowercase/digits/hyphens only — a colon kept them out of /flow:, so they
|
|
1464
|
-
// showed only under /skill:. Renamed to patchcord-inbox etc.
|
|
1465
|
-
for (const stale of ["patchcord", "patchcord-wait", "patchcord:inbox", "patchcord:wait", "patchcord:subscribe"]) {
|
|
1466
|
-
const d = join(HOME, ".kimi", "skills", stale);
|
|
1467
|
-
if (existsSync(d)) { try { rmSync(d, { recursive: true, force: true }); } catch {} }
|
|
1468
|
-
}
|
|
1469
|
-
|
|
1470
|
-
// Install three focused Kimi flow skills (hyphen names → /flow:patchcord-inbox)
|
|
1471
|
-
const kimiInboxDir = join(HOME, ".kimi", "skills", "patchcord-inbox");
|
|
1472
|
-
const kimiWaitDir = join(HOME, ".kimi", "skills", "patchcord-wait");
|
|
1473
|
-
const kimiSubDir = join(HOME, ".kimi", "skills", "patchcord-subscribe");
|
|
1474
1461
|
let kimiChanged = false;
|
|
1475
|
-
|
|
1476
1462
|
const installKimiSkill = (destDir, relSrc) => {
|
|
1477
1463
|
const src = join(pluginRoot, "per-project-skills", "kimi", relSrc, "SKILL.md");
|
|
1478
1464
|
const dest = join(destDir, "SKILL.md");
|
|
@@ -1481,9 +1467,24 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
|
|
|
1481
1467
|
copyFileSync(src, dest);
|
|
1482
1468
|
return changed;
|
|
1483
1469
|
};
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1470
|
+
// Kimi CLI (Python) reads ~/.kimi/skills; Kimi Code (Node) reads
|
|
1471
|
+
// ~/.kimi-code/skills. Install into BOTH user dirs that exist — a global
|
|
1472
|
+
// `npx patchcord` must fix whichever Kimi the user runs. Clean up the old
|
|
1473
|
+
// combined skill AND colon-named flow skills (Kimi requires names to be
|
|
1474
|
+
// lowercase/digits/hyphens only — a colon kept them out of /flow:, showing
|
|
1475
|
+
// them only under /skill:). Renamed to patchcord-inbox etc.
|
|
1476
|
+
const kimiCodeHome = process.env.KIMI_CODE_HOME || join(HOME, ".kimi-code");
|
|
1477
|
+
const kimiSkillRoots = [join(HOME, ".kimi", "skills")];
|
|
1478
|
+
if (existsSync(kimiCodeHome)) kimiSkillRoots.push(join(kimiCodeHome, "skills"));
|
|
1479
|
+
for (const root of kimiSkillRoots) {
|
|
1480
|
+
for (const stale of ["patchcord", "patchcord-wait", "patchcord:inbox", "patchcord:wait", "patchcord:subscribe"]) {
|
|
1481
|
+
const d = join(root, stale);
|
|
1482
|
+
if (existsSync(d)) { try { rmSync(d, { recursive: true, force: true }); } catch {} }
|
|
1483
|
+
}
|
|
1484
|
+
kimiChanged = installKimiSkill(join(root, "patchcord-inbox"), "inbox") || kimiChanged;
|
|
1485
|
+
kimiChanged = installKimiSkill(join(root, "patchcord-wait"), "wait") || kimiChanged;
|
|
1486
|
+
kimiChanged = installKimiSkill(join(root, "patchcord-subscribe"), "subscribe") || kimiChanged;
|
|
1487
|
+
}
|
|
1487
1488
|
|
|
1488
1489
|
// Install/update stop hook — fires after each Kimi turn to check inbox
|
|
1489
1490
|
let hookChanged = false;
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: patchcord-inbox
|
|
3
3
|
description: Read Patchcord inbox and reply to messages
|
|
4
|
-
type: flow
|
|
5
4
|
---
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
Run this with `/skill:patchcord-inbox`. (Kimi Code has no `/flow:` — `/skill:` injects this as a prompt and you act on it.)
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
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.
|
|
9
|
+
|
|
10
|
+
For each pending message, classify it and act:
|
|
11
|
+
- **ACK** — short signals like thanks, noted, works, great, ok, 👍 with no task → close it silently: `reply(message_id, resolve=true)` with NO content. Never send a text reply to an ack (it creates infinite ack chains).
|
|
12
|
+
- **BLOCKED** — you cannot do the work right now (busy, missing credentials, ambiguous target) → `reply(message_id, "<reason>", defer=true)` so it stays in your inbox as a reminder. Never silently skip a message.
|
|
13
|
+
- **ACTIONABLE** — do the work the message asks for FIRST (edit the file, run the command, write the code), THEN `reply(message_id, "<concrete summary of what you did, with file paths and line numbers>")`. Never reply "will do" / "understood" before doing the work.
|
|
14
|
+
|
|
15
|
+
After handling every message, re-arm the background listener: use the Shell tool to run `patchcord subscribe --kimi 5` with run_in_background=true, timeout=86400, description="Patchcord listener".
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: patchcord-subscribe
|
|
3
3
|
description: Start the Patchcord background polling listener
|
|
4
|
-
type: flow
|
|
5
4
|
---
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
Run this with `/skill:patchcord-subscribe`. (Kimi Code has no `/flow:` — `/skill:` injects this as a prompt and you act on it.)
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
First, call the `inbox` MCP tool and DRAIN every pending message before starting the listener (the listener exits immediately if messages are already waiting). In the inbox response, the first header line is YOUR identity (recipient); the real sender is on each `From X` line. For each message:
|
|
9
|
+
- **ACK** (thanks, noted, works, ok, 👍) → `reply(message_id, resolve=true)`, no content.
|
|
10
|
+
- **BLOCKED** → `reply(message_id, "<reason>", defer=true)`.
|
|
11
|
+
- **ACTIONABLE** → do the work first, then `reply(message_id, "<what you did>")`.
|
|
12
|
+
|
|
13
|
+
Then start the background listener: use the Shell tool to run `patchcord subscribe --kimi 5` with run_in_background=true, timeout=86400, description="Patchcord listener". Tell the user in one sentence: Patchcord listener active.
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: patchcord-wait
|
|
3
3
|
description: Wait for one incoming Patchcord message
|
|
4
|
-
type: flow
|
|
5
4
|
---
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
Run this with `/skill:patchcord-wait`. (Kimi Code has no `/flow:` — `/skill:` injects this as a prompt and you act on it.)
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
```
|
|
8
|
+
Call the `wait_for_message` MCP tool now to block until a message arrives or ~5 minutes elapse.
|
|
9
|
+
|
|
10
|
+
When a message arrives, classify it and act:
|
|
11
|
+
- **ACK** (thanks, noted, works, ok, 👍, no task) → `reply(message_id, resolve=true)` with NO content. Never text-reply an ack.
|
|
12
|
+
- **BLOCKED** (cannot do the work right now) → `reply(message_id, "<reason>", defer=true)`.
|
|
13
|
+
- **ACTIONABLE** → do the work FIRST, then `reply(message_id, "<concrete summary of what you did>")`.
|
|
14
|
+
|
|
15
|
+
Then re-arm the background listener: use the Shell tool to run `patchcord subscribe --kimi 5` with run_in_background=true, timeout=86400, description="Patchcord listener".
|