claude-memory-layer 1.0.51 → 1.0.53

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/dist/cli/index.js CHANGED
@@ -2327,6 +2327,10 @@ var DEFAULT_CONFIG2 = {
2327
2327
  // 5 minutes
2328
2328
  cleanupDays: 7
2329
2329
  };
2330
+ function isRetryableLanceCommitConflict(error) {
2331
+ const normalized = error.toLowerCase();
2332
+ return normalized.includes("lance") && normalized.includes("commit") && normalized.includes("conflict");
2333
+ }
2330
2334
  var VectorOutbox = class {
2331
2335
  constructor(db, config) {
2332
2336
  this.db = db;
@@ -2431,6 +2435,16 @@ var VectorOutbox = class {
2431
2435
  );
2432
2436
  if (rows.length === 0) return;
2433
2437
  const retryCount = rows[0].retry_count;
2438
+ if (isRetryableLanceCommitConflict(error)) {
2439
+ await dbRun(
2440
+ this.db,
2441
+ `UPDATE vector_outbox
2442
+ SET status = 'pending', error = ?, updated_at = ?
2443
+ WHERE job_id = ?`,
2444
+ [error, now, jobId]
2445
+ );
2446
+ return;
2447
+ }
2434
2448
  const newStatus = retryCount >= this.config.maxRetries - 1 ? "failed" : "pending";
2435
2449
  await dbRun(
2436
2450
  this.db,
@@ -4114,6 +4128,7 @@ var SQLiteEventStore = class {
4114
4128
  async getOutboxStats(options = {}) {
4115
4129
  await this.initialize();
4116
4130
  const thresholdMs = Number.isFinite(options.stuckThresholdMs) && (options.stuckThresholdMs ?? 0) >= 0 ? options.stuckThresholdMs : DEFAULT_OUTBOX_STUCK_THRESHOLD_MS;
4131
+ const maxRetries = Number.isFinite(options.maxRetries) && (options.maxRetries ?? 0) > 0 ? options.maxRetries : DEFAULT_OUTBOX_MAX_RETRIES;
4117
4132
  const now = options.now ?? /* @__PURE__ */ new Date();
4118
4133
  const threshold = new Date(now.getTime() - thresholdMs).toISOString();
4119
4134
  const embeddingRows = sqliteAll(
@@ -4131,8 +4146,8 @@ var SQLiteEventStore = class {
4131
4146
  if (!Number.isFinite(time)) return null;
4132
4147
  return Math.max(0, now.getTime() - time);
4133
4148
  };
4134
- const fromRows = (rows, stuckProcessing, oldestProcessingAgeMs) => {
4135
- const out = { pending: 0, processing: 0, failed: 0, total: 0, stuckProcessing, oldestProcessingAgeMs };
4149
+ const fromRows = (rows, stuckProcessing, oldestProcessingAgeMs, retryableFailed, quarantinedFailed) => {
4150
+ const out = { pending: 0, processing: 0, failed: 0, retryableFailed, quarantinedFailed, total: 0, stuckProcessing, oldestProcessingAgeMs };
4136
4151
  for (const row of rows) {
4137
4152
  const key = row.status;
4138
4153
  if (key === "pending" || key === "processing" || key === "failed") {
@@ -4156,6 +4171,22 @@ var SQLiteEventStore = class {
4156
4171
  FROM embedding_outbox
4157
4172
  WHERE status = 'processing'`
4158
4173
  );
4174
+ const embeddingRetryableFailed = sqliteGet(
4175
+ this.db,
4176
+ `SELECT COUNT(*) as count
4177
+ FROM embedding_outbox
4178
+ WHERE status = 'failed'
4179
+ AND retry_count < ?`,
4180
+ [maxRetries]
4181
+ );
4182
+ const embeddingQuarantinedFailed = sqliteGet(
4183
+ this.db,
4184
+ `SELECT COUNT(*) as count
4185
+ FROM embedding_outbox
4186
+ WHERE status = 'failed'
4187
+ AND retry_count >= ?`,
4188
+ [maxRetries]
4189
+ );
4159
4190
  const vectorStuck = sqliteGet(
4160
4191
  this.db,
4161
4192
  `SELECT COUNT(*) as count
@@ -4170,16 +4201,36 @@ var SQLiteEventStore = class {
4170
4201
  FROM vector_outbox
4171
4202
  WHERE status = 'processing'`
4172
4203
  );
4204
+ const vectorRetryableFailed = sqliteGet(
4205
+ this.db,
4206
+ `SELECT COUNT(*) as count
4207
+ FROM vector_outbox
4208
+ WHERE status = 'failed'
4209
+ AND retry_count < ?`,
4210
+ [maxRetries]
4211
+ );
4212
+ const vectorQuarantinedFailed = sqliteGet(
4213
+ this.db,
4214
+ `SELECT COUNT(*) as count
4215
+ FROM vector_outbox
4216
+ WHERE status = 'failed'
4217
+ AND retry_count >= ?`,
4218
+ [maxRetries]
4219
+ );
4173
4220
  return {
4174
4221
  embedding: fromRows(
4175
4222
  embeddingRows,
4176
4223
  Number(embeddingStuck?.count ?? 0),
4177
- processingAgeMs(embeddingOldest?.oldest)
4224
+ processingAgeMs(embeddingOldest?.oldest),
4225
+ Number(embeddingRetryableFailed?.count ?? 0),
4226
+ Number(embeddingQuarantinedFailed?.count ?? 0)
4178
4227
  ),
4179
4228
  vector: fromRows(
4180
4229
  vectorRows,
4181
4230
  Number(vectorStuck?.count ?? 0),
4182
- processingAgeMs(vectorOldest?.oldest)
4231
+ processingAgeMs(vectorOldest?.oldest),
4232
+ Number(vectorRetryableFailed?.count ?? 0),
4233
+ Number(vectorQuarantinedFailed?.count ?? 0)
4183
4234
  )
4184
4235
  };
4185
4236
  }
@@ -18384,6 +18435,8 @@ function summarizeProjectOutbox(outbox) {
18384
18435
  pending: (embedding.pending || 0) + (vector.pending || 0),
18385
18436
  processing: (embedding.processing || 0) + (vector.processing || 0),
18386
18437
  failed: (embedding.failed || 0) + (vector.failed || 0),
18438
+ retryableFailed: (embedding.retryableFailed || 0) + (vector.retryableFailed || 0),
18439
+ quarantinedFailed: (embedding.quarantinedFailed || 0) + (vector.quarantinedFailed || 0),
18387
18440
  stuckProcessing: (embedding.stuckProcessing || 0) + (vector.stuckProcessing || 0)
18388
18441
  };
18389
18442
  }
@@ -18721,8 +18774,10 @@ function aggregateOutbox(outbox) {
18721
18774
  const pending = (outbox.embedding?.pending || 0) + (outbox.vector?.pending || 0);
18722
18775
  const processing = (outbox.embedding?.processing || 0) + (outbox.vector?.processing || 0);
18723
18776
  const failed = (outbox.embedding?.failed || 0) + (outbox.vector?.failed || 0);
18777
+ const retryableFailed = (outbox.embedding?.retryableFailed || 0) + (outbox.vector?.retryableFailed || 0);
18778
+ const quarantinedFailed = (outbox.embedding?.quarantinedFailed || 0) + (outbox.vector?.quarantinedFailed || 0);
18724
18779
  const stuckProcessing = (outbox.embedding?.stuckProcessing || 0) + (outbox.vector?.stuckProcessing || 0);
18725
- return { pending, processing, failed, stuckProcessing };
18780
+ return { pending, processing, failed, retryableFailed, quarantinedFailed, stuckProcessing };
18726
18781
  }
18727
18782
  healthRouter.get("/setup", async (c) => {
18728
18783
  const memoryService = getLightweightServiceFromQuery(c);
@@ -18791,6 +18846,8 @@ healthRouter.get("/", async (c) => {
18791
18846
  const outboxPending = outbox.embedding.pending + outbox.vector.pending;
18792
18847
  const outboxProcessing = outbox.embedding.processing + outbox.vector.processing;
18793
18848
  const outboxFailed = outbox.embedding.failed + outbox.vector.failed;
18849
+ const outboxRetryableFailed = (outbox.embedding.retryableFailed ?? 0) + (outbox.vector.retryableFailed ?? 0);
18850
+ const outboxQuarantinedFailed = (outbox.embedding.quarantinedFailed ?? 0) + (outbox.vector.quarantinedFailed ?? 0);
18794
18851
  const outboxStuckProcessing = outbox.embedding.stuckProcessing + outbox.vector.stuckProcessing;
18795
18852
  const oldestProcessingAgeMs = Math.max(
18796
18853
  outbox.embedding.oldestProcessingAgeMs ?? 0,
@@ -18811,6 +18868,8 @@ healthRouter.get("/", async (c) => {
18811
18868
  pending: outboxPending,
18812
18869
  processing: outboxProcessing,
18813
18870
  failed: outboxFailed,
18871
+ retryableFailed: outboxRetryableFailed,
18872
+ quarantinedFailed: outboxQuarantinedFailed,
18814
18873
  stuckProcessing: outboxStuckProcessing,
18815
18874
  oldestProcessingAgeMs
18816
18875
  }
@@ -20843,38 +20902,65 @@ function resolveVectorStatusCommandOptions(options, cwd = process.cwd()) {
20843
20902
  if (options.project !== void 0 && options.project.trim().length === 0) {
20844
20903
  throw new Error("--project must not be empty");
20845
20904
  }
20846
- return { projectPath: options.project ?? cwd };
20905
+ return { projectPath: options.project ?? cwd, json: options.json === true };
20847
20906
  }
20848
20907
  function formatVectorStatusReport(input) {
20849
- const embedding = normalizeQueue(input.outbox.embedding);
20850
- const vector = normalizeQueue(input.outbox.vector);
20851
- const totals = sumQueues(embedding, vector);
20852
- const status = totals.failed > 0 || totals.stuckProcessing > 0 ? "needs-attention" : "ok";
20853
- const oldestProcessingAge = maxNullable2(embedding.oldestProcessingAgeMs, vector.oldestProcessingAgeMs);
20908
+ const report = buildVectorStatusReport(input);
20909
+ const { embedding, vector, totals } = report.outbox;
20910
+ const oldestProcessingAge = report.oldestProcessingAgeMs;
20854
20911
  const lines = [
20855
20912
  "Vector Outbox Status",
20856
20913
  `Vector count: ${input.stats.vectorCount}`,
20857
20914
  `Total events: ${input.stats.totalEvents}`,
20858
20915
  "",
20859
- "Queue pending processing failed stuck total oldest",
20916
+ "Queue pending processing failed retryable quarantined stuck total oldest",
20860
20917
  formatQueueRow("Embedding", embedding),
20861
20918
  formatQueueRow("Vector", vector),
20862
20919
  formatQueueRow("Total", totals),
20863
20920
  "",
20864
- `Totals: pending=${totals.pending}, processing=${totals.processing}, failed=${totals.failed}, stuck=${totals.stuckProcessing}, total=${totals.total}`,
20921
+ `Totals: pending=${totals.pending}, processing=${totals.processing}, failed=${totals.failed}, retryableFailed=${totals.retryableFailed ?? 0}, quarantinedFailed=${totals.quarantinedFailed ?? 0}, stuck=${totals.stuckProcessing}, total=${totals.total}`,
20865
20922
  `Oldest processing age: ${formatDuration2(oldestProcessingAge)}`,
20866
- `Status: ${status}`
20923
+ `Status: ${report.status}`
20867
20924
  ];
20868
- if (status === "needs-attention") {
20925
+ if (report.recommendedAction === "run-recovery") {
20869
20926
  lines.push("", "Next step: claude-memory-layer process --dry-run-recovery");
20927
+ } else if (report.recommendedAction === "inspect-quarantined") {
20928
+ lines.push("", "Next step: inspect quarantined outbox failures; recovery has no retryable failed rows.");
20870
20929
  }
20871
20930
  return lines.join("\n");
20872
20931
  }
20932
+ function formatVectorStatusJsonReport(input) {
20933
+ return JSON.stringify(buildVectorStatusReport(input), null, 2);
20934
+ }
20935
+ function buildVectorStatusReport(input) {
20936
+ const embedding = normalizeQueue(input.outbox.embedding);
20937
+ const vector = normalizeQueue(input.outbox.vector);
20938
+ const totals = sumQueues(embedding, vector);
20939
+ const status = totals.failed > 0 || totals.stuckProcessing > 0 ? "needs-attention" : "ok";
20940
+ const oldestProcessingAgeMs = maxNullable2(embedding.oldestProcessingAgeMs, vector.oldestProcessingAgeMs);
20941
+ return {
20942
+ storage: {
20943
+ totalEvents: numberOrZero(input.stats.totalEvents),
20944
+ vectorCount: numberOrZero(input.stats.vectorCount)
20945
+ },
20946
+ outbox: { embedding, vector, totals },
20947
+ status,
20948
+ recommendedAction: selectRecommendedAction(totals),
20949
+ oldestProcessingAgeMs
20950
+ };
20951
+ }
20952
+ function selectRecommendedAction(totals) {
20953
+ if ((totals.retryableFailed ?? 0) > 0 || totals.stuckProcessing > 0) return "run-recovery";
20954
+ if ((totals.quarantinedFailed ?? 0) > 0) return "inspect-quarantined";
20955
+ return "none";
20956
+ }
20873
20957
  function normalizeQueue(queue) {
20874
20958
  return {
20875
20959
  pending: numberOrZero(queue.pending),
20876
20960
  processing: numberOrZero(queue.processing),
20877
20961
  failed: numberOrZero(queue.failed),
20962
+ retryableFailed: numberOrZero(queue.retryableFailed),
20963
+ quarantinedFailed: numberOrZero(queue.quarantinedFailed),
20878
20964
  total: numberOrZero(queue.total),
20879
20965
  stuckProcessing: numberOrZero(queue.stuckProcessing),
20880
20966
  oldestProcessingAgeMs: Number.isFinite(queue.oldestProcessingAgeMs ?? Number.NaN) ? queue.oldestProcessingAgeMs : null
@@ -20885,6 +20971,8 @@ function sumQueues(a, b) {
20885
20971
  pending: a.pending + b.pending,
20886
20972
  processing: a.processing + b.processing,
20887
20973
  failed: a.failed + b.failed,
20974
+ retryableFailed: (a.retryableFailed ?? 0) + (b.retryableFailed ?? 0),
20975
+ quarantinedFailed: (a.quarantinedFailed ?? 0) + (b.quarantinedFailed ?? 0),
20888
20976
  stuckProcessing: a.stuckProcessing + b.stuckProcessing,
20889
20977
  total: a.total + b.total,
20890
20978
  oldestProcessingAgeMs: maxNullable2(a.oldestProcessingAgeMs, b.oldestProcessingAgeMs)
@@ -20896,6 +20984,8 @@ function formatQueueRow(label, queue) {
20896
20984
  String(queue.pending).padStart(7),
20897
20985
  String(queue.processing).padStart(11),
20898
20986
  String(queue.failed).padStart(7),
20987
+ String(queue.retryableFailed ?? 0).padStart(9),
20988
+ String(queue.quarantinedFailed ?? 0).padStart(11),
20899
20989
  String(queue.stuckProcessing).padStart(6),
20900
20990
  String(queue.total).padStart(6),
20901
20991
  formatDuration2(queue.oldestProcessingAgeMs).padStart(7)
@@ -20907,7 +20997,8 @@ function maxNullable2(a, b) {
20907
20997
  return Math.max(a, b);
20908
20998
  }
20909
20999
  function numberOrZero(value) {
20910
- return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
21000
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return 0;
21001
+ return Math.floor(value);
20911
21002
  }
20912
21003
  function formatDuration2(ms) {
20913
21004
  if (ms === null) return "none";
@@ -21538,7 +21629,7 @@ async function runOperationCli(action, label) {
21538
21629
  }
21539
21630
  }
21540
21631
  var program = new Command();
21541
- program.name("claude-memory-layer").description("Claude Code Memory Plugin CLI").version("1.0.51");
21632
+ program.name("claude-memory-layer").description("Claude Code Memory Plugin CLI").version("1.0.53");
21542
21633
  program.command("market-context").description("Fetch read-only DART/FRED/Finnhub context with structured MarketContextSnapshot bull/bear/risk/catalyst analysis").option("--company <name>", "Company name for DART fallback search and report subject").option("--dart-corp-code <code>", "Exact DART corp_code for issuer-specific filings").option("--symbol <ticker>", "Listed ticker for Finnhub company profile").option("--providers <list>", "Comma-separated providers: dart,fred,finnhub").option("--fred-series <list>", "Comma-separated FRED series IDs").option("--json", "Print structured JSON including analysis.marketSnapshot").option("--no-snapshot", "Disable MarketContextSnapshot and DART company snapshot analysis").action(async (options) => {
21543
21634
  try {
21544
21635
  await runMarketContextCommand(options);
@@ -21752,7 +21843,7 @@ program.command("stats").description("View memory statistics").option("-p, --pro
21752
21843
  process.exit(1);
21753
21844
  }
21754
21845
  });
21755
- program.command("vector-status").description("Show aggregate vector outbox status").option("-p, --project <path>", "Project path (defaults to cwd)").action(async (options) => {
21846
+ program.command("vector-status").description("Show aggregate vector outbox status").option("-p, --project <path>", "Project path (defaults to cwd)").option("--json", "Print aggregate vector outbox status as JSON for automation").action(async (options) => {
21756
21847
  let service;
21757
21848
  try {
21758
21849
  const vectorOptions = resolveVectorStatusCommandOptions(options);
@@ -21761,7 +21852,8 @@ program.command("vector-status").description("Show aggregate vector outbox statu
21761
21852
  service.getStats(),
21762
21853
  service.getOutboxStats()
21763
21854
  ]);
21764
- console.log(formatVectorStatusReport({ stats, outbox }));
21855
+ const rendered = vectorOptions.json ? formatVectorStatusJsonReport({ stats, outbox }) : formatVectorStatusReport({ stats, outbox });
21856
+ console.log(rendered);
21765
21857
  } catch (error) {
21766
21858
  const message = error instanceof Error && error.message.startsWith("--") ? error.message : "Vector status failed";
21767
21859
  console.error(message);