mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-31 18:02:27 +00:00
Merge pull request #2008 from PR0M3TH3AN/ai/schema-validate-20250226-13203498180481473459
chore(ai): event schema validation tool + fixes
This commit is contained in:
7 files changed
+81
-17
No files matched your search
@@ -348,5 +348,6 @@ npm run test:unit
|
||||
```
|
||||
|
||||
When modifying schemas or builders, use `scripts/agent/validate-events.mjs` to
|
||||
verify your changes locally. This tool also scans the codebase to ensure all
|
||||
active event builders are covered by tests.
|
||||
verify your changes locally. This tool validates that builders produce events
|
||||
conforming to the defined schemas, covering standard and application-specific
|
||||
usage patterns.
|
||||
+4
-4
@@ -859,10 +859,10 @@ class SubscriptionsManager {
|
||||
|
||||
let signer = getActiveSigner();
|
||||
if (
|
||||
!signer ||
|
||||
(!signerHasRequiredDecryptors(signer) &&
|
||||
typeof nostrClient?.ensureActiveSignerForPubkey === "function" &&
|
||||
allowPermissionPrompt)
|
||||
allowPermissionPrompt &&
|
||||
(!signer ||
|
||||
(!signerHasRequiredDecryptors(signer) &&
|
||||
typeof nostrClient?.ensureActiveSignerForPubkey === "function"))
|
||||
) {
|
||||
signer = await nostrClient.ensureActiveSignerForPubkey(userPubkey);
|
||||
}
|
||||
|
||||
+4
-3
@@ -959,9 +959,10 @@ class UserBlockListManager {
|
||||
};
|
||||
|
||||
if (
|
||||
!signer ||
|
||||
(!signerHasRequiredDecryptors(signer) &&
|
||||
typeof nostrClient?.ensureActiveSignerForPubkey === "function")
|
||||
allowPermissionPrompt &&
|
||||
(!signer ||
|
||||
(!signerHasRequiredDecryptors(signer) &&
|
||||
typeof nostrClient?.ensureActiveSignerForPubkey === "function"))
|
||||
) {
|
||||
signer = await nostrClient.ensureActiveSignerForPubkey(normalized);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ function getSessionActorKey() {
|
||||
return normalizeActorKey(nostrClient?.sessionActor?.pubkey);
|
||||
}
|
||||
|
||||
async function ensureWatchHistoryExtensionPermissions(actorKey) {
|
||||
async function ensureWatchHistoryExtensionPermissions(actorKey, options = {}) {
|
||||
const normalizedActor = normalizeActorKey(actorKey);
|
||||
if (!normalizedActor) {
|
||||
return { ok: true };
|
||||
@@ -85,8 +85,13 @@ async function ensureWatchHistoryExtensionPermissions(actorKey) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const allowPermissionPrompt = options?.allowPermissionPrompt !== false;
|
||||
|
||||
let signer = getActiveSigner();
|
||||
if (!signer && typeof nostrClient?.ensureActiveSignerForPubkey === "function") {
|
||||
if (
|
||||
allowPermissionPrompt &&
|
||||
(!signer && typeof nostrClient?.ensureActiveSignerForPubkey === "function")
|
||||
) {
|
||||
signer = await nostrClient.ensureActiveSignerForPubkey(normalizedActor);
|
||||
}
|
||||
|
||||
@@ -97,6 +102,10 @@ async function ensureWatchHistoryExtensionPermissions(actorKey) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
if (!allowPermissionPrompt) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
const permissionResult = await requestDefaultExtensionPermissions();
|
||||
if (permissionResult.ok) {
|
||||
return { ok: true };
|
||||
@@ -984,7 +993,7 @@ async function snapshot(items, options = {}) {
|
||||
return run;
|
||||
}
|
||||
|
||||
function scheduleWatchHistoryRefresh(actorKey, cacheEntry = {}) {
|
||||
function scheduleWatchHistoryRefresh(actorKey, cacheEntry = {}, options = {}) {
|
||||
if (!actorKey) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
@@ -996,6 +1005,7 @@ function scheduleWatchHistoryRefresh(actorKey, cacheEntry = {}) {
|
||||
const promise = (async () => {
|
||||
const permissionResult = await ensureWatchHistoryExtensionPermissions(
|
||||
actorKey,
|
||||
options
|
||||
);
|
||||
if (!permissionResult.ok) {
|
||||
throw permissionResult.error;
|
||||
@@ -1264,11 +1274,19 @@ async function loadLatest(actorInput, options = {}) {
|
||||
}
|
||||
|
||||
if (!allowStale || !hasCachedItems) {
|
||||
const resolved = await scheduleWatchHistoryRefresh(actorKey, cacheEntry);
|
||||
const resolved = await scheduleWatchHistoryRefresh(
|
||||
actorKey,
|
||||
cacheEntry,
|
||||
normalizedOptions
|
||||
);
|
||||
return mergeQueuedItemsIfNeeded(actorKey, resolved);
|
||||
}
|
||||
|
||||
const refreshPromise = scheduleWatchHistoryRefresh(actorKey, cacheEntry);
|
||||
const refreshPromise = scheduleWatchHistoryRefresh(
|
||||
actorKey,
|
||||
cacheEntry,
|
||||
normalizedOptions
|
||||
);
|
||||
refreshPromise.catch(() => {});
|
||||
|
||||
devLogger.info(
|
||||
|
||||
@@ -69,7 +69,9 @@ import {
|
||||
buildAdminListEvent,
|
||||
validateEventStructure,
|
||||
NOTE_TYPES,
|
||||
ADMIN_LIST_IDENTIFIERS
|
||||
ADMIN_LIST_IDENTIFIERS,
|
||||
getNostrEventSchema,
|
||||
sanitizeAdditionalTags
|
||||
} from '../../js/nostrEventSchemas.js';
|
||||
import { buildNip71VideoEvent } from '../../js/nostr/nip71.js';
|
||||
|
||||
@@ -94,6 +96,22 @@ const testCases = [
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Video Post (Usage Pattern)',
|
||||
type: NOTE_TYPES.VIDEO_POST,
|
||||
builder: buildVideoPostEvent,
|
||||
params: {
|
||||
pubkey: '0000000000000000000000000000000000000000000000000000000000000001',
|
||||
created_at: 1234567890,
|
||||
dTagValue: 'test-video-usage',
|
||||
content: {
|
||||
version: 3,
|
||||
title: 'Test Video Usage',
|
||||
videoRootId: 'test-root-usage',
|
||||
},
|
||||
additionalTags: [['t', 'extra'], ['invalid']]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'HTTP Auth',
|
||||
type: NOTE_TYPES.HTTP_AUTH,
|
||||
@@ -158,6 +176,20 @@ const testCases = [
|
||||
relays: ['wss://relay.example.com']
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Relay List (Usage Pattern)',
|
||||
type: NOTE_TYPES.RELAY_LIST,
|
||||
builder: buildRelayListEvent,
|
||||
params: {
|
||||
pubkey: '0000000000000000000000000000000000000000000000000000000000000001',
|
||||
created_at: 1234567890,
|
||||
relays: [
|
||||
{ url: 'wss://relay.read.com', mode: 'read' },
|
||||
{ url: 'wss://relay.write.com', mode: 'write' },
|
||||
{ url: 'wss://relay.both.com', mode: 'both' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'DM Relay List',
|
||||
type: NOTE_TYPES.DM_RELAY_LIST,
|
||||
@@ -326,6 +358,16 @@ const testCases = [
|
||||
content: JSON.stringify({ version: 1, interests: [], disinterests: [] })
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Hashtag Preferences (Encrypted)',
|
||||
type: NOTE_TYPES.HASHTAG_PREFERENCES,
|
||||
builder: buildHashtagPreferenceEvent,
|
||||
params: {
|
||||
pubkey: '0000000000000000000000000000000000000000000000000000000000000001',
|
||||
created_at: 1234567890,
|
||||
content: 'encrypted-content-string-nip44'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Admin List (Moderation)',
|
||||
type: NOTE_TYPES.ADMIN_MODERATION_LIST,
|
||||
|
||||
@@ -250,6 +250,8 @@ test(
|
||||
};
|
||||
|
||||
nostrClient.fetchListIncrementally = async () => {
|
||||
fetchCalls += 1;
|
||||
// Always return the event so the second load call (with permissions) finds data
|
||||
return [event];
|
||||
};
|
||||
nostrClient.relays = relayUrls;
|
||||
@@ -257,7 +259,7 @@ test(
|
||||
|
||||
const decryptCalls = [];
|
||||
window.nostr = {
|
||||
enable: async () => {},
|
||||
enable: async () => true,
|
||||
getPublicKey: async () => pubkey,
|
||||
nip04: {
|
||||
decrypt: async () => {
|
||||
|
||||
@@ -67,7 +67,7 @@ test.after(() => {
|
||||
} else {
|
||||
globalThis.NostrTools = originalGlobalNostrTools;
|
||||
}
|
||||
|
||||
// Force exit to prevent hanging handles from singletons
|
||||
setTimeout(() => process.exit(0), 100);
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user