@dxos/plugin-magazine 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/dist/lib/MagazinePlugin.mjs +36 -0
  2. package/dist/lib/MagazinePlugin.mjs.map +1 -0
  3. package/dist/lib/MagazinePlugin.workerd.mjs +26 -0
  4. package/dist/lib/MagazinePlugin.workerd.mjs.map +1 -0
  5. package/dist/lib/atoms.mjs +175 -0
  6. package/dist/lib/atoms.mjs.map +1 -0
  7. package/dist/lib/capabilities.mjs +12 -0
  8. package/dist/lib/capabilities.mjs.map +1 -0
  9. package/dist/lib/chunk-FeedArticle.mjs +70 -0
  10. package/dist/lib/chunk-FeedArticle.mjs.map +1 -0
  11. package/dist/lib/chunk-FeedProperties.mjs +78 -0
  12. package/dist/lib/chunk-FeedProperties.mjs.map +1 -0
  13. package/dist/lib/chunk-MagazineArticle.mjs +267 -0
  14. package/dist/lib/chunk-MagazineArticle.mjs.map +1 -0
  15. package/dist/lib/chunk-PostArticle.mjs +174 -0
  16. package/dist/lib/chunk-PostArticle.mjs.map +1 -0
  17. package/dist/lib/chunk-PostCard.mjs +62 -0
  18. package/dist/lib/chunk-PostCard.mjs.map +1 -0
  19. package/dist/lib/chunk-app-graph-builder.mjs +91 -0
  20. package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
  21. package/dist/lib/chunk-clear-magazine.mjs +37 -0
  22. package/dist/lib/chunk-clear-magazine.mjs.map +1 -0
  23. package/dist/lib/chunk-create-object.mjs +59 -0
  24. package/dist/lib/chunk-create-object.mjs.map +1 -0
  25. package/dist/lib/chunk-curate-magazine.mjs +164 -0
  26. package/dist/lib/chunk-curate-magazine.mjs.map +1 -0
  27. package/dist/lib/chunk-date.mjs +25 -0
  28. package/dist/lib/chunk-date.mjs.map +1 -0
  29. package/dist/lib/chunk-fetch-article-content.mjs +26 -0
  30. package/dist/lib/chunk-fetch-article-content.mjs.map +1 -0
  31. package/dist/lib/chunk-load-post-content.mjs +57 -0
  32. package/dist/lib/chunk-load-post-content.mjs.map +1 -0
  33. package/dist/lib/{neutral/chunk-JFPR6OV4.mjs → chunk-meta.mjs} +19 -26
  34. package/dist/lib/chunk-meta.mjs.map +1 -0
  35. package/dist/lib/chunk-operation-handler.mjs +13 -0
  36. package/dist/lib/chunk-operation-handler.mjs.map +1 -0
  37. package/dist/lib/chunk-paths.mjs +8 -0
  38. package/dist/lib/chunk-paths.mjs.map +1 -0
  39. package/dist/lib/chunk-post-content.mjs +14 -0
  40. package/dist/lib/chunk-post-content.mjs.map +1 -0
  41. package/dist/lib/chunk-react-surface.mjs +60 -0
  42. package/dist/lib/chunk-react-surface.mjs.map +1 -0
  43. package/dist/lib/chunk-routine-templates.mjs +52 -0
  44. package/dist/lib/chunk-routine-templates.mjs.map +1 -0
  45. package/dist/lib/chunk-skill-definition.mjs +12 -0
  46. package/dist/lib/chunk-skill-definition.mjs.map +1 -0
  47. package/dist/lib/chunk-sources.mjs +576 -0
  48. package/dist/lib/chunk-sources.mjs.map +1 -0
  49. package/dist/lib/chunk-sync-feed.mjs +86 -0
  50. package/dist/lib/chunk-sync-feed.mjs.map +1 -0
  51. package/dist/lib/chunk-text.mjs +52 -0
  52. package/dist/lib/chunk-text.mjs.map +1 -0
  53. package/dist/lib/chunk-types.mjs +607 -0
  54. package/dist/lib/chunk-types.mjs.map +1 -0
  55. package/dist/lib/components.mjs +323 -0
  56. package/dist/lib/components.mjs.map +1 -0
  57. package/dist/lib/containers.mjs +11 -0
  58. package/dist/lib/containers.mjs.map +1 -0
  59. package/dist/lib/index.mjs +3 -0
  60. package/dist/lib/meta.mjs +2 -0
  61. package/dist/lib/operations.mjs +7 -0
  62. package/dist/lib/operations.mjs.map +1 -0
  63. package/dist/lib/plugin.mjs +9 -0
  64. package/dist/lib/plugin.mjs.map +1 -0
  65. package/dist/lib/plugin.workerd.mjs +3 -0
  66. package/dist/lib/{neutral/skills/index.mjs → skills.mjs} +15 -28
  67. package/dist/lib/skills.mjs.map +1 -0
  68. package/dist/lib/testing.mjs +71 -0
  69. package/dist/lib/testing.mjs.map +1 -0
  70. package/dist/lib/translations.mjs +74 -0
  71. package/dist/lib/translations.mjs.map +1 -0
  72. package/dist/lib/types.mjs +2 -0
  73. package/dist/types/src/MagazinePlugin.d.ts.map +1 -1
  74. package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
  75. package/dist/types/src/capabilities/create-object.d.ts +1 -1
  76. package/dist/types/src/capabilities/index.d.ts +0 -1
  77. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  78. package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
  79. package/dist/types/src/capabilities/react-surface.d.ts +1 -1
  80. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  81. package/dist/types/src/capabilities/routine-templates.d.ts +1 -1
  82. package/dist/types/src/components/PostContent/PostContent.d.ts +1 -13
  83. package/dist/types/src/components/PostContent/PostContent.d.ts.map +1 -1
  84. package/dist/types/src/components/PostContent/dedupe-images.d.ts +13 -0
  85. package/dist/types/src/components/PostContent/dedupe-images.d.ts.map +1 -0
  86. package/dist/types/src/components/PostContent/index.d.ts +1 -0
  87. package/dist/types/src/components/PostContent/index.d.ts.map +1 -1
  88. package/dist/types/src/components/PostStack/PostStack.d.ts +1 -1
  89. package/dist/types/src/components/PostStack/PostStack.d.ts.map +1 -1
  90. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts +1 -1
  91. package/dist/types/src/components/SubscriptionStack/SubscriptionStack.d.ts.map +1 -1
  92. package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts +4 -1
  93. package/dist/types/src/containers/FeedArticle/FeedArticle.d.ts.map +1 -1
  94. package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts +4 -1
  95. package/dist/types/src/containers/FeedProperties/FeedProperties.d.ts.map +1 -1
  96. package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts +4 -1
  97. package/dist/types/src/containers/MagazineArticle/MagazineArticle.d.ts.map +1 -1
  98. package/dist/types/src/containers/MagazineArticle/MagazineArticle.stories.d.ts.map +1 -1
  99. package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts +4 -1
  100. package/dist/types/src/containers/MagazineArticle/MagazineTile.d.ts.map +1 -1
  101. package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts +4 -8
  102. package/dist/types/src/containers/MagazineArticle/useToolbar.d.ts.map +1 -1
  103. package/dist/types/src/containers/PostArticle/PostArticle.d.ts +4 -1
  104. package/dist/types/src/containers/PostArticle/PostArticle.d.ts.map +1 -1
  105. package/dist/types/src/containers/PostArticle/PostArticle.stories.d.ts.map +1 -1
  106. package/dist/types/src/containers/PostArticle/PostToolbar.d.ts +1 -1
  107. package/dist/types/src/containers/PostArticle/PostToolbar.d.ts.map +1 -1
  108. package/dist/types/src/containers/PostCard/PostCard.d.ts +4 -6
  109. package/dist/types/src/containers/PostCard/PostCard.d.ts.map +1 -1
  110. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts +4 -1
  111. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.d.ts.map +1 -1
  112. package/dist/types/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.d.ts.map +1 -1
  113. package/dist/types/src/stories/ArticleExtractor.stories.d.ts +1 -0
  114. package/dist/types/src/stories/ArticleExtractor.stories.d.ts.map +1 -1
  115. package/dist/types/src/stories/MagazineCurate.stories.d.ts.map +1 -1
  116. package/dist/types/src/templates/magazine-curation.d.ts.map +1 -1
  117. package/dist/types/src/translations.d.ts +1 -0
  118. package/dist/types/src/translations.d.ts.map +1 -1
  119. package/dist/types/tsconfig.tsbuildinfo +1 -1
  120. package/dx.config.ts +1 -1
  121. package/package.json +57 -60
  122. package/src/MagazinePlugin.tsx +0 -3
  123. package/src/atoms/atoms.test.ts +5 -4
  124. package/src/capabilities/app-graph-builder.ts +8 -6
  125. package/src/capabilities/index.ts +0 -1
  126. package/src/capabilities/{react-surface.tsx → react-surface.ts} +10 -12
  127. package/src/components/PostContent/PostContent.test.ts +1 -1
  128. package/src/components/PostContent/PostContent.tsx +1 -41
  129. package/src/components/PostContent/dedupe-images.ts +48 -0
  130. package/src/components/PostContent/index.ts +1 -0
  131. package/src/containers/FeedArticle/FeedArticle.stories.tsx +2 -2
  132. package/src/containers/FeedArticle/FeedArticle.tsx +4 -2
  133. package/src/containers/FeedProperties/FeedProperties.tsx +6 -4
  134. package/src/containers/MagazineArticle/MagazineArticle.stories.tsx +2 -1
  135. package/src/containers/MagazineArticle/MagazineArticle.tsx +8 -6
  136. package/src/containers/MagazineArticle/MagazineTile.tsx +2 -0
  137. package/src/containers/MagazineArticle/useToolbar.tsx +2 -0
  138. package/src/containers/PostArticle/PostArticle.stories.tsx +2 -1
  139. package/src/containers/PostArticle/PostArticle.tsx +6 -3
  140. package/src/containers/PostArticle/PostToolbar.tsx +1 -1
  141. package/src/containers/PostCard/PostCard.tsx +3 -1
  142. package/src/containers/SubscriptionsArticle/SubscriptionsArticle.stories.tsx +2 -1
  143. package/src/containers/SubscriptionsArticle/SubscriptionsArticle.tsx +5 -3
  144. package/src/operations/curate-magazine.test.ts +108 -4
  145. package/src/operations/sync-feed.test.ts +1 -1
  146. package/src/operations/sync-feed.ts +1 -1
  147. package/src/paths.ts +3 -3
  148. package/src/stories/ArticleExtractor.stories.tsx +1 -1
  149. package/src/stories/MagazineCurate.stories.tsx +3 -2
  150. package/src/templates/magazine-curation.ts +3 -2
  151. package/src/types/Magazine.test.ts +1 -1
  152. package/src/types/Subscription.ts +1 -1
  153. package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs +0 -90
  154. package/dist/lib/neutral/FeedArticle-PEWCFFSP.mjs.map +0 -7
  155. package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs +0 -97
  156. package/dist/lib/neutral/FeedProperties-EIO7IZOA.mjs.map +0 -7
  157. package/dist/lib/neutral/MagazineArticle-5T7RTIPS.mjs +0 -325
  158. package/dist/lib/neutral/MagazineArticle-5T7RTIPS.mjs.map +0 -7
  159. package/dist/lib/neutral/MagazinePlugin.mjs +0 -62
  160. package/dist/lib/neutral/MagazinePlugin.mjs.map +0 -7
  161. package/dist/lib/neutral/MagazinePlugin.workerd.mjs +0 -12
  162. package/dist/lib/neutral/MagazinePlugin.workerd.mjs.map +0 -7
  163. package/dist/lib/neutral/PostArticle-BGIPU7XA.mjs +0 -230
  164. package/dist/lib/neutral/PostArticle-BGIPU7XA.mjs.map +0 -7
  165. package/dist/lib/neutral/PostCard-VDGN7BBA.mjs +0 -60
  166. package/dist/lib/neutral/PostCard-VDGN7BBA.mjs.map +0 -7
  167. package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs +0 -121
  168. package/dist/lib/neutral/app-graph-builder-JDPRBVHL.mjs.map +0 -7
  169. package/dist/lib/neutral/capabilities/index.mjs +0 -21
  170. package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
  171. package/dist/lib/neutral/chunk-3K4AQKBZ.mjs +0 -12
  172. package/dist/lib/neutral/chunk-3K4AQKBZ.mjs.map +0 -7
  173. package/dist/lib/neutral/chunk-AFPBWBTK.mjs +0 -591
  174. package/dist/lib/neutral/chunk-AFPBWBTK.mjs.map +0 -7
  175. package/dist/lib/neutral/chunk-APQRTYT3.mjs +0 -57
  176. package/dist/lib/neutral/chunk-APQRTYT3.mjs.map +0 -7
  177. package/dist/lib/neutral/chunk-GU725ZF4.mjs +0 -11
  178. package/dist/lib/neutral/chunk-GU725ZF4.mjs.map +0 -7
  179. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
  180. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
  181. package/dist/lib/neutral/chunk-JFPR6OV4.mjs.map +0 -7
  182. package/dist/lib/neutral/chunk-KTYLUOUG.mjs +0 -36
  183. package/dist/lib/neutral/chunk-KTYLUOUG.mjs.map +0 -7
  184. package/dist/lib/neutral/chunk-LFSQMLPK.mjs +0 -8
  185. package/dist/lib/neutral/chunk-LFSQMLPK.mjs.map +0 -7
  186. package/dist/lib/neutral/chunk-MBPX7RPI.mjs +0 -14
  187. package/dist/lib/neutral/chunk-MBPX7RPI.mjs.map +0 -7
  188. package/dist/lib/neutral/chunk-OYCDRSWB.mjs +0 -624
  189. package/dist/lib/neutral/chunk-OYCDRSWB.mjs.map +0 -7
  190. package/dist/lib/neutral/chunk-SAWKLGJU.mjs +0 -28
  191. package/dist/lib/neutral/chunk-SAWKLGJU.mjs.map +0 -7
  192. package/dist/lib/neutral/chunk-XCNCK47N.mjs +0 -15
  193. package/dist/lib/neutral/chunk-XCNCK47N.mjs.map +0 -7
  194. package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs +0 -59
  195. package/dist/lib/neutral/clear-magazine-KNY4OWY4.mjs.map +0 -7
  196. package/dist/lib/neutral/components/index.mjs +0 -338
  197. package/dist/lib/neutral/components/index.mjs.map +0 -7
  198. package/dist/lib/neutral/containers/index.mjs +0 -17
  199. package/dist/lib/neutral/containers/index.mjs.map +0 -7
  200. package/dist/lib/neutral/create-object-SYZMRR4H.mjs +0 -98
  201. package/dist/lib/neutral/create-object-SYZMRR4H.mjs.map +0 -7
  202. package/dist/lib/neutral/curate-magazine-7RMKSJC5.mjs +0 -184
  203. package/dist/lib/neutral/curate-magazine-7RMKSJC5.mjs.map +0 -7
  204. package/dist/lib/neutral/fetch-article-content-CXPKXIMR.mjs +0 -31
  205. package/dist/lib/neutral/fetch-article-content-CXPKXIMR.mjs.map +0 -7
  206. package/dist/lib/neutral/index.mjs +0 -18
  207. package/dist/lib/neutral/index.mjs.map +0 -7
  208. package/dist/lib/neutral/load-post-content-H3S4TKVM.mjs +0 -65
  209. package/dist/lib/neutral/load-post-content-H3S4TKVM.mjs.map +0 -7
  210. package/dist/lib/neutral/meta.json +0 -1
  211. package/dist/lib/neutral/meta.mjs +0 -8
  212. package/dist/lib/neutral/meta.mjs.map +0 -7
  213. package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs +0 -18
  214. package/dist/lib/neutral/navigation-resolver-IN4OMCDR.mjs.map +0 -7
  215. package/dist/lib/neutral/operation-handler-JE3743BU.mjs +0 -8
  216. package/dist/lib/neutral/operation-handler-JE3743BU.mjs.map +0 -7
  217. package/dist/lib/neutral/operations/index.mjs +0 -8
  218. package/dist/lib/neutral/operations/index.mjs.map +0 -7
  219. package/dist/lib/neutral/plugin.mjs +0 -16
  220. package/dist/lib/neutral/plugin.mjs.map +0 -7
  221. package/dist/lib/neutral/plugin.workerd.mjs +0 -16
  222. package/dist/lib/neutral/plugin.workerd.mjs.map +0 -7
  223. package/dist/lib/neutral/react-surface-TZESAMG2.mjs +0 -60
  224. package/dist/lib/neutral/react-surface-TZESAMG2.mjs.map +0 -7
  225. package/dist/lib/neutral/routine-templates-D5A2L4KL.mjs +0 -52
  226. package/dist/lib/neutral/routine-templates-D5A2L4KL.mjs.map +0 -7
  227. package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs +0 -8
  228. package/dist/lib/neutral/skill-definition-3KLMUEC5.mjs.map +0 -7
  229. package/dist/lib/neutral/skills/index.mjs.map +0 -7
  230. package/dist/lib/neutral/sync-feed-SDXYF7HU.mjs +0 -99
  231. package/dist/lib/neutral/sync-feed-SDXYF7HU.mjs.map +0 -7
  232. package/dist/lib/neutral/translations.mjs +0 -81
  233. package/dist/lib/neutral/translations.mjs.map +0 -7
  234. package/dist/lib/neutral/types/index.mjs +0 -14
  235. package/dist/lib/neutral/types/index.mjs.map +0 -7
  236. package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -5
  237. package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
  238. package/dist/types/src/operations/curate-magazine.skill.test.d.ts +0 -2
  239. package/dist/types/src/operations/curate-magazine.skill.test.d.ts.map +0 -1
  240. package/src/capabilities/navigation-resolver.ts +0 -21
  241. package/src/operations/curate-magazine.skill.conversations.json +0 -1
  242. package/src/operations/curate-magazine.skill.test.ts +0 -167
