@anthusai/papyrus 5.1.0 → 5.2.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 (35) hide show
  1. package/amplify/data/schema.js +2 -0
  2. package/amplify/data/schema.ts +2 -0
  3. package/amplify/functions/monitoring-view/handler.py +11 -0
  4. package/amplify/functions/monitoring-view/resource.js +24 -0
  5. package/amplify/functions/monitoring-view/resource.ts +34 -0
  6. package/amplify/functions/monitoring-view/schema.js +16 -0
  7. package/amplify/functions/monitoring-view/schema.ts +18 -0
  8. package/amplify/functions/monitoring-view/wire.js +37 -0
  9. package/amplify/functions/monitoring-view/wire.ts +47 -0
  10. package/amplify/publication/redirect-and-index.js +49 -0
  11. package/amplify/publication/redirect-rules.js +26 -10
  12. package/amplify/publication/redirect-rules.ts +36 -10
  13. package/amplify/publication/s3-projection.js +4 -2
  14. package/amplify/publication/s3-projection.ts +4 -2
  15. package/amplify/site-backend.js +4 -0
  16. package/amplify/site-backend.ts +4 -0
  17. package/components/monitoring-overview-view.tsx +240 -0
  18. package/components/monitoring-panel.tsx +40 -0
  19. package/components/newsroom-organizer.css +17 -0
  20. package/components/newsroom-references-view.tsx +14 -14
  21. package/components/publication-cyclotron-panel.tsx +10 -10
  22. package/components/reference-add-entry.tsx +75 -0
  23. package/components/reference-curation-controls.tsx +30 -21
  24. package/components/reference-cyclotron-priming.tsx +4 -4
  25. package/components/reference-cyclotron-suggestion.tsx +1 -1
  26. package/components/reference-priming.tsx +14 -10
  27. package/components/reference-section-suggestion.tsx +1 -1
  28. package/components/topic-steering-workspace.tsx +13 -2
  29. package/lib/category-repository.ts +1 -1
  30. package/lib/monitoring-client.ts +29 -0
  31. package/lib/monitoring-overview-fixture.ts +51 -0
  32. package/lib/monitoring-overview.ts +144 -0
  33. package/lib/relevance-status.ts +2 -2
  34. package/package.json +8 -2
  35. package/routes.manifest.json +1 -1
