some auth fixes, as well as a pile of new lexicons for future use

Orual 25aed9ad 75f19169

+2667 -41
+10
crates/weaver-app/.env-dev
··· 1 + WEAVER_APP_ENV="dev" 2 + WEAVER_APP_HOST="http://localhost" 3 + WEAVER_APP_DOMAIN="" 4 + WEAVER_PORT=8080 5 + WEAVER_APP_SCOPES="atproto transition:generic" 6 + WEAVER_CLIENT_NAME="Weaver" 7 + 8 + WEAVER_LOGO_URI="" 9 + WEAVER_TOS_URI="" 10 + WEAVER_PRIVACY_POLICY_URI=""
-10
crates/weaver-app/.env-pro
··· 1 - WEAVER_APP_ENV="prod" 2 - WEAVER_APP_HOST="https://alpha.weaver.sh" 3 - WEAVER_APP_DOMAIN="https://alpha.weaver.sh" 4 - WEAVER_PORT=8080 5 - WEAVER_APP_SCOPES="atproto transition:generic" 6 - WEAVER_CLIENT_NAME="Weaver" 7 - 8 - WEAVER_LOGO_URI="https://alpha.weaver.sh/favicon.ico" 9 - WEAVER_TOS_URI="" 10 - WEAVER_PRIVACY_POLICY_URI=""
+9 -5
crates/weaver-app/assets/styling/editor.css
··· 156 156 outline: none; 157 157 min-height: 700px; 158 158 line-height: var(--spacing-line-height); 159 - font-size: 16px; 160 159 background: var(--color-base); 161 160 border: 1px solid var(--color-overlay); 162 161 color: var(--color-text); ··· 1197 1196 .remote-cursor-caret { 1198 1197 width: 2px; 1199 1198 height: var(--cursor-height, 18px); 1200 - background: var(--cursor-color, #4ECDC4); 1199 + background: var(--cursor-color, #4ecdc4); 1201 1200 border-radius: 1px; 1202 1201 animation: cursor-blink 1.2s ease-in-out infinite; 1203 1202 } ··· 1207 1206 top: -18px; 1208 1207 left: 0; 1209 1208 padding: 2px 6px; 1210 - background: var(--cursor-color, #4ECDC4); 1209 + background: var(--cursor-color, #4ecdc4); 1211 1210 color: #fff; 1212 1211 font-size: 10px; 1213 1212 font-weight: 500; ··· 1219 1218 } 1220 1219 1221 1220 @keyframes cursor-blink { 1222 - 0%, 100% { opacity: 1; } 1223 - 50% { opacity: 0.5; } 1221 + 0%, 1222 + 100% { 1223 + opacity: 1; 1224 + } 1225 + 50% { 1226 + opacity: 0.5; 1227 + } 1224 1228 }
+1 -1
crates/weaver-app/assets/styling/entry-card.css
··· 97 97 98 98 .feed-entry-card .entry-card-byline { 99 99 display: flex; 100 - align-items: center; 100 + align-items: last baseline; 101 101 gap: 0.5rem; 102 102 margin-bottom: 0.5rem; 103 103 }
+14 -9
crates/weaver-app/src/auth/mod.rs
··· 41 41 42 42 #[cfg(target_arch = "wasm32")] 43 43 pub async fn restore_session(fetcher: Fetcher, mut auth_state: Signal<AuthState>) -> RestoreResult { 44 + use std::collections::BTreeMap; 45 + 44 46 use gloo_storage::{LocalStorage, Storage}; 45 47 use jacquard::oauth::authstore::ClientAuthStore; 48 + use jacquard::smol_str::SmolStr; 46 49 use jacquard::types::string::Did; 47 50 48 51 // Look for session keys in localStorage (format: oauth_session_{did}_{session_id}) 49 - let Ok(keys) = LocalStorage::get_all::<serde_json::Value>() else { 50 - return RestoreResult::NoSession; 51 - }; 52 - let Some(keys) = keys.as_object() else { 53 - return RestoreResult::NoSession; 52 + let entries = match LocalStorage::get_all::<BTreeMap<SmolStr, serde_json::Value>>() { 53 + Ok(e) => e, 54 + Err(e) => { 55 + tracing::warn!("restore_session: localStorage.get_all failed: {:?}", e); 56 + return RestoreResult::NoSession; 57 + } 54 58 }; 55 59 56 60 let mut found_session: Option<(String, String)> = None; 57 - for key in keys.keys() { 61 + for key in entries.keys() { 58 62 if key.starts_with("oauth_session_") { 59 63 let parts: Vec<&str> = key 60 64 .strip_prefix("oauth_session_") ··· 71 75 let Some((did_str, session_id)) = found_session else { 72 76 return RestoreResult::NoSession; 73 77 }; 74 - let Ok(did) = Did::new_owned(did_str) else { 78 + 79 + let Ok(did) = Did::new_owned(did_str.clone()) else { 80 + tracing::warn!("restore_session: invalid DID format: {}", did_str); 75 81 return RestoreResult::NoSession; 76 82 }; 77 83 ··· 82 88 .write() 83 89 .set_authenticated(restored_did, session_id); 84 90 fetcher.upgrade_to_authenticated(session).await; 85 - tracing::debug!("session restored"); 86 91 RestoreResult::Restored 87 92 } 88 93 Err(e) => { 89 - tracing::warn!("Session restore failed, clearing dead session: {e}"); 94 + tracing::warn!("restore_session: failed, clearing dead session: {e}"); 90 95 let _ = AuthStore::new().delete_session(&did, &session_id).await; 91 96 RestoreResult::SessionExpired 92 97 }
+4 -4
crates/weaver-app/src/env.rs
··· 1 1 // This file is automatically generated by build.rs 2 2 3 3 #[allow(unused)] 4 - pub const WEAVER_APP_ENV: &'static str = "dev"; 4 + pub const WEAVER_APP_ENV: &'static str = "prod"; 5 5 #[allow(unused)] 6 - pub const WEAVER_APP_HOST: &'static str = "http://localhost"; 6 + pub const WEAVER_APP_HOST: &'static str = "https://alpha.weaver.sh"; 7 7 #[allow(unused)] 8 - pub const WEAVER_APP_DOMAIN: &'static str = ""; 8 + pub const WEAVER_APP_DOMAIN: &'static str = "https://alpha.weaver.sh"; 9 9 #[allow(unused)] 10 10 pub const WEAVER_PORT: &'static str = "8080"; 11 11 #[allow(unused)] ··· 13 13 #[allow(unused)] 14 14 pub const WEAVER_CLIENT_NAME: &'static str = "Weaver"; 15 15 #[allow(unused)] 16 - pub const WEAVER_LOGO_URI: &'static str = ""; 16 + pub const WEAVER_LOGO_URI: &'static str = "https://alpha.weaver.sh/favicon.ico"; 17 17 #[allow(unused)] 18 18 pub const WEAVER_TOS_URI: &'static str = ""; 19 19 #[allow(unused)]
+8 -6
crates/weaver-renderer/src/css.rs
··· 354 354 }} 355 355 356 356 .embed-avatar {{ 357 - width: 42px; 358 - height: 42px; 359 - max-width: 42px; 360 - max-height: 42px; 357 + width: 36px; 358 + height: 36px; 359 + max-width: 36px; 360 + max-height: 36px; 361 361 aspect-ratio: 1; 362 362 margin: 0; 363 363 object-fit: cover; ··· 366 366 .embed-author-info {{ 367 367 display: flex; 368 368 flex-direction: column; 369 - gap: 0.1rem; 369 + gap: 0; 370 370 min-width: 0; 371 371 }} 372 372 ··· 382 382 text-overflow: ellipsis; 383 383 white-space: nowrap; 384 384 text-decoration: none; 385 + line-height: 1.2; 385 386 }} 386 387 387 388 a.embed-author-name:hover {{ ··· 389 390 }} 390 391 391 392 .embed-author-handle {{ 392 - font-size: 0.9em; 393 + font-size: 0.85em; 393 394 font-family: var(--font-mono); 394 395 color: var(--color-subtle); 395 396 text-decoration: none; 396 397 overflow: hidden; 397 398 text-overflow: ellipsis; 398 399 white-space: nowrap; 400 + line-height: 1.2; 399 401 }} 400 402 401 403 .embed-author-handle:hover {{
+4
flake.nix
··· 252 252 253 253 LD_LIBRARY_PATH = "$LD_LIBRARY_PATH:$NIX_LD_LIBRARY_PATH"; 254 254 255 + # musl linker for static builds 256 + #CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER = "${pkgs.pkgsMusl.stdenv.cc}/bin/cc"; 257 + 255 258 # Additional dev-shell environment variables can be set directly 256 259 # MY_CUSTOM_DEVELOPMENT_VAR = "something else"; 257 260 ··· 269 272 wasm-pack 270 273 twiggy 271 274 binaryen.out 275 + patchelf 272 276 llvmPackages_18.clang-unwrapped 273 277 llvmPackages_18.llvm 274 278 llvmPackages_18.libclang
+34
lexicons/actor/getActorEntries.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.actor.getActorEntries", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get all entries for an actor, optionally including collaborations.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "includeCollaborations": { "type": "boolean", "default": false }, 14 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 15 + "cursor": { "type": "string" } 16 + } 17 + }, 18 + "output": { 19 + "encoding": "application/json", 20 + "schema": { 21 + "type": "object", 22 + "required": ["entries"], 23 + "properties": { 24 + "entries": { 25 + "type": "array", 26 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#entryView" } 27 + }, 28 + "cursor": { "type": "string" } 29 + } 30 + } 31 + } 32 + } 33 + } 34 + }
+34
lexicons/actor/getActorNotebooks.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.actor.getActorNotebooks", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get all notebooks for an actor, optionally including collaborations.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "includeCollaborations": { "type": "boolean", "default": false }, 14 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 15 + "cursor": { "type": "string" } 16 + } 17 + }, 18 + "output": { 19 + "encoding": "application/json", 20 + "schema": { 21 + "type": "object", 22 + "required": ["notebooks"], 23 + "properties": { 24 + "notebooks": { 25 + "type": "array", 26 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" } 27 + }, 28 + "cursor": { "type": "string" } 29 + } 30 + } 31 + } 32 + } 33 + } 34 + }
+34
lexicons/actor/getActorProfile.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.actor.getActorProfile", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a Weaver profile with notebook/entry statistics.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" } 13 + } 14 + }, 15 + "output": { 16 + "encoding": "application/json", 17 + "schema": { 18 + "type": "object", 19 + "required": ["profile", "notebookCount", "entryCount"], 20 + "properties": { 21 + "profile": { "type": "ref", "ref": "sh.weaver.actor.defs#profileView" }, 22 + "notebookCount": { "type": "integer" }, 23 + "entryCount": { "type": "integer" }, 24 + "collaborationCount": { "type": "integer" }, 25 + "followerCount": { "type": "integer" }, 26 + "followingCount": { "type": "integer" }, 27 + "viewerFollowing": { "type": "string", "format": "at-uri" }, 28 + "viewerFollowedBy": { "type": "string", "format": "at-uri" } 29 + } 30 + } 31 + } 32 + } 33 + } 34 + }
+51
lexicons/actor/getSuggestedAuthors.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.actor.getSuggestedAuthors", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get author recommendations for the authenticated user.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } 12 + } 13 + }, 14 + "output": { 15 + "encoding": "application/json", 16 + "schema": { 17 + "type": "object", 18 + "required": ["authors"], 19 + "properties": { 20 + "authors": { 21 + "type": "array", 22 + "items": { 23 + "type": "object", 24 + "required": ["author", "reason"], 25 + "properties": { 26 + "author": { "type": "ref", "ref": "sh.weaver.actor.defs#profileView" }, 27 + "reason": { 28 + "type": "string", 29 + "knownValues": [ 30 + "similar-to-followed", 31 + "writes-similar-content", 32 + "popular-in-tags-you-read", 33 + "followed-by-people-you-follow" 34 + ] 35 + }, 36 + "mutualFollows": { 37 + "type": "array", 38 + "maxLength": 3, 39 + "items": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 40 + "description": "People you follow who also follow this author." 41 + }, 42 + "notebookCount": { "type": "integer" } 43 + } 44 + } 45 + } 46 + } 47 + } 48 + } 49 + } 50 + } 51 + }
+38
lexicons/actor/searchActors.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.actor.searchActors", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Find actors matching search criteria.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["q"], 11 + "properties": { 12 + "q": { 13 + "type": "string", 14 + "minLength": 1, 15 + "maxLength": 100, 16 + "description": "Search query - matches handle, display name, description." 17 + }, 18 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 }, 19 + "cursor": { "type": "string" } 20 + } 21 + }, 22 + "output": { 23 + "encoding": "application/json", 24 + "schema": { 25 + "type": "object", 26 + "required": ["actors"], 27 + "properties": { 28 + "actors": { 29 + "type": "array", 30 + "items": { "type": "ref", "ref": "sh.weaver.actor.defs#profileView" } 31 + }, 32 + "cursor": { "type": "string" } 33 + } 34 + } 35 + } 36 + } 37 + } 38 + }
+36
lexicons/actor/searchActorsTypeahead.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.actor.searchActorsTypeahead", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Fast typeahead search for actors (handle/display name prefix matching).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["q"], 11 + "properties": { 12 + "q": { 13 + "type": "string", 14 + "minLength": 1, 15 + "maxLength": 100, 16 + "description": "Search query prefix." 17 + }, 18 + "limit": { "type": "integer", "minimum": 1, "maximum": 25, "default": 10 } 19 + } 20 + }, 21 + "output": { 22 + "encoding": "application/json", 23 + "schema": { 24 + "type": "object", 25 + "required": ["actors"], 26 + "properties": { 27 + "actors": { 28 + "type": "array", 29 + "items": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" } 30 + } 31 + } 32 + } 33 + } 34 + } 35 + } 36 + }
+149
lexicons/collab/defs.json
··· 13 13 "chapter": { 14 14 "type": "token", 15 15 "description": "Collaboration scoped to a chapter." 16 + }, 17 + "inviteView": { 18 + "type": "object", 19 + "description": "Hydrated view of a collaboration invite with status.", 20 + "required": ["uri", "cid", "inviter", "invitee", "resource", "createdAt", "status"], 21 + "properties": { 22 + "uri": { "type": "string", "format": "at-uri" }, 23 + "cid": { "type": "string", "format": "cid" }, 24 + "inviter": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 25 + "invitee": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 26 + "resource": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 27 + "resourceTitle": { "type": "string" }, 28 + "scope": { 29 + "type": "string", 30 + "knownValues": ["notebook", "entry", "chapter"] 31 + }, 32 + "message": { "type": "string" }, 33 + "createdAt": { "type": "string", "format": "datetime" }, 34 + "expiresAt": { "type": "string", "format": "datetime" }, 35 + "status": { 36 + "type": "string", 37 + "knownValues": ["pending", "accepted", "expired", "revoked"] 38 + }, 39 + "acceptUri": { "type": "string", "format": "at-uri" }, 40 + "acceptedAt": { "type": "string", "format": "datetime" } 41 + } 42 + }, 43 + "sessionView": { 44 + "type": "object", 45 + "description": "Active real-time collaboration session.", 46 + "required": ["uri", "user", "resource", "nodeId", "createdAt"], 47 + "properties": { 48 + "uri": { "type": "string", "format": "at-uri" }, 49 + "user": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 50 + "resource": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 51 + "nodeId": { "type": "string" }, 52 + "relayUrl": { "type": "string", "format": "uri" }, 53 + "createdAt": { "type": "string", "format": "datetime" }, 54 + "expiresAt": { "type": "string", "format": "datetime" } 55 + } 56 + }, 57 + "collaborationStateView": { 58 + "type": "object", 59 + "description": "Full state of a collaboration relationship including version reconciliation. Tracks both current and former collaborators.", 60 + "required": ["resource", "status", "participants"], 61 + "properties": { 62 + "resource": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 63 + "canonicalUri": { 64 + "type": "string", 65 + "format": "at-uri", 66 + "description": "The 'canonical' version URI (usually owner's)" 67 + }, 68 + "status": { 69 + "type": "string", 70 + "knownValues": ["active", "broken", "diverged", "reconciled"], 71 + "description": "active=normal, broken=all invites revoked/expired, diverged=versions differ, reconciled=was diverged but resolved" 72 + }, 73 + "participants": { 74 + "type": "array", 75 + "items": { "type": "ref", "ref": "#participantStateView" }, 76 + "description": "Current active + invited participants" 77 + }, 78 + "formerParticipants": { 79 + "type": "array", 80 + "items": { "type": "ref", "ref": "#formerCollaboratorView" }, 81 + "description": "People who used to collaborate but relationship ended" 82 + }, 83 + "publishedVersions": { 84 + "type": "array", 85 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#publishedVersionView" } 86 + }, 87 + "hasDivergence": { "type": "boolean" }, 88 + "hasFormerCollaborators": { "type": "boolean" }, 89 + "hasOrphanedVersions": { 90 + "type": "boolean", 91 + "description": "Published versions from former collaborators still exist" 92 + }, 93 + "lastSyncedAt": { "type": "string", "format": "datetime" }, 94 + "createdAt": { "type": "string", "format": "datetime" }, 95 + "firstCollaboratorAddedAt": { "type": "string", "format": "datetime" } 96 + } 97 + }, 98 + "participantStateView": { 99 + "type": "object", 100 + "description": "Individual participant's state in a collaboration. Distinguishes 'was collaborator' vs 'never was'.", 101 + "required": ["user", "role", "status"], 102 + "properties": { 103 + "user": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 104 + "role": { 105 + "type": "string", 106 + "knownValues": ["owner", "collaborator", "former_collaborator"] 107 + }, 108 + "status": { 109 + "type": "string", 110 + "knownValues": ["active", "invited", "left", "removed", "expired"], 111 + "description": "active=can edit, invited=pending, left=voluntarily departed, removed=invite revoked, expired=invite timed out" 112 + }, 113 + "wasCollaborator": { 114 + "type": "boolean", 115 + "description": "True if they ever had active collaboration status" 116 + }, 117 + "inviteUri": { "type": "string", "format": "at-uri" }, 118 + "acceptUri": { 119 + "type": "string", 120 + "format": "at-uri", 121 + "description": "If they accepted (even if later broken)" 122 + }, 123 + "publishedVersion": { 124 + "type": "ref", 125 + "ref": "com.atproto.repo.strongRef", 126 + "description": "Their published copy if any" 127 + }, 128 + "firstEditAt": { 129 + "type": "string", 130 + "format": "datetime", 131 + "description": "When they first contributed" 132 + }, 133 + "lastEditAt": { "type": "string", "format": "datetime" }, 134 + "relationshipEndedAt": { 135 + "type": "string", 136 + "format": "datetime", 137 + "description": "When left/removed/expired" 138 + }, 139 + "endReason": { 140 + "type": "string", 141 + "knownValues": ["voluntary_leave", "invite_revoked", "invite_expired", "owner_deleted_resource"], 142 + "description": "Why the relationship ended, if applicable" 143 + } 144 + } 145 + }, 146 + "formerCollaboratorView": { 147 + "type": "object", 148 + "description": "Lightweight view for 'this person used to collaborate but doesn't anymore'.", 149 + "required": ["user", "wasActiveFrom", "wasActiveUntil", "endReason"], 150 + "properties": { 151 + "user": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 152 + "wasActiveFrom": { "type": "string", "format": "datetime" }, 153 + "wasActiveUntil": { "type": "string", "format": "datetime" }, 154 + "endReason": { 155 + "type": "string", 156 + "knownValues": ["voluntary_leave", "invite_revoked", "invite_expired", "owner_deleted_resource"] 157 + }, 158 + "contributionCount": { 159 + "type": "integer", 160 + "description": "Number of diffs they created while active" 161 + }, 162 + "hasPublishedVersion": { "type": "boolean" }, 163 + "publishedVersionUri": { "type": "string", "format": "at-uri" } 164 + } 16 165 } 17 166 } 18 167 }
+24
lexicons/collab/getCollaborationState.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.collab.getCollaborationState", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get full collaboration state for a resource, including all participants and published versions.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["resource"], 11 + "properties": { 12 + "resource": { "type": "string", "format": "at-uri" } 13 + } 14 + }, 15 + "output": { 16 + "encoding": "application/json", 17 + "schema": { 18 + "type": "ref", 19 + "ref": "sh.weaver.collab.defs#collaborationStateView" 20 + } 21 + } 22 + } 23 + } 24 + }
+43
lexicons/collab/getInvites.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.collab.getInvites", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get collaboration invites for an actor (sent, received, or both).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "direction": { 14 + "type": "string", 15 + "default": "all", 16 + "knownValues": ["sent", "received", "all"] 17 + }, 18 + "status": { 19 + "type": "string", 20 + "default": "all", 21 + "knownValues": ["pending", "accepted", "expired", "all"] 22 + }, 23 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 24 + "cursor": { "type": "string" } 25 + } 26 + }, 27 + "output": { 28 + "encoding": "application/json", 29 + "schema": { 30 + "type": "object", 31 + "required": ["invites"], 32 + "properties": { 33 + "invites": { 34 + "type": "array", 35 + "items": { "type": "ref", "ref": "sh.weaver.collab.defs#inviteView" } 36 + }, 37 + "cursor": { "type": "string" } 38 + } 39 + } 40 + } 41 + } 42 + } 43 + }
+32
lexicons/collab/getResourceParticipants.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.collab.getResourceParticipants", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get all participants (owner + collaborators) for a resource.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["resource"], 11 + "properties": { 12 + "resource": { "type": "string", "format": "at-uri" } 13 + } 14 + }, 15 + "output": { 16 + "encoding": "application/json", 17 + "schema": { 18 + "type": "object", 19 + "required": ["owner", "participants"], 20 + "properties": { 21 + "owner": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 22 + "participants": { 23 + "type": "array", 24 + "items": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" } 25 + }, 26 + "viewerCanEdit": { "type": "boolean" } 27 + } 28 + } 29 + } 30 + } 31 + } 32 + }
+30
lexicons/collab/getResourceSessions.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.collab.getResourceSessions", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get active real-time collaboration sessions for a resource.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["resource"], 11 + "properties": { 12 + "resource": { "type": "string", "format": "at-uri" } 13 + } 14 + }, 15 + "output": { 16 + "encoding": "application/json", 17 + "schema": { 18 + "type": "object", 19 + "required": ["sessions"], 20 + "properties": { 21 + "sessions": { 22 + "type": "array", 23 + "items": { "type": "ref", "ref": "sh.weaver.collab.defs#sessionView" } 24 + } 25 + } 26 + } 27 + } 28 + } 29 + } 30 + }
+59
lexicons/edit/defs.json
··· 42 42 "maxLength": 200 43 43 } 44 44 } 45 + }, 46 + "editHistoryEntry": { 47 + "type": "object", 48 + "description": "Summary of an edit (root or diff) for history queries.", 49 + "required": ["uri", "cid", "author", "createdAt", "type"], 50 + "properties": { 51 + "uri": { "type": "string", "format": "at-uri" }, 52 + "cid": { "type": "string", "format": "cid" }, 53 + "author": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 54 + "type": { 55 + "type": "string", 56 + "knownValues": ["root", "diff"] 57 + }, 58 + "rootRef": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 59 + "prevRef": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 60 + "snapshotCid": { "type": "string", "format": "cid" }, 61 + "hasInlineDiff": { "type": "boolean" }, 62 + "createdAt": { "type": "string", "format": "datetime" } 63 + } 64 + }, 65 + "editBranchView": { 66 + "type": "object", 67 + "description": "A branch/fork in edit history (for when collaborators diverge).", 68 + "required": ["head", "author", "length", "lastUpdated"], 69 + "properties": { 70 + "head": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 71 + "root": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 72 + "author": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 73 + "length": { 74 + "type": "integer", 75 + "description": "Number of diffs in this branch" 76 + }, 77 + "lastUpdated": { "type": "string", "format": "datetime" }, 78 + "divergesFrom": { 79 + "type": "ref", 80 + "ref": "com.atproto.repo.strongRef", 81 + "description": "Common ancestor if this is a fork" 82 + }, 83 + "isMerged": { "type": "boolean" } 84 + } 85 + }, 86 + "editTreeView": { 87 + "type": "object", 88 + "description": "Full tree structure showing all branches for a resource.", 89 + "required": ["resource", "branches"], 90 + "properties": { 91 + "resource": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 92 + "mainBranch": { "type": "ref", "ref": "#editBranchView" }, 93 + "branches": { 94 + "type": "array", 95 + "items": { "type": "ref", "ref": "#editBranchView" } 96 + }, 97 + "hasConflicts": { "type": "boolean" }, 98 + "conflictPoints": { 99 + "type": "array", 100 + "items": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 101 + "description": "Diffs where branches diverge" 102 + } 103 + } 45 104 } 46 105 } 47 106 }
+42
lexicons/edit/getBranch.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.edit.getBranch", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get edit history for a specific branch, identified by its head.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["head"], 11 + "properties": { 12 + "head": { 13 + "type": "string", 14 + "format": "at-uri", 15 + "description": "AT-URI of the branch head (latest diff)" 16 + }, 17 + "afterRkey": { 18 + "type": "string", 19 + "description": "Only diffs after this rkey" 20 + }, 21 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 22 + "cursor": { "type": "string" } 23 + } 24 + }, 25 + "output": { 26 + "encoding": "application/json", 27 + "schema": { 28 + "type": "object", 29 + "required": ["branch", "diffs"], 30 + "properties": { 31 + "branch": { "type": "ref", "ref": "sh.weaver.edit.defs#editBranchView" }, 32 + "diffs": { 33 + "type": "array", 34 + "items": { "type": "ref", "ref": "sh.weaver.edit.defs#editHistoryEntry" } 35 + }, 36 + "cursor": { "type": "string" } 37 + } 38 + } 39 + } 40 + } 41 + } 42 + }
+41
lexicons/edit/getEditHistory.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.edit.getEditHistory", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get edit history (roots and diffs) for a resource.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["resource"], 11 + "properties": { 12 + "resource": { "type": "string", "format": "at-uri" }, 13 + "afterRkey": { 14 + "type": "string", 15 + "description": "Only diffs after this rkey (incremental sync)" 16 + }, 17 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 18 + "cursor": { "type": "string" } 19 + } 20 + }, 21 + "output": { 22 + "encoding": "application/json", 23 + "schema": { 24 + "type": "object", 25 + "required": ["roots", "diffs"], 26 + "properties": { 27 + "roots": { 28 + "type": "array", 29 + "items": { "type": "ref", "ref": "sh.weaver.edit.defs#editHistoryEntry" } 30 + }, 31 + "diffs": { 32 + "type": "array", 33 + "items": { "type": "ref", "ref": "sh.weaver.edit.defs#editHistoryEntry" } 34 + }, 35 + "cursor": { "type": "string" } 36 + } 37 + } 38 + } 39 + } 40 + } 41 + }
+24
lexicons/edit/getEditTree.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.edit.getEditTree", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get the edit tree structure showing all branches and forks.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["resource"], 11 + "properties": { 12 + "resource": { "type": "string", "format": "at-uri" } 13 + } 14 + }, 15 + "output": { 16 + "encoding": "application/json", 17 + "schema": { 18 + "type": "ref", 19 + "ref": "sh.weaver.edit.defs#editTreeView" 20 + } 21 + } 22 + } 23 + } 24 + }
+110
lexicons/graph/defs.json
··· 9 9 "readinglist": { 10 10 "type": "token", 11 11 "description": "A personal reading list." 12 + }, 13 + "serieslist": { 14 + "type": "token", 15 + "description": "An ordered series of related works (sequels, spin-offs)." 16 + }, 17 + "tagView": { 18 + "type": "object", 19 + "description": "Aggregated view of a tag with usage statistics.", 20 + "required": ["tag", "useCount"], 21 + "properties": { 22 + "tag": { "type": "string" }, 23 + "useCount": { 24 + "type": "integer", 25 + "description": "Total number of resources tagged with this tag." 26 + }, 27 + "notebookCount": { "type": "integer" }, 28 + "entryCount": { "type": "integer" }, 29 + "recentUseCount": { 30 + "type": "integer", 31 + "description": "Uses in the last 30 days." 32 + }, 33 + "trendingScore": { 34 + "type": "number", 35 + "description": "Appview-computed trending score." 36 + } 37 + } 38 + }, 39 + "tagApplicationView": { 40 + "type": "object", 41 + "description": "A single tag application with who applied it.", 42 + "required": ["uri", "tag", "appliedBy", "createdAt"], 43 + "properties": { 44 + "uri": { "type": "string", "format": "at-uri" }, 45 + "tag": { "type": "string" }, 46 + "appliedBy": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 47 + "createdAt": { "type": "string", "format": "datetime" } 48 + } 49 + }, 50 + "resourceTagsView": { 51 + "type": "object", 52 + "description": "All tags for a resource, grouped by source.", 53 + "required": ["resource", "authorTags", "communityTags"], 54 + "properties": { 55 + "resource": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, 56 + "authorTags": { 57 + "type": "array", 58 + "description": "Tags from the record itself (author-applied).", 59 + "items": { "type": "string" } 60 + }, 61 + "communityTags": { 62 + "type": "array", 63 + "description": "Aggregated community-applied tags with counts.", 64 + "items": { "type": "ref", "ref": "#communityTagCount" } 65 + }, 66 + "viewerAppliedTags": { 67 + "type": "array", 68 + "description": "Tags the current viewer has applied.", 69 + "items": { "type": "string" } 70 + } 71 + } 72 + }, 73 + "communityTagCount": { 74 + "type": "object", 75 + "description": "A community tag with how many people applied it.", 76 + "required": ["tag", "count"], 77 + "properties": { 78 + "tag": { "type": "string" }, 79 + "count": { "type": "integer" } 80 + } 81 + }, 82 + "listView": { 83 + "type": "object", 84 + "description": "Hydrated view of a list.", 85 + "required": ["uri", "cid", "creator", "name", "purpose", "itemCount", "indexedAt"], 86 + "properties": { 87 + "uri": { "type": "string", "format": "at-uri" }, 88 + "cid": { "type": "string", "format": "cid" }, 89 + "creator": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 90 + "name": { "type": "string" }, 91 + "purpose": { "type": "ref", "ref": "#listPurpose" }, 92 + "description": { "type": "string" }, 93 + "avatar": { "type": "string", "format": "uri" }, 94 + "itemCount": { "type": "integer" }, 95 + "indexedAt": { "type": "string", "format": "datetime" }, 96 + "viewerSubscribed": { "type": "string", "format": "at-uri" } 97 + } 98 + }, 99 + "listPurpose": { 100 + "type": "string", 101 + "knownValues": [ 102 + "sh.weaver.graph.defs#curatelist", 103 + "sh.weaver.graph.defs#readinglist", 104 + "sh.weaver.graph.defs#serieslist" 105 + ] 106 + }, 107 + "listItemView": { 108 + "type": "object", 109 + "description": "An item in a list with hydrated subject.", 110 + "required": ["uri", "subject"], 111 + "properties": { 112 + "uri": { "type": "string", "format": "at-uri" }, 113 + "subject": { 114 + "type": "union", 115 + "refs": [ 116 + "sh.weaver.notebook.defs#notebookView", 117 + "sh.weaver.notebook.defs#entryView" 118 + ] 119 + }, 120 + "addedAt": { "type": "string", "format": "datetime" } 121 + } 12 122 } 13 123 } 14 124 }
+47
lexicons/graph/getActorBookmarks.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getActorBookmarks", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get resources an actor has bookmarked.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["bookmarks"], 22 + "properties": { 23 + "bookmarks": { 24 + "type": "array", 25 + "items": { 26 + "type": "object", 27 + "required": ["subject", "createdAt"], 28 + "properties": { 29 + "subject": { 30 + "type": "union", 31 + "refs": [ 32 + "sh.weaver.notebook.defs#notebookView", 33 + "sh.weaver.notebook.defs#entryView" 34 + ] 35 + }, 36 + "note": { "type": "string" }, 37 + "createdAt": { "type": "string", "format": "datetime" } 38 + } 39 + } 40 + }, 41 + "cursor": { "type": "string" } 42 + } 43 + } 44 + } 45 + } 46 + } 47 + }
+46
lexicons/graph/getActorLikes.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getActorLikes", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get resources an actor has liked.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["likes"], 22 + "properties": { 23 + "likes": { 24 + "type": "array", 25 + "items": { 26 + "type": "object", 27 + "required": ["subject", "createdAt"], 28 + "properties": { 29 + "subject": { 30 + "type": "union", 31 + "refs": [ 32 + "sh.weaver.notebook.defs#notebookView", 33 + "sh.weaver.notebook.defs#entryView" 34 + ] 35 + }, 36 + "createdAt": { "type": "string", "format": "datetime" } 37 + } 38 + } 39 + }, 40 + "cursor": { "type": "string" } 41 + } 42 + } 43 + } 44 + } 45 + } 46 + }
+37
lexicons/graph/getActorLists.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getActorLists", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get lists created by an actor.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "purpose": { 14 + "type": "string", 15 + "description": "Filter by list purpose." 16 + }, 17 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 18 + "cursor": { "type": "string" } 19 + } 20 + }, 21 + "output": { 22 + "encoding": "application/json", 23 + "schema": { 24 + "type": "object", 25 + "required": ["lists"], 26 + "properties": { 27 + "lists": { 28 + "type": "array", 29 + "items": { "type": "ref", "ref": "sh.weaver.graph.defs#listView" } 30 + }, 31 + "cursor": { "type": "string" } 32 + } 33 + } 34 + } 35 + } 36 + } 37 + }
+48
lexicons/graph/getActorSubscriptions.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getActorSubscriptions", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get notebooks an actor is subscribed to (accepted subscriptions only).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["subscriptions"], 22 + "properties": { 23 + "subscriptions": { 24 + "type": "array", 25 + "items": { 26 + "type": "object", 27 + "required": ["notebook", "subscribedAt"], 28 + "properties": { 29 + "notebook": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" }, 30 + "subscribedAt": { "type": "string", "format": "datetime" }, 31 + "hasUpdates": { 32 + "type": "boolean", 33 + "description": "True if notebook has new content since last visit." 34 + }, 35 + "newEntryCount": { 36 + "type": "integer", 37 + "description": "Number of new entries since last visit." 38 + } 39 + } 40 + } 41 + }, 42 + "cursor": { "type": "string" } 43 + } 44 + } 45 + } 46 + } 47 + } 48 + }
+42
lexicons/graph/getBookmarkedBy.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getBookmarkedBy", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get users who bookmarked a resource.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["subject"], 11 + "properties": { 12 + "subject": { "type": "string", "format": "at-uri" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["uri", "bookmarks"], 22 + "properties": { 23 + "uri": { "type": "string", "format": "at-uri" }, 24 + "cid": { "type": "string", "format": "cid" }, 25 + "bookmarks": { 26 + "type": "array", 27 + "items": { 28 + "type": "object", 29 + "required": ["actor", "createdAt"], 30 + "properties": { 31 + "actor": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 32 + "createdAt": { "type": "string", "format": "datetime" } 33 + } 34 + } 35 + }, 36 + "cursor": { "type": "string" } 37 + } 38 + } 39 + } 40 + } 41 + } 42 + }
+34
lexicons/graph/getFollowers.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getFollowers", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get followers of an actor (accepted follows only).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["subject", "followers"], 22 + "properties": { 23 + "subject": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 24 + "followers": { 25 + "type": "array", 26 + "items": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" } 27 + }, 28 + "cursor": { "type": "string" } 29 + } 30 + } 31 + } 32 + } 33 + } 34 + }
+34
lexicons/graph/getFollowing.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getFollowing", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get actors that an actor follows (accepted follows only).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["subject", "following"], 22 + "properties": { 23 + "subject": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 24 + "following": { 25 + "type": "array", 26 + "items": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" } 27 + }, 28 + "cursor": { "type": "string" } 29 + } 30 + } 31 + } 32 + } 33 + } 34 + }
+42
lexicons/graph/getLikedBy.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getLikedBy", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get users who liked a resource.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["subject"], 11 + "properties": { 12 + "subject": { "type": "string", "format": "at-uri" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["uri", "likes"], 22 + "properties": { 23 + "uri": { "type": "string", "format": "at-uri" }, 24 + "cid": { "type": "string", "format": "cid" }, 25 + "likes": { 26 + "type": "array", 27 + "items": { 28 + "type": "object", 29 + "required": ["actor", "createdAt"], 30 + "properties": { 31 + "actor": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 32 + "createdAt": { "type": "string", "format": "datetime" } 33 + } 34 + } 35 + }, 36 + "cursor": { "type": "string" } 37 + } 38 + } 39 + } 40 + } 41 + } 42 + }
+37
lexicons/graph/getList.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getList", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a list with its items.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["list"], 11 + "properties": { 12 + "list": { "type": "string", "format": "at-uri" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["list", "items"], 22 + "properties": { 23 + "list": { "type": "ref", "ref": "sh.weaver.graph.defs#listView" }, 24 + "items": { 25 + "type": "array", 26 + "items": { "type": "ref", "ref": "sh.weaver.graph.defs#listItemView" } 27 + }, 28 + "cursor": { "type": "string" } 29 + } 30 + } 31 + }, 32 + "errors": [ 33 + { "name": "ListNotFound" } 34 + ] 35 + } 36 + } 37 + }
+31
lexicons/graph/getPopularTags.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getPopularTags", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get most-used tags overall.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 12 + "cursor": { "type": "string" } 13 + } 14 + }, 15 + "output": { 16 + "encoding": "application/json", 17 + "schema": { 18 + "type": "object", 19 + "required": ["tags"], 20 + "properties": { 21 + "tags": { 22 + "type": "array", 23 + "items": { "type": "ref", "ref": "sh.weaver.graph.defs#tagView" } 24 + }, 25 + "cursor": { "type": "string" } 26 + } 27 + } 28 + } 29 + } 30 + } 31 + }
+24
lexicons/graph/getResourceTags.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getResourceTags", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get all tags for a resource (author + community), grouped by source.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["resource"], 11 + "properties": { 12 + "resource": { "type": "string", "format": "at-uri" } 13 + } 14 + }, 15 + "output": { 16 + "encoding": "application/json", 17 + "schema": { 18 + "type": "ref", 19 + "ref": "sh.weaver.graph.defs#resourceTagsView" 20 + } 21 + } 22 + } 23 + } 24 + }
+34
lexicons/graph/getSubscribers.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getSubscribers", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get subscribers to a notebook (accepted subscriptions only).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["notebook"], 11 + "properties": { 12 + "notebook": { "type": "string", "format": "at-uri" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["notebook", "subscribers"], 22 + "properties": { 23 + "notebook": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" }, 24 + "subscribers": { 25 + "type": "array", 26 + "items": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" } 27 + }, 28 + "cursor": { "type": "string" } 29 + } 30 + } 31 + } 32 + } 33 + } 34 + }
+40
lexicons/graph/getTagSuggestions.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getTagSuggestions", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get tag suggestions for autocomplete or based on existing tags.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "query": { 12 + "type": "string", 13 + "maxLength": 128, 14 + "description": "Partial tag for autocomplete." 15 + }, 16 + "existingTags": { 17 + "type": "array", 18 + "maxLength": 20, 19 + "items": { "type": "string" }, 20 + "description": "Tags already on the resource, to suggest related tags." 21 + }, 22 + "limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } 23 + } 24 + }, 25 + "output": { 26 + "encoding": "application/json", 27 + "schema": { 28 + "type": "object", 29 + "required": ["suggestions"], 30 + "properties": { 31 + "suggestions": { 32 + "type": "array", 33 + "items": { "type": "ref", "ref": "sh.weaver.graph.defs#tagView" } 34 + } 35 + } 36 + } 37 + } 38 + } 39 + } 40 + }
+60
lexicons/graph/getTaggedResources.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getTaggedResources", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get notebooks and entries tagged with a specific tag.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["tag"], 11 + "properties": { 12 + "tag": { "type": "string", "minLength": 1, "maxLength": 128 }, 13 + "resourceType": { 14 + "type": "string", 15 + "knownValues": ["notebook", "entry", "all"], 16 + "default": "all" 17 + }, 18 + "includeAuthorTags": { 19 + "type": "boolean", 20 + "default": true, 21 + "description": "Include resources where author applied this tag." 22 + }, 23 + "includeCommunityTags": { 24 + "type": "boolean", 25 + "default": true, 26 + "description": "Include resources where community applied this tag." 27 + }, 28 + "sort": { 29 + "type": "string", 30 + "knownValues": ["recent", "popular"], 31 + "default": "recent" 32 + }, 33 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 34 + "cursor": { "type": "string" } 35 + } 36 + }, 37 + "output": { 38 + "encoding": "application/json", 39 + "schema": { 40 + "type": "object", 41 + "required": ["resources"], 42 + "properties": { 43 + "tag": { "type": "ref", "ref": "sh.weaver.graph.defs#tagView" }, 44 + "resources": { 45 + "type": "array", 46 + "items": { 47 + "type": "union", 48 + "refs": [ 49 + "sh.weaver.notebook.defs#notebookView", 50 + "sh.weaver.notebook.defs#entryView" 51 + ] 52 + } 53 + }, 54 + "cursor": { "type": "string" } 55 + } 56 + } 57 + } 58 + } 59 + } 60 + }
+29
lexicons/graph/getTrendingTags.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.getTrendingTags", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get trending tags based on recent usage.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 } 12 + } 13 + }, 14 + "output": { 15 + "encoding": "application/json", 16 + "schema": { 17 + "type": "object", 18 + "required": ["tags"], 19 + "properties": { 20 + "tags": { 21 + "type": "array", 22 + "items": { "type": "ref", "ref": "sh.weaver.graph.defs#tagView" } 23 + } 24 + } 25 + } 26 + } 27 + } 28 + } 29 + }
+32
lexicons/graph/tag.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.graph.tag", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "description": "Apply a community tag to a notebook or entry. Can be created by readers, authors, or bots for categorization and discovery.", 8 + "key": "tid", 9 + "record": { 10 + "type": "object", 11 + "required": ["subject", "tag", "createdAt"], 12 + "properties": { 13 + "subject": { 14 + "type": "ref", 15 + "ref": "com.atproto.repo.strongRef", 16 + "description": "The notebook or entry being tagged." 17 + }, 18 + "tag": { 19 + "type": "string", 20 + "minLength": 1, 21 + "maxLength": 128, 22 + "description": "The tag value (e.g., 'enemies-to-lovers', 'slow-burn', 'found-family')." 23 + }, 24 + "createdAt": { 25 + "type": "string", 26 + "format": "datetime" 27 + } 28 + } 29 + } 30 + } 31 + } 32 + }
+3 -1
lexicons/notebook/book.json
··· 40 40 "type": "string", 41 41 "format": "datetime", 42 42 "description": "Client-declared timestamp of last modification. Used for canonicality tiebreaking in multi-author scenarios." 43 - } 43 + }, 44 + "contentWarnings": { "type": "ref", "ref": "sh.weaver.notebook.defs#contentWarnings" }, 45 + "rating": { "type": "ref", "ref": "sh.weaver.notebook.defs#contentRating" } 44 46 } 45 47 } 46 48 }
+3 -1
lexicons/notebook/chapter.json
··· 35 35 "type": "string", 36 36 "format": "datetime", 37 37 "description": "Client-declared timestamp when this was originally created." 38 - } 38 + }, 39 + "contentWarnings": { "type": "ref", "ref": "sh.weaver.notebook.defs#contentWarnings" }, 40 + "rating": { "type": "ref", "ref": "sh.weaver.notebook.defs#contentRating" } 39 41 } 40 42 } 41 43 }
+180 -2
lexicons/notebook/defs.json
··· 21 21 "ref": "#permissionsState" 22 22 }, 23 23 "record": { "type": "unknown" }, 24 - "indexedAt": { "type": "string", "format": "datetime" } 24 + "indexedAt": { "type": "string", "format": "datetime" }, 25 + "likeCount": { "type": "integer" }, 26 + "bookmarkCount": { "type": "integer" }, 27 + "subscriberCount": { "type": "integer" }, 28 + "entryCount": { "type": "integer" }, 29 + "viewerLike": { "type": "string", "format": "at-uri" }, 30 + "viewerBookmark": { "type": "string", "format": "at-uri" }, 31 + "viewerSubscription": { "type": "string", "format": "at-uri" }, 32 + "viewerReadingProgress": { "type": "ref", "ref": "#readingProgress" } 25 33 } 26 34 }, 27 35 "entryView": { ··· 47 55 "type": "ref", 48 56 "ref": "#renderedView" 49 57 }, 50 - "indexedAt": { "type": "string", "format": "datetime" } 58 + "indexedAt": { "type": "string", "format": "datetime" }, 59 + "likeCount": { "type": "integer" }, 60 + "bookmarkCount": { "type": "integer" }, 61 + "viewerLike": { "type": "string", "format": "at-uri" }, 62 + "viewerBookmark": { "type": "string", "format": "at-uri" }, 63 + "viewerReadingProgress": { "type": "ref", "ref": "#readingProgress" } 51 64 } 52 65 }, 53 66 ··· 181 194 "format": "datetime", 182 195 "description": "For authority: record createdAt. For invitees: accept createdAt" 183 196 } 197 + } 198 + }, 199 + "feedEntryView": { 200 + "type": "object", 201 + "description": "Entry with feed-specific context (discovery reason, notebook context).", 202 + "required": ["entry"], 203 + "properties": { 204 + "entry": { "type": "ref", "ref": "#entryView" }, 205 + "reason": { "type": "ref", "ref": "#feedReason" }, 206 + "notebookContext": { "type": "ref", "ref": "#feedNotebookContext" } 207 + } 208 + }, 209 + "feedNotebookContext": { 210 + "type": "object", 211 + "description": "Minimal notebook context for feed display.", 212 + "required": ["uri", "title"], 213 + "properties": { 214 + "uri": { "type": "string", "format": "at-uri" }, 215 + "title": { "type": "string" }, 216 + "path": { "type": "string" } 217 + } 218 + }, 219 + "feedReason": { 220 + "type": "union", 221 + "description": "Why this entry appeared in the feed.", 222 + "refs": ["#reasonLike", "#reasonBookmark", "#reasonSubscription"] 223 + }, 224 + "reasonLike": { 225 + "type": "object", 226 + "required": ["by", "indexedAt"], 227 + "properties": { 228 + "by": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 229 + "indexedAt": { "type": "string", "format": "datetime" } 230 + } 231 + }, 232 + "reasonBookmark": { 233 + "type": "object", 234 + "required": ["by", "indexedAt"], 235 + "properties": { 236 + "by": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 237 + "indexedAt": { "type": "string", "format": "datetime" } 238 + } 239 + }, 240 + "reasonSubscription": { 241 + "type": "object", 242 + "required": ["indexedAt"], 243 + "properties": { 244 + "indexedAt": { "type": "string", "format": "datetime" } 245 + } 246 + }, 247 + "publishedVersionView": { 248 + "type": "object", 249 + "description": "A published version of an entry in a collaborator's repo.", 250 + "required": ["uri", "cid", "publisher", "publishedAt"], 251 + "properties": { 252 + "uri": { "type": "string", "format": "at-uri" }, 253 + "cid": { "type": "string", "format": "cid" }, 254 + "publisher": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 255 + "publishedAt": { "type": "string", "format": "datetime" }, 256 + "updatedAt": { "type": "string", "format": "datetime" }, 257 + "isCanonical": { 258 + "type": "boolean", 259 + "description": "True if this is the 'primary' version (owner's repo)" 260 + }, 261 + "divergedFrom": { 262 + "type": "ref", 263 + "ref": "com.atproto.repo.strongRef", 264 + "description": "If content differs, the version it diverged from" 265 + } 266 + } 267 + }, 268 + "contentWarning": { 269 + "type": "string", 270 + "description": "Author-applied content warning.", 271 + "knownValues": [ 272 + "violence", 273 + "graphic-violence", 274 + "death", 275 + "major-character-death", 276 + "sexual-content", 277 + "explicit-sexual-content", 278 + "language", 279 + "substance-use", 280 + "self-harm", 281 + "abuse", 282 + "disturbing-imagery" 283 + ] 284 + }, 285 + "contentWarnings": { 286 + "type": "array", 287 + "description": "Author-applied content warnings.", 288 + "maxLength": 10, 289 + "items": { "type": "ref", "ref": "#contentWarning" } 290 + }, 291 + "contentRating": { 292 + "type": "string", 293 + "description": "Author-applied content rating.", 294 + "knownValues": ["general", "teen", "mature", "explicit"] 295 + }, 296 + "chapterView": { 297 + "type": "object", 298 + "description": "Hydrated view of a chapter.", 299 + "required": ["uri", "cid", "notebook", "authors", "record", "indexedAt"], 300 + "properties": { 301 + "uri": { "type": "string", "format": "at-uri" }, 302 + "cid": { "type": "string", "format": "cid" }, 303 + "title": { "type": "ref", "ref": "#title" }, 304 + "tags": { "type": "ref", "ref": "#tags" }, 305 + "notebook": { "type": "ref", "ref": "#notebookView" }, 306 + "authors": { 307 + "type": "array", 308 + "items": { "type": "ref", "ref": "#authorListView" } 309 + }, 310 + "record": { "type": "unknown" }, 311 + "entryCount": { "type": "integer" }, 312 + "indexedAt": { "type": "string", "format": "datetime" } 313 + } 314 + }, 315 + "chapterEntryView": { 316 + "type": "object", 317 + "description": "An entry within a chapter context.", 318 + "required": ["entry", "index"], 319 + "properties": { 320 + "entry": { "type": "ref", "ref": "#entryView" }, 321 + "index": { "type": "integer" }, 322 + "next": { "type": "ref", "ref": "#bookEntryRef" }, 323 + "prev": { "type": "ref", "ref": "#bookEntryRef" } 324 + } 325 + }, 326 + "pageView": { 327 + "type": "object", 328 + "description": "Hydrated view of a page (entries displayed together).", 329 + "required": ["uri", "cid", "notebook", "record", "indexedAt"], 330 + "properties": { 331 + "uri": { "type": "string", "format": "at-uri" }, 332 + "cid": { "type": "string", "format": "cid" }, 333 + "title": { "type": "ref", "ref": "#title" }, 334 + "tags": { "type": "ref", "ref": "#tags" }, 335 + "notebook": { "type": "ref", "ref": "#notebookView" }, 336 + "record": { "type": "unknown" }, 337 + "entryCount": { "type": "integer" }, 338 + "indexedAt": { "type": "string", "format": "datetime" } 339 + } 340 + }, 341 + "readingProgress": { 342 + "type": "object", 343 + "description": "Viewer's reading progress (appview-side state, not a record).", 344 + "properties": { 345 + "status": { 346 + "type": "string", 347 + "knownValues": ["reading", "finished", "abandoned", "want-to-read"] 348 + }, 349 + "currentEntry": { 350 + "type": "string", 351 + "format": "at-uri", 352 + "description": "Last entry the viewer was reading." 353 + }, 354 + "percentComplete": { 355 + "type": "integer", 356 + "minimum": 0, 357 + "maximum": 100 358 + }, 359 + "lastReadAt": { "type": "string", "format": "datetime" }, 360 + "startedAt": { "type": "string", "format": "datetime" }, 361 + "finishedAt": { "type": "string", "format": "datetime" } 184 362 } 185 363 } 186 364 }
+2
lexicons/notebook/entry.json
··· 34 34 "format": "datetime", 35 35 "description": "Client-declared timestamp of last modification. Used for canonicality tiebreaking in multi-author scenarios." 36 36 }, 37 + "contentWarnings": { "type": "ref", "ref": "sh.weaver.notebook.defs#contentWarnings" }, 38 + "rating": { "type": "ref", "ref": "sh.weaver.notebook.defs#contentRating" }, 37 39 "embeds": { 38 40 "type": "object", 39 41 "description": "The set of images and records, if any, embedded in the notebook entry.",
+37
lexicons/notebook/getChapter.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getChapter", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a chapter with its entries.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["chapter"], 11 + "properties": { 12 + "chapter": { "type": "string", "format": "at-uri" }, 13 + "entryLimit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "entryCursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["chapter", "entries"], 22 + "properties": { 23 + "chapter": { "type": "ref", "ref": "sh.weaver.notebook.defs#chapterView" }, 24 + "entries": { 25 + "type": "array", 26 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#chapterEntryView" } 27 + }, 28 + "entryCursor": { "type": "string" } 29 + } 30 + } 31 + }, 32 + "errors": [ 33 + { "name": "ChapterNotFound" } 34 + ] 35 + } 36 + } 37 + }
+47
lexicons/notebook/getContinueReading.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getContinueReading", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get notebooks the user is currently reading, sorted by most recent activity.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "limit": { "type": "integer", "minimum": 1, "maximum": 20, "default": 10 } 12 + } 13 + }, 14 + "output": { 15 + "encoding": "application/json", 16 + "schema": { 17 + "type": "object", 18 + "required": ["items"], 19 + "properties": { 20 + "items": { 21 + "type": "array", 22 + "items": { 23 + "type": "object", 24 + "required": ["notebook", "progress", "nextEntry"], 25 + "properties": { 26 + "notebook": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" }, 27 + "progress": { "type": "ref", "ref": "sh.weaver.notebook.defs#readingProgress" }, 28 + "currentEntry": { 29 + "type": "ref", 30 + "ref": "sh.weaver.notebook.defs#entryView", 31 + "description": "Where the user left off." 32 + }, 33 + "nextEntry": { 34 + "type": "ref", 35 + "ref": "sh.weaver.notebook.defs#entryView", 36 + "description": "The next entry to read (if any)." 37 + }, 38 + "entriesRemaining": { "type": "integer" } 39 + } 40 + } 41 + } 42 + } 43 + } 44 + } 45 + } 46 + } 47 + }
+38
lexicons/notebook/getEntryDetail.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getEntryDetail", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get an entry with its containing notebooks in a single call.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["entry"], 11 + "properties": { 12 + "entry": { "type": "string", "format": "at-uri" }, 13 + "notebookContext": { "type": "string", "format": "at-uri" } 14 + } 15 + }, 16 + "output": { 17 + "encoding": "application/json", 18 + "schema": { 19 + "type": "object", 20 + "required": ["entry", "record", "notebookCount"], 21 + "properties": { 22 + "entry": { "type": "ref", "ref": "sh.weaver.notebook.defs#entryView" }, 23 + "record": { "type": "unknown" }, 24 + "notebookCount": { "type": "integer" }, 25 + "notebooks": { 26 + "type": "array", 27 + "maxLength": 10, 28 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" } 29 + } 30 + } 31 + } 32 + }, 33 + "errors": [ 34 + { "name": "EntryNotFound" } 35 + ] 36 + } 37 + } 38 + }
+46
lexicons/notebook/getEntryFeed.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getEntryFeed", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a feed of entries with optional algorithm and tag filtering.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "algorithm": { 12 + "type": "string", 13 + "default": "chronological", 14 + "knownValues": ["chronological", "popular"] 15 + }, 16 + "feed": { 17 + "type": "string", 18 + "format": "at-uri", 19 + "description": "Optional custom feed generator URI" 20 + }, 21 + "tags": { 22 + "type": "array", 23 + "items": { "type": "string" }, 24 + "maxLength": 10 25 + }, 26 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 27 + "cursor": { "type": "string" } 28 + } 29 + }, 30 + "output": { 31 + "encoding": "application/json", 32 + "schema": { 33 + "type": "object", 34 + "required": ["feed"], 35 + "properties": { 36 + "feed": { 37 + "type": "array", 38 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#feedEntryView" } 39 + }, 40 + "cursor": { "type": "string" } 41 + } 42 + } 43 + } 44 + } 45 + } 46 + }
+33
lexicons/notebook/getNotebookChapters.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getNotebookChapters", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get all chapters for a notebook.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["notebook"], 11 + "properties": { 12 + "notebook": { "type": "string", "format": "at-uri" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "cursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["chapters"], 22 + "properties": { 23 + "chapters": { 24 + "type": "array", 25 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#chapterView" } 26 + }, 27 + "cursor": { "type": "string" } 28 + } 29 + } 30 + } 31 + } 32 + } 33 + }
+37
lexicons/notebook/getNotebookDetail.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getNotebookDetail", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a notebook with its entries in a single call.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["notebook"], 11 + "properties": { 12 + "notebook": { "type": "string", "format": "at-uri" }, 13 + "entryLimit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 14 + "entryCursor": { "type": "string" } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["notebook", "entries"], 22 + "properties": { 23 + "notebook": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" }, 24 + "entries": { 25 + "type": "array", 26 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#bookEntryView" } 27 + }, 28 + "entryCursor": { "type": "string" } 29 + } 30 + } 31 + }, 32 + "errors": [ 33 + { "name": "NotebookNotFound" } 34 + ] 35 + } 36 + } 37 + }
+46
lexicons/notebook/getNotebookFeed.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getNotebookFeed", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a feed of notebooks with optional algorithm and tag filtering.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "algorithm": { 12 + "type": "string", 13 + "default": "chronological", 14 + "knownValues": ["chronological", "popular"] 15 + }, 16 + "feed": { 17 + "type": "string", 18 + "format": "at-uri", 19 + "description": "Optional custom feed generator URI" 20 + }, 21 + "tags": { 22 + "type": "array", 23 + "items": { "type": "string" }, 24 + "maxLength": 10 25 + }, 26 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 27 + "cursor": { "type": "string" } 28 + } 29 + }, 30 + "output": { 31 + "encoding": "application/json", 32 + "schema": { 33 + "type": "object", 34 + "required": ["notebooks"], 35 + "properties": { 36 + "notebooks": { 37 + "type": "array", 38 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" } 39 + }, 40 + "cursor": { "type": "string" } 41 + } 42 + } 43 + } 44 + } 45 + } 46 + }
+34
lexicons/notebook/getPage.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getPage", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get a page with its entries (all entries, since pages display together).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["page"], 11 + "properties": { 12 + "page": { "type": "string", "format": "at-uri" } 13 + } 14 + }, 15 + "output": { 16 + "encoding": "application/json", 17 + "schema": { 18 + "type": "object", 19 + "required": ["page", "entries"], 20 + "properties": { 21 + "page": { "type": "ref", "ref": "sh.weaver.notebook.defs#pageView" }, 22 + "entries": { 23 + "type": "array", 24 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#entryView" } 25 + } 26 + } 27 + } 28 + }, 29 + "errors": [ 30 + { "name": "PageNotFound" } 31 + ] 32 + } 33 + } 34 + }
+49
lexicons/notebook/getPublishedVersions.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getPublishedVersions", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get all published versions of an entry (same rkey in collaborator repos).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["entry"], 11 + "properties": { 12 + "entry": { "type": "string", "format": "at-uri" }, 13 + "includeContent": { 14 + "type": "boolean", 15 + "default": false, 16 + "description": "Include full entry record in response" 17 + } 18 + } 19 + }, 20 + "output": { 21 + "encoding": "application/json", 22 + "schema": { 23 + "type": "object", 24 + "required": ["versions"], 25 + "properties": { 26 + "canonical": { "type": "ref", "ref": "sh.weaver.notebook.defs#publishedVersionView" }, 27 + "versions": { 28 + "type": "array", 29 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#publishedVersionView" } 30 + }, 31 + "hasDivergence": { "type": "boolean" }, 32 + "records": { 33 + "type": "array", 34 + "description": "Full entry records if includeContent=true", 35 + "items": { 36 + "type": "object", 37 + "required": ["uri", "record"], 38 + "properties": { 39 + "uri": { "type": "string", "format": "at-uri" }, 40 + "record": { "type": "unknown" } 41 + } 42 + } 43 + } 44 + } 45 + } 46 + } 47 + } 48 + } 49 + }
+50
lexicons/notebook/getReadingHistory.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getReadingHistory", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get the authenticated user's reading history.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "status": { 12 + "type": "string", 13 + "knownValues": ["reading", "finished", "abandoned", "want-to-read", "all"], 14 + "default": "all", 15 + "description": "Filter by reading status." 16 + }, 17 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 18 + "cursor": { "type": "string" } 19 + } 20 + }, 21 + "output": { 22 + "encoding": "application/json", 23 + "schema": { 24 + "type": "object", 25 + "required": ["history"], 26 + "properties": { 27 + "history": { 28 + "type": "array", 29 + "items": { "type": "ref", "ref": "#readingHistoryItem" } 30 + }, 31 + "cursor": { "type": "string" } 32 + } 33 + } 34 + } 35 + }, 36 + "readingHistoryItem": { 37 + "type": "object", 38 + "required": ["notebook", "progress"], 39 + "properties": { 40 + "notebook": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" }, 41 + "progress": { "type": "ref", "ref": "sh.weaver.notebook.defs#readingProgress" }, 42 + "currentEntry": { 43 + "type": "ref", 44 + "ref": "sh.weaver.notebook.defs#entryView", 45 + "description": "The entry the user was last reading." 46 + } 47 + } 48 + } 49 + } 50 + }
+43
lexicons/notebook/getSimilarNotebooks.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getSimilarNotebooks", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get notebooks similar to a given notebook (by tags, author, readers who also liked, etc).", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["notebook"], 11 + "properties": { 12 + "notebook": { "type": "string", "format": "at-uri" }, 13 + "limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 10 } 14 + } 15 + }, 16 + "output": { 17 + "encoding": "application/json", 18 + "schema": { 19 + "type": "object", 20 + "required": ["notebooks"], 21 + "properties": { 22 + "notebooks": { 23 + "type": "array", 24 + "items": { 25 + "type": "object", 26 + "required": ["notebook"], 27 + "properties": { 28 + "notebook": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" }, 29 + "sharedTags": { 30 + "type": "array", 31 + "items": { "type": "string" } 32 + }, 33 + "sameAuthor": { "type": "boolean" }, 34 + "readersAlsoLiked": { "type": "boolean" } 35 + } 36 + } 37 + } 38 + } 39 + } 40 + } 41 + } 42 + } 43 + }
+80
lexicons/notebook/getSuggestedNotebooks.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.getSuggestedNotebooks", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get notebook recommendations for the authenticated user based on reading history, likes, and follows.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } 12 + } 13 + }, 14 + "output": { 15 + "encoding": "application/json", 16 + "schema": { 17 + "type": "object", 18 + "required": ["notebooks"], 19 + "properties": { 20 + "notebooks": { 21 + "type": "array", 22 + "items": { "type": "ref", "ref": "#suggestedNotebook" } 23 + } 24 + } 25 + } 26 + } 27 + }, 28 + "suggestedNotebook": { 29 + "type": "object", 30 + "required": ["notebook", "reason"], 31 + "properties": { 32 + "notebook": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" }, 33 + "reason": { "type": "ref", "ref": "#suggestionReason" }, 34 + "score": { 35 + "type": "number", 36 + "description": "Appview-computed relevance score." 37 + } 38 + } 39 + }, 40 + "suggestionReason": { 41 + "type": "object", 42 + "description": "Why this notebook was suggested.", 43 + "required": ["type"], 44 + "properties": { 45 + "type": { 46 + "type": "string", 47 + "knownValues": [ 48 + "similar-tags", 49 + "similar-to-liked", 50 + "similar-to-read", 51 + "followed-author", 52 + "popular-in-tag", 53 + "trending", 54 + "from-list" 55 + ] 56 + }, 57 + "relatedNotebook": { 58 + "type": "ref", 59 + "ref": "sh.weaver.notebook.defs#notebookView", 60 + "description": "If similar-to-X, the notebook it's similar to." 61 + }, 62 + "relatedAuthor": { 63 + "type": "ref", 64 + "ref": "sh.weaver.actor.defs#profileViewBasic", 65 + "description": "If followed-author, the author." 66 + }, 67 + "relatedTags": { 68 + "type": "array", 69 + "items": { "type": "string" }, 70 + "description": "Tags that matched." 71 + }, 72 + "relatedList": { 73 + "type": "ref", 74 + "ref": "sh.weaver.graph.defs#listView", 75 + "description": "If from-list, the list it's from." 76 + } 77 + } 78 + } 79 + } 80 + }
+40
lexicons/notebook/resolveEntry.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.resolveEntry", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Resolve an entry by actor + notebook + entry title/path.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor", "notebook", "entry"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "notebook": { "type": "string", "maxLength": 300 }, 14 + "entry": { "type": "string", "maxLength": 300 } 15 + } 16 + }, 17 + "output": { 18 + "encoding": "application/json", 19 + "schema": { 20 + "type": "object", 21 + "required": ["entry", "record", "notebookCount"], 22 + "properties": { 23 + "entry": { "type": "ref", "ref": "sh.weaver.notebook.defs#entryView" }, 24 + "record": { "type": "unknown" }, 25 + "notebookCount": { "type": "integer" }, 26 + "notebooks": { 27 + "type": "array", 28 + "maxLength": 10, 29 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" } 30 + } 31 + } 32 + } 33 + }, 34 + "errors": [ 35 + { "name": "NotebookNotFound" }, 36 + { "name": "EntryNotFound" } 37 + ] 38 + } 39 + } 40 + }
+38
lexicons/notebook/resolveNotebook.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.resolveNotebook", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Resolve a notebook by actor + title/path, returns full detail.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["actor", "name"], 11 + "properties": { 12 + "actor": { "type": "string", "format": "at-identifier" }, 13 + "name": { "type": "string", "maxLength": 300 }, 14 + "entryLimit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 15 + "entryCursor": { "type": "string" } 16 + } 17 + }, 18 + "output": { 19 + "encoding": "application/json", 20 + "schema": { 21 + "type": "object", 22 + "required": ["notebook", "entries"], 23 + "properties": { 24 + "notebook": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" }, 25 + "entries": { 26 + "type": "array", 27 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#bookEntryView" } 28 + }, 29 + "entryCursor": { "type": "string" } 30 + } 31 + } 32 + }, 33 + "errors": [ 34 + { "name": "NotebookNotFound" } 35 + ] 36 + } 37 + } 38 + }
+40
lexicons/notebook/resolveVersionConflict.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.resolveVersionConflict", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Given multiple URIs that might refer to the same collaborative entry, resolve to canonical version.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["uris"], 11 + "properties": { 12 + "uris": { 13 + "type": "array", 14 + "minLength": 1, 15 + "maxLength": 20, 16 + "items": { "type": "string", "format": "at-uri" } 17 + } 18 + } 19 + }, 20 + "output": { 21 + "encoding": "application/json", 22 + "schema": { 23 + "type": "object", 24 + "required": ["canonical", "related"], 25 + "properties": { 26 + "canonical": { "type": "ref", "ref": "sh.weaver.notebook.defs#publishedVersionView" }, 27 + "related": { 28 + "type": "array", 29 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#publishedVersionView" } 30 + }, 31 + "collaborationState": { "type": "ref", "ref": "sh.weaver.collab.defs#collaborationStateView" } 32 + } 33 + } 34 + }, 35 + "errors": [ 36 + { "name": "NoRelatedVersions", "description": "The URIs don't appear to be related versions" } 37 + ] 38 + } 39 + } 40 + }
+39
lexicons/notebook/searchEntries.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.searchEntries", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Full-text search for entries with optional author and tag filtering.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["q"], 11 + "properties": { 12 + "q": { "type": "string", "minLength": 1, "maxLength": 500 }, 13 + "author": { "type": "string", "format": "at-identifier" }, 14 + "tags": { 15 + "type": "array", 16 + "items": { "type": "string" }, 17 + "maxLength": 10 18 + }, 19 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 }, 20 + "cursor": { "type": "string" } 21 + } 22 + }, 23 + "output": { 24 + "encoding": "application/json", 25 + "schema": { 26 + "type": "object", 27 + "required": ["entries"], 28 + "properties": { 29 + "entries": { 30 + "type": "array", 31 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#entryView" } 32 + }, 33 + "cursor": { "type": "string" } 34 + } 35 + } 36 + } 37 + } 38 + } 39 + }
+54
lexicons/notebook/searchNotebooks.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.searchNotebooks", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Full-text search for notebooks.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["q"], 11 + "properties": { 12 + "q": { "type": "string", "minLength": 1, "maxLength": 500 }, 13 + "author": { 14 + "type": "string", 15 + "format": "at-identifier", 16 + "description": "Filter by author." 17 + }, 18 + "tags": { 19 + "type": "array", 20 + "items": { "type": "string" }, 21 + "maxLength": 10, 22 + "description": "Filter by tags (all must match)." 23 + }, 24 + "rating": { 25 + "type": "array", 26 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#contentRating" }, 27 + "description": "Filter by content rating (any of these)." 28 + }, 29 + "sort": { 30 + "type": "string", 31 + "knownValues": ["relevance", "recent", "popular"], 32 + "default": "relevance" 33 + }, 34 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 25 }, 35 + "cursor": { "type": "string" } 36 + } 37 + }, 38 + "output": { 39 + "encoding": "application/json", 40 + "schema": { 41 + "type": "object", 42 + "required": ["notebooks"], 43 + "properties": { 44 + "notebooks": { 45 + "type": "array", 46 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" } 47 + }, 48 + "cursor": { "type": "string" } 49 + } 50 + } 51 + } 52 + } 53 + } 54 + }
+44
lexicons/notebook/updateReadingProgress.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notebook.updateReadingProgress", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Update reading progress for a notebook (appview-side state).", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["notebook"], 13 + "properties": { 14 + "notebook": { "type": "string", "format": "at-uri" }, 15 + "currentEntry": { 16 + "type": "string", 17 + "format": "at-uri", 18 + "description": "The entry the user is currently on." 19 + }, 20 + "status": { 21 + "type": "string", 22 + "knownValues": ["reading", "finished", "abandoned", "want-to-read"] 23 + }, 24 + "percentComplete": { 25 + "type": "integer", 26 + "minimum": 0, 27 + "maximum": 100 28 + } 29 + } 30 + } 31 + }, 32 + "output": { 33 + "encoding": "application/json", 34 + "schema": { 35 + "type": "object", 36 + "required": ["progress"], 37 + "properties": { 38 + "progress": { "type": "ref", "ref": "sh.weaver.notebook.defs#readingProgress" } 39 + } 40 + } 41 + } 42 + } 43 + } 44 + }
+87
lexicons/notification/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notification.defs", 4 + "defs": { 5 + "notification": { 6 + "type": "object", 7 + "description": "A notification for a user.", 8 + "required": ["uri", "cid", "author", "reason", "isRead", "indexedAt"], 9 + "properties": { 10 + "uri": { "type": "string", "format": "at-uri" }, 11 + "cid": { "type": "string", "format": "cid" }, 12 + "author": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 13 + "reason": { "type": "ref", "ref": "#notificationReason" }, 14 + "reasonSubject": { 15 + "type": "string", 16 + "format": "at-uri", 17 + "description": "The subject of the notification (entry, notebook, etc)." 18 + }, 19 + "record": { "type": "unknown" }, 20 + "isRead": { "type": "boolean" }, 21 + "indexedAt": { "type": "string", "format": "datetime" } 22 + } 23 + }, 24 + "notificationReason": { 25 + "type": "string", 26 + "description": "Why this notification was generated.", 27 + "knownValues": [ 28 + "like", 29 + "bookmark", 30 + "follow", 31 + "followAccept", 32 + "subscribe", 33 + "subscribeAccept", 34 + "collaborationInvite", 35 + "collaborationAccept", 36 + "newEntry", 37 + "entryUpdate", 38 + "mention", 39 + "tag", 40 + "comment" 41 + ] 42 + }, 43 + "notificationGroup": { 44 + "type": "object", 45 + "description": "Grouped notifications (e.g., '5 people liked your entry').", 46 + "required": ["reason", "subject", "count", "actors", "mostRecentAt"], 47 + "properties": { 48 + "reason": { "type": "ref", "ref": "#notificationReason" }, 49 + "subject": { 50 + "type": "union", 51 + "refs": [ 52 + "sh.weaver.notebook.defs#notebookView", 53 + "sh.weaver.notebook.defs#entryView" 54 + ] 55 + }, 56 + "count": { "type": "integer" }, 57 + "actors": { 58 + "type": "array", 59 + "maxLength": 5, 60 + "items": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" }, 61 + "description": "Most recent actors (up to 5)." 62 + }, 63 + "mostRecentAt": { "type": "string", "format": "datetime" }, 64 + "isRead": { "type": "boolean" } 65 + } 66 + }, 67 + "subscriptionUpdateView": { 68 + "type": "object", 69 + "description": "New content from a notebook subscription.", 70 + "required": ["notebook", "newEntries", "updatedAt"], 71 + "properties": { 72 + "notebook": { "type": "ref", "ref": "sh.weaver.notebook.defs#notebookView" }, 73 + "newEntries": { 74 + "type": "array", 75 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#entryView" }, 76 + "description": "New entries since last check." 77 + }, 78 + "updatedEntries": { 79 + "type": "array", 80 + "items": { "type": "ref", "ref": "sh.weaver.notebook.defs#entryView" }, 81 + "description": "Entries that were updated." 82 + }, 83 + "updatedAt": { "type": "string", "format": "datetime" } 84 + } 85 + } 86 + } 87 + }
+36
lexicons/notification/getSubscriptionUpdates.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notification.getSubscriptionUpdates", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get new/updated content from notebooks the user subscribes to.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "since": { 12 + "type": "string", 13 + "format": "datetime", 14 + "description": "Only show updates since this timestamp." 15 + }, 16 + "limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 }, 17 + "cursor": { "type": "string" } 18 + } 19 + }, 20 + "output": { 21 + "encoding": "application/json", 22 + "schema": { 23 + "type": "object", 24 + "required": ["updates"], 25 + "properties": { 26 + "updates": { 27 + "type": "array", 28 + "items": { "type": "ref", "ref": "sh.weaver.notification.defs#subscriptionUpdateView" } 29 + }, 30 + "cursor": { "type": "string" } 31 + } 32 + } 33 + } 34 + } 35 + } 36 + }
+30
lexicons/notification/getUnreadCount.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notification.getUnreadCount", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get count of unread notifications for the authenticated user.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "seenAt": { 12 + "type": "string", 13 + "format": "datetime", 14 + "description": "Count notifications after this timestamp." 15 + } 16 + } 17 + }, 18 + "output": { 19 + "encoding": "application/json", 20 + "schema": { 21 + "type": "object", 22 + "required": ["count"], 23 + "properties": { 24 + "count": { "type": "integer" } 25 + } 26 + } 27 + } 28 + } 29 + } 30 + }
+42
lexicons/notification/listNotifications.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notification.listNotifications", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Get notifications for the authenticated user.", 8 + "parameters": { 9 + "type": "params", 10 + "properties": { 11 + "reasons": { 12 + "type": "array", 13 + "items": { "type": "ref", "ref": "sh.weaver.notification.defs#notificationReason" }, 14 + "description": "Filter by notification reasons." 15 + }, 16 + "seenAt": { 17 + "type": "string", 18 + "format": "datetime", 19 + "description": "Only show notifications after this timestamp." 20 + }, 21 + "limit": { "type": "integer", "minimum": 1, "maximum": 100, "default": 50 }, 22 + "cursor": { "type": "string" } 23 + } 24 + }, 25 + "output": { 26 + "encoding": "application/json", 27 + "schema": { 28 + "type": "object", 29 + "required": ["notifications"], 30 + "properties": { 31 + "notifications": { 32 + "type": "array", 33 + "items": { "type": "ref", "ref": "sh.weaver.notification.defs#notification" } 34 + }, 35 + "cursor": { "type": "string" }, 36 + "seenAt": { "type": "string", "format": "datetime" } 37 + } 38 + } 39 + } 40 + } 41 + } 42 + }
+27
lexicons/notification/updateSeen.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.notification.updateSeen", 4 + "defs": { 5 + "main": { 6 + "type": "procedure", 7 + "description": "Mark notifications as seen up to a given timestamp.", 8 + "input": { 9 + "encoding": "application/json", 10 + "schema": { 11 + "type": "object", 12 + "required": ["seenAt"], 13 + "properties": { 14 + "seenAt": { "type": "string", "format": "datetime" } 15 + } 16 + } 17 + }, 18 + "output": { 19 + "encoding": "application/json", 20 + "schema": { 21 + "type": "object", 22 + "properties": {} 23 + } 24 + } 25 + } 26 + } 27 + }
+14 -2
weaver_notes/.obsidian/workspace.json
··· 48 48 "icon": "lucide-file", 49 49 "title": "Why I rewrote pdsls in Rust (tm)" 50 50 } 51 + }, 52 + { 53 + "id": "4b584137400d2323", 54 + "type": "leaf", 55 + "state": { 56 + "type": "release-notes", 57 + "state": { 58 + "currentVersion": "1.10.6" 59 + }, 60 + "icon": "lucide-book-up", 61 + "title": "Release Notes 1.10.6" 62 + } 51 63 } 52 64 ], 53 - "currentTab": 2 65 + "currentTab": 3 54 66 } 55 67 ], 56 68 "direction": "vertical" ··· 199 211 "bases:Create new base": false 200 212 } 201 213 }, 202 - "active": "6029beecc3d03bce", 214 + "active": "4b584137400d2323", 203 215 "lastOpenFiles": [ 204 216 "light_mode_excerpt.png", 205 217 "notebook_entry_preview.png",