Compare commits

...

9 Commits

Author SHA1 Message Date
Alex Newman 12c2ecce06 chore: bump version to 7.1.6
Improved error messages with platform-specific worker restart instructions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-13 17:08:16 -05:00
Alex Newman bb0508d639 Refactor error handling to use platform-specific worker restart instructions
- Updated multiple hooks (context-hook, new-hook, save-hook, summary-hook, user-message-hook) to throw errors using `getWorkerRestartInstructions` for improved user guidance on worker connection issues.
- Enhanced `handleWorkerError` function to utilize the new error message generator for consistent error reporting.
- Modified `ensureWorkerRunning` function to provide detailed instructions based on the worker's state, including port information.
- Introduced `getWorkerRestartInstructions` utility in `error-messages.ts` to generate platform-aware error messages for worker failures.
2025-12-13 17:06:45 -05:00
Alex Newman f00ef33f86 Merge remote-tracking branch 'refs/remotes/origin/main' 2025-12-13 16:54:24 -05:00
Alex Newman c270bd3177 chore: add FUNDING.yml to support GitHub Sponsors 2025-12-13 16:53:00 -05:00
Alex Newman 0836a97845 Add GitHub Actions workflow to summarize new issues (#278) 2025-12-13 16:19:18 -05:00
Alex Newman 19e285a209 docs: regenerate CHANGELOG from GitHub releases 2025-12-13 15:55:46 -05:00
Alex Newman ba877214c1 chore: bump version to 7.1.5
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-13 15:54:57 -05:00
Justin Kowarsch 3d4baefac2 fix: Use getWorkerHost() instead of hardcoded localhost in MCP server (#276)
On Windows systems, `localhost` resolves to IPv6 (::1) while the worker
binds to IPv4 (127.0.0.1), causing MCP tool connections to fail.

This change uses the existing getWorkerHost() function which correctly
returns the configured host address (defaulting to 127.0.0.1).

Fixes connection failures on Windows where localhost prefers IPv6.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 15:54:03 -05:00
Alex Newman 453b7857b8 docs: regenerate CHANGELOG from GitHub releases 2025-12-13 15:37:11 -05:00
26 changed files with 260 additions and 125 deletions
+1 -1
View File
@@ -10,7 +10,7 @@
"plugins": [
{
"name": "claude-mem",
"version": "7.1.4",
"version": "7.1.6",
"source": "./plugin",
"description": "Persistent memory system for Claude Code - context compression across sessions"
}
+1
View File
@@ -0,0 +1 @@
github: [thedotmack]
+34
View File
@@ -0,0 +1,34 @@
name: Summarize new issues
on:
issues:
types: [opened]
jobs:
summary:
runs-on: ubuntu-latest
permissions:
issues: write
models: read
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run AI inference
id: inference
uses: actions/ai-inference@v1
with:
prompt: |
Summarize the following GitHub issue in one paragraph:
Title: ${{ github.event.issue.title }}
Body: ${{ github.event.issue.body }}
- name: Comment with AI summary
run: |
gh issue comment $ISSUE_NUMBER --body '${{ steps.inference.outputs.response }}'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
RESPONSE: ${{ steps.inference.outputs.response }}
+19
View File
@@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [7.1.5] - 2025-12-13
## What's Changed
* fix: Use getWorkerHost() instead of hardcoded localhost in MCP server (#276)
### Bug Fix
Fixes Windows IPv6 issue where `localhost` resolves to `::1` (IPv6) but worker binds to `127.0.0.1` (IPv4), causing MCP tool connections to fail.
**Full Changelog**: https://github.com/thedotmack/claude-mem/compare/v7.1.4...v7.1.5
## [7.1.4] - 2025-12-13
## What's Changed
* fix: add npm fallback when bun install fails with alias packages (#265)
**Full Changelog**: https://github.com/thedotmack/claude-mem/compare/v7.1.3...v7.1.4
## [7.1.3] - 2025-12-13
## Bug Fixes
+1 -1
View File
@@ -6,7 +6,7 @@
Claude-mem is a Claude Code plugin providing persistent memory across sessions. It captures tool usage, compresses observations using the Claude Agent SDK, and injects relevant context into future sessions.
**Current Version**: 7.1.4
**Current Version**: 7.1.6
## Architecture
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claude-mem",
"version": "7.1.4",
"version": "7.1.6",
"description": "Memory compression system for Claude Code - persist context across sessions",
"keywords": [
"claude",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claude-mem",
"version": "7.1.4",
"version": "7.1.6",
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
"author": {
"name": "Alex Newman"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claude-mem-plugin",
"version": "7.1.4",
"version": "7.1.6",
"private": true,
"description": "Runtime dependencies for claude-mem bundled hooks",
"type": "module",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -11,6 +11,7 @@ import { stdin } from "process";
import { ensureWorkerRunning, getWorkerPort } from "../shared/worker-utils.js";
import { HOOK_TIMEOUTS } from "../shared/hook-constants.js";
import { handleWorkerError } from "../shared/hook-error-handler.js";
import { getWorkerRestartInstructions } from "../utils/error-messages.js";
export interface SessionStartInput {
session_id: string;
@@ -34,7 +35,7 @@ async function contextHook(input?: SessionStartInput): Promise<string> {
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Failed to fetch context: ${response.status} ${errorText}`);
throw new Error(getWorkerRestartInstructions({ includeSkillFallback: true }));
}
const result = await response.text();
+3 -2
View File
@@ -4,6 +4,7 @@ import { createHookResponse } from './hook-response.js';
import { ensureWorkerRunning, getWorkerPort } from '../shared/worker-utils.js';
import { happy_path_error__with_fallback } from '../utils/silent-debug.js';
import { handleWorkerError } from '../shared/hook-error-handler.js';
import { getWorkerRestartInstructions } from '../utils/error-messages.js';
export interface UserPromptSubmitInput {
session_id: string;
@@ -52,7 +53,7 @@ async function newHook(input?: UserPromptSubmitInput): Promise<void> {
if (!initResponse.ok) {
const errorText = await initResponse.text();
throw new Error(`Failed to initialize session: ${initResponse.status} ${errorText}`);
throw new Error(getWorkerRestartInstructions({ includeSkillFallback: true }));
}
const initResult = await initResponse.json();
@@ -86,7 +87,7 @@ async function newHook(input?: UserPromptSubmitInput): Promise<void> {
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Failed to start SDK agent: ${response.status} ${errorText}`);
throw new Error(getWorkerRestartInstructions({ includeSkillFallback: true }));
}
} catch (error: any) {
handleWorkerError(error);
+2 -1
View File
@@ -13,6 +13,7 @@ import { ensureWorkerRunning, getWorkerPort } from '../shared/worker-utils.js';
import { HOOK_TIMEOUTS } from '../shared/hook-constants.js';
import { happy_path_error__with_fallback } from '../utils/silent-debug.js';
import { handleWorkerError } from '../shared/hook-error-handler.js';
import { getWorkerRestartInstructions } from '../utils/error-messages.js';
export interface PostToolUseInput {
session_id: string;
@@ -67,7 +68,7 @@ async function saveHook(input?: PostToolUseInput): Promise<void> {
logger.failure('HOOK', 'Failed to send observation', {
status: response.status
}, errorText);
throw new Error(`Failed to send observation to worker: ${response.status} ${errorText}`);
throw new Error(getWorkerRestartInstructions({ includeSkillFallback: true }));
}
logger.debug('HOOK', 'Observation sent successfully', { toolName: tool_name });
+2 -1
View File
@@ -17,6 +17,7 @@ import { HOOK_TIMEOUTS } from '../shared/hook-constants.js';
import { happy_path_error__with_fallback } from '../utils/silent-debug.js';
import { handleWorkerError } from '../shared/hook-error-handler.js';
import { extractLastMessage } from '../shared/transcript-parser.js';
import { getWorkerRestartInstructions } from '../utils/error-messages.js';
export interface StopInput {
session_id: string;
@@ -72,7 +73,7 @@ async function summaryHook(input?: StopInput): Promise<void> {
logger.failure('HOOK', 'Failed to generate summary', {
status: response.status
}, errorText);
throw new Error(`Failed to request summary from worker: ${response.status} ${errorText}`);
throw new Error(getWorkerRestartInstructions({ includeSkillFallback: true }));
}
logger.debug('HOOK', 'Summary request sent successfully');
+2 -1
View File
@@ -9,6 +9,7 @@
import { basename } from "path";
import { ensureWorkerRunning, getWorkerPort } from "../shared/worker-utils.js";
import { HOOK_EXIT_CODES } from "../shared/hook-constants.js";
import { getWorkerRestartInstructions } from "../utils/error-messages.js";
try {
// Ensure worker is running
@@ -24,7 +25,7 @@ try {
);
if (!response.ok) {
throw new Error(`Worker error ${response.status}`);
throw new Error(getWorkerRestartInstructions({ includeSkillFallback: true }));
}
const output = await response.text();
+3 -2
View File
@@ -15,13 +15,14 @@ import {
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';
import { happy_path_error__with_fallback } from '../utils/silent-debug.js';
import { getWorkerPort } from '../shared/worker-utils.js';
import { getWorkerPort, getWorkerHost } from '../shared/worker-utils.js';
/**
* Worker HTTP API configuration
*/
const WORKER_PORT = getWorkerPort();
const WORKER_BASE_URL = `http://localhost:${WORKER_PORT}`;
const WORKER_HOST = getWorkerHost();
const WORKER_BASE_URL = `http://${WORKER_HOST}:${WORKER_PORT}`;
/**
* Map tool names to Worker HTTP endpoints
+3 -3
View File
@@ -1,3 +1,5 @@
import { getWorkerRestartInstructions } from '../utils/error-messages.js';
/**
* Handles fetch errors by providing user-friendly messages for connection issues
* @throws Error with helpful message if worker is unreachable, re-throws original otherwise
@@ -8,9 +10,7 @@ export function handleWorkerError(error: any): never {
error.name === 'TimeoutError' ||
error.message?.includes('fetch failed') ||
error.message?.includes('Unable to connect')) {
throw new Error(
"There's a problem with the worker. Try: npm run worker:restart"
);
throw new Error(getWorkerRestartInstructions());
}
throw error;
}
+9 -5
View File
@@ -6,6 +6,7 @@ import { logger } from "../utils/logger.js";
import { HOOK_TIMEOUTS, getTimeout } from "./hook-constants.js";
import { ProcessManager } from "../services/process/ProcessManager.js";
import { SettingsDefaultsManager } from "./SettingsDefaultsManager.js";
import { getWorkerRestartInstructions } from "../utils/error-messages.js";
const MARKETPLACE_ROOT = path.join(homedir(), '.claude', 'plugins', 'marketplaces', 'thedotmack');
@@ -197,9 +198,10 @@ export async function ensureWorkerRunning(): Promise<void> {
if (!started) {
const port = getWorkerPort();
throw new Error(
`Worker service failed to start on port ${port}.\n\n` +
`To start manually, run: npm run worker:start\n` +
`If already running, try: npm run worker:restart`
getWorkerRestartInstructions({
port,
customPrefix: `Worker service failed to start on port ${port}.`
})
);
}
@@ -217,7 +219,9 @@ export async function ensureWorkerRunning(): Promise<void> {
const port = getWorkerPort();
logger.error('SYSTEM', 'Worker started but not responding to health checks');
throw new Error(
`Worker service started but is not responding on port ${port}.\n\n` +
`Try: npm run worker:restart`
getWorkerRestartInstructions({
port,
customPrefix: `Worker service started but is not responding on port ${port}.`
})
);
}
+53
View File
@@ -0,0 +1,53 @@
/**
* Platform-aware error message generator for worker connection failures
*/
export interface WorkerErrorMessageOptions {
port?: number;
includeSkillFallback?: boolean;
customPrefix?: string;
}
/**
* Generate platform-specific worker restart instructions
* @param options Configuration for error message generation
* @returns Formatted error message with platform-specific paths and commands
*/
export function getWorkerRestartInstructions(
options: WorkerErrorMessageOptions = {}
): string {
const {
port,
includeSkillFallback = false,
customPrefix
} = options;
const isWindows = process.platform === 'win32';
// Platform-specific directory paths
const pluginDir = isWindows
? '%USERPROFILE%\\.claude\\plugins\\marketplaces\\thedotmack'
: '~/.claude/plugins/marketplaces/thedotmack';
// Platform-specific terminal name
const terminal = isWindows
? 'Command Prompt or PowerShell'
: 'Terminal';
// Build error message
const prefix = customPrefix || 'Worker service connection failed.';
const portInfo = port ? ` (port ${port})` : '';
let message = `${prefix}${portInfo}\n\n`;
message += `To restart the worker:\n`;
message += `1. Exit Claude Code completely\n`;
message += `2. Open ${terminal}\n`;
message += `3. Navigate to: ${pluginDir}\n`;
message += `4. Run: npm run worker:restart`;
if (includeSkillFallback) {
message += `\n\nIf that doesn't work, try: /troubleshoot`;
}
return message;
}