@vibevibes/mcp 0.9.1 → 0.9.3

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/dist/index.js CHANGED
@@ -86,30 +86,43 @@ const PROJECT_ROOT = process.cwd();
86
86
  const AGENTS_DIR = resolve(PROJECT_ROOT, ".claude/vibevibes-agents");
87
87
  const SETTINGS_PATH = resolve(PROJECT_ROOT, ".claude/settings.json");
88
88
  // ── Dynamic Hook Registration ─────────────────────────────────────
89
+ const HOOK_COMMAND = `node "$CLAUDE_PROJECT_DIR/.claude/hooks/vibevibes-stop.js"`;
90
+ const HOOKS_DEST_DIR = resolve(PROJECT_ROOT, ".claude/hooks");
89
91
  /**
90
- * Ensure the Stop hook is registered in .claude/settings.json.
91
- * Called on connect. Idempotent — skips if already present.
92
- * Uses absolute path because hook CWD may differ from project root.
92
+ * Copy stop hook files into the project's .claude/hooks/ and register
93
+ * the Stop hook in .claude/settings.json.
94
+ *
95
+ * Uses $CLAUDE_PROJECT_DIR so the path stays valid regardless of
96
+ * npx cache changes between versions.
93
97
  */
94
98
  function ensureStopHook() {
95
99
  try {
96
- const hookScript = resolve(MCP_ROOT, "hooks/stop-hook.js");
97
- const command = `node "${hookScript}"`;
100
+ // 1. Copy hook files into the project
101
+ if (!existsSync(HOOKS_DEST_DIR))
102
+ mkdirSync(HOOKS_DEST_DIR, { recursive: true });
103
+ const srcStop = resolve(MCP_ROOT, "hooks/stop-hook.js");
104
+ const srcLogic = resolve(MCP_ROOT, "hooks/logic.js");
105
+ const destStop = resolve(HOOKS_DEST_DIR, "vibevibes-stop.js");
106
+ const destLogic = resolve(HOOKS_DEST_DIR, "logic.js");
107
+ // Always overwrite to ensure latest version
108
+ if (existsSync(srcStop))
109
+ writeFileSync(destStop, readFileSync(srcStop, "utf-8"));
110
+ if (existsSync(srcLogic))
111
+ writeFileSync(destLogic, readFileSync(srcLogic, "utf-8"));
112
+ // 2. Register in settings.json
98
113
  let settings = {};
99
114
  if (existsSync(SETTINGS_PATH)) {
100
115
  settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
101
116
  }
102
117
  const hooks = (settings.hooks ?? {});
103
118
  const stopHooks = (hooks.Stop ?? []);
104
- const alreadyRegistered = stopHooks.some((entry) => entry.hooks?.some((h) => h.type === "command" && h.command === command));
105
- if (alreadyRegistered)
106
- return;
107
- stopHooks.push({
108
- hooks: [{ type: "command", command, timeout: 60 }],
119
+ // Remove any old vibevibes stop hooks (stale npx paths, etc.)
120
+ const cleaned = stopHooks.filter((entry) => !entry.hooks?.some((h) => h.type === "command" && (h.command.includes("vibevibes") || h.command.includes("stop-hook"))));
121
+ cleaned.push({
122
+ hooks: [{ type: "command", command: HOOK_COMMAND, timeout: 60 }],
109
123
  });
110
- hooks.Stop = stopHooks;
124
+ hooks.Stop = cleaned;
111
125
  settings.hooks = hooks;
112
- // Ensure directory exists
113
126
  const settingsDir = dirname(SETTINGS_PATH);
114
127
  if (!existsSync(settingsDir))
115
128
  mkdirSync(settingsDir, { recursive: true });
@@ -123,12 +136,10 @@ function removeStopHook() {
123
136
  try {
124
137
  if (!existsSync(SETTINGS_PATH))
125
138
  return;
126
- const hookScript = resolve(MCP_ROOT, "hooks/stop-hook.js");
127
- const command = `node "${hookScript}"`;
128
139
  const settings = JSON.parse(readFileSync(SETTINGS_PATH, "utf-8"));
129
140
  const hooks = (settings.hooks ?? {});
130
141
  const stopHooks = (hooks.Stop ?? []);
131
- hooks.Stop = stopHooks.filter((entry) => !entry.hooks?.some((h) => h.type === "command" && h.command === command));
142
+ hooks.Stop = stopHooks.filter((entry) => !entry.hooks?.some((h) => h.type === "command" && (h.command.includes("vibevibes") || h.command.includes("stop-hook"))));
132
143
  settings.hooks = hooks;
133
144
  writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2));
134
145
  }
@@ -186,9 +186,19 @@ async function main() {
186
186
  const POLL_DEADLINE_MS = 55_000;
187
187
  const pollStart = Date.now();
188
188
  while (true) {
189
- // Wall-clock guard — exit cleanly before Claude Code kills us
189
+ // Wall-clock guard — block exit to keep agent alive
190
190
  const elapsed = Date.now() - pollStart;
191
191
  if (elapsed > POLL_DEADLINE_MS) {
192
+ // Re-check agent files — if deleted by disconnect, allow exit
193
+ const currentAgents = loadAgentFiles();
194
+ if (currentAgents.length === 0) {
195
+ process.exit(0);
196
+ }
197
+ // Still connected — block exit
198
+ process.stdout.write(JSON.stringify({
199
+ decision: "block",
200
+ reason: "Still connected to the experience. Waiting for activity.",
201
+ }));
192
202
  process.exit(0);
193
203
  }
194
204
  // Cap poll timeout to remaining time minus buffer, so we don't overshoot the deadline
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibevibes/mcp",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "MCP server — connects Claude to vibevibes experiences",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",