@codemem/server 0.46.0-alpha.1 → 0.46.0-alpha.2
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 +185 -97
- package/dist/index.js.map +1 -1
- package/dist/raw-event-inbox.d.ts +8 -0
- package/dist/raw-event-inbox.d.ts.map +1 -1
- package/dist/routes/raw-events.d.ts.map +1 -1
- package/package.json +2 -2
- package/static/app.js +2 -2
- package/static/app.js.br +0 -0
- package/static/app.js.gz +0 -0
- package/static/index.html +15 -4
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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, CodememConfigMutationError, CoordinatorReciprocalApprovalRequestChangedError, DEFAULT_TIME_WINDOW_S, LEGACY_SHARED_REVIEW_SCOPE_ID, LOCAL_DEFAULT_SCOPE_ID, LOCAL_SYNC_CAPABILITY, LOCAL_SYNC_FEATURES, LegacyTeamSetupAdditiveConvergenceError, LegacyTeamSetupRosterCapacityError, MEMORY_FILTER_FIELD_TYPES, MEMORY_FILTER_NAMES, MEMORY_KIND_DESCRIPTIONS, MemoryStore, ObserverClient, PROMPT_TRANSPORT_PROTOCOL_RANGE, REMEMBER_MEMORY_KINDS, 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, buildDistillReport, buildFilterClausesWithContext, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, buildRawEventEnvelopeFromPiEvent, 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, dedupeOrderedIds, 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, judgeDistillReport, legacyTeamCandidateId, legacyTeamCandidateProjectInventory, legacyTeamCanonicalProjectRef, legacyTeamDeviceRef, legacyTeamResolvedProjectRef, legacyTeamSetupApiErrorCode, listAuthorizedScopesForPeer, listCoordinatorJoinRequests, listDeviceIdentityInventory, listInboundScopeRejections, listLegacyRecipientPolicyProjections, listMaintenanceJobs, listObserverProviderOptions, listPerPeerScopeSyncState, listProjectScopeCandidates, listProjectScopeInventory, listProjectScopeSettingsMappings, listRecipientPolicyIntent, listRecipientPolicyReview, listSharingDomainSettingsScopes, loadMemorySnapshotPageForPeer, loadReplicationOpsForPeer, lookupCoordinatorPeers, memoryFilterValueMatchesType, mergeAddresses, migrateRecipientPolicyIntent, mutateCodememConfigFile, negotiateSyncCapability, normalizeAddress, normalizeHumanPresentationName, normalizeSyncCapability, normalizeSyncFeatures, normalizeTeammateName, parseAcceptedProjectIntent, parsePositiveMemoryId, parseReassignScopePayload, parseRecipientPolicyEdgeCommitRequest, parseStrictInteger, parseSyncScopeRequest, persistShareOperation, personalScopeGrantStatusForPeer, planShareOperation, previewDeviceIdentityBindings, previewLegacyTeamSetupActivation, previewRecipientPolicyEdges, previewRecipientPolicyOnboarding, previewRecipientPolicyOnboardingFromReviewedIntent, probeAvailableCredentials, projectMatchesFilter, 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, resolveProjectRoot, resolveRecipientPolicyReview, resolveRecipientPolicyReviewBulk, runSyncPass, schema, serializeRecipientPolicyCoordinatorGroupMutation, serializeRecipientPolicyPublicationMutation, serializeRecipientPolicyTeamMutation, setLegacyTeamSetupDeviceAssignment, setLegacyTeamSetupDeviceDecision, setLegacyTeamSetupProjectMapping, storeVectors, summarizeInboundScopeRejections, summaryLikeSqlPredicate, supportsSyncFeature, syncScopeResetRequiredPayload, toJson, tryUpdateRetrievalDelivery, updatePeerAddresses, upsertCoordinatorGroupPreference, upsertProjectScopeSettingsMapping, validateLegacyTeamSetupCompletionManifest, validateLegacyTeamSetupCompletionManifestBinding, validateRawEvents, verifyDirectPeerSignature, verifyRecipientReviewedIntent, verifySignature } from "@codemem/core";
|
|
3
|
+
import { ACCESS_CLEANUP_OP_TYPE, CODEMEM_CONFIG_ENV_OVERRIDES, CodememConfigMutationError, CoordinatorReciprocalApprovalRequestChangedError, DEFAULT_TIME_WINDOW_S, LEGACY_SHARED_REVIEW_SCOPE_ID, LOCAL_DEFAULT_SCOPE_ID, LOCAL_SYNC_CAPABILITY, LOCAL_SYNC_FEATURES, LegacyTeamSetupAdditiveConvergenceError, LegacyTeamSetupRosterCapacityError, MEMORY_FILTER_FIELD_TYPES, MEMORY_FILTER_NAMES, MEMORY_KIND_DESCRIPTIONS, MemoryStore, ObserverClient, PROMPT_TRANSPORT_PROTOCOL_RANGE, REMEMBER_MEMORY_KINDS, 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, buildDistillReport, buildFilterClausesWithContext, buildPiFlushSignalFromEvent, buildRawEventEnvelopeFromCodexHook, buildRawEventEnvelopeFromHook, buildRawEventEnvelopeFromPiEvent, 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, dedupeOrderedIds, 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, judgeDistillReport, legacyTeamCandidateId, legacyTeamCandidateProjectInventory, legacyTeamCanonicalProjectRef, legacyTeamDeviceRef, legacyTeamResolvedProjectRef, legacyTeamSetupApiErrorCode, listAuthorizedScopesForPeer, listCoordinatorJoinRequests, listDeviceIdentityInventory, listInboundScopeRejections, listLegacyRecipientPolicyProjections, listMaintenanceJobs, listObserverProviderOptions, listPerPeerScopeSyncState, listProjectScopeCandidates, listProjectScopeInventory, listProjectScopeSettingsMappings, listRecipientPolicyIntent, listRecipientPolicyReview, listSharingDomainSettingsScopes, loadMemorySnapshotPageForPeer, loadReplicationOpsForPeer, lookupCoordinatorPeers, memoryFilterValueMatchesType, mergeAddresses, migrateRecipientPolicyIntent, mutateCodememConfigFile, negotiateSyncCapability, normalizeAddress, normalizeHumanPresentationName, normalizeSyncCapability, normalizeSyncFeatures, normalizeTeammateName, parseAcceptedProjectIntent, parsePositiveMemoryId, parseReassignScopePayload, parseRecipientPolicyEdgeCommitRequest, parseStrictInteger, parseSyncScopeRequest, persistShareOperation, personalScopeGrantStatusForPeer, planShareOperation, previewDeviceIdentityBindings, previewLegacyTeamSetupActivation, previewRecipientPolicyEdges, previewRecipientPolicyOnboarding, previewRecipientPolicyOnboardingFromReviewedIntent, probeAvailableCredentials, projectMatchesFilter, 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, resolveProjectRoot, resolveRecipientPolicyReview, resolveRecipientPolicyReviewBulk, runSyncPass, schema, serializeRecipientPolicyCoordinatorGroupMutation, serializeRecipientPolicyPublicationMutation, serializeRecipientPolicyTeamMutation, setLegacyTeamSetupDeviceAssignment, setLegacyTeamSetupDeviceDecision, setLegacyTeamSetupProjectMapping, storeVectors, summarizeInboundScopeRejections, summaryLikeSqlPredicate, supportsSyncFeature, syncScopeResetRequiredPayload, toJson, tryUpdateRetrievalDelivery, updatePeerAddresses, upsertCoordinatorGroupPreference, upsertProjectScopeSettingsMapping, validateLegacyTeamSetupCompletionManifest, validateLegacyTeamSetupCompletionManifestBinding, validateRawEvents, verifyDirectPeerSignature, verifyRecipientReviewedIntent, verifySignature } 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";
|
|
@@ -2675,21 +2675,26 @@ function resolveRawEventInboxDirectory(dbPath, homeDir = homedir()) {
|
|
|
2675
2675
|
const target = createHash("sha256").update(resolve(dbPath)).digest("hex").slice(0, 24);
|
|
2676
2676
|
return join(homeDir, ".codemem", INBOX_DIRECTORY_NAME, target);
|
|
2677
2677
|
}
|
|
2678
|
-
function entryContent(request, flushBoundary) {
|
|
2678
|
+
function entryContent(request, flushBoundary, boundary) {
|
|
2679
2679
|
return {
|
|
2680
2680
|
version: 1,
|
|
2681
2681
|
request,
|
|
2682
|
-
flush_boundary: flushBoundary
|
|
2682
|
+
flush_boundary: flushBoundary,
|
|
2683
|
+
...boundary ? { boundary: {
|
|
2684
|
+
source: boundary.source,
|
|
2685
|
+
stream_id: boundary.streamId,
|
|
2686
|
+
...boundary.id ? { id: boundary.id } : {}
|
|
2687
|
+
} } : {}
|
|
2683
2688
|
};
|
|
2684
2689
|
}
|
|
2685
|
-
function storedEntry(request, flushBoundary, enqueueOrder) {
|
|
2690
|
+
function storedEntry(request, flushBoundary, boundary, enqueueOrder) {
|
|
2686
2691
|
return {
|
|
2687
|
-
...entryContent(request, flushBoundary),
|
|
2692
|
+
...entryContent(request, flushBoundary, boundary),
|
|
2688
2693
|
enqueue_order: enqueueOrder.toString()
|
|
2689
2694
|
};
|
|
2690
2695
|
}
|
|
2691
2696
|
function entryContentId(entry) {
|
|
2692
|
-
return contentId(JSON.stringify(entryContent(entry.request, entry.flushBoundary)));
|
|
2697
|
+
return contentId(JSON.stringify(entryContent(entry.request, entry.flushBoundary, entry.boundary)));
|
|
2693
2698
|
}
|
|
2694
2699
|
function inboxFileName(enqueueOrder, id) {
|
|
2695
2700
|
return `${enqueueOrder.toString().padStart(24, "0")}-${id}.json`;
|
|
@@ -2749,10 +2754,17 @@ async function ensurePrivateDirectory(path) {
|
|
|
2749
2754
|
function parseStoredEntry(serialized) {
|
|
2750
2755
|
const parsed = JSON.parse(serialized);
|
|
2751
2756
|
if (parsed.version !== 1 || typeof parsed.enqueue_order !== "string" || !/^[1-9]\d*$/u.test(parsed.enqueue_order) || parsed.request == null || typeof parsed.request !== "object" || Array.isArray(parsed.request) || typeof parsed.flush_boundary !== "boolean") throw new Error("invalid raw-event inbox entry");
|
|
2757
|
+
const storedBoundary = parsed.boundary;
|
|
2758
|
+
if (storedBoundary !== void 0 && (typeof storedBoundary.source !== "string" || storedBoundary.source.trim() === "" || typeof storedBoundary.stream_id !== "string" || storedBoundary.stream_id.trim() === "" || storedBoundary.id !== void 0 && (typeof storedBoundary.id !== "string" || storedBoundary.id.trim() === ""))) throw new Error("invalid raw-event inbox boundary");
|
|
2752
2759
|
return {
|
|
2753
2760
|
entry: {
|
|
2754
2761
|
request: parsed.request,
|
|
2755
|
-
flushBoundary: parsed.flush_boundary
|
|
2762
|
+
flushBoundary: parsed.flush_boundary,
|
|
2763
|
+
...storedBoundary ? { boundary: {
|
|
2764
|
+
source: storedBoundary.source,
|
|
2765
|
+
streamId: storedBoundary.stream_id,
|
|
2766
|
+
...storedBoundary.id ? { id: storedBoundary.id } : {}
|
|
2767
|
+
} } : {}
|
|
2756
2768
|
},
|
|
2757
2769
|
enqueueOrder: BigInt(parsed.enqueue_order)
|
|
2758
2770
|
};
|
|
@@ -2803,7 +2815,8 @@ var FileRawEventInbox = class {
|
|
|
2803
2815
|
const flushBoundary = options.flushBoundary === true;
|
|
2804
2816
|
const id = entryContentId({
|
|
2805
2817
|
request,
|
|
2806
|
-
flushBoundary
|
|
2818
|
+
flushBoundary,
|
|
2819
|
+
boundary: options.boundary
|
|
2807
2820
|
});
|
|
2808
2821
|
await ensurePrivateDirectory(this.directory);
|
|
2809
2822
|
const entries = await readdir(this.directory, { withFileTypes: true });
|
|
@@ -2823,7 +2836,7 @@ var FileRawEventInbox = class {
|
|
|
2823
2836
|
throw error;
|
|
2824
2837
|
}
|
|
2825
2838
|
const enqueueOrder = await this.allocateEnqueueOrder(entries);
|
|
2826
|
-
const serialized = JSON.stringify(storedEntry(request, flushBoundary, enqueueOrder));
|
|
2839
|
+
const serialized = JSON.stringify(storedEntry(request, flushBoundary, options.boundary, enqueueOrder));
|
|
2827
2840
|
const destination = join(this.directory, inboxFileName(enqueueOrder, id));
|
|
2828
2841
|
const temporary = join(this.directory, `.${id}.${process.pid}.${randomUUID()}.tmp`);
|
|
2829
2842
|
try {
|
|
@@ -3024,10 +3037,11 @@ function createViewerRawEventInbox(options) {
|
|
|
3024
3037
|
onCorruptEntries: options.onCorruptEntries,
|
|
3025
3038
|
onBacklog: options.onBacklog,
|
|
3026
3039
|
onBacklogRecovered: options.onBacklogRecovered,
|
|
3027
|
-
processEntry: async ({ request, flushBoundary }) => {
|
|
3040
|
+
processEntry: async ({ request, flushBoundary, boundary }) => {
|
|
3028
3041
|
const result = ingestRawEvents(store, request);
|
|
3029
3042
|
nudgeRawEventSessions(options.sweeper, result.sessions);
|
|
3030
|
-
if (
|
|
3043
|
+
if (boundary) await options.sweeper?.flushBoundary(boundary.streamId, boundary.source);
|
|
3044
|
+
else if (flushBoundary && isClaudeBoundaryEnvelope(request)) await flushRawEventBoundarySessions(options.sweeper, result.sessions);
|
|
3031
3045
|
}
|
|
3032
3046
|
});
|
|
3033
3047
|
return {
|
|
@@ -3155,15 +3169,94 @@ async function enqueueRawEventRequest(options) {
|
|
|
3155
3169
|
if (!target.ok) return options.c.json(target.body, target.status);
|
|
3156
3170
|
const validation = validateRawEvents(options.request);
|
|
3157
3171
|
try {
|
|
3158
|
-
await options.inbox.enqueue(validation.request,
|
|
3172
|
+
await options.inbox.enqueue(validation.request, options.boundary ? {
|
|
3173
|
+
flushBoundary: options.flushBoundary,
|
|
3174
|
+
boundary: options.boundary
|
|
3175
|
+
} : { flushBoundary: options.flushBoundary });
|
|
3159
3176
|
} catch (error) {
|
|
3160
3177
|
return boundedInboxErrorResponse(options.c, error);
|
|
3161
3178
|
}
|
|
3179
|
+
const accepted = options.acceptedCount ?? validation.received;
|
|
3162
3180
|
return options.c.json({
|
|
3163
|
-
accepted
|
|
3164
|
-
queued:
|
|
3181
|
+
accepted,
|
|
3182
|
+
queued: accepted
|
|
3165
3183
|
}, 202);
|
|
3166
3184
|
}
|
|
3185
|
+
function piEventName(payload) {
|
|
3186
|
+
for (const key of [
|
|
3187
|
+
"piEvent",
|
|
3188
|
+
"pi_event",
|
|
3189
|
+
"event",
|
|
3190
|
+
"type"
|
|
3191
|
+
]) {
|
|
3192
|
+
const value = payload[key];
|
|
3193
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
3194
|
+
}
|
|
3195
|
+
return "";
|
|
3196
|
+
}
|
|
3197
|
+
function piInboxBoundary(payload, envelope, signal) {
|
|
3198
|
+
if (!["session_before_compact", "session_shutdown"].includes(piEventName(payload))) return;
|
|
3199
|
+
const streamId = envelope?.session_stream_id ?? signal?.session_id;
|
|
3200
|
+
if (!streamId) return;
|
|
3201
|
+
const envelopeTimestamp = envelope?.payload.timestamp;
|
|
3202
|
+
const id = typeof envelopeTimestamp === "string" ? envelopeTimestamp : signal?.ts;
|
|
3203
|
+
return {
|
|
3204
|
+
source: "pi",
|
|
3205
|
+
streamId,
|
|
3206
|
+
...id ? { id } : {}
|
|
3207
|
+
};
|
|
3208
|
+
}
|
|
3209
|
+
async function postPiHookRequest(c, getStore, sweeper, inbox, inboxTarget) {
|
|
3210
|
+
const result = await parseJsonObjectBody(c, MAX_RAW_EVENTS_BODY_BYTES);
|
|
3211
|
+
if (result instanceof Response) return result;
|
|
3212
|
+
const payload = result;
|
|
3213
|
+
try {
|
|
3214
|
+
const target = validateViewerTarget(inbox && inboxTarget ? inboxTarget : getStore(), payload, { requirePairedTargets: true });
|
|
3215
|
+
if (!target.ok) return c.json(target.body, target.status);
|
|
3216
|
+
const untargeted = untargetedPayload(payload);
|
|
3217
|
+
const envelope = buildRawEventEnvelopeFromPiEvent(untargeted);
|
|
3218
|
+
const signal = buildPiFlushSignalFromEvent(untargeted);
|
|
3219
|
+
const boundary = piInboxBoundary(untargeted, envelope, signal);
|
|
3220
|
+
if (envelope === null && signal === null) return c.json({
|
|
3221
|
+
inserted: 0,
|
|
3222
|
+
skipped: 1
|
|
3223
|
+
});
|
|
3224
|
+
if (inbox) return await enqueueRawEventRequest({
|
|
3225
|
+
c,
|
|
3226
|
+
getStore,
|
|
3227
|
+
inbox,
|
|
3228
|
+
inboxTarget,
|
|
3229
|
+
payload,
|
|
3230
|
+
request: envelope ? {
|
|
3231
|
+
...envelope,
|
|
3232
|
+
source: "pi"
|
|
3233
|
+
} : {
|
|
3234
|
+
source: "pi",
|
|
3235
|
+
session_stream_id: signal?.session_id,
|
|
3236
|
+
events: []
|
|
3237
|
+
},
|
|
3238
|
+
flushBoundary: false,
|
|
3239
|
+
...boundary ? {
|
|
3240
|
+
boundary,
|
|
3241
|
+
acceptedCount: 1
|
|
3242
|
+
} : {}
|
|
3243
|
+
});
|
|
3244
|
+
if (envelope === null) return c.json({
|
|
3245
|
+
inserted: 0,
|
|
3246
|
+
skipped: 1
|
|
3247
|
+
});
|
|
3248
|
+
const ingestResult = await ingestNormalizedEnvelope(getStore(), sweeper, {
|
|
3249
|
+
...envelope,
|
|
3250
|
+
source: "pi"
|
|
3251
|
+
});
|
|
3252
|
+
return c.json({
|
|
3253
|
+
inserted: ingestResult.inserted,
|
|
3254
|
+
skipped: ingestResult.skipped
|
|
3255
|
+
});
|
|
3256
|
+
} catch (error) {
|
|
3257
|
+
return boundedIngestErrorResponse(c, error);
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3167
3260
|
async function postRawEventRequest(c, getStore, sweeper, inbox, inboxTarget) {
|
|
3168
3261
|
const result = await parseJsonObjectBody(c, MAX_RAW_EVENTS_BODY_BYTES);
|
|
3169
3262
|
if (result instanceof Response) return result;
|
|
@@ -3197,6 +3290,81 @@ async function ingestNormalizedEnvelope(store, sweeper, envelope, flushBoundary
|
|
|
3197
3290
|
if (flushBoundary && isClaudeBoundaryEnvelope(envelope)) await flushRawEventBoundarySessions(sweeper, result.sessions);
|
|
3198
3291
|
return result;
|
|
3199
3292
|
}
|
|
3293
|
+
async function postClaudeHookRequest(c, getStore, sweeper, inbox, inboxTarget, transcriptDiagnostics) {
|
|
3294
|
+
const result = await parseJsonObjectBody(c, MAX_RAW_EVENTS_BODY_BYTES);
|
|
3295
|
+
if (result instanceof Response) return result;
|
|
3296
|
+
const payload = result;
|
|
3297
|
+
try {
|
|
3298
|
+
const target = validateViewerTarget(inbox && inboxTarget ? inboxTarget : getStore(), payload, { requirePairedTargets: true });
|
|
3299
|
+
if (!target.ok) return c.json(target.body, target.status);
|
|
3300
|
+
let transcriptOutcome = null;
|
|
3301
|
+
const envelope = buildRawEventEnvelopeFromHook(untargetedPayload(payload), {
|
|
3302
|
+
transcriptPolicy: {
|
|
3303
|
+
trust: "restricted",
|
|
3304
|
+
approvedRoots: [claudeTranscriptRoot()]
|
|
3305
|
+
},
|
|
3306
|
+
onTranscriptOutcome: (outcome) => {
|
|
3307
|
+
transcriptOutcome = outcome;
|
|
3308
|
+
transcriptDiagnostics.record("claude", outcome);
|
|
3309
|
+
}
|
|
3310
|
+
});
|
|
3311
|
+
if (envelope === null) return c.json(transcriptSkipResponse(transcriptOutcome));
|
|
3312
|
+
const flushBoundary = c.req.header("x-codemem-boundary-flush") === "1";
|
|
3313
|
+
if (inbox) return await enqueueRawEventRequest({
|
|
3314
|
+
c,
|
|
3315
|
+
getStore,
|
|
3316
|
+
inbox,
|
|
3317
|
+
inboxTarget,
|
|
3318
|
+
payload,
|
|
3319
|
+
request: { ...envelope },
|
|
3320
|
+
flushBoundary
|
|
3321
|
+
});
|
|
3322
|
+
const ingestResult = await ingestNormalizedEnvelope(getStore(), sweeper, envelope, flushBoundary);
|
|
3323
|
+
return c.json({
|
|
3324
|
+
inserted: ingestResult.inserted,
|
|
3325
|
+
skipped: ingestResult.skipped
|
|
3326
|
+
});
|
|
3327
|
+
} catch (error) {
|
|
3328
|
+
return boundedIngestErrorResponse(c, error);
|
|
3329
|
+
}
|
|
3330
|
+
}
|
|
3331
|
+
async function postCodexHookRequest(c, getStore, sweeper, inbox, inboxTarget, transcriptDiagnostics) {
|
|
3332
|
+
const result = await parseJsonObjectBody(c, MAX_RAW_EVENTS_BODY_BYTES);
|
|
3333
|
+
if (result instanceof Response) return result;
|
|
3334
|
+
const payload = result;
|
|
3335
|
+
try {
|
|
3336
|
+
const target = validateViewerTarget(inbox && inboxTarget ? inboxTarget : getStore(), payload, { requirePairedTargets: true });
|
|
3337
|
+
if (!target.ok) return c.json(target.body, target.status);
|
|
3338
|
+
let transcriptOutcome = null;
|
|
3339
|
+
const envelope = buildRawEventEnvelopeFromCodexHook(untargetedPayload(payload), {
|
|
3340
|
+
transcriptPolicy: {
|
|
3341
|
+
trust: "restricted",
|
|
3342
|
+
approvedRoots: [codexTranscriptRoot()]
|
|
3343
|
+
},
|
|
3344
|
+
onTranscriptOutcome: (outcome) => {
|
|
3345
|
+
transcriptOutcome = outcome;
|
|
3346
|
+
transcriptDiagnostics.record("codex", outcome);
|
|
3347
|
+
}
|
|
3348
|
+
});
|
|
3349
|
+
if (envelope === null) return c.json(transcriptSkipResponse(transcriptOutcome));
|
|
3350
|
+
if (inbox) return await enqueueRawEventRequest({
|
|
3351
|
+
c,
|
|
3352
|
+
getStore,
|
|
3353
|
+
inbox,
|
|
3354
|
+
inboxTarget,
|
|
3355
|
+
payload,
|
|
3356
|
+
request: { ...envelope },
|
|
3357
|
+
flushBoundary: false
|
|
3358
|
+
});
|
|
3359
|
+
const ingestResult = await ingestNormalizedEnvelope(getStore(), sweeper, envelope);
|
|
3360
|
+
return c.json({
|
|
3361
|
+
inserted: ingestResult.inserted,
|
|
3362
|
+
skipped: ingestResult.skipped
|
|
3363
|
+
});
|
|
3364
|
+
} catch (error) {
|
|
3365
|
+
return boundedIngestErrorResponse(c, error);
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3200
3368
|
function rawEventsRoutes(getStore, sweeper, inbox, inboxTarget) {
|
|
3201
3369
|
const app = new Hono();
|
|
3202
3370
|
const transcriptDiagnostics = createTranscriptDiagnostics();
|
|
@@ -3248,89 +3416,9 @@ function rawEventsRoutes(getStore, sweeper, inbox, inboxTarget) {
|
|
|
3248
3416
|
});
|
|
3249
3417
|
});
|
|
3250
3418
|
app.post("/api/raw-events", (c) => postRawEventRequest(c, getStore, sweeper, inbox, inboxTarget));
|
|
3251
|
-
app.post("/api/claude-hooks",
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
const payload = result;
|
|
3255
|
-
try {
|
|
3256
|
-
const store = getStore();
|
|
3257
|
-
const target = validateViewerTarget(store, payload, { requirePairedTargets: true });
|
|
3258
|
-
if (!target.ok) return c.json(target.body, target.status);
|
|
3259
|
-
let transcriptOutcome = null;
|
|
3260
|
-
const envelope = buildRawEventEnvelopeFromHook(untargetedPayload(payload), {
|
|
3261
|
-
transcriptPolicy: {
|
|
3262
|
-
trust: "restricted",
|
|
3263
|
-
approvedRoots: [claudeTranscriptRoot()]
|
|
3264
|
-
},
|
|
3265
|
-
onTranscriptOutcome: (outcome) => {
|
|
3266
|
-
transcriptOutcome = outcome;
|
|
3267
|
-
transcriptDiagnostics.record("claude", outcome);
|
|
3268
|
-
}
|
|
3269
|
-
});
|
|
3270
|
-
if (envelope === null) return c.json(transcriptSkipResponse(transcriptOutcome));
|
|
3271
|
-
const ingestResult = await ingestNormalizedEnvelope(store, sweeper, envelope, c.req.header("x-codemem-boundary-flush") === "1");
|
|
3272
|
-
return c.json({
|
|
3273
|
-
inserted: ingestResult.inserted,
|
|
3274
|
-
skipped: ingestResult.skipped
|
|
3275
|
-
});
|
|
3276
|
-
} catch (err) {
|
|
3277
|
-
return boundedIngestErrorResponse(c, err);
|
|
3278
|
-
}
|
|
3279
|
-
});
|
|
3280
|
-
app.post("/api/codex-hooks", async (c) => {
|
|
3281
|
-
const result = await parseJsonObjectBody(c, MAX_RAW_EVENTS_BODY_BYTES);
|
|
3282
|
-
if (result instanceof Response) return result;
|
|
3283
|
-
const payload = result;
|
|
3284
|
-
try {
|
|
3285
|
-
const store = getStore();
|
|
3286
|
-
const target = validateViewerTarget(store, payload, { requirePairedTargets: true });
|
|
3287
|
-
if (!target.ok) return c.json(target.body, target.status);
|
|
3288
|
-
let transcriptOutcome = null;
|
|
3289
|
-
const envelope = buildRawEventEnvelopeFromCodexHook(untargetedPayload(payload), {
|
|
3290
|
-
transcriptPolicy: {
|
|
3291
|
-
trust: "restricted",
|
|
3292
|
-
approvedRoots: [codexTranscriptRoot()]
|
|
3293
|
-
},
|
|
3294
|
-
onTranscriptOutcome: (outcome) => {
|
|
3295
|
-
transcriptOutcome = outcome;
|
|
3296
|
-
transcriptDiagnostics.record("codex", outcome);
|
|
3297
|
-
}
|
|
3298
|
-
});
|
|
3299
|
-
if (envelope === null) return c.json(transcriptSkipResponse(transcriptOutcome));
|
|
3300
|
-
const ingestResult = await ingestNormalizedEnvelope(store, sweeper, envelope);
|
|
3301
|
-
return c.json({
|
|
3302
|
-
inserted: ingestResult.inserted,
|
|
3303
|
-
skipped: ingestResult.skipped
|
|
3304
|
-
});
|
|
3305
|
-
} catch (err) {
|
|
3306
|
-
return boundedIngestErrorResponse(c, err);
|
|
3307
|
-
}
|
|
3308
|
-
});
|
|
3309
|
-
app.post("/api/pi-hooks", async (c) => {
|
|
3310
|
-
const result = await parseJsonObjectBody(c, MAX_RAW_EVENTS_BODY_BYTES);
|
|
3311
|
-
if (result instanceof Response) return result;
|
|
3312
|
-
const payload = result;
|
|
3313
|
-
try {
|
|
3314
|
-
const store = getStore();
|
|
3315
|
-
const target = validateViewerTarget(store, payload, { requirePairedTargets: true });
|
|
3316
|
-
if (!target.ok) return c.json(target.body, target.status);
|
|
3317
|
-
const envelope = buildRawEventEnvelopeFromPiEvent(untargetedPayload(payload));
|
|
3318
|
-
if (envelope === null) return c.json({
|
|
3319
|
-
inserted: 0,
|
|
3320
|
-
skipped: 1
|
|
3321
|
-
});
|
|
3322
|
-
const ingestResult = await ingestNormalizedEnvelope(store, sweeper, {
|
|
3323
|
-
...envelope,
|
|
3324
|
-
source: "pi"
|
|
3325
|
-
});
|
|
3326
|
-
return c.json({
|
|
3327
|
-
inserted: ingestResult.inserted,
|
|
3328
|
-
skipped: ingestResult.skipped
|
|
3329
|
-
});
|
|
3330
|
-
} catch (err) {
|
|
3331
|
-
return boundedIngestErrorResponse(c, err);
|
|
3332
|
-
}
|
|
3333
|
-
});
|
|
3419
|
+
app.post("/api/claude-hooks", (c) => postClaudeHookRequest(c, getStore, sweeper, inbox, inboxTarget, transcriptDiagnostics));
|
|
3420
|
+
app.post("/api/codex-hooks", (c) => postCodexHookRequest(c, getStore, sweeper, inbox, inboxTarget, transcriptDiagnostics));
|
|
3421
|
+
app.post("/api/pi-hooks", (c) => postPiHookRequest(c, getStore, sweeper, inbox, inboxTarget));
|
|
3334
3422
|
return app;
|
|
3335
3423
|
}
|
|
3336
3424
|
//#endregion
|