codemem 0.45.0-rc.2 → 0.46.0-alpha.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/dist/index.js +159 -50
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { ContextOnlyReplayError, DEDUP_KEY_BACKFILL_JOB, DEFAULT_COORDINATOR_DB_PATH, DedupKeyBackfillRunner, DeviceIdentityError, EXTRACTION_BENCHMARK_QUALITY_WEIGHTS, MUTATING_TOOL_NAMES, MemoryStore, ObserverClient, ObserverOutputError, ObserverOutputTransportError, 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, extractionReplayObserverIdentity, 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, isAutomaticRecallMeasurement, isEmbeddingDisabled, isExplicitUpdateInstallEligible, 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, recordAutomaticRecall, recordPromptPackArtifacts, recordPromptPackTerminal, recordRetrievalSurface, renderUnifiedDiff, replayBatchExtraction, replayBatchExtractionWithTierRouting, requestJson, resolveCodememConfigPath, resolveComparablePath, resolveDbPath, resolveHookProject, resolveProject, resolveProjectRoot, resolveRetrievalSession, retryRawEventFailures, runSyncDaemon, runSyncPass, scanSecretsRetroactive, schema, scoreExtractionBenchmarkOutput, setPeerProjectFilter, stripJsonComments, stripTrailingCommas, syncPassPreflight, tryUpdateRetrievalDelivery, updatePeerAddresses, vacuumDatabase, viewerUrl
|
|
2
|
+
import { ContextOnlyReplayError, DEDUP_KEY_BACKFILL_JOB, DEFAULT_COORDINATOR_DB_PATH, DedupKeyBackfillRunner, DeviceIdentityError, EXTRACTION_BENCHMARK_QUALITY_WEIGHTS, MUTATING_TOOL_NAMES, MemoryStore, ObserverClient, ObserverOutputError, ObserverOutputTransportError, 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, extractionReplayObserverIdentity, fetchAllSnapshotPages, fingerprintPublicKey, flushRawEvents, formatHostPort, getAttributionDiagnostics, getCodememConfigPath, getExtractionBenchmarkProfile, getExtractionModelPricing, getInjectionEvalScenarioPack, getInjectionEvalScenarioPrompts, getMaintenanceJob, getMemoryArtifactReport, getMemoryRoleReport, getRawEventRelinkPlan, getRawEventRelinkReport, getRawEventStatus, getSemanticIndexDiagnostics, getSessionExtractionEval, getSessionExtractionEvalScenario, getUpdateStatus, getWorkspaceCodememConfigPath, hasPendingDedupKeyBackfill, hasPendingRefBackfill, hasPendingScopeBackfill, hasPendingSessionContextBackfill, hasPendingSummaryDedupBackfill, hasUnsyncedSharedMemoryChanges, importMemories, ingestRawEvents, initDatabase, isAutomaticRecallMeasurement, isEmbeddingDisabled, isExplicitUpdateInstallEligible, isReleaseVersionForChannel, judgeDistillReport, listMaintenanceJobs, listPerPeerScopeSyncState, listRetentionScopeIds, loadObserverConfig, loadPublicKey, loadSqliteVec, mdnsEnabled, mutateCodememConfigFile, normalizePromptTransportProtocolRange, observerBaseUrlForProviderOverride, planReplicationOpsAgePrune, probeCodememViewerLiveness, probeCodememViewerLiveness as probeCodememViewerLiveness$1, probeRequiredNativeRuntime, projectMatchesFilter, promptPackArtifactFingerprint, pruneReplicationOpsUntilCaughtUp, rawEventsGate, readCodememConfigFile, readCodememConfigFileAtPath, readCoordinatorSyncConfig, readImportPayload, recordAutomaticRecall, recordPromptPackArtifacts, recordPromptPackTerminal, recordRetrievalSurface, renderUnifiedDiff, replayBatchExtraction, replayBatchExtractionWithTierRouting, requestJson, resolveCodememConfigPath, resolveComparablePath, resolveDbPath, resolveHookProject, resolveProject, resolveProjectRoot, resolveRetrievalSession, retryRawEventFailures, runSyncDaemon, runSyncPass, scanSecretsRetroactive, schema, scoreExtractionBenchmarkOutput, setPeerProjectFilter, stripJsonComments, stripTrailingCommas, syncPassPreflight, tryUpdateRetrievalDelivery, updatePeerAddresses, vacuumDatabase, viewerUrl } from "@codemem/core";
|
|
3
3
|
import { Command, Option } from "commander";
|
|
4
4
|
import omelette from "omelette";
|
|
5
5
|
import { randomInt, randomUUID } from "node:crypto";
|
|
@@ -2343,7 +2343,6 @@ function runWorkspaceConfigCommand(opts) {
|
|
|
2343
2343
|
const workspaceId = opts.workspaceId;
|
|
2344
2344
|
if (!workspaceId) throw new Error("workspace-id is required");
|
|
2345
2345
|
const configPath = getWorkspaceCodememConfigPath(workspaceId);
|
|
2346
|
-
const existingConfig = existsSync(configPath) ? readCodememConfigFileAtPath(configPath) : readCodememConfigFile();
|
|
2347
2346
|
const patch = buildWorkspaceConfigPatch({
|
|
2348
2347
|
workspaceId,
|
|
2349
2348
|
syncEnabled: opts.enableSync ? true : opts.disableSync ? false : void 0,
|
|
@@ -2355,10 +2354,11 @@ function runWorkspaceConfigCommand(opts) {
|
|
|
2355
2354
|
json: opts.json
|
|
2356
2355
|
});
|
|
2357
2356
|
if (Object.keys(patch).length === 0) throw new Error("Provide at least one config field to update");
|
|
2358
|
-
const
|
|
2357
|
+
const result = mutateCodememConfigFile((existingConfig) => mergeWorkspaceConfig(existingConfig, patch), configPath, { fallbackReadPath: getCodememConfigPath() });
|
|
2358
|
+
const nextConfig = result.data;
|
|
2359
2359
|
return {
|
|
2360
2360
|
workspace_id: workspaceId,
|
|
2361
|
-
config_path:
|
|
2361
|
+
config_path: result.path,
|
|
2362
2362
|
updated_keys: Object.keys(patch).sort(),
|
|
2363
2363
|
config: nextConfig
|
|
2364
2364
|
};
|
|
@@ -4187,6 +4187,21 @@ var enqueueCmd = new Command("enqueue-raw-event").configureHelp(helpStyle).descr
|
|
|
4187
4187
|
addDbOption(enqueueCmd);
|
|
4188
4188
|
var enqueueRawEventCommand = enqueueCmd.action((opts) => runEnqueueRawEvent(opts));
|
|
4189
4189
|
//#endregion
|
|
4190
|
+
//#region src/top-level-alias.ts
|
|
4191
|
+
/**
|
|
4192
|
+
* True when the CLI process was invoked through the named top-level
|
|
4193
|
+
* compatibility alias (first non-flag token of the real argv). Forwarding
|
|
4194
|
+
* wrappers such as `memory export` re-parse the alias command with synthetic
|
|
4195
|
+
* argv, so this stays false for canonical invocations.
|
|
4196
|
+
*/
|
|
4197
|
+
function invokedAsTopLevelAlias(name, argv = process.argv.slice(2)) {
|
|
4198
|
+
for (const token of argv) {
|
|
4199
|
+
if (token === "--") return false;
|
|
4200
|
+
if (!token.startsWith("-")) return token === name;
|
|
4201
|
+
}
|
|
4202
|
+
return false;
|
|
4203
|
+
}
|
|
4204
|
+
//#endregion
|
|
4190
4205
|
//#region src/commands/export-memories.ts
|
|
4191
4206
|
function expandUserPath(value) {
|
|
4192
4207
|
return value.startsWith("~/") ? join(homedir(), value.slice(2)) : value;
|
|
@@ -5395,6 +5410,13 @@ function summarizeExtractionBenchmarkAttempts(attempts, batches) {
|
|
|
5395
5410
|
})
|
|
5396
5411
|
};
|
|
5397
5412
|
}
|
|
5413
|
+
function cliObserverProviderOverride(cfg, providerFlag) {
|
|
5414
|
+
const observerProvider = providerFlag?.trim() || cfg.observerProvider;
|
|
5415
|
+
return {
|
|
5416
|
+
observerProvider,
|
|
5417
|
+
observerBaseUrl: observerBaseUrlForProviderOverride(cfg, observerProvider || "")
|
|
5418
|
+
};
|
|
5419
|
+
}
|
|
5398
5420
|
function createMemoryExtractionBenchmarkCommand() {
|
|
5399
5421
|
const cmd = new Command("extraction-benchmark").configureHelp(helpStyle).description("Run the formal extraction replay benchmark set and print a cost/quality scoreboard").requiredOption("--benchmark <id>", "benchmark profile id").option("--observer-provider <provider>", "override observer provider for this benchmark run").option("--observer-model <model>", "override observer model for this benchmark run").option("--observer-tier-routing", "use replay-only benchmark-backed observer tier routing").option("--openai-responses", "use OpenAI Responses API for this benchmark run").option("--reasoning-effort <level>", "set OpenAI reasoning.effort for this benchmark run (responses path)").option("--reasoning-summary <mode>", "set OpenAI reasoning.summary for this benchmark run (responses path)").option("--max-output-tokens <n>", "override OpenAI max_output_tokens for this benchmark run (responses path)").option("--observer-temperature <value>", "override observer temperature for this benchmark run").option("--transcript-budget <chars>", "override replay transcript budget in characters for this benchmark run").option("--repetitions <n>", "run every benchmark batch 1-10 times to measure model stability", "1");
|
|
5400
5422
|
addDbOption(cmd);
|
|
@@ -5423,7 +5445,7 @@ function createMemoryExtractionBenchmarkCommand() {
|
|
|
5423
5445
|
const observerConfig = loadObserverConfig();
|
|
5424
5446
|
const observerConfigWithOverrides = {
|
|
5425
5447
|
...observerConfig,
|
|
5426
|
-
|
|
5448
|
+
...cliObserverProviderOverride(observerConfig, opts.observerProvider),
|
|
5427
5449
|
observerModel: opts.observerModel?.trim() || observerConfig.observerModel,
|
|
5428
5450
|
observerTemperature: observerTemperature ?? observerConfig.observerTemperature,
|
|
5429
5451
|
observerOpenAIUseResponses: resolveOpenAIResponsesOverride(opts.openaiResponses, observerConfig.observerOpenAIUseResponses),
|
|
@@ -6792,6 +6814,19 @@ async function nativeRuntimeAllowsServeStart(invocation) {
|
|
|
6792
6814
|
process.exitCode = 1;
|
|
6793
6815
|
return false;
|
|
6794
6816
|
}
|
|
6817
|
+
function createServeCoordinatorMaintenanceDependencies(server) {
|
|
6818
|
+
return {
|
|
6819
|
+
advancePendingProjectShares: (store, options) => server.advancePendingProjectSharesOperation(store, {
|
|
6820
|
+
...options,
|
|
6821
|
+
advanceOperation: server.advanceProjectShareOperation
|
|
6822
|
+
}),
|
|
6823
|
+
reconcileConfiguredCoordinatorEnrollment: server.reconcileConfiguredCoordinatorEnrollment,
|
|
6824
|
+
reconcileRecipientPolicyProjects: (store, options) => server.reconcileRecipientPolicyProjectsOperation(store, {
|
|
6825
|
+
...options,
|
|
6826
|
+
effects: server.createRecipientPolicyReconcilerEffects(store)
|
|
6827
|
+
})
|
|
6828
|
+
};
|
|
6829
|
+
}
|
|
6795
6830
|
async function runServeCoordinatorMaintenance(store, dependencies) {
|
|
6796
6831
|
const projectShares = await dependencies.advancePendingProjectShares(store, { limit: 3 });
|
|
6797
6832
|
const coordinatorEnrollment = await dependencies.reconcileConfiguredCoordinatorEnrollment(store);
|
|
@@ -6844,8 +6879,77 @@ async function startBackgroundViewer(invocation) {
|
|
|
6844
6879
|
p.intro("codemem viewer");
|
|
6845
6880
|
p.outro(`Viewer started in background (pid ${child.pid}) at http://${invocation.host}:${invocation.port}`);
|
|
6846
6881
|
}
|
|
6882
|
+
function startRawEventProcessing(dbPath, store, observer, createInbox) {
|
|
6883
|
+
const sweeper = new RawEventSweeper(store, { observer });
|
|
6884
|
+
sweeper.start();
|
|
6885
|
+
const queue = createInbox({
|
|
6886
|
+
dbPath,
|
|
6887
|
+
sweeper,
|
|
6888
|
+
onDrainError: () => {
|
|
6889
|
+
p.log.warn("Raw-event database ingestion is delayed; accepted events remain queued");
|
|
6890
|
+
},
|
|
6891
|
+
onDrainRecovered: () => {
|
|
6892
|
+
p.log.info("Raw-event database ingestion recovered");
|
|
6893
|
+
},
|
|
6894
|
+
onCorruptEntries: (count) => {
|
|
6895
|
+
p.log.error(`Raw-event queue contains ${count} corrupt retained entries`);
|
|
6896
|
+
},
|
|
6897
|
+
onBacklog: (pending, oldestAgeMs) => {
|
|
6898
|
+
p.log.warn(`Raw-event queue backlog is sustained (${pending} pending, oldest ${Math.ceil(oldestAgeMs / 1e3)}s)`);
|
|
6899
|
+
},
|
|
6900
|
+
onBacklogRecovered: () => {
|
|
6901
|
+
p.log.info("Raw-event queue backlog recovered");
|
|
6902
|
+
}
|
|
6903
|
+
});
|
|
6904
|
+
queue.inbox.start();
|
|
6905
|
+
const rawEventTarget = createRawEventTargetState(store);
|
|
6906
|
+
return {
|
|
6907
|
+
appOptions: {
|
|
6908
|
+
rawEventInbox: queue.inbox,
|
|
6909
|
+
rawEventTarget,
|
|
6910
|
+
sweeper,
|
|
6911
|
+
observer
|
|
6912
|
+
},
|
|
6913
|
+
stop: async () => {
|
|
6914
|
+
rawEventTarget.stop();
|
|
6915
|
+
await queue.stop();
|
|
6916
|
+
await sweeper.stop();
|
|
6917
|
+
}
|
|
6918
|
+
};
|
|
6919
|
+
}
|
|
6920
|
+
function createRawEventTargetState(store) {
|
|
6921
|
+
let hasCurrentIdentity = false;
|
|
6922
|
+
let actorId = store.actorId;
|
|
6923
|
+
let deviceId = store.deviceId;
|
|
6924
|
+
const refreshCurrentIdentity = () => {
|
|
6925
|
+
try {
|
|
6926
|
+
hasCurrentIdentity = store.hasCurrentIdentity();
|
|
6927
|
+
} catch {
|
|
6928
|
+
hasCurrentIdentity = false;
|
|
6929
|
+
}
|
|
6930
|
+
actorId = store.actorId;
|
|
6931
|
+
deviceId = store.deviceId;
|
|
6932
|
+
};
|
|
6933
|
+
refreshCurrentIdentity();
|
|
6934
|
+
const stop = store.onIdentityChanged(refreshCurrentIdentity);
|
|
6935
|
+
return {
|
|
6936
|
+
dbPath: store.dbPath,
|
|
6937
|
+
hasCurrentIdentity: () => {
|
|
6938
|
+
if (!hasCurrentIdentity || actorId !== store.actorId || deviceId !== store.deviceId) return false;
|
|
6939
|
+
try {
|
|
6940
|
+
return store.hasCurrentConfiguredIdentity();
|
|
6941
|
+
} catch {
|
|
6942
|
+
return false;
|
|
6943
|
+
}
|
|
6944
|
+
},
|
|
6945
|
+
stop
|
|
6946
|
+
};
|
|
6947
|
+
}
|
|
6847
6948
|
async function startForegroundViewer(invocation) {
|
|
6848
|
-
const
|
|
6949
|
+
const serverModule = await import("@codemem/server");
|
|
6950
|
+
const { createApp, createSyncApp, closeStore, createViewerRawEventInbox, getStore } = serverModule;
|
|
6951
|
+
const createRawEventInbox = createViewerRawEventInbox;
|
|
6952
|
+
const coordinatorMaintenanceDependencies = createServeCoordinatorMaintenanceDependencies(serverModule);
|
|
6849
6953
|
const { serve } = await import("@hono/node-server");
|
|
6850
6954
|
if (invocation.dbPath) process.env.CODEMEM_DB = invocation.dbPath;
|
|
6851
6955
|
if (invocation.configPath) process.env.CODEMEM_CONFIG = invocation.configPath;
|
|
@@ -6869,8 +6973,7 @@ async function startForegroundViewer(invocation) {
|
|
|
6869
6973
|
store = getStore();
|
|
6870
6974
|
p.log.warn("Embeddings disabled for this viewer process; raw-event ingestion remains active.");
|
|
6871
6975
|
}
|
|
6872
|
-
const
|
|
6873
|
-
sweeper.start();
|
|
6976
|
+
const rawEventProcessing = startRawEventProcessing(dbPath, store, observer, createRawEventInbox);
|
|
6874
6977
|
const syncAbort = new AbortController();
|
|
6875
6978
|
const config = invocation.configPath ? readCodememConfigFileAtPath(invocation.configPath) : readCodememConfigFile();
|
|
6876
6979
|
const syncConfig = readCoordinatorSyncConfig(config);
|
|
@@ -6881,8 +6984,7 @@ async function startForegroundViewer(invocation) {
|
|
|
6881
6984
|
};
|
|
6882
6985
|
const appOpts = {
|
|
6883
6986
|
storeFactory: () => store,
|
|
6884
|
-
|
|
6885
|
-
observer,
|
|
6987
|
+
...rawEventProcessing.appOptions,
|
|
6886
6988
|
getSyncRuntimeStatus: () => syncRuntimeStatus
|
|
6887
6989
|
};
|
|
6888
6990
|
const app = createApp(appOpts);
|
|
@@ -6933,11 +7035,7 @@ async function startForegroundViewer(invocation) {
|
|
|
6933
7035
|
signal: syncAbort.signal,
|
|
6934
7036
|
scanner: store.scanner,
|
|
6935
7037
|
onAfterCoordinatorRefresh: async () => {
|
|
6936
|
-
await runServeCoordinatorMaintenance(store,
|
|
6937
|
-
advancePendingProjectShares,
|
|
6938
|
-
reconcileConfiguredCoordinatorEnrollment,
|
|
6939
|
-
reconcileRecipientPolicyProjects
|
|
6940
|
-
});
|
|
7038
|
+
await runServeCoordinatorMaintenance(store, coordinatorMaintenanceDependencies);
|
|
6941
7039
|
},
|
|
6942
7040
|
onPhaseChange: (phase) => {
|
|
6943
7041
|
if (phase === "running") {
|
|
@@ -6979,7 +7077,7 @@ async function startForegroundViewer(invocation) {
|
|
|
6979
7077
|
syncServer?.close(done);
|
|
6980
7078
|
server.close(done);
|
|
6981
7079
|
}).catch(() => {});
|
|
6982
|
-
await
|
|
7080
|
+
await rawEventProcessing.stop();
|
|
6983
7081
|
try {
|
|
6984
7082
|
rmSync(pidPath);
|
|
6985
7083
|
} catch {}
|
|
@@ -7735,6 +7833,17 @@ function fmtTokens(n) {
|
|
|
7735
7833
|
if (n >= 1e3) return `~${(n / 1e3).toFixed(0)}K`;
|
|
7736
7834
|
return `${n}`;
|
|
7737
7835
|
}
|
|
7836
|
+
function formatUsageEvent(event, provenance) {
|
|
7837
|
+
const parts = [`${event.event}: ${event.count.toLocaleString()}`];
|
|
7838
|
+
if (event.tokens_read > 0) parts.push(`read ${fmtTokens(event.tokens_read)} tokens`);
|
|
7839
|
+
if (event.tokens_saved > 0) parts.push(`est. saved ${fmtTokens(event.tokens_saved)} tokens`);
|
|
7840
|
+
if (provenance?.measured_count) parts.push(`${provenance.measured_count} provider-measured`);
|
|
7841
|
+
if (provenance?.estimated_count) parts.push(`${provenance.estimated_count} estimated`);
|
|
7842
|
+
if (provenance?.unavailable_count) parts.push(`${provenance.unavailable_count} unavailable`);
|
|
7843
|
+
if (provenance?.legacy_text_length_count) parts.push(`${provenance.legacy_text_length_count} legacy length excluded`);
|
|
7844
|
+
if (provenance?.legacy_unclassified_count) parts.push(`${provenance.legacy_unclassified_count} legacy unclassified`);
|
|
7845
|
+
return ` ${parts.join(", ")}`;
|
|
7846
|
+
}
|
|
7738
7847
|
var statsCmd = new Command("stats").configureHelp(helpStyle).description("Show database statistics");
|
|
7739
7848
|
addDbOption(statsCmd);
|
|
7740
7849
|
addJsonOption(statsCmd);
|
|
@@ -7788,12 +7897,8 @@ var statsCommand = statsCmd.action((opts) => {
|
|
|
7788
7897
|
`Raw events: ${db.raw_events.toLocaleString()}`
|
|
7789
7898
|
].join("\n"));
|
|
7790
7899
|
if (result.usage.events.length > 0) {
|
|
7791
|
-
const
|
|
7792
|
-
|
|
7793
|
-
if (e.tokens_read > 0) parts.push(`read ${fmtTokens(e.tokens_read)} tokens`);
|
|
7794
|
-
if (e.tokens_saved > 0) parts.push(`est. saved ${fmtTokens(e.tokens_saved)} tokens`);
|
|
7795
|
-
return ` ${parts.join(", ")}`;
|
|
7796
|
-
});
|
|
7900
|
+
const provenanceByEvent = new Map(result.usage.provenance.events.map((event) => [event.event, event]));
|
|
7901
|
+
const lines = result.usage.events.map((event) => formatUsageEvent(event, provenanceByEvent.get(event.event)));
|
|
7797
7902
|
const t = result.usage.totals;
|
|
7798
7903
|
lines.push("");
|
|
7799
7904
|
lines.push(` Total: ${t.events.toLocaleString()} events, read ${fmtTokens(t.tokens_read)} tokens, est. saved ${fmtTokens(t.tokens_saved)} tokens`);
|
|
@@ -8194,8 +8299,8 @@ function collectAdvertiseAddresses(explicitAddress, configuredHost, port, interf
|
|
|
8194
8299
|
function readCliConfig(configPath) {
|
|
8195
8300
|
return configPath ? readCodememConfigFileAtPath(configPath) : readCodememConfigFile();
|
|
8196
8301
|
}
|
|
8197
|
-
function
|
|
8198
|
-
return
|
|
8302
|
+
function mutateCliConfig(mutator, configPath) {
|
|
8303
|
+
return mutateCodememConfigFile(mutator, configPath || void 0).data;
|
|
8199
8304
|
}
|
|
8200
8305
|
function parseAttemptsLimit(value) {
|
|
8201
8306
|
if (!/^\d+$/.test(value.trim())) throw new Error(`Invalid --limit: ${value}`);
|
|
@@ -8819,14 +8924,15 @@ enableCmd.action((opts) => {
|
|
|
8819
8924
|
try {
|
|
8820
8925
|
const keysDir = process.env.CODEMEM_KEYS_DIR?.trim() || void 0;
|
|
8821
8926
|
const [deviceId, fingerprint] = ensureDeviceIdentity(store.db, { keysDir });
|
|
8822
|
-
const config = readCliConfig(opts.config);
|
|
8823
|
-
config.sync_enabled = true;
|
|
8824
|
-
if (effectiveHost) config.sync_host = effectiveHost;
|
|
8825
8927
|
const syncPort = parsePositiveIntegerOption(effectivePort, "--sync-port");
|
|
8826
8928
|
const syncInterval = parsePositiveIntegerOption(opts.interval, "--interval");
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8929
|
+
const config = mutateCliConfig((current) => {
|
|
8930
|
+
current.sync_enabled = true;
|
|
8931
|
+
if (effectiveHost) current.sync_host = effectiveHost;
|
|
8932
|
+
if (syncPort != null) current.sync_port = syncPort;
|
|
8933
|
+
if (syncInterval != null) current.sync_interval_s = syncInterval;
|
|
8934
|
+
return current;
|
|
8935
|
+
}, opts.config);
|
|
8830
8936
|
if (opts.json) {
|
|
8831
8937
|
console.log(JSON.stringify({
|
|
8832
8938
|
ok: true,
|
|
@@ -8863,9 +8969,17 @@ syncCommand.addCommand(enableCmd);
|
|
|
8863
8969
|
var disableCmd = new Command("disable").configureHelp(helpStyle).description("Disable sync without deleting keys or peers");
|
|
8864
8970
|
addConfigOption(disableCmd);
|
|
8865
8971
|
disableCmd.action((opts) => {
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8972
|
+
try {
|
|
8973
|
+
mutateCliConfig((config) => ({
|
|
8974
|
+
...config,
|
|
8975
|
+
sync_enabled: false
|
|
8976
|
+
}), opts.config);
|
|
8977
|
+
} catch (error) {
|
|
8978
|
+
const message = error instanceof Error ? error.message : "Failed to disable sync";
|
|
8979
|
+
p.log.error(message);
|
|
8980
|
+
process.exitCode = 1;
|
|
8981
|
+
return;
|
|
8982
|
+
}
|
|
8869
8983
|
p.intro("codemem sync disable");
|
|
8870
8984
|
p.outro("Sync disabled — restart `codemem serve` to take effect");
|
|
8871
8985
|
});
|
|
@@ -9117,10 +9231,18 @@ syncCommand.addCommand(bootstrapCmd);
|
|
|
9117
9231
|
var connectCmd = new Command("connect").configureHelp(helpStyle).description("Configure coordinator URL for cloud sync").argument("<url>", "coordinator URL (e.g. https://coordinator.example.com)").option("--group <group>", "sync group ID");
|
|
9118
9232
|
addConfigOption(connectCmd);
|
|
9119
9233
|
connectCmd.action((url, opts) => {
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9234
|
+
try {
|
|
9235
|
+
mutateCliConfig((config) => {
|
|
9236
|
+
config.sync_coordinator_url = url.trim();
|
|
9237
|
+
if (opts.group) config.sync_coordinator_group = opts.group.trim();
|
|
9238
|
+
return config;
|
|
9239
|
+
}, opts.config);
|
|
9240
|
+
} catch (error) {
|
|
9241
|
+
const message = error instanceof Error ? error.message : "Failed to configure coordinator sync";
|
|
9242
|
+
p.log.error(message);
|
|
9243
|
+
process.exitCode = 1;
|
|
9244
|
+
return;
|
|
9245
|
+
}
|
|
9124
9246
|
p.intro("codemem sync connect");
|
|
9125
9247
|
p.log.success(`Coordinator: ${url.trim()}`);
|
|
9126
9248
|
if (opts.group) p.log.info(`Group: ${opts.group.trim()}`);
|
|
@@ -9966,19 +10088,6 @@ var ROOT_COMPLETION_COMMANDS = [
|
|
|
9966
10088
|
"--help",
|
|
9967
10089
|
"--version"
|
|
9968
10090
|
];
|
|
9969
|
-
/**
|
|
9970
|
-
* True when the CLI process was invoked through the named top-level
|
|
9971
|
-
* compatibility alias (first non-flag token of the real argv). Forwarding
|
|
9972
|
-
* wrappers such as `memory export` re-parse the alias command with synthetic
|
|
9973
|
-
* argv, so this stays false for canonical invocations.
|
|
9974
|
-
*/
|
|
9975
|
-
function invokedAsTopLevelAlias(name, argv = process.argv.slice(2)) {
|
|
9976
|
-
for (const token of argv) {
|
|
9977
|
-
if (token === "--") return false;
|
|
9978
|
-
if (!token.startsWith("-")) return token === name;
|
|
9979
|
-
}
|
|
9980
|
-
return false;
|
|
9981
|
-
}
|
|
9982
10091
|
function registerMemoryGroupWrappers() {
|
|
9983
10092
|
if (memoryCommand.commands.some((command) => command.name() === "export")) return;
|
|
9984
10093
|
const forwardedTail = (subcommand) => {
|