graphile-llm 1.16.0 → 1.17.1

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.
@@ -1,10 +0,0 @@
1
- /**
2
- * Unit tests for LlmTextSearchPlugin's embedTextInWhere function.
3
- *
4
- * Tests the transformation logic:
5
- * - unifiedSearch: "text" → unifiedSearch: { __text: "text", __vector: [...] }
6
- * - VectorNearbyInput.text → VectorNearbyInput.vector (existing behavior)
7
- *
8
- * Pure unit tests — no database or Ollama required.
9
- */
10
- export {};
@@ -1,176 +0,0 @@
1
- "use strict";
2
- /**
3
- * Unit tests for LlmTextSearchPlugin's embedTextInWhere function.
4
- *
5
- * Tests the transformation logic:
6
- * - unifiedSearch: "text" → unifiedSearch: { __text: "text", __vector: [...] }
7
- * - VectorNearbyInput.text → VectorNearbyInput.vector (existing behavior)
8
- *
9
- * Pure unit tests — no database or Ollama required.
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- const text_search_plugin_1 = require("../../src/plugins/text-search-plugin");
13
- describe('unifiedSearch embedding integration', () => {
14
- const mockVector = [0.1, 0.2, 0.3, 0.4, 0.5];
15
- const mockEmbedder = jest.fn(async (_text) => mockVector);
16
- const nullEmbedder = jest.fn(async (_text) => null);
17
- beforeEach(() => {
18
- mockEmbedder.mockClear();
19
- nullEmbedder.mockClear();
20
- });
21
- describe('unifiedSearch text → { __text, __vector } transformation', () => {
22
- it('transforms unifiedSearch string to object with __text and __vector', async () => {
23
- const where = { unifiedSearch: 'HIPAA compliance' };
24
- await (0, text_search_plugin_1.embedTextInWhere)(where, mockEmbedder, true);
25
- expect(where.unifiedSearch).toEqual({
26
- __text: 'HIPAA compliance',
27
- __vector: mockVector,
28
- });
29
- expect(mockEmbedder).toHaveBeenCalledWith('HIPAA compliance');
30
- });
31
- it('leaves unifiedSearch as plain string when embedder returns null (graceful degradation)', async () => {
32
- const where = { unifiedSearch: 'database normalization' };
33
- await (0, text_search_plugin_1.embedTextInWhere)(where, nullEmbedder, true);
34
- // Should remain as string — text adapters handle it
35
- expect(where.unifiedSearch).toBe('database normalization');
36
- expect(nullEmbedder).toHaveBeenCalledWith('database normalization');
37
- });
38
- it('throws when embedder returns null and no text adapters available', async () => {
39
- const where = { unifiedSearch: 'vector only query' };
40
- await expect((0, text_search_plugin_1.embedTextInWhere)(where, nullEmbedder, false)).rejects.toThrow('embedding failed');
41
- });
42
- it('does not embed empty unifiedSearch strings', async () => {
43
- const where = { unifiedSearch: ' ' };
44
- await (0, text_search_plugin_1.embedTextInWhere)(where, mockEmbedder, true);
45
- expect(where.unifiedSearch).toBe(' ');
46
- expect(mockEmbedder).not.toHaveBeenCalled();
47
- });
48
- it('does not embed null unifiedSearch', async () => {
49
- const where = { unifiedSearch: null };
50
- await (0, text_search_plugin_1.embedTextInWhere)(where, mockEmbedder, true);
51
- expect(where.unifiedSearch).toBeNull();
52
- expect(mockEmbedder).not.toHaveBeenCalled();
53
- });
54
- });
55
- describe('VectorNearbyInput text → vector (existing behavior)', () => {
56
- it('transforms VectorNearbyInput text to vector', async () => {
57
- const where = { vectorEmbedding: { text: 'semantic query' } };
58
- await (0, text_search_plugin_1.embedTextInWhere)(where, mockEmbedder, true);
59
- expect(where.vectorEmbedding).toEqual({ vector: mockVector });
60
- expect(mockEmbedder).toHaveBeenCalledWith('semantic query');
61
- });
62
- it('removes text field when embedder returns null', async () => {
63
- const where = { vectorEmbedding: { text: 'failed query' } };
64
- await (0, text_search_plugin_1.embedTextInWhere)(where, nullEmbedder, true);
65
- expect(where.vectorEmbedding).toEqual({});
66
- expect(nullEmbedder).toHaveBeenCalledWith('failed query');
67
- });
68
- it('does not modify VectorNearbyInput with existing vector', async () => {
69
- const existingVector = [1, 2, 3];
70
- const where = { vectorEmbedding: { vector: existingVector, text: 'ignored' } };
71
- await (0, text_search_plugin_1.embedTextInWhere)(where, mockEmbedder, true);
72
- // text + vector present → not modified (vector takes precedence)
73
- expect(where.vectorEmbedding.vector).toBe(existingVector);
74
- expect(mockEmbedder).not.toHaveBeenCalled();
75
- });
76
- });
77
- describe('combined unifiedSearch + VectorNearbyInput', () => {
78
- it('embeds both unifiedSearch and VectorNearbyInput.text in parallel', async () => {
79
- const where = {
80
- unifiedSearch: 'hybrid search query',
81
- vectorEmbedding: { text: 'vector part' },
82
- };
83
- await (0, text_search_plugin_1.embedTextInWhere)(where, mockEmbedder, true);
84
- expect(where.unifiedSearch).toEqual({
85
- __text: 'hybrid search query',
86
- __vector: mockVector,
87
- });
88
- expect(where.vectorEmbedding).toEqual({ vector: mockVector });
89
- expect(mockEmbedder).toHaveBeenCalledTimes(2);
90
- });
91
- });
92
- describe('nested filter structures (AND, OR)', () => {
93
- it('handles unifiedSearch inside nested AND/OR filters', async () => {
94
- const where = {
95
- AND: [
96
- { unifiedSearch: 'first query' },
97
- { unifiedSearch: 'second query' },
98
- ],
99
- };
100
- await (0, text_search_plugin_1.embedTextInWhere)(where, mockEmbedder, true);
101
- expect(where.AND[0].unifiedSearch).toEqual({
102
- __text: 'first query',
103
- __vector: mockVector,
104
- });
105
- expect(where.AND[1].unifiedSearch).toEqual({
106
- __text: 'second query',
107
- __vector: mockVector,
108
- });
109
- });
110
- });
111
- describe('onQuotaExceeded option', () => {
112
- it('degrade mode (default): leaves unifiedSearch as string when embedder returns null', async () => {
113
- const where = { unifiedSearch: 'some query' };
114
- await (0, text_search_plugin_1.embedTextInWhere)(where, nullEmbedder, true, 'degrade');
115
- expect(where.unifiedSearch).toBe('some query');
116
- });
117
- it('throw mode: throws on unifiedSearch when embedder returns null even with text adapters', async () => {
118
- const where = { unifiedSearch: 'some query' };
119
- await expect((0, text_search_plugin_1.embedTextInWhere)(where, nullEmbedder, true, 'throw')).rejects.toThrow('onQuotaExceeded is set to \'throw\'');
120
- });
121
- it('throw mode: throws on VectorNearbyInput.text when embedder returns null', async () => {
122
- const where = { vectorEmbedding: { text: 'semantic query' } };
123
- await expect((0, text_search_plugin_1.embedTextInWhere)(where, nullEmbedder, true, 'throw')).rejects.toThrow('VectorNearbyInput: embedding failed');
124
- });
125
- it('degrade mode: silently removes VectorNearbyInput.text when embedder returns null', async () => {
126
- const where = { vectorEmbedding: { text: 'failed query' } };
127
- await (0, text_search_plugin_1.embedTextInWhere)(where, nullEmbedder, true, 'degrade');
128
- expect(where.vectorEmbedding).toEqual({});
129
- });
130
- it('throw mode: still works normally when embedder succeeds', async () => {
131
- const where = { unifiedSearch: 'good query' };
132
- await (0, text_search_plugin_1.embedTextInWhere)(where, mockEmbedder, true, 'throw');
133
- expect(where.unifiedSearch).toEqual({
134
- __text: 'good query',
135
- __vector: mockVector,
136
- });
137
- });
138
- it('no text adapters: throws regardless of onQuotaExceeded setting', async () => {
139
- const where1 = { unifiedSearch: 'query1' };
140
- await expect((0, text_search_plugin_1.embedTextInWhere)(where1, nullEmbedder, false, 'degrade')).rejects.toThrow('No text search adapters available');
141
- const where2 = { unifiedSearch: 'query2' };
142
- await expect((0, text_search_plugin_1.embedTextInWhere)(where2, nullEmbedder, false, 'throw')).rejects.toThrow('No text search adapters available');
143
- });
144
- });
145
- describe('apply function object shape handling', () => {
146
- it('plugin.ts apply function handles { __text, __vector } correctly', () => {
147
- // Simulate what the apply function does with the transformed value
148
- const val = { __text: 'HIPAA compliance', __vector: [0.1, 0.2, 0.3] };
149
- let text;
150
- let vector = null;
151
- if (typeof val === 'object' && val.__text) {
152
- text = val.__text;
153
- vector = val.__vector ?? null;
154
- }
155
- else {
156
- text = typeof val === 'string' ? val : String(val);
157
- }
158
- expect(text).toBe('HIPAA compliance');
159
- expect(vector).toEqual([0.1, 0.2, 0.3]);
160
- });
161
- it('plugin.ts apply function handles plain string correctly', () => {
162
- const val = 'plain text search';
163
- let text;
164
- let vector = null;
165
- if (typeof val === 'object' && val.__text) {
166
- text = val.__text;
167
- vector = val.__vector ?? null;
168
- }
169
- else {
170
- text = typeof val === 'string' ? val : String(val);
171
- }
172
- expect(text).toBe('plain text search');
173
- expect(vector).toBeNull();
174
- });
175
- });
176
- });
@@ -1 +0,0 @@
1
- export {};