codemem 0.44.0-alpha.1 → 0.44.0-beta.1

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
@@ -7,24 +7,27 @@ This is the published npm package for the `codemem` CLI.
7
7
 
8
8
  ## Install
9
9
 
10
- **Prerequisites:** Node.js 24.15+ and npm (or pnpm). Native database support
10
+ **Prerequisites:** Node.js 24.15+ and npm. Native database support
11
11
  covers macOS x64/arm64, Linux x64/arm64 (glibc 2.34+ or musl), and Windows x64.
12
12
  32-bit targets, including Linux armv7, are not supported.
13
13
 
14
14
  On Linux, skip the unused ONNX Runtime GPU provider download:
15
15
 
16
16
  ```bash
17
- env ONNXRUNTIME_NODE_INSTALL=skip npm install -g codemem @codemem/embeddings
17
+ env ONNXRUNTIME_NODE_INSTALL=skip npm install -g codemem
18
18
  ```
19
19
 
20
20
  On Apple silicon macOS and Windows:
21
21
 
22
22
  ```bash
23
- npm install -g codemem @codemem/embeddings
23
+ npm install -g codemem
24
24
  ```
25
25
 
26
- The embedding package enables semantic retrieval. Installing only `codemem` keeps
27
- the CLI functional with FTS5 keyword retrieval.
26
+ The CLI installs its matching embedding runtime by default. For a smaller
27
+ keyword-only install, use `npm install -g codemem --omit=optional` and set
28
+ `CODEMEM_EMBEDDING_DISABLED=1` in every Codemem process. The flag is required
29
+ because npm also omits sqlite-vec's optional platform package; the CLI then
30
+ remains functional with FTS5.
28
31
 
29
32
  Intel x64 Macs have no ONNX Runtime 1.24.3 artifact and remain on FTS5 retrieval.
