@codemem/server 0.44.0-beta.1 → 0.44.0
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.d.ts.map +1 -1
- package/dist/index.js +464 -45
- package/dist/index.js.map +1 -1
- package/dist/routes/diagnostics.d.ts +31 -0
- package/dist/routes/diagnostics.d.ts.map +1 -0
- package/dist/routes/memory.d.ts.map +1 -1
- package/dist/routes/pack.d.ts.map +1 -1
- package/dist/routes/stats.d.ts.map +1 -1
- package/package.json +2 -2
- package/static/app.js +41 -41
- package/static/app.js.br +0 -0
- package/static/app.js.gz +0 -0
- package/static/index.html +182 -19
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EACX,iCAAiC,EACjC,sBAAsB,EACtB,cAAc,EACd,YAAY,EACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAiB,OAAO,EAAE,MAAM,eAAe,CAAC;AAE1F,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAEN,KAAK,0BAA0B,EAC/B,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EACX,iCAAiC,EACjC,sBAAsB,EACtB,cAAc,EACd,YAAY,EACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAiB,OAAO,EAAE,MAAM,eAAe,CAAC;AAE1F,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAEN,KAAK,0BAA0B,EAC/B,MAAM,yBAAyB,CAAC;AASjC,OAAO,EAAE,KAAK,iBAAiB,EAAkC,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EACN,KAAK,gCAAgC,EACrC,KAAK,uCAAuC,EAG5C,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EACX,iCAAiC,EACjC,kCAAkC,EAClC,sCAAsC,EACtC,sCAAsC,EACtC,8CAA8C,EAC9C,sCAAsC,GACtC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,2BAA2B,EAC3B,4BAA4B,EAC5B,sCAAsC,EACtC,uCAAuC,EACvC,mCAAmC,EACnC,wCAAwC,EACxC,gCAAgC,GAChC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACX,oCAAoC,EACpC,2BAA2B,EAC3B,iCAAiC,EACjC,+BAA+B,EAC/B,uBAAuB,EACvB,8BAA8B,EAC9B,+BAA+B,EAC/B,+BAA+B,EAC/B,iCAAiC,EACjC,wCAAwC,EACxC,wBAAwB,EACxB,gCAAgC,EAChC,kCAAkC,EAClC,qBAAqB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,OAAO,EAAE,CAAC;AAKnB,uFAAuF;AACvF,wBAAgB,QAAQ,IAAI,WAAW,CAKtC;AAED,mDAAmD;AACnD,wBAAgB,UAAU,IAAI,IAAI,CAGjC;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IAC1B,YAAY,CAAC,EAAE,MAAM,WAAW,CAAC;IACjC,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACjC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7E,qCAAqC,CAAC,EAAE,MAAM,OAAO,CAAC,iCAAiC,CAAC,CAAC;IACzF,sCAAsC,CAAC,EAAE,uCAAuC,CAAC;IACjF,+BAA+B,CAAC,EAAE,gCAAgC,GAAG,IAAI,CAAC;IAC1E,qBAAqB,CAAC,EAAE,iBAAiB,CAAC,uBAAuB,CAAC,CAAC;IACnE,sBAAsB,CAAC,EAAE,iBAAiB,CAAC,wBAAwB,CAAC,CAAC;IACrE,oBAAoB,CAAC,EAAE;QACtB,OAAO,CAAC,EAAE,0BAA0B,CAAC;QACrC,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,wBAAwB,CAAC,EAAE,MAAM,CAAC;QAClC,4BAA4B,CAAC,EAAE,MAAM,CAAC;KACtC,CAAC;IACF,oBAAoB,CAAC,EAAE,MAAM;QAC5B,KAAK,EACF,UAAU,GACV,SAAS,GACT,UAAU,GACV,OAAO,GACP,UAAU,GACV,iBAAiB,GACjB,iBAAiB,GACjB,IAAI,CAAC;QACR,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACvB,GAAG,IAAI,CAAC;CACT;AAmCD,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,UAAU,8EAsD1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,UAAU,8EA8B9C"}
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { dirname, isAbsolute, join, posix, resolve, win32 } from "node:path";
|
|
3
|
-
import { ACCESS_CLEANUP_OP_TYPE, CODEMEM_CONFIG_ENV_OVERRIDES, CoordinatorReciprocalApprovalRequestChangedError, DEFAULT_TIME_WINDOW_S, LEGACY_SHARED_REVIEW_SCOPE_ID, LOCAL_DEFAULT_SCOPE_ID, LOCAL_SYNC_CAPABILITY, LOCAL_SYNC_FEATURES, LegacyTeamSetupAdditiveConvergenceError, LegacyTeamSetupRosterCapacityError, MemoryStore, PROMPT_TRANSPORT_PROTOCOL_RANGE, RawEventIngestValidationError, RecipientPolicyEdgeRequestError, RecipientPolicyTeamRenameError, RemoteCoordinatorRequestError, SCOPE_MEMBERSHIP_REVOCATION_LIMITATION, SYNC_AUTHORIZATION_REFRESH_HEADER, SYNC_CAPABILITY_HEADER, SYNC_FEATURES_HEADER, SYNC_SCOPE_QUERY_PARAM, VERSION, VERSION as VERSION$1, VIEWER_IDENTITY_TARGET_KEYS, VIEWER_SERVICE_DISCRIMINATOR, addSyncScopeToBoundary, analyzeProjectScopeMappingChangeGuardrails, applyLegacyTeamSetupCompletionManifest, applyLegacyTeamSetupCompletionManifestAndReturnActivation, applyReplicationOps, areLegacyTeamSetupCompletionPolicyFactsAdditivelyCompatible, buildAuthHeaders, buildBaseUrl, buildDirectPeerAuthHeaders, buildFilterClausesWithContext, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, buildViewerIdentityTarget, canonicalCoordinatorLegacyTeamCompletionManifestJson, canonicalMemoryKind, canonicalWorkspaceIdentity, claimRecipientPolicyActorMutations, claimRecipientPolicyPublicationMutation, cleanupNonces, clearLegacyTeamSetupDeviceDecision, clonePromptPackAttempt, coerceObserverCommand, commitDeviceIdentityBindings, commitRecipientPolicyEdges, containLegacyTeamSetupCompletionConflict, coordinatorArchiveGroupAction, coordinatorCreateAddDeviceInviteAction, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateLegacyTeamCompletionAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnableDeviceAction, coordinatorGetLegacyTeamCompletionAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListConsumedTeamInvitesAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListLegacyTeamCompletionsAction, coordinatorListReviewedRecipientInviteEvidenceAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorRenameGroupAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorStatusSnapshot, coordinatorUnarchiveGroupAction, coordinatorUpdateScopeAction, countShareableProjectMemories, createCoordinatorReciprocalApproval, decodeInvitePayload, defaultSpaceScopeIdForGroup, deleteProjectScopeSettingsMapping, deriveLegacyTeamSetupCompletionManifest, detectInstallKind, deterministicPolicyTeamId, diagnoseStalePeerReceivedRows, discoverLegacyTeamCandidates, ensureDeviceIdentity, executeShareProvisioning, extractInvitePayload, extractReplicationOps, filterReplicationOpsForSyncWithStatus, fingerprintPublicKey, formatHostPort, friendlyDeviceName, fromJson, getCodememConfigPath, getCodememEnvOverrides, getCoordinatorEnrollmentReconciliationIssueSummary, getCoordinatorGroupPreference, getLegacyTeamSetupDraft, getRecipientPolicyAuthorityState, getSemanticIndexDiagnostics, getSyncResetState, getUpdateStatus, ingestRawEvents, inspectFreshLegacyTeamSetupActivation, inspectLegacyTeamSetupActivation, inviteTokenDigest, isLegacyTeamCandidateSelectable, isLegacyTeamSetupProjectMappingIdentity, isPeerTrustBindingCompatible, isProjectSyncEnablementError, isScopedSyncCapability, legacyTeamCandidateId, legacyTeamCandidateProjectInventory, legacyTeamCanonicalProjectRef, legacyTeamDeviceRef, legacyTeamResolvedProjectRef, legacyTeamSetupApiErrorCode, listAuthorizedScopesForPeer, listCoordinatorJoinRequests, listDeviceIdentityInventory, listInboundScopeRejections, listLegacyRecipientPolicyProjections, listMaintenanceJobs, listObserverProviderOptions, listPerPeerScopeSyncState, listProjectScopeCandidates, listProjectScopeInventory, listProjectScopeSettingsMappings, listRecipientPolicyIntent, listRecipientPolicyReview, listSharingDomainSettingsScopes, loadMemorySnapshotPageForPeer, loadReplicationOpsForPeer, lookupCoordinatorPeers, mergeAddresses, migrateRecipientPolicyIntent, negotiateSyncCapability, normalizeAddress, normalizeHumanPresentationName, normalizeSyncCapability, normalizeSyncFeatures, normalizeTeammateName, parseAcceptedProjectIntent, parsePositiveMemoryId, parseReassignScopePayload, parseRecipientPolicyEdgeCommitRequest, parseStrictInteger, parseSyncScopeRequest, persistShareOperation, personalScopeGrantStatusForPeer, planShareOperation, previewDeviceIdentityBindings, previewLegacyTeamSetupActivation, previewRecipientPolicyEdges, previewRecipientPolicyOnboarding, previewRecipientPolicyOnboardingFromReviewedIntent, probeAvailableCredentials, projectShareLifecycle, promptPackArtifactFingerprint, readCodememConfigFile, readCoordinatorSyncConfig, reassignProjectScopeInventoryProject, recipientInviteAuthoritativeIdentityId, recipientPolicyDigest, recipientReviewedIntentDigest, reconcileCoordinatorEnrollmentSnapshot, reconcileRecipientPolicyProject, reconcileShareOperationAcceptance, reconstructLegacyTeamSetupCompletionManifest, recordHighestObservedDirectSignatureVersion, recordNonce, recordPromptPackArtifacts, recordPromptPackTerminal, refreshAuthorizedCoordinatorPeerTrust, refreshConfiguredScopeMembershipCache, refreshLegacyTeamCandidate, rejectInboundScopeFailures, renameRecipientPolicyTeam, replayLegacyTeamSetupActivation, requestJson, requireLegacyTeamSetupAccessDeltaWithinLimit, resolveDbPath, resolveProject, resolveRecipientPolicyReview, resolveRecipientPolicyReviewBulk, runSyncPass, schema, serializeRecipientPolicyCoordinatorGroupMutation, serializeRecipientPolicyPublicationMutation, serializeRecipientPolicyTeamMutation, setLegacyTeamSetupDeviceAssignment, setLegacyTeamSetupDeviceDecision, setLegacyTeamSetupProjectMapping, summarizeInboundScopeRejections, supportsSyncFeature, syncScopeResetRequiredPayload, tryUpdateRetrievalDelivery, updatePeerAddresses, upsertCoordinatorGroupPreference, upsertProjectScopeSettingsMapping, validateLegacyTeamSetupCompletionManifest, validateLegacyTeamSetupCompletionManifestBinding, verifyDirectPeerSignature, verifyRecipientReviewedIntent, verifySignature, writeCodememConfigFile } from "@codemem/core";
|
|
3
|
+
import { ACCESS_CLEANUP_OP_TYPE, CODEMEM_CONFIG_ENV_OVERRIDES, CoordinatorReciprocalApprovalRequestChangedError, DEFAULT_TIME_WINDOW_S, LEGACY_SHARED_REVIEW_SCOPE_ID, LOCAL_DEFAULT_SCOPE_ID, LOCAL_SYNC_CAPABILITY, LOCAL_SYNC_FEATURES, LegacyTeamSetupAdditiveConvergenceError, LegacyTeamSetupRosterCapacityError, MemoryStore, PROMPT_TRANSPORT_PROTOCOL_RANGE, RawEventIngestValidationError, RecipientPolicyEdgeRequestError, RecipientPolicyTeamRenameError, RemoteCoordinatorRequestError, SCOPE_MEMBERSHIP_REVOCATION_LIMITATION, SYNC_AUTHORIZATION_REFRESH_HEADER, SYNC_CAPABILITY_HEADER, SYNC_FEATURES_HEADER, SYNC_SCOPE_QUERY_PARAM, VERSION, VERSION as VERSION$1, VIEWER_IDENTITY_TARGET_KEYS, VIEWER_SERVICE_DISCRIMINATOR, addSyncScopeToBoundary, analyzeProjectScopeMappingChangeGuardrails, applyLegacyTeamSetupCompletionManifest, applyLegacyTeamSetupCompletionManifestAndReturnActivation, applyReplicationOps, areLegacyTeamSetupCompletionPolicyFactsAdditivelyCompatible, automaticRecallHealth, buildAuthHeaders, buildBaseUrl, buildDirectPeerAuthHeaders, buildFilterClausesWithContext, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, buildViewerIdentityTarget, canonicalCoordinatorLegacyTeamCompletionManifestJson, canonicalMemoryKind, canonicalWorkspaceIdentity, claimRecipientPolicyActorMutations, claimRecipientPolicyPublicationMutation, cleanupNonces, clearLegacyTeamSetupDeviceDecision, clonePromptPackAttempt, coerceObserverCommand, commitDeviceIdentityBindings, commitRecipientPolicyEdges, containLegacyTeamSetupCompletionConflict, coordinatorArchiveGroupAction, coordinatorCreateAddDeviceInviteAction, coordinatorCreateGroupAction, coordinatorCreateInviteAction, coordinatorCreateLegacyTeamCompletionAction, coordinatorCreateScopeAction, coordinatorDisableDeviceAction, coordinatorEnableDeviceAction, coordinatorGetLegacyTeamCompletionAction, coordinatorGrantScopeMembershipAction, coordinatorImportInviteAction, coordinatorListBootstrapGrantsAction, coordinatorListConsumedTeamInvitesAction, coordinatorListDevicesAction, coordinatorListGroupsAction, coordinatorListJoinRequestsAction, coordinatorListLegacyTeamCompletionsAction, coordinatorListReviewedRecipientInviteEvidenceAction, coordinatorListScopeMembershipsAction, coordinatorListScopesAction, coordinatorRemoveDeviceAction, coordinatorRenameDeviceAction, coordinatorRenameGroupAction, coordinatorReviewJoinRequestAction, coordinatorRevokeBootstrapGrantAction, coordinatorRevokeScopeMembershipAction, coordinatorStatusSnapshot, coordinatorUnarchiveGroupAction, coordinatorUpdateScopeAction, countShareableProjectMemories, createCoordinatorReciprocalApproval, decodeInvitePayload, defaultSpaceScopeIdForGroup, deleteProjectScopeSettingsMapping, deriveLegacyTeamSetupCompletionManifest, detectInstallKind, deterministicPolicyTeamId, diagnoseStalePeerReceivedRows, discoverLegacyTeamCandidates, ensureDeviceIdentity, executeShareProvisioning, extractInvitePayload, extractReplicationOps, filterReplicationOpsForSyncWithStatus, fingerprintPublicKey, formatHostPort, friendlyDeviceName, fromJson, getCodememConfigPath, getCodememEnvOverrides, getCoordinatorEnrollmentReconciliationIssueSummary, getCoordinatorGroupPreference, getLegacyTeamSetupDraft, getRecipientPolicyAuthorityState, getSemanticIndexDiagnostics, getSyncResetState, getUpdateStatus, ingestRawEvents, inspectFreshLegacyTeamSetupActivation, inspectLegacyTeamSetupActivation, inviteTokenDigest, isAutomaticRecallMeasurement, isLegacyTeamCandidateSelectable, isLegacyTeamSetupProjectMappingIdentity, isPeerTrustBindingCompatible, isProjectSyncEnablementError, isScopedSyncCapability, legacyTeamCandidateId, legacyTeamCandidateProjectInventory, legacyTeamCanonicalProjectRef, legacyTeamDeviceRef, legacyTeamResolvedProjectRef, legacyTeamSetupApiErrorCode, listAuthorizedScopesForPeer, listCoordinatorJoinRequests, listDeviceIdentityInventory, listInboundScopeRejections, listLegacyRecipientPolicyProjections, listMaintenanceJobs, listObserverProviderOptions, listPerPeerScopeSyncState, listProjectScopeCandidates, listProjectScopeInventory, listProjectScopeSettingsMappings, listRecipientPolicyIntent, listRecipientPolicyReview, listSharingDomainSettingsScopes, loadMemorySnapshotPageForPeer, loadReplicationOpsForPeer, lookupCoordinatorPeers, mergeAddresses, migrateRecipientPolicyIntent, negotiateSyncCapability, normalizeAddress, normalizeHumanPresentationName, normalizeSyncCapability, normalizeSyncFeatures, normalizeTeammateName, parseAcceptedProjectIntent, parsePositiveMemoryId, parseReassignScopePayload, parseRecipientPolicyEdgeCommitRequest, parseStrictInteger, parseSyncScopeRequest, persistShareOperation, personalScopeGrantStatusForPeer, planShareOperation, previewDeviceIdentityBindings, previewLegacyTeamSetupActivation, previewRecipientPolicyEdges, previewRecipientPolicyOnboarding, previewRecipientPolicyOnboardingFromReviewedIntent, probeAvailableCredentials, projectShareLifecycle, promptPackArtifactFingerprint, readCodememConfigFile, readCoordinatorSyncConfig, reassignProjectScopeInventoryProject, recipientInviteAuthoritativeIdentityId, recipientPolicyDigest, recipientReviewedIntentDigest, reconcileCoordinatorEnrollmentSnapshot, reconcileRecipientPolicyProject, reconcileShareOperationAcceptance, reconstructLegacyTeamSetupCompletionManifest, recordAutomaticRecall, recordHighestObservedDirectSignatureVersion, recordNonce, recordPromptPackArtifacts, recordPromptPackTerminal, refreshAuthorizedCoordinatorPeerTrust, refreshConfiguredScopeMembershipCache, refreshLegacyTeamCandidate, rejectInboundScopeFailures, renameRecipientPolicyTeam, replayLegacyTeamSetupActivation, requestJson, requireLegacyTeamSetupAccessDeltaWithinLimit, resolveDbPath, resolveProject, resolveRecipientPolicyReview, resolveRecipientPolicyReviewBulk, runSyncPass, schema, serializeRecipientPolicyCoordinatorGroupMutation, serializeRecipientPolicyPublicationMutation, serializeRecipientPolicyTeamMutation, setLegacyTeamSetupDeviceAssignment, setLegacyTeamSetupDeviceDecision, setLegacyTeamSetupProjectMapping, summarizeInboundScopeRejections, summaryLikeSqlPredicate, supportsSyncFeature, syncScopeResetRequiredPayload, tryUpdateRetrievalDelivery, updatePeerAddresses, upsertCoordinatorGroupPreference, upsertProjectScopeSettingsMapping, validateLegacyTeamSetupCompletionManifest, validateLegacyTeamSetupCompletionManifestBinding, verifyDirectPeerSignature, verifyRecipientReviewedIntent, verifySignature, writeCodememConfigFile } from "@codemem/core";
|
|
4
4
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
5
5
|
import { Hono } from "hono";
|
|
6
6
|
import { createMiddleware } from "hono/factory";
|
|
7
7
|
import { RateLimiter } from "limiter";
|
|
8
|
+
import { createCipheriv, createDecipheriv, createHash, randomBytes, randomUUID } from "node:crypto";
|
|
8
9
|
import { and, count, desc, eq, inArray, max, ne } from "drizzle-orm";
|
|
9
10
|
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
10
11
|
import { homedir, hostname, networkInterfaces } from "node:os";
|
|
11
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
12
12
|
//#region src/middleware.ts
|
|
13
13
|
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
|
|
14
14
|
"127.0.0.1",
|
|
@@ -513,6 +513,363 @@ function configRoutes(opts = {}) {
|
|
|
513
513
|
return app;
|
|
514
514
|
}
|
|
515
515
|
//#endregion
|
|
516
|
+
//#region src/routes/diagnostics.ts
|
|
517
|
+
var DEFAULT_LIMIT = 50;
|
|
518
|
+
var MAX_LIMIT = 100;
|
|
519
|
+
var CURSOR_KEY = randomBytes(32);
|
|
520
|
+
var DIAGNOSTIC_SEVERITIES = [
|
|
521
|
+
"info",
|
|
522
|
+
"warning",
|
|
523
|
+
"error"
|
|
524
|
+
];
|
|
525
|
+
var DIAGNOSTIC_SUBSYSTEMS = [
|
|
526
|
+
"viewer",
|
|
527
|
+
"observer",
|
|
528
|
+
"capture",
|
|
529
|
+
"sync",
|
|
530
|
+
"storage",
|
|
531
|
+
"maintenance"
|
|
532
|
+
];
|
|
533
|
+
function opaqueId(kind, sourceId) {
|
|
534
|
+
return createHash("sha256").update(`${kind}\0${String(sourceId)}`).digest("base64url").slice(0, 22);
|
|
535
|
+
}
|
|
536
|
+
function encodeCursor(event) {
|
|
537
|
+
const iv = randomBytes(12);
|
|
538
|
+
const cipher = createCipheriv("aes-256-gcm", CURSOR_KEY, iv);
|
|
539
|
+
const plaintext = JSON.stringify({
|
|
540
|
+
occurredAt: event.occurred_at,
|
|
541
|
+
orderKey: event.orderKey
|
|
542
|
+
});
|
|
543
|
+
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
544
|
+
return Buffer.concat([
|
|
545
|
+
iv,
|
|
546
|
+
cipher.getAuthTag(),
|
|
547
|
+
encrypted
|
|
548
|
+
]).toString("base64url");
|
|
549
|
+
}
|
|
550
|
+
function parseCursor(raw) {
|
|
551
|
+
if (!raw) return null;
|
|
552
|
+
try {
|
|
553
|
+
const encoded = Buffer.from(raw, "base64url");
|
|
554
|
+
if (encoded.length < 29) return "invalid";
|
|
555
|
+
const decipher = createDecipheriv("aes-256-gcm", CURSOR_KEY, encoded.subarray(0, 12));
|
|
556
|
+
decipher.setAuthTag(encoded.subarray(12, 28));
|
|
557
|
+
const plaintext = Buffer.concat([decipher.update(encoded.subarray(28)), decipher.final()]).toString("utf8");
|
|
558
|
+
const parsed = JSON.parse(plaintext);
|
|
559
|
+
if (typeof parsed.occurredAt !== "string" || !/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:.+-]+Z$/.test(parsed.occurredAt) || !Number.isFinite(Date.parse(parsed.occurredAt))) return "invalid";
|
|
560
|
+
if (typeof parsed.orderKey !== "string" || parsed.orderKey.length < 3 || parsed.orderKey.length > 2048) return "invalid";
|
|
561
|
+
return {
|
|
562
|
+
occurredAt: parsed.occurredAt,
|
|
563
|
+
orderKey: parsed.orderKey
|
|
564
|
+
};
|
|
565
|
+
} catch {
|
|
566
|
+
return "invalid";
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function parseLimit(raw) {
|
|
570
|
+
if (raw == null || raw === "") return DEFAULT_LIMIT;
|
|
571
|
+
if (!/^\d+$/.test(raw)) return "invalid";
|
|
572
|
+
const parsed = Number(raw);
|
|
573
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) return "invalid";
|
|
574
|
+
return Math.min(parsed, MAX_LIMIT);
|
|
575
|
+
}
|
|
576
|
+
function parseFilter(raw, allowed) {
|
|
577
|
+
if (raw == null) return new Set(allowed);
|
|
578
|
+
const values = raw.split(",").map((value) => value.trim()).filter(Boolean);
|
|
579
|
+
if (!values.length || values.some((value) => !allowed.includes(value))) return "invalid";
|
|
580
|
+
return new Set(values);
|
|
581
|
+
}
|
|
582
|
+
function parseTechnical(raw) {
|
|
583
|
+
if (raw == null || raw === "0") return false;
|
|
584
|
+
if (raw === "1") return true;
|
|
585
|
+
return "invalid";
|
|
586
|
+
}
|
|
587
|
+
function technicalDetail(available, text, include) {
|
|
588
|
+
if (!available) return { available: false };
|
|
589
|
+
return include ? {
|
|
590
|
+
available: true,
|
|
591
|
+
text: text.slice(0, 2e3)
|
|
592
|
+
} : { available: true };
|
|
593
|
+
}
|
|
594
|
+
var SYNC_OCCURRED_AT_SQL = "CASE WHEN finished_at IS NULL THEN started_at ELSE finished_at END";
|
|
595
|
+
function syncSelect(options) {
|
|
596
|
+
if (!options.subsystems.has("sync")) return null;
|
|
597
|
+
const predicates = [];
|
|
598
|
+
if (!options.severities.has("info")) predicates.push("ok = 0");
|
|
599
|
+
if (!options.severities.has("error")) predicates.push("ok <> 0");
|
|
600
|
+
if (!options.severities.has("info") && !options.severities.has("error")) return null;
|
|
601
|
+
if (options.cursor) predicates.push(`(${SYNC_OCCURRED_AT_SQL} < @cursorOccurredAt OR
|
|
602
|
+
(${SYNC_OCCURRED_AT_SQL} = @cursorOccurredAt AND
|
|
603
|
+
's:' || printf('%020d', id) < @cursorOrderKey))`);
|
|
604
|
+
return `SELECT 'sync' AS source_type, id AS source_id,
|
|
605
|
+
's:' || printf('%020d', id) AS order_key,
|
|
606
|
+
${SYNC_OCCURRED_AT_SQL} AS occurred_at,
|
|
607
|
+
CASE WHEN ok <> 0 THEN 'succeeded' ELSE 'failed' END AS status,
|
|
608
|
+
ops_in AS metric_a, ops_out AS metric_b,
|
|
609
|
+
CASE
|
|
610
|
+
WHEN lower(error) LIKE '%auth%' OR lower(error) LIKE '%unauthorized%' THEN 'authentication'
|
|
611
|
+
WHEN lower(error) LIKE '%timeout%' OR lower(error) LIKE '%timed out%' THEN 'timeout'
|
|
612
|
+
WHEN lower(error) LIKE '%version%' OR lower(error) LIKE '%capability%' THEN 'compatibility'
|
|
613
|
+
WHEN lower(error) LIKE '%connect%' OR lower(error) LIKE '%network%'
|
|
614
|
+
OR lower(error) LIKE '%dns%' THEN 'connectivity'
|
|
615
|
+
ELSE 'unspecified'
|
|
616
|
+
END AS category
|
|
617
|
+
FROM sync_attempts ${predicates.length ? `WHERE ${predicates.join(" AND ")}` : ""}
|
|
618
|
+
ORDER BY ${SYNC_OCCURRED_AT_SQL} DESC, id DESC
|
|
619
|
+
LIMIT @sourceLimit`;
|
|
620
|
+
}
|
|
621
|
+
function observerSelect(options) {
|
|
622
|
+
if (!options.severities.has("error")) return null;
|
|
623
|
+
const observer = options.subsystems.has("observer");
|
|
624
|
+
const capture = options.subsystems.has("capture");
|
|
625
|
+
if (!observer && !capture) return null;
|
|
626
|
+
let providerFilter = "";
|
|
627
|
+
if (observer && !capture) providerFilter = "AND observer_provider IS NOT NULL";
|
|
628
|
+
if (capture && !observer) providerFilter = "AND observer_provider IS NULL";
|
|
629
|
+
const cursorFilter = options.cursor ? `AND (updated_at < @cursorOccurredAt OR
|
|
630
|
+
(updated_at = @cursorOccurredAt AND
|
|
631
|
+
'o:' || printf('%020d', id) < @cursorOrderKey))` : "";
|
|
632
|
+
return [
|
|
633
|
+
"error",
|
|
634
|
+
"failed",
|
|
635
|
+
"gave_up"
|
|
636
|
+
].map((status) => `SELECT * FROM (
|
|
637
|
+
SELECT
|
|
638
|
+
CASE WHEN observer_provider IS NULL THEN 'capture_failure' ELSE 'observer' END AS source_type,
|
|
639
|
+
id AS source_id, 'o:' || printf('%020d', id) AS order_key,
|
|
640
|
+
updated_at AS occurred_at, status, attempt_count AS metric_a,
|
|
641
|
+
NULL AS metric_b,
|
|
642
|
+
CASE
|
|
643
|
+
WHEN lower(COALESCE(observer_error_code, error_type)) LIKE '%auth%' THEN 'authentication'
|
|
644
|
+
WHEN lower(COALESCE(observer_error_code, error_type)) LIKE '%rate%'
|
|
645
|
+
OR lower(COALESCE(observer_error_code, error_type)) LIKE '%limit%' THEN 'rate limit'
|
|
646
|
+
WHEN lower(COALESCE(observer_error_code, error_type)) LIKE '%timeout%' THEN 'timeout'
|
|
647
|
+
WHEN lower(COALESCE(observer_error_code, error_type)) LIKE '%schema%'
|
|
648
|
+
OR lower(COALESCE(observer_error_code, error_type)) LIKE '%parse%' THEN 'response format'
|
|
649
|
+
ELSE 'unspecified'
|
|
650
|
+
END AS category
|
|
651
|
+
FROM raw_event_flush_batches
|
|
652
|
+
WHERE status = '${status}' ${providerFilter} ${cursorFilter}
|
|
653
|
+
ORDER BY updated_at DESC, id DESC
|
|
654
|
+
LIMIT @sourceLimit
|
|
655
|
+
)`).join(" UNION ALL ");
|
|
656
|
+
}
|
|
657
|
+
function maintenanceSelect(options) {
|
|
658
|
+
if (!options.subsystems.has("maintenance")) return null;
|
|
659
|
+
const statuses = [];
|
|
660
|
+
if (options.severities.has("info")) statuses.push("'pending'", "'running'");
|
|
661
|
+
if (options.severities.has("warning")) statuses.push("'cancelled'");
|
|
662
|
+
if (options.severities.has("error")) statuses.push("'failed'");
|
|
663
|
+
if (!statuses.length) return null;
|
|
664
|
+
return `SELECT 'maintenance' AS source_type, kind AS source_id,
|
|
665
|
+
'm:' || hex(kind) AS order_key, updated_at AS occurred_at,
|
|
666
|
+
status, progress_current AS metric_a, progress_total AS metric_b,
|
|
667
|
+
NULL AS category
|
|
668
|
+
FROM maintenance_jobs WHERE status IN (${statuses.join(", ")})`;
|
|
669
|
+
}
|
|
670
|
+
function backlogSelect(options) {
|
|
671
|
+
if (!options.subsystems.has("capture")) return null;
|
|
672
|
+
const warning = options.severities.has("warning");
|
|
673
|
+
const error = options.severities.has("error");
|
|
674
|
+
if (!warning && !error) return null;
|
|
675
|
+
let having = "pending >= 200";
|
|
676
|
+
if (!warning) having = "pending >= 1000";
|
|
677
|
+
if (!error) having = "pending >= 200 AND pending < 1000";
|
|
678
|
+
return `WITH candidate_sessions AS MATERIALIZED (
|
|
679
|
+
SELECT source, stream_id, last_flushed_event_seq, updated_at
|
|
680
|
+
FROM raw_event_sessions
|
|
681
|
+
WHERE last_received_event_seq > last_flushed_event_seq
|
|
682
|
+
ORDER BY updated_at DESC
|
|
683
|
+
LIMIT 1001
|
|
684
|
+
), bounded_sessions AS MATERIALIZED (
|
|
685
|
+
SELECT source, stream_id, last_flushed_event_seq, updated_at
|
|
686
|
+
FROM candidate_sessions
|
|
687
|
+
ORDER BY updated_at DESC
|
|
688
|
+
LIMIT 1000
|
|
689
|
+
), retained_sessions AS MATERIALIZED (
|
|
690
|
+
SELECT updated_at,
|
|
691
|
+
(SELECT COUNT(*) FROM raw_events AS events
|
|
692
|
+
WHERE events.source = sessions.source
|
|
693
|
+
AND events.stream_id = sessions.stream_id
|
|
694
|
+
AND events.event_seq > sessions.last_flushed_event_seq) AS pending
|
|
695
|
+
FROM bounded_sessions AS sessions
|
|
696
|
+
)
|
|
697
|
+
SELECT 'backlog' AS source_type, 0 AS source_id,
|
|
698
|
+
'b:' || printf('%020d', 0) AS order_key, occurred_at,
|
|
699
|
+
CASE WHEN pending >= 1000 THEN 'error' ELSE 'warning' END AS status,
|
|
700
|
+
pending AS metric_a, sessions AS metric_b,
|
|
701
|
+
CASE WHEN candidate_count > 1000 THEN 'capped' ELSE NULL END AS category
|
|
702
|
+
FROM (
|
|
703
|
+
SELECT MAX(updated_at) AS occurred_at,
|
|
704
|
+
SUM(pending) AS pending,
|
|
705
|
+
COUNT(*) FILTER (WHERE pending > 0) AS sessions,
|
|
706
|
+
(SELECT COUNT(*) FROM candidate_sessions) AS candidate_count
|
|
707
|
+
FROM retained_sessions
|
|
708
|
+
WHERE pending > 0
|
|
709
|
+
) WHERE ${having}`;
|
|
710
|
+
}
|
|
711
|
+
function sourceSelects(options) {
|
|
712
|
+
return [
|
|
713
|
+
syncSelect(options),
|
|
714
|
+
observerSelect(options),
|
|
715
|
+
maintenanceSelect(options),
|
|
716
|
+
backlogSelect(options)
|
|
717
|
+
].filter((select) => select != null);
|
|
718
|
+
}
|
|
719
|
+
function boundedSourceSelect(select, hasCursor) {
|
|
720
|
+
return `SELECT * FROM (
|
|
721
|
+
SELECT * FROM (${select})
|
|
722
|
+
${hasCursor ? "WHERE occurred_at < @cursorOccurredAt OR (occurred_at = @cursorOccurredAt AND order_key < @cursorOrderKey)" : ""}
|
|
723
|
+
ORDER BY occurred_at DESC, order_key DESC
|
|
724
|
+
LIMIT @sourceLimit
|
|
725
|
+
)`;
|
|
726
|
+
}
|
|
727
|
+
function loadSourceRows(store, options) {
|
|
728
|
+
const selects = sourceSelects(options);
|
|
729
|
+
if (!selects.length) return [];
|
|
730
|
+
const boundedSelects = selects.map((select) => boundedSourceSelect(select, options.cursor != null));
|
|
731
|
+
const params = {
|
|
732
|
+
resultLimit: options.limit + 1,
|
|
733
|
+
sourceLimit: options.limit + 1
|
|
734
|
+
};
|
|
735
|
+
if (options.cursor) {
|
|
736
|
+
params.cursorOccurredAt = options.cursor.occurredAt;
|
|
737
|
+
params.cursorOrderKey = options.cursor.orderKey;
|
|
738
|
+
}
|
|
739
|
+
return store.db.prepare(`SELECT * FROM (${boundedSelects.join(" UNION ALL ")})
|
|
740
|
+
ORDER BY occurred_at DESC, order_key DESC
|
|
741
|
+
LIMIT @resultLimit`).all(params);
|
|
742
|
+
}
|
|
743
|
+
function syncEvent(row, includeTechnical) {
|
|
744
|
+
const succeeded = row.status === "succeeded";
|
|
745
|
+
const opsIn = Number(row.metric_a ?? 0);
|
|
746
|
+
const opsOut = Number(row.metric_b ?? 0);
|
|
747
|
+
const category = row.category ?? "unspecified";
|
|
748
|
+
return {
|
|
749
|
+
id: opaqueId("sync-attempt", row.source_id),
|
|
750
|
+
orderKey: row.order_key,
|
|
751
|
+
occurred_at: row.occurred_at,
|
|
752
|
+
severity: succeeded ? "info" : "error",
|
|
753
|
+
subsystem: "sync",
|
|
754
|
+
code: succeeded ? "sync_attempt_succeeded" : "sync_attempt_failed",
|
|
755
|
+
message: succeeded ? "A sync attempt completed." : "A sync attempt failed before all work completed.",
|
|
756
|
+
recovery: succeeded ? void 0 : {
|
|
757
|
+
label: "Open advanced sync diagnostics",
|
|
758
|
+
href: "#advanced/sync/diagnostics"
|
|
759
|
+
},
|
|
760
|
+
technical_detail: technicalDetail(true, succeeded ? `${opsIn} inbound and ${opsOut} outbound operations.` : `Failure category: ${category}. ${opsIn} inbound and ${opsOut} outbound operations.`, includeTechnical)
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
function failureEvent(row, includeTechnical) {
|
|
764
|
+
const subsystem = row.source_type === "observer" ? "observer" : "capture";
|
|
765
|
+
const attempts = Math.max(0, Number(row.metric_a ?? 0));
|
|
766
|
+
const gaveUp = row.status === "gave_up";
|
|
767
|
+
return {
|
|
768
|
+
id: opaqueId("processing-failure", row.source_id),
|
|
769
|
+
orderKey: row.order_key,
|
|
770
|
+
occurred_at: row.occurred_at,
|
|
771
|
+
severity: "error",
|
|
772
|
+
subsystem,
|
|
773
|
+
code: `${subsystem}_flush_${gaveUp ? "gave_up" : "failed"}`,
|
|
774
|
+
message: gaveUp ? "Processing stopped after all retry attempts were exhausted." : "Processing failed and queued events are waiting for retry.",
|
|
775
|
+
recovery: {
|
|
776
|
+
label: "Open Health",
|
|
777
|
+
href: "#health"
|
|
778
|
+
},
|
|
779
|
+
technical_detail: technicalDetail(true, `Failure category: ${row.category ?? "unspecified"}. Attempts: ${attempts}.`, includeTechnical)
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
function maintenanceEvent(row, includeTechnical) {
|
|
783
|
+
let severity = "info";
|
|
784
|
+
let code = "maintenance_job_active";
|
|
785
|
+
let message = "A background maintenance task is active.";
|
|
786
|
+
if (row.status === "failed") {
|
|
787
|
+
severity = "error";
|
|
788
|
+
code = "maintenance_job_failed";
|
|
789
|
+
message = "A background maintenance task failed.";
|
|
790
|
+
} else if (row.status === "cancelled") {
|
|
791
|
+
severity = "warning";
|
|
792
|
+
code = "maintenance_job_cancelled";
|
|
793
|
+
message = "A background maintenance task was cancelled.";
|
|
794
|
+
}
|
|
795
|
+
const total = row.metric_b == null ? "unknown" : String(row.metric_b);
|
|
796
|
+
return {
|
|
797
|
+
id: opaqueId("maintenance", row.source_id),
|
|
798
|
+
orderKey: row.order_key,
|
|
799
|
+
occurred_at: row.occurred_at,
|
|
800
|
+
severity,
|
|
801
|
+
subsystem: "maintenance",
|
|
802
|
+
code,
|
|
803
|
+
message,
|
|
804
|
+
recovery: severity === "error" ? {
|
|
805
|
+
label: "Open Health",
|
|
806
|
+
href: "#health"
|
|
807
|
+
} : void 0,
|
|
808
|
+
technical_detail: technicalDetail(true, `Progress: ${Number(row.metric_a ?? 0)} of ${total}.`, includeTechnical)
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
function backlogEvent(row, includeTechnical) {
|
|
812
|
+
const severity = row.status === "error" ? "error" : "warning";
|
|
813
|
+
const pending = Number(row.metric_a ?? 0);
|
|
814
|
+
const sessions = Number(row.metric_b ?? 0);
|
|
815
|
+
const countPrefix = row.category === "capped" ? "At least " : "";
|
|
816
|
+
const sessionLabel = sessions === 1 ? "session" : "sessions";
|
|
817
|
+
return {
|
|
818
|
+
id: opaqueId("capture-backlog", 0),
|
|
819
|
+
orderKey: row.order_key,
|
|
820
|
+
occurred_at: row.occurred_at,
|
|
821
|
+
severity,
|
|
822
|
+
subsystem: "capture",
|
|
823
|
+
code: severity === "error" ? "capture_backlog_high" : "capture_backlog_growing",
|
|
824
|
+
message: severity === "error" ? "The capture queue has a high pending backlog." : "The capture queue is growing and may need attention.",
|
|
825
|
+
recovery: {
|
|
826
|
+
label: "Open Health",
|
|
827
|
+
href: "#health"
|
|
828
|
+
},
|
|
829
|
+
technical_detail: technicalDetail(true, `${countPrefix}${pending} pending events across ${sessions} ${sessionLabel}.`, includeTechnical)
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
function collectEvents(store, options) {
|
|
833
|
+
return loadSourceRows(store, options).map((row) => {
|
|
834
|
+
if (row.source_type === "sync") return syncEvent(row, options.includeTechnical);
|
|
835
|
+
if (row.source_type === "maintenance") return maintenanceEvent(row, options.includeTechnical);
|
|
836
|
+
if (row.source_type === "backlog") return backlogEvent(row, options.includeTechnical);
|
|
837
|
+
return failureEvent(row, options.includeTechnical);
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
function diagnosticsRoutes(getStore) {
|
|
841
|
+
const app = new Hono();
|
|
842
|
+
app.get("/api/diagnostics/events", (c) => {
|
|
843
|
+
const limit = parseLimit(c.req.query("limit"));
|
|
844
|
+
const cursor = parseCursor(c.req.query("cursor"));
|
|
845
|
+
const severities = parseFilter(c.req.query("severity"), DIAGNOSTIC_SEVERITIES);
|
|
846
|
+
const subsystems = parseFilter(c.req.query("subsystem"), DIAGNOSTIC_SUBSYSTEMS);
|
|
847
|
+
const includeTechnical = parseTechnical(c.req.query("includeTechnical"));
|
|
848
|
+
if (limit === "invalid" || cursor === "invalid" || severities === "invalid" || subsystems === "invalid" || includeTechnical === "invalid") return c.json({ error: "invalid_diagnostics_query" }, 400);
|
|
849
|
+
const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
850
|
+
const events = collectEvents(getStore(), {
|
|
851
|
+
cursor,
|
|
852
|
+
includeTechnical,
|
|
853
|
+
limit,
|
|
854
|
+
severities,
|
|
855
|
+
subsystems
|
|
856
|
+
});
|
|
857
|
+
const orderedItems = events.slice(0, limit);
|
|
858
|
+
const items = orderedItems.map(({ orderKey: _orderKey, ...event }) => event);
|
|
859
|
+
const lastItem = orderedItems.at(-1);
|
|
860
|
+
const nextCursor = events.length > limit && lastItem ? encodeCursor(lastItem) : null;
|
|
861
|
+
c.header("Cache-Control", "no-store");
|
|
862
|
+
return c.json({
|
|
863
|
+
contract_version: 1,
|
|
864
|
+
items,
|
|
865
|
+
next_cursor: nextCursor,
|
|
866
|
+
redacted: true,
|
|
867
|
+
generated_at: generatedAt
|
|
868
|
+
});
|
|
869
|
+
});
|
|
870
|
+
return app;
|
|
871
|
+
}
|
|
872
|
+
//#endregion
|
|
516
873
|
//#region src/routes/health.ts
|
|
517
874
|
function databaseReachable(getStore) {
|
|
518
875
|
try {
|
|
@@ -801,18 +1158,6 @@ function countVisibleMemoryRows(store, filters) {
|
|
|
801
1158
|
const row = store.db.prepare(`SELECT COUNT(*) AS total FROM ${from} WHERE ${clauses.join(" AND ")}`).get(...filterResult.params);
|
|
802
1159
|
return Number(row?.total ?? 0);
|
|
803
1160
|
}
|
|
804
|
-
function summaryLikeSqlPredicate() {
|
|
805
|
-
return `(
|
|
806
|
-
LOWER(TRIM(COALESCE(memory_items.kind, ''))) = 'session_summary'
|
|
807
|
-
OR (
|
|
808
|
-
json_valid(COALESCE(memory_items.metadata_json, ''))
|
|
809
|
-
AND (
|
|
810
|
-
COALESCE(json_type(memory_items.metadata_json, '$.is_summary') = 'true', 0)
|
|
811
|
-
OR LOWER(TRIM(COALESCE(json_extract(memory_items.metadata_json, '$.source'), ''))) = 'observer_summary'
|
|
812
|
-
)
|
|
813
|
-
)
|
|
814
|
-
)`;
|
|
815
|
-
}
|
|
816
1161
|
function memorySearchSql(query) {
|
|
817
1162
|
const textClause = `INSTR(codemem_casefold(
|
|
818
1163
|
COALESCE(memory_items.title, '') || CHAR(10) ||
|
|
@@ -1351,9 +1696,12 @@ var PACK_KEYS = /* @__PURE__ */ new Set([
|
|
|
1351
1696
|
"compact_detail_count",
|
|
1352
1697
|
"db_path",
|
|
1353
1698
|
"identity_target",
|
|
1354
|
-
"attempt"
|
|
1699
|
+
"attempt",
|
|
1700
|
+
"automatic_context"
|
|
1355
1701
|
]);
|
|
1356
1702
|
var LEDGER_KEYS = /* @__PURE__ */ new Set([
|
|
1703
|
+
"automatic_recall",
|
|
1704
|
+
"evaluation_key",
|
|
1357
1705
|
"action",
|
|
1358
1706
|
"attempt_id",
|
|
1359
1707
|
"started_at",
|
|
@@ -1459,6 +1807,48 @@ function attemptMetadata(payload) {
|
|
|
1459
1807
|
requestId: payload.request_id ?? null
|
|
1460
1808
|
};
|
|
1461
1809
|
}
|
|
1810
|
+
function validateAutomaticContext(value) {
|
|
1811
|
+
if (value === null) return null;
|
|
1812
|
+
if (!isRecord(value)) return "automatic_context must be an object or null";
|
|
1813
|
+
for (const key of Object.keys(value)) if (key !== "source" && key !== "host_session_id") return `automatic_context contains unsupported field: ${key}`;
|
|
1814
|
+
const source = value.source;
|
|
1815
|
+
const hostSessionId = value.host_session_id;
|
|
1816
|
+
if (typeof source !== "string" || !source.trim() || source.length > 64) return "automatic_context source is invalid";
|
|
1817
|
+
if (typeof hostSessionId !== "string" || !hostSessionId.trim() || hostSessionId.length > MAX_METADATA_FIELD_CHARS || isAbsolutePath(hostSessionId)) return "automatic_context host_session_id is invalid";
|
|
1818
|
+
return {
|
|
1819
|
+
source: source.trim(),
|
|
1820
|
+
hostSessionId: hostSessionId.trim()
|
|
1821
|
+
};
|
|
1822
|
+
}
|
|
1823
|
+
function resolveRequestAutomaticContext(value, attempt) {
|
|
1824
|
+
if (Object.hasOwn(value, "automatic_context")) return validateAutomaticContext(value.automatic_context);
|
|
1825
|
+
if (!attempt) return void 0;
|
|
1826
|
+
const source = typeof attempt.source === "string" ? attempt.source.trim().toLowerCase() : "";
|
|
1827
|
+
if (source && source !== "opencode") return void 0;
|
|
1828
|
+
const hostSessionId = attempt.source_session_id;
|
|
1829
|
+
if (source === "opencode" && typeof hostSessionId === "string" && hostSessionId.trim()) return {
|
|
1830
|
+
source,
|
|
1831
|
+
hostSessionId: hostSessionId.trim()
|
|
1832
|
+
};
|
|
1833
|
+
return null;
|
|
1834
|
+
}
|
|
1835
|
+
function packRenderOptions(value) {
|
|
1836
|
+
if (value.compact == null && value.compact_detail_count == null) return void 0;
|
|
1837
|
+
return {
|
|
1838
|
+
compact: value.compact === true || value.compact_detail_count != null,
|
|
1839
|
+
...value.compact_detail_count != null ? { compactDetailCount: value.compact_detail_count } : {}
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
function packRequestArgs(request) {
|
|
1843
|
+
return [
|
|
1844
|
+
request.context,
|
|
1845
|
+
request.limit,
|
|
1846
|
+
request.tokenBudget,
|
|
1847
|
+
request.filters,
|
|
1848
|
+
request.renderOptions,
|
|
1849
|
+
request.automaticContext
|
|
1850
|
+
];
|
|
1851
|
+
}
|
|
1462
1852
|
function validatePackRequest(value) {
|
|
1463
1853
|
if (!isRecord(value)) return "request body must be an object";
|
|
1464
1854
|
for (const key of Object.keys(value)) if (!PACK_KEYS.has(key)) return `request body contains unsupported field: ${key}`;
|
|
@@ -1490,6 +1880,8 @@ function validatePackRequest(value) {
|
|
|
1490
1880
|
if (attemptError) return attemptError;
|
|
1491
1881
|
attempt = value.attempt;
|
|
1492
1882
|
}
|
|
1883
|
+
const automaticContext = resolveRequestAutomaticContext(value, attempt);
|
|
1884
|
+
if (typeof automaticContext === "string") return automaticContext;
|
|
1493
1885
|
const filters = {};
|
|
1494
1886
|
if (value.all_projects !== true) {
|
|
1495
1887
|
const envProject = process.env.CODEMEM_PROJECT?.trim() || null;
|
|
@@ -1499,18 +1891,14 @@ function validatePackRequest(value) {
|
|
|
1499
1891
|
if (project) filters.project = project;
|
|
1500
1892
|
}
|
|
1501
1893
|
if (workingSetFiles.length > 0) filters.working_set_paths = workingSetFiles;
|
|
1502
|
-
let renderOptions;
|
|
1503
|
-
if (value.compact != null || value.compact_detail_count != null) renderOptions = {
|
|
1504
|
-
compact: value.compact === true || value.compact_detail_count != null,
|
|
1505
|
-
...value.compact_detail_count != null ? { compactDetailCount: value.compact_detail_count } : {}
|
|
1506
|
-
};
|
|
1507
1894
|
return {
|
|
1508
1895
|
context,
|
|
1509
1896
|
limit,
|
|
1510
1897
|
tokenBudget,
|
|
1511
1898
|
filters,
|
|
1512
|
-
renderOptions,
|
|
1513
|
-
attempt
|
|
1899
|
+
renderOptions: packRenderOptions(value),
|
|
1900
|
+
attempt,
|
|
1901
|
+
automaticContext
|
|
1514
1902
|
};
|
|
1515
1903
|
}
|
|
1516
1904
|
function ledgerFailureStatus(reason) {
|
|
@@ -1519,19 +1907,37 @@ function ledgerFailureStatus(reason) {
|
|
|
1519
1907
|
if (reason === "storage_unavailable") return 503;
|
|
1520
1908
|
return 400;
|
|
1521
1909
|
}
|
|
1910
|
+
function dispatchRecallMeasurement(store, payload) {
|
|
1911
|
+
const action = payload.action;
|
|
1912
|
+
if (payload.automatic_recall === void 0 && action !== "recall") return null;
|
|
1913
|
+
const isValidMeasurement = isAutomaticRecallMeasurement(payload.automatic_recall) && typeof payload.evaluation_key === "string" && /^[a-f0-9]{64}$/.test(payload.evaluation_key);
|
|
1914
|
+
if (action === "delivery") {
|
|
1915
|
+
if (!isValidMeasurement) return null;
|
|
1916
|
+
try {
|
|
1917
|
+
recordAutomaticRecall(store.db, payload.attempt_id, payload.evaluation_key, payload.automatic_recall);
|
|
1918
|
+
} catch {}
|
|
1919
|
+
return null;
|
|
1920
|
+
}
|
|
1921
|
+
if (action !== "recall" || !isValidMeasurement) return "invalid automatic recall measurement";
|
|
1922
|
+
return recordAutomaticRecall(store.db, payload.attempt_id, payload.evaluation_key, payload.automatic_recall);
|
|
1923
|
+
}
|
|
1522
1924
|
function dispatchLedger(store, payload) {
|
|
1523
1925
|
const action = payload.action;
|
|
1524
|
-
if (action !== "record" && action !== "delivery" && action !== "cache_reuse") return "ledger action is invalid";
|
|
1525
1926
|
const metadata = attemptMetadata(payload);
|
|
1526
1927
|
if (action === "delivery") {
|
|
1527
1928
|
const status = payload.delivery_status;
|
|
1528
1929
|
if (status !== "handed_off" && status !== "failed" && status !== "unknown") return "delivery action requires a valid delivery_status";
|
|
1529
|
-
|
|
1930
|
+
const outcome = tryUpdateRetrievalDelivery(store.db, metadata.attemptId, status);
|
|
1931
|
+
if (outcome.ok) dispatchRecallMeasurement(store, payload);
|
|
1932
|
+
return outcome;
|
|
1530
1933
|
}
|
|
1934
|
+
const measurement = dispatchRecallMeasurement(store, payload);
|
|
1935
|
+
if (measurement !== null) return measurement;
|
|
1531
1936
|
if (action === "cache_reuse") {
|
|
1532
1937
|
if (typeof payload.original_attempt_id !== "string" || !payload.original_attempt_id) return "cache_reuse action requires original_attempt_id";
|
|
1533
1938
|
return clonePromptPackAttempt(store.db, payload.original_attempt_id, metadata);
|
|
1534
1939
|
}
|
|
1940
|
+
if (action !== "record") return "ledger action is invalid";
|
|
1535
1941
|
if (payload.retrieval_status !== "skipped" && payload.retrieval_status !== "failed" || typeof payload.failure_code !== "string" || !payload.failure_code || typeof payload.failure_stage !== "string" || !payload.failure_stage) return "record action requires retrieval_status, failure_code, and failure_stage";
|
|
1536
1942
|
return recordPromptPackTerminal(store.db, metadata, payload.retrieval_status, payload.failure_code, payload.failure_stage);
|
|
1537
1943
|
}
|
|
@@ -1568,10 +1974,10 @@ function packTransportRoutes(getStore) {
|
|
|
1568
1974
|
const target = validateViewerTarget(store, parsed, { requireCurrentIdentity: true });
|
|
1569
1975
|
if (!target.ok) return c.json(target.body, target.status);
|
|
1570
1976
|
if (!request.attempt) {
|
|
1571
|
-
const pack = await store.buildMemoryPackAsync(request
|
|
1977
|
+
const pack = await store.buildMemoryPackAsync(...packRequestArgs(request));
|
|
1572
1978
|
return c.json(pack);
|
|
1573
1979
|
}
|
|
1574
|
-
const artifacts = await store.buildMemoryPackWithTraceAsync(request
|
|
1980
|
+
const artifacts = await store.buildMemoryPackWithTraceAsync(...packRequestArgs(request));
|
|
1575
1981
|
let ledgerArtifactFingerprint;
|
|
1576
1982
|
try {
|
|
1577
1983
|
ledgerArtifactFingerprint = promptPackArtifactFingerprint(store.db, request.context, request.filters, artifacts);
|
|
@@ -2128,7 +2534,7 @@ function statsRoutes(getStore) {
|
|
|
2128
2534
|
error: job.error
|
|
2129
2535
|
}));
|
|
2130
2536
|
return c.json({
|
|
2131
|
-
...store
|
|
2537
|
+
...healthStats(store),
|
|
2132
2538
|
viewer_pid: process.pid,
|
|
2133
2539
|
maintenance_jobs: surfacedJobs
|
|
2134
2540
|
});
|
|
@@ -2193,6 +2599,15 @@ function statsRoutes(getStore) {
|
|
|
2193
2599
|
});
|
|
2194
2600
|
return app;
|
|
2195
2601
|
}
|
|
2602
|
+
function healthStats(store) {
|
|
2603
|
+
return {
|
|
2604
|
+
...store.stats(),
|
|
2605
|
+
automatic_recall: automaticRecallHealth(store.db, {
|
|
2606
|
+
actorId: store.actorId,
|
|
2607
|
+
deviceId: store.deviceId
|
|
2608
|
+
})
|
|
2609
|
+
};
|
|
2610
|
+
}
|
|
2196
2611
|
//#endregion
|
|
2197
2612
|
//#region src/routes/team-setup-view.ts
|
|
2198
2613
|
var enabled = {
|
|
@@ -10201,6 +10616,26 @@ function closeStore() {
|
|
|
10201
10616
|
sharedStore?.close();
|
|
10202
10617
|
sharedStore = null;
|
|
10203
10618
|
}
|
|
10619
|
+
function registerStaticRoutes(app) {
|
|
10620
|
+
const staticRoot = process.env.CODEMEM_VIEWER_STATIC_DIR ?? join(import.meta.dirname ?? ".", "../static");
|
|
10621
|
+
app.use("/assets/*", async (c, next) => {
|
|
10622
|
+
c.header("Cache-Control", "no-cache");
|
|
10623
|
+
await next();
|
|
10624
|
+
});
|
|
10625
|
+
app.use("/assets/*", serveStatic({
|
|
10626
|
+
root: staticRoot,
|
|
10627
|
+
rewriteRequestPath: (path) => path.replace(/^\/assets/, ""),
|
|
10628
|
+
precompressed: true
|
|
10629
|
+
}));
|
|
10630
|
+
const indexPath = join(staticRoot, "index.html");
|
|
10631
|
+
if (!existsSync(indexPath)) throw new Error(`Viewer assets missing at ${indexPath}. Run \`pnpm build\` from the repo root before starting the viewer.`);
|
|
10632
|
+
const indexHtml = readFileSync(indexPath, "utf-8");
|
|
10633
|
+
app.get("*", (c) => {
|
|
10634
|
+
if (c.req.path.startsWith("/api/")) return c.json({ error: "not found" }, 404);
|
|
10635
|
+
c.header("Cache-Control", "no-store");
|
|
10636
|
+
return c.html(indexHtml);
|
|
10637
|
+
});
|
|
10638
|
+
}
|
|
10204
10639
|
function createApp(opts) {
|
|
10205
10640
|
const storeFactory = opts?.storeFactory ?? getStore;
|
|
10206
10641
|
const sweeper = opts?.sweeper ?? null;
|
|
@@ -10211,6 +10646,7 @@ function createApp(opts) {
|
|
|
10211
10646
|
app.use("*", preflightHandler());
|
|
10212
10647
|
app.use("*", originGuard({ unsafeGetPathPrefixes: [TEAM_SETUP_ROUTE_PREFIX] }));
|
|
10213
10648
|
app.route("/", healthRoutes(storeFactory));
|
|
10649
|
+
app.route("/", diagnosticsRoutes(storeFactory));
|
|
10214
10650
|
app.route("/", statsRoutes(storeFactory));
|
|
10215
10651
|
app.route("/", memoryRoutes(storeFactory));
|
|
10216
10652
|
app.route("/", packTransportRoutes(storeFactory));
|
|
@@ -10237,24 +10673,7 @@ function createApp(opts) {
|
|
|
10237
10673
|
}
|
|
10238
10674
|
}));
|
|
10239
10675
|
app.route("/", updateStatusRoutes({ getUpdateStatus: opts?.getUpdateStatus }));
|
|
10240
|
-
|
|
10241
|
-
app.use("/assets/*", async (c, next) => {
|
|
10242
|
-
c.header("Cache-Control", "no-cache");
|
|
10243
|
-
await next();
|
|
10244
|
-
});
|
|
10245
|
-
app.use("/assets/*", serveStatic({
|
|
10246
|
-
root: staticRoot,
|
|
10247
|
-
rewriteRequestPath: (path) => path.replace(/^\/assets/, ""),
|
|
10248
|
-
precompressed: true
|
|
10249
|
-
}));
|
|
10250
|
-
const indexPath = join(staticRoot, "index.html");
|
|
10251
|
-
if (!existsSync(indexPath)) throw new Error(`Viewer assets missing at ${indexPath}. Run \`pnpm build\` from the repo root before starting the viewer.`);
|
|
10252
|
-
const indexHtml = readFileSync(indexPath, "utf-8");
|
|
10253
|
-
app.get("*", (c) => {
|
|
10254
|
-
if (c.req.path.startsWith("/api/")) return c.json({ error: "not found" }, 404);
|
|
10255
|
-
c.header("Cache-Control", "no-store");
|
|
10256
|
-
return c.html(indexHtml);
|
|
10257
|
-
});
|
|
10676
|
+
registerStaticRoutes(app);
|
|
10258
10677
|
return app;
|
|
10259
10678
|
}
|
|
10260
10679
|
/**
|