feat: Implement Worker Service with session management and SDK integration
- Added WorkerService to handle long-running HTTP service with session management. - Implemented endpoints for initializing, observing, finalizing, checking status, and deleting sessions. - Integrated with Claude SDK for processing observations and generating responses. - Added port allocator utility to dynamically find available ports for the service. - Configured TypeScript settings for the project.
This commit is contained in:
+69
-44
@@ -2,27 +2,31 @@
|
||||
|
||||
/**
|
||||
* Build script for claude-mem hooks
|
||||
* Bundles TypeScript hooks into individual standalone executables
|
||||
* Bundles TypeScript hooks into individual standalone executables using esbuild
|
||||
*/
|
||||
|
||||
import { exec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
import { build } from 'esbuild';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const HOOKS = [
|
||||
{ name: 'context-hook', source: 'src/bin/hooks/context-hook.ts' },
|
||||
{ name: 'new-hook', source: 'src/bin/hooks/new-hook.ts' },
|
||||
{ name: 'save-hook', source: 'src/bin/hooks/save-hook.ts' },
|
||||
{ name: 'summary-hook', source: 'src/bin/hooks/summary-hook.ts' },
|
||||
{ name: 'cleanup-hook', source: 'src/bin/hooks/cleanup-hook.ts' },
|
||||
{ name: 'worker', source: 'src/bin/hooks/worker.ts' }
|
||||
{ name: 'cleanup-hook', source: 'src/bin/hooks/cleanup-hook.ts' }
|
||||
];
|
||||
|
||||
const WORKER_SERVICE = {
|
||||
name: 'worker-service',
|
||||
source: 'src/services/worker-service.ts'
|
||||
};
|
||||
|
||||
async function buildHooks() {
|
||||
console.log('🔨 Building claude-mem hooks...\n');
|
||||
console.log('🔨 Building claude-mem hooks and worker service...\n');
|
||||
|
||||
try {
|
||||
// Read version from package.json
|
||||
@@ -30,46 +34,65 @@ async function buildHooks() {
|
||||
const version = packageJson.version;
|
||||
console.log(`📌 Version: ${version}`);
|
||||
|
||||
// Check if bun is installed
|
||||
try {
|
||||
await execAsync('bun --version');
|
||||
console.log('✓ Bun detected');
|
||||
} catch {
|
||||
console.error('❌ Bun is not installed. Please install it from https://bun.sh');
|
||||
process.exit(1);
|
||||
}
|
||||
// Create output directories
|
||||
console.log('\n📦 Preparing output directories...');
|
||||
const hooksDir = 'plugin/scripts';
|
||||
const distDir = 'dist';
|
||||
|
||||
// Create scripts directory
|
||||
console.log('\n📦 Preparing scripts directory...');
|
||||
const scriptsDir = 'claude-mem/scripts';
|
||||
if (!fs.existsSync(scriptsDir)) {
|
||||
fs.mkdirSync(scriptsDir, { recursive: true });
|
||||
if (!fs.existsSync(hooksDir)) {
|
||||
fs.mkdirSync(hooksDir, { recursive: true });
|
||||
}
|
||||
console.log('✓ Scripts directory ready');
|
||||
if (!fs.existsSync(distDir)) {
|
||||
fs.mkdirSync(distDir, { recursive: true });
|
||||
}
|
||||
console.log('✓ Output directories ready');
|
||||
|
||||
// Build worker service
|
||||
console.log(`\n🔧 Building worker service...`);
|
||||
await build({
|
||||
entryPoints: [WORKER_SERVICE.source],
|
||||
bundle: true,
|
||||
platform: 'node',
|
||||
target: 'node18',
|
||||
format: 'cjs',
|
||||
outfile: `${distDir}/${WORKER_SERVICE.name}.cjs`,
|
||||
minify: true,
|
||||
external: ['better-sqlite3'],
|
||||
define: {
|
||||
'__DEFAULT_PACKAGE_VERSION__': `"${version}"`
|
||||
},
|
||||
banner: {
|
||||
js: '#!/usr/bin/env node'
|
||||
}
|
||||
});
|
||||
|
||||
// Make worker service executable
|
||||
fs.chmodSync(`${distDir}/${WORKER_SERVICE.name}.cjs`, 0o755);
|
||||
const workerStats = fs.statSync(`${distDir}/${WORKER_SERVICE.name}.cjs`);
|
||||
console.log(`✓ worker-service built (${(workerStats.size / 1024).toFixed(2)} KB)`);
|
||||
|
||||
// Build each hook
|
||||
for (const hook of HOOKS) {
|
||||
console.log(`\n🔧 Building ${hook.name}...`);
|
||||
|
||||
const outfile = `${scriptsDir}/${hook.name}.js`;
|
||||
const buildCommand = [
|
||||
'bun build',
|
||||
hook.source,
|
||||
'--target=bun',
|
||||
`--outfile=${outfile}`,
|
||||
'--minify',
|
||||
'--external bun:sqlite',
|
||||
`--define __DEFAULT_PACKAGE_VERSION__='"${version}"'`
|
||||
].join(' ');
|
||||
const outfile = `${hooksDir}/${hook.name}.js`;
|
||||
|
||||
const { stdout, stderr } = await execAsync(buildCommand);
|
||||
if (stdout) console.log(stdout);
|
||||
if (stderr && !stderr.includes('warn')) console.error(stderr);
|
||||
|
||||
// Add shebang
|
||||
let content = fs.readFileSync(outfile, 'utf-8');
|
||||
content = content.replace(/^#!.*\n/gm, '');
|
||||
fs.writeFileSync(outfile, `#!/usr/bin/env bun\n${content}`);
|
||||
await build({
|
||||
entryPoints: [hook.source],
|
||||
bundle: true,
|
||||
platform: 'node',
|
||||
target: 'node18',
|
||||
format: 'esm',
|
||||
outfile,
|
||||
minify: true,
|
||||
external: ['better-sqlite3'],
|
||||
define: {
|
||||
'__DEFAULT_PACKAGE_VERSION__': `"${version}"`
|
||||
},
|
||||
banner: {
|
||||
js: '#!/usr/bin/env node'
|
||||
}
|
||||
});
|
||||
|
||||
// Make executable
|
||||
fs.chmodSync(outfile, 0o755);
|
||||
@@ -80,13 +103,15 @@ async function buildHooks() {
|
||||
console.log(`✓ ${hook.name} built (${sizeInKB} KB)`);
|
||||
}
|
||||
|
||||
console.log('\n✅ All hooks built successfully!');
|
||||
console.log(` Output: ${scriptsDir}/`);
|
||||
console.log('\n✅ All hooks and worker service built successfully!');
|
||||
console.log(` Hooks: ${hooksDir}/`);
|
||||
console.log(` Worker: ${distDir}/worker-service.cjs`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ Hook build failed:', error.message);
|
||||
if (error.stderr) {
|
||||
console.error('\nError details:', error.stderr);
|
||||
console.error('\n❌ Build failed:', error.message);
|
||||
if (error.errors) {
|
||||
console.error('\nBuild errors:');
|
||||
error.errors.forEach(err => console.error(` - ${err.text}`));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user