30
33
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { DEDUP_KEY_BACKFILL_JOB, DEFAULT_COORDINATOR_DB_PATH, DedupKeyBackfillRunner, DeviceIdentityError, MUTATING_TOOL_NAMES, MemoryStore, ObserverClient, PROMPT_TRANSPORT_PROTOCOL_RANGE, REF_BACKFILL_JOB, RawEventIngestValidationError, RawEventSweeper, RefBackfillRunner, SCOPE_BACKFILL_JOB, SESSION_CONTEXT_BACKFILL_JOB, SUMMARY_DEDUP_BACKFILL_JOB, ScopeBackfillRunner, SessionContextBackfillRunner, SummaryDedupBackfillRunner, SyncRetentionRunner, TRUSTED_HOOK_MAPPER_OPTIONS, VERSION, VectorModelMigrationRunner, aiBackfillStructuredContent, applyBootstrapSnapshot, applyDistillRule, arePromptTransportProtocolRangesCompatible, backfillMemoryDedupKeys, backfillNarrativeFromBody, backfillTagsText, backfillVectors, buildBaseUrl, buildDirectPeerAuthHeaders, buildDistillReport, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, buildViewerIdentityTarget, classifyPromptTransportFailure, clonePromptPackAttempt, collectOperationalStatus, compareMemoryRoleReports, connect, connectReadOnly, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnrollDeviceAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorUpdateScopeAction, createBetterSqliteCoordinatorApp, deactivateLowSignalMemories, deactivateLowSignalObservations, dedupNearDuplicateMemories, detectInstallKind, draftDistillRule, ensureDeviceIdentity, ensureSchemaBootstrapped, estimateExtractionModelCost, exportMemories, extractApplyPatchPaths, fetchAllSnapshotPages, fingerprintPublicKey, flushRawEvents, formatHostPort, getAttributionDiagnostics, getExtractionBenchmarkProfile, getExtractionModelPricing, getInjectionEvalScenarioPack, getInjectionEvalScenarioPrompts, getMaintenanceJob, getMemoryArtifactReport, getMemoryRoleReport, getRawEventRelinkPlan, getRawEventRelinkReport, getRawEventStatus, getSemanticIndexDiagnostics, getSessionExtractionEval, getSessionExtractionEvalScenario, getUpdateStatus, getWorkspaceCodememConfigPath, hasPendingDedupKeyBackfill, hasPendingRefBackfill, hasPendingScopeBackfill, hasPendingSessionContextBackfill, hasPendingSummaryDedupBackfill, hasUnsyncedSharedMemoryChanges, importMemories, ingestRawEvents, initDatabase, isEmbeddingDisabled, isStableReleaseVersion, judgeDistillReport, listMaintenanceJobs, listPerPeerScopeSyncState, listRetentionScopeIds, loadObserverConfig, loadPublicKey, loadSqliteVec, mdnsEnabled, normalizePromptTransportProtocolRange, planReplicationOpsAgePrune, probeCodememViewerLiveness, probeCodememViewerLiveness as probeCodememViewerLiveness$1, projectMatchesFilter, promptPackArtifactFingerprint, pruneReplicationOpsUntilCaughtUp, rawEventsGate, readCodememConfigFile, readCodememConfigFileAtPath, readCoordinatorSyncConfig, readImportPayload, recordPromptPackArtifacts, recordPromptPackTerminal, recordRetrievalSurface, renderUnifiedDiff, replayBatchExtraction, replayBatchExtractionWithTierRouting, requestJson, resolveCodememConfigPath, resolveDbPath, resolveHookProject, resolveProject, resolveProjectRoot, resolveRetrievalSession, retryRawEventFailures, runSyncDaemon, runSyncPass, scanSecretsRetroactive, schema, scoreExtractionBenchmarkOutput, setPeerProjectFilter, stripJsonComments, stripTrailingCommas, syncPassPreflight, tryUpdateRetrievalDelivery, updatePeerAddresses, vacuumDatabase, viewerUrl, writeCodememConfigFile } from "@codemem/core";
2
+ import { DEDUP_KEY_BACKFILL_JOB, DEFAULT_COORDINATOR_DB_PATH, DedupKeyBackfillRunner, DeviceIdentityError, MUTATING_TOOL_NAMES, MemoryStore, ObserverClient, PROMPT_TRANSPORT_PROTOCOL_RANGE, REF_BACKFILL_JOB, RawEventIngestValidationError, RawEventSweeper, RefBackfillRunner, SCOPE_BACKFILL_JOB, SESSION_CONTEXT_BACKFILL_JOB, SUMMARY_DEDUP_BACKFILL_JOB, ScopeBackfillRunner, SessionContextBackfillRunner, SummaryDedupBackfillRunner, SyncRetentionRunner, TRUSTED_HOOK_MAPPER_OPTIONS, VERSION, VectorModelMigrationRunner, aiBackfillStructuredContent, applyBootstrapSnapshot, applyDistillRule, arePromptTransportProtocolRangesCompatible, backfillMemoryDedupKeys, backfillNarrativeFromBody, backfillTagsText, backfillVectors, buildBaseUrl, buildDirectPeerAuthHeaders, buildDistillReport, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, buildViewerIdentityTarget, classifyPromptTransportFailure, clonePromptPackAttempt, collectOperationalStatus, compareMemoryRoleReports, connect, connectReadOnly, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnrollDeviceAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorUpdateScopeAction, createBetterSqliteCoordinatorApp, deactivateLowSignalMemories, deactivateLowSignalObservations, dedupNearDuplicateMemories, detectInstallKind, draftDistillRule, ensureDeviceIdentity, ensureSchemaBootstrapped, estimateExtractionModelCost, exportMemories, extractApplyPatchPaths, fetchAllSnapshotPages, fingerprintPublicKey, flushRawEvents, formatHostPort, getAttributionDiagnostics, getExtractionBenchmarkProfile, getExtractionModelPricing, getInjectionEvalScenarioPack, getInjectionEvalScenarioPrompts, getMaintenanceJob, getMemoryArtifactReport, getMemoryRoleReport, getRawEventRelinkPlan, getRawEventRelinkReport, getRawEventStatus, getSemanticIndexDiagnostics, getSessionExtractionEval, getSessionExtractionEvalScenario, getUpdateStatus, getWorkspaceCodememConfigPath, hasPendingDedupKeyBackfill, hasPendingRefBackfill, hasPendingScopeBackfill, hasPendingSessionContextBackfill, hasPendingSummaryDedupBackfill, hasUnsyncedSharedMemoryChanges, importMemories, ingestRawEvents, initDatabase, isEmbeddingDisabled, isReleaseVersionForChannel, judgeDistillReport, listMaintenanceJobs, listPerPeerScopeSyncState, listRetentionScopeIds, loadObserverConfig, loadPublicKey, loadSqliteVec, mdnsEnabled, normalizePromptTransportProtocolRange, planReplicationOpsAgePrune, probeCodememViewerLiveness, probeCodememViewerLiveness as probeCodememViewerLiveness$1, probeRequiredNativeRuntime, projectMatchesFilter, promptPackArtifactFingerprint, pruneReplicationOpsUntilCaughtUp, rawEventsGate, readCodememConfigFile, readCodememConfigFileAtPath, readCoordinatorSyncConfig, readImportPayload, recordPromptPackArtifacts, recordPromptPackTerminal, recordRetrievalSurface, renderUnifiedDiff, replayBatchExtraction, replayBatchExtractionWithTierRouting, requestJson, resolveCodememConfigPath, resolveDbPath, resolveHookProject, resolveProject, resolveProjectRoot, resolveRetrievalSession, retryRawEventFailures, runSyncDaemon, runSyncPass, scanSecretsRetroactive, schema, scoreExtractionBenchmarkOutput, setPeerProjectFilter, stripJsonComments, stripTrailingCommas, syncPassPreflight, tryUpdateRetrievalDelivery, updatePeerAddresses, vacuumDatabase, viewerUrl, writeCodememConfigFile } from "@codemem/core";
3
3
  import { Command, Option } from "commander";