@@ -60,7 +60,7 @@ export function ReferenceSuggestionBlock({
60
60
  <section aria-label="Suggestion" className="space-y-2 border-y border-foreground py-3" data-reference-suggestion={referenceLineageId}>
61
61
  <h3 className="text-xs font-semibold uppercase tracking-wide text-foreground">Suggestion</h3>
62
62
  <p className="text-sm text-foreground">
63
- The cyclotron suggests <span className="font-semibold">{decision.label}</span> ({suggestionConfidenceWords(decision)}).
63
+ Papyrus suggests <span className="font-semibold">{decision.label}</span> ({suggestionConfidenceWords(decision)}).
64
64
  </p>
65
65
  <p className="text-xs text-foreground" data-reference-suggestion-notice>
66
66
  A suggestion never changes the status until an editor acts. This reference is {statusLabel.toLowerCase()}.
@@ -1,18 +1,22 @@
1
1
  "use client";
2
2
 
3
- import { useState } from "react";
4
3
  import { PrimingPanel, type PrimingPanelProps } from "cyclotron/components/priming-panel";
5
- import { Button } from "./ui/button";
6
4
 
7
- /** Papyrus supplies its transport/configuration; Cyclotron owns preview and labels. */
5
+ /**
6
+ * The "Import a file" option of the Add a reference area. Papyrus supplies the
7
+ * transport and configuration; Cyclotron owns the preview and label controls.
8
+ * It is only rendered by `ReferenceAddEntry`, never as a section of its own.
9
+ */
8
10
  export function ReferencePriming(props: PrimingPanelProps) {
9
- const [open, setOpen] = useState(false);
10
11
  return (
11
- <section className="shrink-0 space-y-3" aria-label="Representative reference examples">
12
- <Button aria-expanded={open} onClick={() => setOpen((value) => !value)} variant="outline">
13
- {open ? "Hide example references" : "Add example references (optional)"}
14
- </Button>
15
- {open ? <div className="max-h-[55dvh] space-y-3 overflow-y-auto pr-1"><p className="text-sm text-muted-foreground">Corrections to extracted content: describe what needs fixing, then enter the corrected title and abstract or summary. The note is saved with your correction; it does not automatically regenerate the content. Choose Publish / Not publish separately. An explanation of that judgment is optional.</p><PrimingPanel {...props} renderItem={props.renderItem ?? ((item) => <div className="space-y-2"><p className="whitespace-pre-wrap text-sm">{String(item.values.abstract ?? item.values.text ?? "")}</p><p className="break-all text-xs text-muted-foreground">{String(item.values.source_uri ?? "")}</p></div>)} /></div> : null}
16
- </section>
12
+ <PrimingPanel
13
+ {...props}
14
+ renderItem={props.renderItem ?? ((item) => (
15
+ <div className="space-y-2">
16
+ <p className="whitespace-pre-wrap text-sm">{String(item.values.abstract ?? item.values.text ?? "")}</p>
17
+ <p className="break-all text-xs text-muted-foreground">{String(item.values.source_uri ?? "")}</p>
18
+ </div>
19
+ ))}
20
+ />
17
21
  );
18
22
  }
@@ -40,7 +40,7 @@ export function SectionSuggestionBlock({
40
40
  <section aria-label="Suggested Section" className="space-y-2 border-y border-foreground py-3" data-reference-section-suggestion={referenceLineageId}>
41
41
  <h3 className="text-xs font-semibold uppercase tracking-wide text-foreground">Suggested Section</h3>
42
42
  <p className="text-sm text-foreground">
43
- The cyclotron suggests <span className="font-semibold">{titleOf(sections, suggestion.sectionId)}</span>
43
+ Papyrus suggests <span className="font-semibold">{titleOf(sections, suggestion.sectionId)}</span>
44
44
  {suggestion.confidence !== null ? ` (${formatPercentage(suggestion.confidence)})` : ""}.
45
45
  </p>
46
46
  {others.length ? (
@@ -14,6 +14,7 @@ import type { ReactNode, RefObject } from "react";
14
14
  import { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useTransition } from "react";
15
15
  import amplifyOutputs from "papyrus-amplify-outputs";
16
16
  import { EditorialChecksAdminPanel } from "./editorial-checks-admin-panel";
17
+ import { MonitoringPanel } from "./monitoring-panel";
17
18
  import { SignupEntriesPanel } from "./signup-entries-panel";
18
19
  import { pluginSettings, type PluginOutputs } from "../lib/plugin-settings";
19
20
  import { generateClient } from "aws-amplify/data";
@@ -247,7 +248,7 @@ type AssignmentAction = "claim" | "release" | "complete" | "cancel" | "reopen" |
247
248
  type ReportingPacketReviewDecision = "select" | "merge" | "brief" | "hold" | "kill";
248
249
  type AssignmentDeskViewMode = "queue" | "budget";
249
250
  type UserRoleAction = "grant" | "revoke";
250
- type AdministrationPanel = "users" | "policies" | "sections" | "procedures" | "delegations" | "signups" | "editorial-checks";
251
+ type AdministrationPanel = "users" | "policies" | "sections" | "procedures" | "delegations" | "signups" | "editorial-checks" | "monitoring";
251
252
  export type NewsDeskTab = "overview" | "desks" | "topics" | "concepts" | "references" | "messages" | "assignments" | "administration" | "search";
252
253
  type LexicalRuleScope = "publication" | "corpus" | "classifier" | "category";
253
254
  type AnalysisReindexMode = "online-update" | "classifier-retrain" | "scoped-topic-rebuild" | "entity-graph-rebuild" | "generated-analysis-rebuild";
@@ -4327,6 +4328,15 @@ function AdministrationDeskView({
4327
4328
  <strong>Editorial checks</strong>
4328
4329
  <span>Policies the article editor checks drafts against</span>
4329
4330
  </Link>
4331
+ <Link
4332
+ href={administrationPanelHref("monitoring", isDemo)}
4333
+ data-news-desk-admin-nav="monitoring"
4334
+ data-active={administrationPanel === "monitoring" || undefined}
4335
+ onClick={() => onPanelChange("monitoring")}
4336
+ >
4337
+ <strong>Monitoring</strong>
4338
+ <span>The automated research pipeline, read only</span>
4339
+ </Link>
4330
4340
  {signupPluginEnabled() ? (
4331
4341
  <Link
4332
4342
  href={administrationPanelHref("signups", isDemo)}
@@ -4342,6 +4352,7 @@ function AdministrationDeskView({
4342
4352
  <div className="news-desk-settings-panel">
4343
4353
  {administrationPanel === "signups" ? <SignupEntriesPanel /> : null}
4344
4354
  {administrationPanel === "editorial-checks" ? <EditorialChecksAdminPanel /> : null}
4355
+ {administrationPanel === "monitoring" ? <MonitoringPanel isAdmin={canManageUsers} isDemo={isDemo} /> : null}
4345
4356
  {administrationPanel === "delegations" ? <AdministrationDelegationsPanel disabled={disabled} /> : null}
4346
4357
  {administrationPanel === "users" ? (
4347
4358
  <AdministrationUsersPanel
@@ -12806,7 +12817,7 @@ function signupPluginEnabled(): boolean {
12806
12817
  }
12807
12818
 
12808
12819
  function normalizeAdministrationPanel(value: string | null | undefined): AdministrationPanel {
12809
- if (value === "policies" || value === "sections" || value === "procedures" || value === "delegations" || value === "editorial-checks") return value;
12820
+ if (value === "policies" || value === "sections" || value === "procedures" || value === "delegations" || value === "editorial-checks" || value === "monitoring") return value;
12810
12821
  if (value === "signups" && signupPluginEnabled()) return value;
12811
12822
  return "users";
12812
12823
  }
@@ -1700,7 +1700,7 @@ export function createDemoCategorySteeringDashboard(
1700
1700
  question: "Should this candidate source become a reference for this publication?",
1701
1701
  reviewControl: "thumbs",
1702
1702
  reviewReason: "program",
1703
- reviewDetail: "Every decision is reviewed while the cyclotron is onboarding.",
1703
+ reviewDetail: "Every suggestion is reviewed while suggestions are getting started.",
1704
1704
  version: 1,
1705
1705
  }),
1706
1706
  },
@@ -0,0 +1,29 @@
1
+ "use client";
2
+
3
+ import { generateClient } from "aws-amplify/data";
4
+ import type { MonitoringResult } from "./monitoring-overview";
5
+
6
+ type GraphQLResult = { data?: { monitoringOverview?: unknown }; errors?: { message?: string; errorType?: string }[] };
7
+
8
+ /**
9
+ * Reads the monitoring overview through the site's own authenticated API (user pool, editor or admin).
10
+ * The browser holds no table name, key or secret: the function behind the query does the read.
11
+ */
12
+ export async function loadMonitoringOverview(scope: "publication" | "all"): Promise<MonitoringResult> {
13
+ const client = generateClient({ authMode: "userPool" });
14
+ let result: GraphQLResult;
15
+ try {
16
+ result = (await client.graphql({
17
+ query: `query MonitoringOverview($scope: String) { monitoringOverview(scope: $scope) }`,
18
+ variables: { scope },
19
+ })) as GraphQLResult;
20
+ } catch (error) {
21
+ // Amplify throws the response when AppSync returns errors.
22
+ result = (error && typeof error === "object" && "errors" in error ? error : { errors: [{ message: "failed" }] }) as GraphQLResult;
23
+ }
24
+ const refused = result.errors?.some((entry) => /unauthorized|not authorized|forbidden/i.test(`${entry.errorType ?? ""} ${entry.message ?? ""}`));
25
+ if (refused) return { error: "forbidden" };
26
+ if (result.errors?.length || result.data?.monitoringOverview === undefined || result.data.monitoringOverview === null) return { state: "unavailable" };
27
+ const raw = result.data.monitoringOverview;
28
+ return (typeof raw === "string" ? JSON.parse(raw) : raw) as MonitoringResult;
29
+ }
@@ -0,0 +1,51 @@
1
+ import type { MonitoringOverview } from "./monitoring-overview";
2
+
3
+ /** A realistic overview for tests and the `?demo=1` newsroom. Public Hacker News titles only. */
4
+ export const FIXTURE_MONITORING_OVERVIEW: MonitoringOverview = {
5
+ state: "ready",
6
+ asOf: "2026-10-21T02:40:00Z",
7
+ scope: { mode: "publication", publicationId: "desk-a", site: "a.example.test", canViewAll: true },
8
+ feeds: [{ id: "hn", sourceUrl: "https://news.ycombinator.com/rss", intervalSeconds: 900, limit: 30, enabled: true,
9
+ lastStatus: "complete", lastFinishedAt: "2026-10-21T02:33:00Z", nextDueAt: "2026-10-21T02:50:00Z" }],
10
+ runs: [
11
+ { runId: "r3", startedAt: "2026-10-21T02:33:00.000000Z", status: "complete", new: 2, revised: 1, unchanged: 27, itemCount: 30, errorCount: 0, errors: [] },
12
+ { runId: "r1", startedAt: "2026-10-21T02:18:00.000000Z", status: "complete", new: 0, revised: 0, unchanged: 30, itemCount: 30, errorCount: 0, errors: [] },
13
+ { runId: "r0", startedAt: "2026-10-21T02:03:00.000000Z", status: "partial", new: 1, revised: 0, unchanged: 28, itemCount: 30, errorCount: 1, errors: ["ConnectionError: timeout"] },
14
+ ],
15
+ routerRuns: [{ runId: "q2", startedAt: "2026-10-21T02:37:00.000000Z", mode: "live", status: "stopped", stoppedBy: "request_ceiling_reached",
16
+ counts: { examined: 3, decided: 1, delivered: 1, deliveryFailed: 1, routed: 1 }, errorCount: 0 }],
17
+ router: { mode: "live", feedback: true, enabled: true, maxItemsPerRun: 5 },
18
+ usage: { day: "2026-10-21", decisionsToday: 2, decisionsTotal: 3, ceilings: { decisionsTotal: 300, decisionsPerDay: 100, items: 300 } },
19
+ hiddenNotRelevant: 1,
20
+ items: [
21
+ { sourceId: "104", revision: 1, title: "Fresh Show HN", url: "https://example.org/104", discussionUrl: "https://news.ycombinator.com/item?id=104",
22
+ observedAt: "2026-10-21T02:30:00.000000Z", routing: "collected", routingNote: null, decidedAt: null,
23
+ relevance: [{ publicationId: "desk-a", site: "a.example.test", relevant: null, label: null, confidence: null, delivery: { state: null } }] },
24
+ { sourceId: "105", revision: 1, title: "Broken request", url: "https://example.org/105", discussionUrl: "https://news.ycombinator.com/item?id=105",
25
+ observedAt: "2026-10-21T01:30:00.000000Z", routing: "error", routingNote: "invalid request: bad title", decidedAt: null,
26
+ relevance: [{ publicationId: "desk-a", site: "a.example.test", relevant: null, label: null, confidence: null, delivery: { state: null } }] },
27
+ { sourceId: "101", revision: 1, title: "Quantum paper on arXiv", url: "https://example.org/101", discussionUrl: "https://news.ycombinator.com/item?id=101",
28
+ observedAt: "2026-10-21T00:10:00.000000Z", routing: "routed", routingNote: null, decidedAt: "2026-10-21T01:00:00Z",
29
+ relevance: [{ publicationId: "desk-a", site: "a.example.test", relevant: true, label: "include", confidence: 0.91,
30
+ delivery: { state: "delivered", referenceId: "ref-1", referenceLineageId: "lin-1", deliveredAt: "2026-10-21T01:00:05Z" } }] },
31
+ { sourceId: "103", revision: 1, title: "Phishing kit leaks", url: "https://example.org/103", discussionUrl: "https://news.ycombinator.com/item?id=103",
32
+ observedAt: "2026-10-20T23:00:00.000000Z", routing: "decided", routingNote: null, decidedAt: "2026-10-20T23:10:00Z",
33
+ relevance: [{ publicationId: "desk-a", site: "a.example.test", relevant: true, label: "include", confidence: 0.7,
34
+ delivery: { state: "failed", error: "ClientError: throttled", attempts: 2 } }] },
35
+ ],
36
+ };
37
+
38
+ export const FIXTURE_ALL_PIPELINE_OVERVIEW: MonitoringOverview = {
39
+ ...FIXTURE_MONITORING_OVERVIEW,
40
+ scope: { mode: "all", publicationId: "desk-a", site: "a.example.test", canViewAll: true },
41
+ hiddenNotRelevant: 0,
42
+ items: FIXTURE_MONITORING_OVERVIEW.items.map((item) => item.sourceId !== "101" ? item : {
43
+ ...item,
44
+ relevance: [
45
+ ...item.relevance,
46
+ { publicationId: "desk-b", site: "b.example.test", relevant: false, label: "exclude", confidence: 0.8, delivery: { state: "not_applicable" } },
47
+ { publicationId: "desk-c", site: "desk-c", relevant: true, label: "include", confidence: null,
48
+ delivery: { state: "delivered", referenceId: "ref-2", referenceLineageId: "lin-2" } },
49
+ ],
50
+ }),
51
+ };
@@ -0,0 +1,144 @@
1
+ /** Shapes and wording for the newsroom Monitoring page. The function in src/papyrus_content/monitoring_view.py produces them. */
2
+ import { getNewsroomNavHref } from "./newsroom-nav";
3
+
4
+ export type MonitoringDeliveryState = "delivered" | "failed" | "pending" | "not_applicable" | null;
5
+
6
+ export type MonitoringRelevance = {
7
+ publicationId: string;
8
+ site: string | null;
9
+ relevant: boolean | null;
10
+ label: string | null;
11
+ confidence: number | null;
12
+ delivery: {
13
+ state: MonitoringDeliveryState;
14
+ referenceId?: string | null;
15
+ referenceLineageId?: string | null;
16
+ deliveredAt?: string | null;
17
+ error?: string | null;
18
+ attempts?: number | null;
19
+ };
20
+ };
21
+
22
+ export type MonitoringItem = {
23
+ sourceId: string;
24
+ revision: number;
25
+ title: string;
26
+ url: string | null;
27
+ discussionUrl: string | null;
28
+ observedAt: string | null;
29
+ routing: string;
30
+ routingNote: string | null;
31
+ decidedAt: string | null;
32
+ relevance: MonitoringRelevance[];
33
+ };
34
+
35
+ export type MonitoringRun = {
36
+ runId: string;
37
+ startedAt: string;
38
+ status: string;
39
+ new: number;
40
+ revised: number;
41
+ unchanged: number;
42
+ itemCount: number | null;
43
+ errorCount: number;
44
+ errors: (string | null)[];
45
+ };
46
+
47
+ export type MonitoringRouterRun = {
48
+ runId: string;
49
+ startedAt: string;
50
+ mode: string;
51
+ status: string;
52
+ stoppedBy: string | null;
53
+ counts: Record<string, number>;
54
+ errorCount: number;
55
+ };
56
+
57
+ export type MonitoringFeed = {
58
+ id: string;
59
+ sourceUrl: string | null;
60
+ intervalSeconds: number | null;
61
+ limit: number | null;
62
+ enabled: boolean;
63
+ lastStatus: string | null;
64
+ lastFinishedAt: string | null;
65
+ nextDueAt: string | null;
66
+ };
67
+
68
+ export type MonitoringOverview = {
69
+ state: "ready" | "empty";
70
+ asOf: string;
71
+ notice?: "publication_not_routed";
72
+ scope: { mode: "publication" | "all"; publicationId: string | null; site: string | null; canViewAll: boolean };
73
+ feeds: MonitoringFeed[];
74
+ runs: MonitoringRun[];
75
+ routerRuns: MonitoringRouterRun[];
76
+ router: { mode: string; feedback: boolean; enabled: boolean; maxItemsPerRun: number | null } | null;
77
+ usage: {
78
+ day: string;
79
+ decisionsToday: number;
80
+ decisionsTotal: number;
81
+ ceilings: { decisionsTotal?: number; decisionsPerDay?: number; items?: number } | null;
82
+ } | null;
83
+ items: MonitoringItem[];
84
+ hiddenNotRelevant: number;
85
+ };
86
+
87
+ export type MonitoringResult =
88
+ | MonitoringOverview
89
+ | { state: "not_configured" }
90
+ | { state: "unavailable" }
91
+ | { error: "forbidden" | "bad_request" };
92
+
93
+ const ROUTING_WORDS: Record<string, string> = {
94
+ collected: "Collected, waiting for the router",
95
+ "dry-run-validated": "Checked in a dry run, not sent",
96
+ decided: "Judged, delivery not finished",
97
+ routed: "Routed",
98
+ refused: "Refused by the shared Cyclotron",
99
+ uncertain: "Uncertain, needs a person",
100
+ error: "Error",
101
+ };
102
+
103
+ export function routingLabel(routing: string): string {
104
+ return ROUTING_WORDS[routing] ?? routing;
105
+ }
106
+
107
+ /** Fixed-format UTC time so the page reads the same everywhere. */
108
+ export function formatUtc(iso: string | null | undefined): string {
109
+ if (!iso) return "never";
110
+ const match = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2})/.exec(iso);
111
+ return match ? `${match[1]} ${match[2]} UTC` : iso;
112
+ }
113
+
114
+ export function confidenceText(confidence: number | null): string {
115
+ return confidence === null ? "confidence not reported" : `${Math.round(confidence * 100)}% confidence`;
116
+ }
117
+
118
+ export function usageText(used: number, ceiling: number | undefined): string {
119
+ return ceiling === undefined ? `${used} used, no ceiling set` : `${used} of ${ceiling}`;
120
+ }
121
+
122
+ export function everyText(seconds: number | null): string {
123
+ if (!seconds) return "on a schedule";
124
+ return seconds % 3600 === 0 ? `every ${seconds / 3600} h` : seconds % 60 === 0 ? `every ${seconds / 60} min` : `every ${seconds} s`;
125
+ }
126
+
127
+ export function referenceHref(lineageId: string, demo?: boolean): string {
128
+ return getNewsroomNavHref(`/newsroom/references/${encodeURIComponent(lineageId)}`, demo);
129
+ }
130
+
131
+ export function describeRelevance(entry: MonitoringRelevance): string {
132
+ if (entry.relevant === null) return "Not judged yet";
133
+ return entry.relevant ? "Relevant" : "Not relevant";
134
+ }
135
+
136
+ export function describeDelivery(entry: MonitoringRelevance): string {
137
+ switch (entry.delivery.state) {
138
+ case "delivered": return "In the References queue";
139
+ case "failed": return "Not in the References queue: delivery failed";
140
+ case "pending": return "Not in the References queue yet";
141
+ case "not_applicable": return "Nothing to deliver";
142
+ default: return "";
143
+ }
144
+ }
@@ -52,10 +52,10 @@ export const DEMO_CYCLOTRON_STATUS: CyclotronStatus = {
52
52
  },
53
53
  calibration: { saysSure: null, isRight: null, gapPoints: null, curve: [] },
54
54
  reviewRate: {
55
- state: "onboarding", rate: 1, reason: "Onboarding: every decision is reviewed until the cyclotron earns a lower rate.",
55
+ state: "onboarding", rate: 1, reason: "Getting started: every suggestion is reviewed until suggestions earn a lower review rate.",
56
56
  auditFloor: 0.05, confidenceThreshold: 0.7, override: null,
57
57
  nextCheckAfterDecisions: 99,
58
- nextStep: "Steps down to 50% after 2 more windows of 100 decisions with accuracy on confident decisions of at least 85% (at least 20 reviewed) and a calibration gap under 5 points. Next check in 99 decisions.",
58
+ nextStep: "Steps down to 50% after 2 more windows of 100 decisions with accuracy on confident decisions of at least 85% (at least 20 reviewed) and a gap under 5 points between how sure suggestions say they are and how often they are right. Next check in 99 decisions.",
59
59
  expectedReviewsPerWeek: 1,
60
60
  },
61
61
  lastChange: null,
package/package.json CHANGED
@@ -85,6 +85,8 @@
85
85
  "./components/item-stream-view": "./components/item-stream-view.tsx",
86
86
  "./components/markus-body-editor": "./components/markus-body-editor.tsx",
87
87
  "./components/markus-ir-preview": "./components/markus-ir-preview.tsx",
88
+ "./components/monitoring-overview-view": "./components/monitoring-overview-view.tsx",
89
+ "./components/monitoring-panel": "./components/monitoring-panel.tsx",
88
90
  "./components/news-desk-client-provider": "./components/news-desk-client-provider.tsx",
89
91
  "./components/news-desk-page": "./components/news-desk-page.tsx",
90
92
  "./components/news-desk-taxonomy-client": "./components/news-desk-taxonomy-client.ts",
@@ -118,6 +120,7 @@
118
120
  "./components/reader-auth-state": "./components/reader-auth-state.ts",
119
121
  "./components/reader-settings": "./components/reader-settings.ts",
120
122
  "./components/reader-theme-control": "./components/reader-theme-control.tsx",
123
+ "./components/reference-add-entry": "./components/reference-add-entry.tsx",
121
124
  "./components/reference-curation-controls": "./components/reference-curation-controls.tsx",
122
125
  "./components/reference-cyclotron-priming": "./components/reference-cyclotron-priming.tsx",
123
126
  "./components/reference-cyclotron-status": "./components/reference-cyclotron-status.tsx",
@@ -224,6 +227,9 @@
224
227
  "./lib/markus-projection": "./lib/markus-projection.ts",
225
228
  "./lib/markus-to-article": "./lib/markus-to-article.ts",
226
229
  "./lib/media-route-response": "./lib/media-route-response.ts",
230
+ "./lib/monitoring-client": "./lib/monitoring-client.ts",
231
+ "./lib/monitoring-overview-fixture": "./lib/monitoring-overview-fixture.ts",
232
+ "./lib/monitoring-overview": "./lib/monitoring-overview.ts",
227
233
  "./lib/news-desk-session": "./lib/news-desk-session.ts",
228
234
  "./lib/newspaper-layout": "./lib/newspaper-layout.ts",
229
235
  "./lib/newsroom-articles": "./lib/newsroom-articles.ts",
@@ -395,7 +401,7 @@
395
401
  "optional": true
396
402
  }
397
403
  },
398
- "version": "5.1.0",
404
+ "version": "5.2.0",
399
405
  "dependencies": {
400
406
  "@aws-amplify/adapter-nextjs": "^1.7.3",
401
407
  "@aws-crypto/sha256-js": "5.2.0",
@@ -435,7 +441,7 @@
435
441
  "class-variance-authority": "^0.7.1",
436
442
  "clsx": "^2.1.1",
437
443
  "cmdk": "^1.1.1",
438
- "cyclotron": "https://github.com/AnthusAI/Cyclotron/releases/download/ui-v0.2.2/cyclotron-0.2.2.tgz",
444
+ "cyclotron": "https://github.com/AnthusAI/Cyclotron/releases/download/ui-v0.2.3/cyclotron-0.2.3.tgz",
439
445
  "d3": "^7.9.0",
440
446
  "esbuild": "^0.28.2",
441
447
  "framer-motion": "^14.3.0",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.1.0",
2
+ "version": "5.2.0",
3
3
  "routes": [
4
4
  {
5
5
  "file": "app/%5F_preview/[[...path]]/route.ts",