@oscharko-dev/keiko-local-knowledge 0.2.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/dist/.tsbuildinfo +1 -0
- package/dist/bounded-document-extraction.d.ts +27 -0
- package/dist/bounded-document-extraction.d.ts.map +1 -0
- package/dist/bounded-document-extraction.js +214 -0
- package/dist/capsule-lifecycle.d.ts +33 -0
- package/dist/capsule-lifecycle.d.ts.map +1 -0
- package/dist/capsule-lifecycle.js +292 -0
- package/dist/capsule-set-lifecycle.d.ts +15 -0
- package/dist/capsule-set-lifecycle.d.ts.map +1 -0
- package/dist/capsule-set-lifecycle.js +158 -0
- package/dist/chunking/chunker-persist.d.ts +36 -0
- package/dist/chunking/chunker-persist.d.ts.map +1 -0
- package/dist/chunking/chunker-persist.js +74 -0
- package/dist/chunking/chunker-runner.d.ts +9 -0
- package/dist/chunking/chunker-runner.d.ts.map +1 -0
- package/dist/chunking/chunker-runner.js +218 -0
- package/dist/chunking/chunker.d.ts +7 -0
- package/dist/chunking/chunker.d.ts.map +1 -0
- package/dist/chunking/chunker.js +139 -0
- package/dist/chunking/citation-mapper.d.ts +4 -0
- package/dist/chunking/citation-mapper.d.ts.map +1 -0
- package/dist/chunking/citation-mapper.js +180 -0
- package/dist/chunking/index.d.ts +6 -0
- package/dist/chunking/index.d.ts.map +1 -0
- package/dist/chunking/index.js +8 -0
- package/dist/chunking/token-estimator.d.ts +3 -0
- package/dist/chunking/token-estimator.d.ts.map +1 -0
- package/dist/chunking/token-estimator.js +26 -0
- package/dist/chunking/types.d.ts +49 -0
- package/dist/chunking/types.d.ts.map +1 -0
- package/dist/chunking/types.js +26 -0
- package/dist/composition.d.ts +57 -0
- package/dist/composition.d.ts.map +1 -0
- package/dist/composition.js +310 -0
- package/dist/conversation/citation-attacher.d.ts +8 -0
- package/dist/conversation/citation-attacher.d.ts.map +1 -0
- package/dist/conversation/citation-attacher.js +55 -0
- package/dist/conversation/citation-excerpts.d.ts +4 -0
- package/dist/conversation/citation-excerpts.d.ts.map +1 -0
- package/dist/conversation/citation-excerpts.js +41 -0
- package/dist/conversation/grounded-answer-runner.d.ts +9 -0
- package/dist/conversation/grounded-answer-runner.d.ts.map +1 -0
- package/dist/conversation/grounded-answer-runner.js +61 -0
- package/dist/conversation/index.d.ts +5 -0
- package/dist/conversation/index.d.ts.map +1 -0
- package/dist/conversation/index.js +7 -0
- package/dist/conversation/model-gateway-answer-generator.d.ts +28 -0
- package/dist/conversation/model-gateway-answer-generator.d.ts.map +1 -0
- package/dist/conversation/model-gateway-answer-generator.js +105 -0
- package/dist/conversation/types.d.ts +35 -0
- package/dist/conversation/types.d.ts.map +1 -0
- package/dist/conversation/types.js +24 -0
- package/dist/discovery/discovery-runner.d.ts +23 -0
- package/dist/discovery/discovery-runner.d.ts.map +1 -0
- package/dist/discovery/discovery-runner.js +109 -0
- package/dist/discovery/extract-progressive.d.ts +17 -0
- package/dist/discovery/extract-progressive.d.ts.map +1 -0
- package/dist/discovery/extract-progressive.js +522 -0
- package/dist/discovery/extract.d.ts +26 -0
- package/dist/discovery/extract.d.ts.map +1 -0
- package/dist/discovery/extract.js +906 -0
- package/dist/discovery/glob.d.ts +10 -0
- package/dist/discovery/glob.d.ts.map +1 -0
- package/dist/discovery/glob.js +72 -0
- package/dist/discovery/index.d.ts +6 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +8 -0
- package/dist/discovery/media-type.d.ts +4 -0
- package/dist/discovery/media-type.d.ts.map +1 -0
- package/dist/discovery/media-type.js +62 -0
- package/dist/discovery/persist.d.ts +63 -0
- package/dist/discovery/persist.d.ts.map +1 -0
- package/dist/discovery/persist.js +345 -0
- package/dist/discovery/test-support.d.ts +16 -0
- package/dist/discovery/test-support.d.ts.map +1 -0
- package/dist/discovery/test-support.js +127 -0
- package/dist/discovery/types.d.ts +63 -0
- package/dist/discovery/types.d.ts.map +1 -0
- package/dist/discovery/types.js +28 -0
- package/dist/discovery/walk.d.ts +12 -0
- package/dist/discovery/walk.d.ts.map +1 -0
- package/dist/discovery/walk.js +302 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +22 -0
- package/dist/evaluations/dimensions.d.ts +14 -0
- package/dist/evaluations/dimensions.d.ts.map +1 -0
- package/dist/evaluations/dimensions.js +191 -0
- package/dist/evaluations/fixtures.d.ts +18 -0
- package/dist/evaluations/fixtures.d.ts.map +1 -0
- package/dist/evaluations/fixtures.js +858 -0
- package/dist/evaluations/index.d.ts +7 -0
- package/dist/evaluations/index.d.ts.map +1 -0
- package/dist/evaluations/index.js +10 -0
- package/dist/evaluations/report.d.ts +3 -0
- package/dist/evaluations/report.d.ts.map +1 -0
- package/dist/evaluations/report.js +31 -0
- package/dist/evaluations/runner-seed.d.ts +12 -0
- package/dist/evaluations/runner-seed.d.ts.map +1 -0
- package/dist/evaluations/runner-seed.js +175 -0
- package/dist/evaluations/runner.d.ts +8 -0
- package/dist/evaluations/runner.d.ts.map +1 -0
- package/dist/evaluations/runner.js +205 -0
- package/dist/evaluations/scripted-embedding-adapter.d.ts +13 -0
- package/dist/evaluations/scripted-embedding-adapter.d.ts.map +1 -0
- package/dist/evaluations/scripted-embedding-adapter.js +163 -0
- package/dist/evaluations/types.d.ts +116 -0
- package/dist/evaluations/types.d.ts.map +1 -0
- package/dist/evaluations/types.js +27 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/indexing/bounded-indexing.d.ts +41 -0
- package/dist/indexing/bounded-indexing.d.ts.map +1 -0
- package/dist/indexing/bounded-indexing.js +240 -0
- package/dist/indexing/checkpoint-persist.d.ts +8 -0
- package/dist/indexing/checkpoint-persist.d.ts.map +1 -0
- package/dist/indexing/checkpoint-persist.js +135 -0
- package/dist/indexing/checkpoint-resume.d.ts +20 -0
- package/dist/indexing/checkpoint-resume.d.ts.map +1 -0
- package/dist/indexing/checkpoint-resume.js +50 -0
- package/dist/indexing/embedding-batcher.d.ts +3 -0
- package/dist/indexing/embedding-batcher.d.ts.map +1 -0
- package/dist/indexing/embedding-batcher.js +390 -0
- package/dist/indexing/index.d.ts +7 -0
- package/dist/indexing/index.d.ts.map +1 -0
- package/dist/indexing/index.js +11 -0
- package/dist/indexing/job-persist.d.ts +46 -0
- package/dist/indexing/job-persist.d.ts.map +1 -0
- package/dist/indexing/job-persist.js +157 -0
- package/dist/indexing/job-resume.d.ts +4 -0
- package/dist/indexing/job-resume.d.ts.map +1 -0
- package/dist/indexing/job-resume.js +14 -0
- package/dist/indexing/orchestrator.d.ts +3 -0
- package/dist/indexing/orchestrator.d.ts.map +1 -0
- package/dist/indexing/orchestrator.js +1151 -0
- package/dist/indexing/types.d.ts +156 -0
- package/dist/indexing/types.d.ts.map +1 -0
- package/dist/indexing/types.js +30 -0
- package/dist/indexing/vector-persist.d.ts +32 -0
- package/dist/indexing/vector-persist.d.ts.map +1 -0
- package/dist/indexing/vector-persist.js +105 -0
- package/dist/parsers/_internal.d.ts +20 -0
- package/dist/parsers/_internal.d.ts.map +1 -0
- package/dist/parsers/_internal.js +122 -0
- package/dist/parsers/csv-parser.d.ts +3 -0
- package/dist/parsers/csv-parser.d.ts.map +1 -0
- package/dist/parsers/csv-parser.js +202 -0
- package/dist/parsers/docx-parser.d.ts +3 -0
- package/dist/parsers/docx-parser.d.ts.map +1 -0
- package/dist/parsers/docx-parser.js +390 -0
- package/dist/parsers/html-parser.d.ts +3 -0
- package/dist/parsers/html-parser.d.ts.map +1 -0
- package/dist/parsers/html-parser.js +310 -0
- package/dist/parsers/index.d.ts +15 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +41 -0
- package/dist/parsers/json-parser.d.ts +3 -0
- package/dist/parsers/json-parser.d.ts.map +1 -0
- package/dist/parsers/json-parser.js +192 -0
- package/dist/parsers/large-document/capability-discovery.d.ts +27 -0
- package/dist/parsers/large-document/capability-discovery.d.ts.map +1 -0
- package/dist/parsers/large-document/capability-discovery.js +76 -0
- package/dist/parsers/large-document/diagnostics.d.ts +3 -0
- package/dist/parsers/large-document/diagnostics.d.ts.map +1 -0
- package/dist/parsers/large-document/diagnostics.js +11 -0
- package/dist/parsers/large-document/index.d.ts +15 -0
- package/dist/parsers/large-document/index.d.ts.map +1 -0
- package/dist/parsers/large-document/index.js +10 -0
- package/dist/parsers/large-document/legacy-format.d.ts +5 -0
- package/dist/parsers/large-document/legacy-format.d.ts.map +1 -0
- package/dist/parsers/large-document/legacy-format.js +25 -0
- package/dist/parsers/large-document/preflight.d.ts +9 -0
- package/dist/parsers/large-document/preflight.d.ts.map +1 -0
- package/dist/parsers/large-document/preflight.js +43 -0
- package/dist/parsers/large-document/progressive-extraction.d.ts +55 -0
- package/dist/parsers/large-document/progressive-extraction.d.ts.map +1 -0
- package/dist/parsers/large-document/progressive-extraction.js +123 -0
- package/dist/parsers/large-document/progressive-pdf.d.ts +20 -0
- package/dist/parsers/large-document/progressive-pdf.d.ts.map +1 -0
- package/dist/parsers/large-document/progressive-pdf.js +145 -0
- package/dist/parsers/large-document/synthetic-source.d.ts +9 -0
- package/dist/parsers/large-document/synthetic-source.d.ts.map +1 -0
- package/dist/parsers/large-document/synthetic-source.js +101 -0
- package/dist/parsers/large-document/window-builder.d.ts +24 -0
- package/dist/parsers/large-document/window-builder.d.ts.map +1 -0
- package/dist/parsers/large-document/window-builder.js +75 -0
- package/dist/parsers/ocr/index.d.ts +4 -0
- package/dist/parsers/ocr/index.d.ts.map +1 -0
- package/dist/parsers/ocr/index.js +4 -0
- package/dist/parsers/ocr/null-ocr-adapter.d.ts +3 -0
- package/dist/parsers/ocr/null-ocr-adapter.d.ts.map +1 -0
- package/dist/parsers/ocr/null-ocr-adapter.js +14 -0
- package/dist/parsers/ocr/ocr-pipeline-parser.d.ts +8 -0
- package/dist/parsers/ocr/ocr-pipeline-parser.d.ts.map +1 -0
- package/dist/parsers/ocr/ocr-pipeline-parser.js +147 -0
- package/dist/parsers/ocr/types.d.ts +16 -0
- package/dist/parsers/ocr/types.d.ts.map +1 -0
- package/dist/parsers/ocr/types.js +4 -0
- package/dist/parsers/parser-test-fixtures.d.ts +28 -0
- package/dist/parsers/parser-test-fixtures.d.ts.map +1 -0
- package/dist/parsers/parser-test-fixtures.js +139 -0
- package/dist/parsers/pdf-parser.d.ts +43 -0
- package/dist/parsers/pdf-parser.d.ts.map +1 -0
- package/dist/parsers/pdf-parser.js +388 -0
- package/dist/parsers/registry.d.ts +8 -0
- package/dist/parsers/registry.d.ts.map +1 -0
- package/dist/parsers/registry.js +57 -0
- package/dist/parsers/text-parser.d.ts +3 -0
- package/dist/parsers/text-parser.d.ts.map +1 -0
- package/dist/parsers/text-parser.js +214 -0
- package/dist/parsers/types.d.ts +53 -0
- package/dist/parsers/types.d.ts.map +1 -0
- package/dist/parsers/types.js +21 -0
- package/dist/parsers/unsupported-parser.d.ts +4 -0
- package/dist/parsers/unsupported-parser.d.ts.map +1 -0
- package/dist/parsers/unsupported-parser.js +97 -0
- package/dist/parsers/xlsx-parser.d.ts +3 -0
- package/dist/parsers/xlsx-parser.d.ts.map +1 -0
- package/dist/parsers/xlsx-parser.js +425 -0
- package/dist/privacy/audit-emitter.d.ts +5 -0
- package/dist/privacy/audit-emitter.d.ts.map +1 -0
- package/dist/privacy/audit-emitter.js +93 -0
- package/dist/privacy/diagnostic-redactor.d.ts +2 -0
- package/dist/privacy/diagnostic-redactor.d.ts.map +1 -0
- package/dist/privacy/diagnostic-redactor.js +153 -0
- package/dist/privacy/index.d.ts +5 -0
- package/dist/privacy/index.d.ts.map +1 -0
- package/dist/privacy/index.js +6 -0
- package/dist/privacy/retention-applier.d.ts +5 -0
- package/dist/privacy/retention-applier.d.ts.map +1 -0
- package/dist/privacy/retention-applier.js +88 -0
- package/dist/privacy/types.d.ts +98 -0
- package/dist/privacy/types.d.ts.map +1 -0
- package/dist/privacy/types.js +12 -0
- package/dist/qualityIntelligence/capsuleCorpus.d.ts +27 -0
- package/dist/qualityIntelligence/capsuleCorpus.d.ts.map +1 -0
- package/dist/qualityIntelligence/capsuleCorpus.js +58 -0
- package/dist/qualityIntelligence/index.d.ts +3 -0
- package/dist/qualityIntelligence/index.d.ts.map +1 -0
- package/dist/qualityIntelligence/index.js +5 -0
- package/dist/qualityIntelligence/qiHandoff.d.ts +36 -0
- package/dist/qualityIntelligence/qiHandoff.d.ts.map +1 -0
- package/dist/qualityIntelligence/qiHandoff.js +82 -0
- package/dist/retrieval/answer-grounding.d.ts +9 -0
- package/dist/retrieval/answer-grounding.d.ts.map +1 -0
- package/dist/retrieval/answer-grounding.js +31 -0
- package/dist/retrieval/context-pack-assembler.d.ts +24 -0
- package/dist/retrieval/context-pack-assembler.d.ts.map +1 -0
- package/dist/retrieval/context-pack-assembler.js +50 -0
- package/dist/retrieval/index.d.ts +6 -0
- package/dist/retrieval/index.d.ts.map +1 -0
- package/dist/retrieval/index.js +9 -0
- package/dist/retrieval/retrieval-runner.d.ts +10 -0
- package/dist/retrieval/retrieval-runner.d.ts.map +1 -0
- package/dist/retrieval/retrieval-runner.js +163 -0
- package/dist/retrieval/scoped-vector-search.d.ts +24 -0
- package/dist/retrieval/scoped-vector-search.d.ts.map +1 -0
- package/dist/retrieval/scoped-vector-search.js +864 -0
- package/dist/retrieval/types.d.ts +28 -0
- package/dist/retrieval/types.d.ts.map +1 -0
- package/dist/retrieval/types.js +33 -0
- package/dist/section-path-hash.d.ts +3 -0
- package/dist/section-path-hash.d.ts.map +1 -0
- package/dist/section-path-hash.js +9 -0
- package/dist/source-lifecycle.d.ts +14 -0
- package/dist/source-lifecycle.d.ts.map +1 -0
- package/dist/source-lifecycle.js +155 -0
- package/dist/source-routing-validation.d.ts +11 -0
- package/dist/source-routing-validation.d.ts.map +1 -0
- package/dist/source-routing-validation.js +140 -0
- package/dist/store-content-cipher.d.ts +11 -0
- package/dist/store-content-cipher.d.ts.map +1 -0
- package/dist/store-content-cipher.js +67 -0
- package/dist/store-content-encryption.d.ts +12 -0
- package/dist/store-content-encryption.d.ts.map +1 -0
- package/dist/store-content-encryption.js +275 -0
- package/dist/store-paths.d.ts +6 -0
- package/dist/store-paths.d.ts.map +1 -0
- package/dist/store-paths.js +61 -0
- package/dist/store.d.ts +30 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +219 -0
- package/dist/testing.d.ts +47 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +170 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/package.json +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-gateway-answer-generator.d.ts","sourceRoot":"","sources":["../../src/conversation/model-gateway-answer-generator.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,4BAA4B,EAC5B,WAAW,EACX,cAAc,EACd,kBAAkB,EACnB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;AAEhG,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAMxE,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAK1D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACzE;AAED,MAAM,WAAW,kCAAkC;IACjD,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAGzB,QAAQ,CAAC,MAAM,EAAE,4BAA4B,CAAC;IAC9C,QAAQ,CAAC,sBAAsB,CAAC,EAAE,wBAAwB,CAAC;CAC5D;AAMD,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,SAAyB,IAAI,EAAE,MAAM,CAAkC;;CAIxE;AAED,qBAAa,2BAA4B,YAAW,eAAe;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA2B;gBAE/C,OAAO,EAAE,kCAAkC;IAOjD,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;CAwBpE;AAKD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,iCAAiC,EACvC,sBAAsB,GAAE,wBAAmD,GAC1E,SAAS,WAAW,EAAE,CAexB"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// Production `AnswerGenerator` (Epic #189, Issue #200). Builds a grounding prompt from a
|
|
2
|
+
// `LocalKnowledgeGroundedContextPack` and calls the configured model gateway to produce
|
|
3
|
+
// the answer text. The runner attaches `[n]` citation markers after generation.
|
|
4
|
+
//
|
|
5
|
+
// Two hard contracts:
|
|
6
|
+
// 1. The gateway is NEVER called when `validateAnswerGrounding` rejects the references.
|
|
7
|
+
// The runner is the primary guard (it short-circuits before reaching the generator),
|
|
8
|
+
// but the generator re-checks defensively so a misuse from a future caller still
|
|
9
|
+
// fails closed. Same belt-and-braces stance as the indexing layer's content-hash
|
|
10
|
+
// check.
|
|
11
|
+
// 2. The prompt is shaped DETERMINISTICALLY from the pack — same pack ⇒ same prompt
|
|
12
|
+
// string. The model's response is non-deterministic by nature, but the *input*
|
|
13
|
+
// surface the audit ledger replays is byte-identical.
|
|
14
|
+
//
|
|
15
|
+
// The generator depends on a `ChatGateway` port (structural — `Gateway.chat` satisfies
|
|
16
|
+
// it). We do NOT import the `Gateway` class directly: ADR-0019 direction 3e lets
|
|
17
|
+
// keiko-local-knowledge depend on keiko-model-gateway, but pinning the structural port
|
|
18
|
+
// keeps the test fakes trivial and isolates this module from constructor churn in the
|
|
19
|
+
// real gateway.
|
|
20
|
+
import { ProviderError } from "@oscharko-dev/keiko-model-gateway";
|
|
21
|
+
import { validateAnswerGrounding } from "../retrieval/answer-grounding.js";
|
|
22
|
+
const CITATION_METADATA_WHITESPACE_PATTERN = /\s+/gu;
|
|
23
|
+
const MAX_PROMPT_CITATION_LABEL_CHARS = 240;
|
|
24
|
+
const EMPTY_ASSISTANT_RESPONSE_STATUS = 200;
|
|
25
|
+
// Surfaced when the defensive grounding check refuses to release refs to the gateway.
|
|
26
|
+
// The runner's primary path produces a `noEvidence` answer before this is ever thrown.
|
|
27
|
+
// If this error escapes the generator it indicates a caller bypassed the runner — that's
|
|
28
|
+
// a real bug, not a user-facing condition.
|
|
29
|
+
export class AnswerGroundingRejectedError extends Error {
|
|
30
|
+
name = "AnswerGroundingRejectedError";
|
|
31
|
+
constructor() {
|
|
32
|
+
super("Answer grounding policy rejected the references; gateway call refused");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class ModelGatewayAnswerGenerator {
|
|
36
|
+
chatGateway;
|
|
37
|
+
modelId;
|
|
38
|
+
policy;
|
|
39
|
+
redactCitationMetadata;
|
|
40
|
+
constructor(options) {
|
|
41
|
+
this.chatGateway = options.chatGateway;
|
|
42
|
+
this.modelId = options.modelId;
|
|
43
|
+
this.policy = options.policy;
|
|
44
|
+
this.redactCitationMetadata = options.redactCitationMetadata ?? ((value) => value);
|
|
45
|
+
}
|
|
46
|
+
async generate(input) {
|
|
47
|
+
const decision = validateAnswerGrounding(input.references, this.policy);
|
|
48
|
+
if (!decision.allow) {
|
|
49
|
+
// Defensive: the runner already short-circuits the no-evidence path. Reaching
|
|
50
|
+
// this branch means a caller wired the generator outside the runner with refs
|
|
51
|
+
// the policy disallows. Refuse the gateway call rather than leak refs.
|
|
52
|
+
throw new AnswerGroundingRejectedError();
|
|
53
|
+
}
|
|
54
|
+
const messages = buildPromptMessages(input.query.text, input.pack, this.redactCitationMetadata);
|
|
55
|
+
const request = {
|
|
56
|
+
modelId: this.modelId,
|
|
57
|
+
messages,
|
|
58
|
+
...(input.signal !== undefined ? { cancellationSignal: input.signal } : {}),
|
|
59
|
+
};
|
|
60
|
+
const response = await this.chatGateway.chat(request);
|
|
61
|
+
const content = response.content.trim();
|
|
62
|
+
if (content.length === 0) {
|
|
63
|
+
throw new ProviderError(`model '${this.modelId}' returned an empty grounded answer`, EMPTY_ASSISTANT_RESPONSE_STATUS);
|
|
64
|
+
}
|
|
65
|
+
return content;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Exported so tests can pin the exact prompt the gateway sees. Determinism contract:
|
|
69
|
+
// the returned messages are a pure function of `(question, pack)`; identical inputs
|
|
70
|
+
// produce byte-identical messages (citations are pre-sorted by the pack assembler).
|
|
71
|
+
export function buildPromptMessages(question, pack, redactCitationMetadata = (value) => value) {
|
|
72
|
+
const citationsBlock = renderCitations(pack, redactCitationMetadata);
|
|
73
|
+
return [
|
|
74
|
+
{
|
|
75
|
+
role: "system",
|
|
76
|
+
content: "You answer questions strictly from the supplied citations. Cite each claim " +
|
|
77
|
+
"with the matching [n] marker. If the citations do not contain the answer, " +
|
|
78
|
+
"reply 'No evidence found in the supplied citations.'",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
role: "user",
|
|
82
|
+
content: `Question: ${question}\nContext (${String(pack.counts.totalReferences)} citations):\n${citationsBlock}\nAnswer with citations only.`,
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
function sanitizeCitationMetadata(value, redactCitationMetadata) {
|
|
87
|
+
const compact = value.replace(CITATION_METADATA_WHITESPACE_PATTERN, " ").trim();
|
|
88
|
+
const redacted = redactCitationMetadata(compact);
|
|
89
|
+
return redacted
|
|
90
|
+
.replace(CITATION_METADATA_WHITESPACE_PATTERN, " ")
|
|
91
|
+
.trim()
|
|
92
|
+
.slice(0, MAX_PROMPT_CITATION_LABEL_CHARS);
|
|
93
|
+
}
|
|
94
|
+
function renderCitations(pack, redactCitationMetadata) {
|
|
95
|
+
const lines = [];
|
|
96
|
+
for (let i = 0; i < pack.citations.length; i += 1) {
|
|
97
|
+
const c = pack.citations[i];
|
|
98
|
+
if (c === undefined)
|
|
99
|
+
continue;
|
|
100
|
+
const index = i + 1;
|
|
101
|
+
const label = sanitizeCitationMetadata(c.safeDisplayName, redactCitationMetadata) || "citation";
|
|
102
|
+
lines.push(`[${String(index)}] ${label} (chunk ${String(c.chunkId)})`);
|
|
103
|
+
}
|
|
104
|
+
return lines.join("\n");
|
|
105
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CitationReference, RetrievalReference } from "@oscharko-dev/keiko-contracts";
|
|
2
|
+
import type { LocalKnowledgeGroundedContextPack } from "../retrieval/context-pack-assembler.js";
|
|
3
|
+
import type { RetrievalNoEvidenceReason, RetrievalQuery } from "../retrieval/types.js";
|
|
4
|
+
export interface ConversationGroundedQuery {
|
|
5
|
+
readonly conversationId: string;
|
|
6
|
+
readonly capsuleId?: RetrievalQuery["capsuleId"];
|
|
7
|
+
readonly capsuleSetId?: RetrievalQuery["capsuleSetId"];
|
|
8
|
+
readonly text: string;
|
|
9
|
+
readonly topK?: number;
|
|
10
|
+
readonly minScore?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ConversationGroundedAnswer {
|
|
13
|
+
readonly answer: string;
|
|
14
|
+
readonly references: readonly RetrievalReference[];
|
|
15
|
+
readonly citations: readonly ConversationCitationReference[];
|
|
16
|
+
readonly pack: LocalKnowledgeGroundedContextPack;
|
|
17
|
+
readonly noEvidence: boolean;
|
|
18
|
+
readonly reason?: RetrievalNoEvidenceReason;
|
|
19
|
+
}
|
|
20
|
+
export interface ConversationCitationReference {
|
|
21
|
+
readonly marker: string;
|
|
22
|
+
readonly index: number;
|
|
23
|
+
readonly citation: CitationReference;
|
|
24
|
+
readonly reference: RetrievalReference;
|
|
25
|
+
}
|
|
26
|
+
export interface AnswerGeneratorInput {
|
|
27
|
+
readonly query: ConversationGroundedQuery;
|
|
28
|
+
readonly pack: LocalKnowledgeGroundedContextPack;
|
|
29
|
+
readonly references: readonly RetrievalReference[];
|
|
30
|
+
readonly signal?: AbortSignal | undefined;
|
|
31
|
+
}
|
|
32
|
+
export interface AnswerGenerator {
|
|
33
|
+
readonly generate: (input: AnswerGeneratorInput) => Promise<string>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/conversation/types.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAE3F,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;AAChG,OAAO,KAAK,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAIvF,MAAM,WAAW,yBAAyB;IAGxC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC;IACjD,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAMD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACnD,QAAQ,CAAC,SAAS,EAAE,SAAS,6BAA6B,EAAE,CAAC;IAC7D,QAAQ,CAAC,IAAI,EAAE,iCAAiC,CAAC;IACjD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,yBAAyB,CAAC;CAC7C;AAOD,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;CACxC;AAID,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,yBAAyB,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,iCAAiC,CAAC;IACjD,QAAQ,CAAC,UAAU,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC3C;AAKD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACrE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Conversation Center wiring contracts (Epic #189, Issue #200). The conversation/ layer
|
|
2
|
+
// is the *integration seam* that exposes the #199 retrieval pipeline to the Conversation
|
|
3
|
+
// Center BFF. The BFF (in `packages/keiko-server`, out of scope here) calls
|
|
4
|
+
// `runGroundedAnswer` when a chat user submits a question with a CapsuleSet (or single
|
|
5
|
+
// Capsule) selected; the runner composes retrieval + grounded-context assembly + an
|
|
6
|
+
// injected `AnswerGenerator` and returns a structured answer with mapped citations.
|
|
7
|
+
//
|
|
8
|
+
// Three shapes live here:
|
|
9
|
+
// * `ConversationGroundedQuery` — the BFF's input. Exactly one of `capsuleId` or
|
|
10
|
+
// `capsuleSetId` may be set (the runner enforces this; "neither" surfaces as a
|
|
11
|
+
// `no-scope` answer, the same contract the underlying retrieval runner uses).
|
|
12
|
+
// * `ConversationGroundedAnswer` — the BFF's output. Carries the answer text, the
|
|
13
|
+
// citations the answer is grounded in, the verbatim `LocalKnowledgeGroundedContextPack`
|
|
14
|
+
// (so the audit ledger can persist the same shape #199 already documents), and the
|
|
15
|
+
// `noEvidence` flag the UI uses to phrase its message.
|
|
16
|
+
// * `AnswerGenerator` — the injectable port that turns a context pack into an answer
|
|
17
|
+
// string. Production composition uses `ModelGatewayAnswerGenerator` to call `Gateway.chat`;
|
|
18
|
+
// tests inject local fixtures at the runner boundary.
|
|
19
|
+
//
|
|
20
|
+
// `ConversationGroundedAnswer.references` is the SAME `RetrievalReference` array the pack
|
|
21
|
+
// was assembled from — the BFF and audit ledger need both the human-readable citation
|
|
22
|
+
// metadata (in `pack.citations`) and the score-bearing retrieval refs (here) without
|
|
23
|
+
// re-deriving one from the other.
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ExtractionCapabilityAvailability, KnowledgeCapsuleId, KnowledgeSource, LargeDocumentResourcePolicy } from "@oscharko-dev/keiko-contracts";
|
|
2
|
+
import type { WorkspaceFs } from "@oscharko-dev/keiko-workspace";
|
|
3
|
+
import { type ParserOptions, type ParserRegistry, type ProgressiveExtractor } from "../parsers/index.js";
|
|
4
|
+
import type { KnowledgeStore } from "../store.js";
|
|
5
|
+
import { type DiscoveryOptions, type ExtractionEvent } from "./types.js";
|
|
6
|
+
export interface DiscoverAndExtractDeps {
|
|
7
|
+
readonly fs: WorkspaceFs;
|
|
8
|
+
readonly store: KnowledgeStore;
|
|
9
|
+
readonly parserRegistry: ParserRegistry;
|
|
10
|
+
readonly largeDocumentPolicy?: LargeDocumentResourcePolicy;
|
|
11
|
+
readonly extractionCapabilities?: ExtractionCapabilityAvailability;
|
|
12
|
+
readonly progressiveExtractors?: readonly ProgressiveExtractor[];
|
|
13
|
+
readonly largeDocumentJobId?: string;
|
|
14
|
+
readonly chunkingStrategyVersion?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface DiscoverAndExtractParams {
|
|
17
|
+
readonly capsuleId: KnowledgeCapsuleId;
|
|
18
|
+
readonly source: KnowledgeSource;
|
|
19
|
+
readonly discovery?: DiscoveryOptions;
|
|
20
|
+
readonly parserOptions?: ParserOptions;
|
|
21
|
+
}
|
|
22
|
+
export declare function discoverAndExtract(deps: DiscoverAndExtractDeps, params: DiscoverAndExtractParams): AsyncGenerator<ExtractionEvent>;
|
|
23
|
+
//# sourceMappingURL=discovery-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery-runner.d.ts","sourceRoot":"","sources":["../../src/discovery/discovery-runner.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,gCAAgC,EAChC,kBAAkB,EAClB,eAAe,EACf,2BAA2B,EAC5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,OAAO,EAA6B,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAGpG,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAGxC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;IAC3D,QAAQ,CAAC,sBAAsB,CAAC,EAAE,gCAAgC,CAAC;IACnE,QAAQ,CAAC,qBAAqB,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACjE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACxC;AAqGD,wBAAuB,kBAAkB,CACvC,IAAI,EAAE,sBAAsB,EAC5B,MAAM,EAAE,wBAAwB,GAC/B,cAAc,CAAC,eAAe,CAAC,CAmBjC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Discovery orchestrator (Epic #189, Issue #194). Composes the walker (walk.ts) with the
|
|
2
|
+
// per-file extractor (extract.ts) and emits a stream of `ExtractionEvent` values. The
|
|
3
|
+
// runner is intentionally an async generator so the consumer (e.g. the eventual indexer
|
|
4
|
+
// loop in #196 or the streaming UI surface) decides how aggressively to back-pressure.
|
|
5
|
+
//
|
|
6
|
+
// Cancellation: a single `AbortSignal` flows into BOTH the walker AND the per-file parser
|
|
7
|
+
// options. Aborting the signal mid-walk drops out within one directory of work; aborting
|
|
8
|
+
// between extractions yields a terminal `cancelled` event and stops iteration.
|
|
9
|
+
import { buildParserOptions, } from "../parsers/index.js";
|
|
10
|
+
import { extractDocument, recordExtractionFailure } from "./extract.js";
|
|
11
|
+
import { DEFAULT_DISCOVERY_OPTIONS } from "./types.js";
|
|
12
|
+
import { walkSource } from "./walk.js";
|
|
13
|
+
function makeParserOptions(params, signal) {
|
|
14
|
+
if (params.parserOptions !== undefined) {
|
|
15
|
+
if (signal === undefined || params.parserOptions.signal !== undefined) {
|
|
16
|
+
return params.parserOptions;
|
|
17
|
+
}
|
|
18
|
+
return { ...params.parserOptions, signal };
|
|
19
|
+
}
|
|
20
|
+
return buildParserOptions(signal !== undefined ? { signal } : {});
|
|
21
|
+
}
|
|
22
|
+
function makeDiscoveryOptions(params, signal) {
|
|
23
|
+
const base = params.discovery ?? DEFAULT_DISCOVERY_OPTIONS;
|
|
24
|
+
if (signal === undefined || base.signal !== undefined) {
|
|
25
|
+
return base;
|
|
26
|
+
}
|
|
27
|
+
return { ...base, signal };
|
|
28
|
+
}
|
|
29
|
+
function bumpCounters(counters, kind) {
|
|
30
|
+
if (kind === "persisted") {
|
|
31
|
+
counters.extracted += 1;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (kind === "skipped") {
|
|
35
|
+
counters.skipped += 1;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
counters.failed += 1;
|
|
39
|
+
}
|
|
40
|
+
async function* handleWalkYield(yld, deps, params, parserOptions, counters) {
|
|
41
|
+
if (yld.kind === "error") {
|
|
42
|
+
if (yld.error.code === "CANCELLED") {
|
|
43
|
+
yield { kind: "cancelled", reason: yld.error.message };
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (yld.error.relativePath !== undefined && yld.error.code !== "INVALID_SCOPE") {
|
|
47
|
+
recordExtractionFailure(deps, {
|
|
48
|
+
capsuleId: params.capsuleId,
|
|
49
|
+
source: params.source,
|
|
50
|
+
file: { relativePath: yld.error.relativePath, sizeBytes: 0 },
|
|
51
|
+
error: yld.error,
|
|
52
|
+
});
|
|
53
|
+
counters.failed += 1;
|
|
54
|
+
}
|
|
55
|
+
yield { kind: "scope-error", error: yld.error };
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
counters.discovered += 1;
|
|
59
|
+
yield {
|
|
60
|
+
kind: "file-discovered",
|
|
61
|
+
relativePath: yld.file.relativePath,
|
|
62
|
+
sizeBytes: yld.file.sizeBytes,
|
|
63
|
+
};
|
|
64
|
+
const result = await extractDocument(deps, {
|
|
65
|
+
capsuleId: params.capsuleId,
|
|
66
|
+
source: params.source,
|
|
67
|
+
file: yld.file,
|
|
68
|
+
parserOptions,
|
|
69
|
+
});
|
|
70
|
+
bumpCounters(counters, result.outcome.kind);
|
|
71
|
+
yield { kind: "file-extracted", result };
|
|
72
|
+
}
|
|
73
|
+
function completionEvent(counters) {
|
|
74
|
+
return {
|
|
75
|
+
kind: "completed",
|
|
76
|
+
totalDiscovered: counters.discovered,
|
|
77
|
+
totalExtracted: counters.extracted,
|
|
78
|
+
totalSkipped: counters.skipped,
|
|
79
|
+
totalFailed: counters.failed,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// Reads `signal?.aborted` through a function call so TypeScript's control-flow analysis
|
|
83
|
+
// does NOT narrow the optional chain after the first false branch (same pattern as walk.ts).
|
|
84
|
+
function aborted(signal) {
|
|
85
|
+
return signal?.aborted === true;
|
|
86
|
+
}
|
|
87
|
+
export async function* discoverAndExtract(deps, params) {
|
|
88
|
+
const signal = params.discovery?.signal ?? params.parserOptions?.signal;
|
|
89
|
+
const discovery = makeDiscoveryOptions(params, signal);
|
|
90
|
+
const parserOptions = makeParserOptions(params, signal);
|
|
91
|
+
const counters = { discovered: 0, extracted: 0, skipped: 0, failed: 0 };
|
|
92
|
+
let cancelled = false;
|
|
93
|
+
for (const yld of walkSource(deps.fs, params.source.scope, discovery)) {
|
|
94
|
+
if (aborted(signal)) {
|
|
95
|
+
yield { kind: "cancelled", reason: "AbortSignal fired between files" };
|
|
96
|
+
cancelled = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
for await (const evt of handleWalkYield(yld, deps, params, parserOptions, counters)) {
|
|
100
|
+
yield evt;
|
|
101
|
+
if (evt.kind === "cancelled")
|
|
102
|
+
cancelled = true;
|
|
103
|
+
}
|
|
104
|
+
if (cancelled)
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
if (!cancelled)
|
|
108
|
+
yield completionEvent(counters);
|
|
109
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ExtractionCapabilityAvailability, LargeDocumentResourcePolicy } from "@oscharko-dev/keiko-contracts";
|
|
2
|
+
import { type ProgressiveExtractionSource, type ProgressiveExtractor } from "../parsers/index.js";
|
|
3
|
+
import { type ExtractionResult } from "./types.js";
|
|
4
|
+
import type { ExtractDocumentDeps, ExtractDocumentParams } from "./extract.js";
|
|
5
|
+
export interface ProgressiveExtractContext {
|
|
6
|
+
readonly policy: LargeDocumentResourcePolicy;
|
|
7
|
+
readonly capabilities: ExtractionCapabilityAvailability;
|
|
8
|
+
readonly extractors: readonly ProgressiveExtractor[];
|
|
9
|
+
readonly jobId: string;
|
|
10
|
+
readonly chunkingStrategyVersion: string;
|
|
11
|
+
readonly absolutePath: string;
|
|
12
|
+
readonly relativePath: string;
|
|
13
|
+
readonly signal?: AbortSignal;
|
|
14
|
+
}
|
|
15
|
+
export declare function selectProgressiveExtractor(context: ProgressiveExtractContext, extension: string, mediaType: string): ProgressiveExtractor | undefined;
|
|
16
|
+
export declare function extractDocumentProgressive(deps: ExtractDocumentDeps, params: ExtractDocumentParams, context: ProgressiveExtractContext, source: ProgressiveExtractionSource, contentHash: string, extractor: ProgressiveExtractor): Promise<ExtractionResult>;
|
|
17
|
+
//# sourceMappingURL=extract-progressive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-progressive.d.ts","sourceRoot":"","sources":["../../src/discovery/extract-progressive.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAMV,gCAAgC,EAGhC,2BAA2B,EAE5B,MAAM,+BAA+B,CAAC;AAQvC,OAAO,EAGL,KAAK,2BAA2B,EAGhC,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAgB7B,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAG/E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,gCAAgC,CAAC;IACxD,QAAQ,CAAC,UAAU,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,yBAAyB,EAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,oBAAoB,GAAG,SAAS,CAElC;AAs5BD,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,qBAAqB,EAC7B,OAAO,EAAE,yBAAyB,EAClC,MAAM,EAAE,2BAA2B,EACnC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,oBAAoB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAY3B"}
|