@askdkc/kiokuko 0.2.5 → 0.2.7
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.ja.md +54 -0
- package/README.ko.md +54 -0
- package/README.md +55 -0
- package/README.zh-CN.md +52 -0
- package/dist/agent-file/render.d.ts +1 -1
- package/dist/agent-file/render.js +2 -2
- package/dist/agent-file/render.js.map +1 -1
- package/dist/akinator/agent-task.d.ts +3 -0
- package/dist/akinator/agent-task.d.ts.map +1 -1
- package/dist/akinator/agent-task.js +52 -10
- package/dist/akinator/agent-task.js.map +1 -1
- package/dist/akinator/capabilities.d.ts +7 -1
- package/dist/akinator/capabilities.d.ts.map +1 -1
- package/dist/akinator/capabilities.js +10 -3
- package/dist/akinator/capabilities.js.map +1 -1
- package/dist/akinator/capability-binding.d.ts.map +1 -1
- package/dist/akinator/capability-binding.js +18 -3
- package/dist/akinator/capability-binding.js.map +1 -1
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +89 -8
- package/dist/cli.js.map +1 -1
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +21 -1
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/doctor.d.ts +4 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +45 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/embeddings.d.ts +19 -0
- package/dist/commands/embeddings.d.ts.map +1 -0
- package/dist/commands/embeddings.js +159 -0
- package/dist/commands/embeddings.js.map +1 -0
- package/dist/commands/import.d.ts.map +1 -1
- package/dist/commands/import.js +7 -0
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +4 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/use.d.ts.map +1 -1
- package/dist/commands/use.js +22 -8
- package/dist/commands/use.js.map +1 -1
- package/dist/context/broker.d.ts +3 -1
- package/dist/context/broker.d.ts.map +1 -1
- package/dist/context/broker.js +11 -7
- package/dist/context/broker.js.map +1 -1
- package/dist/context/delivery.d.ts.map +1 -1
- package/dist/context/delivery.js +10 -4
- package/dist/context/delivery.js.map +1 -1
- package/dist/context/ranking.d.ts +1 -1
- package/dist/context/ranking.d.ts.map +1 -1
- package/dist/context/ranking.js +2 -0
- package/dist/context/ranking.js.map +1 -1
- package/dist/context/scoped-broker.d.ts +4 -3
- package/dist/context/scoped-broker.d.ts.map +1 -1
- package/dist/context/scoped-broker.js +45 -7
- package/dist/context/scoped-broker.js.map +1 -1
- package/dist/context/selection-state.d.ts +12 -0
- package/dist/context/selection-state.d.ts.map +1 -1
- package/dist/context/selection-state.js +117 -7
- package/dist/context/selection-state.js.map +1 -1
- package/dist/db/capabilities.d.ts +8 -0
- package/dist/db/capabilities.d.ts.map +1 -1
- package/dist/db/capabilities.js +14 -0
- package/dist/db/capabilities.js.map +1 -1
- package/dist/db/connection.d.ts +7 -0
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +56 -0
- package/dist/db/connection.js.map +1 -1
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +3 -0
- package/dist/db/migrate.js.map +1 -1
- package/dist/embedding/backend.d.ts +27 -0
- package/dist/embedding/backend.d.ts.map +1 -0
- package/dist/embedding/backend.js +51 -0
- package/dist/embedding/backend.js.map +1 -0
- package/dist/embedding/config.d.ts +7 -0
- package/dist/embedding/config.d.ts.map +1 -0
- package/dist/embedding/config.js +125 -0
- package/dist/embedding/config.js.map +1 -0
- package/dist/embedding/diagnostics.d.ts +34 -0
- package/dist/embedding/diagnostics.d.ts.map +1 -0
- package/dist/embedding/diagnostics.js +248 -0
- package/dist/embedding/diagnostics.js.map +1 -0
- package/dist/embedding/document.d.ts +15 -0
- package/dist/embedding/document.d.ts.map +1 -0
- package/dist/embedding/document.js +102 -0
- package/dist/embedding/document.js.map +1 -0
- package/dist/embedding/javascript-backend.d.ts +11 -0
- package/dist/embedding/javascript-backend.d.ts.map +1 -0
- package/dist/embedding/javascript-backend.js +164 -0
- package/dist/embedding/javascript-backend.js.map +1 -0
- package/dist/embedding/jobs.d.ts +67 -0
- package/dist/embedding/jobs.d.ts.map +1 -0
- package/dist/embedding/jobs.js +259 -0
- package/dist/embedding/jobs.js.map +1 -0
- package/dist/embedding/openai-compatible-provider.d.ts +24 -0
- package/dist/embedding/openai-compatible-provider.d.ts.map +1 -0
- package/dist/embedding/openai-compatible-provider.js +330 -0
- package/dist/embedding/openai-compatible-provider.js.map +1 -0
- package/dist/embedding/profile.d.ts +6 -0
- package/dist/embedding/profile.d.ts.map +1 -0
- package/dist/embedding/profile.js +31 -0
- package/dist/embedding/profile.js.map +1 -0
- package/dist/embedding/provider.d.ts +13 -0
- package/dist/embedding/provider.d.ts.map +1 -0
- package/dist/embedding/provider.js +17 -0
- package/dist/embedding/provider.js.map +1 -0
- package/dist/embedding/query-cache.d.ts +39 -0
- package/dist/embedding/query-cache.d.ts.map +1 -0
- package/dist/embedding/query-cache.js +160 -0
- package/dist/embedding/query-cache.js.map +1 -0
- package/dist/embedding/runtime.d.ts +13 -0
- package/dist/embedding/runtime.d.ts.map +1 -0
- package/dist/embedding/runtime.js +373 -0
- package/dist/embedding/runtime.js.map +1 -0
- package/dist/embedding/sqlite-vec-backend.d.ts +9 -0
- package/dist/embedding/sqlite-vec-backend.d.ts.map +1 -0
- package/dist/embedding/sqlite-vec-backend.js +106 -0
- package/dist/embedding/sqlite-vec-backend.js.map +1 -0
- package/dist/embedding/sqlite-vec-loader.d.ts +17 -0
- package/dist/embedding/sqlite-vec-loader.d.ts.map +1 -0
- package/dist/embedding/sqlite-vec-loader.js +51 -0
- package/dist/embedding/sqlite-vec-loader.js.map +1 -0
- package/dist/embedding/store.d.ts +64 -0
- package/dist/embedding/store.d.ts.map +1 -0
- package/dist/embedding/store.js +377 -0
- package/dist/embedding/store.js.map +1 -0
- package/dist/embedding/types.d.ts +97 -0
- package/dist/embedding/types.d.ts.map +1 -0
- package/dist/embedding/types.js +2 -0
- package/dist/embedding/types.js.map +1 -0
- package/dist/embedding/vector.d.ts +9 -0
- package/dist/embedding/vector.d.ts.map +1 -0
- package/dist/embedding/vector.js +90 -0
- package/dist/embedding/vector.js.map +1 -0
- package/dist/embedding/worker.d.ts +23 -0
- package/dist/embedding/worker.d.ts.map +1 -0
- package/dist/embedding/worker.js +84 -0
- package/dist/embedding/worker.js.map +1 -0
- package/dist/enno-oduno/schemas.d.ts +2 -2
- package/dist/ledger/checkpoint-contract.d.ts +2 -2
- package/dist/mcp/bounded-stdio-transport.d.ts +12 -2
- package/dist/mcp/bounded-stdio-transport.d.ts.map +1 -1
- package/dist/mcp/bounded-stdio-transport.js +103 -4
- package/dist/mcp/bounded-stdio-transport.js.map +1 -1
- package/dist/mcp/runtime-owner.d.ts +27 -0
- package/dist/mcp/runtime-owner.d.ts.map +1 -0
- package/dist/mcp/runtime-owner.js +130 -0
- package/dist/mcp/runtime-owner.js.map +1 -0
- package/dist/mcp/server.d.ts +9 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +103 -43
- package/dist/mcp/server.js.map +1 -1
- package/dist/memory/checkpoint-contract.d.ts +3 -3
- package/dist/memory/entries.d.ts.map +1 -1
- package/dist/memory/entries.js +13 -0
- package/dist/memory/entries.js.map +1 -1
- package/dist/memory/federated-retrieval.d.ts +3 -2
- package/dist/memory/federated-retrieval.d.ts.map +1 -1
- package/dist/memory/federated-retrieval.js +112 -31
- package/dist/memory/federated-retrieval.js.map +1 -1
- package/dist/memory/hybrid-retrieval.d.ts +11 -2
- package/dist/memory/hybrid-retrieval.d.ts.map +1 -1
- package/dist/memory/hybrid-retrieval.js +175 -31
- package/dist/memory/hybrid-retrieval.js.map +1 -1
- package/dist/memory/rebuild-search.d.ts +5 -0
- package/dist/memory/rebuild-search.d.ts.map +1 -1
- package/dist/memory/rebuild-search.js +61 -7
- package/dist/memory/rebuild-search.js.map +1 -1
- package/dist/memory/retrieval-query.d.ts.map +1 -1
- package/dist/memory/retrieval-query.js +99 -1
- package/dist/memory/retrieval-query.js.map +1 -1
- package/dist/memory/retrieval.d.ts +4 -3
- package/dist/memory/retrieval.d.ts.map +1 -1
- package/dist/memory/retrieval.js +6 -6
- package/dist/memory/retrieval.js.map +1 -1
- package/dist/memory/scoped-memory.d.ts +2 -1
- package/dist/memory/scoped-memory.d.ts.map +1 -1
- package/dist/memory/scoped-memory.js +2 -2
- package/dist/memory/scoped-memory.js.map +1 -1
- package/dist/memory/structured-memory.d.ts +4 -0
- package/dist/memory/structured-memory.d.ts.map +1 -1
- package/dist/memory/structured-memory.js +101 -14
- package/dist/memory/structured-memory.js.map +1 -1
- package/dist/server/agent-application.js +1 -1
- package/dist/server/agent-application.js.map +1 -1
- package/dist/server/agent-checkpoint-use-case.d.ts.map +1 -1
- package/dist/server/agent-checkpoint-use-case.js +4 -3
- package/dist/server/agent-checkpoint-use-case.js.map +1 -1
- package/dist/server/http.d.ts +17 -1
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +76 -13
- package/dist/server/http.js.map +1 -1
- package/dist/server/routes/agent-capability-gate.d.ts +3 -0
- package/dist/server/routes/agent-capability-gate.d.ts.map +1 -1
- package/dist/server/routes/agent-capability-gate.js +23 -5
- package/dist/server/routes/agent-capability-gate.js.map +1 -1
- package/dist/setup/render.d.ts.map +1 -1
- package/dist/setup/render.js +9 -4
- package/dist/setup/render.js.map +1 -1
- package/dist/setup/standard-skills.d.ts +8 -1
- package/dist/setup/standard-skills.d.ts.map +1 -1
- package/dist/setup/standard-skills.js +8 -1
- package/dist/setup/standard-skills.js.map +1 -1
- package/migrations/020_cjk_fts.sql +80 -0
- package/migrations/021_semantic_embeddings.sql +122 -0
- package/migrations/down/020_cjk_fts.sql +38 -0
- package/migrations/down/021_semantic_embeddings.sql +17 -0
- package/package.json +7 -1
- package/skills/kiokuko-simple-work/SKILL.md +112 -0
- package/skills/kiokuko-soul/SKILL.md +39 -7
- package/templates/AGENTS.md +3 -3
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import { TextDecoder } from 'node:util';
|
|
2
|
+
import { parseStrictJson } from '../setup/strict-json.js';
|
|
3
|
+
import { findSecret } from '../memory/secrets.js';
|
|
4
|
+
import { KiokukoError } from '../errors.js';
|
|
5
|
+
import { normalizeEmbeddingBaseUrl, requireEnabledEmbeddingConfig } from './config.js';
|
|
6
|
+
import { createEmbeddingProfileIdentity } from './profile.js';
|
|
7
|
+
import { normalizeVector } from './vector.js';
|
|
8
|
+
import { EmbeddingProviderError } from './provider.js';
|
|
9
|
+
export const MAX_EMBEDDING_PROVIDER_INPUTS = 64;
|
|
10
|
+
export const MAX_EMBEDDING_PROVIDER_REQUEST_BYTES = 4 * 1024 * 1024;
|
|
11
|
+
export const MAX_EMBEDDING_PROVIDER_RESPONSE_BYTES = 4 * 1024 * 1024;
|
|
12
|
+
export const DEFAULT_EMBEDDING_PROVIDER_RETRIES = 2;
|
|
13
|
+
export const MAX_EMBEDDING_PROVIDER_RETRY_DELAY_MS = 5_000;
|
|
14
|
+
const INVALID_UNICODE = /[\p{Cs}\uFFFD]/u;
|
|
15
|
+
const INVALID_CONTROL = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/u;
|
|
16
|
+
const decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
17
|
+
function invalidResponse() {
|
|
18
|
+
throw new EmbeddingProviderError('invalid_response', false);
|
|
19
|
+
}
|
|
20
|
+
function requestInvalid(message) {
|
|
21
|
+
throw new KiokukoError('VALIDATION_ERROR', message);
|
|
22
|
+
}
|
|
23
|
+
function isRecord(value) {
|
|
24
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
function boundedInteger(value, minimum, maximum, label) {
|
|
27
|
+
if (!Number.isSafeInteger(value) || value < minimum || value > maximum)
|
|
28
|
+
requestInvalid(`${label} is invalid`);
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
function endpointUrl(baseUrl) {
|
|
32
|
+
const url = new URL(baseUrl);
|
|
33
|
+
const path = url.pathname.replace(/\/+$/u, '');
|
|
34
|
+
url.pathname = `${path}/embeddings`;
|
|
35
|
+
return url;
|
|
36
|
+
}
|
|
37
|
+
function validateInputs(inputs, batchSize) {
|
|
38
|
+
if (!Array.isArray(inputs) || inputs.length < 1 || inputs.length > Math.min(MAX_EMBEDDING_PROVIDER_INPUTS, batchSize)) {
|
|
39
|
+
requestInvalid('Embedding provider input count is invalid');
|
|
40
|
+
}
|
|
41
|
+
const copied = [...inputs];
|
|
42
|
+
for (const input of copied) {
|
|
43
|
+
if (typeof input !== 'string' || input.length === 0 || INVALID_CONTROL.test(input) || INVALID_UNICODE.test(input)) {
|
|
44
|
+
requestInvalid('Embedding provider input is invalid');
|
|
45
|
+
}
|
|
46
|
+
if (findSecret(input) !== undefined)
|
|
47
|
+
throw new EmbeddingProviderError('secret_blocked', false);
|
|
48
|
+
}
|
|
49
|
+
return copied;
|
|
50
|
+
}
|
|
51
|
+
function requestBody(config, inputs) {
|
|
52
|
+
const body = JSON.stringify({
|
|
53
|
+
input: [...inputs],
|
|
54
|
+
model: config.model,
|
|
55
|
+
encoding_format: 'float',
|
|
56
|
+
});
|
|
57
|
+
if (Buffer.byteLength(body, 'utf8') > MAX_EMBEDDING_PROVIDER_REQUEST_BYTES) {
|
|
58
|
+
requestInvalid('Embedding provider request exceeds the byte limit');
|
|
59
|
+
}
|
|
60
|
+
return body;
|
|
61
|
+
}
|
|
62
|
+
function retryAfterMs(response) {
|
|
63
|
+
const value = response.headers.get('retry-after');
|
|
64
|
+
if (value === null || !/^\d+$/u.test(value))
|
|
65
|
+
return null;
|
|
66
|
+
const seconds = Number(value);
|
|
67
|
+
if (!Number.isSafeInteger(seconds))
|
|
68
|
+
return null;
|
|
69
|
+
return Math.min(MAX_EMBEDDING_PROVIDER_RETRY_DELAY_MS, seconds * 1_000);
|
|
70
|
+
}
|
|
71
|
+
function statusFailure(response) {
|
|
72
|
+
if (response.status === 429)
|
|
73
|
+
return new EmbeddingProviderError('rate_limited', true, retryAfterMs(response));
|
|
74
|
+
if (response.status === 408 || response.status === 425)
|
|
75
|
+
return new EmbeddingProviderError('timeout', true);
|
|
76
|
+
if (response.status >= 500 && response.status <= 599)
|
|
77
|
+
return new EmbeddingProviderError('provider_unavailable', true);
|
|
78
|
+
return new EmbeddingProviderError('provider_unavailable', false);
|
|
79
|
+
}
|
|
80
|
+
async function cancelResponse(response) {
|
|
81
|
+
if (response.body === null)
|
|
82
|
+
return;
|
|
83
|
+
try {
|
|
84
|
+
await response.body.cancel();
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// The response is already being discarded; the public failure remains bounded.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function readResponseText(response) {
|
|
91
|
+
const contentType = response.headers.get('content-type');
|
|
92
|
+
if (contentType === null || !/^application\/(?:[\w.+-]+\+)?json(?:\s*;|$)/iu.test(contentType))
|
|
93
|
+
invalidResponse();
|
|
94
|
+
const contentLength = response.headers.get('content-length');
|
|
95
|
+
if (contentLength !== null && !/^\d+$/u.test(contentLength))
|
|
96
|
+
invalidResponse();
|
|
97
|
+
const declared = contentLength === null ? null : Number(contentLength);
|
|
98
|
+
if (declared !== null && (!Number.isSafeInteger(declared) || declared > MAX_EMBEDDING_PROVIDER_RESPONSE_BYTES))
|
|
99
|
+
invalidResponse();
|
|
100
|
+
const reader = response.body?.getReader();
|
|
101
|
+
if (reader === undefined) {
|
|
102
|
+
let body;
|
|
103
|
+
try {
|
|
104
|
+
body = await response.text();
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
throw new EmbeddingProviderError('provider_unavailable', true);
|
|
108
|
+
}
|
|
109
|
+
if (Buffer.byteLength(body, 'utf8') > MAX_EMBEDDING_PROVIDER_RESPONSE_BYTES || INVALID_UNICODE.test(body))
|
|
110
|
+
invalidResponse();
|
|
111
|
+
return body;
|
|
112
|
+
}
|
|
113
|
+
const chunks = [];
|
|
114
|
+
let size = 0;
|
|
115
|
+
for (;;) {
|
|
116
|
+
let next;
|
|
117
|
+
try {
|
|
118
|
+
next = await reader.read();
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
throw new EmbeddingProviderError('provider_unavailable', true);
|
|
122
|
+
}
|
|
123
|
+
if (next.done)
|
|
124
|
+
break;
|
|
125
|
+
if (next.value === undefined)
|
|
126
|
+
invalidResponse();
|
|
127
|
+
const chunk = Buffer.from(next.value);
|
|
128
|
+
size += chunk.byteLength;
|
|
129
|
+
if (size > MAX_EMBEDDING_PROVIDER_RESPONSE_BYTES) {
|
|
130
|
+
try {
|
|
131
|
+
await reader.cancel();
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Preserve the bounded validation failure if cancellation itself fails.
|
|
135
|
+
}
|
|
136
|
+
invalidResponse();
|
|
137
|
+
}
|
|
138
|
+
chunks.push(chunk);
|
|
139
|
+
}
|
|
140
|
+
let body;
|
|
141
|
+
try {
|
|
142
|
+
body = decoder.decode(Buffer.concat(chunks));
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
invalidResponse();
|
|
146
|
+
}
|
|
147
|
+
if (INVALID_UNICODE.test(body))
|
|
148
|
+
invalidResponse();
|
|
149
|
+
return body;
|
|
150
|
+
}
|
|
151
|
+
function parseProviderResponse(value, config, expectedCount) {
|
|
152
|
+
if (!isRecord(value))
|
|
153
|
+
invalidResponse();
|
|
154
|
+
const allowedRootKeys = new Set(['object', 'data', 'model', 'usage']);
|
|
155
|
+
if (Object.keys(value).some((key) => !allowedRootKeys.has(key))
|
|
156
|
+
|| !Object.prototype.hasOwnProperty.call(value, 'data')
|
|
157
|
+
|| !Object.prototype.hasOwnProperty.call(value, 'model'))
|
|
158
|
+
invalidResponse();
|
|
159
|
+
const response = value;
|
|
160
|
+
if (response.object !== undefined && response.object !== 'list')
|
|
161
|
+
invalidResponse();
|
|
162
|
+
if (response.model !== config.model || !Array.isArray(response.data) || response.data.length !== expectedCount)
|
|
163
|
+
invalidResponse();
|
|
164
|
+
const vectors = new Array(expectedCount);
|
|
165
|
+
const seen = new Set();
|
|
166
|
+
for (const itemValue of response.data) {
|
|
167
|
+
if (!isRecord(itemValue))
|
|
168
|
+
invalidResponse();
|
|
169
|
+
const allowedItemKeys = new Set(['object', 'embedding', 'index']);
|
|
170
|
+
if (Object.keys(itemValue).some((key) => !allowedItemKeys.has(key))
|
|
171
|
+
|| !Object.prototype.hasOwnProperty.call(itemValue, 'embedding')
|
|
172
|
+
|| !Object.prototype.hasOwnProperty.call(itemValue, 'index'))
|
|
173
|
+
invalidResponse();
|
|
174
|
+
const item = itemValue;
|
|
175
|
+
if (item.object !== undefined && item.object !== 'embedding')
|
|
176
|
+
invalidResponse();
|
|
177
|
+
if (typeof item.index !== 'number' || !Number.isSafeInteger(item.index) || item.index < 0 || item.index >= expectedCount || seen.has(item.index))
|
|
178
|
+
invalidResponse();
|
|
179
|
+
if (!Array.isArray(item.embedding) || item.embedding.length !== config.dimensions) {
|
|
180
|
+
throw new EmbeddingProviderError('dimension_mismatch', false);
|
|
181
|
+
}
|
|
182
|
+
for (const valueAtIndex of item.embedding) {
|
|
183
|
+
if (typeof valueAtIndex !== 'number' || !Number.isFinite(valueAtIndex))
|
|
184
|
+
invalidResponse();
|
|
185
|
+
}
|
|
186
|
+
let vector;
|
|
187
|
+
try {
|
|
188
|
+
vector = normalizeVector(item.embedding, config.dimensions);
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
if (error instanceof KiokukoError && error.code === 'VALIDATION_ERROR') {
|
|
192
|
+
throw new EmbeddingProviderError('dimension_mismatch', false);
|
|
193
|
+
}
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
seen.add(item.index);
|
|
197
|
+
vectors[item.index] = vector;
|
|
198
|
+
}
|
|
199
|
+
if (seen.size !== expectedCount || vectors.some((vector) => vector === undefined))
|
|
200
|
+
invalidResponse();
|
|
201
|
+
return Object.freeze(vectors);
|
|
202
|
+
}
|
|
203
|
+
async function defaultSleep(milliseconds, signal) {
|
|
204
|
+
if (milliseconds <= 0)
|
|
205
|
+
return;
|
|
206
|
+
await new Promise((resolve, reject) => {
|
|
207
|
+
let timer;
|
|
208
|
+
const onAbort = () => {
|
|
209
|
+
clearTimeout(timer);
|
|
210
|
+
signal?.removeEventListener('abort', onAbort);
|
|
211
|
+
reject(new EmbeddingProviderError('timeout', false));
|
|
212
|
+
};
|
|
213
|
+
const finish = () => {
|
|
214
|
+
signal?.removeEventListener('abort', onAbort);
|
|
215
|
+
resolve();
|
|
216
|
+
};
|
|
217
|
+
timer = setTimeout(finish, milliseconds);
|
|
218
|
+
if (signal === undefined)
|
|
219
|
+
return;
|
|
220
|
+
if (signal.aborted) {
|
|
221
|
+
clearTimeout(timer);
|
|
222
|
+
reject(new EmbeddingProviderError('timeout', false));
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function retryDelay(attempt, configuredDelayMs, retryAfter) {
|
|
229
|
+
const exponential = configuredDelayMs * (2 ** attempt);
|
|
230
|
+
return Math.min(MAX_EMBEDDING_PROVIDER_RETRY_DELAY_MS, retryAfter ?? exponential);
|
|
231
|
+
}
|
|
232
|
+
export class OpenAICompatibleEmbeddingProvider {
|
|
233
|
+
profile;
|
|
234
|
+
#endpoint;
|
|
235
|
+
#config;
|
|
236
|
+
#fetchImpl;
|
|
237
|
+
#timeoutMs;
|
|
238
|
+
#maxRetries;
|
|
239
|
+
#retryDelayMs;
|
|
240
|
+
#sleepImpl;
|
|
241
|
+
constructor(options) {
|
|
242
|
+
const config = requireEnabledEmbeddingConfig(options.config);
|
|
243
|
+
const baseUrl = normalizeEmbeddingBaseUrl(config.baseUrl, config.allowRemote);
|
|
244
|
+
this.#config = Object.freeze({ ...config, baseUrl });
|
|
245
|
+
this.profile = createEmbeddingProfileIdentity(this.#config);
|
|
246
|
+
this.#endpoint = endpointUrl(baseUrl);
|
|
247
|
+
this.#fetchImpl = options.fetchImpl ?? fetch;
|
|
248
|
+
this.#timeoutMs = boundedInteger(options.timeoutMs ?? config.timeoutMs, 100, 120_000, 'Embedding provider timeout');
|
|
249
|
+
this.#maxRetries = boundedInteger(options.maxRetries ?? DEFAULT_EMBEDDING_PROVIDER_RETRIES, 0, 3, 'Embedding provider retries');
|
|
250
|
+
this.#retryDelayMs = boundedInteger(options.retryDelayMs ?? 100, 0, MAX_EMBEDDING_PROVIDER_RETRY_DELAY_MS, 'Embedding provider retry delay');
|
|
251
|
+
this.#sleepImpl = options.sleepImpl ?? defaultSleep;
|
|
252
|
+
}
|
|
253
|
+
async embed(inputs, options = {}) {
|
|
254
|
+
const normalizedInputs = validateInputs(inputs, this.#config.batchSize);
|
|
255
|
+
const body = requestBody(this.#config, normalizedInputs);
|
|
256
|
+
if (options.signal?.aborted)
|
|
257
|
+
throw new EmbeddingProviderError('timeout', false);
|
|
258
|
+
for (let attempt = 0; attempt <= this.#maxRetries; attempt += 1) {
|
|
259
|
+
let timedOut = false;
|
|
260
|
+
const controller = new AbortController();
|
|
261
|
+
const onAbort = () => controller.abort();
|
|
262
|
+
if (options.signal?.aborted)
|
|
263
|
+
controller.abort();
|
|
264
|
+
else
|
|
265
|
+
options.signal?.addEventListener('abort', onAbort, { once: true });
|
|
266
|
+
const timer = setTimeout(() => {
|
|
267
|
+
timedOut = true;
|
|
268
|
+
controller.abort();
|
|
269
|
+
}, this.#timeoutMs);
|
|
270
|
+
try {
|
|
271
|
+
let response;
|
|
272
|
+
try {
|
|
273
|
+
response = await this.#fetchImpl(this.#endpoint, {
|
|
274
|
+
method: 'POST',
|
|
275
|
+
redirect: 'manual',
|
|
276
|
+
headers: {
|
|
277
|
+
accept: 'application/json',
|
|
278
|
+
'content-type': 'application/json',
|
|
279
|
+
...(this.#config.apiKey === undefined ? {} : { authorization: `Bearer ${this.#config.apiKey}` }),
|
|
280
|
+
},
|
|
281
|
+
body,
|
|
282
|
+
signal: controller.signal,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
throw timedOut || options.signal?.aborted === true
|
|
287
|
+
? new EmbeddingProviderError('timeout', timedOut)
|
|
288
|
+
: new EmbeddingProviderError('provider_unavailable', true);
|
|
289
|
+
}
|
|
290
|
+
if (response.status !== 200) {
|
|
291
|
+
const failure = statusFailure(response);
|
|
292
|
+
await cancelResponse(response);
|
|
293
|
+
throw failure;
|
|
294
|
+
}
|
|
295
|
+
const responseText = await readResponseText(response);
|
|
296
|
+
let parsed;
|
|
297
|
+
try {
|
|
298
|
+
parsed = parseStrictJson(responseText, { allowTrailingComma: false, disallowComments: true, allowEmptyContent: false }, 'Embedding provider response is invalid');
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
invalidResponse();
|
|
302
|
+
}
|
|
303
|
+
return parseProviderResponse(parsed, this.#config, normalizedInputs.length);
|
|
304
|
+
}
|
|
305
|
+
catch (error) {
|
|
306
|
+
const classified = error instanceof EmbeddingProviderError
|
|
307
|
+
? error
|
|
308
|
+
: error instanceof KiokukoError && error.code === 'VALIDATION_ERROR'
|
|
309
|
+
? new EmbeddingProviderError('invalid_response', false)
|
|
310
|
+
: new EmbeddingProviderError('provider_unavailable', true);
|
|
311
|
+
const failure = timedOut
|
|
312
|
+
? new EmbeddingProviderError('timeout', true)
|
|
313
|
+
: options.signal?.aborted === true
|
|
314
|
+
? new EmbeddingProviderError('timeout', false)
|
|
315
|
+
: classified;
|
|
316
|
+
if (!failure.retryable || attempt >= this.#maxRetries || options.signal?.aborted)
|
|
317
|
+
throw failure;
|
|
318
|
+
const delay = retryDelay(attempt, this.#retryDelayMs, failure.retryAfterMs);
|
|
319
|
+
await this.#sleepImpl(delay, options.signal);
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
clearTimeout(timer);
|
|
323
|
+
options.signal?.removeEventListener('abort', onAbort);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
throw new EmbeddingProviderError('provider_unavailable', false);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
export { OpenAICompatibleEmbeddingProvider as OpenAICompatibleProvider };
|
|
330
|
+
//# sourceMappingURL=openai-compatible-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-compatible-provider.js","sourceRoot":"","sources":["../../src/embedding/openai-compatible-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EmbeddingConfig, EmbeddingProfile, EmbeddingProfileIdentity, EnabledEmbeddingConfig } from './types.js';
|
|
2
|
+
export declare function endpointFingerprint(endpoint: string): string;
|
|
3
|
+
export declare function embeddingProfileId(identity: EmbeddingProfileIdentity): string;
|
|
4
|
+
export declare function createEmbeddingProfileIdentity(config: EnabledEmbeddingConfig): EmbeddingProfileIdentity;
|
|
5
|
+
export declare function createEmbeddingProfile(config: EmbeddingConfig): EmbeddingProfile;
|
|
6
|
+
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/embedding/profile.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAMtH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,CAE7E;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,sBAAsB,GAAG,wBAAwB,CAYvG;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,GAAG,gBAAgB,CAIhF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { canonicalJson } from '../serialization/validate.js';
|
|
3
|
+
import { requireEnabledEmbeddingConfig } from './config.js';
|
|
4
|
+
function sha256(value) {
|
|
5
|
+
return createHash('sha256').update(value).digest('hex');
|
|
6
|
+
}
|
|
7
|
+
export function endpointFingerprint(endpoint) {
|
|
8
|
+
return sha256(endpoint);
|
|
9
|
+
}
|
|
10
|
+
export function embeddingProfileId(identity) {
|
|
11
|
+
return sha256(canonicalJson(identity));
|
|
12
|
+
}
|
|
13
|
+
export function createEmbeddingProfileIdentity(config) {
|
|
14
|
+
return {
|
|
15
|
+
schemaVersion: 1,
|
|
16
|
+
providerKind: config.provider,
|
|
17
|
+
endpointFingerprint: endpointFingerprint(config.baseUrl),
|
|
18
|
+
model: config.model,
|
|
19
|
+
dimensions: config.dimensions,
|
|
20
|
+
distanceMetric: 'cosine',
|
|
21
|
+
documentTemplateVersion: 1,
|
|
22
|
+
queryTemplateVersion: 1,
|
|
23
|
+
distanceCeiling: config.distanceCeiling,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function createEmbeddingProfile(config) {
|
|
27
|
+
const enabled = requireEnabledEmbeddingConfig(config);
|
|
28
|
+
const identity = createEmbeddingProfileIdentity(enabled);
|
|
29
|
+
return Object.freeze({ profileId: embeddingProfileId(identity), identity: Object.freeze(identity) });
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/embedding/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAG5D,SAAS,MAAM,CAAC,KAA0B;IACxC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAkC;IACnE,OAAO,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,MAA8B;IAC3E,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC,QAAQ;QAC7B,mBAAmB,EAAE,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC;QACxD,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,cAAc,EAAE,QAAQ;QACxB,uBAAuB,EAAE,CAAC;QAC1B,oBAAoB,EAAE,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC,eAAe;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAuB;IAC5D,MAAM,OAAO,GAAG,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,8BAA8B,CAAC,OAAO,CAAC,CAAC;IACzD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,kBAAkB,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvG,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EmbeddingProvider } from './types.js';
|
|
2
|
+
export type EmbeddingProviderFailureCode = 'timeout' | 'rate_limited' | 'provider_unavailable' | 'invalid_response' | 'dimension_mismatch' | 'secret_blocked';
|
|
3
|
+
/** A provider failure contains only a stable classification, never remote data. */
|
|
4
|
+
export declare class EmbeddingProviderError extends Error {
|
|
5
|
+
readonly code: EmbeddingProviderFailureCode;
|
|
6
|
+
readonly retryable: boolean;
|
|
7
|
+
readonly retryAfterMs: number | null;
|
|
8
|
+
readonly name = "EmbeddingProviderError";
|
|
9
|
+
constructor(code: EmbeddingProviderFailureCode, retryable: boolean, retryAfterMs?: number | null);
|
|
10
|
+
}
|
|
11
|
+
export declare function isEmbeddingProviderError(value: unknown): value is EmbeddingProviderError;
|
|
12
|
+
export type { EmbeddingProvider };
|
|
13
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/embedding/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,MAAM,4BAA4B,GACpC,SAAS,GACT,cAAc,GACd,sBAAsB,GACtB,kBAAkB,GAClB,oBAAoB,GACpB,gBAAgB,CAAC;AAErB,mFAAmF;AACnF,qBAAa,sBAAuB,SAAQ,KAAK;IAI7C,QAAQ,CAAC,IAAI,EAAE,4BAA4B;IAC3C,QAAQ,CAAC,SAAS,EAAE,OAAO;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IALtC,SAAkB,IAAI,4BAA4B;gBAGvC,IAAI,EAAE,4BAA4B,EAClC,SAAS,EAAE,OAAO,EAClB,YAAY,GAAE,MAAM,GAAG,IAAW;CAI9C;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sBAAsB,CAExF;AAED,YAAY,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** A provider failure contains only a stable classification, never remote data. */
|
|
2
|
+
export class EmbeddingProviderError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
retryable;
|
|
5
|
+
retryAfterMs;
|
|
6
|
+
name = 'EmbeddingProviderError';
|
|
7
|
+
constructor(code, retryable, retryAfterMs = null) {
|
|
8
|
+
super(code);
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.retryable = retryable;
|
|
11
|
+
this.retryAfterMs = retryAfterMs;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function isEmbeddingProviderError(value) {
|
|
15
|
+
return value instanceof EmbeddingProviderError;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/embedding/provider.ts"],"names":[],"mappings":"AAUA,mFAAmF;AACnF,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAIpC;IACA;IACA;IALO,IAAI,GAAG,wBAAwB,CAAC;IAElD,YACW,IAAkC,EAClC,SAAkB,EAClB,eAA8B,IAAI;QAE3C,KAAK,CAAC,IAAI,CAAC,CAAC;QAJH,SAAI,GAAJ,IAAI,CAA8B;QAClC,cAAS,GAAT,SAAS,CAAS;QAClB,iBAAY,GAAZ,YAAY,CAAsB;IAG7C,CAAC;CACF;AAED,MAAM,UAAU,wBAAwB,CAAC,KAAc;IACrD,OAAO,KAAK,YAAY,sBAAsB,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { SqliteDatabase } from '../db/adapter.js';
|
|
2
|
+
export declare const QUERY_TEMPLATE_VERSION: 1;
|
|
3
|
+
export declare const MAX_QUERY_TEXT_BYTES: number;
|
|
4
|
+
export declare const QUERY_EMBEDDING_CACHE_LIMIT = 512;
|
|
5
|
+
export interface StoredQueryEmbedding {
|
|
6
|
+
readonly profileId: string;
|
|
7
|
+
readonly queryHash: string;
|
|
8
|
+
readonly dimensions: number;
|
|
9
|
+
readonly vector: Float32Array;
|
|
10
|
+
readonly vectorHash: string;
|
|
11
|
+
readonly createdAt: string;
|
|
12
|
+
readonly lastUsedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface QueryEmbeddingInput {
|
|
15
|
+
readonly profileId: string;
|
|
16
|
+
readonly queryHash: string;
|
|
17
|
+
readonly vector: Float32Array | readonly number[];
|
|
18
|
+
}
|
|
19
|
+
export interface QueryEmbeddingWriteOptions {
|
|
20
|
+
readonly now?: string;
|
|
21
|
+
readonly expectedGeneration?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function normalizeEmbeddingQuery(value: string): string;
|
|
24
|
+
/** Hash only the canonical query template; the raw query is never stored. */
|
|
25
|
+
export declare function queryEmbeddingHash(value: string): string;
|
|
26
|
+
export declare const embeddingQueryHash: typeof queryEmbeddingHash;
|
|
27
|
+
export declare function readQueryEmbeddingInTransaction(database: SqliteDatabase, input: {
|
|
28
|
+
profileId: string;
|
|
29
|
+
queryHash: string;
|
|
30
|
+
now?: string;
|
|
31
|
+
}): StoredQueryEmbedding | undefined;
|
|
32
|
+
export declare function readQueryEmbedding(database: SqliteDatabase, input: {
|
|
33
|
+
profileId: string;
|
|
34
|
+
queryHash: string;
|
|
35
|
+
now?: string;
|
|
36
|
+
}): StoredQueryEmbedding | undefined;
|
|
37
|
+
export declare function writeQueryEmbeddingInTransaction(database: SqliteDatabase, input: QueryEmbeddingInput, options?: QueryEmbeddingWriteOptions): StoredQueryEmbedding;
|
|
38
|
+
export declare function writeQueryEmbedding(database: SqliteDatabase, input: QueryEmbeddingInput, options?: QueryEmbeddingWriteOptions): StoredQueryEmbedding;
|
|
39
|
+
//# sourceMappingURL=query-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-cache.d.ts","sourceRoot":"","sources":["../../src/embedding/query-cache.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAa,MAAM,kBAAkB,CAAC;AAKlE,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC;AACjD,eAAO,MAAM,oBAAoB,QAAY,CAAC;AAC9C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAM/C,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,MAAM,EAAE,CAAC;CACnD;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AAqCD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,eAAO,MAAM,kBAAkB,2BAAqB,CAAC;AA2DrD,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D,oBAAoB,GAAG,SAAS,CAoBlC;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D,oBAAoB,GAAG,SAAS,CAElC;AAED,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,mBAAmB,EAC1B,OAAO,GAAE,0BAA+B,GACvC,oBAAoB,CA0BtB;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,mBAAmB,EAC1B,OAAO,GAAE,0BAA+B,GACvC,oBAAoB,CAEtB"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { canonicalContentHash } from '../serialization/validate.js';
|
|
2
|
+
import { validateTimestamp } from '../ledger/validate.js';
|
|
3
|
+
import { withImmediateTransaction } from '../db/transaction.js';
|
|
4
|
+
import { KiokukoError } from '../errors.js';
|
|
5
|
+
import { readEmbeddingProfile, readEmbeddingRuntimeState } from './store.js';
|
|
6
|
+
import { decodeVector, encodeVector, hashVectorBytes } from './vector.js';
|
|
7
|
+
export const QUERY_TEMPLATE_VERSION = 1;
|
|
8
|
+
export const MAX_QUERY_TEXT_BYTES = 32 * 1024;
|
|
9
|
+
export const QUERY_EMBEDDING_CACHE_LIMIT = 512;
|
|
10
|
+
const HASH_PATTERN = /^[0-9a-f]{64}$/u;
|
|
11
|
+
const INVALID_CONTROL = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/u;
|
|
12
|
+
const INVALID_UNICODE = /[\p{Cs}\uFFFD]/u;
|
|
13
|
+
function invalid(message) {
|
|
14
|
+
throw new KiokukoError('VALIDATION_ERROR', message);
|
|
15
|
+
}
|
|
16
|
+
function integrity(message) {
|
|
17
|
+
throw new KiokukoError('INTEGRITY_ERROR', message);
|
|
18
|
+
}
|
|
19
|
+
function conflict(message) {
|
|
20
|
+
throw new KiokukoError('CONFLICT', message);
|
|
21
|
+
}
|
|
22
|
+
function hash(value, label) {
|
|
23
|
+
if (typeof value !== 'string' || !HASH_PATTERN.test(value))
|
|
24
|
+
invalid(`${label} must be a lowercase SHA-256 hash`);
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
function canonicalQueryText(value) {
|
|
28
|
+
if (typeof value !== 'string')
|
|
29
|
+
invalid('Query text must be a string');
|
|
30
|
+
const normalized = value.normalize('NFKC').replaceAll('\r\n', '\n').replaceAll('\r', '\n').trim();
|
|
31
|
+
if (normalized.length === 0 || INVALID_CONTROL.test(normalized) || INVALID_UNICODE.test(normalized))
|
|
32
|
+
invalid('Query text is invalid');
|
|
33
|
+
if (Buffer.byteLength(normalized, 'utf8') > MAX_QUERY_TEXT_BYTES)
|
|
34
|
+
invalid('Query text exceeds the byte limit');
|
|
35
|
+
return normalized;
|
|
36
|
+
}
|
|
37
|
+
export function normalizeEmbeddingQuery(value) {
|
|
38
|
+
return canonicalQueryText(value);
|
|
39
|
+
}
|
|
40
|
+
/** Hash only the canonical query template; the raw query is never stored. */
|
|
41
|
+
export function queryEmbeddingHash(value) {
|
|
42
|
+
return canonicalContentHash({ templateVersion: QUERY_TEMPLATE_VERSION, text: canonicalQueryText(value) });
|
|
43
|
+
}
|
|
44
|
+
export const embeddingQueryHash = queryEmbeddingHash;
|
|
45
|
+
function storedTimestamp(value, label) {
|
|
46
|
+
if (typeof value !== 'string')
|
|
47
|
+
integrity(`${label} is invalid`);
|
|
48
|
+
try {
|
|
49
|
+
return validateTimestamp(value, label);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
integrity(`${label} is invalid`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function storedQueryEmbedding(row) {
|
|
56
|
+
const profileId = hash(row.profile_id, 'Stored query embedding profile ID');
|
|
57
|
+
const queryHash = hash(row.query_hash, 'Stored query embedding query hash');
|
|
58
|
+
if (typeof row.dimensions !== 'number' || !Number.isSafeInteger(row.dimensions) || row.dimensions < 2 || row.dimensions > 8192) {
|
|
59
|
+
integrity('Stored query embedding dimensions are invalid');
|
|
60
|
+
}
|
|
61
|
+
const vectorHash = hash(row.vector_hash, 'Stored query embedding vector hash');
|
|
62
|
+
let vector;
|
|
63
|
+
try {
|
|
64
|
+
vector = decodeVector(row.embedding, row.dimensions, vectorHash);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
integrity('Stored query embedding vector is invalid');
|
|
68
|
+
}
|
|
69
|
+
const createdAt = storedTimestamp(row.created_at, 'query embedding created_at');
|
|
70
|
+
const lastUsedAt = storedTimestamp(row.last_used_at, 'query embedding last_used_at');
|
|
71
|
+
return { profileId, queryHash, dimensions: row.dimensions, vector, vectorHash, createdAt, lastUsedAt };
|
|
72
|
+
}
|
|
73
|
+
function validateWriteInput(input) {
|
|
74
|
+
return {
|
|
75
|
+
profileId: hash(input.profileId, 'profileId'),
|
|
76
|
+
queryHash: hash(input.queryHash, 'queryHash'),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function assertExpectedGeneration(database, profileId, expectedGeneration) {
|
|
80
|
+
if (expectedGeneration === undefined)
|
|
81
|
+
return;
|
|
82
|
+
if (!Number.isSafeInteger(expectedGeneration) || expectedGeneration < 1)
|
|
83
|
+
invalid('expectedGeneration must be a positive integer');
|
|
84
|
+
const runtime = readEmbeddingRuntimeState(database);
|
|
85
|
+
if (runtime.activeProfileId !== profileId || runtime.generation !== expectedGeneration) {
|
|
86
|
+
conflict('Embedding profile changed while writing the query cache');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function pruneProfileCache(database, profileId) {
|
|
90
|
+
database.prepare(`
|
|
91
|
+
DELETE FROM query_embeddings
|
|
92
|
+
WHERE profile_id = ?
|
|
93
|
+
AND query_hash NOT IN (
|
|
94
|
+
SELECT query_hash
|
|
95
|
+
FROM query_embeddings
|
|
96
|
+
WHERE profile_id = ?
|
|
97
|
+
ORDER BY last_used_at DESC, query_hash ASC
|
|
98
|
+
LIMIT ?
|
|
99
|
+
)
|
|
100
|
+
`).run(profileId, profileId, QUERY_EMBEDDING_CACHE_LIMIT);
|
|
101
|
+
}
|
|
102
|
+
export function readQueryEmbeddingInTransaction(database, input) {
|
|
103
|
+
const profileId = hash(input.profileId, 'profileId');
|
|
104
|
+
const queryHash = hash(input.queryHash, 'queryHash');
|
|
105
|
+
const now = validateTimestamp(input.now ?? new Date().toISOString(), 'now');
|
|
106
|
+
readEmbeddingRuntimeState(database);
|
|
107
|
+
const row = database.prepare(`
|
|
108
|
+
SELECT profile_id, query_hash, dimensions, embedding, vector_hash, created_at, last_used_at
|
|
109
|
+
FROM query_embeddings
|
|
110
|
+
WHERE profile_id = ? AND query_hash = ?
|
|
111
|
+
`).get(profileId, queryHash);
|
|
112
|
+
if (row === undefined)
|
|
113
|
+
return undefined;
|
|
114
|
+
const stored = storedQueryEmbedding(row);
|
|
115
|
+
const profile = readEmbeddingProfile(database, profileId);
|
|
116
|
+
if (profile === undefined || profile.identity.dimensions !== stored.dimensions)
|
|
117
|
+
integrity('Stored query embedding profile is invalid');
|
|
118
|
+
database.prepare(`
|
|
119
|
+
UPDATE query_embeddings
|
|
120
|
+
SET last_used_at = ?
|
|
121
|
+
WHERE profile_id = ? AND query_hash = ?
|
|
122
|
+
`).run(now, profileId, queryHash);
|
|
123
|
+
return { ...stored, lastUsedAt: now, vector: new Float32Array(stored.vector) };
|
|
124
|
+
}
|
|
125
|
+
export function readQueryEmbedding(database, input) {
|
|
126
|
+
return withImmediateTransaction(database, () => readQueryEmbeddingInTransaction(database, input));
|
|
127
|
+
}
|
|
128
|
+
export function writeQueryEmbeddingInTransaction(database, input, options = {}) {
|
|
129
|
+
const { profileId, queryHash } = validateWriteInput(input);
|
|
130
|
+
const now = validateTimestamp(options.now ?? new Date().toISOString(), 'now');
|
|
131
|
+
assertExpectedGeneration(database, profileId, options.expectedGeneration);
|
|
132
|
+
const profile = readEmbeddingProfile(database, profileId);
|
|
133
|
+
if (profile === undefined)
|
|
134
|
+
throw new KiokukoError('NOT_FOUND', 'Embedding profile not found');
|
|
135
|
+
const bytes = encodeVector(input.vector, profile.identity.dimensions);
|
|
136
|
+
const vectorHash = hashVectorBytes(bytes);
|
|
137
|
+
database.prepare(`
|
|
138
|
+
INSERT INTO query_embeddings (
|
|
139
|
+
profile_id, query_hash, dimensions, embedding, vector_hash, created_at, last_used_at
|
|
140
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
141
|
+
ON CONFLICT(profile_id, query_hash) DO UPDATE SET
|
|
142
|
+
dimensions = excluded.dimensions,
|
|
143
|
+
embedding = excluded.embedding,
|
|
144
|
+
vector_hash = excluded.vector_hash,
|
|
145
|
+
last_used_at = excluded.last_used_at
|
|
146
|
+
`).run(profileId, queryHash, profile.identity.dimensions, bytes, vectorHash, now, now);
|
|
147
|
+
pruneProfileCache(database, profileId);
|
|
148
|
+
const row = database.prepare(`
|
|
149
|
+
SELECT profile_id, query_hash, dimensions, embedding, vector_hash, created_at, last_used_at
|
|
150
|
+
FROM query_embeddings
|
|
151
|
+
WHERE profile_id = ? AND query_hash = ?
|
|
152
|
+
`).get(profileId, queryHash);
|
|
153
|
+
if (row === undefined)
|
|
154
|
+
integrity('Query embedding write could not be read back');
|
|
155
|
+
return storedQueryEmbedding(row);
|
|
156
|
+
}
|
|
157
|
+
export function writeQueryEmbedding(database, input, options = {}) {
|
|
158
|
+
return withImmediateTransaction(database, () => writeQueryEmbeddingInTransaction(database, input, options));
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=query-cache.js.map
|