patchcord 0.5.124 → 0.5.126

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.5.124",
4
+ "version": "0.5.126",
5
5
  "author": {
6
6
  "name": "ppravdin"
7
7
  },
package/bin/patchcord.mjs CHANGED
@@ -1786,6 +1786,33 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
1786
1786
  // Kimi Code (Node) reads ~/.kimi-code/skills. The legacy Python kimi-cli
1787
1787
  // (~/.kimi) is deprecated — install only into Kimi Code's home.
1788
1788
  const kimiSkillRoots = [join(kimiCodeHome, "skills")];
1789
+
1790
+ // Remove [[hooks]] array-of-tables blocks whose body matches `predicate`,
1791
+ // preserving everything else. A block runs from a `[[hooks]]` header line
1792
+ // until the next TOML table / array-of-tables header (`[...]` / `[[...]]`)
1793
+ // or EOF — so trailing sections like [providers.*] and [models.*] are NOT
1794
+ // swallowed. (The old split("[[hooks]]")+filter approach dropped the whole
1795
+ // segment after the patchcord hook, deleting kimi's model/provider defs and
1796
+ // leaving "Model not configured" on every host on the next install.)
1797
+ const removeHookBlocks = (toml, predicate) => {
1798
+ const lines = toml.split("\n");
1799
+ const out = [];
1800
+ let i = 0;
1801
+ while (i < lines.length) {
1802
+ if (/^\s*\[\[hooks\]\]\s*$/.test(lines[i])) {
1803
+ const block = [lines[i]];
1804
+ let j = i + 1;
1805
+ while (j < lines.length && !/^\s*\[/.test(lines[j])) { block.push(lines[j]); j++; }
1806
+ if (!predicate(block.join("\n"))) out.push(...block);
1807
+ i = j;
1808
+ } else {
1809
+ out.push(lines[i]); i++;
1810
+ }
1811
+ }
1812
+ return out.join("\n");
1813
+ };
1814
+ const isPatchcordHook = (b) => /patchcord-(stop-hook|session-start|prompt-hook)/.test(b);
1815
+
1789
1816
  for (const root of kimiSkillRoots) {
1790
1817
  for (const stale of ["patchcord", "patchcord-wait", "patchcord:inbox", "patchcord:wait", "patchcord:subscribe"]) {
1791
1818
  const d = join(root, stale);
@@ -1815,11 +1842,6 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
1815
1842
  // Remove old inline hooks = [] (conflicts with [[hooks]] array-of-tables)
1816
1843
  kimiConfig = kimiConfig.replace(/^hooks\s*=\s*\[\]\n?/gm, "");
1817
1844
 
1818
- // Remove existing patchcord stop hook blocks
1819
- const segments = kimiConfig.split("[[hooks]]");
1820
- const kept = segments.filter((seg, idx) => idx === 0 || !seg.includes("patchcord-stop-hook"));
1821
- kimiConfig = kept.join("[[hooks]]").replace(/\n{3,}/g, "\n\n").trim();
1822
-
1823
1845
  // Install session-start hook
1824
1846
  const kimiSessionSrc = join(pluginRoot, "scripts", "kimi-session-start.sh");
1825
1847
  const kimiSessionDest = join(kimiCodeHome, "patchcord-session-start.sh");
@@ -1828,10 +1850,25 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
1828
1850
  chmodSync(kimiSessionDest, 0o755);
1829
1851
  }
1830
1852
 
1831
- // Remove existing patchcord session-start hook blocks
1832
- const segments2 = kimiConfig.split("[[hooks]]");
1833
- const kept2 = segments2.filter((seg, idx) => idx === 0 || !seg.includes("patchcord-session-start") && !seg.includes("patchcord-prompt-hook"));
1834
- kimiConfig = kept2.join("[[hooks]]").replace(/\n{3,}/g, "\n\n").trim();
1853
+ // Remove any existing patchcord hook blocks (stop / session-start /
1854
+ // legacy prompt) in one pass, preserving all other tables.
1855
+ kimiConfig = removeHookBlocks(kimiConfig, isPatchcordHook).replace(/\n{3,}/g, "\n\n").trim();
1856
+
1857
+ // Self-heal config a PRIOR patchcord version corrupted. The old
1858
+ // split("[[hooks]]")+filter deleted every table that trailed a patchcord
1859
+ // hook block — including kimi's own [providers."managed:kimi-code"] and
1860
+ // [models."kimi-code/kimi-for-coding"] — leaving `default_model` dangling
1861
+ // and the CLI dead with "Model ... is not configured". Restore the
1862
+ // canonical managed block. Guarded three ways: only when default_model
1863
+ // names exactly that managed model AND neither the model nor the provider
1864
+ // section is present — so a user's own provider/model config is never
1865
+ // touched, and this is a no-op on healthy hosts.
1866
+ if (/^\s*default_model\s*=\s*"kimi-code\/kimi-for-coding"/m.test(kimiConfig)
1867
+ && !/^\s*\[models\."kimi-code\/kimi-for-coding"\]/m.test(kimiConfig)
1868
+ && !/^\s*\[providers\."managed:kimi-code"\]/m.test(kimiConfig)) {
1869
+ kimiConfig = kimiConfig.trimEnd() + `\n\n[providers."managed:kimi-code"]\ntype = "kimi"\napi_key = ""\nbase_url = "https://api.kimi.com/coding/v1"\n\n[providers."managed:kimi-code".oauth]\nstorage = "file"\nkey = "oauth/kimi-code"\n\n[models."kimi-code/kimi-for-coding"]\nprovider = "managed:kimi-code"\nmodel = "kimi-for-coding"\nmax_context_size = 262144\ncapabilities = [ "thinking", "always_thinking", "image_in", "video_in", "tool_use" ]\ndisplay_name = "K2.7 Code"\n`;
1870
+ globalChanges.push("Repaired kimi-code model/provider block deleted by an earlier patchcord version");
1871
+ }
1835
1872
 
1836
1873
  // Append new hooks
1837
1874
  kimiConfig = kimiConfig.trimEnd() + `\n\n[[hooks]]\nevent = "SessionStart"\ncommand = "${kimiSessionDest}"\ntimeout = 10\n\n[[hooks]]\nevent = "Stop"\ncommand = "${kimiHookDest}"\ntimeout = 10\n`;
@@ -1853,9 +1890,7 @@ if (!cmd || cmd === "install" || cmd === "agent" || cmd?.startsWith("--")) {
1853
1890
  if (existsSync(legacyConfigPath)) {
1854
1891
  try {
1855
1892
  let lc = readFileSync(legacyConfigPath, "utf-8");
1856
- const segs = lc.split("[[hooks]]");
1857
- const keptLegacy = segs.filter((seg, idx) => idx === 0 || !seg.includes("patchcord-"));
1858
- lc = keptLegacy.join("[[hooks]]").replace(/\n{3,}/g, "\n\n").trim();
1893
+ lc = removeHookBlocks(lc, (b) => /patchcord-/.test(b)).replace(/\n{3,}/g, "\n\n").trim();
1859
1894
  writeFileSync(legacyConfigPath, lc ? lc + "\n" : "");
1860
1895
  } catch {}
1861
1896
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patchcord",
3
- "version": "0.5.124",
3
+ "version": "0.5.126",
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"