@vibevibes/mcp 0.9.0 → 0.9.2

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
  }
package/hooks/logic.js CHANGED
@@ -136,9 +136,14 @@ export function makeDecision(ctx, iteration) {
136
136
  // Experience signaled completion — allow exit (agent file already deleted by stop-hook)
137
137
  if (ctx.observation?.done)
138
138
  return null;
139
- // Nothing to react toallow exit silently (zero wasted tokens)
140
- if (!hasEvents && !hasError && !hasBrowserErrors && !hasObserveError)
141
- return null;
139
+ // Always block exit while connected the agent should stay alive.
140
+ // If there are events/errors, include them. Otherwise, minimal keepalive.
141
+ if (!hasEvents && !hasError && !hasBrowserErrors && !hasObserveError) {
142
+ return {
143
+ decision: "block",
144
+ reason: "Still connected. Waiting for activity.",
145
+ };
146
+ }
142
147
  const reason = formatPrompt(ctx);
143
148
  return {
144
149
  decision: "block",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibevibes/mcp",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "MCP server — connects Claude to vibevibes experiences",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",