@@ -1,624 +0,0 @@
1
- import {
2
- __export
3
- } from "./chunk-J5LGTIGS.mjs";
4
-
5
- // src/types/CreateSubscription.ts
6
- var CreateSubscription_exports = {};
7
- __export(CreateSubscription_exports, {
8
- HandleSchema: () => HandleSchema,
9
- RssCreateBase: () => RssCreateBase,
10
- StandardSiteCreateBase: () => StandardSiteCreateBase,
11
- isHandle: () => isHandle,
12
- isUrl: () => isUrl,
13
- makeSubscriptionFromCreate: () => makeSubscriptionFromCreate
14
- });
15
- import * as Schema2 from "effect/Schema";
16
- import { Format } from "@dxos/echo";
17
-
18
- // src/types/Subscription.ts
19
- var Subscription_exports = {};
20
- __export(Subscription_exports, {
21
- DEFAULT_KEEP: () => DEFAULT_KEEP,
22
- FeedType: () => FeedType,
23
- Post: () => Post,
24
- PostContent: () => PostContent,
25
- PostState: () => PostState,
26
- SYSTEM_TAGS: () => SYSTEM_TAGS,
27
- Subscription: () => Subscription,
28
- appendPostContent: () => appendPostContent,
29
- findPostContent: () => findPostContent,
30
- findSystemTagUri: () => findSystemTagUri,
31
- getPostSubscription: () => getPostSubscription,
32
- getReadAt: () => getReadAt,
33
- hasTag: () => hasTag,
34
- instanceOf: () => instanceOf,
35
- makePost: () => makePost,
36
- makeSubscription: () => makeSubscription,
37
- pickLatestPostContent: () => pickLatestPostContent,
38
- queryPostContentForPost: () => queryPostContentForPost,
39
- setReadAt: () => setReadAt,
40
- setTag: () => setTag
41
- });
42
- import * as Effect from "effect/Effect";
43
- import * as Schema from "effect/Schema";
44
- import { Annotation, Database, DXN, Feed, Filter, Obj, Query, Ref, Scope, Tag, Type } from "@dxos/echo";
45
- import { FormInputAnnotation, LabelAnnotation } from "@dxos/echo/Annotation";
46
- import { EffectEx } from "@dxos/effect";
47
- import { FactoryAnnotation, FeedAnnotation, StateMap, TagIndex } from "@dxos/schema";
48
- var FeedType = Schema.Literal("standard-site", "rss", "bluesky");
49
- var SYSTEM_TAGS = {
50
- starred: {
51
- key: {
52
- source: "org.dxos.plugin.magazine",
53
- id: "starred"
54
- },
55
- label: "Starred",
56
- hue: "amber"
57
- },
58
- archived: {
59
- key: {
60
- source: "org.dxos.plugin.magazine",
61
- id: "archived"
62
- },
63
- label: "Archived",
64
- hue: "neutral"
65
- }
66
- };
67
- var PostState = Schema.Struct({
68
- /** ISO 8601 timestamp when first opened. */
69
- readAt: Schema.optional(Schema.String)
70
- });
71
- var DEFAULT_KEEP = 10;
72
- var Subscription = class extends Type.makeObject(DXN.make("org.dxos.type.subscription.feed", "0.1.0"))(Schema.Struct({
73
- /** User-facing title of the feed. */
74
- name: Schema.String.pipe(Schema.optional),
75
- /** The URL of the RSS/Atom feed or AT Protocol handle/DID. */
76
- url: Schema.String.pipe(Schema.optional),
77
- /** Protocol type — determines which fetcher is used for sync. */
78
- type: FeedType.pipe(Schema.optional),
79
- /** Description of the feed. */
80
- description: Schema.String.pipe(Schema.optional),
81
- /** URL of the feed's associated website. */
82
- link: Schema.String.pipe(Schema.optional),
83
- /** URL of the feed's icon/image. */
84
- iconUrl: Schema.String.pipe(Schema.optional),
85
- /**
86
- * Maximum number of (non-starred) Posts retained in the feed's queue when syncing.
87
- * Older posts beyond this bound are dropped; starred posts are preserved regardless.
88
- * Defaults to {@link DEFAULT_KEEP} when unset.
89
- */
90
- keep: Schema.Number.pipe(Schema.annotations({
91
- title: "Keep",
92
- description: "Number of synced items."
93
- }), Schema.optional),
94
- /** Opaque sync cursor — protocol-specific. */
95
- cursor: Schema.String.pipe(FormInputAnnotation.set(false), Schema.optional),
96
- /** Backing ECHO feed (queue) for Posts: immutable feed entries appended by sync. */
97
- feed: Ref.Ref(Feed.Feed).pipe(FormInputAnnotation.set(false)),
98
- /**
99
- * Backing ECHO feed (queue) for fetched article bodies — one
100
- * {@link PostContent} entry per Post whose content has been loaded.
101
- *
102
- * Feeds (not the {@link postState} side map) are the right home for big
103
- * immutable payloads: they're append-only, lazily replicated, and don't
104
- * inflate the Subscription document. The side map keeps only the small
105
- * per-Post user state (read/archived/star/imageUrl).
106
- *
107
- * Optional for backwards compatibility with older Subscription documents
108
- * that pre-date this feed; new subscriptions always have one via
109
- * {@link makeSubscription}.
110
- */
111
- contentFeed: Ref.Ref(Feed.Feed).pipe(FormInputAnnotation.set(false), Schema.optional),
112
- /**
113
- * Per-Post mutable state keyed by Post id, shared across every Magazine that references the Post.
114
- * Posts live immutably in the `feed` queue; their `readAt` marker lives here. (`snippet`/`imageUrl`
115
- * are derived from the Post, or refined onto `contentFeed` entries — not stored here; star/archive
116
- * are tags — see `tags`.)
117
- */
118
- postState: Ref.Ref(StateMap.StateMap).pipe(FormInputAnnotation.set(false)),
119
- /**
120
- * Per-Post tags keyed by tag uri → Post ids. Boolean flags (starred, archived — see
121
- * {@link SYSTEM_TAGS}) are modelled as {@link Tag} objects so they
122
- * participate in the space-wide tag system. Stored as a child {@link TagIndex} object.
123
- */
124
- tags: Ref.Ref(TagIndex.TagIndex).pipe(FormInputAnnotation.set(false))
125
- }).pipe(LabelAnnotation.set([
126
- "name",
127
- "url"
128
- ]), Annotation.IconAnnotation.set({
129
- icon: "ph--rss--regular",
130
- hue: "indigo"
131
- }), FeedAnnotation.set(true), FactoryAnnotation.set((values) => makeSubscription(values)))) {
132
- };
133
- var instanceOf = (value) => Obj.instanceOf(Subscription, value);
134
- var makeSubscription = (props = {}) => {
135
- const postFeed = Feed.make();
136
- const contentFeed = Feed.make();
137
- const postState = StateMap.make();
138
- const tags = TagIndex.make();
139
- const subscription = Obj.make(Subscription, {
140
- feed: Ref.make(postFeed),
141
- contentFeed: Ref.make(contentFeed),
142
- postState: Ref.make(postState),
143
- tags: Ref.make(tags),
144
- ...props
145
- });
146
- Obj.setParent(postFeed, subscription);
147
- Obj.setParent(contentFeed, subscription);
148
- Obj.setParent(postState, subscription);
149
- Obj.setParent(tags, subscription);
150
- return subscription;
151
- };
152
- var Post = class extends Type.makeObject(DXN.make("org.dxos.type.subscription.post", "0.1.0"))(Schema.Struct({
153
- /** Source subscription feed; populated by `SyncSubscription` so curated posts can show provenance. */
154
- source: Ref.Ref(Subscription).pipe(FormInputAnnotation.set(false), Schema.optional),
155
- /** Post title. */
156
- title: Schema.String.pipe(Schema.optional),
157
- /** URL link to the original article. */
158
- link: Schema.String.pipe(Schema.optional),
159
- /** Plain-text or summary. */
160
- description: Schema.String.pipe(Schema.optional),
161
- /** Plain-text or HTML content. */
162
- content: Schema.String.pipe(Schema.optional),
163
- /** Author name. */
164
- author: Schema.String.pipe(Schema.optional),
165
- /** ISO 8601 publication date. */
166
- published: Schema.String.pipe(Schema.optional),
167
- /** Unique identifier (guid) from the feed. */
168
- guid: Schema.String.pipe(Schema.optional)
169
- }).pipe(LabelAnnotation.set([
170
- "title"
171
- ]), Annotation.IconAnnotation.set({
172
- icon: "ph--article--regular",
173
- hue: "orange"
174
- }))) {
175
- };
176
- var makePost = (props = {}) => Obj.make(Post, props);
177
- var PostContent = class extends Type.makeObject(DXN.make("org.dxos.type.subscription.postContent", "0.1.0"))(Schema.Struct({
178
- /** Source Post (in the Subscription's `feed` queue). */
179
- post: Ref.Ref(Post).pipe(FormInputAnnotation.set(false)),
180
- /** Extracted article body, in Markdown. */
181
- text: Schema.String,
182
- /** Refined snippet derived from the full article (preferred over the description-derived one). */
183
- snippet: Schema.optional(Schema.String),
184
- /** Refined hero image derived from the full article (preferred over the description-derived one). */
185
- imageUrl: Schema.optional(Schema.String),
186
- /** ISO 8601 timestamp when the content was fetched. */
187
- fetchedAt: Schema.String
188
- }).pipe(Annotation.HiddenAnnotation.set(true))) {
189
- };
190
- var getReadAt = (subscription, postId) => {
191
- const stateMap = subscription?.postState.target;
192
- return stateMap ? StateMap.bind(stateMap).get(postId).readAt : void 0;
193
- };
194
- var setReadAt = (subscription, postId, value) => {
195
- const stateMap = subscription.postState.target;
196
- if (stateMap) {
197
- StateMap.bind(stateMap).patch(postId, {
198
- readAt: value
199
- });
200
- }
201
- };
202
- var findSystemTagUri = async (db, which) => {
203
- const [currentTag] = await db.query(Filter.foreignKeys(Tag.Tag, [
204
- SYSTEM_TAGS[which].key
205
- ])).run();
206
- if (currentTag) {
207
- return Obj.getURI(currentTag).toString();
208
- }
209
- const legacyKey = {
210
- source: "org.dxos.plugin.feed",
211
- id: SYSTEM_TAGS[which].key.id
212
- };
213
- const [legacyTag] = await db.query(Filter.foreignKeys(Tag.Tag, [
214
- legacyKey
215
- ])).run();
216
- return legacyTag ? Obj.getURI(legacyTag).toString() : void 0;
217
- };
218
- var hasTag = (subscription, postId, tagUri) => {
219
- const tagIndex = subscription?.tags.target;
220
- return !!(tagIndex && tagUri) && TagIndex.bind(tagIndex).objects(tagUri).includes(postId);
221
- };
222
- var setTag = async (subscription, postId, db, which, value) => {
223
- const tag = await Tag.findOrCreate(db, SYSTEM_TAGS[which]);
224
- const uri = Obj.getURI(tag).toString();
225
- const tagIndex = subscription.tags.target;
226
- if (!tagIndex) {
227
- return;
228
- }
229
- const tags = TagIndex.bind(tagIndex);
230
- if (value) {
231
- tags.setTag(uri, postId);
232
- } else {
233
- tags.unsetTag(uri, postId);
234
- }
235
- };
236
- var getPostSubscription = (post) => post.source?.target;
237
- var queryPostContentForPost = (subscription, post) => {
238
- const postFeed = subscription.feed?.target;
239
- const contentFeed = subscription.contentFeed?.target;
240
- if (!postFeed || !contentFeed) {
241
- return void 0;
242
- }
243
- const postFeedUri = Obj.getURI(postFeed);
244
- const contentFeedUri = Obj.getURI(contentFeed);
245
- return Query.select(Filter.id(post.id)).referencedBy(PostContent, "post").from(Scope.feed(postFeedUri), Scope.feed(contentFeedUri));
246
- };
247
- var pickLatestPostContent = (entries) => {
248
- if (entries.length === 0) {
249
- return void 0;
250
- }
251
- return [
252
- ...entries
253
- ].sort((entryA, entryB) => entryB.fetchedAt.localeCompare(entryA.fetchedAt))[0];
254
- };
255
- var findPostContent = async (subscription, post) => {
256
- const db = Obj.getDatabase(subscription);
257
- const query = queryPostContentForPost(subscription, post);
258
- if (!db || !query) {
259
- return void 0;
260
- }
261
- return pickLatestPostContent(await db.query(query).run());
262
- };
263
- var ensureContentFeed = (subscription) => {
264
- const existing = subscription.contentFeed?.target;
265
- if (existing) {
266
- return existing;
267
- }
268
- const created = Feed.make();
269
- Obj.update(subscription, (subscription2) => {
270
- const mutable = subscription2;
271
- mutable.contentFeed = Ref.make(created);
272
- });
273
- Obj.setParent(created, subscription);
274
- return created;
275
- };
276
- var appendPostContent = async (space, subscription, entry) => {
277
- const echoFeed = ensureContentFeed(subscription);
278
- const content = Obj.make(PostContent, {
279
- post: Ref.fromURI(Obj.getURI(entry.post)),
280
- text: entry.text,
281
- ...entry.snippet ? {
282
- snippet: entry.snippet
283
- } : {},
284
- ...entry.imageUrl ? {
285
- imageUrl: entry.imageUrl
286
- } : {},
287
- fetchedAt: entry.fetchedAt ?? (/* @__PURE__ */ new Date()).toISOString()
288
- });
289
- await Feed.append(echoFeed, [
290
- content
291
- ]).pipe(Effect.provide(Database.layer(space.db)), EffectEx.runAndForwardErrors);
292
- };
293
-
294
- // src/types/CreateSubscription.ts
295
- var HandleSchema = Schema2.String.pipe(Schema2.pattern(/^@?([\da-z-]+\.)+[a-z]{2,}$|^did:[a-z]+:[a-zA-Z0-9._%:-]+$/i));
296
- var isHandle = Schema2.is(HandleSchema);
297
- var isUrl = Schema2.is(Format.URL);
298
- var StandardSiteCreateBase = Schema2.Struct({
299
- type: Schema2.Literal("standard-site"),
300
- handle: HandleSchema.annotations({
301
- title: "Handle",
302
- description: "atproto handle, e.g. dxos.org."
303
- }),
304
- // No `name`: the feed name is taken from the selected publication (resolved by `fetchStandardSite`).
305
- publication: Schema2.String.annotations({
306
- title: "Publication",
307
- description: "Choose a publication."
308
- })
309
- });
310
- var RssCreateBase = Schema2.Struct({
311
- type: Schema2.Literal("rss"),
312
- url: Format.URL.annotations({
313
- title: "URL",
314
- description: "RSS feed URL."
315
- }),
316
- name: Schema2.optional(Schema2.String.annotations({
317
- title: "Name"
318
- }))
319
- });
320
- var makeSubscriptionFromCreate = (input) => {
321
- switch (input.type) {
322
- case "standard-site":
323
- return makeSubscription({
324
- type: "standard-site",
325
- url: input.publication
326
- });
327
- case "rss":
328
- return makeSubscription({
329
- type: "rss",
330
- url: input.url,
331
- name: input.name
332
- });
333
- }
334
- };
335
-
336
- // src/types/FeedOperation.ts
337
- var FeedOperation_exports = {};
338
- __export(FeedOperation_exports, {
339
- ClearMagazine: () => ClearMagazine,
340
- CurateMagazine: () => CurateMagazine,
341
- FetchArticleContent: () => FetchArticleContent,
342
- LoadPostContent: () => LoadPostContent,
343
- SyncFeed: () => SyncFeed
344
- });
345
- import * as Schema4 from "effect/Schema";
346
- import { Operation } from "@dxos/compute";
347
- import { Database as Database2, DXN as DXN3, Ref as Ref3, Registry } from "@dxos/echo";
348
- import { meta } from "#meta";
349
-
350
- // src/types/Magazine.ts
351
- var Magazine_exports = {};
352
- __export(Magazine_exports, {
353
- CreateMagazineSchema: () => CreateMagazineSchema,
354
- CurationOutput: () => CurationOutput,
355
- DEFAULT_INSTRUCTIONS: () => DEFAULT_INSTRUCTIONS,
356
- Magazine: () => Magazine,
357
- PostState: () => PostState2,
358
- SKILL_KEY: () => SKILL_KEY,
359
- composeInstructions: () => composeInstructions,
360
- getPostState: () => getPostState,
361
- getRank: () => getRank,
362
- instanceOf: () => instanceOf2,
363
- make: () => make,
364
- patchPostState: () => patchPostState,
365
- setRank: () => setRank
366
- });
367
- import * as Schema3 from "effect/Schema";
368
- import { AppAnnotation } from "@dxos/app-toolkit";
369
- import { Instructions, Skill } from "@dxos/compute";
370
- import { Annotation as Annotation2, DXN as DXN2, Obj as Obj2, Ref as Ref2, Type as Type2 } from "@dxos/echo";
371
- import { FormInlineAnnotation, FormInputAnnotation as FormInputAnnotation2, LabelAnnotation as LabelAnnotation2 } from "@dxos/echo/Annotation";
372
- import { StateMap as StateMap2 } from "@dxos/schema";
373
- import { trim } from "@dxos/util";
374
- var SKILL_KEY = "org.dxos.skill.magazine";
375
- var DEFAULT_INSTRUCTIONS = trim`
376
- You curate articles for a Magazine around the Topic described below.
377
-
378
- Select only candidates that clearly match the Topic — quality over quantity.
379
-
380
- Never select duplicate articles. Two candidates are duplicates if they share a link or guid, or if
381
- their titles and content describe the same story (e.g. the same article syndicated by different
382
- feeds). Keep only one of each — prefer the most complete or authoritative source — and skip the rest.
383
-
384
- For each candidate you select, also produce:
385
- - A concise 1-2 sentence snippet (plain text, no markdown) capturing why the article is relevant to
386
- the Topic. If you read the full article, use it to write a richer snippet.
387
- - The best hero image URL for the article, when one is available.
388
- `;
389
- var PostState2 = Schema3.Struct({
390
- /** Agent-assigned relevance within this magazine (lower = more relevant). */
391
- rank: Schema3.optional(Schema3.Number),
392
- /** Agent-written concise snippet summarising the article in the context of this magazine's topic. */
393
- snippet: Schema3.optional(Schema3.String),
394
- /** Agent-selected hero image URL for this post in this magazine. */
395
- imageUrl: Schema3.optional(Schema3.String)
396
- });
397
- var CurationOutput = Schema3.Struct({
398
- posts: Schema3.Array(Schema3.Struct({
399
- id: Obj2.ID,
400
- /** Concise 1-2 sentence snippet summarising why this article is relevant to the magazine topic. */
401
- snippet: Schema3.optional(Schema3.String),
402
- /** Best image URL found for this article (from the post or fetched content). */
403
- imageUrl: Schema3.optional(Schema3.String)
404
- }))
405
- });
406
- var Magazine = class extends Type2.makeObject(DXN2.make("org.dxos.type.magazine", "0.2.0"))(Schema3.Struct({
407
- /** User-facing title of the magazine. */
408
- name: Schema3.String.pipe(Schema3.optional),
409
- /** Feeds to pull content from. */
410
- feeds: Schema3.Array(Ref2.Ref(Subscription)),
411
- /** Curated Post refs (insertion order; UI displays newest-last reversed). */
412
- posts: Schema3.Array(Ref2.Ref(Post)).pipe(FormInputAnnotation2.set(false)),
413
- /**
414
- * Curation Instructions, created with the magazine ({@link make}). Holds the editorial brief and
415
- * references the Magazine skill. Rendered inline by the properties form (the Instructions'
416
- * own fields), so the brief is edited there without a custom surface.
417
- * Optional for backward compatibility; {@link CurateMagazine} and the toolbar require it.
418
- */
419
- instructions: Ref2.Ref(Instructions.Instructions).pipe(FormInlineAnnotation.set(true), Schema3.optional),
420
- /**
421
- * Per-Post magazine-scoped curation state, keyed by Post id. Shared per-Post state (readAt,
422
- * star/archive tags) lives on `Subscription`; snippet/imageUrl here are agent-written at
423
- * curation time and take precedence over the RSS-derived defaults in display.
424
- */
425
- postState: Ref2.Ref(StateMap2.StateMap).pipe(FormInputAnnotation2.set(false)),
426
- /**
427
- * Maximum number of (non-starred) curated Posts retained on the magazine after curation.
428
- * Older posts beyond this bound are dropped; starred posts are preserved regardless.
429
- * Defaults to {@link Subscription.DEFAULT_KEEP} when unset.
430
- */
431
- keep: Schema3.Number.pipe(Schema3.annotations({
432
- title: "Keep",
433
- description: "Number of items to keep."
434
- }), Schema3.optional)
435
- }).pipe(LabelAnnotation2.set([
436
- "name"
437
- ]), Annotation2.IconAnnotation.set({
438
- icon: "ph--book-open-text--regular",
439
- hue: "indigo"
440
- }), AppAnnotation.SkillsAnnotation.set([
441
- SKILL_KEY
442
- ]))) {
443
- };
444
- var instanceOf2 = (value) => Obj2.instanceOf(Magazine, value);
445
- var make = (props = {}) => {
446
- const postState = StateMap2.make();
447
- const magazine = Obj2.make(Magazine, {
448
- name: props.name,
449
- feeds: props.feeds ?? [],
450
- posts: props.posts ?? [],
451
- keep: props.keep,
452
- postState: Ref2.make(postState)
453
- });
454
- const instructions = Instructions.make({
455
- name: props.name ? `${props.name} curation` : "Magazine curation",
456
- text: composeInstructions(props.instructions),
457
- skills: [
458
- Ref2.fromURI(Skill.registryURI(SKILL_KEY))
459
- ],
460
- // Bind the magazine as session context so the agent sees it, not only the candidate JSON input.
461
- objects: [
462
- Ref2.make(magazine)
463
- ],
464
- // Declare the selection contract so the agent's completeJob carries the chosen Posts.
465
- output: CurationOutput
466
- });
467
- Obj2.update(magazine, (magazine2) => {
468
- magazine2.instructions = Ref2.make(instructions);
469
- });
470
- Obj2.setParent(instructions, magazine);
471
- if (instructions.text.target) {
472
- Obj2.setParent(instructions.text.target, instructions);
473
- }
474
- Obj2.setParent(postState, magazine);
475
- return magazine;
476
- };
477
- var composeInstructions = (topic) => {
478
- const trimmed = topic?.trim();
479
- return trimmed ? `${DEFAULT_INSTRUCTIONS}
480
-
481
- ## Topic
482
-
483
- ${trimmed}` : DEFAULT_INSTRUCTIONS;
484
- };
485
- var CreateMagazineSchema = Schema3.Struct({
486
- name: Schema3.optional(Schema3.String.annotations({
487
- title: "Name"
488
- })),
489
- feeds: Schema3.Array(Ref2.Ref(Subscription)).annotations({
490
- title: "Feeds"
491
- }),
492
- instructions: Schema3.optional(Schema3.String.annotations({
493
- title: "Topic",
494
- description: "Describe what content to curate."
495
- }))
496
- });
497
- var getRank = (magazine, postId) => {
498
- const stateMap = magazine?.postState.target;
499
- return stateMap ? StateMap2.bind(stateMap).get(postId).rank : void 0;
500
- };
501
- var getPostState = (magazine, postId) => {
502
- const stateMap = magazine?.postState.target;
503
- return stateMap ? StateMap2.bind(stateMap).get(postId) : {};
504
- };
505
- var patchPostState = (magazine, postId, state) => {
506
- const stateMap = magazine.postState.target;
507
- if (stateMap) {
508
- StateMap2.bind(stateMap).patch(postId, state);
509
- }
510
- };
511
- var setRank = (magazine, postId, rank) => patchPostState(magazine, postId, {
512
- rank
513
- });
514
-
515
- // src/types/FeedOperation.ts
516
- var makeKey = (name) => DXN3.make(`${meta.profile.key}.operation.${name}`);
517
- var SyncFeed = Operation.make({
518
- meta: {
519
- key: makeKey("syncFeed"),
520
- name: "Sync Feed",
521
- description: "Fetches RSS/Atom feed and writes posts to the ECHO feed.",
522
- icon: "ph--arrows-clockwise--regular"
523
- },
524
- services: [
525
- Database2.Service
526
- ],
527
- input: Schema4.Struct({
528
- feed: Ref3.Ref(Subscription)
529
- }),
530
- output: Schema4.Void
531
- }).pipe(Operation.visible);
532
- var FetchArticleContent = Operation.make({
533
- meta: {
534
- key: makeKey("fetchArticleContent"),
535
- name: "Fetch Article Content",
536
- description: "Fetches and extracts text + image URLs from a Post's article page.",
537
- icon: "ph--article--regular"
538
- },
539
- input: Schema4.Struct({
540
- post: Ref3.Ref(Post).annotations({
541
- description: "The Post to fetch content for. The Post must have a link."
542
- })
543
- }),
544
- output: Schema4.Struct({
545
- text: Schema4.String.annotations({
546
- description: "Extracted plain text from the article page."
547
- }),
548
- imageUrls: Schema4.Array(Schema4.String).annotations({
549
- description: "Image URLs found on the page (og:image first, then <img> src values)."
550
- })
551
- }),
552
- services: [
553
- Database2.Service
554
- ]
555
- });
556
- var LoadPostContent = Operation.make({
557
- meta: {
558
- key: makeKey("loadPostContent"),
559
- name: "Load Post Content",
560
- description: "Fetches and stores the full article content on a Post.",
561
- icon: "ph--download--regular"
562
- },
563
- input: Schema4.Struct({
564
- post: Ref3.Ref(Post).annotations({
565
- description: "The Post to load content for."
566
- }),
567
- force: Schema4.optional(Schema4.Boolean.annotations({
568
- description: "Re-fetch and append fresh content even if an entry already exists (refresh)."
569
- }))
570
- }),
571
- output: Schema4.Void
572
- });
573
- var CurateMagazine = Operation.make({
574
- meta: {
575
- key: makeKey("curateMagazine"),
576
- name: "Curate Magazine",
577
- description: "Syncs feeds, selects matching posts via the magazine skill, and applies per-feed keep limits.",
578
- icon: "ph--sparkle--regular"
579
- },
580
- input: Schema4.Struct({
581
- magazine: Ref3.Ref(Magazine).annotations({
582
- description: "The Magazine to curate."
583
- })
584
- }),
585
- output: Schema4.Struct({
586
- synced: Schema4.Number.annotations({
587
- description: "Number of feeds successfully synced."
588
- }),
589
- curated: Schema4.Number.annotations({
590
- description: "Number of posts added to the magazine."
591
- })
592
- }),
593
- // Database.Service for candidate collection, Registry.Service to resolve the methodology skill;
594
- // sub-operations (SyncFeed, RunInstructions) resolve through the ambient Operation.Service invoker.
595
- services: [
596
- Database2.Service,
597
- Registry.Service
598
- ]
599
- }).pipe(Operation.visible);
600
- var ClearMagazine = Operation.make({
601
- meta: {
602
- key: makeKey("clearMagazine"),
603
- name: "Clear Magazine",
604
- description: "Removes a Magazine's posts, keeping any that are starred.",
605
- icon: "ph--trash--regular"
606
- },
607
- input: Schema4.Struct({
608
- magazine: Ref3.Ref(Magazine).annotations({
609
- description: "The Magazine to clear."
610
- })
611
- }),
612
- output: Schema4.Void,
613
- services: [
614
- Database2.Service
615
- ]
616
- }).pipe(Operation.visible);
617
-
618
- export {
619
- Subscription_exports,
620
- CreateSubscription_exports,
621
- Magazine_exports,
622
- FeedOperation_exports
623
- };
624
- //# sourceMappingURL=chunk-OYCDRSWB.mjs.map