@oscharko-dev/keiko-server 0.2.1 → 0.2.3
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/dist/.tsbuildinfo +1 -1
- package/dist/deps.d.ts +1 -0
- package/dist/deps.d.ts.map +1 -1
- package/dist/gateway-setup.d.ts.map +1 -1
- package/dist/gateway-setup.js +82 -6
- package/dist/local-knowledge-handlers.d.ts.map +1 -1
- package/dist/local-knowledge-handlers.js +62 -11
- package/package.json +19 -19
package/dist/deps.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface GatewayDiscoveredModels {
|
|
|
26
26
|
readonly modelIds: readonly string[];
|
|
27
27
|
readonly chatModelIds: readonly string[];
|
|
28
28
|
readonly embeddingModelIds: readonly string[];
|
|
29
|
+
readonly imageInputModelIds?: readonly string[];
|
|
29
30
|
}
|
|
30
31
|
export type GatewayModelDiscoveryOutput = readonly string[] | GatewayDiscoveredModels;
|
|
31
32
|
export interface UiHandlerDeps {
|
package/dist/deps.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../src/deps.ts"],"names":[],"mappings":"AAQA,OAAO,EAML,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAQ7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAML,KAAK,OAAO,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAkC,KAAK,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAC9F,OAAO,EAA+B,KAAK,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACpG,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGzE,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EACV,2BAA2B,EAC3B,2BAA2B,EAC3B,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,wCAAwC,CAAC;AAChD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAG7E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAErF,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,+CAA+C,CAAC;AAIvD,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;AAMnD,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;AAC1E,KAAK,mBAAmB,GAAG,WAAW,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,OAAO,IAAI,aAAa,GAAG,SAAS,CAAC;IACrC,OAAO,IAAI,OAAO,CAAC;IACnB,GAAG,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CAChE;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../src/deps.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-setup.d.ts","sourceRoot":"","sources":["../src/gateway-setup.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,KAAK,EACV,uBAAuB,EAGvB,aAAa,EACd,MAAM,WAAW,CAAC;AAcnB,eAAO,MAAM,qBAAqB,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway-setup.d.ts","sourceRoot":"","sources":["../src/gateway-setup.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,KAAK,EACV,uBAAuB,EAGvB,aAAa,EACd,MAAM,WAAW,CAAC;AAcnB,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAoXzC,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAO/E;AAoCD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE1E;AAKD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,CA2B7E;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAElE;AAOD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,MAAM,EAAE,CAE7E;AAED,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,CAE3F;AA2JD,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EACzC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CA2B5B;AA+vBD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAkBtB"}
|
package/dist/gateway-setup.js
CHANGED
|
@@ -25,6 +25,7 @@ const FIGMA_CREDENTIAL_SMOKE_RESPONSE_BYTES = 64_000;
|
|
|
25
25
|
const SETUP_SMOKE_CONCURRENCY = 4;
|
|
26
26
|
const CHAT_COMPATIBLE_MODES = new Set(["chat", "completion", "responses"]);
|
|
27
27
|
const EMBEDDING_ID_PATTERN = /(?:^|[-_/. ])(?:text-)?embed(?:ding)?s?(?:[-_/. ]|$)|ada-002(?:$|[-_/. ])/i;
|
|
28
|
+
const IMAGE_INPUT_ID_PATTERN = /(?:^|[-_/. ])(?:vision|multimodal|multi-modal|llava|pixtral|omni|gpt-4o)(?:$|[-_/. ])|(?:^|[-_/. ])vl(?:$|[-_/. ])|qwen(?:2(?:\.5)?|3)?[-_/. ]?vl(?:$|[-_/. ])/i;
|
|
28
29
|
class BodyTooLargeError extends Error {
|
|
29
30
|
constructor() {
|
|
30
31
|
super("request body too large");
|
|
@@ -127,6 +128,54 @@ function providerRaw(modelId, baseUrl, apiKey, options = {}) {
|
|
|
127
128
|
function isLikelyEmbeddingModelId(modelId) {
|
|
128
129
|
return EMBEDDING_ID_PATTERN.test(modelId);
|
|
129
130
|
}
|
|
131
|
+
function isLikelyImageInputModelId(modelId) {
|
|
132
|
+
return IMAGE_INPUT_ID_PATTERN.test(modelId);
|
|
133
|
+
}
|
|
134
|
+
function discoveryRecords(item) {
|
|
135
|
+
return [
|
|
136
|
+
item,
|
|
137
|
+
nestedRecord(item, "model_info"),
|
|
138
|
+
nestedRecord(item, "litellm_params"),
|
|
139
|
+
nestedRecord(item, "capabilities"),
|
|
140
|
+
].filter((record) => record !== undefined);
|
|
141
|
+
}
|
|
142
|
+
function booleanFieldFromRecords(records, fields) {
|
|
143
|
+
return records.some((record) => fields.some((field) => record[field] === true));
|
|
144
|
+
}
|
|
145
|
+
function stringsFromValue(value) {
|
|
146
|
+
if (typeof value === "string")
|
|
147
|
+
return [value];
|
|
148
|
+
if (Array.isArray(value)) {
|
|
149
|
+
return value.filter((entry) => typeof entry === "string");
|
|
150
|
+
}
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
function stringListFieldFromRecords(records, fields) {
|
|
154
|
+
return records.flatMap((record) => fields.flatMap((field) => stringsFromValue(record[field]).map((value) => value.toLowerCase())));
|
|
155
|
+
}
|
|
156
|
+
function supportsImageInputFromDiscoveryItem(item, modelId) {
|
|
157
|
+
const records = discoveryRecords(item);
|
|
158
|
+
if (booleanFieldFromRecords(records, [
|
|
159
|
+
"supports_vision",
|
|
160
|
+
"supportsVision",
|
|
161
|
+
"vision",
|
|
162
|
+
"image_input",
|
|
163
|
+
"imageInput",
|
|
164
|
+
"supports_image_input",
|
|
165
|
+
"supportsImageInput",
|
|
166
|
+
])) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
const modalities = stringListFieldFromRecords(records, [
|
|
170
|
+
"input_modalities",
|
|
171
|
+
"inputModalities",
|
|
172
|
+
"modalities",
|
|
173
|
+
]);
|
|
174
|
+
if (modalities.some((entry) => entry === "image" || entry === "vision")) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
return isLikelyImageInputModelId(modelId);
|
|
178
|
+
}
|
|
130
179
|
function createDefaultEmbeddingCapabilityForSetup(modelId) {
|
|
131
180
|
return {
|
|
132
181
|
id: modelId,
|
|
@@ -273,12 +322,16 @@ function classifyDiscoveryItem(item) {
|
|
|
273
322
|
return undefined;
|
|
274
323
|
}
|
|
275
324
|
if (isExplicitlyEmbeddingModel(item)) {
|
|
276
|
-
return { id, kind: "embedding" };
|
|
325
|
+
return { id, kind: "embedding", supportsImageInput: false };
|
|
277
326
|
}
|
|
278
327
|
if (isExplicitlyNonChatModel(item)) {
|
|
279
|
-
return isLikelyEmbeddingModelId(id)
|
|
328
|
+
return isLikelyEmbeddingModelId(id)
|
|
329
|
+
? { id, kind: "embedding", supportsImageInput: false }
|
|
330
|
+
: undefined;
|
|
280
331
|
}
|
|
281
|
-
return isLikelyEmbeddingModelId(id)
|
|
332
|
+
return isLikelyEmbeddingModelId(id)
|
|
333
|
+
? { id, kind: "embedding", supportsImageInput: false }
|
|
334
|
+
: { id, kind: "chat", supportsImageInput: supportsImageInputFromDiscoveryItem(item, id) };
|
|
282
335
|
}
|
|
283
336
|
// Issue #144: exported as part of the discovery-normalization seam. Gateway setup now returns
|
|
284
337
|
// embedding-capable records so setup can persist them for Local Knowledge while keeping them out of
|
|
@@ -314,6 +367,9 @@ export function parseModelDiscovery(payload) {
|
|
|
314
367
|
embeddingModelIds: limited
|
|
315
368
|
.filter((entry) => entry.kind === "embedding")
|
|
316
369
|
.map((entry) => entry.id),
|
|
370
|
+
imageInputModelIds: limited
|
|
371
|
+
.filter((entry) => entry.kind === "chat" && entry.supportsImageInput)
|
|
372
|
+
.map((entry) => entry.id),
|
|
317
373
|
};
|
|
318
374
|
}
|
|
319
375
|
export function parseModelList(payload) {
|
|
@@ -701,6 +757,19 @@ function assertImageInputModelsWereTested(imageInputModelIds, testedModelIds) {
|
|
|
701
757
|
throw new Error("imageInputModelIds must match tested chat-callable model ids.");
|
|
702
758
|
}
|
|
703
759
|
}
|
|
760
|
+
function testedImageInputModelIds(manualModelIds, discoveredModelIds, testedModelIds) {
|
|
761
|
+
const tested = new Set(testedModelIds);
|
|
762
|
+
const merged = [];
|
|
763
|
+
const seen = new Set();
|
|
764
|
+
for (const modelId of [...manualModelIds, ...discoveredModelIds]) {
|
|
765
|
+
if (!tested.has(modelId) || seen.has(modelId)) {
|
|
766
|
+
continue;
|
|
767
|
+
}
|
|
768
|
+
seen.add(modelId);
|
|
769
|
+
merged.push(modelId);
|
|
770
|
+
}
|
|
771
|
+
return merged;
|
|
772
|
+
}
|
|
704
773
|
function validationConfigForSetup(input) {
|
|
705
774
|
const validationRawConfig = buildRawConfig(input.baseUrl, input.apiKey, ["setup-validation"], {
|
|
706
775
|
apiKeyHeaderName: input.apiKeyHeaderName,
|
|
@@ -716,6 +785,7 @@ function normalizeLegacyDiscoveryResult(modelIds) {
|
|
|
716
785
|
modelIds,
|
|
717
786
|
chatModelIds: modelIds.filter((modelId) => !embeddingSet.has(modelId)),
|
|
718
787
|
embeddingModelIds,
|
|
788
|
+
imageInputModelIds: [],
|
|
719
789
|
};
|
|
720
790
|
}
|
|
721
791
|
function isStructuredDiscoveryResult(result) {
|
|
@@ -733,6 +803,7 @@ function normalizeDiscoveryResult(result) {
|
|
|
733
803
|
modelIds: result.modelIds,
|
|
734
804
|
chatModelIds: result.chatModelIds,
|
|
735
805
|
embeddingModelIds: result.embeddingModelIds,
|
|
806
|
+
imageInputModelIds: result.imageInputModelIds ?? [],
|
|
736
807
|
};
|
|
737
808
|
}
|
|
738
809
|
return normalizeLegacyDiscoveryResult(result);
|
|
@@ -744,6 +815,7 @@ function candidateModelsFromDeploymentNames(deploymentNames) {
|
|
|
744
815
|
modelIds: deploymentNames,
|
|
745
816
|
chatModelIds: deploymentNames.filter((modelId) => !embeddingSet.has(modelId)),
|
|
746
817
|
embeddingModelIds,
|
|
818
|
+
imageInputModelIds: [],
|
|
747
819
|
};
|
|
748
820
|
}
|
|
749
821
|
async function candidateModelIdsForSetup(input, validationConfig) {
|
|
@@ -752,11 +824,11 @@ async function candidateModelIdsForSetup(input, validationConfig) {
|
|
|
752
824
|
}
|
|
753
825
|
return normalizeDiscoveryResult(await input.discovery(input.baseUrl, input.apiKey, input.apiKeyHeaderName, validationConfig.egress));
|
|
754
826
|
}
|
|
755
|
-
function finalRawConfigForSetup(input, testedModelIds, embeddingModelIds) {
|
|
827
|
+
function finalRawConfigForSetup(input, testedModelIds, embeddingModelIds, imageInputModelIds) {
|
|
756
828
|
const configuredModelIds = mergeChatAndEmbeddingModelIds(testedModelIds, embeddingModelIds);
|
|
757
829
|
const rawConfig = buildRawConfig(input.baseUrl, input.apiKey, configuredModelIds, {
|
|
758
830
|
apiKeyHeaderName: input.apiKeyHeaderName,
|
|
759
|
-
imageInputModelIds
|
|
831
|
+
imageInputModelIds,
|
|
760
832
|
embeddingModelIds,
|
|
761
833
|
timeoutMs: input.timeoutMs,
|
|
762
834
|
});
|
|
@@ -772,6 +844,10 @@ function skippedModelIdsForSetup(candidateModelIds, testedModelIds, embeddingMod
|
|
|
772
844
|
const acceptedModelIds = new Set([...testedModelIds, ...embeddingModelIds]);
|
|
773
845
|
return candidateModelIds.filter((modelId) => !acceptedModelIds.has(modelId));
|
|
774
846
|
}
|
|
847
|
+
function finalRawConfigForTestedSetup(input, testedModelIds, candidateModels) {
|
|
848
|
+
const imageInputModelIds = testedImageInputModelIds(input.imageInputModelIds, candidateModels.imageInputModelIds, testedModelIds);
|
|
849
|
+
return finalRawConfigForSetup(input, testedModelIds, candidateModels.embeddingModelIds, imageInputModelIds);
|
|
850
|
+
}
|
|
775
851
|
async function verifySetupCandidate(input) {
|
|
776
852
|
// Defence-in-depth: never send the credential to a candidate URL that has not passed the same
|
|
777
853
|
// scheme/credential/loopback validation as the originally submitted base URL.
|
|
@@ -793,7 +869,7 @@ async function verifySetupCandidate(input) {
|
|
|
793
869
|
const candidateConfig = parseGatewayConfig(withInheritedEgress(candidateRawConfig, input.egress), input.env);
|
|
794
870
|
const testedModelIds = await input.tester(candidateConfig, candidateModels.chatModelIds);
|
|
795
871
|
assertImageInputModelsWereTested(input.imageInputModelIds, testedModelIds);
|
|
796
|
-
const rawConfigWithOptionalBlocks =
|
|
872
|
+
const rawConfigWithOptionalBlocks = finalRawConfigForTestedSetup(input, testedModelIds, candidateModels);
|
|
797
873
|
const config = parseGatewayConfig(withInheritedEgress(rawConfigWithOptionalBlocks, input.egress), input.env);
|
|
798
874
|
return {
|
|
799
875
|
rawConfig: rawConfigWithOptionalBlocks,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-knowledge-handlers.d.ts","sourceRoot":"","sources":["../src/local-knowledge-handlers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"local-knowledge-handlers.d.ts","sourceRoot":"","sources":["../src/local-knowledge-handlers.ts"],"names":[],"mappings":"AAuDA,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,mBAAmB,EAMzB,MAAM,mCAAmC,CAAC;AAiO3C,UAAU,wBAAwB;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5D,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;CACvD;AA0uBD,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,GAClD,MAAM,GAAG,SAAS,CAEpB;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,wBAAwB,GAAG,IAAI,GAAG,SAAS,GAClD,SAAS,MAAM,EAAE,CAKnB;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,aAAa,GAAG,SAAS,GAChC,SAAS,mBAAmB,EAAE,CAGhC;AAoTD,wBAAsB,gCAAgC,CACpD,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAgBtB;AAED,wBAAsB,mCAAmC,CACvD,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAetB;AA4CD,wBAAsB,oCAAoC,CACxD,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAgCtB;AAmCD,wBAAsB,iCAAiC,CACrD,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAetB;AAED,wBAAsB,iCAAiC,CACrD,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAkCtB;AAED,wBAAsB,8BAA8B,CAClD,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAiBtB;AAED,wBAAsB,wCAAwC,CAC5D,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAuCtB;AAED,wBAAsB,yCAAyC,CAC7D,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAkBtB;AAqFD,wBAAsB,kCAAkC,CACtD,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CA4CtB;AAED,wBAAsB,qCAAqC,CACzD,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAgBtB;AAED,wBAAsB,iCAAiC,CACrD,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAYtB;AAED,wBAAsB,kCAAkC,CACtD,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CA2CtB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { statSync } from "node:fs";
|
|
3
3
|
import { basename, dirname } from "node:path";
|
|
4
|
-
import { addSourceToCapsule, checkpointToProgress, composeCapsules, CompositionError, createSqliteAuditSink, createDefaultParserRegistry, createCapsule, deleteCapsule, getCapsule, listCapsuleSets, listCapsuleSources, listCapsules, listExtractionCheckpoints, listResumableDocuments, openKnowledgeStore, removeSourceFromCapsule, resolveKnowledgeStorePath, runIndexingJob, updateCapsuleDetails, updateCapsuleState, } from "@oscharko-dev/keiko-local-knowledge";
|
|
4
|
+
import { addSourceToCapsule, checkpointToProgress, composeCapsules, CompositionError, createSqliteAuditSink, createDefaultParserRegistry, createCapsule, deleteCapsule, getCapsule, listCapsuleSets, listCapsuleSources, listCapsules, listExtractionCheckpoints, listResumableDocuments, openKnowledgeStore, removeSourceFromCapsule, resolveKnowledgeStorePath, runIndexingJob, updateCapsuleEmbeddingModelIdentity, updateCapsuleDetails, updateCapsuleState, } from "@oscharko-dev/keiko-local-knowledge";
|
|
5
5
|
import { KnowledgeNotFoundError, KnowledgeStoreError } from "@oscharko-dev/keiko-local-knowledge";
|
|
6
6
|
import { localKnowledgeProtectionOptions } from "./localKnowledgeKeyProvider.js";
|
|
7
7
|
import { CAPSULE_SET_MAX_MEMBERS, DEFAULT_EXTRACTION_CAPABILITY_AVAILABILITY, DEFAULT_LARGE_DOCUMENT_RESOURCE_POLICY, isSafeDisplaySummary, isSafeQualityWarning, validateCapsuleReindexRequest, validateKnowledgeSourceScope, } from "@oscharko-dev/keiko-contracts";
|
|
@@ -218,6 +218,52 @@ function configuredProviderForCapsule(deps, capsule) {
|
|
|
218
218
|
? provider
|
|
219
219
|
: undefined;
|
|
220
220
|
}
|
|
221
|
+
function embeddingIdentityMatchesCapsuleAlias(stored, current) {
|
|
222
|
+
if (stored.provider !== current.provider ||
|
|
223
|
+
stored.vectorDimensions !== current.vectorDimensions ||
|
|
224
|
+
stored.vectorMetric !== current.vectorMetric) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
if (stored.modelId === current.modelId) {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
return current.modelRevision !== undefined && stored.modelId === current.modelRevision;
|
|
231
|
+
}
|
|
232
|
+
async function probeConfiguredProviderForCapsule(deps, provider, capsule) {
|
|
233
|
+
const adapter = createEmbeddingAdapter(provider, requestEmbeddingImpl(deps), requestEmbeddingBatchImpl(deps));
|
|
234
|
+
try {
|
|
235
|
+
const result = await verifyEmbeddingCapability(adapter, {
|
|
236
|
+
modelId: provider.modelId,
|
|
237
|
+
provider: embeddingProviderIdentity(provider),
|
|
238
|
+
vectorMetric: capsule.embeddingModelIdentity.vectorMetric,
|
|
239
|
+
expectedDimensions: capsule.embeddingModelIdentity.vectorDimensions,
|
|
240
|
+
timeoutMs: provider.timeoutMs,
|
|
241
|
+
});
|
|
242
|
+
return result.ok ? result.identity : undefined;
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async function resolveIndexingProviderForCapsule(deps, store, capsule) {
|
|
249
|
+
const exact = configuredProviderForCapsule(deps, capsule);
|
|
250
|
+
if (exact !== undefined) {
|
|
251
|
+
return { capsule, provider: exact };
|
|
252
|
+
}
|
|
253
|
+
const providers = configuredEmbeddingProviders(currentGatewayConfig(deps));
|
|
254
|
+
for (const provider of providers) {
|
|
255
|
+
if (!storedProviderMatchesConfiguredProvider(capsule.embeddingModelIdentity.provider, provider)) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
const identity = await probeConfiguredProviderForCapsule(deps, provider, capsule);
|
|
259
|
+
if (identity !== undefined &&
|
|
260
|
+
embeddingIdentityMatchesCapsuleAlias(capsule.embeddingModelIdentity, identity)) {
|
|
261
|
+
const repaired = updateCapsuleEmbeddingModelIdentity(store, capsule.id, identity);
|
|
262
|
+
return { capsule: repaired, provider };
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
221
267
|
function embeddingCompatibilityReason(config, capsule) {
|
|
222
268
|
if (config === undefined)
|
|
223
269
|
return undefined;
|
|
@@ -780,6 +826,9 @@ function indexingCompletionResponse(capsuleId, terminal, failedMessage) {
|
|
|
780
826
|
}
|
|
781
827
|
return actionResponse(capsuleId);
|
|
782
828
|
}
|
|
829
|
+
function runningIndexingJobConflict(capsuleId, runningJobId) {
|
|
830
|
+
return indexingConflict("indexing-already-running", "An indexing job is already running for this capsule.", capsuleId, runningJobId);
|
|
831
|
+
}
|
|
783
832
|
function buildIndexingOptions(store, capsule, adapter, options, sourceSelection, signal) {
|
|
784
833
|
return {
|
|
785
834
|
capsuleId: capsule.id,
|
|
@@ -1074,21 +1123,22 @@ export async function handleStartLocalKnowledgeCapsuleIndexing(ctx, deps) {
|
|
|
1074
1123
|
if (capsule.sourceIds.length === 0) {
|
|
1075
1124
|
return emptyCapsuleIndexingConflict();
|
|
1076
1125
|
}
|
|
1077
|
-
|
|
1126
|
+
const resolved = await resolveIndexingProviderForCapsule(deps, env.store, capsule);
|
|
1127
|
+
if (resolved === undefined) {
|
|
1078
1128
|
return conflict("No configured embedding-capable model matches this capsule. Update the Model Gateway configuration before indexing it.");
|
|
1079
1129
|
}
|
|
1080
1130
|
// LK-003 (Epic #189): refuse to start a second concurrent indexer for the same
|
|
1081
1131
|
// capsule — the orchestrator persists running jobs, so a duplicate POST would
|
|
1082
1132
|
// race the in-flight one and corrupt vector counts.
|
|
1083
|
-
const runningJobId = latestRunningJobId(env.store, capsule.id);
|
|
1133
|
+
const runningJobId = latestRunningJobId(env.store, resolved.capsule.id);
|
|
1084
1134
|
if (runningJobId !== undefined) {
|
|
1085
|
-
return
|
|
1135
|
+
return runningIndexingJobConflict(resolved.capsule.id, runningJobId);
|
|
1086
1136
|
}
|
|
1087
|
-
const terminal = await runCapsuleIndexingJob(deps, env.store, capsule, {
|
|
1137
|
+
const terminal = await runCapsuleIndexingJob(deps, env.store, resolved.capsule, {
|
|
1088
1138
|
mode: undefined,
|
|
1089
1139
|
force: false,
|
|
1090
1140
|
});
|
|
1091
|
-
return indexingCompletionResponse(capsule.id, terminal, "Capsule indexing failed. Review the capsule health diagnostics and job history for details.");
|
|
1141
|
+
return indexingCompletionResponse(resolved.capsule.id, terminal, "Capsule indexing failed. Review the capsule health diagnostics and job history for details.");
|
|
1092
1142
|
}
|
|
1093
1143
|
finally {
|
|
1094
1144
|
env.close();
|
|
@@ -1280,19 +1330,20 @@ export async function handleReindexLocalKnowledgeCapsule(ctx, deps) {
|
|
|
1280
1330
|
if (capsule.sourceIds.length === 0) {
|
|
1281
1331
|
return emptyCapsuleIndexingConflict();
|
|
1282
1332
|
}
|
|
1283
|
-
|
|
1333
|
+
const resolved = await resolveIndexingProviderForCapsule(deps, env.store, capsule);
|
|
1334
|
+
if (resolved === undefined) {
|
|
1284
1335
|
return conflict("No configured embedding-capable model matches this capsule. Update the Model Gateway configuration before refreshing it.");
|
|
1285
1336
|
}
|
|
1286
1337
|
// LK-003 (Epic #189): same concurrent-run guard as the start handler.
|
|
1287
|
-
const runningJobId = latestRunningJobId(env.store, capsule.id);
|
|
1338
|
+
const runningJobId = latestRunningJobId(env.store, resolved.capsule.id);
|
|
1288
1339
|
if (runningJobId !== undefined) {
|
|
1289
|
-
return
|
|
1340
|
+
return runningIndexingJobConflict(resolved.capsule.id, runningJobId);
|
|
1290
1341
|
}
|
|
1291
|
-
const terminal = await runCapsuleIndexingJob(deps, env.store, capsule, {
|
|
1342
|
+
const terminal = await runCapsuleIndexingJob(deps, env.store, resolved.capsule, {
|
|
1292
1343
|
mode,
|
|
1293
1344
|
force,
|
|
1294
1345
|
});
|
|
1295
|
-
return indexingCompletionResponse(capsule.id, terminal, "Capsule refresh failed. Review the capsule health diagnostics and job history for details.");
|
|
1346
|
+
return indexingCompletionResponse(resolved.capsule.id, terminal, "Capsule refresh failed. Review the capsule health diagnostics and job history for details.");
|
|
1296
1347
|
}
|
|
1297
1348
|
finally {
|
|
1298
1349
|
env.close();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscharko-dev/keiko-server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"description": "Internal server package: local loopback BFF runtime (HTTP/SSE/WebSocket router, CSP, host check, CSRF gate, terminal, browser, files, run engine, SQLite-backed UI store) that mediates the browser presentation tier and the Node-side domain packages (ADR-0019). Not published independently.",
|
|
@@ -29,24 +29,24 @@
|
|
|
29
29
|
"node": ">=22"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@oscharko-dev/keiko-contracts": "0.2.
|
|
33
|
-
"@oscharko-dev/keiko-security": "0.2.
|
|
34
|
-
"@oscharko-dev/keiko-model-gateway": "0.2.
|
|
35
|
-
"@oscharko-dev/keiko-quality-intelligence": "0.2.
|
|
36
|
-
"@oscharko-dev/keiko-local-knowledge": "0.2.
|
|
37
|
-
"@oscharko-dev/keiko-workspace": "0.2.
|
|
38
|
-
"@oscharko-dev/keiko-sandbox": "0.2.
|
|
39
|
-
"@oscharko-dev/keiko-tools": "0.2.
|
|
40
|
-
"@oscharko-dev/keiko-evidence": "0.2.
|
|
41
|
-
"@oscharko-dev/keiko-verification": "0.2.
|
|
42
|
-
"@oscharko-dev/keiko-harness": "0.2.
|
|
43
|
-
"@oscharko-dev/keiko-sdk": "0.2.
|
|
44
|
-
"@oscharko-dev/keiko-workflows": "0.2.
|
|
45
|
-
"@oscharko-dev/keiko-memory-vault": "0.2.
|
|
46
|
-
"@oscharko-dev/keiko-memory-governance": "0.2.
|
|
47
|
-
"@oscharko-dev/keiko-memory-retrieval": "0.2.
|
|
48
|
-
"@oscharko-dev/keiko-memory-capture": "0.2.
|
|
49
|
-
"@oscharko-dev/keiko-memory-consolidation": "0.2.
|
|
32
|
+
"@oscharko-dev/keiko-contracts": "0.2.3",
|
|
33
|
+
"@oscharko-dev/keiko-security": "0.2.3",
|
|
34
|
+
"@oscharko-dev/keiko-model-gateway": "0.2.3",
|
|
35
|
+
"@oscharko-dev/keiko-quality-intelligence": "0.2.3",
|
|
36
|
+
"@oscharko-dev/keiko-local-knowledge": "0.2.3",
|
|
37
|
+
"@oscharko-dev/keiko-workspace": "0.2.3",
|
|
38
|
+
"@oscharko-dev/keiko-sandbox": "0.2.3",
|
|
39
|
+
"@oscharko-dev/keiko-tools": "0.2.3",
|
|
40
|
+
"@oscharko-dev/keiko-evidence": "0.2.3",
|
|
41
|
+
"@oscharko-dev/keiko-verification": "0.2.3",
|
|
42
|
+
"@oscharko-dev/keiko-harness": "0.2.3",
|
|
43
|
+
"@oscharko-dev/keiko-sdk": "0.2.3",
|
|
44
|
+
"@oscharko-dev/keiko-workflows": "0.2.3",
|
|
45
|
+
"@oscharko-dev/keiko-memory-vault": "0.2.3",
|
|
46
|
+
"@oscharko-dev/keiko-memory-governance": "0.2.3",
|
|
47
|
+
"@oscharko-dev/keiko-memory-retrieval": "0.2.3",
|
|
48
|
+
"@oscharko-dev/keiko-memory-capture": "0.2.3",
|
|
49
|
+
"@oscharko-dev/keiko-memory-consolidation": "0.2.3",
|
|
50
50
|
"typescript": "^6.0.3"
|
|
51
51
|
}
|
|
52
52
|
}
|