searchsocket 0.3.2 → 0.4.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 +8 -8
- package/dist/cli.js +456 -187
- package/dist/client.cjs +121 -0
- package/dist/client.d.cts +17 -2
- package/dist/client.d.ts +17 -2
- package/dist/client.js +121 -1
- package/dist/index.cjs +590 -169
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +590 -170
- package/dist/sveltekit.cjs +380 -82
- package/dist/sveltekit.d.cts +1 -1
- package/dist/sveltekit.d.ts +1 -1
- package/dist/sveltekit.js +380 -82
- package/dist/{types-BrG6XTUU.d.cts → types-z2dw3H6E.d.cts} +37 -1
- package/dist/{types-BrG6XTUU.d.ts → types-z2dw3H6E.d.ts} +37 -1
- package/package.json +1 -1
package/dist/client.cjs
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/merge.ts
|
|
4
|
+
function mergeSearchResults(initial, reranked, options) {
|
|
5
|
+
const maxDisplacement = options?.maxDisplacement ?? 3;
|
|
6
|
+
const initialUrls = initial.results.map((r) => r.url);
|
|
7
|
+
const rerankedUrls = reranked.results.map((r) => r.url);
|
|
8
|
+
const initialPos = /* @__PURE__ */ new Map();
|
|
9
|
+
for (let i = 0; i < initialUrls.length; i++) {
|
|
10
|
+
initialPos.set(initialUrls[i], i);
|
|
11
|
+
}
|
|
12
|
+
const rerankedPos = /* @__PURE__ */ new Map();
|
|
13
|
+
for (let i = 0; i < rerankedUrls.length; i++) {
|
|
14
|
+
rerankedPos.set(rerankedUrls[i], i);
|
|
15
|
+
}
|
|
16
|
+
const displacements = [];
|
|
17
|
+
for (const url of initialUrls) {
|
|
18
|
+
const iPos = initialPos.get(url);
|
|
19
|
+
const rPos = rerankedPos.get(url);
|
|
20
|
+
const displacement = rPos !== void 0 ? Math.abs(iPos - rPos) : 0;
|
|
21
|
+
displacements.push({ url, displacement });
|
|
22
|
+
}
|
|
23
|
+
const totalResults = displacements.length;
|
|
24
|
+
if (totalResults === 0) {
|
|
25
|
+
return {
|
|
26
|
+
response: reranked,
|
|
27
|
+
usedRerankedOrder: true,
|
|
28
|
+
displacements
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const hasLargeDisplacement = displacements.some((d) => d.displacement > maxDisplacement);
|
|
32
|
+
if (hasLargeDisplacement) {
|
|
33
|
+
return {
|
|
34
|
+
response: reranked,
|
|
35
|
+
usedRerankedOrder: true,
|
|
36
|
+
displacements
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const rerankedScoreMap = /* @__PURE__ */ new Map();
|
|
40
|
+
for (const result of reranked.results) {
|
|
41
|
+
rerankedScoreMap.set(result.url, result.score);
|
|
42
|
+
}
|
|
43
|
+
const mergedResults = initial.results.map((result) => ({
|
|
44
|
+
...result,
|
|
45
|
+
score: rerankedScoreMap.get(result.url) ?? result.score
|
|
46
|
+
}));
|
|
47
|
+
return {
|
|
48
|
+
response: {
|
|
49
|
+
...reranked,
|
|
50
|
+
results: mergedResults
|
|
51
|
+
},
|
|
52
|
+
usedRerankedOrder: false,
|
|
53
|
+
displacements
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
3
57
|
// src/client.ts
|
|
4
58
|
function createSearchClient(options = {}) {
|
|
5
59
|
const endpoint = options.endpoint ?? "/api/search";
|
|
@@ -27,10 +81,77 @@ function createSearchClient(options = {}) {
|
|
|
27
81
|
throw new Error(message);
|
|
28
82
|
}
|
|
29
83
|
return payload;
|
|
84
|
+
},
|
|
85
|
+
async streamSearch(request, onPhase) {
|
|
86
|
+
const response = await fetchImpl(endpoint, {
|
|
87
|
+
method: "POST",
|
|
88
|
+
headers: {
|
|
89
|
+
"content-type": "application/json"
|
|
90
|
+
},
|
|
91
|
+
body: JSON.stringify(request)
|
|
92
|
+
});
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
let payload;
|
|
95
|
+
try {
|
|
96
|
+
payload = await response.json();
|
|
97
|
+
} catch {
|
|
98
|
+
throw new Error("Search failed");
|
|
99
|
+
}
|
|
100
|
+
const message = payload.error?.message ?? "Search failed";
|
|
101
|
+
throw new Error(message);
|
|
102
|
+
}
|
|
103
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
104
|
+
if (contentType.includes("application/json")) {
|
|
105
|
+
const data = await response.json();
|
|
106
|
+
onPhase({ phase: "initial", data });
|
|
107
|
+
return data;
|
|
108
|
+
}
|
|
109
|
+
if (!response.body) {
|
|
110
|
+
throw new Error("Response body is not readable");
|
|
111
|
+
}
|
|
112
|
+
const reader = response.body.getReader();
|
|
113
|
+
const decoder = new TextDecoder();
|
|
114
|
+
let buffer = "";
|
|
115
|
+
let lastResponse = null;
|
|
116
|
+
for (; ; ) {
|
|
117
|
+
const { done, value } = await reader.read();
|
|
118
|
+
if (done) break;
|
|
119
|
+
buffer += decoder.decode(value, { stream: true });
|
|
120
|
+
let newlineIdx;
|
|
121
|
+
while ((newlineIdx = buffer.indexOf("\n")) !== -1) {
|
|
122
|
+
const line = buffer.slice(0, newlineIdx).trim();
|
|
123
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
124
|
+
if (line.length === 0) continue;
|
|
125
|
+
const event = JSON.parse(line);
|
|
126
|
+
if (event.phase === "error") {
|
|
127
|
+
const errData = event.data;
|
|
128
|
+
throw new Error(errData.error.message ?? "Streaming search error");
|
|
129
|
+
}
|
|
130
|
+
const searchEvent = event;
|
|
131
|
+
onPhase(searchEvent);
|
|
132
|
+
lastResponse = searchEvent.data;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const remaining = buffer.trim();
|
|
136
|
+
if (remaining.length > 0) {
|
|
137
|
+
const event = JSON.parse(remaining);
|
|
138
|
+
if (event.phase === "error") {
|
|
139
|
+
const errData = event.data;
|
|
140
|
+
throw new Error(errData.error.message ?? "Streaming search error");
|
|
141
|
+
}
|
|
142
|
+
const searchEvent = event;
|
|
143
|
+
onPhase(searchEvent);
|
|
144
|
+
lastResponse = searchEvent.data;
|
|
145
|
+
}
|
|
146
|
+
if (!lastResponse) {
|
|
147
|
+
throw new Error("No search results received");
|
|
148
|
+
}
|
|
149
|
+
return lastResponse;
|
|
30
150
|
}
|
|
31
151
|
};
|
|
32
152
|
}
|
|
33
153
|
|
|
34
154
|
exports.createSearchClient = createSearchClient;
|
|
155
|
+
exports.mergeSearchResults = mergeSearchResults;
|
|
35
156
|
//# sourceMappingURL=client.cjs.map
|
|
36
157
|
//# sourceMappingURL=client.cjs.map
|
package/dist/client.d.cts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import { S as
|
|
1
|
+
import { S as SearchResponse, M as MergeSearchOptions, a as MergeSearchResult, b as SearchRequest, c as StreamSearchEvent } from './types-z2dw3H6E.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Smart merge of initial (pre-rerank) and reranked search results.
|
|
5
|
+
*
|
|
6
|
+
* If the reranker barely changed the ordering, we keep the initial order
|
|
7
|
+
* (which the user already saw) and just update scores from the reranked response.
|
|
8
|
+
* If the reranker moved any single result by more than `maxDisplacement`
|
|
9
|
+
* positions, we adopt the reranked order — the reranker is semantic and
|
|
10
|
+
* expensive, so if it strongly disagrees on even one result, trust it.
|
|
11
|
+
*/
|
|
12
|
+
declare function mergeSearchResults(initial: SearchResponse, reranked: SearchResponse, options?: MergeSearchOptions): MergeSearchResult;
|
|
2
13
|
|
|
3
14
|
interface SearchClientOptions {
|
|
4
15
|
endpoint?: string;
|
|
@@ -6,6 +17,10 @@ interface SearchClientOptions {
|
|
|
6
17
|
}
|
|
7
18
|
declare function createSearchClient(options?: SearchClientOptions): {
|
|
8
19
|
search(request: SearchRequest): Promise<SearchResponse>;
|
|
20
|
+
streamSearch(request: SearchRequest & {
|
|
21
|
+
stream: true;
|
|
22
|
+
rerank: true;
|
|
23
|
+
}, onPhase: (event: StreamSearchEvent) => void): Promise<SearchResponse>;
|
|
9
24
|
};
|
|
10
25
|
|
|
11
|
-
export { type SearchClientOptions, createSearchClient };
|
|
26
|
+
export { type SearchClientOptions, createSearchClient, mergeSearchResults };
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import { S as
|
|
1
|
+
import { S as SearchResponse, M as MergeSearchOptions, a as MergeSearchResult, b as SearchRequest, c as StreamSearchEvent } from './types-z2dw3H6E.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Smart merge of initial (pre-rerank) and reranked search results.
|
|
5
|
+
*
|
|
6
|
+
* If the reranker barely changed the ordering, we keep the initial order
|
|
7
|
+
* (which the user already saw) and just update scores from the reranked response.
|
|
8
|
+
* If the reranker moved any single result by more than `maxDisplacement`
|
|
9
|
+
* positions, we adopt the reranked order — the reranker is semantic and
|
|
10
|
+
* expensive, so if it strongly disagrees on even one result, trust it.
|
|
11
|
+
*/
|
|
12
|
+
declare function mergeSearchResults(initial: SearchResponse, reranked: SearchResponse, options?: MergeSearchOptions): MergeSearchResult;
|
|
2
13
|
|
|
3
14
|
interface SearchClientOptions {
|
|
4
15
|
endpoint?: string;
|
|
@@ -6,6 +17,10 @@ interface SearchClientOptions {
|
|
|
6
17
|
}
|
|
7
18
|
declare function createSearchClient(options?: SearchClientOptions): {
|
|
8
19
|
search(request: SearchRequest): Promise<SearchResponse>;
|
|
20
|
+
streamSearch(request: SearchRequest & {
|
|
21
|
+
stream: true;
|
|
22
|
+
rerank: true;
|
|
23
|
+
}, onPhase: (event: StreamSearchEvent) => void): Promise<SearchResponse>;
|
|
9
24
|
};
|
|
10
25
|
|
|
11
|
-
export { type SearchClientOptions, createSearchClient };
|
|
26
|
+
export { type SearchClientOptions, createSearchClient, mergeSearchResults };
|
package/dist/client.js
CHANGED
|
@@ -1,3 +1,57 @@
|
|
|
1
|
+
// src/merge.ts
|
|
2
|
+
function mergeSearchResults(initial, reranked, options) {
|
|
3
|
+
const maxDisplacement = options?.maxDisplacement ?? 3;
|
|
4
|
+
const initialUrls = initial.results.map((r) => r.url);
|
|
5
|
+
const rerankedUrls = reranked.results.map((r) => r.url);
|
|
6
|
+
const initialPos = /* @__PURE__ */ new Map();
|
|
7
|
+
for (let i = 0; i < initialUrls.length; i++) {
|
|
8
|
+
initialPos.set(initialUrls[i], i);
|
|
9
|
+
}
|
|
10
|
+
const rerankedPos = /* @__PURE__ */ new Map();
|
|
11
|
+
for (let i = 0; i < rerankedUrls.length; i++) {
|
|
12
|
+
rerankedPos.set(rerankedUrls[i], i);
|
|
13
|
+
}
|
|
14
|
+
const displacements = [];
|
|
15
|
+
for (const url of initialUrls) {
|
|
16
|
+
const iPos = initialPos.get(url);
|
|
17
|
+
const rPos = rerankedPos.get(url);
|
|
18
|
+
const displacement = rPos !== void 0 ? Math.abs(iPos - rPos) : 0;
|
|
19
|
+
displacements.push({ url, displacement });
|
|
20
|
+
}
|
|
21
|
+
const totalResults = displacements.length;
|
|
22
|
+
if (totalResults === 0) {
|
|
23
|
+
return {
|
|
24
|
+
response: reranked,
|
|
25
|
+
usedRerankedOrder: true,
|
|
26
|
+
displacements
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const hasLargeDisplacement = displacements.some((d) => d.displacement > maxDisplacement);
|
|
30
|
+
if (hasLargeDisplacement) {
|
|
31
|
+
return {
|
|
32
|
+
response: reranked,
|
|
33
|
+
usedRerankedOrder: true,
|
|
34
|
+
displacements
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const rerankedScoreMap = /* @__PURE__ */ new Map();
|
|
38
|
+
for (const result of reranked.results) {
|
|
39
|
+
rerankedScoreMap.set(result.url, result.score);
|
|
40
|
+
}
|
|
41
|
+
const mergedResults = initial.results.map((result) => ({
|
|
42
|
+
...result,
|
|
43
|
+
score: rerankedScoreMap.get(result.url) ?? result.score
|
|
44
|
+
}));
|
|
45
|
+
return {
|
|
46
|
+
response: {
|
|
47
|
+
...reranked,
|
|
48
|
+
results: mergedResults
|
|
49
|
+
},
|
|
50
|
+
usedRerankedOrder: false,
|
|
51
|
+
displacements
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
1
55
|
// src/client.ts
|
|
2
56
|
function createSearchClient(options = {}) {
|
|
3
57
|
const endpoint = options.endpoint ?? "/api/search";
|
|
@@ -25,10 +79,76 @@ function createSearchClient(options = {}) {
|
|
|
25
79
|
throw new Error(message);
|
|
26
80
|
}
|
|
27
81
|
return payload;
|
|
82
|
+
},
|
|
83
|
+
async streamSearch(request, onPhase) {
|
|
84
|
+
const response = await fetchImpl(endpoint, {
|
|
85
|
+
method: "POST",
|
|
86
|
+
headers: {
|
|
87
|
+
"content-type": "application/json"
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify(request)
|
|
90
|
+
});
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
let payload;
|
|
93
|
+
try {
|
|
94
|
+
payload = await response.json();
|
|
95
|
+
} catch {
|
|
96
|
+
throw new Error("Search failed");
|
|
97
|
+
}
|
|
98
|
+
const message = payload.error?.message ?? "Search failed";
|
|
99
|
+
throw new Error(message);
|
|
100
|
+
}
|
|
101
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
102
|
+
if (contentType.includes("application/json")) {
|
|
103
|
+
const data = await response.json();
|
|
104
|
+
onPhase({ phase: "initial", data });
|
|
105
|
+
return data;
|
|
106
|
+
}
|
|
107
|
+
if (!response.body) {
|
|
108
|
+
throw new Error("Response body is not readable");
|
|
109
|
+
}
|
|
110
|
+
const reader = response.body.getReader();
|
|
111
|
+
const decoder = new TextDecoder();
|
|
112
|
+
let buffer = "";
|
|
113
|
+
let lastResponse = null;
|
|
114
|
+
for (; ; ) {
|
|
115
|
+
const { done, value } = await reader.read();
|
|
116
|
+
if (done) break;
|
|
117
|
+
buffer += decoder.decode(value, { stream: true });
|
|
118
|
+
let newlineIdx;
|
|
119
|
+
while ((newlineIdx = buffer.indexOf("\n")) !== -1) {
|
|
120
|
+
const line = buffer.slice(0, newlineIdx).trim();
|
|
121
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
122
|
+
if (line.length === 0) continue;
|
|
123
|
+
const event = JSON.parse(line);
|
|
124
|
+
if (event.phase === "error") {
|
|
125
|
+
const errData = event.data;
|
|
126
|
+
throw new Error(errData.error.message ?? "Streaming search error");
|
|
127
|
+
}
|
|
128
|
+
const searchEvent = event;
|
|
129
|
+
onPhase(searchEvent);
|
|
130
|
+
lastResponse = searchEvent.data;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const remaining = buffer.trim();
|
|
134
|
+
if (remaining.length > 0) {
|
|
135
|
+
const event = JSON.parse(remaining);
|
|
136
|
+
if (event.phase === "error") {
|
|
137
|
+
const errData = event.data;
|
|
138
|
+
throw new Error(errData.error.message ?? "Streaming search error");
|
|
139
|
+
}
|
|
140
|
+
const searchEvent = event;
|
|
141
|
+
onPhase(searchEvent);
|
|
142
|
+
lastResponse = searchEvent.data;
|
|
143
|
+
}
|
|
144
|
+
if (!lastResponse) {
|
|
145
|
+
throw new Error("No search results received");
|
|
146
|
+
}
|
|
147
|
+
return lastResponse;
|
|
28
148
|
}
|
|
29
149
|
};
|
|
30
150
|
}
|
|
31
151
|
|
|
32
|
-
export { createSearchClient };
|
|
152
|
+
export { createSearchClient, mergeSearchResults };
|
|
33
153
|
//# sourceMappingURL=client.js.map
|
|
34
154
|
//# sourceMappingURL=client.js.map
|