@anthusai/papyrus 5.43.0-next.45 → 5.43.0-next.47
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.
- package/amplify/data/resource.js +19 -1
- package/amplify/data/resource.ts +19 -1
- package/amplify/data/schema.js +19 -1
- package/amplify/data/schema.ts +19 -1
- package/amplify/functions/category-action/handler.ts +19 -0
- package/lib/reference-feed-keys.ts +69 -0
- package/package.json +2 -1
- package/routes.manifest.json +1 -1
package/amplify/data/resource.js
CHANGED
|
@@ -1571,6 +1571,15 @@ const schema = a.schema({
|
|
|
1571
1571
|
curationStatusReason: a.string(),
|
|
1572
1572
|
newsroomFeedKey: a.string(),
|
|
1573
1573
|
reviewedFeedKey: a.string(),
|
|
1574
|
+
// The References page reads the feed through two indexes (docs/reference-feed-indexes.md). `feedStateKey` is
|
|
1575
|
+
// "<corpusId>#unrated" or "<corpusId>#rated" for a current, not archived Reference (null otherwise: it is in no feed).
|
|
1576
|
+
// `predictionSortKey` orders Best bets, `feedArrivalAt` orders Newest. The prediction is the Cyclotron's ORIGINAL
|
|
1577
|
+
// P(accept), written once, and never rewritten by a vote.
|
|
1578
|
+
feedStateKey: a.string(),
|
|
1579
|
+
feedArrivalAt: a.datetime(),
|
|
1580
|
+
predictedAcceptProbability: a.float(),
|
|
1581
|
+
predictionDecidedAt: a.datetime(),
|
|
1582
|
+
predictionSortKey: a.string(),
|
|
1574
1583
|
updatedAt: a.datetime(),
|
|
1575
1584
|
})
|
|
1576
1585
|
.secondaryIndexes((index) => [
|
|
@@ -1583,6 +1592,8 @@ const schema = a.schema({
|
|
|
1583
1592
|
index("curationStatus").sortKeys(["curationStatusUpdatedAt"]).queryField("listReferencesByCurationStatusAndUpdatedAt"),
|
|
1584
1593
|
index("curationStatusKey").sortKeys(["curationStatusUpdatedAt"]).queryField("listReferencesByCurationStatusKeyAndUpdatedAt"),
|
|
1585
1594
|
index("reviewedFeedKey").sortKeys(["updatedAt"]).queryField("listReferencesByReviewedFeedAndUpdatedAt"),
|
|
1595
|
+
index("feedStateKey").sortKeys(["predictionSortKey"]).queryField("listReferencesByFeedStateAndPrediction"),
|
|
1596
|
+
index("feedStateKey").sortKeys(["feedArrivalAt"]).queryField("listReferencesByFeedStateAndArrival"),
|
|
1586
1597
|
])
|
|
1587
1598
|
.authorization((allow) => [
|
|
1588
1599
|
allow.groups(categoryWriteGroups).to(["read"]),
|
|
@@ -1670,6 +1681,9 @@ const schema = a.schema({
|
|
|
1670
1681
|
authorSub: a.string(),
|
|
1671
1682
|
authorUserProfileId: a.id(),
|
|
1672
1683
|
authorLabel: a.string(),
|
|
1684
|
+
editedAt: a.datetime(),
|
|
1685
|
+
deletedAt: a.datetime(),
|
|
1686
|
+
deletedBySub: a.string(),
|
|
1673
1687
|
threadId: a.id(),
|
|
1674
1688
|
parentMessageId: a.id(),
|
|
1675
1689
|
sequenceNumber: a.integer(),
|
|
@@ -1704,8 +1718,12 @@ const schema = a.schema({
|
|
|
1704
1718
|
index("searchVisibility").sortKeys(["createdAt"]).name("messagesBySearchVisibilityCreatedAt").queryField("listMessagesBySearchVisibilityAndCreatedAt"),
|
|
1705
1719
|
])
|
|
1706
1720
|
.authorization((allow) => [
|
|
1707
|
-
|
|
1721
|
+
// One rule per group (a group may appear once per model): editors read and add; admins also delete, for moderation.
|
|
1722
|
+
allow.group("editor").to(categoryAppendOnlyOperations),
|
|
1723
|
+
allow.group(adminGroup).to(["read", "create", "delete"]),
|
|
1708
1724
|
allow.authenticated("identityPool").to(["read", "create", "update"]),
|
|
1725
|
+
// Messages belong to their author: the author edits (and soft-deletes) their own, and only an admin can remove someone else's.
|
|
1726
|
+
allow.ownerDefinedIn("authorSub").identityClaim("sub").to(["read", "update", "delete"]),
|
|
1709
1727
|
]),
|
|
1710
1728
|
MessageThread: a
|
|
1711
1729
|
.model({
|
package/amplify/data/resource.ts
CHANGED
|
@@ -1684,6 +1684,15 @@ const schema = a.schema({
|
|
|
1684
1684
|
curationStatusReason: a.string(),
|
|
1685
1685
|
newsroomFeedKey: a.string(),
|
|
1686
1686
|
reviewedFeedKey: a.string(),
|
|
1687
|
+
// The References page reads the feed through two indexes (docs/reference-feed-indexes.md). `feedStateKey` is
|
|
1688
|
+
// "<corpusId>#unrated" or "<corpusId>#rated" for a current, not archived Reference (null otherwise: it is in no feed).
|
|
1689
|
+
// `predictionSortKey` orders Best bets, `feedArrivalAt` orders Newest. The prediction is the Cyclotron's ORIGINAL
|
|
1690
|
+
// P(accept), written once, and never rewritten by a vote.
|
|
1691
|
+
feedStateKey: a.string(),
|
|
1692
|
+
feedArrivalAt: a.datetime(),
|
|
1693
|
+
predictedAcceptProbability: a.float(),
|
|
1694
|
+
predictionDecidedAt: a.datetime(),
|
|
1695
|
+
predictionSortKey: a.string(),
|
|
1687
1696
|
updatedAt: a.datetime(),
|
|
1688
1697
|
})
|
|
1689
1698
|
.secondaryIndexes((index) => [
|
|
@@ -1696,6 +1705,8 @@ const schema = a.schema({
|
|
|
1696
1705
|
index("curationStatus").sortKeys(["curationStatusUpdatedAt"]).queryField("listReferencesByCurationStatusAndUpdatedAt"),
|
|
1697
1706
|
index("curationStatusKey").sortKeys(["curationStatusUpdatedAt"]).queryField("listReferencesByCurationStatusKeyAndUpdatedAt"),
|
|
1698
1707
|
index("reviewedFeedKey").sortKeys(["updatedAt"]).queryField("listReferencesByReviewedFeedAndUpdatedAt"),
|
|
1708
|
+
index("feedStateKey").sortKeys(["predictionSortKey"]).queryField("listReferencesByFeedStateAndPrediction"),
|
|
1709
|
+
index("feedStateKey").sortKeys(["feedArrivalAt"]).queryField("listReferencesByFeedStateAndArrival"),
|
|
1699
1710
|
])
|
|
1700
1711
|
.authorization((allow) => [
|
|
1701
1712
|
allow.groups(categoryWriteGroups).to(["read"]),
|
|
@@ -1786,6 +1797,9 @@ const schema = a.schema({
|
|
|
1786
1797
|
authorSub: a.string(),
|
|
1787
1798
|
authorUserProfileId: a.id(),
|
|
1788
1799
|
authorLabel: a.string(),
|
|
1800
|
+
editedAt: a.datetime(),
|
|
1801
|
+
deletedAt: a.datetime(),
|
|
1802
|
+
deletedBySub: a.string(),
|
|
1789
1803
|
threadId: a.id(),
|
|
1790
1804
|
parentMessageId: a.id(),
|
|
1791
1805
|
sequenceNumber: a.integer(),
|
|
@@ -1820,8 +1834,12 @@ const schema = a.schema({
|
|
|
1820
1834
|
index("searchVisibility").sortKeys(["createdAt"]).name("messagesBySearchVisibilityCreatedAt").queryField("listMessagesBySearchVisibilityAndCreatedAt"),
|
|
1821
1835
|
])
|
|
1822
1836
|
.authorization((allow) => [
|
|
1823
|
-
|
|
1837
|
+
// One rule per group (a group may appear once per model): editors read and add; admins also delete, for moderation.
|
|
1838
|
+
allow.group("editor").to(categoryAppendOnlyOperations),
|
|
1839
|
+
allow.group(adminGroup).to(["read", "create", "delete"]),
|
|
1824
1840
|
allow.authenticated("identityPool").to(["read", "create", "update"]),
|
|
1841
|
+
// Messages belong to their author: the author edits (and soft-deletes) their own, and only an admin can remove someone else's.
|
|
1842
|
+
allow.ownerDefinedIn("authorSub").identityClaim("sub").to(["read", "update", "delete"]),
|
|
1825
1843
|
]),
|
|
1826
1844
|
|
|
1827
1845
|
MessageThread: a
|
package/amplify/data/schema.js
CHANGED
|
@@ -1477,6 +1477,15 @@ function buildBaseDefinitions(includeEditions) {
|
|
|
1477
1477
|
curationStatusReason: a.string(),
|
|
1478
1478
|
newsroomFeedKey: a.string(),
|
|
1479
1479
|
reviewedFeedKey: a.string(),
|
|
1480
|
+
// The References page reads the feed through two indexes (docs/reference-feed-indexes.md). `feedStateKey` is
|
|
1481
|
+
// "<corpusId>#unrated" or "<corpusId>#rated" for a current, not archived Reference (null otherwise: it is in no feed).
|
|
1482
|
+
// `predictionSortKey` orders Best bets, `feedArrivalAt` orders Newest. The prediction is the Cyclotron's ORIGINAL
|
|
1483
|
+
// P(accept), written once, and never rewritten by a vote.
|
|
1484
|
+
feedStateKey: a.string(),
|
|
1485
|
+
feedArrivalAt: a.datetime(),
|
|
1486
|
+
predictedAcceptProbability: a.float(),
|
|
1487
|
+
predictionDecidedAt: a.datetime(),
|
|
1488
|
+
predictionSortKey: a.string(),
|
|
1480
1489
|
updatedAt: a.datetime(),
|
|
1481
1490
|
})
|
|
1482
1491
|
.secondaryIndexes((index) => [
|
|
@@ -1489,6 +1498,8 @@ function buildBaseDefinitions(includeEditions) {
|
|
|
1489
1498
|
index("curationStatus").sortKeys(["curationStatusUpdatedAt"]).queryField("listReferencesByCurationStatusAndUpdatedAt"),
|
|
1490
1499
|
index("curationStatusKey").sortKeys(["curationStatusUpdatedAt"]).queryField("listReferencesByCurationStatusKeyAndUpdatedAt"),
|
|
1491
1500
|
index("reviewedFeedKey").sortKeys(["updatedAt"]).queryField("listReferencesByReviewedFeedAndUpdatedAt"),
|
|
1501
|
+
index("feedStateKey").sortKeys(["predictionSortKey"]).queryField("listReferencesByFeedStateAndPrediction"),
|
|
1502
|
+
index("feedStateKey").sortKeys(["feedArrivalAt"]).queryField("listReferencesByFeedStateAndArrival"),
|
|
1492
1503
|
])
|
|
1493
1504
|
.authorization((allow) => [
|
|
1494
1505
|
allow.groups(categoryWriteGroups).to(["read"]),
|
|
@@ -1573,6 +1584,9 @@ function buildBaseDefinitions(includeEditions) {
|
|
|
1573
1584
|
authorSub: a.string(),
|
|
1574
1585
|
authorUserProfileId: a.id(),
|
|
1575
1586
|
authorLabel: a.string(),
|
|
1587
|
+
editedAt: a.datetime(),
|
|
1588
|
+
deletedAt: a.datetime(),
|
|
1589
|
+
deletedBySub: a.string(),
|
|
1576
1590
|
threadId: a.id(),
|
|
1577
1591
|
parentMessageId: a.id(),
|
|
1578
1592
|
sequenceNumber: a.integer(),
|
|
@@ -1607,7 +1621,11 @@ function buildBaseDefinitions(includeEditions) {
|
|
|
1607
1621
|
index("searchVisibility").sortKeys(["createdAt"]).name("messagesBySearchVisibilityCreatedAt").queryField("listMessagesBySearchVisibilityAndCreatedAt"),
|
|
1608
1622
|
])
|
|
1609
1623
|
.authorization((allow) => [
|
|
1610
|
-
|
|
1624
|
+
// One rule per group (a group may appear once per model): editors read and add; admins also delete, for moderation.
|
|
1625
|
+
allow.group("editor").to(categoryAppendOnlyOperations),
|
|
1626
|
+
allow.group(adminGroup).to(["read", "create", "delete"]),
|
|
1627
|
+
// Messages belong to their author: the author edits (and soft-deletes) their own, and only an admin can remove someone else's.
|
|
1628
|
+
allow.ownerDefinedIn("authorSub").identityClaim("sub").to(["read", "update", "delete"]),
|
|
1611
1629
|
]),
|
|
1612
1630
|
MessageThread: realtimeModel({
|
|
1613
1631
|
id: a.id().required(),
|
package/amplify/data/schema.ts
CHANGED
|
@@ -1588,6 +1588,15 @@ const definitions = {
|
|
|
1588
1588
|
curationStatusReason: a.string(),
|
|
1589
1589
|
newsroomFeedKey: a.string(),
|
|
1590
1590
|
reviewedFeedKey: a.string(),
|
|
1591
|
+
// The References page reads the feed through two indexes (docs/reference-feed-indexes.md). `feedStateKey` is
|
|
1592
|
+
// "<corpusId>#unrated" or "<corpusId>#rated" for a current, not archived Reference (null otherwise: it is in no feed).
|
|
1593
|
+
// `predictionSortKey` orders Best bets, `feedArrivalAt` orders Newest. The prediction is the Cyclotron's ORIGINAL
|
|
1594
|
+
// P(accept), written once, and never rewritten by a vote.
|
|
1595
|
+
feedStateKey: a.string(),
|
|
1596
|
+
feedArrivalAt: a.datetime(),
|
|
1597
|
+
predictedAcceptProbability: a.float(),
|
|
1598
|
+
predictionDecidedAt: a.datetime(),
|
|
1599
|
+
predictionSortKey: a.string(),
|
|
1591
1600
|
updatedAt: a.datetime(),
|
|
1592
1601
|
})
|
|
1593
1602
|
.secondaryIndexes((index) => [
|
|
@@ -1600,6 +1609,8 @@ const definitions = {
|
|
|
1600
1609
|
index("curationStatus").sortKeys(["curationStatusUpdatedAt"]).queryField("listReferencesByCurationStatusAndUpdatedAt"),
|
|
1601
1610
|
index("curationStatusKey").sortKeys(["curationStatusUpdatedAt"]).queryField("listReferencesByCurationStatusKeyAndUpdatedAt"),
|
|
1602
1611
|
index("reviewedFeedKey").sortKeys(["updatedAt"]).queryField("listReferencesByReviewedFeedAndUpdatedAt"),
|
|
1612
|
+
index("feedStateKey").sortKeys(["predictionSortKey"]).queryField("listReferencesByFeedStateAndPrediction"),
|
|
1613
|
+
index("feedStateKey").sortKeys(["feedArrivalAt"]).queryField("listReferencesByFeedStateAndArrival"),
|
|
1603
1614
|
])
|
|
1604
1615
|
.authorization((allow) => [
|
|
1605
1616
|
allow.groups(categoryWriteGroups).to(["read"]),
|
|
@@ -1687,6 +1698,9 @@ const definitions = {
|
|
|
1687
1698
|
authorSub: a.string(),
|
|
1688
1699
|
authorUserProfileId: a.id(),
|
|
1689
1700
|
authorLabel: a.string(),
|
|
1701
|
+
editedAt: a.datetime(),
|
|
1702
|
+
deletedAt: a.datetime(),
|
|
1703
|
+
deletedBySub: a.string(),
|
|
1690
1704
|
threadId: a.id(),
|
|
1691
1705
|
parentMessageId: a.id(),
|
|
1692
1706
|
sequenceNumber: a.integer(),
|
|
@@ -1721,7 +1735,11 @@ const definitions = {
|
|
|
1721
1735
|
index("searchVisibility").sortKeys(["createdAt"]).name("messagesBySearchVisibilityCreatedAt").queryField("listMessagesBySearchVisibilityAndCreatedAt"),
|
|
1722
1736
|
])
|
|
1723
1737
|
.authorization((allow) => [
|
|
1724
|
-
|
|
1738
|
+
// One rule per group (a group may appear once per model): editors read and add; admins also delete, for moderation.
|
|
1739
|
+
allow.group("editor").to(categoryAppendOnlyOperations),
|
|
1740
|
+
allow.group(adminGroup).to(["read", "create", "delete"]),
|
|
1741
|
+
// Messages belong to their author: the author edits (and soft-deletes) their own, and only an admin can remove someone else's.
|
|
1742
|
+
allow.ownerDefinedIn("authorSub").identityClaim("sub").to(["read", "update", "delete"]),
|
|
1725
1743
|
]),
|
|
1726
1744
|
|
|
1727
1745
|
MessageThread: realtimeModel({
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type DelegationStore,
|
|
26
26
|
} from "../shared/curation-delegation-flow";
|
|
27
27
|
import { rejectionReasonCodeForWrittenReason } from "../../../lib/reference-policy";
|
|
28
|
+
import { referenceFeedKeys, referenceFeedStateKey } from "../../../lib/reference-feed-keys";
|
|
28
29
|
import { claimGroups } from "../../../lib/staff-groups";
|
|
29
30
|
|
|
30
31
|
type ReviewHandler = Schema["reviewSteeringProposal"]["functionHandler"];
|
|
@@ -256,6 +257,8 @@ async function reviewReferenceCuration(
|
|
|
256
257
|
curationStatusReason: note,
|
|
257
258
|
newsroomFeedKey: reference.newsroomFeedKey ?? "references",
|
|
258
259
|
reviewedFeedKey: reviewedFeedKeyForStatus(nextStatus),
|
|
260
|
+
// A vote moves the Reference between the unrated and rated feeds; its original prediction and arrival stay as they were.
|
|
261
|
+
feedStateKey: referenceFeedStateKey({ ...reference, curationStatus: nextStatus }),
|
|
259
262
|
updatedAt: now,
|
|
260
263
|
}),
|
|
261
264
|
"update Reference curation status",
|
|
@@ -642,6 +645,8 @@ async function setReferenceQualityRating(event: Parameters<ReferenceQualityHandl
|
|
|
642
645
|
curationStatusReason: note,
|
|
643
646
|
newsroomFeedKey: reference.newsroomFeedKey ?? "references",
|
|
644
647
|
reviewedFeedKey: reviewedFeedKeyForStatus(nextStatus),
|
|
648
|
+
// A vote moves the Reference between the unrated and rated feeds; its original prediction and arrival stay as they were.
|
|
649
|
+
feedStateKey: referenceFeedStateKey({ ...reference, curationStatus: nextStatus }),
|
|
645
650
|
updatedAt: now,
|
|
646
651
|
}),
|
|
647
652
|
"update Reference quality status",
|
|
@@ -818,6 +823,7 @@ async function moveReferenceCorpus(event: Parameters<MoveReferenceCorpusHandler>
|
|
|
818
823
|
client.models.Reference.update({
|
|
819
824
|
id: normalizeRequiredString(current.id, "reference.id"),
|
|
820
825
|
versionState: "superseded",
|
|
826
|
+
feedStateKey: null, // a superseded version is in no feed
|
|
821
827
|
updatedAt: now,
|
|
822
828
|
}),
|
|
823
829
|
"supersede current Reference version",
|
|
@@ -857,6 +863,19 @@ async function moveReferenceCorpus(event: Parameters<MoveReferenceCorpusHandler>
|
|
|
857
863
|
curationStatusReason: normalizeOptionalString(current.curationStatusReason),
|
|
858
864
|
newsroomFeedKey: normalizeOptionalString(current.newsroomFeedKey) ?? "references",
|
|
859
865
|
reviewedFeedKey: normalizeOptionalString(current.reviewedFeedKey) ?? reviewedFeedKeyForStatus(curationStatus),
|
|
866
|
+
predictedAcceptProbability: typeof current.predictedAcceptProbability === "number" ? current.predictedAcceptProbability : null,
|
|
867
|
+
predictionDecidedAt: normalizeOptionalString(current.predictionDecidedAt),
|
|
868
|
+
...referenceFeedKeys({
|
|
869
|
+
id: nextReferenceId,
|
|
870
|
+
corpusId: targetCorpusId,
|
|
871
|
+
curationStatus,
|
|
872
|
+
versionState: "current",
|
|
873
|
+
predictedAcceptProbability: typeof current.predictedAcceptProbability === "number" ? current.predictedAcceptProbability : null,
|
|
874
|
+
createdAt: normalizeOptionalString(current.createdAt) ?? now,
|
|
875
|
+
importedAt: normalizeOptionalString(current.importedAt),
|
|
876
|
+
retrievedAt: normalizeOptionalString(current.retrievedAt),
|
|
877
|
+
sourcePublishedAt: normalizeOptionalString(current.sourcePublishedAt),
|
|
878
|
+
}),
|
|
860
879
|
updatedAt: now,
|
|
861
880
|
}),
|
|
862
881
|
"create moved Reference version",
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The keys the References page reads through (docs/reference-feed-indexes.md). The Python twin is
|
|
3
|
+
* src/papyrus_content/reference_feed_keys.py; scripts/fixtures/reference-feed-key-vectors.json holds the vectors both test.
|
|
4
|
+
*
|
|
5
|
+
* `feedStateKey` is "<corpusId>#unrated" (pending) or "<corpusId>#rated" (accepted or rejected); a Reference that is not the current
|
|
6
|
+
* version, or is archived, has none and is in neither feed. `predictionSortKey` is the Cyclotron's ORIGINAL P(accept), then arrival, then
|
|
7
|
+
* id; a Reference nobody predicted sorts as 0.5. A vote changes `feedStateKey` and nothing else here.
|
|
8
|
+
*/
|
|
9
|
+
import { normalizeReferenceCurationStatus } from "./reference-policy";
|
|
10
|
+
|
|
11
|
+
export const UNDECIDED_PROBABILITY = 0.5;
|
|
12
|
+
const EPOCH = "1970-01-01T00:00:00.000Z";
|
|
13
|
+
const ARRIVAL_FIELDS = ["createdAt", "importedAt", "retrievedAt", "sourcePublishedAt", "versionCreatedAt"] as const;
|
|
14
|
+
|
|
15
|
+
export type ReferenceFeedKeyInput = {
|
|
16
|
+
id: string;
|
|
17
|
+
corpusId?: string | null;
|
|
18
|
+
curationStatus?: string | null;
|
|
19
|
+
versionState?: string | null;
|
|
20
|
+
predictedAcceptProbability?: number | null;
|
|
21
|
+
createdAt?: string | null;
|
|
22
|
+
importedAt?: string | null;
|
|
23
|
+
retrievedAt?: string | null;
|
|
24
|
+
sourcePublishedAt?: string | null;
|
|
25
|
+
versionCreatedAt?: string | null;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type ReferenceFeedKeys = {
|
|
29
|
+
feedStateKey: string | null;
|
|
30
|
+
feedArrivalAt: string;
|
|
31
|
+
predictionSortKey: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function instant(value: string | null | undefined): string | null {
|
|
35
|
+
if (!value) return null;
|
|
36
|
+
const parsed = Date.parse(value);
|
|
37
|
+
return Number.isFinite(parsed) ? new Date(parsed).toISOString() : null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function referenceFeedArrivalAt(reference: ReferenceFeedKeyInput): string {
|
|
41
|
+
for (const field of ARRIVAL_FIELDS) {
|
|
42
|
+
const found = instant(reference[field]);
|
|
43
|
+
if (found) return found;
|
|
44
|
+
}
|
|
45
|
+
return EPOCH;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function referenceFeedStateKey(reference: ReferenceFeedKeyInput): string | null {
|
|
49
|
+
if (reference.versionState && reference.versionState !== "current") return null;
|
|
50
|
+
if (!reference.corpusId) return null;
|
|
51
|
+
const status = normalizeReferenceCurationStatus(reference.curationStatus);
|
|
52
|
+
if (status === "archived") return null;
|
|
53
|
+
return `${reference.corpusId}#${status === "pending" ? "unrated" : "rated"}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function predictionSortKeyFor(probability: number | null | undefined, arrival: string, referenceId: string): string {
|
|
57
|
+
const chosen = probability === null || probability === undefined ? UNDECIDED_PROBABILITY : Math.min(1, Math.max(0, probability));
|
|
58
|
+
return `${chosen.toFixed(6)}#${arrival}#${referenceId}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The three feed keys for a Reference as it stands. `probability` overrides the one stored on it. */
|
|
62
|
+
export function referenceFeedKeys(reference: ReferenceFeedKeyInput, probability?: number | null): ReferenceFeedKeys {
|
|
63
|
+
const arrival = referenceFeedArrivalAt(reference);
|
|
64
|
+
return {
|
|
65
|
+
feedStateKey: referenceFeedStateKey(reference),
|
|
66
|
+
feedArrivalAt: arrival,
|
|
67
|
+
predictionSortKey: predictionSortKeyFor(probability ?? reference.predictedAcceptProbability, arrival, reference.id),
|
|
68
|
+
};
|
|
69
|
+
}
|
package/package.json
CHANGED
|
@@ -354,6 +354,7 @@
|
|
|
354
354
|
"./lib/reference-capture": "./lib/reference-capture.ts",
|
|
355
355
|
"./lib/reference-display": "./lib/reference-display.ts",
|
|
356
356
|
"./lib/reference-feed-cache": "./lib/reference-feed-cache.ts",
|
|
357
|
+
"./lib/reference-feed-keys": "./lib/reference-feed-keys.ts",
|
|
357
358
|
"./lib/reference-feed-ranking": "./lib/reference-feed-ranking.ts",
|
|
358
359
|
"./lib/reference-policy": "./lib/reference-policy.ts",
|
|
359
360
|
"./lib/reference-preview": "./lib/reference-preview.ts",
|
|
@@ -516,7 +517,7 @@
|
|
|
516
517
|
"optional": true
|
|
517
518
|
}
|
|
518
519
|
},
|
|
519
|
-
"version": "5.43.0-next.
|
|
520
|
+
"version": "5.43.0-next.47",
|
|
520
521
|
"dependencies": {
|
|
521
522
|
"@aws-amplify/adapter-nextjs": "^1.7.3",
|
|
522
523
|
"@aws-crypto/sha256-js": "5.2.0",
|
package/routes.manifest.json
CHANGED