@mclean-capital/neura 2.2.3 → 2.2.5

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/README.md CHANGED
@@ -54,7 +54,7 @@ neura listen # voice chat (mic + speaker, wake-word ready)
54
54
  neura chat # text chat from your terminal
55
55
  ```
56
56
 
57
- After `neura install` completes, core runs as a background OS service — launchd on macOS, systemd on Linux, a Scheduled Task (or Startup folder shim as fallback) on Windows. Say your wake word — by default **"jarvis"** — and Neura activates a voice session. Stop talking for 5 minutes and it drops back to passive listening.
57
+ After `neura install` completes, core runs as a background OS service — launchd on macOS, systemd on Linux, a Scheduled Task (or Startup folder shim as fallback) on Windows. Say your wake word — by default **"neura"** — and Neura activates a voice session. Stop talking for 5 minutes and it drops back to passive listening.
58
58
 
59
59
  ### Windows notes
60
60
 
@@ -50174,7 +50174,7 @@ function loadConfig() {
50174
50174
  voice: process.env.NEURA_VOICE ?? file.voice ?? "eve",
50175
50175
  pgDataPath: process.env.PG_DATA_PATH ?? process.env.DB_PATH ?? file.pgDataPath ?? pgDataPathDefault,
50176
50176
  neuraHome,
50177
- assistantName: process.env.NEURA_ASSISTANT_NAME ?? file.assistantName ?? "jarvis",
50177
+ assistantName: process.env.NEURA_ASSISTANT_NAME ?? file.assistantName ?? "neura",
50178
50178
  retrievalStrategy: process.env.NEURA_RETRIEVAL_STRATEGY ?? file.retrievalStrategy ?? "hybrid",
50179
50179
  authToken: process.env.NEURA_AUTH_TOKEN ?? file.authToken ?? ""
50180
50180
  };
@@ -50186,10 +50186,10 @@ var DEFAULT_TIER_CONFIG = {
50186
50186
  l1Budget: 400,
50187
50187
  l2Budget: 700
50188
50188
  };
50189
- function buildMemoryPrompt(context, tierConfig) {
50190
- const config = tierConfig ?? DEFAULT_TIER_CONFIG;
50189
+ function buildMemoryPrompt(context, options) {
50190
+ const config = options?.tierConfig ?? DEFAULT_TIER_CONFIG;
50191
50191
  const sections = [];
50192
- const l0 = buildL0(context);
50192
+ const l0 = buildL0(context, options?.assistantName);
50193
50193
  sections.push(...trimToTokenBudget(l0, config.l0Budget));
50194
50194
  const l1 = buildL1(context);
50195
50195
  sections.push(...trimToTokenBudget(l1, config.l1Budget));
@@ -50197,8 +50197,12 @@ function buildMemoryPrompt(context, tierConfig) {
50197
50197
  sections.push(...trimToTokenBudget(l2, config.l2Budget));
50198
50198
  return sections.join("\n");
50199
50199
  }
50200
- function buildL0(context) {
50200
+ function buildL0(context, assistantName) {
50201
50201
  const parts = [];
50202
+ if (assistantName) {
50203
+ const displayName = assistantName.charAt(0).toUpperCase() + assistantName.slice(1);
50204
+ parts.push(`Your name is ${displayName}.`);
50205
+ }
50202
50206
  if (context.identity.length > 0) {
50203
50207
  const personality = context.identity.find((e2) => e2.attribute === "base_personality");
50204
50208
  if (personality) parts.push(personality.value);
@@ -68202,18 +68206,20 @@ var MemoryManager = class {
68202
68206
  pipeline;
68203
68207
  reranker;
68204
68208
  strategy;
68209
+ assistantName;
68205
68210
  pendingExtractions = /* @__PURE__ */ new Set();
68206
68211
  onExtractionComplete;
68207
68212
  constructor(options) {
68208
68213
  this.store = options.store;
68209
68214
  this.strategy = options.retrievalStrategy ?? "hybrid";
68215
+ this.assistantName = options.assistantName;
68210
68216
  this.pipeline = new ExtractionPipeline(options.googleApiKey);
68211
68217
  this.reranker = new Reranker(options.googleApiKey);
68212
68218
  this.onExtractionComplete = options.onExtractionComplete;
68213
68219
  }
68214
68220
  async buildSystemPrompt() {
68215
68221
  const context = await this.store.getMemoryContext({ maxTokens: 2e3 });
68216
- return buildMemoryPrompt(context);
68222
+ return buildMemoryPrompt(context, { assistantName: this.assistantName });
68217
68223
  }
68218
68224
  async queueExtraction(sessionId) {
68219
68225
  const transcript = await this.store.getTranscript(sessionId);
@@ -68740,7 +68746,8 @@ async function initServices() {
68740
68746
  store,
68741
68747
  googleApiKey: config.googleApiKey,
68742
68748
  onExtractionComplete: () => backupService?.backup() ?? Promise.resolve(),
68743
- retrievalStrategy: config.retrievalStrategy
68749
+ retrievalStrategy: config.retrievalStrategy,
68750
+ assistantName: config.assistantName
68744
68751
  });
68745
68752
  log6.info("memory manager initialized");
68746
68753
  }
@@ -69982,7 +69989,7 @@ var FRAME_SIZE_16K = 1280;
69982
69989
  var INFERENCE_STRIDE = 4;
69983
69990
  var ENERGY_THRESHOLD = 1e-3;
69984
69991
  var DEBOUNCE_MS = 2e3;
69985
- var MAX_REPLAY_CHUNKS = 12;
69992
+ var MAX_REPLAY_BYTES = 24e3 * 2 * 4;
69986
69993
  var OnnxWakeDetector = class _OnnxWakeDetector {
69987
69994
  config;
69988
69995
  threshold;
@@ -70002,8 +70009,11 @@ var OnnxWakeDetector = class _OnnxWakeDetector {
70002
70009
  totalSamplesWritten = 0;
70003
70010
  // Partial frame accumulator (resampled 16kHz samples)
70004
70011
  accumulator = new Float32Array(0);
70005
- // Replay buffer: original base64 chunks for Grok
70012
+ // Replay buffer: original base64 chunks for Grok, evicted by total byte
70013
+ // count (not chunk count) so the buffer duration is consistent regardless
70014
+ // of the mic's chunk size.
70006
70015
  replayChunks = [];
70016
+ replayBytes = 0;
70007
70017
  // Inference gating
70008
70018
  frameCounter = 0;
70009
70019
  lastDetectionTime = 0;
@@ -70062,8 +70072,10 @@ var OnnxWakeDetector = class _OnnxWakeDetector {
70062
70072
  }
70063
70073
  const resampled = resample24kTo16k(float32);
70064
70074
  this.replayChunks.push(base64Pcm);
70065
- if (this.replayChunks.length > MAX_REPLAY_CHUNKS) {
70066
- this.replayChunks.shift();
70075
+ this.replayBytes += raw.byteLength;
70076
+ while (this.replayBytes > MAX_REPLAY_BYTES && this.replayChunks.length > 1) {
70077
+ const evicted = this.replayChunks.shift();
70078
+ this.replayBytes -= Buffer.from(evicted, "base64").byteLength;
70067
70079
  }
70068
70080
  const combined = new Float32Array(this.accumulator.length + resampled.length);
70069
70081
  combined.set(this.accumulator);
@@ -70104,6 +70116,7 @@ var OnnxWakeDetector = class _OnnxWakeDetector {
70104
70116
  this.closed = true;
70105
70117
  this.accumulator = new Float32Array(0);
70106
70118
  this.replayChunks.length = 0;
70119
+ this.replayBytes = 0;
70107
70120
  }
70108
70121
  /**
70109
70122
  * Clear all buffered audio and inference state without releasing the
@@ -70130,6 +70143,7 @@ var OnnxWakeDetector = class _OnnxWakeDetector {
70130
70143
  this.writePos = 0;
70131
70144
  this.totalSamplesWritten = 0;
70132
70145
  this.replayChunks.length = 0;
70146
+ this.replayBytes = 0;
70133
70147
  this.frameCounter = 0;
70134
70148
  this.lastDetectionTime = 0;
70135
70149
  }
@@ -70152,6 +70166,7 @@ var OnnxWakeDetector = class _OnnxWakeDetector {
70152
70166
  this.lastDetectionTime = Date.now();
70153
70167
  const chunks = [...this.replayChunks];
70154
70168
  this.replayChunks.length = 0;
70169
+ this.replayBytes = 0;
70155
70170
  this.config.onWake(chunks);
70156
70171
  }
70157
70172
  } catch (err) {