strapi-content-embeddings 0.1.4 → 0.1.6
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 +187 -0
- package/dist/_chunks/{App-4UwemHRe.mjs → App-C5NFY1UT.mjs} +287 -103
- package/dist/_chunks/{App-CnXhqiao.js → App-CA5bQnKQ.js} +286 -102
- package/dist/_chunks/{index-BWSiu_nE.mjs → index-CIpGvEcJ.mjs} +122 -104
- package/dist/_chunks/{index-BaPVw3mi.js → index-CVCA8dDp.js} +119 -101
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/custom/EmbeddingsTable.d.ts +1 -1
- package/dist/admin/src/components/custom/MarkdownEditor.d.ts +1 -1
- package/dist/server/index.js +1137 -84
- package/dist/server/index.mjs +1137 -84
- package/dist/server/src/config/index.d.ts +9 -0
- package/dist/server/src/controllers/controller.d.ts +32 -0
- package/dist/server/src/controllers/index.d.ts +5 -0
- package/dist/server/src/index.d.ts +42 -2
- package/dist/server/src/mcp/tools/create-embedding.d.ts +6 -0
- package/dist/server/src/mcp/tools/index.d.ts +4 -0
- package/dist/server/src/plugin-manager.d.ts +32 -0
- package/dist/server/src/routes/content-api.d.ts +10 -0
- package/dist/server/src/routes/index.d.ts +10 -0
- package/dist/server/src/services/embeddings.d.ts +43 -2
- package/dist/server/src/services/index.d.ts +24 -2
- package/dist/server/src/services/sync.d.ts +71 -0
- package/dist/server/src/utils/chunking.d.ts +44 -0
- package/package.json +1 -1
|
@@ -14,12 +14,21 @@ export interface PluginConfigSchema {
|
|
|
14
14
|
openAIApiKey?: string;
|
|
15
15
|
neonConnectionString?: string;
|
|
16
16
|
embeddingModel?: EmbeddingModelName;
|
|
17
|
+
/** Maximum characters per chunk (default: 4000, roughly ~1000 tokens) */
|
|
18
|
+
chunkSize?: number;
|
|
19
|
+
/** Number of characters to overlap between chunks (default: 200) */
|
|
20
|
+
chunkOverlap?: number;
|
|
21
|
+
/** Automatically chunk content that exceeds chunkSize (default: false) */
|
|
22
|
+
autoChunk?: boolean;
|
|
17
23
|
}
|
|
18
24
|
declare const _default: {
|
|
19
25
|
default: {
|
|
20
26
|
openAIApiKey: string;
|
|
21
27
|
neonConnectionString: string;
|
|
22
28
|
embeddingModel: "text-embedding-3-small" | "text-embedding-3-large" | "text-embedding-ada-002";
|
|
29
|
+
chunkSize: number;
|
|
30
|
+
chunkOverlap: number;
|
|
31
|
+
autoChunk: boolean;
|
|
23
32
|
};
|
|
24
33
|
validator(config: PluginConfigSchema): void;
|
|
25
34
|
};
|
|
@@ -8,5 +8,37 @@ declare const controller: ({ strapi }: {
|
|
|
8
8
|
getEmbeddings(ctx: any): Promise<void>;
|
|
9
9
|
getEmbedding(ctx: any): Promise<void>;
|
|
10
10
|
queryEmbeddings(ctx: any): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Get all chunks related to a document
|
|
13
|
+
* GET /api/strapi-content-embeddings/embeddings/related-chunks/:id
|
|
14
|
+
*/
|
|
15
|
+
getRelatedChunks(ctx: any): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Sync embeddings from Neon DB to Strapi DB
|
|
18
|
+
* GET /api/strapi-content-embeddings/sync
|
|
19
|
+
*
|
|
20
|
+
* Query params:
|
|
21
|
+
* - removeOrphans: boolean (default: false) - Remove Strapi entries that don't exist in Neon
|
|
22
|
+
* - dryRun: boolean (default: false) - Preview changes without applying them
|
|
23
|
+
*/
|
|
24
|
+
syncFromNeon(ctx: any): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Get sync status - compare Neon and Strapi without making changes
|
|
27
|
+
* GET /api/strapi-content-embeddings/sync/status
|
|
28
|
+
*/
|
|
29
|
+
getSyncStatus(ctx: any): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Debug endpoint to inspect Neon DB contents
|
|
32
|
+
* GET /api/strapi-content-embeddings/debug/neon
|
|
33
|
+
*/
|
|
34
|
+
debugNeon(ctx: any): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Recreate all embeddings in Neon from Strapi data
|
|
37
|
+
* POST /api/strapi-content-embeddings/recreate
|
|
38
|
+
*
|
|
39
|
+
* Use this when embeddings were created with incorrect metadata format
|
|
40
|
+
* WARNING: This will delete ALL existing Neon embeddings and recreate them
|
|
41
|
+
*/
|
|
42
|
+
recreateEmbeddings(ctx: any): Promise<void>;
|
|
11
43
|
};
|
|
12
44
|
export default controller;
|
|
@@ -8,6 +8,11 @@ declare const _default: {
|
|
|
8
8
|
getEmbeddings(ctx: any): Promise<void>;
|
|
9
9
|
getEmbedding(ctx: any): Promise<void>;
|
|
10
10
|
queryEmbeddings(ctx: any): Promise<void>;
|
|
11
|
+
getRelatedChunks(ctx: any): Promise<void>;
|
|
12
|
+
syncFromNeon(ctx: any): Promise<void>;
|
|
13
|
+
getSyncStatus(ctx: any): Promise<void>;
|
|
14
|
+
debugNeon(ctx: any): Promise<void>;
|
|
15
|
+
recreateEmbeddings(ctx: any): Promise<void>;
|
|
11
16
|
};
|
|
12
17
|
mcp: ({ strapi }: {
|
|
13
18
|
strapi: import("@strapi/types/dist/core").Strapi;
|
|
@@ -13,6 +13,9 @@ declare const _default: {
|
|
|
13
13
|
openAIApiKey: string;
|
|
14
14
|
neonConnectionString: string;
|
|
15
15
|
embeddingModel: "text-embedding-3-small" | "text-embedding-3-large" | "text-embedding-ada-002";
|
|
16
|
+
chunkSize: number;
|
|
17
|
+
chunkOverlap: number;
|
|
18
|
+
autoChunk: boolean;
|
|
16
19
|
};
|
|
17
20
|
validator(config: import("./config").PluginConfigSchema): void;
|
|
18
21
|
};
|
|
@@ -26,6 +29,11 @@ declare const _default: {
|
|
|
26
29
|
getEmbeddings(ctx: any): Promise<void>;
|
|
27
30
|
getEmbedding(ctx: any): Promise<void>;
|
|
28
31
|
queryEmbeddings(ctx: any): Promise<void>;
|
|
32
|
+
getRelatedChunks(ctx: any): Promise<void>;
|
|
33
|
+
syncFromNeon(ctx: any): Promise<void>;
|
|
34
|
+
getSyncStatus(ctx: any): Promise<void>;
|
|
35
|
+
debugNeon(ctx: any): Promise<void>;
|
|
36
|
+
recreateEmbeddings(ctx: any): Promise<void>;
|
|
29
37
|
};
|
|
30
38
|
mcp: ({ strapi }: {
|
|
31
39
|
strapi: import("@strapi/types/dist/core").Strapi;
|
|
@@ -41,6 +49,15 @@ declare const _default: {
|
|
|
41
49
|
path: string;
|
|
42
50
|
handler: string;
|
|
43
51
|
config?: undefined;
|
|
52
|
+
} | {
|
|
53
|
+
method: string;
|
|
54
|
+
path: string;
|
|
55
|
+
handler: string;
|
|
56
|
+
config: {
|
|
57
|
+
description: string;
|
|
58
|
+
auth?: undefined;
|
|
59
|
+
policies?: undefined;
|
|
60
|
+
};
|
|
44
61
|
} | {
|
|
45
62
|
method: string;
|
|
46
63
|
path: string;
|
|
@@ -48,6 +65,7 @@ declare const _default: {
|
|
|
48
65
|
config: {
|
|
49
66
|
auth: boolean;
|
|
50
67
|
policies: any[];
|
|
68
|
+
description?: undefined;
|
|
51
69
|
};
|
|
52
70
|
})[];
|
|
53
71
|
};
|
|
@@ -72,12 +90,17 @@ declare const _default: {
|
|
|
72
90
|
embeddings: ({ strapi }: {
|
|
73
91
|
strapi: import("@strapi/types/dist/core").Strapi;
|
|
74
92
|
}) => {
|
|
75
|
-
|
|
93
|
+
getConfig(): import("./config").PluginConfigSchema;
|
|
94
|
+
createEmbedding(data: import("./services/embeddings").CreateEmbeddingData): Promise<any>;
|
|
95
|
+
createChunkedEmbedding(data: import("./services/embeddings").CreateEmbeddingData): Promise<import("./services/embeddings").ChunkedEmbeddingResult>;
|
|
76
96
|
deleteEmbedding(id: string | number): Promise<{
|
|
77
97
|
documentId: string;
|
|
78
98
|
entries: import("@strapi/types/dist/modules/documents").AnyDocument[];
|
|
79
99
|
}>;
|
|
80
|
-
|
|
100
|
+
findRelatedChunks(documentId: string): Promise<any[]>;
|
|
101
|
+
deleteRelatedChunks(documentId: string): Promise<number>;
|
|
102
|
+
updateChunkedEmbedding(id: string, data: import("./services/embeddings").UpdateEmbeddingData): Promise<import("./services/embeddings").ChunkedEmbeddingResult>;
|
|
103
|
+
updateEmbedding(id: string, data: import("./services/embeddings").UpdateEmbeddingData): Promise<any>;
|
|
81
104
|
queryEmbeddings(query: string): Promise<import("./plugin-manager").QueryResponse | {
|
|
82
105
|
error: string;
|
|
83
106
|
}>;
|
|
@@ -92,6 +115,23 @@ declare const _default: {
|
|
|
92
115
|
totalCount: number;
|
|
93
116
|
}>;
|
|
94
117
|
};
|
|
118
|
+
sync: ({ strapi }: {
|
|
119
|
+
strapi: import("@strapi/types/dist/core").Strapi;
|
|
120
|
+
}) => {
|
|
121
|
+
syncFromNeon(options?: {
|
|
122
|
+
removeOrphans?: boolean;
|
|
123
|
+
dryRun?: boolean;
|
|
124
|
+
}): Promise<import("./services/sync").SyncResult>;
|
|
125
|
+
getSyncStatus(): Promise<{
|
|
126
|
+
neonCount: number;
|
|
127
|
+
strapiCount: number;
|
|
128
|
+
inSync: boolean;
|
|
129
|
+
missingInStrapi: number;
|
|
130
|
+
missingInNeon: number;
|
|
131
|
+
contentDifferences: number;
|
|
132
|
+
}>;
|
|
133
|
+
recreateAllEmbeddings(): Promise<import("./services/sync").RecreateResult>;
|
|
134
|
+
};
|
|
95
135
|
};
|
|
96
136
|
contentTypes: {
|
|
97
137
|
embedding: {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Create Embedding Tool
|
|
3
3
|
*
|
|
4
4
|
* Creates a new embedding from text content.
|
|
5
|
+
* Supports automatic chunking for large content.
|
|
5
6
|
*/
|
|
6
7
|
import type { Core } from '@strapi/strapi';
|
|
7
8
|
export declare const createEmbeddingTool: {
|
|
@@ -22,6 +23,10 @@ export declare const createEmbeddingTool: {
|
|
|
22
23
|
type: string;
|
|
23
24
|
description: string;
|
|
24
25
|
};
|
|
26
|
+
autoChunk: {
|
|
27
|
+
type: string;
|
|
28
|
+
description: string;
|
|
29
|
+
};
|
|
25
30
|
};
|
|
26
31
|
required: string[];
|
|
27
32
|
};
|
|
@@ -30,6 +35,7 @@ export declare function handleCreateEmbedding(strapi: Core.Strapi, args: {
|
|
|
30
35
|
title: string;
|
|
31
36
|
content: string;
|
|
32
37
|
metadata?: Record<string, any>;
|
|
38
|
+
autoChunk?: boolean;
|
|
33
39
|
}): Promise<{
|
|
34
40
|
content: {
|
|
35
41
|
type: string;
|
|
@@ -39,7 +39,39 @@ declare class PluginManager {
|
|
|
39
39
|
queryEmbedding(query: string): Promise<QueryResponse>;
|
|
40
40
|
similaritySearch(query: string, k?: number): Promise<Document[]>;
|
|
41
41
|
isInitialized(): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Get all embeddings from Neon DB
|
|
44
|
+
* Returns the metadata (including Strapi documentId) for each embedding
|
|
45
|
+
*/
|
|
46
|
+
getAllNeonEmbeddings(): Promise<Array<{
|
|
47
|
+
id: string;
|
|
48
|
+
strapiId: string;
|
|
49
|
+
title: string;
|
|
50
|
+
content: string;
|
|
51
|
+
collectionType: string;
|
|
52
|
+
fieldName: string;
|
|
53
|
+
}>>;
|
|
54
|
+
/**
|
|
55
|
+
* Delete an embedding from Neon by its Neon UUID (not Strapi ID)
|
|
56
|
+
*/
|
|
57
|
+
deleteNeonEmbeddingById(neonId: string): Promise<void>;
|
|
42
58
|
destroy(): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Clear all embeddings from Neon DB
|
|
61
|
+
* Returns the number of deleted rows
|
|
62
|
+
*/
|
|
63
|
+
clearAllNeonEmbeddings(): Promise<number>;
|
|
64
|
+
/**
|
|
65
|
+
* Debug method to inspect raw data in Neon DB
|
|
66
|
+
*/
|
|
67
|
+
debugNeonEmbeddings(): Promise<Array<{
|
|
68
|
+
id: string;
|
|
69
|
+
content: string;
|
|
70
|
+
metadata: any;
|
|
71
|
+
metadataType: string;
|
|
72
|
+
hasEmbedding: boolean;
|
|
73
|
+
embeddingLength: number;
|
|
74
|
+
}>>;
|
|
43
75
|
}
|
|
44
76
|
export declare const pluginManager: PluginManager;
|
|
45
77
|
export type { PluginConfig, EmbeddingDocument, QueryResponse, CreateEmbeddingResult };
|
|
@@ -3,6 +3,15 @@ declare const _default: ({
|
|
|
3
3
|
path: string;
|
|
4
4
|
handler: string;
|
|
5
5
|
config?: undefined;
|
|
6
|
+
} | {
|
|
7
|
+
method: string;
|
|
8
|
+
path: string;
|
|
9
|
+
handler: string;
|
|
10
|
+
config: {
|
|
11
|
+
description: string;
|
|
12
|
+
auth?: undefined;
|
|
13
|
+
policies?: undefined;
|
|
14
|
+
};
|
|
6
15
|
} | {
|
|
7
16
|
method: string;
|
|
8
17
|
path: string;
|
|
@@ -10,6 +19,7 @@ declare const _default: ({
|
|
|
10
19
|
config: {
|
|
11
20
|
auth: boolean;
|
|
12
21
|
policies: any[];
|
|
22
|
+
description?: undefined;
|
|
13
23
|
};
|
|
14
24
|
})[];
|
|
15
25
|
export default _default;
|
|
@@ -6,6 +6,15 @@ declare const _default: {
|
|
|
6
6
|
path: string;
|
|
7
7
|
handler: string;
|
|
8
8
|
config?: undefined;
|
|
9
|
+
} | {
|
|
10
|
+
method: string;
|
|
11
|
+
path: string;
|
|
12
|
+
handler: string;
|
|
13
|
+
config: {
|
|
14
|
+
description: string;
|
|
15
|
+
auth?: undefined;
|
|
16
|
+
policies?: undefined;
|
|
17
|
+
};
|
|
9
18
|
} | {
|
|
10
19
|
method: string;
|
|
11
20
|
path: string;
|
|
@@ -13,6 +22,7 @@ declare const _default: {
|
|
|
13
22
|
config: {
|
|
14
23
|
auth: boolean;
|
|
15
24
|
policies: any[];
|
|
25
|
+
description?: undefined;
|
|
16
26
|
};
|
|
17
27
|
})[];
|
|
18
28
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Core } from "@strapi/strapi";
|
|
2
|
+
import type { PluginConfigSchema } from "../config";
|
|
2
3
|
export interface CreateEmbeddingData {
|
|
3
4
|
data: {
|
|
4
5
|
title: string;
|
|
@@ -10,6 +11,8 @@ export interface CreateEmbeddingData {
|
|
|
10
11
|
__type: string;
|
|
11
12
|
id: number;
|
|
12
13
|
};
|
|
14
|
+
/** Enable chunking for large content (overrides config.autoChunk) */
|
|
15
|
+
autoChunk?: boolean;
|
|
13
16
|
};
|
|
14
17
|
}
|
|
15
18
|
export interface UpdateEmbeddingData {
|
|
@@ -17,17 +20,55 @@ export interface UpdateEmbeddingData {
|
|
|
17
20
|
title?: string;
|
|
18
21
|
content?: string;
|
|
19
22
|
metadata?: Record<string, any>;
|
|
23
|
+
/** Enable chunking for large content on update (overrides config.autoChunk) */
|
|
24
|
+
autoChunk?: boolean;
|
|
20
25
|
};
|
|
21
26
|
}
|
|
27
|
+
export interface ChunkedEmbeddingResult {
|
|
28
|
+
/** The parent/first embedding entity */
|
|
29
|
+
entity: any;
|
|
30
|
+
/** All chunk entities created */
|
|
31
|
+
chunks: any[];
|
|
32
|
+
/** Total number of chunks created */
|
|
33
|
+
totalChunks: number;
|
|
34
|
+
/** Whether content was chunked */
|
|
35
|
+
wasChunked: boolean;
|
|
36
|
+
}
|
|
22
37
|
declare const embeddings: ({ strapi }: {
|
|
23
38
|
strapi: Core.Strapi;
|
|
24
39
|
}) => {
|
|
25
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Get plugin config with defaults
|
|
42
|
+
*/
|
|
43
|
+
getConfig(): PluginConfigSchema;
|
|
44
|
+
/**
|
|
45
|
+
* Create a single embedding (no chunking)
|
|
46
|
+
*/
|
|
47
|
+
createEmbedding(data: CreateEmbeddingData): Promise<any>;
|
|
48
|
+
/**
|
|
49
|
+
* Create embeddings with automatic chunking for large content
|
|
50
|
+
* Creates multiple embedding entities, one per chunk
|
|
51
|
+
*/
|
|
52
|
+
createChunkedEmbedding(data: CreateEmbeddingData): Promise<ChunkedEmbeddingResult>;
|
|
26
53
|
deleteEmbedding(id: number | string): Promise<{
|
|
27
54
|
documentId: string;
|
|
28
55
|
entries: import("@strapi/types/dist/modules/documents").AnyDocument[];
|
|
29
56
|
}>;
|
|
30
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Find all chunks related to a parent document
|
|
59
|
+
* Returns chunks including the parent itself
|
|
60
|
+
*/
|
|
61
|
+
findRelatedChunks(documentId: string): Promise<any[]>;
|
|
62
|
+
/**
|
|
63
|
+
* Delete all chunks related to a parent document
|
|
64
|
+
*/
|
|
65
|
+
deleteRelatedChunks(documentId: string): Promise<number>;
|
|
66
|
+
/**
|
|
67
|
+
* Update embeddings with automatic chunking support
|
|
68
|
+
* Handles re-chunking when content changes and exceeds chunk size
|
|
69
|
+
*/
|
|
70
|
+
updateChunkedEmbedding(id: string, data: UpdateEmbeddingData): Promise<ChunkedEmbeddingResult>;
|
|
71
|
+
updateEmbedding(id: string, data: UpdateEmbeddingData): Promise<any>;
|
|
31
72
|
queryEmbeddings(query: string): Promise<import("../plugin-manager").QueryResponse | {
|
|
32
73
|
error: string;
|
|
33
74
|
}>;
|
|
@@ -2,12 +2,17 @@ declare const _default: {
|
|
|
2
2
|
embeddings: ({ strapi }: {
|
|
3
3
|
strapi: import("@strapi/types/dist/core").Strapi;
|
|
4
4
|
}) => {
|
|
5
|
-
|
|
5
|
+
getConfig(): import("../config").PluginConfigSchema;
|
|
6
|
+
createEmbedding(data: import("./embeddings").CreateEmbeddingData): Promise<any>;
|
|
7
|
+
createChunkedEmbedding(data: import("./embeddings").CreateEmbeddingData): Promise<import("./embeddings").ChunkedEmbeddingResult>;
|
|
6
8
|
deleteEmbedding(id: string | number): Promise<{
|
|
7
9
|
documentId: string;
|
|
8
10
|
entries: import("@strapi/types/dist/modules/documents").AnyDocument[];
|
|
9
11
|
}>;
|
|
10
|
-
|
|
12
|
+
findRelatedChunks(documentId: string): Promise<any[]>;
|
|
13
|
+
deleteRelatedChunks(documentId: string): Promise<number>;
|
|
14
|
+
updateChunkedEmbedding(id: string, data: import("./embeddings").UpdateEmbeddingData): Promise<import("./embeddings").ChunkedEmbeddingResult>;
|
|
15
|
+
updateEmbedding(id: string, data: import("./embeddings").UpdateEmbeddingData): Promise<any>;
|
|
11
16
|
queryEmbeddings(query: string): Promise<import("../plugin-manager").QueryResponse | {
|
|
12
17
|
error: string;
|
|
13
18
|
}>;
|
|
@@ -22,5 +27,22 @@ declare const _default: {
|
|
|
22
27
|
totalCount: number;
|
|
23
28
|
}>;
|
|
24
29
|
};
|
|
30
|
+
sync: ({ strapi }: {
|
|
31
|
+
strapi: import("@strapi/types/dist/core").Strapi;
|
|
32
|
+
}) => {
|
|
33
|
+
syncFromNeon(options?: {
|
|
34
|
+
removeOrphans?: boolean;
|
|
35
|
+
dryRun?: boolean;
|
|
36
|
+
}): Promise<import("./sync").SyncResult>;
|
|
37
|
+
getSyncStatus(): Promise<{
|
|
38
|
+
neonCount: number;
|
|
39
|
+
strapiCount: number;
|
|
40
|
+
inSync: boolean;
|
|
41
|
+
missingInStrapi: number;
|
|
42
|
+
missingInNeon: number;
|
|
43
|
+
contentDifferences: number;
|
|
44
|
+
}>;
|
|
45
|
+
recreateAllEmbeddings(): Promise<import("./sync").RecreateResult>;
|
|
46
|
+
};
|
|
25
47
|
};
|
|
26
48
|
export default _default;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Core } from "@strapi/strapi";
|
|
2
|
+
export interface SyncResult {
|
|
3
|
+
success: boolean;
|
|
4
|
+
timestamp: string;
|
|
5
|
+
neonCount: number;
|
|
6
|
+
strapiCount: number;
|
|
7
|
+
actions: {
|
|
8
|
+
created: number;
|
|
9
|
+
updated: number;
|
|
10
|
+
orphansRemoved: number;
|
|
11
|
+
};
|
|
12
|
+
details: {
|
|
13
|
+
created: string[];
|
|
14
|
+
updated: string[];
|
|
15
|
+
orphansRemoved: string[];
|
|
16
|
+
};
|
|
17
|
+
errors: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface RecreateResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
timestamp: string;
|
|
22
|
+
deletedFromNeon: number;
|
|
23
|
+
processedFromStrapi: number;
|
|
24
|
+
recreatedInNeon: number;
|
|
25
|
+
errors: string[];
|
|
26
|
+
details: {
|
|
27
|
+
recreated: string[];
|
|
28
|
+
failed: string[];
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
declare const sync: ({ strapi }: {
|
|
32
|
+
strapi: Core.Strapi;
|
|
33
|
+
}) => {
|
|
34
|
+
/**
|
|
35
|
+
* Sync embeddings from Neon DB to Strapi DB
|
|
36
|
+
*
|
|
37
|
+
* This performs the following operations:
|
|
38
|
+
* 1. Fetches all embeddings from Neon DB (source of truth)
|
|
39
|
+
* 2. Fetches all embeddings from Strapi DB
|
|
40
|
+
* 3. Creates missing entries in Strapi that exist in Neon
|
|
41
|
+
* 4. Updates Strapi entries where content differs from Neon
|
|
42
|
+
* 5. Optionally removes orphaned Strapi entries (no matching Neon record)
|
|
43
|
+
*/
|
|
44
|
+
syncFromNeon(options?: {
|
|
45
|
+
removeOrphans?: boolean;
|
|
46
|
+
dryRun?: boolean;
|
|
47
|
+
}): Promise<SyncResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Get sync status - compare Neon and Strapi without making changes
|
|
50
|
+
*/
|
|
51
|
+
getSyncStatus(): Promise<{
|
|
52
|
+
neonCount: number;
|
|
53
|
+
strapiCount: number;
|
|
54
|
+
inSync: boolean;
|
|
55
|
+
missingInStrapi: number;
|
|
56
|
+
missingInNeon: number;
|
|
57
|
+
contentDifferences: number;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Recreate all embeddings in Neon DB from Strapi data
|
|
61
|
+
*
|
|
62
|
+
* This will:
|
|
63
|
+
* 1. Delete ALL embeddings from Neon DB
|
|
64
|
+
* 2. Re-create embeddings for each Strapi embedding entry
|
|
65
|
+
* 3. Update Strapi entries with new embedding IDs
|
|
66
|
+
*
|
|
67
|
+
* Use this when embeddings were created with incorrect metadata format
|
|
68
|
+
*/
|
|
69
|
+
recreateAllEmbeddings(): Promise<RecreateResult>;
|
|
70
|
+
};
|
|
71
|
+
export default sync;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text chunking utilities for splitting large content into embeddable chunks
|
|
3
|
+
*/
|
|
4
|
+
export interface ChunkOptions {
|
|
5
|
+
/** Maximum characters per chunk (default: 4000, roughly ~1000 tokens) */
|
|
6
|
+
chunkSize?: number;
|
|
7
|
+
/** Number of characters to overlap between chunks (default: 200) */
|
|
8
|
+
chunkOverlap?: number;
|
|
9
|
+
/** Separator to use when splitting (default: splits on paragraphs, sentences, then words) */
|
|
10
|
+
separators?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface TextChunk {
|
|
13
|
+
/** The chunk text content */
|
|
14
|
+
text: string;
|
|
15
|
+
/** Zero-based chunk index */
|
|
16
|
+
chunkIndex: number;
|
|
17
|
+
/** Total number of chunks */
|
|
18
|
+
totalChunks: number;
|
|
19
|
+
/** Character offset in original text */
|
|
20
|
+
startOffset: number;
|
|
21
|
+
/** Character end offset in original text */
|
|
22
|
+
endOffset: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Estimate token count from character count
|
|
26
|
+
* OpenAI models average ~4 characters per token for English text
|
|
27
|
+
*/
|
|
28
|
+
export declare function estimateTokens(text: string): number;
|
|
29
|
+
/**
|
|
30
|
+
* Check if content exceeds the recommended chunk size
|
|
31
|
+
*/
|
|
32
|
+
export declare function needsChunking(content: string, maxChars?: number): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Split content into chunks suitable for embedding
|
|
35
|
+
*
|
|
36
|
+
* @param content - The text content to split
|
|
37
|
+
* @param options - Chunking options
|
|
38
|
+
* @returns Array of TextChunk objects
|
|
39
|
+
*/
|
|
40
|
+
export declare function chunkContent(content: string, options?: ChunkOptions): TextChunk[];
|
|
41
|
+
/**
|
|
42
|
+
* Format chunk title with index information
|
|
43
|
+
*/
|
|
44
|
+
export declare function formatChunkTitle(baseTitle: string, chunkIndex: number, totalChunks: number): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-content-embeddings",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Strapi v5 plugin for vector embeddings with OpenAI and Neon PostgreSQL. Enables semantic search, RAG chat, and MCP (Model Context Protocol) integration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"strapi",
|