4
4
  import omelette from "omelette";
5
5
  import { randomInt, randomUUID } from "node:crypto";
@@ -4397,7 +4397,7 @@ function startMaintenanceWorkerRuntime(options = {}) {
4397
4397
  dbPath,
4398
4398
  signal: options.signal,
4399
4399
  batchSize: 10,
4400
- idleIntervalMs: 5e3
4400
+ idleIntervalMs: 6e4
4401
4401
  }));
4402
4402
  runners.push(createSequentialBackfillCoordinator(store, [
4403
4403
  {
@@ -6460,6 +6460,51 @@ function sqliteVecFailureDiagnostics(error, dbPath) {
6460
6460
  `error=${message}`
6461
6461
  ];
6462
6462
  }
6463
+ function requiredNativeRuntimeFailureDiagnostics(error, context = {
6464
+ version: VERSION,
6465
+ nodeVersion: process.version,
6466
+ platform: process.platform,
6467
+ arch: process.arch
6468
+ }) {
6469
+ const detail = error instanceof Error ? error.message : String(error);
6470
+ return [
6471
+ "Required SQLite native binding is unavailable.",
6472
+ `Runtime: Node ${context.nodeVersion} on ${context.platform}/${context.arch}.`,
6473
+ `Details: ${detail}`,
6474
+ `Reinstall this exact codemem version: npm install -g codemem@${context.version}`,
6475
+ "Use Node 24.15+ on a supported 64-bit macOS, Linux, or Windows target; see the native install matrix for current platform coverage.",
6476
+ "This required better-sqlite3 failure is separate from optional sqlite-vec loading, which can fall back to lexical search."
6477
+ ];
6478
+ }
6479
+ async function preflightServeNativeRuntime(invocation, dependencies = {
6480
+ isPortOpen,
6481
+ probe: probeRequiredNativeRuntime
6482
+ }) {
6483
+ if (invocation.mode === "start" && await dependencies.isPortOpen(invocation.host, invocation.port)) return { state: "already_running" };
6484
+ try {
6485
+ dependencies.probe();
6486
+ return { state: "ready" };
6487
+ } catch (error) {
6488
+ return {
6489
+ state: "unavailable",
6490
+ diagnostics: requiredNativeRuntimeFailureDiagnostics(error)
6491
+ };
6492
+ }
6493
+ }
6494
+ async function nativeRuntimeAllowsServeStart(invocation) {
6495
+ if (invocation.mode !== "start" && invocation.mode !== "restart") return true;
6496
+ const preflight = await preflightServeNativeRuntime(invocation);
6497
+ if (preflight.state === "already_running") {
6498
+ p.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);
6499
+ if (!invocation.background) process.exitCode = 1;
6500
+ return false;
6501
+ }
6502
+ if (preflight.state === "ready") return true;
6503
+ p.intro("codemem viewer");
6504
+ for (const line of preflight.diagnostics) p.log.error(line);
6505
+ process.exitCode = 1;
6506
+ return false;
6507
+ }
6463
6508
  async function runServeCoordinatorMaintenance(store, dependencies) {
6464
6509
  const projectShares = await dependencies.advancePendingProjectShares(store, { limit: 3 });
6465
6510
  const coordinatorEnrollment = await dependencies.reconcileConfiguredCoordinatorEnrollment(store);
@@ -6518,11 +6563,11 @@ async function startForegroundViewer(invocation) {
6518
6563
  if (invocation.dbPath) process.env.CODEMEM_DB = invocation.dbPath;
6519
6564
  if (invocation.configPath) process.env.CODEMEM_CONFIG = invocation.configPath;
6520
6565
  warnIfViewerExposed(invocation.host, invocation.port);
6521
- if (await isPortOpen(invocation.host, invocation.port)) {
6522
- p.log.warn(`Viewer already running at http://${invocation.host}:${invocation.port}`);
6523
- process.exitCode = 1;
6524
- return;
6525
- }
6566
+ const dbPath = resolveDbPath(invocation.dbPath ?? void 0);
6567
+ if (!await terminateTrustedMaintenanceWorker(dbPath, {
6568
+ gracefulMs: 1e3,
6569
+ forceMs: 5e3
6570
+ })) p.log.warn("Existing maintenance worker is not trusted or did not stop; starting viewer anyway");
6526
6571
  const preparedDb = prepareViewerDatabase(invocation.dbPath);
6527
6572
  const observer = new ObserverClient();
6528
6573
  let store;
@@ -6543,11 +6588,6 @@ async function startForegroundViewer(invocation) {
6543
6588
  const config = invocation.configPath ? readCodememConfigFileAtPath(invocation.configPath) : readCodememConfigFile();
6544
6589
  const syncConfig = readCoordinatorSyncConfig(config);
6545
6590
  const syncEnabled = syncConfig.syncEnabled;
6546
- const dbPath = resolveDbPath(invocation.dbPath ?? void 0);
6547
- if (!await terminateTrustedMaintenanceWorker(dbPath, {
6548
- gracefulMs: 1e3,
6549
- forceMs: 5e3
6550
- })) p.log.warn("Existing maintenance worker is not trusted or did not stop; starting viewer anyway");
6551
6591
  const syncRuntimeStatus = {
6552
6592
  phase: syncEnabled ? "starting" : "disabled",
6553
6593
  detail: syncEnabled ? "Waiting for viewer startup to finish" : "Sync is disabled"
@@ -6683,7 +6723,10 @@ async function startForegroundViewer(invocation) {
6683
6723
  shutdown();
6684
6724
  });
6685
6725
  }
6686
- async function runServeInvocation(invocation) {
6726
+ async function runServeInvocation(invocation, dependencies = {
6727
+ nativeRuntimeAllowsServeStart,
6728
+ stopExistingViewer
6729
+ }) {
6687
6730
  const dbPath = resolveDbPath(invocation.dbPath ?? void 0);
6688
6731
  const runtimeConflict = await findRuntimeViewerConflict(dbPath, {
6689
6732
  host: invocation.host,
@@ -6696,8 +6739,9 @@ async function runServeInvocation(invocation) {
6696
6739
  process.exitCode = 1;
6697
6740
  return;
6698
6741
  }
6742
+ if (!await dependencies.nativeRuntimeAllowsServeStart(invocation)) return;
6699
6743
  if (invocation.mode === "stop" || invocation.mode === "restart") {
6700
- const result = await stopExistingViewer(dbPath, {
6744
+ const result = await dependencies.stopExistingViewer(dbPath, {
6701
6745
  host: invocation.host,
6702
6746
  port: invocation.port
6703
6747
  });
@@ -7337,7 +7381,7 @@ function installCodex(force) {
7337
7381
  }
7338
7382
  if (codememOnPath(true)) p.log.info("Codex hooks will call `codemem` directly (found on PATH).");
7339
7383
  else {
7340
- const globalInstallCommand = process.platform === "linux" ? "env ONNXRUNTIME_NODE_INSTALL=skip npm install -g codemem @codemem/embeddings" : "npm install -g codemem @codemem/embeddings";
7384
+ const globalInstallCommand = process.platform === "linux" ? "env ONNXRUNTIME_NODE_INSTALL=skip npm install -g codemem" : "npm install -g codemem";
7341
7385
  p.log.info(`\`codemem\` is not on PATH, so Codex hooks will run via \`npx -y --package codemem --package @codemem/embeddings codemem\` (works without a global install). For lower hook latency: ${globalInstallCommand}`);
7342
7386
  }
7343
7387
  let ok = true;
@@ -8970,10 +9014,10 @@ function renderStatusWarning(error) {
8970
9014
  function renderHumanStatus(status) {
8971
9015
  const warning = renderStatusWarning(status.error);
8972
9016
  if (status.update_available) return `Update available${cacheQualifier(status.stale)}: ${status.current_version} → ${status.latest_version}. ${status.recommended_action}${warning}`;
8973
- if (!isStableReleaseVersion(status.current_version)) return `Unable to compare current version ${status.current_version} with ${status.latest_version}. ${status.recommended_action}${warning}`;
9017
+ if (!status.channel || !isReleaseVersionForChannel(status.current_version, status.channel)) return `Unable to compare current version ${status.current_version} with ${status.latest_version}. ${status.recommended_action}${warning}`;
8974
9018
  return `${status.current_version} is up to date${cacheQualifier(status.stale)}.${warning}`;
8975
9019
  }
8976
- var checkCommand = addJsonOption(new Command("check").description("Check for a newer stable codemem release")).addOption(new Option("-r, --refresh", "bypass the six-hour release cache")).configureHelp(helpStyle).action(async (options) => {
9020
+ var checkCommand = addJsonOption(new Command("check").description("Check for a newer codemem release on the installed channel")).addOption(new Option("-r, --refresh", "bypass the six-hour release cache")).configureHelp(helpStyle).action(async (options) => {
8977
9021
  try {
8978
9022
  const installKind = detectInstallKind({
8979
9023
  entryPath: process.argv[1] ?? "",
@@ -9037,8 +9081,8 @@ async function installUpdate(options) {
9037
9081
  return;
9038
9082
  }
9039
9083
  const targetVersion = status.latest_version;
9040
- if (!isStableReleaseVersion(targetVersion)) {
9041
- failInstall(options, "update_install_refused", "release version is not a stable semantic version");
9084
+ if (!status.channel || !isReleaseVersionForChannel(targetVersion, status.channel)) {
9085
+ failInstall(options, "update_install_refused", "release version does not match the installed channel");
9042
9086
  return;
9043
9087
  }
9044
9088
  releaseInstallLock = await acquireInstallLock();
@@ -9076,7 +9120,7 @@ async function installUpdate(options) {
9076
9120
  await releaseInstallLock?.();
9077
9121
  }
9078
9122
  }
9079
- var installCommand = addJsonOption(new Command("install").description("Install an eligible stable codemem update")).configureHelp(helpStyle).action(installUpdate);
9123
+ var installCommand = addJsonOption(new Command("install").description("Install an eligible codemem update on the installed channel")).configureHelp(helpStyle).action(installUpdate);
9080
9124
  var updateCommand = new Command("update").description("Inspect and manage codemem updates").enablePositionalOptions().configureHelp(helpStyle).addCommand(checkCommand).addCommand(installCommand);
9081
9125
  //#endregion
9082
9126
  //#region src/commands/version.ts