@sentry/junior-memory 0.180.0 → 0.181.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 +25 -24
- package/dist/agent.d.ts +4 -0
- package/dist/api.d.ts +3 -4
- package/dist/db/schema.d.ts +19 -2
- package/dist/events.d.ts +3 -3
- package/dist/index.js +487 -666
- package/dist/index.js.map +1 -1
- package/dist/process-session.d.ts +3 -4
- package/dist/ranking.d.ts +0 -2
- package/dist/recall.d.ts +9 -2
- package/dist/scope.d.ts +11 -15
- package/dist/store.d.ts +6 -7
- package/dist/tools.d.ts +8 -1
- package/dist/types.d.ts +4 -2
- package/dist/user-pages.d.ts +1 -1
- package/dist/viewer.d.ts +85 -0
- package/migrations/0009_faithful_whizzer.sql +114 -0
- package/migrations/meta/0009_snapshot.json +411 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +2 -2
- package/src/agent.ts +6 -8
- package/src/api.ts +33 -24
- package/src/db/schema.ts +3 -1
- package/src/events.ts +30 -8
- package/src/operational-report.ts +20 -20
- package/src/plugin.ts +13 -1
- package/src/process-session.ts +21 -35
- package/src/ranking.ts +9 -26
- package/src/recall.ts +11 -1
- package/src/scope.ts +34 -135
- package/src/store.ts +34 -91
- package/src/tools.ts +30 -14
- package/src/types.ts +5 -2
- package/src/user-pages.ts +4 -6
- package/src/viewer.ts +393 -0
- package/dist/personal-store.d.ts +0 -92
- package/dist/personal.d.ts +0 -31
- package/src/personal-store.ts +0 -421
- package/src/personal.ts +0 -140
|
@@ -2,9 +2,8 @@ import { type PluginTaskContext } from "@sentry/junior-plugin-api";
|
|
|
2
2
|
/**
|
|
3
3
|
* Extract and store memories from a completed session plugin task.
|
|
4
4
|
*
|
|
5
|
-
* Memory owns
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* or private conversations.
|
|
5
|
+
* Memory owns learning after a run and reads only the plugin run data.
|
|
6
|
+
* Explicit memory tools stay separate so retries do not reinterpret user
|
|
7
|
+
* requests.
|
|
9
8
|
*/
|
|
10
9
|
export declare function processMemorySession(context: PluginTaskContext): Promise<void>;
|
package/dist/ranking.d.ts
CHANGED
|
@@ -4,14 +4,12 @@ export interface MemoryMatch {
|
|
|
4
4
|
rank: number;
|
|
5
5
|
};
|
|
6
6
|
memory: MemoryRecord;
|
|
7
|
-
sourceKey: string;
|
|
8
7
|
vector?: {
|
|
9
8
|
rank: number;
|
|
10
9
|
};
|
|
11
10
|
}
|
|
12
11
|
/** Fuse lexical and vector ranks without comparing provider raw scores. */
|
|
13
12
|
export declare function rankMemoryMatches(matches: MemoryMatch[], options: {
|
|
14
|
-
channelPrefix?: string;
|
|
15
13
|
/** Optional RRF weight for the lexical leg. Defaults to 1. */
|
|
16
14
|
lexicalWeight?: number;
|
|
17
15
|
nowMs: number;
|
package/dist/recall.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type UserPromptContribution, type Actor, type PluginConversationEvents, type PluginLogger, type Source } from "@sentry/junior-plugin-api";
|
|
1
|
+
import { type UserPromptContribution, type Actor, type Identity, type PluginConversationEvents, type PluginLogger, type Source, type User } from "@sentry/junior-plugin-api";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import type { MemoryAgent } from "./agent";
|
|
4
4
|
import { type MemoryDb, type MemoryEmbeddingProvider } from "./store";
|
|
@@ -9,9 +9,16 @@ export interface MemoryRecallContext {
|
|
|
9
9
|
embedder?: MemoryEmbeddingProvider;
|
|
10
10
|
events?: PluginConversationEvents;
|
|
11
11
|
log: PluginLogger;
|
|
12
|
+
locationId?: string;
|
|
12
13
|
actor?: Actor;
|
|
13
14
|
source: Source;
|
|
14
15
|
text: string;
|
|
16
|
+
users: {
|
|
17
|
+
resolveActor(): Promise<{
|
|
18
|
+
identity: Identity;
|
|
19
|
+
user?: User;
|
|
20
|
+
} | undefined>;
|
|
21
|
+
};
|
|
15
22
|
}
|
|
16
23
|
/** Structured snapshot retained for one automatic memory recall. */
|
|
17
24
|
export declare const memoryRecallContextSchema: z.ZodObject<{
|
|
@@ -20,8 +27,8 @@ export declare const memoryRecallContextSchema: z.ZodObject<{
|
|
|
20
27
|
content: z.ZodString;
|
|
21
28
|
observedAtMs: z.ZodNumber;
|
|
22
29
|
scope: z.ZodEnum<{
|
|
23
|
-
personal: "personal";
|
|
24
30
|
conversation: "conversation";
|
|
31
|
+
personal: "personal";
|
|
25
32
|
}>;
|
|
26
33
|
kind: z.ZodEnum<{
|
|
27
34
|
preference: "preference";
|
package/dist/scope.d.ts
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
import { type Identity } from "@sentry/junior-plugin-api";
|
|
2
1
|
import type { MemoryRuntimeContext, MemoryScope, MemorySubjectType } from "./types";
|
|
3
|
-
/**
|
|
2
|
+
/** Stored memory access rule. */
|
|
4
3
|
export interface ResolvedMemoryScope {
|
|
5
4
|
scope: MemoryScope;
|
|
6
5
|
scopeKey: string;
|
|
7
6
|
}
|
|
8
|
-
/**
|
|
7
|
+
/** What a stored memory is about. */
|
|
9
8
|
export interface ResolvedMemorySubject {
|
|
10
|
-
subjectKey
|
|
11
|
-
subjectType: MemorySubjectType
|
|
9
|
+
subjectKey: string;
|
|
10
|
+
subjectType: Extract<MemorySubjectType, "user" | "conversation">;
|
|
12
11
|
}
|
|
13
|
-
/**
|
|
14
|
-
export declare
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/** Derive the memory subject from the already-authorized write scope. */
|
|
21
|
-
export declare function deriveMemorySubject(ctx: MemoryRuntimeContext, scope: ResolvedMemoryScope): ResolvedMemorySubject;
|
|
22
|
-
/** Return every visible scope for memory retrieval in the current context. */
|
|
12
|
+
/** Public memories are visible everywhere. */
|
|
13
|
+
export declare const publicMemoryScope: ResolvedMemoryScope;
|
|
14
|
+
/** Set memory access from the Source. */
|
|
15
|
+
export declare function deriveMemoryScope(ctx: MemoryRuntimeContext): ResolvedMemoryScope;
|
|
16
|
+
/** Set what a memory is about. Access is set separately. */
|
|
17
|
+
export declare function deriveMemorySubject(ctx: MemoryRuntimeContext, subjectType: Extract<MemorySubjectType, "user" | "conversation">): ResolvedMemorySubject;
|
|
18
|
+
/** Return the memory scopes that the current User can access. */
|
|
23
19
|
export declare function deriveVisibleMemoryScopes(ctx: MemoryRuntimeContext): ResolvedMemoryScope[];
|
package/dist/store.d.ts
CHANGED
|
@@ -39,8 +39,8 @@ declare const memoryRecordSchema: z.ZodObject<{
|
|
|
39
39
|
id: z.ZodString;
|
|
40
40
|
observedAtMs: z.ZodNumber;
|
|
41
41
|
scope: z.ZodEnum<{
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
public: "public";
|
|
43
|
+
private: "private";
|
|
44
44
|
}>;
|
|
45
45
|
subjectType: z.ZodEnum<{
|
|
46
46
|
user: "user";
|
|
@@ -67,6 +67,7 @@ export declare const memorySupersessionInputSchema: z.ZodObject<{
|
|
|
67
67
|
}, z.core.$strict>>;
|
|
68
68
|
runtimeContext: z.ZodObject<{
|
|
69
69
|
conversationId: z.ZodOptional<z.ZodString>;
|
|
70
|
+
locationId: z.ZodOptional<z.ZodString>;
|
|
70
71
|
actor: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
71
72
|
platform: z.ZodLiteral<"slack">;
|
|
72
73
|
teamId: z.ZodString;
|
|
@@ -112,6 +113,7 @@ export declare const memorySupersessionInputSchema: z.ZodObject<{
|
|
|
112
113
|
}>;
|
|
113
114
|
conversationId: z.ZodString;
|
|
114
115
|
}, z.core.$strict>], "platform">;
|
|
116
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
115
117
|
}, z.core.$strict>;
|
|
116
118
|
}, z.core.$strict>;
|
|
117
119
|
/**
|
|
@@ -177,14 +179,12 @@ export interface MemoryStore {
|
|
|
177
179
|
archiveExpiredMemories(input?: ArchiveExpiredMemoriesInput): Promise<ArchiveExpiredMemoriesResult>;
|
|
178
180
|
/** Archive a visible memory in the current runtime context. */
|
|
179
181
|
archiveMemory(input: ArchiveMemoryInput): Promise<MemoryRecord>;
|
|
180
|
-
/** Store a
|
|
182
|
+
/** Store a memory about the current User. The Source sets access. */
|
|
181
183
|
createMemory(input: CreateMemoryInput): Promise<CreateMemoryResult>;
|
|
182
|
-
/** Store a
|
|
184
|
+
/** Store a memory about the current Conversation. The Source sets access. */
|
|
183
185
|
createConversationMemory(input: CreateMemoryInput): Promise<CreateMemoryResult>;
|
|
184
186
|
/** List active memories visible in the current runtime context. */
|
|
185
187
|
listMemories(input: ListMemoriesInput): Promise<MemoryRecord[]>;
|
|
186
|
-
/** List active personal memories owned by the current actor. */
|
|
187
|
-
listPersonalMemories(input: ListMemoriesInput): Promise<MemoryRecord[]>;
|
|
188
188
|
/**
|
|
189
189
|
* Retrieve a broad relevance-ranked candidate window for automatic recall.
|
|
190
190
|
* Prompt admission remains owned by the recall boundary.
|
|
@@ -193,7 +193,6 @@ export interface MemoryStore {
|
|
|
193
193
|
/** Search active memories visible in the current runtime context. */
|
|
194
194
|
searchMemories(input: SearchMemoriesInput): Promise<MemoryRecord[]>;
|
|
195
195
|
}
|
|
196
|
-
/** Parse one SQL row into the public memory record projection. */
|
|
197
196
|
/** Parse one SQL row into the public memory projection. */
|
|
198
197
|
export declare function parseMemoryRow(row: unknown): MemoryRecord;
|
|
199
198
|
/** Build the active-row predicate for already-authorized memory scopes. */
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Source, type Actor } from "@sentry/junior-plugin-api";
|
|
1
|
+
import { type Source, type Actor, type Identity, type User } from "@sentry/junior-plugin-api";
|
|
2
2
|
import { type MemoryEmbeddingProvider, type MemoryDb, type MemorySupersessionDecider } from "./store";
|
|
3
3
|
import { type MemoryAgent } from "./agent";
|
|
4
4
|
export type MemoryReviewer = Pick<MemoryAgent, "reviewCreateRequest">;
|
|
@@ -8,8 +8,15 @@ export interface MemoryToolContext {
|
|
|
8
8
|
conversationId?: string;
|
|
9
9
|
db: MemoryDb;
|
|
10
10
|
embedder?: MemoryEmbeddingProvider;
|
|
11
|
+
locationId?: string;
|
|
11
12
|
actor?: Actor;
|
|
12
13
|
source: Source;
|
|
14
|
+
users: {
|
|
15
|
+
resolveActor(): Promise<{
|
|
16
|
+
identity: Identity;
|
|
17
|
+
user?: User;
|
|
18
|
+
} | undefined>;
|
|
19
|
+
};
|
|
13
20
|
userText?: string;
|
|
14
21
|
}
|
|
15
22
|
export interface MemoryCreateToolContext extends MemoryToolContext {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export declare const MEMORY_KINDS: readonly ["preference", "procedure", "knowledge"];
|
|
3
|
-
export declare const MEMORY_SCOPES: readonly ["
|
|
3
|
+
export declare const MEMORY_SCOPES: readonly ["private", "public"];
|
|
4
4
|
export declare const MEMORY_SUBJECT_TYPES: readonly ["user", "conversation", "general"];
|
|
5
5
|
export declare const MEMORY_SOURCE_PLATFORMS: readonly ["slack", "local", "web"];
|
|
6
6
|
export declare const MEMORY_EMBEDDING_METRICS: readonly ["cosine"];
|
|
@@ -10,9 +10,10 @@ export type MemoryScope = (typeof MEMORY_SCOPES)[number];
|
|
|
10
10
|
export type MemorySubjectType = (typeof MEMORY_SUBJECT_TYPES)[number];
|
|
11
11
|
export type MemorySourcePlatform = (typeof MEMORY_SOURCE_PLATFORMS)[number];
|
|
12
12
|
export type MemoryEmbeddingMetric = (typeof MEMORY_EMBEDDING_METRICS)[number];
|
|
13
|
-
/**
|
|
13
|
+
/** Host data used to set memory access, subject, and source. */
|
|
14
14
|
export declare const memoryRuntimeContextSchema: z.ZodObject<{
|
|
15
15
|
conversationId: z.ZodOptional<z.ZodString>;
|
|
16
|
+
locationId: z.ZodOptional<z.ZodString>;
|
|
16
17
|
actor: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
17
18
|
platform: z.ZodLiteral<"slack">;
|
|
18
19
|
teamId: z.ZodString;
|
|
@@ -58,5 +59,6 @@ export declare const memoryRuntimeContextSchema: z.ZodObject<{
|
|
|
58
59
|
}>;
|
|
59
60
|
conversationId: z.ZodString;
|
|
60
61
|
}, z.core.$strict>], "platform">;
|
|
62
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
61
63
|
}, z.core.$strict>;
|
|
62
64
|
export type MemoryRuntimeContext = z.output<typeof memoryRuntimeContextSchema>;
|
package/dist/user-pages.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Render memory in Junior's User page format. */
|
|
2
2
|
import type { PluginUserPageDefinition } from "@sentry/junior-plugin-api";
|
|
3
3
|
/** Create the interactive Memories dashboard page. */
|
|
4
4
|
export declare function createMemoryUserPage(): PluginUserPageDefinition;
|
package/dist/viewer.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type MemoryDb, type MemoryRecord } from "./store";
|
|
3
|
+
import { type MemorySourcePlatform } from "./types";
|
|
4
|
+
declare const memoryVisibilitySchema: z.ZodEnum<{
|
|
5
|
+
public: "public";
|
|
6
|
+
private: "private";
|
|
7
|
+
}>;
|
|
8
|
+
declare const pageInputSchema: z.ZodObject<{
|
|
9
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
10
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
11
|
+
preference: "preference";
|
|
12
|
+
procedure: "procedure";
|
|
13
|
+
knowledge: "knowledge";
|
|
14
|
+
}>>;
|
|
15
|
+
limit: z.ZodNumber;
|
|
16
|
+
origin: z.ZodOptional<z.ZodEnum<{
|
|
17
|
+
automatic: "automatic";
|
|
18
|
+
explicit: "explicit";
|
|
19
|
+
}>>;
|
|
20
|
+
query: z.ZodOptional<z.ZodString>;
|
|
21
|
+
visibility: z.ZodOptional<z.ZodEnum<{
|
|
22
|
+
public: "public";
|
|
23
|
+
private: "private";
|
|
24
|
+
}>>;
|
|
25
|
+
}, z.core.$strict>;
|
|
26
|
+
/** Access label returned by dashboard and REST memory views. */
|
|
27
|
+
export type MemoryVisibility = z.output<typeof memoryVisibilitySchema>;
|
|
28
|
+
/** Memory fields returned to an authenticated User. */
|
|
29
|
+
export type MemoryView = MemoryRecord & {
|
|
30
|
+
origin: "automatic" | "explicit" | "other";
|
|
31
|
+
sourcePlatform: MemorySourcePlatform;
|
|
32
|
+
visibility: MemoryVisibility;
|
|
33
|
+
};
|
|
34
|
+
interface MemoryPage {
|
|
35
|
+
memories: MemoryView[];
|
|
36
|
+
nextCursor?: string;
|
|
37
|
+
}
|
|
38
|
+
type MemoryPageInput = z.output<typeof pageInputSchema>;
|
|
39
|
+
/** Expected error for a malformed or mismatched page cursor. */
|
|
40
|
+
export declare class InvalidMemoryCursorError extends Error {
|
|
41
|
+
constructor();
|
|
42
|
+
}
|
|
43
|
+
/** Expected error when the current User cannot access a memory. */
|
|
44
|
+
export declare class MemoryNotFoundError extends Error {
|
|
45
|
+
constructor();
|
|
46
|
+
}
|
|
47
|
+
/** Archive one active private memory owned by the authenticated User. */
|
|
48
|
+
export declare function archiveMemory(db: MemoryDb, userId: string, id: string): Promise<{
|
|
49
|
+
content: string;
|
|
50
|
+
createdAtMs: number;
|
|
51
|
+
id: string;
|
|
52
|
+
observedAtMs: number;
|
|
53
|
+
scope: "public" | "private";
|
|
54
|
+
subjectType: "user" | "conversation" | "general";
|
|
55
|
+
kind: "preference" | "procedure" | "knowledge";
|
|
56
|
+
archivedAtMs?: number | undefined;
|
|
57
|
+
archiveReason?: string | undefined;
|
|
58
|
+
expiresAtMs?: number | undefined;
|
|
59
|
+
supersededAtMs?: number | undefined;
|
|
60
|
+
supersededById?: string | undefined;
|
|
61
|
+
}>;
|
|
62
|
+
/** Read one active memory visible to the authenticated User. */
|
|
63
|
+
export declare function getMemory(db: MemoryDb, userId: string, id: string): Promise<MemoryView>;
|
|
64
|
+
/** List one stable page of active memory visible to the authenticated User. */
|
|
65
|
+
export declare function listMemories(db: MemoryDb, userId: string, input: MemoryPageInput): Promise<MemoryPage>;
|
|
66
|
+
/** Summarize active memory visible to the authenticated User. */
|
|
67
|
+
export declare function getMemoryStats(db: MemoryDb, userId: string): Promise<{
|
|
68
|
+
active: number;
|
|
69
|
+
automatic: number;
|
|
70
|
+
createdThirtyDays: number;
|
|
71
|
+
embedded: number;
|
|
72
|
+
explicit: number;
|
|
73
|
+
knowledge: number;
|
|
74
|
+
private: number;
|
|
75
|
+
preference: number;
|
|
76
|
+
procedure: number;
|
|
77
|
+
public: number;
|
|
78
|
+
}>;
|
|
79
|
+
/** Read daily memory creation totals visible to the authenticated User in UTC. */
|
|
80
|
+
export declare function getMemoryTimeline(db: MemoryDb, userId: string, days: number): Promise<{
|
|
81
|
+
date: string;
|
|
82
|
+
private: number;
|
|
83
|
+
public: number;
|
|
84
|
+
}[]>;
|
|
85
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
ALTER TABLE "junior_memory_memories" DROP CONSTRAINT "junior_memory_memories_scope_check";--> statement-breakpoint
|
|
2
|
+
ALTER TABLE "junior_memory_memories" ADD COLUMN "location_id" text;--> statement-breakpoint
|
|
3
|
+
CREATE TEMP TABLE junior_memory_legacy_owners (
|
|
4
|
+
id text PRIMARY KEY,
|
|
5
|
+
user_id text NOT NULL
|
|
6
|
+
) ON COMMIT DROP;--> statement-breakpoint
|
|
7
|
+
DO $$
|
|
8
|
+
BEGIN
|
|
9
|
+
IF to_regclass('junior_identities') IS NOT NULL THEN
|
|
10
|
+
EXECUTE $migration$
|
|
11
|
+
INSERT INTO junior_memory_legacy_owners (id, user_id)
|
|
12
|
+
SELECT memory.id, owner.user_id
|
|
13
|
+
FROM junior_memory_memories AS memory
|
|
14
|
+
INNER JOIN LATERAL (
|
|
15
|
+
SELECT identity.user_id
|
|
16
|
+
FROM junior_identities AS identity
|
|
17
|
+
WHERE identity.user_id IS NOT NULL
|
|
18
|
+
AND (
|
|
19
|
+
(
|
|
20
|
+
memory.scope_key LIKE 'slack:%'
|
|
21
|
+
AND identity.provider = 'slack'
|
|
22
|
+
AND identity.provider_tenant_id = split_part(memory.scope_key, ':', 2)
|
|
23
|
+
AND identity.provider_subject_id = split_part(memory.scope_key, ':', 3)
|
|
24
|
+
)
|
|
25
|
+
OR (
|
|
26
|
+
memory.scope_key LIKE 'local:%'
|
|
27
|
+
AND identity.provider = 'local'
|
|
28
|
+
AND identity.provider_subject_id = substring(memory.scope_key FROM 7)
|
|
29
|
+
)
|
|
30
|
+
OR (
|
|
31
|
+
memory.scope_key LIKE 'junior:%'
|
|
32
|
+
AND identity.provider = 'junior'
|
|
33
|
+
AND identity.provider_subject_id = substring(memory.scope_key FROM 8)
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
ORDER BY identity.id
|
|
37
|
+
LIMIT 1
|
|
38
|
+
) AS owner ON memory.scope = 'personal'
|
|
39
|
+
$migration$;
|
|
40
|
+
END IF;
|
|
41
|
+
END
|
|
42
|
+
$$;--> statement-breakpoint
|
|
43
|
+
CREATE TEMP TABLE junior_memory_scope_targets ON COMMIT DROP AS
|
|
44
|
+
SELECT
|
|
45
|
+
memory.id,
|
|
46
|
+
CASE
|
|
47
|
+
WHEN memory.scope = 'conversation'
|
|
48
|
+
AND memory.source_platform = 'slack'
|
|
49
|
+
AND memory.scope_key = 'slack:' || split_part(memory.source_key, ':', 2)
|
|
50
|
+
THEN 'public'
|
|
51
|
+
ELSE 'private'
|
|
52
|
+
END AS target_scope,
|
|
53
|
+
CASE
|
|
54
|
+
WHEN memory.scope = 'conversation'
|
|
55
|
+
AND memory.source_platform = 'slack'
|
|
56
|
+
AND memory.scope_key = 'slack:' || split_part(memory.source_key, ':', 2)
|
|
57
|
+
THEN 'public'
|
|
58
|
+
WHEN memory.scope = 'personal' AND owner.user_id IS NOT NULL
|
|
59
|
+
THEN owner.user_id
|
|
60
|
+
ELSE 'legacy-unowned:' || memory.id
|
|
61
|
+
END AS target_scope_key,
|
|
62
|
+
(
|
|
63
|
+
memory.scope <> 'personal' AND NOT (
|
|
64
|
+
memory.scope = 'conversation'
|
|
65
|
+
AND memory.source_platform = 'slack'
|
|
66
|
+
AND memory.scope_key = 'slack:' || split_part(memory.source_key, ':', 2)
|
|
67
|
+
)
|
|
68
|
+
) OR (memory.scope = 'personal' AND owner.user_id IS NULL) AS archive_unowned
|
|
69
|
+
FROM junior_memory_memories AS memory
|
|
70
|
+
LEFT JOIN junior_memory_legacy_owners AS owner ON owner.id = memory.id;--> statement-breakpoint
|
|
71
|
+
WITH duplicate_targets AS (
|
|
72
|
+
SELECT
|
|
73
|
+
memory.id,
|
|
74
|
+
row_number() OVER (
|
|
75
|
+
PARTITION BY target.target_scope, target.target_scope_key, memory.idempotency_key
|
|
76
|
+
ORDER BY memory.id
|
|
77
|
+
) AS duplicate_rank
|
|
78
|
+
FROM junior_memory_memories AS memory
|
|
79
|
+
INNER JOIN junior_memory_scope_targets AS target ON target.id = memory.id
|
|
80
|
+
WHERE memory.idempotency_key IS NOT NULL
|
|
81
|
+
AND memory.archived_at_ms IS NULL
|
|
82
|
+
AND memory.superseded_at_ms IS NULL
|
|
83
|
+
AND memory.superseded_by_id IS NULL
|
|
84
|
+
AND NOT target.archive_unowned
|
|
85
|
+
)
|
|
86
|
+
UPDATE junior_memory_memories AS memory
|
|
87
|
+
SET idempotency_key = 'legacy-scope:' || memory.id
|
|
88
|
+
FROM duplicate_targets
|
|
89
|
+
WHERE memory.id = duplicate_targets.id
|
|
90
|
+
AND duplicate_targets.duplicate_rank > 1;--> statement-breakpoint
|
|
91
|
+
UPDATE junior_memory_memories AS memory
|
|
92
|
+
SET
|
|
93
|
+
scope = target.target_scope,
|
|
94
|
+
scope_key = target.target_scope_key,
|
|
95
|
+
subject_key = CASE
|
|
96
|
+
WHEN memory.subject_type = 'user' AND target.target_scope = 'private'
|
|
97
|
+
THEN target.target_scope_key
|
|
98
|
+
ELSE memory.subject_key
|
|
99
|
+
END,
|
|
100
|
+
archived_at_ms = CASE
|
|
101
|
+
WHEN target.archive_unowned
|
|
102
|
+
THEN coalesce(memory.archived_at_ms, floor(extract(epoch FROM clock_timestamp()) * 1000)::bigint)
|
|
103
|
+
ELSE memory.archived_at_ms
|
|
104
|
+
END,
|
|
105
|
+
archive_reason = CASE
|
|
106
|
+
WHEN target.archive_unowned
|
|
107
|
+
THEN coalesce(memory.archive_reason, 'legacy_unowned_scope')
|
|
108
|
+
ELSE memory.archive_reason
|
|
109
|
+
END
|
|
110
|
+
FROM junior_memory_scope_targets AS target
|
|
111
|
+
WHERE memory.id = target.id;--> statement-breakpoint
|
|
112
|
+
DROP TABLE junior_memory_scope_targets;--> statement-breakpoint
|
|
113
|
+
DROP TABLE junior_memory_legacy_owners;--> statement-breakpoint
|
|
114
|
+
ALTER TABLE "junior_memory_memories" ADD CONSTRAINT "junior_memory_memories_scope_check" CHECK ("junior_memory_memories"."scope" IN ('private', 'public'));
|