specmem-hardwicksoftware 3.7.12 → 3.7.14

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.
@@ -47,7 +47,9 @@ function getSpecmemDir() {
47
47
  // Otherwise we're in src/config
48
48
  return path.resolve(currentDir, '..', '..');
49
49
  }
50
- const BOOTSTRAP_PATH = path.join(getSpecmemDir(), 'bootstrap.cjs');
50
+ // Prefer proxy for resilient MCP connections (auto-reconnect on crash)
51
+ const _proxyPath = path.join(getSpecmemDir(), 'mcp-proxy.cjs');
52
+ const BOOTSTRAP_PATH = fs.existsSync(_proxyPath) ? _proxyPath : path.join(getSpecmemDir(), 'bootstrap.cjs');
51
53
  const SOURCE_HOOKS_DIR = path.join(getSpecmemDir(), 'claude-hooks');
52
54
  const SOURCE_COMMANDS_DIR = path.join(getSpecmemDir(), 'commands');
53
55
  // ============================================================================
@@ -97,8 +97,11 @@ function getSpecmemRoot() {
97
97
  // 6. Last resort - return __dirname-based path even without bootstrap
98
98
  return fromThisFile;
99
99
  }
100
- // Find the actual bootstrap file (cjs or js)
100
+ // Find the MCP entry point prefer proxy for resilient connections
101
101
  function findBootstrapPath(root) {
102
+ // Proxy wraps bootstrap.cjs with auto-reconnect on crash
103
+ const proxy = path.join(root, 'mcp-proxy.cjs');
104
+ if (fs.existsSync(proxy)) return proxy;
102
105
  for (const name of ['bootstrap.cjs', 'bootstrap.js']) {
103
106
  const p = path.join(root, name);
104
107
  if (fs.existsSync(p)) return p;
@@ -189,6 +189,13 @@ PROJECT_PATH = os.environ.get('SPECMEM_PROJECT_PATH', 'default')
189
189
 
190
190
  SPECMEM_HOME = os.environ.get('SPECMEM_HOME', os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
191
191
  SPECMEM_RUN_DIR = os.environ.get('SPECMEM_RUN_DIR', os.path.join(SPECMEM_HOME, 'run'))
192
+
193
+ # Bundled model: shipped with the npm package, no download needed
194
+ _SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
195
+ _BUNDLED_MODEL_DIR = os.path.join(_SCRIPT_DIR, 'models', 'all-MiniLM-L6-v2')
196
+ BUNDLED_MODEL_PATH = _BUNDLED_MODEL_DIR if os.path.isfile(os.path.join(_BUNDLED_MODEL_DIR, 'onnx', 'model_quint8_avx2.onnx')) else None
197
+ if BUNDLED_MODEL_PATH:
198
+ print(f"📦 Bundled model found: {BUNDLED_MODEL_PATH}", file=sys.stderr)
192
199
  # Socket directory: {PROJECT}/specmem/sockets/ - matches config.ts expectations
193
200
  # This is the ONLY location config.ts checks for per-project sockets
194
201
  def _get_socket_dir():
@@ -821,7 +828,8 @@ class LayerOffloadingTransformer:
821
828
  """
822
829
 
823
830
  def __init__(self, model_name: str, cache_dir: Path):
824
- self.model_name = model_name
831
+ # Use bundled model if available
832
+ self.model_name = BUNDLED_MODEL_PATH if BUNDLED_MODEL_PATH else model_name
825
833
  self.cache_dir = cache_dir
826
834
  self.tokenizer = None
827
835
  self.model_config = None
@@ -2026,7 +2034,8 @@ class FrankensteinEmbeddings:
2026
2034
  self.ram_guard = RAMGuard()
2027
2035
 
2028
2036
  # Store model name for lazy-loading
2029
- self.base_model = base_model
2037
+ # Use bundled model path if available (no network download needed)
2038
+ self.base_model = BUNDLED_MODEL_PATH if BUNDLED_MODEL_PATH else base_model
2030
2039
 
2031
2040
  # Track request time for idle cleanup
2032
2041
  self.last_request_time = time.time()
@@ -2049,10 +2058,10 @@ class FrankensteinEmbeddings:
2049
2058
  self.dim_config.native_dims = 384 # MiniLM-L6-v2 is always 384
2050
2059
  else:
2051
2060
  # EAGER MODE: Load model immediately (for high-RAM or heavyOps)
2052
- print(f"Loading model: {base_model} ({_BEST_ONNX_FILE})", file=sys.stderr)
2061
+ print(f"Loading model: {self.base_model} ({_BEST_ONNX_FILE})", file=sys.stderr)
2053
2062
  # NOTE: backend='onnx' is REQUIRED for model_kwargs file_name to work
2054
2063
  self.model = SentenceTransformer(
2055
- base_model,
2064
+ self.base_model,
2056
2065
  device='cpu',
2057
2066
  backend='onnx',
2058
2067
  cache_folder=str(self.cache_dir),
@@ -0,0 +1,7 @@
1
+ {
2
+ "word_embedding_dimension": 384,
3
+ "pooling_mode_cls_token": false,
4
+ "pooling_mode_mean_tokens": true,
5
+ "pooling_mode_max_tokens": false,
6
+ "pooling_mode_mean_sqrt_len_tokens": false
7
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "_name_or_path": "nreimers/MiniLM-L6-H384-uncased",
3
+ "architectures": [
4
+ "BertModel"
5
+ ],
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "gradient_checkpointing": false,
8
+ "hidden_act": "gelu",
9
+ "hidden_dropout_prob": 0.1,
10
+ "hidden_size": 384,
11
+ "initializer_range": 0.02,
12
+ "intermediate_size": 1536,
13
+ "layer_norm_eps": 1e-12,
14
+ "max_position_embeddings": 512,
15
+ "model_type": "bert",
16
+ "num_attention_heads": 12,
17
+ "num_hidden_layers": 6,
18
+ "pad_token_id": 0,
19
+ "position_embedding_type": "absolute",
20
+ "transformers_version": "4.8.2",
21
+ "type_vocab_size": 2,
22
+ "use_cache": true,
23
+ "vocab_size": 30522
24
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "__version__": {
3
+ "sentence_transformers": "2.0.0",
4
+ "transformers": "4.6.1",
5
+ "pytorch": "1.8.1"
6
+ }
7
+ }
@@ -0,0 +1,20 @@
1
+ [
2
+ {
3
+ "idx": 0,
4
+ "name": "0",
5
+ "path": "",
6
+ "type": "sentence_transformers.models.Transformer"
7
+ },
8
+ {
9
+ "idx": 1,
10
+ "name": "1",
11
+ "path": "1_Pooling",
12
+ "type": "sentence_transformers.models.Pooling"
13
+ },
14
+ {
15
+ "idx": 2,
16
+ "name": "2",
17
+ "path": "2_Normalize",
18
+ "type": "sentence_transformers.models.Normalize"
19
+ }
20
+ ]
@@ -0,0 +1,4 @@
1
+ {
2
+ "max_seq_length": 256,
3
+ "do_lower_case": false
4
+ }
@@ -0,0 +1 @@
1
+ {"unk_token": "[UNK]", "sep_token": "[SEP]", "pad_token": "[PAD]", "cls_token": "[CLS]", "mask_token": "[MASK]"}