Fase B8+B9: stateful code kernel and live notes bound to external URLs

B8 - executable code blocks with a real kernel:
- worker/handler/kernel.cljs: one persistent SCI interpreter session per
  page, reused across block evaluations so defs/state survive between runs.
  Deliberately scoped to the same privileges the existing client-side
  single-shot evaluator already had (no shell/fs access, no call-api).
- Run button + result display wired into block.cljs's code-block UI.
- New :logseq.property.code/result and /executed-at properties (65.38).

B9 - live notes: pages tagged #LiveNote that fetch external content on a
refresh schedule and render it via the render-resource pipeline:
- worker/handler/live_notes.cljs: per-block credential storage, scheduled
  refresh (Node-only), thread-apis for manual refresh and auth.
- worker/handler/render_resource/live_note.cljs: reads back fetched content,
  watching [:entity block-uuid] for reactive invalidation.
- New :logseq.class/LiveNote + :logseq.property.livenote/* properties (65.39).

Bugs found and fixed along the way while actually exercising page creation
through page-handler/create! for the first time in a test (previously only
pure-fn tests existed for CalDAV/Event/Contact):
- logseq-property-namespaces (property.cljs) was missing the citation/event/
  contact/caldav/livenote namespaces, causing auto-create-ontology to treat
  already-built-in properties as new user idents.
- outliner/page.cljs's build-page-tx always added the generic #Page tag even
  when the caller tagged with a built-in class that extends #Page, which
  malli-schema rejects as conflicting; it also lost the property type when
  building ref-typed property values for new pages, breaking non-:default
  types like :number.
- entity-util/page? never recognized Event/Contact/LiveNote as pages (only
  Journal/Whiteboard/Tag/Property/Page had dedicated recognition), so pages
  tagged with those classes alone weren't treated as pages anywhere in the
  app; added built-in-page-child? alongside the existing per-class checks.
- caldav.cljs's upsert-page! passed a bare keyword as a tag where an entity
  was required, and two error logs passed raw error objects to glogi that
  triggered runaway recursion in this test environment; both fixed.
This commit is contained in:
2026-08-26 22:41:23 +02:00
parent 0158430489
commit d8996bd5e1
18 changed files with 698 additions and 13 deletions

View File

@@ -154,10 +154,33 @@
(ldb/transact! conn tx-data tx-meta'))
true))))))
(defn- tag-ident
[tag]
(cond (de/entity? tag) (:db/ident tag)
(keyword? tag) tag
(map? tag) (:db/ident tag)))
(defn- build-page-tx [db properties page {:keys [class? tags class-ident-namespace]}]
(when (:block/uuid page)
(let [type-tag (if class? :logseq.class/Tag :logseq.class/Page)
tags' (if (:block/journal-day page) tags (conj tags type-tag))
;; A page already tagged with a built-in class that extends #Page
;; (Journal, Whiteboard, Event, Contact, Project, Area, ...) must
;; not also carry the generic #Page tag -- malli-schema rejects
;; that combination as conflicting built-in page tags.
already-page-tagged? (and (= type-tag :logseq.class/Page)
(some (fn [tag]
(let [ident (tag-ident tag)]
(and ident
(or (= ident :logseq.class/Page)
(contains? db-class/page-children-classes ident)))))
tags))
tags' (if (or (:block/journal-day page) already-page-tagged?) tags (conj tags type-tag))
;; page-name->map may have already seeded :block/tags with the
;; generic #Page tag -- strip it back out here too, or it survives
;; the merge below even though tags' no longer re-adds it.
page (cond-> page
already-page-tagged?
(update :block/tags (fn [existing] (remove #{:logseq.class/Page} existing))))
page' (update page :block/tags
(fnil into [])
(mapv (fn [tag]
@@ -181,10 +204,10 @@
page'
(->> properties
(keep (fn [[k v]]
;; TODO: Pass in property type in order to support property
;; types other than :default
(when (db-property/built-in-has-ref-value? k)
[k v])))
[{:db/ident k
:logseq.property/type (get-in db-property/built-in-properties [k :schema :type])}
v])))
(into {})))]
(cond-> (if class?
[(merge (db-class/build-new-class db page' {:ident-namespace class-ident-namespace})