@sentry/junior-memory 0.124.1 → 0.125.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.
- package/README.md +11 -1
- package/dist/agent.d.ts +12 -2
- package/dist/api.d.ts +23 -7
- package/dist/events.d.ts +17 -1
- package/dist/index.js +282 -106
- package/dist/index.js.map +1 -1
- package/dist/operational-report.d.ts +2 -1
- package/dist/personal-store.d.ts +22 -11
- package/dist/personal.d.ts +5 -3
- package/dist/recall.d.ts +2 -1
- package/dist/store.d.ts +1 -0
- package/dist/user-pages.d.ts +2 -2
- package/package.json +2 -2
- package/src/agent.ts +26 -8
- package/src/api.ts +32 -9
- package/src/events.ts +53 -16
- package/src/operational-report.ts +37 -1
- package/src/personal-store.ts +108 -46
- package/src/personal.ts +14 -6
- package/src/plugin.ts +17 -2
- package/src/process-session.ts +39 -28
- package/src/recall.ts +52 -5
- package/src/store.ts +2 -0
- package/src/tools.ts +1 -0
- package/src/user-pages.ts +34 -23
package/dist/index.js
CHANGED
|
@@ -397,6 +397,7 @@ var memoryRecordSchema = z2.object({
|
|
|
397
397
|
}).strict();
|
|
398
398
|
var embeddingVectorSchema = z2.array(numberSchema).length(MEMORY_EMBEDDING_DIMENSIONS);
|
|
399
399
|
var embeddingResultSchema = z2.object({
|
|
400
|
+
costUsd: z2.number().finite().nonnegative().optional(),
|
|
400
401
|
dimensions: z2.literal(MEMORY_EMBEDDING_DIMENSIONS),
|
|
401
402
|
model: nonEmptyStringSchema2,
|
|
402
403
|
provider: nonEmptyStringSchema2,
|
|
@@ -496,12 +497,12 @@ function visibleScopePredicate(scopes) {
|
|
|
496
497
|
);
|
|
497
498
|
}
|
|
498
499
|
function activeVisiblePredicate(args) {
|
|
499
|
-
const
|
|
500
|
-
if (!
|
|
500
|
+
const scopePredicate2 = visibleScopePredicate(args.scopes);
|
|
501
|
+
if (!scopePredicate2) {
|
|
501
502
|
return void 0;
|
|
502
503
|
}
|
|
503
504
|
return and(
|
|
504
|
-
|
|
505
|
+
scopePredicate2,
|
|
505
506
|
isNull(juniorMemoryMemories.archivedAtMs),
|
|
506
507
|
isNull(juniorMemoryMemories.supersededAtMs),
|
|
507
508
|
isNull(juniorMemoryMemories.supersededById),
|
|
@@ -571,12 +572,12 @@ async function findByIdempotencyKey(args) {
|
|
|
571
572
|
return void 0;
|
|
572
573
|
}
|
|
573
574
|
async function archiveExpiredMemoryBatch(args) {
|
|
574
|
-
const
|
|
575
|
-
if (!
|
|
575
|
+
const scopePredicate2 = visibleScopePredicate(args.scopes);
|
|
576
|
+
if (!scopePredicate2) {
|
|
576
577
|
return { archivedCount: 0 };
|
|
577
578
|
}
|
|
578
579
|
const predicates = [
|
|
579
|
-
|
|
580
|
+
scopePredicate2,
|
|
580
581
|
isNull(juniorMemoryMemories.archivedAtMs),
|
|
581
582
|
isNull(juniorMemoryMemories.supersededAtMs),
|
|
582
583
|
isNull(juniorMemoryMemories.supersededById),
|
|
@@ -1680,9 +1681,12 @@ function createMemoryAgent(model) {
|
|
|
1680
1681
|
});
|
|
1681
1682
|
const decision = memoryRecallDecisionSchema.parse(result.object);
|
|
1682
1683
|
const candidateIds = new Set(request.candidates.map(({ id }) => id));
|
|
1683
|
-
return
|
|
1684
|
-
|
|
1685
|
-
|
|
1684
|
+
return {
|
|
1685
|
+
relevantIds: [...new Set(decision.relevantIds)].filter(
|
|
1686
|
+
(id) => candidateIds.has(id)
|
|
1687
|
+
),
|
|
1688
|
+
...result.costUsd !== void 0 ? { costUsd: result.costUsd } : {}
|
|
1689
|
+
};
|
|
1686
1690
|
},
|
|
1687
1691
|
async adjudicateSupersession(rawRequest) {
|
|
1688
1692
|
const request = memorySupersessionInputSchema.parse(rawRequest);
|
|
@@ -1702,9 +1706,12 @@ function createMemoryAgent(model) {
|
|
|
1702
1706
|
prompt: sessionExtractionPrompt(request),
|
|
1703
1707
|
maxTokens: 1e3
|
|
1704
1708
|
});
|
|
1705
|
-
return
|
|
1706
|
-
|
|
1707
|
-
|
|
1709
|
+
return {
|
|
1710
|
+
memories: extractedMemoriesFromResponse(
|
|
1711
|
+
extractMemoriesResponseSchema.parse(result.object)
|
|
1712
|
+
),
|
|
1713
|
+
...result.costUsd !== void 0 ? { costUsd: result.costUsd } : {}
|
|
1714
|
+
};
|
|
1708
1715
|
},
|
|
1709
1716
|
async reviewCreateRequest(rawRequest) {
|
|
1710
1717
|
const request = parseCreateMemoryRequest(rawRequest);
|
|
@@ -1765,6 +1772,7 @@ import { z as z5 } from "zod";
|
|
|
1765
1772
|
import { and as and2, asc as asc2, desc as desc2, eq as eq2, gt as gt2, ilike, like as like2, lt, or as or2, sql as sql3 } from "drizzle-orm";
|
|
1766
1773
|
import { z as z4 } from "zod";
|
|
1767
1774
|
var nonEmptyStringSchema3 = z4.string().min(1);
|
|
1775
|
+
var memoryVisibilitySchema = z4.enum(["private", "public"]);
|
|
1768
1776
|
var personalMemoryCursorSchema = z4.object({
|
|
1769
1777
|
createdAtMs: z4.number().finite(),
|
|
1770
1778
|
id: nonEmptyStringSchema3
|
|
@@ -1774,7 +1782,8 @@ var personalMemoryPageInputSchema = z4.object({
|
|
|
1774
1782
|
kind: z4.enum(MEMORY_KINDS).optional(),
|
|
1775
1783
|
limit: z4.number().int().min(1).max(50),
|
|
1776
1784
|
origin: z4.enum(["automatic", "explicit"]).optional(),
|
|
1777
|
-
query: z4.string().max(200).optional()
|
|
1785
|
+
query: z4.string().max(200).optional(),
|
|
1786
|
+
visibility: memoryVisibilitySchema.optional()
|
|
1778
1787
|
}).strict();
|
|
1779
1788
|
var personalMemoryTimelineInputSchema = z4.object({
|
|
1780
1789
|
days: z4.number().int().min(1).max(365)
|
|
@@ -1796,7 +1805,26 @@ function personalScopes(runtimeContexts) {
|
|
|
1796
1805
|
).values()
|
|
1797
1806
|
];
|
|
1798
1807
|
}
|
|
1799
|
-
function
|
|
1808
|
+
function publicWorkspaceScopes(runtimeContexts) {
|
|
1809
|
+
return [
|
|
1810
|
+
...new Map(
|
|
1811
|
+
runtimeContexts.flatMap((context) => {
|
|
1812
|
+
if (context.source.platform !== "slack" || !context.actor) {
|
|
1813
|
+
return [];
|
|
1814
|
+
}
|
|
1815
|
+
if (context.actor.platform !== "slack") {
|
|
1816
|
+
return [];
|
|
1817
|
+
}
|
|
1818
|
+
const scope = {
|
|
1819
|
+
scope: "conversation",
|
|
1820
|
+
scopeKey: `slack:${context.actor.teamId}`
|
|
1821
|
+
};
|
|
1822
|
+
return [[`${scope.scope}:${scope.scopeKey}`, scope]];
|
|
1823
|
+
})
|
|
1824
|
+
).values()
|
|
1825
|
+
];
|
|
1826
|
+
}
|
|
1827
|
+
function scopePredicate(scopes) {
|
|
1800
1828
|
if (scopes.length === 0) return void 0;
|
|
1801
1829
|
return or2(
|
|
1802
1830
|
...scopes.map(
|
|
@@ -1822,21 +1850,50 @@ function memoryOrigin(idempotencyKey) {
|
|
|
1822
1850
|
if (idempotencyKey?.startsWith("tool:")) return "explicit";
|
|
1823
1851
|
return "other";
|
|
1824
1852
|
}
|
|
1853
|
+
function memoryVisibility(scope) {
|
|
1854
|
+
return scope === "personal" ? "private" : "public";
|
|
1855
|
+
}
|
|
1825
1856
|
function personalMemoryRecord(row) {
|
|
1857
|
+
const memory = parseMemoryRow(row);
|
|
1826
1858
|
return {
|
|
1827
|
-
...
|
|
1859
|
+
...memory,
|
|
1828
1860
|
origin: memoryOrigin(row.idempotencyKey),
|
|
1829
|
-
sourcePlatform: row.sourcePlatform
|
|
1861
|
+
sourcePlatform: row.sourcePlatform,
|
|
1862
|
+
visibility: memoryVisibility(memory.scope)
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1865
|
+
function emptyStats() {
|
|
1866
|
+
return {
|
|
1867
|
+
active: 0,
|
|
1868
|
+
automatic: 0,
|
|
1869
|
+
createdThirtyDays: 0,
|
|
1870
|
+
embedded: 0,
|
|
1871
|
+
explicit: 0,
|
|
1872
|
+
knowledge: 0,
|
|
1873
|
+
personal: 0,
|
|
1874
|
+
preference: 0,
|
|
1875
|
+
procedure: 0,
|
|
1876
|
+
public: 0
|
|
1830
1877
|
};
|
|
1831
1878
|
}
|
|
1832
1879
|
function createPersonalMemoryCollection(db, runtimeContexts, options = {}) {
|
|
1833
|
-
const
|
|
1880
|
+
const privateScopes = personalScopes(runtimeContexts);
|
|
1881
|
+
const publicScopes = publicWorkspaceScopes(runtimeContexts);
|
|
1882
|
+
const allScopes = [...privateScopes, ...publicScopes];
|
|
1834
1883
|
const getNowMs = () => options.now?.() ?? Date.now();
|
|
1884
|
+
function scopesForVisibility(visibility) {
|
|
1885
|
+
if (visibility === "private") return privateScopes;
|
|
1886
|
+
if (visibility === "public") return publicScopes;
|
|
1887
|
+
return allScopes;
|
|
1888
|
+
}
|
|
1835
1889
|
return {
|
|
1836
1890
|
async archive(id) {
|
|
1837
1891
|
const memoryId = nonEmptyStringSchema3.parse(id);
|
|
1838
1892
|
const nowMs = getNowMs();
|
|
1839
|
-
const predicate = activeVisiblePredicate({
|
|
1893
|
+
const predicate = activeVisiblePredicate({
|
|
1894
|
+
nowMs,
|
|
1895
|
+
scopes: privateScopes
|
|
1896
|
+
});
|
|
1840
1897
|
if (!predicate) {
|
|
1841
1898
|
throw new PersonalMemoryNotFoundError();
|
|
1842
1899
|
}
|
|
@@ -1853,7 +1910,7 @@ function createPersonalMemoryCollection(db, runtimeContexts, options = {}) {
|
|
|
1853
1910
|
async get(id) {
|
|
1854
1911
|
const memoryId = nonEmptyStringSchema3.parse(id);
|
|
1855
1912
|
const nowMs = getNowMs();
|
|
1856
|
-
const predicate = activeVisiblePredicate({ nowMs, scopes });
|
|
1913
|
+
const predicate = activeVisiblePredicate({ nowMs, scopes: allScopes });
|
|
1857
1914
|
if (!predicate) {
|
|
1858
1915
|
throw new PersonalMemoryNotFoundError();
|
|
1859
1916
|
}
|
|
@@ -1861,11 +1918,12 @@ function createPersonalMemoryCollection(db, runtimeContexts, options = {}) {
|
|
|
1861
1918
|
if (!rows[0]) {
|
|
1862
1919
|
throw new PersonalMemoryNotFoundError();
|
|
1863
1920
|
}
|
|
1864
|
-
return
|
|
1921
|
+
return personalMemoryRecord(rows[0]);
|
|
1865
1922
|
},
|
|
1866
1923
|
async list(input) {
|
|
1867
1924
|
input = personalMemoryPageInputSchema.parse(input);
|
|
1868
1925
|
const nowMs = getNowMs();
|
|
1926
|
+
const scopes = scopesForVisibility(input.visibility);
|
|
1869
1927
|
await archiveExpiredMemoryBatch({ db, nowMs, scopes });
|
|
1870
1928
|
const active = activeVisiblePredicate({ nowMs, scopes });
|
|
1871
1929
|
if (!active) {
|
|
@@ -1905,19 +1963,10 @@ function createPersonalMemoryCollection(db, runtimeContexts, options = {}) {
|
|
|
1905
1963
|
},
|
|
1906
1964
|
async stats() {
|
|
1907
1965
|
const nowMs = getNowMs();
|
|
1908
|
-
await archiveExpiredMemoryBatch({ db, nowMs, scopes });
|
|
1909
|
-
const active = activeVisiblePredicate({ nowMs, scopes });
|
|
1966
|
+
await archiveExpiredMemoryBatch({ db, nowMs, scopes: allScopes });
|
|
1967
|
+
const active = activeVisiblePredicate({ nowMs, scopes: allScopes });
|
|
1910
1968
|
if (!active) {
|
|
1911
|
-
return
|
|
1912
|
-
active: 0,
|
|
1913
|
-
automatic: 0,
|
|
1914
|
-
createdThirtyDays: 0,
|
|
1915
|
-
embedded: 0,
|
|
1916
|
-
explicit: 0,
|
|
1917
|
-
knowledge: 0,
|
|
1918
|
-
preference: 0,
|
|
1919
|
-
procedure: 0
|
|
1920
|
-
};
|
|
1969
|
+
return emptyStats();
|
|
1921
1970
|
}
|
|
1922
1971
|
const [counts] = await db.select({
|
|
1923
1972
|
active: sql3`count(*)`.mapWith(Number),
|
|
@@ -1936,11 +1985,17 @@ function createPersonalMemoryCollection(db, runtimeContexts, options = {}) {
|
|
|
1936
1985
|
knowledge: sql3`count(*) filter (where ${juniorMemoryMemories.kind} = 'knowledge')`.mapWith(
|
|
1937
1986
|
Number
|
|
1938
1987
|
),
|
|
1988
|
+
personal: sql3`count(*) filter (where ${juniorMemoryMemories.scope} = 'personal')`.mapWith(
|
|
1989
|
+
Number
|
|
1990
|
+
),
|
|
1939
1991
|
preference: sql3`count(*) filter (where ${juniorMemoryMemories.kind} = 'preference')`.mapWith(
|
|
1940
1992
|
Number
|
|
1941
1993
|
),
|
|
1942
1994
|
procedure: sql3`count(*) filter (where ${juniorMemoryMemories.kind} = 'procedure')`.mapWith(
|
|
1943
1995
|
Number
|
|
1996
|
+
),
|
|
1997
|
+
public: sql3`count(*) filter (where ${juniorMemoryMemories.scope} = 'conversation')`.mapWith(
|
|
1998
|
+
Number
|
|
1944
1999
|
)
|
|
1945
2000
|
}).from(juniorMemoryMemories).leftJoin(
|
|
1946
2001
|
juniorMemoryEmbeddings,
|
|
@@ -1953,34 +2008,32 @@ function createPersonalMemoryCollection(db, runtimeContexts, options = {}) {
|
|
|
1953
2008
|
embedded: counts?.embedded ?? 0,
|
|
1954
2009
|
explicit: counts?.explicit ?? 0,
|
|
1955
2010
|
knowledge: counts?.knowledge ?? 0,
|
|
2011
|
+
personal: counts?.personal ?? 0,
|
|
1956
2012
|
preference: counts?.preference ?? 0,
|
|
1957
|
-
procedure: counts?.procedure ?? 0
|
|
2013
|
+
procedure: counts?.procedure ?? 0,
|
|
2014
|
+
public: counts?.public ?? 0
|
|
1958
2015
|
};
|
|
1959
2016
|
},
|
|
1960
2017
|
async timeline(input) {
|
|
1961
2018
|
input = personalMemoryTimelineInputSchema.parse(input);
|
|
1962
2019
|
const todayMs = Date.parse(`${utcDate(getNowMs())}T00:00:00.000Z`);
|
|
1963
2020
|
const startMs = todayMs - (input.days - 1) * DAY_MS;
|
|
1964
|
-
const ownership =
|
|
2021
|
+
const ownership = scopePredicate(allScopes);
|
|
1965
2022
|
if (!ownership) {
|
|
1966
2023
|
return Array.from({ length: input.days }, (_, index2) => ({
|
|
1967
2024
|
date: utcDate(startMs + index2 * DAY_MS),
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
procedure: 0
|
|
2025
|
+
personal: 0,
|
|
2026
|
+
public: 0
|
|
1971
2027
|
}));
|
|
1972
2028
|
}
|
|
1973
2029
|
const rows = await db.select({
|
|
1974
2030
|
date: sql3`to_char(to_timestamp(${juniorMemoryMemories.createdAtMs} / 1000.0) AT TIME ZONE 'UTC', 'YYYY-MM-DD')`.as(
|
|
1975
2031
|
"date"
|
|
1976
2032
|
),
|
|
1977
|
-
|
|
2033
|
+
personal: sql3`count(*) filter (where ${juniorMemoryMemories.scope} = 'personal')`.mapWith(
|
|
1978
2034
|
Number
|
|
1979
2035
|
),
|
|
1980
|
-
|
|
1981
|
-
Number
|
|
1982
|
-
),
|
|
1983
|
-
procedure: sql3`count(*) filter (where ${juniorMemoryMemories.kind} = 'procedure')`.mapWith(
|
|
2036
|
+
public: sql3`count(*) filter (where ${juniorMemoryMemories.scope} = 'conversation')`.mapWith(
|
|
1984
2037
|
Number
|
|
1985
2038
|
)
|
|
1986
2039
|
}).from(juniorMemoryMemories).where(
|
|
@@ -1994,9 +2047,8 @@ function createPersonalMemoryCollection(db, runtimeContexts, options = {}) {
|
|
|
1994
2047
|
const row = byDate.get(date);
|
|
1995
2048
|
return {
|
|
1996
2049
|
date,
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
procedure: row?.procedure ?? 0
|
|
2050
|
+
personal: row?.personal ?? 0,
|
|
2051
|
+
public: row?.public ?? 0
|
|
2000
2052
|
};
|
|
2001
2053
|
});
|
|
2002
2054
|
}
|
|
@@ -2010,7 +2062,8 @@ var cursorSchema = z5.object({
|
|
|
2010
2062
|
kind: z5.enum(["preference", "procedure", "knowledge"]).optional(),
|
|
2011
2063
|
origin: z5.enum(["automatic", "explicit"]).optional(),
|
|
2012
2064
|
query: z5.string().max(200).optional(),
|
|
2013
|
-
version: z5.literal(1)
|
|
2065
|
+
version: z5.literal(1),
|
|
2066
|
+
visibility: z5.enum(["private", "public"]).optional()
|
|
2014
2067
|
}).strict();
|
|
2015
2068
|
var InvalidMemoryCursorError = class extends Error {
|
|
2016
2069
|
constructor() {
|
|
@@ -2045,7 +2098,7 @@ function decodeCursor(value, input) {
|
|
|
2045
2098
|
const parsed = cursorSchema.parse(
|
|
2046
2099
|
JSON.parse(Buffer.from(value, "base64url").toString("utf8"))
|
|
2047
2100
|
);
|
|
2048
|
-
if (parsed.query !== input.query || parsed.kind !== input.kind || parsed.origin !== input.origin) {
|
|
2101
|
+
if (parsed.query !== input.query || parsed.kind !== input.kind || parsed.origin !== input.origin || parsed.visibility !== input.visibility) {
|
|
2049
2102
|
throw new InvalidMemoryCursorError();
|
|
2050
2103
|
}
|
|
2051
2104
|
return { createdAtMs: parsed.createdAtMs, id: parsed.id };
|
|
@@ -2060,6 +2113,7 @@ function encodeCursor(cursor, input) {
|
|
|
2060
2113
|
...input.query ? { query: input.query } : {},
|
|
2061
2114
|
...input.kind ? { kind: input.kind } : {},
|
|
2062
2115
|
...input.origin ? { origin: input.origin } : {},
|
|
2116
|
+
...input.visibility ? { visibility: input.visibility } : {},
|
|
2063
2117
|
version: 1
|
|
2064
2118
|
}),
|
|
2065
2119
|
"utf8"
|
|
@@ -2082,7 +2136,8 @@ function createViewerMemories(db, actors) {
|
|
|
2082
2136
|
const filters = {
|
|
2083
2137
|
...input.kind ? { kind: input.kind } : {},
|
|
2084
2138
|
...input.origin ? { origin: input.origin } : {},
|
|
2085
|
-
...query ? { query } : {}
|
|
2139
|
+
...query ? { query } : {},
|
|
2140
|
+
...input.visibility ? { visibility: input.visibility } : {}
|
|
2086
2141
|
};
|
|
2087
2142
|
const page = await collection.list({
|
|
2088
2143
|
cursor: decodeCursor(input.cursor, filters),
|
|
@@ -2110,7 +2165,8 @@ var memoryApiSchema = z6.object({
|
|
|
2110
2165
|
expiresAt: z6.iso.datetime().optional(),
|
|
2111
2166
|
id: z6.string().min(1),
|
|
2112
2167
|
kind: z6.enum(["preference", "procedure", "knowledge"]),
|
|
2113
|
-
observedAt: z6.iso.datetime()
|
|
2168
|
+
observedAt: z6.iso.datetime(),
|
|
2169
|
+
visibility: z6.enum(["private", "public"])
|
|
2114
2170
|
}).strict();
|
|
2115
2171
|
var memoryListResponseSchema = z6.object({
|
|
2116
2172
|
memories: z6.array(memoryApiSchema),
|
|
@@ -2118,12 +2174,17 @@ var memoryListResponseSchema = z6.object({
|
|
|
2118
2174
|
}).strict();
|
|
2119
2175
|
var memoryDashboardDaySchema = z6.object({
|
|
2120
2176
|
date: z6.iso.date(),
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2177
|
+
personal: z6.number().int().min(0),
|
|
2178
|
+
public: z6.number().int().min(0)
|
|
2179
|
+
}).strict();
|
|
2180
|
+
var memoryExtractionDaySchema = z6.object({
|
|
2181
|
+
costUsd: z6.number().finite().nonnegative(),
|
|
2182
|
+
date: z6.iso.date(),
|
|
2183
|
+
events: z6.number().int().min(0)
|
|
2124
2184
|
}).strict();
|
|
2125
2185
|
var memoryDashboardResponseSchema = z6.object({
|
|
2126
2186
|
days: z6.array(memoryDashboardDaySchema).length(90),
|
|
2187
|
+
extractionDays: z6.array(memoryExtractionDaySchema).length(90),
|
|
2127
2188
|
generatedAt: z6.iso.datetime(),
|
|
2128
2189
|
stats: z6.object({
|
|
2129
2190
|
active: z6.number().int().min(0),
|
|
@@ -2132,8 +2193,10 @@ var memoryDashboardResponseSchema = z6.object({
|
|
|
2132
2193
|
embedded: z6.number().int().min(0),
|
|
2133
2194
|
explicit: z6.number().int().min(0),
|
|
2134
2195
|
knowledge: z6.number().int().min(0),
|
|
2196
|
+
personal: z6.number().int().min(0),
|
|
2135
2197
|
preference: z6.number().int().min(0),
|
|
2136
|
-
procedure: z6.number().int().min(0)
|
|
2198
|
+
procedure: z6.number().int().min(0),
|
|
2199
|
+
public: z6.number().int().min(0)
|
|
2137
2200
|
}).strict()
|
|
2138
2201
|
}).strict();
|
|
2139
2202
|
var memoryListQuerySchema = z6.object({
|
|
@@ -2154,7 +2217,8 @@ function apiMemory(memory) {
|
|
|
2154
2217
|
...memory.expiresAtMs !== void 0 ? { expiresAt: new Date(memory.expiresAtMs).toISOString() } : {},
|
|
2155
2218
|
id: memory.id,
|
|
2156
2219
|
kind: memory.kind,
|
|
2157
|
-
observedAt: new Date(memory.observedAtMs).toISOString()
|
|
2220
|
+
observedAt: new Date(memory.observedAtMs).toISOString(),
|
|
2221
|
+
visibility: memory.visibility
|
|
2158
2222
|
};
|
|
2159
2223
|
}
|
|
2160
2224
|
function viewerEmail(context) {
|
|
@@ -2182,12 +2246,17 @@ function createMemoryApi(options) {
|
|
|
2182
2246
|
const memories = createViewerMemories(options.db, actors);
|
|
2183
2247
|
try {
|
|
2184
2248
|
if (isDashboard && (request.method === "GET" || request.method === "HEAD")) {
|
|
2185
|
-
const [stats, days] = await Promise.all([
|
|
2249
|
+
const [stats, days, extractionDays] = await Promise.all([
|
|
2186
2250
|
memories.stats(),
|
|
2187
|
-
memories.timeline({ days: 90 })
|
|
2251
|
+
memories.timeline({ days: 90 }),
|
|
2252
|
+
options.eventStats.costsByDay({
|
|
2253
|
+
days: 90,
|
|
2254
|
+
eventName: "memories_captured"
|
|
2255
|
+
})
|
|
2188
2256
|
]);
|
|
2189
2257
|
const body = memoryDashboardResponseSchema.parse({
|
|
2190
2258
|
days,
|
|
2259
|
+
extractionDays,
|
|
2191
2260
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2192
2261
|
stats
|
|
2193
2262
|
});
|
|
@@ -2628,6 +2697,7 @@ function memoryToolResult(target, data) {
|
|
|
2628
2697
|
}
|
|
2629
2698
|
function createMemoryCreateTool(context) {
|
|
2630
2699
|
return definePluginTool({
|
|
2700
|
+
approvalMode: "approve",
|
|
2631
2701
|
annotations: {
|
|
2632
2702
|
destructiveHint: false,
|
|
2633
2703
|
idempotentHint: true,
|
|
@@ -2807,23 +2877,47 @@ function eventPreview(content) {
|
|
|
2807
2877
|
if (trimmed.length <= MAX_EVENT_PREVIEW_CHARS) return trimmed;
|
|
2808
2878
|
return `${trimmed.slice(0, MAX_EVENT_PREVIEW_CHARS - 3).trimEnd()}...`;
|
|
2809
2879
|
}
|
|
2810
|
-
var
|
|
2880
|
+
var capturedMemoriesSchema = z8.object({
|
|
2881
|
+
memories: z8.array(capturedMemorySchema).max(100),
|
|
2882
|
+
costUsd: z8.number().finite().nonnegative().optional()
|
|
2883
|
+
}).strict();
|
|
2884
|
+
var recalledMemoriesSchema = z8.object({
|
|
2885
|
+
memories: z8.array(z8.string().min(1)).max(5),
|
|
2886
|
+
costUsd: z8.number().finite().nonnegative().optional()
|
|
2887
|
+
}).strict();
|
|
2888
|
+
function renderCapturedMemories(event) {
|
|
2889
|
+
const count = event.memories.length;
|
|
2890
|
+
if (count === 0) return void 0;
|
|
2891
|
+
return {
|
|
2892
|
+
icon: "brain",
|
|
2893
|
+
title: count === 1 ? "Memory captured" : "Memories captured",
|
|
2894
|
+
preview: count === 1 ? eventPreview(event.memories[0].content) : `${count} memories`,
|
|
2895
|
+
details: event.memories.map((memory) => ({
|
|
2896
|
+
title: memory.content,
|
|
2897
|
+
metadata: [memory.kind, memory.scope]
|
|
2898
|
+
}))
|
|
2899
|
+
};
|
|
2900
|
+
}
|
|
2901
|
+
var memoriesCapturedEventV1 = defineConversationEvent({
|
|
2811
2902
|
name: "memories_captured",
|
|
2812
2903
|
version: 1,
|
|
2813
2904
|
schema: z8.object({
|
|
2814
2905
|
memories: z8.array(capturedMemorySchema).min(1).max(100)
|
|
2815
2906
|
}).strict(),
|
|
2816
|
-
renderEvent
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2907
|
+
renderEvent: renderCapturedMemories
|
|
2908
|
+
});
|
|
2909
|
+
var memoriesCapturedEvent = defineConversationEvent({
|
|
2910
|
+
name: "memories_captured",
|
|
2911
|
+
version: 2,
|
|
2912
|
+
schema: capturedMemoriesSchema,
|
|
2913
|
+
renderEvent: renderCapturedMemories
|
|
2914
|
+
});
|
|
2915
|
+
var memoriesRecalledEvent = defineConversationEvent({
|
|
2916
|
+
name: "memories_recalled",
|
|
2917
|
+
version: 1,
|
|
2918
|
+
schema: recalledMemoriesSchema,
|
|
2919
|
+
renderEvent() {
|
|
2920
|
+
return void 0;
|
|
2827
2921
|
}
|
|
2828
2922
|
});
|
|
2829
2923
|
function capturedMemory(memory) {
|
|
@@ -2844,14 +2938,19 @@ var MEMORY_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
2844
2938
|
"searchMemories"
|
|
2845
2939
|
]);
|
|
2846
2940
|
var MEMORY_TASK_STATE_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
2847
|
-
var
|
|
2941
|
+
var extractedMemorySchema2 = z9.object({
|
|
2942
|
+
content: z9.string().min(1),
|
|
2943
|
+
expiresAtMs: z9.number().finite().nullable(),
|
|
2944
|
+
kind: z9.enum(MEMORY_KINDS),
|
|
2945
|
+
evidenceMessageIndices: z9.array(z9.number().int().nonnegative()).min(1).max(10)
|
|
2946
|
+
}).strict().transform(parseExtractedMemory);
|
|
2947
|
+
var extractedMemoryCacheSchema = z9.union([
|
|
2848
2948
|
z9.object({
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
);
|
|
2949
|
+
costUsd: z9.number().finite().nonnegative().optional(),
|
|
2950
|
+
memories: z9.array(extractedMemorySchema2).max(5)
|
|
2951
|
+
}).strict(),
|
|
2952
|
+
z9.array(extractedMemorySchema2).max(5).transform((memories) => ({ memories }))
|
|
2953
|
+
]);
|
|
2855
2954
|
function recordCapturedMemory(captured, result) {
|
|
2856
2955
|
const supersededIds = new Set(result.supersededIds ?? []);
|
|
2857
2956
|
for (let index2 = captured.length - 1; index2 >= 0; index2 -= 1) {
|
|
@@ -2918,7 +3017,7 @@ function passiveInput(sessionId, memory, sourceKey2, target) {
|
|
|
2918
3017
|
...memory.expiresAtMs !== null ? { expiresAtMs: memory.expiresAtMs } : {}
|
|
2919
3018
|
};
|
|
2920
3019
|
}
|
|
2921
|
-
async function
|
|
3020
|
+
async function getTaskExtraction(context, extract) {
|
|
2922
3021
|
const cacheKey = `memory-extraction:${context.id}`;
|
|
2923
3022
|
const cached = await context.state.get(cacheKey);
|
|
2924
3023
|
if (cached !== void 0) {
|
|
@@ -2928,11 +3027,9 @@ async function getTaskMemories(context, extract) {
|
|
|
2928
3027
|
}
|
|
2929
3028
|
await context.state.delete(cacheKey);
|
|
2930
3029
|
}
|
|
2931
|
-
const
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
}
|
|
2935
|
-
return memories;
|
|
3030
|
+
const extraction = await extract();
|
|
3031
|
+
await context.state.set(cacheKey, extraction, MEMORY_TASK_STATE_TTL_MS);
|
|
3032
|
+
return extraction;
|
|
2936
3033
|
}
|
|
2937
3034
|
async function processMemorySession(context) {
|
|
2938
3035
|
const run = await context.run.load();
|
|
@@ -2964,7 +3061,7 @@ async function processMemorySession(context) {
|
|
|
2964
3061
|
supersessionDecider: agent
|
|
2965
3062
|
});
|
|
2966
3063
|
await store.archiveExpiredMemories();
|
|
2967
|
-
const
|
|
3064
|
+
const extraction = await getTaskExtraction(context, async () => {
|
|
2968
3065
|
const existingMemories = await store.searchMemories({
|
|
2969
3066
|
limit: 10,
|
|
2970
3067
|
query: evidenceText
|
|
@@ -2978,11 +3075,8 @@ async function processMemorySession(context) {
|
|
|
2978
3075
|
runtimeContext: runtimeContext2
|
|
2979
3076
|
});
|
|
2980
3077
|
});
|
|
2981
|
-
if (memories.length === 0) {
|
|
2982
|
-
return;
|
|
2983
|
-
}
|
|
2984
3078
|
const captured = [];
|
|
2985
|
-
for (const memory of memories) {
|
|
3079
|
+
for (const memory of extraction.memories) {
|
|
2986
3080
|
const target = routeExtractedMemory(memory, transcript, run);
|
|
2987
3081
|
if (target === "drop") {
|
|
2988
3082
|
continue;
|
|
@@ -2996,9 +3090,12 @@ async function processMemorySession(context) {
|
|
|
2996
3090
|
const result = await store.createMemory(input);
|
|
2997
3091
|
recordCapturedMemory(captured, result);
|
|
2998
3092
|
}
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3093
|
+
await context.events.emit(
|
|
3094
|
+
memoriesCapturedEvent({
|
|
3095
|
+
memories: captured,
|
|
3096
|
+
...extraction.costUsd !== void 0 ? { costUsd: extraction.costUsd } : {}
|
|
3097
|
+
})
|
|
3098
|
+
);
|
|
3002
3099
|
}
|
|
3003
3100
|
|
|
3004
3101
|
// src/recall.ts
|
|
@@ -3062,6 +3159,19 @@ function renderMemoryPrompt(memories) {
|
|
|
3062
3159
|
"Treat these as possibly stale context. Current user instructions and repository evidence take priority."
|
|
3063
3160
|
].join("\n");
|
|
3064
3161
|
}
|
|
3162
|
+
function addUsd(left, right) {
|
|
3163
|
+
if (left === void 0) return right;
|
|
3164
|
+
if (right === void 0) return left;
|
|
3165
|
+
return Math.round((left + right) * 1e12) / 1e12;
|
|
3166
|
+
}
|
|
3167
|
+
async function emitRecallOutcome(args) {
|
|
3168
|
+
await args.events?.emit(
|
|
3169
|
+
memoriesRecalledEvent({
|
|
3170
|
+
memories: args.memories,
|
|
3171
|
+
...args.costUsd !== void 0 ? { costUsd: args.costUsd } : {}
|
|
3172
|
+
})
|
|
3173
|
+
);
|
|
3174
|
+
}
|
|
3065
3175
|
var memoryRecallContext = definePromptContext({
|
|
3066
3176
|
kind: "recall",
|
|
3067
3177
|
version: 1,
|
|
@@ -3077,19 +3187,33 @@ async function createMemoryPromptContributions(context) {
|
|
|
3077
3187
|
...context.actor ? { actor: context.actor } : {},
|
|
3078
3188
|
source: context.source
|
|
3079
3189
|
});
|
|
3190
|
+
let embeddingCostUsd;
|
|
3191
|
+
const sourceEmbedder = context.embedder;
|
|
3192
|
+
const embedder = sourceEmbedder ? {
|
|
3193
|
+
async embedTexts(input) {
|
|
3194
|
+
const result = await sourceEmbedder.embedTexts(input);
|
|
3195
|
+
embeddingCostUsd = addUsd(embeddingCostUsd, result.costUsd);
|
|
3196
|
+
return result;
|
|
3197
|
+
}
|
|
3198
|
+
} : void 0;
|
|
3080
3199
|
const candidates = await createMemoryStore(context.db, runtimeContext2, {
|
|
3081
|
-
...
|
|
3200
|
+
...embedder ? { embedder } : {},
|
|
3082
3201
|
...context.maxVectorDistance !== void 0 ? { maxVectorDistance: context.maxVectorDistance } : {}
|
|
3083
3202
|
}).recallMemories({
|
|
3084
3203
|
query: context.text,
|
|
3085
3204
|
limit: RECALL_CANDIDATE_LIMIT
|
|
3086
3205
|
});
|
|
3087
3206
|
if (candidates.length === 0) {
|
|
3207
|
+
await emitRecallOutcome({
|
|
3208
|
+
...embeddingCostUsd !== void 0 ? { costUsd: embeddingCostUsd } : {},
|
|
3209
|
+
events: context.events,
|
|
3210
|
+
memories: []
|
|
3211
|
+
});
|
|
3088
3212
|
return void 0;
|
|
3089
3213
|
}
|
|
3090
|
-
let
|
|
3214
|
+
let recall;
|
|
3091
3215
|
try {
|
|
3092
|
-
|
|
3216
|
+
recall = await context.agent.selectRelevantMemories({
|
|
3093
3217
|
candidates: candidates.map(({ content, id }) => ({ content, id })),
|
|
3094
3218
|
userRequest: context.text
|
|
3095
3219
|
});
|
|
@@ -3100,8 +3224,14 @@ async function createMemoryPromptContributions(context) {
|
|
|
3100
3224
|
const candidatesById = new Map(
|
|
3101
3225
|
candidates.map((memory) => [memory.id, memory])
|
|
3102
3226
|
);
|
|
3103
|
-
const relevant = relevantIds.map((id) => candidatesById.get(id)).filter((memory) => memory !== void 0).slice(0, DEFAULT_RECALL_LIMIT);
|
|
3227
|
+
const relevant = recall.relevantIds.map((id) => candidatesById.get(id)).filter((memory) => memory !== void 0).slice(0, DEFAULT_RECALL_LIMIT);
|
|
3104
3228
|
const selected = selectPromptMemories(relevant);
|
|
3229
|
+
const costUsd = addUsd(embeddingCostUsd, recall.costUsd);
|
|
3230
|
+
await emitRecallOutcome({
|
|
3231
|
+
...costUsd !== void 0 ? { costUsd } : {},
|
|
3232
|
+
events: context.events,
|
|
3233
|
+
memories: selected.map(({ id }) => id)
|
|
3234
|
+
});
|
|
3105
3235
|
if (selected.length === 0) {
|
|
3106
3236
|
return void 0;
|
|
3107
3237
|
}
|
|
@@ -3180,6 +3310,15 @@ function formatPercent(value) {
|
|
|
3180
3310
|
style: "percent"
|
|
3181
3311
|
}).format(value);
|
|
3182
3312
|
}
|
|
3313
|
+
function formatUsd(value) {
|
|
3314
|
+
const maximumFractionDigits = value > 0 && value < 0.01 ? 4 : 2;
|
|
3315
|
+
return new Intl.NumberFormat("en-US", {
|
|
3316
|
+
currency: "USD",
|
|
3317
|
+
maximumFractionDigits,
|
|
3318
|
+
minimumFractionDigits: 2,
|
|
3319
|
+
style: "currency"
|
|
3320
|
+
}).format(value);
|
|
3321
|
+
}
|
|
3183
3322
|
async function buildMemoryOperationalReport(args) {
|
|
3184
3323
|
const active = and4(
|
|
3185
3324
|
isNull3(juniorMemoryMemories.archivedAtMs),
|
|
@@ -3214,6 +3353,11 @@ async function buildMemoryOperationalReport(args) {
|
|
|
3214
3353
|
const activeCount = counts?.active ?? 0;
|
|
3215
3354
|
const embeddedCount = counts?.embedded ?? 0;
|
|
3216
3355
|
const embeddingCoverage = activeCount === 0 ? 0 : embeddedCount / activeCount;
|
|
3356
|
+
const extractionThirtyDays = args.extractionDays.slice(-30);
|
|
3357
|
+
const extractionCostThirtyDays = extractionThirtyDays.reduce(
|
|
3358
|
+
(total, day) => total + day.costUsd,
|
|
3359
|
+
0
|
|
3360
|
+
);
|
|
3217
3361
|
return {
|
|
3218
3362
|
generatedAt: new Date(args.nowMs).toISOString(),
|
|
3219
3363
|
title: "Memory",
|
|
@@ -3223,6 +3367,10 @@ async function buildMemoryOperationalReport(args) {
|
|
|
3223
3367
|
tone: activeCount > 0 ? "good" : "neutral",
|
|
3224
3368
|
value: formatCount(activeCount)
|
|
3225
3369
|
},
|
|
3370
|
+
{
|
|
3371
|
+
label: "extraction cost \xB7 30d",
|
|
3372
|
+
value: formatUsd(extractionCostThirtyDays)
|
|
3373
|
+
},
|
|
3226
3374
|
{
|
|
3227
3375
|
label: "created \xB7 30d",
|
|
3228
3376
|
value: formatCount(counts?.createdThirtyDays ?? 0)
|
|
@@ -3242,6 +3390,19 @@ async function buildMemoryOperationalReport(args) {
|
|
|
3242
3390
|
}
|
|
3243
3391
|
],
|
|
3244
3392
|
widgets: [
|
|
3393
|
+
{
|
|
3394
|
+
categories: args.extractionDays.map((day) => ({
|
|
3395
|
+
id: day.date,
|
|
3396
|
+
label: day.date,
|
|
3397
|
+
values: { costUsd: day.costUsd }
|
|
3398
|
+
})),
|
|
3399
|
+
description: "Estimated model cost of passive memory extraction",
|
|
3400
|
+
id: "extraction-cost",
|
|
3401
|
+
series: [{ format: "usd", key: "costUsd", label: "Cost" }],
|
|
3402
|
+
timeRangeDays: [...WINDOWS],
|
|
3403
|
+
title: "Extraction cost",
|
|
3404
|
+
type: "bar_chart"
|
|
3405
|
+
},
|
|
3245
3406
|
{
|
|
3246
3407
|
categories: memoryDays.map((day) => ({
|
|
3247
3408
|
id: day.date,
|
|
@@ -3281,25 +3442,26 @@ function originLabel(origin) {
|
|
|
3281
3442
|
if (origin === "explicit") return "Explicit";
|
|
3282
3443
|
return "Other";
|
|
3283
3444
|
}
|
|
3445
|
+
function visibilityLabel(visibility) {
|
|
3446
|
+
return visibility === "public" ? "Public" : "Private";
|
|
3447
|
+
}
|
|
3284
3448
|
function pageFilter(filter) {
|
|
3285
|
-
if (filter === "
|
|
3286
|
-
if (filter === "
|
|
3287
|
-
if (filter === "explicit") return { origin: "explicit" };
|
|
3449
|
+
if (filter === "private") return { visibility: "private" };
|
|
3450
|
+
if (filter === "public") return { visibility: "public" };
|
|
3288
3451
|
return {};
|
|
3289
3452
|
}
|
|
3290
3453
|
function pageEmptyText(input) {
|
|
3291
3454
|
if (input.query) return "No memories matched your search.";
|
|
3292
|
-
if (input.filter === "
|
|
3293
|
-
if (input.filter === "
|
|
3294
|
-
|
|
3295
|
-
return "No personal memories yet.";
|
|
3455
|
+
if (input.filter === "private") return "No private memories yet.";
|
|
3456
|
+
if (input.filter === "public") return "No public memories yet.";
|
|
3457
|
+
return "No memories yet.";
|
|
3296
3458
|
}
|
|
3297
3459
|
function createMemoryUserPage() {
|
|
3298
3460
|
return {
|
|
3299
3461
|
id: "memories",
|
|
3300
3462
|
label: "Memories",
|
|
3301
3463
|
navigation: "primary",
|
|
3302
|
-
description: "Personal
|
|
3464
|
+
description: "Personal and public memories Junior can use across conversations.",
|
|
3303
3465
|
async read(ctx, input) {
|
|
3304
3466
|
const memories = createViewerMemories(
|
|
3305
3467
|
ctx.db,
|
|
@@ -3317,7 +3479,7 @@ function createMemoryUserPage() {
|
|
|
3317
3479
|
...page.nextCursor ? { nextCursor: page.nextCursor } : {},
|
|
3318
3480
|
searchPlaceholder: "Search memories",
|
|
3319
3481
|
records: page.memories.map((memory) => ({
|
|
3320
|
-
actions: [
|
|
3482
|
+
actions: memory.visibility === "private" ? [
|
|
3321
3483
|
{
|
|
3322
3484
|
confirmation: "Forget this memory?",
|
|
3323
3485
|
href: `/api/plugins/memory/memories/${encodeURIComponent(memory.id)}`,
|
|
@@ -3325,14 +3487,17 @@ function createMemoryUserPage() {
|
|
|
3325
3487
|
method: "DELETE",
|
|
3326
3488
|
tone: "danger"
|
|
3327
3489
|
}
|
|
3328
|
-
],
|
|
3490
|
+
] : [],
|
|
3329
3491
|
id: memory.id,
|
|
3330
3492
|
title: memory.content,
|
|
3331
3493
|
metadata: [
|
|
3332
3494
|
{ label: "Type", value: titleCase(memory.kind) },
|
|
3333
3495
|
{ label: "Learned", value: originLabel(memory.origin) },
|
|
3334
3496
|
{ label: "Source", value: titleCase(memory.sourcePlatform) },
|
|
3335
|
-
{
|
|
3497
|
+
{
|
|
3498
|
+
label: "Visibility",
|
|
3499
|
+
value: visibilityLabel(memory.visibility)
|
|
3500
|
+
},
|
|
3336
3501
|
{ label: "Remembered", value: rememberedDate(memory.createdAtMs) },
|
|
3337
3502
|
{ label: "Observed", value: rememberedDate(memory.observedAtMs) },
|
|
3338
3503
|
{
|
|
@@ -3398,7 +3563,11 @@ function memoryPlugin(options = {}) {
|
|
|
3398
3563
|
},
|
|
3399
3564
|
model: modelId ? { structuredModelId: modelId } : { structuredModel: "default" },
|
|
3400
3565
|
packageName: "@sentry/junior-memory",
|
|
3401
|
-
conversationEvents: [
|
|
3566
|
+
conversationEvents: [
|
|
3567
|
+
memoriesCapturedEventV1,
|
|
3568
|
+
memoriesCapturedEvent,
|
|
3569
|
+
memoriesRecalledEvent
|
|
3570
|
+
],
|
|
3402
3571
|
cli: {
|
|
3403
3572
|
commands: [createMemoryCliCommand()]
|
|
3404
3573
|
},
|
|
@@ -3412,15 +3581,21 @@ function memoryPlugin(options = {}) {
|
|
|
3412
3581
|
userPages: [createMemoryUserPage()],
|
|
3413
3582
|
hooks: {
|
|
3414
3583
|
async operationalReport(ctx) {
|
|
3584
|
+
const extractionDays = await ctx.eventStats.costsByDay({
|
|
3585
|
+
days: 90,
|
|
3586
|
+
eventName: "memories_captured"
|
|
3587
|
+
});
|
|
3415
3588
|
return await buildMemoryOperationalReport({
|
|
3416
3589
|
db: ctx.db,
|
|
3590
|
+
extractionDays,
|
|
3417
3591
|
nowMs: ctx.nowMs
|
|
3418
3592
|
});
|
|
3419
3593
|
},
|
|
3420
3594
|
apiRoutes(ctx) {
|
|
3421
3595
|
return createMemoryApi({
|
|
3422
3596
|
actors: ctx.viewer.actors,
|
|
3423
|
-
db: ctx.db
|
|
3597
|
+
db: ctx.db,
|
|
3598
|
+
eventStats: ctx.eventStats
|
|
3424
3599
|
});
|
|
3425
3600
|
},
|
|
3426
3601
|
tools(ctx) {
|
|
@@ -3453,6 +3628,7 @@ function memoryPlugin(options = {}) {
|
|
|
3453
3628
|
...ctx.actor ? { actor: ctx.actor } : {},
|
|
3454
3629
|
db: ctx.db,
|
|
3455
3630
|
embedder: ctx.embedder,
|
|
3631
|
+
events: ctx.events,
|
|
3456
3632
|
log: ctx.log,
|
|
3457
3633
|
maxVectorDistance: recallMaxVectorDistance(options),
|
|
3458
3634
|
source: ctx.source,
|