fix: resolve SDK spawn failures and sharp native binary crashes
- Strip CLAUDECODE env var from SDK subprocesses to prevent "cannot be launched inside another Claude Code session" error (Claude Code 2.1.42+) - Lazy-load @chroma-core/default-embed to avoid eagerly pulling in sharp native binaries at bundle startup (fixes ERR_DLOPEN_FAILED) - Add stderr capture to SDK spawn for diagnosing future process failures - Exclude lockfiles from marketplace rsync and delete stale lockfiles before npm install to prevent native dep version mismatches Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+260
-266
File diff suppressed because one or more lines are too long
@@ -61,10 +61,20 @@ function getPluginVersion() {
|
|||||||
console.log('Syncing to marketplace...');
|
console.log('Syncing to marketplace...');
|
||||||
try {
|
try {
|
||||||
execSync(
|
execSync(
|
||||||
'rsync -av --delete --exclude=.git --exclude=/.mcp.json ./ ~/.claude/plugins/marketplaces/thedotmack/',
|
'rsync -av --delete --exclude=.git --exclude=/.mcp.json --exclude=bun.lock --exclude=package-lock.json ./ ~/.claude/plugins/marketplaces/thedotmack/',
|
||||||
{ stdio: 'inherit' }
|
{ stdio: 'inherit' }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Remove stale lockfiles before install — they pin old native dep versions
|
||||||
|
const { unlinkSync } = require('fs');
|
||||||
|
for (const lockfile of ['package-lock.json', 'bun.lock']) {
|
||||||
|
const lockpath = path.join(INSTALLED_PATH, lockfile);
|
||||||
|
if (existsSync(lockpath)) {
|
||||||
|
unlinkSync(lockpath);
|
||||||
|
console.log(`Removed stale ${lockfile}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log('Running npm install in marketplace...');
|
console.log('Running npm install in marketplace...');
|
||||||
execSync(
|
execSync(
|
||||||
'cd ~/.claude/plugins/marketplaces/thedotmack/ && npm install',
|
'cd ~/.claude/plugins/marketplaces/thedotmack/ && npm install',
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChromaClient, Collection } from 'chromadb';
|
import { ChromaClient, Collection } from 'chromadb';
|
||||||
import { DefaultEmbeddingFunction } from '@chroma-core/default-embed';
|
|
||||||
import { ParsedObservation, ParsedSummary } from '../../sdk/parser.js';
|
import { ParsedObservation, ParsedSummary } from '../../sdk/parser.js';
|
||||||
import { SessionStore } from '../sqlite/SessionStore.js';
|
import { SessionStore } from '../sqlite/SessionStore.js';
|
||||||
import { logger } from '../../utils/logger.js';
|
import { logger } from '../../utils/logger.js';
|
||||||
@@ -191,7 +190,9 @@ export class ChromaSync {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// getOrCreateCollection handles both cases
|
// getOrCreateCollection handles both cases
|
||||||
// Use DefaultEmbeddingFunction for local embeddings (all-MiniLM-L6-v2)
|
// Lazy-load DefaultEmbeddingFunction to avoid eagerly pulling in
|
||||||
|
// @huggingface/transformers → sharp native binaries at bundle startup
|
||||||
|
const { DefaultEmbeddingFunction } = await import('@chroma-core/default-embed');
|
||||||
const embeddingFunction = new DefaultEmbeddingFunction();
|
const embeddingFunction = new DefaultEmbeddingFunction();
|
||||||
this.collection = await this.chromaClient.getOrCreateCollection({
|
this.collection = await this.chromaClient.getOrCreateCollection({
|
||||||
name: this.collectionName,
|
name: this.collectionName,
|
||||||
|
|||||||
@@ -290,12 +290,22 @@ export function createPidCapturingSpawn(sessionDbId: number) {
|
|||||||
windowsHide: true
|
windowsHide: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Capture stderr for debugging spawn failures
|
||||||
|
if (child.stderr) {
|
||||||
|
child.stderr.on('data', (data: Buffer) => {
|
||||||
|
logger.debug('SDK_SPAWN', `[session-${sessionDbId}] stderr: ${data.toString().trim()}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Register PID
|
// Register PID
|
||||||
if (child.pid) {
|
if (child.pid) {
|
||||||
registerProcess(child.pid, sessionDbId, child);
|
registerProcess(child.pid, sessionDbId, child);
|
||||||
|
|
||||||
// Auto-unregister on exit
|
// Auto-unregister on exit
|
||||||
child.on('exit', () => {
|
child.on('exit', (code: number | null, signal: string | null) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
logger.warn('SDK_SPAWN', `[session-${sessionDbId}] Claude process exited`, { code, signal, pid: child.pid });
|
||||||
|
}
|
||||||
if (child.pid) {
|
if (child.pid) {
|
||||||
unregisterProcess(child.pid);
|
unregisterProcess(child.pid);
|
||||||
}
|
}
|
||||||
@@ -306,6 +316,7 @@ export function createPidCapturingSpawn(sessionDbId: number) {
|
|||||||
return {
|
return {
|
||||||
stdin: child.stdin,
|
stdin: child.stdin,
|
||||||
stdout: child.stdout,
|
stdout: child.stdout,
|
||||||
|
stderr: child.stderr,
|
||||||
get killed() { return child.killed; },
|
get killed() { return child.killed; },
|
||||||
get exitCode() { return child.exitCode; },
|
get exitCode() { return child.exitCode; },
|
||||||
kill: child.kill.bind(child),
|
kill: child.kill.bind(child),
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export const ENV_FILE_PATH = join(DATA_DIR, '.env');
|
|||||||
// are passed through to avoid breaking CLI authentication, proxies, and platform features.
|
// are passed through to avoid breaking CLI authentication, proxies, and platform features.
|
||||||
const BLOCKED_ENV_VARS = [
|
const BLOCKED_ENV_VARS = [
|
||||||
'ANTHROPIC_API_KEY', // Issue #733: Prevent auto-discovery from project .env files
|
'ANTHROPIC_API_KEY', // Issue #733: Prevent auto-discovery from project .env files
|
||||||
|
'CLAUDECODE', // Prevent "cannot be launched inside another Claude Code session" error
|
||||||
];
|
];
|
||||||
|
|
||||||
// Credential keys that claude-mem manages
|
// Credential keys that claude-mem manages
|
||||||
|
|||||||
Reference in New Issue
Block a user