@chatpanel/bridge 0.10.28 → 0.10.29

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatpanel/bridge",
3
- "version": "0.10.28",
3
+ "version": "0.10.29",
4
4
  "type": "module",
5
5
  "description": "Local bridge that exposes the AI coding agents installed on your machine \u2014 Claude Code (CLI), Codex (CLI), and Antigravity CLI (formerly Gemini CLI, which remains available for business/enterprise) \u2014 to the ChatPanel Chrome extension over a localhost SSE endpoint. Bring your own agent.",
6
6
  "keywords": [
package/src/server.js CHANGED
@@ -64,7 +64,7 @@ import {
64
64
  // Hardcoded (not read from package.json) so it survives Bun's single-file
65
65
  // --compile, where package.json isn't on a readable FS. CI fails the publish if
66
66
  // this drifts from package.json, so the two can't silently diverge.
67
- const VERSION = '0.10.28';
67
+ const VERSION = '0.10.29';
68
68
  const HOST = process.env.CHATPANEL_BRIDGE_HOST || '127.0.0.1';
69
69
  const PORT = Number(process.env.CHATPANEL_BRIDGE_PORT) || 4319;
70
70
 
package/src/skills.js CHANGED
@@ -45,11 +45,40 @@ const MAX_SKILLS = 500; // a scan is bounded work, not "whatever is o
45
45
  const MAX_DEPTH = 2; // <root>/<name>/ and <root>/<category>/<name>/
46
46
 
47
47
  /**
48
- * Where skills are scanned from, in precedence order first hit wins on a name clash,
49
- * which makes ChatPanel's own directory authoritative over a shared one.
48
+ * The agent CLIs that keep skills in a well-known directory, and what to call each one.
50
49
  *
51
- * `~/.agents/skills` is the cross-tool location; it is READ, never written, because it
52
- * belongs to whatever else the user runs.
50
+ * Every one of these stores the SAME agentskills.io layout `<name>/SKILL.md` plus
51
+ * optional `references/`. In practice a machine ends up with the same skill copied into
52
+ * several of them, which is the duplication the shared `~/.agents/skills` convention
53
+ * exists to end and has not yet. Reading all of them is what lets ChatPanel show the
54
+ * user's actual skills rather than the subset that happens to live in one folder.
55
+ *
56
+ * Ordered: ChatPanel's own directory, then the cross-tool convention, then each agent.
57
+ * The order IS the precedence — see skillRoots.
58
+ */
59
+ export const AGENT_SKILL_DIRS = Object.freeze([
60
+ { source: 'local', label: 'ChatPanel', segments: ['.chatpanel', 'skills'], writable: true },
61
+ { source: 'agents-dir', label: 'Shared (~/.agents)', segments: ['.agents', 'skills'] },
62
+ { source: 'claude', label: 'Claude Code', segments: ['.claude', 'skills'] },
63
+ { source: 'codex', label: 'Codex', segments: ['.codex', 'skills'] },
64
+ { source: 'copilot', label: 'GitHub Copilot', segments: ['.copilot', 'skills'] },
65
+ { source: 'gemini', label: 'Antigravity / Gemini', segments: ['.gemini', 'skills'] },
66
+ { source: 'opencode', label: 'OpenCode', segments: ['.opencode', 'skills'] },
67
+ { source: 'kiro', label: 'Kiro', segments: ['.kiro', 'skills'] },
68
+ { source: 'pi', label: 'Pi', segments: ['.pi', 'skills'] },
69
+ { source: 'hermes', label: 'Hermes', segments: ['.hermes', 'skills'] },
70
+ ]);
71
+
72
+ /**
73
+ * Where skills are scanned from, in precedence order — first hit wins on a name clash.
74
+ *
75
+ * ChatPanel's own directory is authoritative, then the shared cross-tool one, then each
76
+ * agent's. That order matters because the same skill genuinely does exist in several of
77
+ * these at once: whichever root answers first is the copy that gets shown, and a stable
78
+ * order means the answer does not change between scans.
79
+ *
80
+ * Only the first is written. The rest belong to whatever else the user runs, and a tool
81
+ * that edits another tool's configuration directory is a tool people uninstall.
53
82
  */
54
83
  export function skillRoots(env = process.env, home = os.homedir()) {
55
84
  const extra = String(env.CHATPANEL_SKILL_DIRS || '')
@@ -57,9 +86,13 @@ export function skillRoots(env = process.env, home = os.homedir()) {
57
86
  .map((s) => s.trim())
58
87
  .filter(Boolean);
59
88
  return [
60
- { dir: join(home, '.chatpanel', 'skills'), source: 'local', writable: true },
61
- { dir: join(home, '.agents', 'skills'), source: 'agents-dir', writable: false },
62
- ...extra.map((dir) => ({ dir: resolve(dir), source: 'external', writable: false })),
89
+ ...AGENT_SKILL_DIRS.map((d) => ({
90
+ dir: join(home, ...d.segments),
91
+ source: d.source,
92
+ label: d.label,
93
+ writable: !!d.writable,
94
+ })),
95
+ ...extra.map((dir) => ({ dir: resolve(dir), source: 'external', label: 'Custom', writable: false })),
63
96
  ];
64
97
  }
65
98
 
@@ -289,9 +322,13 @@ export function clearSkillCache() { cached = null; }
289
322
  /** The `/health` summary — counts and roots, never contents. */
290
323
  export async function skillsHealth() {
291
324
  const { index, problems } = await skillIndex();
325
+ const used = new Set([...index.values()].map((v) => v.root));
292
326
  return {
293
327
  count: index.size,
294
- roots: skillRoots().filter((r) => [...index.values()].some((v) => v.root === r.dir)).map((r) => r.dir),
328
+ // Only roots that actually contributed. A list of every path we looked in would be
329
+ // mostly absent directories, and would say nothing about what the user has.
330
+ roots: skillRoots().filter((r) => used.has(r.dir)).map((r) => r.dir),
331
+ sources: [...new Set([...index.values()].map((v) => v.source))].sort(),
295
332
  ...(problems.length ? { problems: problems.length } : {}),
296
333
  };
297
334
  }