kibi-cli 0.17.0 → 0.19.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/cli-json-command.d.ts +1 -2
- package/dist/cli-json-command.d.ts.map +1 -1
- package/dist/cli-json-command.js +88 -44
- package/dist/cli-operation-loader.d.ts +3 -0
- package/dist/cli-operation-loader.d.ts.map +1 -0
- package/dist/cli-operation-loader.js +58 -0
- package/dist/cli-operation-metadata.d.ts +82 -0
- package/dist/cli-operation-metadata.d.ts.map +1 -0
- package/dist/cli-operation-metadata.js +106 -0
- package/dist/cli-protocol.d.ts +1 -1
- package/dist/cli-protocol.d.ts.map +1 -1
- package/dist/cli-protocol.js +4 -3
- package/dist/cli-register-foundation.d.ts.map +1 -1
- package/dist/cli-register-foundation.js +14 -17
- package/dist/cli-register-json.d.ts +3 -0
- package/dist/cli-register-json.d.ts.map +1 -0
- package/dist/cli-register-json.js +35 -0
- package/dist/cli-register-maintenance.d.ts.map +1 -1
- package/dist/cli-register-maintenance.js +41 -8
- package/dist/cli-register-reporting.d.ts.map +1 -1
- package/dist/cli-register-reporting.js +18 -14
- package/dist/cli-register-skills.d.ts.map +1 -1
- package/dist/cli-register-skills.js +8 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/commands/aggregated-checks.d.ts.map +1 -1
- package/dist/commands/aggregated-checks.js +1 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +30 -12
- package/dist/commands/coverage.d.ts +5 -0
- package/dist/commands/coverage.d.ts.map +1 -1
- package/dist/commands/coverage.js +6 -1
- package/dist/commands/discovery-shared.d.ts +2 -1
- package/dist/commands/discovery-shared.d.ts.map +1 -1
- package/dist/commands/discovery-shared.js +35 -13
- package/dist/commands/discovery-table.d.ts.map +1 -1
- package/dist/commands/discovery-table.js +96 -5
- package/dist/commands/engine.d.ts +8 -0
- package/dist/commands/engine.d.ts.map +1 -0
- package/dist/commands/engine.js +100 -0
- package/dist/commands/gaps.js +1 -1
- package/dist/commands/graph.js +1 -1
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +3 -1
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +3 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +2 -1
- package/dist/commands/sync/cache.d.ts +12 -0
- package/dist/commands/sync/cache.d.ts.map +1 -1
- package/dist/commands/sync/cache.js +38 -1
- package/dist/commands/sync/persistence.d.ts +10 -1
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +276 -43
- package/dist/commands/sync/staging.d.ts +10 -1
- package/dist/commands/sync/staging.d.ts.map +1 -1
- package/dist/commands/sync/staging.js +84 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +521 -27
- package/dist/commands/usage-metrics.d.ts +66 -2
- package/dist/commands/usage-metrics.d.ts.map +1 -1
- package/dist/commands/usage-metrics.js +34 -24
- package/dist/commands/usage-remediation.d.ts +9 -0
- package/dist/commands/usage-remediation.d.ts.map +1 -0
- package/dist/commands/usage-remediation.js +52 -0
- package/dist/engine-daemon.d.ts +3 -0
- package/dist/engine-daemon.d.ts.map +1 -0
- package/dist/engine-daemon.js +34 -0
- package/dist/engine.d.ts +63 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +1256 -0
- package/dist/extractors/markdown.d.ts +8 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +69 -2
- package/dist/extractors/relationships.d.ts +2 -0
- package/dist/extractors/relationships.d.ts.map +1 -1
- package/dist/extractors/relationships.js +15 -17
- package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
- package/dist/operations/modeling/logic-modeling.js +14 -5
- package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
- package/dist/operations/modeling/model-requirement.js +27 -2
- package/dist/operations/modeling/predicate-applyplan.d.ts +1 -1
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +18 -6
- package/dist/operations/modeling/predicate-inference.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-inference.js +5 -17
- package/dist/operations/modeling/predicate-loader.js +1 -1
- package/dist/operations/modeling/predicate-types.d.ts +9 -1
- package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.js +35 -11
- package/dist/operations/mutation/audit.js +1 -1
- package/dist/operations/mutation/contradictions.d.ts +1 -1
- package/dist/operations/mutation/contradictions.d.ts.map +1 -1
- package/dist/operations/mutation/contradictions.js +23 -18
- package/dist/operations/mutation/serialization.d.ts.map +1 -1
- package/dist/operations/mutation/serialization.js +6 -3
- package/dist/operations/mutation/upsert.d.ts +3 -1
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +51 -12
- package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
- package/dist/operations/mutation/validate-upsert.js +18 -2
- package/dist/operations/mutation/validation.d.ts.map +1 -1
- package/dist/operations/mutation/validation.js +8 -0
- package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analysis-receipt.js +7 -1
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +76 -61
- package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
- package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/clauses.js +7 -7
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +18 -0
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -0
- package/dist/operations/semantic-advisor/ingestion-boundary.js +167 -0
- package/dist/operations/semantic-advisor/shared.d.ts +8 -0
- package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/shared.js +37 -3
- package/dist/operations/semantic-advisor/types.d.ts +5 -0
- package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +9 -2
- package/dist/prolog.d.ts +14 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +279 -69
- package/dist/public/diagnostic-usage.d.ts +17 -0
- package/dist/public/diagnostic-usage.d.ts.map +1 -0
- package/dist/public/diagnostic-usage.js +152 -0
- package/dist/public/distribution-parity.d.ts +90 -0
- package/dist/public/distribution-parity.d.ts.map +1 -0
- package/dist/public/distribution-parity.js +367 -0
- package/dist/public/impact/full-kb-quality.d.ts +2 -0
- package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
- package/dist/public/impact/full-kb-quality.js +53 -1
- package/dist/public/impact-diagnostics.d.ts +2 -0
- package/dist/public/impact-diagnostics.d.ts.map +1 -1
- package/dist/public/impact-diagnostics.js +1 -0
- package/dist/public/operations/catalog.d.ts +151 -6
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +4 -0
- package/dist/public/operations/discovery-entities.d.ts.map +1 -1
- package/dist/public/operations/discovery-entities.js +3 -2
- package/dist/public/operations/discovery-executors.d.ts +6 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +58 -5
- package/dist/public/operations/index.d.ts +4 -0
- package/dist/public/operations/index.d.ts.map +1 -1
- package/dist/public/operations/index.js +4 -0
- package/dist/public/operations/legacy-migration-plan.d.ts +113 -0
- package/dist/public/operations/legacy-migration-plan.d.ts.map +1 -0
- package/dist/public/operations/legacy-migration-plan.js +409 -0
- package/dist/public/operations/node-ports.d.ts.map +1 -1
- package/dist/public/operations/node-ports.js +90 -0
- package/dist/public/operations/prolog-json.d.ts.map +1 -1
- package/dist/public/operations/prolog-json.js +14 -4
- package/dist/public/operations/repair-plan.d.ts +184 -0
- package/dist/public/operations/repair-plan.d.ts.map +1 -0
- package/dist/public/operations/repair-plan.js +397 -0
- package/dist/public/operations/runtime-types.d.ts +38 -0
- package/dist/public/operations/runtime-types.d.ts.map +1 -1
- package/dist/public/operations/specs/check.d.ts +2 -2
- package/dist/public/operations/specs/check.js +2 -2
- package/dist/public/operations/specs/discovery.d.ts +1 -1
- package/dist/public/operations/specs/discovery.js +1 -1
- package/dist/public/operations/specs/modeling.d.ts +19 -1
- package/dist/public/operations/specs/modeling.d.ts.map +1 -1
- package/dist/public/operations/specs/modeling.js +16 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts +96 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +40 -1
- package/dist/public/operations/specs/reporting.d.ts +42 -1
- package/dist/public/operations/specs/reporting.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.js +70 -6
- package/dist/public/operations/specs/semantic.js +1 -1
- package/dist/public/operations/specs/upsert.d.ts +96 -1
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/workspace-snapshot.d.ts +10 -0
- package/dist/public/operations/workspace-snapshot.d.ts.map +1 -0
- package/dist/public/operations/workspace-snapshot.js +20 -0
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +43 -1
- package/dist/public/skills/init-kibi/SKILL.md +2 -2
- package/dist/public/skills/kibi-freshness/SKILL.md +2 -2
- package/dist/public/skills/kibi-traceability/SKILL.md +8 -2
- package/dist/public/skills/kibi-usage/SKILL.md +12 -6
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
- package/dist/public/skills/kibi-usage/resources/logic-ir.md +1 -1
- package/dist/public/skills/kibi-usage/resources/operation-access.md +1 -1
- package/dist/public/skills/kibi-usage/resources/workflows.md +19 -2
- package/dist/public/telemetry-acceptance.d.ts +89 -0
- package/dist/public/telemetry-acceptance.d.ts.map +1 -0
- package/dist/public/telemetry-acceptance.js +597 -0
- package/dist/public/telemetry-remediation.d.ts +33 -0
- package/dist/public/telemetry-remediation.d.ts.map +1 -0
- package/dist/public/telemetry-remediation.js +257 -0
- package/dist/public/verification-receipt.d.ts +75 -0
- package/dist/public/verification-receipt.d.ts.map +1 -0
- package/dist/public/verification-receipt.js +129 -0
- package/dist/runtime/cli-runtime.d.ts.map +1 -1
- package/dist/runtime/cli-runtime.js +33 -37
- package/dist/schemas/entity.schema.json +96 -2
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +36 -3
- package/dist/types/entities.d.ts +1 -0
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/utils/rule-registry.d.ts +2 -0
- package/dist/utils/rule-registry.d.ts.map +1 -1
- package/package.json +36 -4
- package/src/public/diagnostic-usage.ts +206 -0
- package/src/public/distribution-parity.ts +580 -0
- package/src/public/impact/full-kb-quality.ts +74 -1
- package/src/public/impact-diagnostics.ts +16 -0
- package/src/public/operations/check-executor.ts +4 -0
- package/src/public/operations/discovery-entities.ts +3 -2
- package/src/public/operations/discovery-executors.ts +68 -5
- package/src/public/operations/index.ts +4 -0
- package/src/public/operations/legacy-migration-plan.ts +688 -0
- package/src/public/operations/node-ports.ts +109 -0
- package/src/public/operations/prolog-json.ts +15 -3
- package/src/public/operations/repair-plan.ts +562 -0
- package/src/public/operations/runtime-types.ts +47 -0
- package/src/public/operations/specs/check.ts +2 -2
- package/src/public/operations/specs/discovery.ts +1 -1
- package/src/public/operations/specs/modeling.ts +19 -1
- package/src/public/operations/specs/mutation-schemas.ts +47 -1
- package/src/public/operations/specs/reporting.ts +91 -6
- package/src/public/operations/specs/semantic.ts +1 -1
- package/src/public/operations/workspace-snapshot.ts +28 -0
- package/src/public/schemas/entity.ts +44 -1
- package/src/public/skills/init-kibi/SKILL.md +2 -2
- package/src/public/skills/kibi-freshness/SKILL.md +2 -2
- package/src/public/skills/kibi-traceability/SKILL.md +8 -2
- package/src/public/skills/kibi-usage/SKILL.md +12 -6
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
- package/src/public/skills/kibi-usage/resources/logic-ir.md +1 -1
- package/src/public/skills/kibi-usage/resources/operation-access.md +1 -1
- package/src/public/skills/kibi-usage/resources/workflows.md +19 -2
- package/src/public/telemetry-acceptance.ts +859 -0
- package/src/public/telemetry-remediation.ts +462 -0
- package/src/public/verification-receipt.ts +170 -0
- package/src/schemas/entity.schema.json +96 -2
package/dist/prolog.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
|
-
import { spawn
|
|
18
|
+
import { spawn } from "node:child_process";
|
|
19
19
|
import { existsSync } from "node:fs";
|
|
20
20
|
import { createRequire } from "node:module";
|
|
21
21
|
import path from "node:path";
|
|
@@ -26,6 +26,22 @@ const PROLOG_OUTPUT_MAX_BUFFER_BYTES = 8 * 1024 * 1024;
|
|
|
26
26
|
const PROLOG_OUTPUT_OVERFLOW_ERROR = "Query exceeded bounded Prolog output capacity (ENOBUFS); narrow the operation or reduce stored entity size";
|
|
27
27
|
const INTERACTIVE_QUERY_FRAME_END = "__KIBI_QUERY_FRAME_END__";
|
|
28
28
|
const require = createRequire(import.meta.url);
|
|
29
|
+
function packageVersion(packagePath) {
|
|
30
|
+
try {
|
|
31
|
+
const packageJson = require(packagePath);
|
|
32
|
+
return typeof packageJson.version === "string"
|
|
33
|
+
? packageJson.version
|
|
34
|
+
: "unknown";
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return "unknown";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const KIBI_PACKAGE_VERSIONS = [
|
|
41
|
+
`kibi-cli@${packageVersion(path.join(importMetaDir, "..", "package.json"))}`,
|
|
42
|
+
`kibi-core@${packageVersion(path.join(importMetaDir, "..", "..", "core", "package.json"))}`,
|
|
43
|
+
`kibi-mcp@${packageVersion(path.join(importMetaDir, "..", "..", "mcp", "package.json"))}`,
|
|
44
|
+
].join(",");
|
|
29
45
|
export function resolveKbPlPath() {
|
|
30
46
|
// implements REQ-009
|
|
31
47
|
const overrideKbPath = getKbPlPathOverride();
|
|
@@ -74,12 +90,17 @@ export class PrologProcess {
|
|
|
74
90
|
cache = new Map();
|
|
75
91
|
interactiveQueryTail = Promise.resolve();
|
|
76
92
|
terminationPromise = null;
|
|
77
|
-
|
|
93
|
+
oneShotProcesses = new Set();
|
|
94
|
+
useOneShotMode;
|
|
78
95
|
attachedKbPath = null;
|
|
79
96
|
onProcessExit = null;
|
|
80
97
|
constructor(options = {}) {
|
|
81
98
|
this.swiplPath = options.swiplPath || "swipl";
|
|
82
99
|
this.timeout = options.timeout || 30000;
|
|
100
|
+
this.useOneShotMode =
|
|
101
|
+
options.oneShot ??
|
|
102
|
+
(process.env.NODE_ENV === "test" &&
|
|
103
|
+
typeof globalThis.Bun !== "undefined");
|
|
83
104
|
}
|
|
84
105
|
async start() {
|
|
85
106
|
if (!existsSync(this.swiplPath) && this.swiplPath !== "swipl") {
|
|
@@ -90,7 +111,15 @@ export class PrologProcess {
|
|
|
90
111
|
"-g",
|
|
91
112
|
`use_module('${kbPath}'), use_module(library(semweb/rdf_db)), set_prolog_flag(answer_write_options, [max_depth(0), quoted(true)])`,
|
|
92
113
|
"--quiet",
|
|
93
|
-
]
|
|
114
|
+
], {
|
|
115
|
+
detached: process.platform !== "win32",
|
|
116
|
+
env: {
|
|
117
|
+
...process.env,
|
|
118
|
+
KIBI_RUNTIME_NAME: process.versions.bun !== undefined ? "bun" : "node",
|
|
119
|
+
KIBI_RUNTIME_VERSION: process.versions.bun ?? process.versions.node ?? "unknown",
|
|
120
|
+
KIBI_PACKAGE_VERSIONS: process.env.KIBI_PACKAGE_VERSIONS ?? KIBI_PACKAGE_VERSIONS,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
94
123
|
this.clearQueryBuffers();
|
|
95
124
|
if (!this.process.stdout || !this.process.stderr || !this.process.stdin) {
|
|
96
125
|
throw new Error("Failed to spawn Prolog process");
|
|
@@ -164,34 +193,53 @@ export class PrologProcess {
|
|
|
164
193
|
return oneShotResult;
|
|
165
194
|
}
|
|
166
195
|
if (!isSingleGoal) {
|
|
167
|
-
|
|
196
|
+
// A batch is one logical write. Wrapping it here keeps RDF mutations
|
|
197
|
+
// atomic in the long-lived process; persistence is appended by the
|
|
198
|
+
// interactive wrapper once the transaction succeeds.
|
|
199
|
+
const batchGoal = `rdf_transaction((${goal.map((item) => this.normalizeGoal(item)).join(", ")}))`;
|
|
168
200
|
return this.query(batchGoal);
|
|
169
201
|
}
|
|
170
202
|
if (!this.isProcessUsable()) {
|
|
203
|
+
// Keep the low-level PrologPort useful for isolated callers that only
|
|
204
|
+
// need a single read (and for legacy unit fixtures). Normal CLI/MCP
|
|
205
|
+
// runtimes provide an EngineClient, while explicitly attached callers
|
|
206
|
+
// call start() and stay interactive; this fallback never participates
|
|
207
|
+
// in the engine-backed workflow.
|
|
208
|
+
if (this.process === null) {
|
|
209
|
+
return this.execOneShot(goal, this.attachedKbPath);
|
|
210
|
+
}
|
|
171
211
|
throw new Error("Prolog process not started");
|
|
172
212
|
}
|
|
173
213
|
const runInteractiveQuery = async () => {
|
|
174
214
|
this.clearQueryBuffers();
|
|
175
215
|
const debug = isPrologDebugEnabled();
|
|
176
216
|
const normalizedGoal = this.normalizeGoal(goal);
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
217
|
+
const goalLabel = this.goalLabel(normalizedGoal);
|
|
218
|
+
const shouldPersist = this.isMutatingGoal(normalizedGoal) &&
|
|
219
|
+
!normalizedGoal.includes("kb_save") &&
|
|
220
|
+
!normalizedGoal.includes("kb_commit_upsert");
|
|
221
|
+
const goalWithPersistence = shouldPersist
|
|
222
|
+
? `(${normalizedGoal}, kb_save)`
|
|
223
|
+
: normalizedGoal;
|
|
224
|
+
const wrappedGoal = /^once\s*\(/.test(goalWithPersistence)
|
|
225
|
+
? `catch(${goalWithPersistence}, _E, (print_message(error, _E), fail))`
|
|
226
|
+
: `catch(once((${goalWithPersistence})), _E, (print_message(error, _E), fail))`;
|
|
180
227
|
const start = Date.now();
|
|
181
228
|
if (debug) {
|
|
182
|
-
console.error(`[prolog debug] start query: ${
|
|
229
|
+
console.error(`[prolog debug] start query: ${goalLabel}`);
|
|
183
230
|
}
|
|
184
231
|
this.process?.stdin?.write(`${wrappedGoal}.\nwriteln('${INTERACTIVE_QUERY_FRAME_END}').\n`);
|
|
185
232
|
return new Promise((resolve, reject) => {
|
|
186
233
|
let settled = false;
|
|
187
234
|
const timeoutId = setTimeout(() => {
|
|
188
|
-
const
|
|
235
|
+
const stage = this.lastDiagnosticStage(this.errorBuffer) ?? "unknown";
|
|
236
|
+
const msg = `Query timeout after ${this.timeout / 1000}s (stage=${stage}, pid=${this.process?.pid ?? 0}, killed=${this.process?.killed ? "yes" : "no"}, exitCode=${this.process?.exitCode ?? "null"}, goal=${goalLabel})`;
|
|
189
237
|
if (debug) {
|
|
190
|
-
const tailOut = this.outputBuffer.slice(-2048);
|
|
191
|
-
const tailErr = this.errorBuffer.slice(-2048);
|
|
192
238
|
console.error(`[prolog debug] timeout: ${msg}`);
|
|
193
|
-
|
|
194
|
-
|
|
239
|
+
const runtime = this.errorBuffer
|
|
240
|
+
.split("\n")
|
|
241
|
+
.find((line) => line.includes("__KIBI_RUNTIME__"));
|
|
242
|
+
console.error(`[prolog debug] runtime=${runtime ?? "unknown"} packages=${process.env.KIBI_PACKAGE_VERSIONS ?? KIBI_PACKAGE_VERSIONS}`);
|
|
195
243
|
}
|
|
196
244
|
settled = true;
|
|
197
245
|
void this.terminate().finally(() => {
|
|
@@ -229,12 +277,12 @@ export class PrologProcess {
|
|
|
229
277
|
clearTimeout(timeoutId);
|
|
230
278
|
settled = true;
|
|
231
279
|
if (debug) {
|
|
232
|
-
console.error(`[prolog debug] query error: ${
|
|
280
|
+
console.error(`[prolog debug] query error: ${goalLabel} error=${this.errorBuffer.split("\n")[0]}`);
|
|
233
281
|
}
|
|
234
282
|
resolve({
|
|
235
283
|
success: false,
|
|
236
284
|
bindings: {},
|
|
237
|
-
error: this.translateError(this.errorBuffer),
|
|
285
|
+
error: this.addDiagnosticStage(this.translateError(this.errorBuffer), normalizedGoal, this.errorBuffer),
|
|
238
286
|
});
|
|
239
287
|
return;
|
|
240
288
|
}
|
|
@@ -268,7 +316,7 @@ export class PrologProcess {
|
|
|
268
316
|
this.cache.set(goalKey, result);
|
|
269
317
|
}
|
|
270
318
|
if (debug) {
|
|
271
|
-
console.error(`[prolog debug] query success: ${
|
|
319
|
+
console.error(`[prolog debug] query success: ${goalLabel} elapsed=${(Date.now() - start) / 1000}s`);
|
|
272
320
|
}
|
|
273
321
|
resolve(result);
|
|
274
322
|
return;
|
|
@@ -294,23 +342,34 @@ export class PrologProcess {
|
|
|
294
342
|
releaseQuery();
|
|
295
343
|
}
|
|
296
344
|
}
|
|
345
|
+
/** Execute a group of goals as one transaction and one durable save. */
|
|
346
|
+
async queryBatch(goals) {
|
|
347
|
+
return this.query([...goals]);
|
|
348
|
+
}
|
|
297
349
|
invalidateCache() {
|
|
298
350
|
this.cache.clear();
|
|
299
351
|
}
|
|
300
352
|
isCacheableGoal(goal) {
|
|
301
353
|
const trimmed = goal.trim();
|
|
354
|
+
if (trimmed.startsWith("rdf_transaction(") ||
|
|
355
|
+
this.isMutatingGoal(trimmed)) {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
302
358
|
return !(trimmed.startsWith("kb_attach(") ||
|
|
303
359
|
trimmed.startsWith("kb_detach") ||
|
|
304
360
|
trimmed.startsWith("kb_save") ||
|
|
361
|
+
trimmed.startsWith("kb_storage_status") ||
|
|
362
|
+
trimmed.startsWith("kb_storage_compact") ||
|
|
363
|
+
trimmed.startsWith("kb_storage_export") ||
|
|
364
|
+
trimmed.startsWith("status:") ||
|
|
365
|
+
trimmed.startsWith("kb_commit_upsert(") ||
|
|
305
366
|
trimmed.startsWith("kb_assert_") ||
|
|
306
367
|
trimmed.startsWith("kb_delete_") ||
|
|
307
368
|
trimmed.startsWith("kb_retract_"));
|
|
308
369
|
}
|
|
309
370
|
// implements REQ-009
|
|
310
371
|
isMutatingGoal(goal) {
|
|
311
|
-
return (
|
|
312
|
-
goal.includes("kb_delete_") ||
|
|
313
|
-
goal.includes("kb_retract_"));
|
|
372
|
+
return /(?:kb_(?:assert|delete|retract|commit|save|log)_|\bkb_save\b|\brdf_(?:assert|retract))/u.test(goal);
|
|
314
373
|
}
|
|
315
374
|
// implements REQ-009
|
|
316
375
|
isExplicitSaveGoal(goal) {
|
|
@@ -344,7 +403,7 @@ export class PrologProcess {
|
|
|
344
403
|
error: "KB already attached",
|
|
345
404
|
};
|
|
346
405
|
}
|
|
347
|
-
const attachResult = this.execOneShot(trimmedGoal, null);
|
|
406
|
+
const attachResult = await this.execOneShot(trimmedGoal, null);
|
|
348
407
|
if (attachResult.success) {
|
|
349
408
|
this.attachedKbPath = attachPath;
|
|
350
409
|
}
|
|
@@ -352,7 +411,7 @@ export class PrologProcess {
|
|
|
352
411
|
}
|
|
353
412
|
return this.execOneShot(trimmedGoal, this.attachedKbPath);
|
|
354
413
|
}
|
|
355
|
-
execOneShot(goal, kbPath) {
|
|
414
|
+
async execOneShot(goal, kbPath) {
|
|
356
415
|
const originalGoalList = Array.isArray(goal)
|
|
357
416
|
? goal.map((item) => this.normalizeGoal(item))
|
|
358
417
|
: [this.normalizeGoal(goal)];
|
|
@@ -386,37 +445,121 @@ export class PrologProcess {
|
|
|
386
445
|
kbPath ? "kb_detach" : "true",
|
|
387
446
|
"(QuerySucceeded == true -> (forall(member(Name=Value, Vars), (write(Name), write('='), write_term(Value, [quoted(true), max_depth(0)]), writeln('.'))), writeln('__KIBI_TRUE__.')) ; writeln('__KIBI_FALSE__.'))",
|
|
388
447
|
].join(", ");
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
448
|
+
const runtimeName = process.versions.bun !== undefined ? "bun" : "node";
|
|
449
|
+
const runtimeVersion = process.versions.bun ?? process.versions.node ?? "unknown";
|
|
450
|
+
const packageVersions = process.env.KIBI_PACKAGE_VERSIONS ?? KIBI_PACKAGE_VERSIONS;
|
|
451
|
+
let child;
|
|
452
|
+
try {
|
|
453
|
+
child = spawn(this.swiplPath, ["-q", "-g", prologGoal, "-t", "halt"], {
|
|
454
|
+
detached: process.platform !== "win32",
|
|
455
|
+
env: {
|
|
456
|
+
...process.env,
|
|
457
|
+
KIBI_GOAL: combinedGoal,
|
|
458
|
+
KIBI_RUNTIME_NAME: runtimeName,
|
|
459
|
+
KIBI_RUNTIME_VERSION: runtimeVersion,
|
|
460
|
+
KIBI_PACKAGE_VERSIONS: packageVersions,
|
|
461
|
+
...(kbPath ? { KIBI_KB_PATH: kbPath } : {}),
|
|
462
|
+
},
|
|
463
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
catch (error) {
|
|
467
|
+
return {
|
|
468
|
+
success: false,
|
|
469
|
+
bindings: {},
|
|
470
|
+
error: error instanceof Error ? error.message : String(error),
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
this.oneShotProcesses.add(child);
|
|
474
|
+
let stdout = "";
|
|
475
|
+
let stderr = "";
|
|
476
|
+
let outputBytes = 0;
|
|
477
|
+
let errorBytes = 0;
|
|
478
|
+
let outputOverflowed = false;
|
|
479
|
+
let timedOut = false;
|
|
480
|
+
let settled = false;
|
|
481
|
+
let closed = false;
|
|
482
|
+
let termination = null;
|
|
483
|
+
const appendChunk = (chunk, target) => {
|
|
484
|
+
if (outputOverflowed)
|
|
485
|
+
return;
|
|
486
|
+
const bytes = target === "stdout" ? outputBytes : errorBytes;
|
|
487
|
+
const remaining = PROLOG_OUTPUT_MAX_BUFFER_BYTES - bytes;
|
|
488
|
+
if (chunk.byteLength > remaining) {
|
|
489
|
+
const clipped = chunk.subarray(0, Math.max(0, remaining)).toString();
|
|
490
|
+
if (target === "stdout")
|
|
491
|
+
stdout += clipped;
|
|
492
|
+
else
|
|
493
|
+
stderr += clipped;
|
|
494
|
+
outputOverflowed = true;
|
|
495
|
+
termination ??= this.terminateProcessTree(child);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (target === "stdout") {
|
|
499
|
+
stdout += chunk.toString();
|
|
500
|
+
outputBytes += chunk.byteLength;
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
stderr += chunk.toString();
|
|
504
|
+
errorBytes += chunk.byteLength;
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
child.stdout?.on("data", (chunk) => appendChunk(chunk, "stdout"));
|
|
508
|
+
child.stderr?.on("data", (chunk) => appendChunk(chunk, "stderr"));
|
|
509
|
+
const completion = new Promise((resolve) => {
|
|
510
|
+
child.once("error", (error) => {
|
|
511
|
+
closed = true;
|
|
512
|
+
resolve({ code: null, signal: null, error });
|
|
513
|
+
});
|
|
514
|
+
child.once("close", (code, signal) => {
|
|
515
|
+
closed = true;
|
|
516
|
+
resolve({ code, signal });
|
|
517
|
+
});
|
|
399
518
|
});
|
|
400
|
-
|
|
401
|
-
(
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
519
|
+
const timeoutId = setTimeout(() => {
|
|
520
|
+
if (settled || closed)
|
|
521
|
+
return;
|
|
522
|
+
timedOut = true;
|
|
523
|
+
termination ??= this.terminateProcessTree(child);
|
|
524
|
+
}, this.timeout);
|
|
525
|
+
const result = await completion;
|
|
526
|
+
settled = true;
|
|
527
|
+
clearTimeout(timeoutId);
|
|
528
|
+
if (termination !== null)
|
|
529
|
+
await termination;
|
|
530
|
+
this.oneShotProcesses.delete(child);
|
|
531
|
+
const stage = this.lastDiagnosticStage(stderr) ?? "unknown";
|
|
532
|
+
if (isPrologDebugEnabled()) {
|
|
533
|
+
const runtime = stderr
|
|
534
|
+
.split("\n")
|
|
535
|
+
.find((line) => line.includes("__KIBI_RUNTIME__"));
|
|
536
|
+
if (runtime !== undefined) {
|
|
537
|
+
console.error(`[prolog debug] ${runtime}`);
|
|
538
|
+
}
|
|
539
|
+
console.error(`[prolog debug] child pid=${child.pid ?? 0} runtime=${runtimeName}@${runtimeVersion} packages=${packageVersions} stage=${stage}`);
|
|
540
|
+
}
|
|
541
|
+
if (timedOut) {
|
|
542
|
+
throw new Error(`Query timeout after ${this.timeout / 1000}s (stage=${stage}, pid=${child.pid ?? 0}, goal=${this.goalLabel(combinedGoal ?? "true")})`);
|
|
543
|
+
}
|
|
544
|
+
if (outputOverflowed) {
|
|
545
|
+
return {
|
|
546
|
+
success: false,
|
|
547
|
+
bindings: {},
|
|
548
|
+
error: this.addDiagnosticStage(PROLOG_OUTPUT_OVERFLOW_ERROR, combinedGoal ?? "true", stderr),
|
|
549
|
+
};
|
|
405
550
|
}
|
|
406
|
-
if (result.error
|
|
551
|
+
if (result.error !== undefined) {
|
|
407
552
|
return {
|
|
408
553
|
success: false,
|
|
409
554
|
bindings: {},
|
|
410
|
-
error:
|
|
555
|
+
error: this.addDiagnosticStage(result.error.message, combinedGoal ?? "true", stderr),
|
|
411
556
|
};
|
|
412
557
|
}
|
|
413
|
-
const stdout = result.stdout ?? "";
|
|
414
|
-
const stderr = result.stderr ?? "";
|
|
415
558
|
if (stderr.includes("ERROR")) {
|
|
416
559
|
return {
|
|
417
560
|
success: false,
|
|
418
561
|
bindings: {},
|
|
419
|
-
error: this.translateError(stderr),
|
|
562
|
+
error: this.addDiagnosticStage(this.translateError(stderr), combinedGoal ?? "true", stderr),
|
|
420
563
|
};
|
|
421
564
|
}
|
|
422
565
|
if (stdout.includes("__KIBI_TRUE__")) {
|
|
@@ -439,7 +582,7 @@ export class PrologProcess {
|
|
|
439
582
|
return {
|
|
440
583
|
success: false,
|
|
441
584
|
bindings: {},
|
|
442
|
-
error: `Query failed - stdout: ${stdout.substring(0, 200)}, stderr: ${stderr.substring(0, 200)}`,
|
|
585
|
+
error: this.addDiagnosticStage(`Query failed - stdout: ${stdout.substring(0, 200)}, stderr: ${stderr.substring(0, 200)}`, combinedGoal ?? "true", stderr),
|
|
443
586
|
};
|
|
444
587
|
}
|
|
445
588
|
normalizeGoal(goal) {
|
|
@@ -478,6 +621,66 @@ export class PrologProcess {
|
|
|
478
621
|
this.errorBuffer += chunk.toString();
|
|
479
622
|
this.errorBufferBytes += chunk.byteLength;
|
|
480
623
|
}
|
|
624
|
+
goalLabel(goal) {
|
|
625
|
+
const match = goal
|
|
626
|
+
.trim()
|
|
627
|
+
.match(/^([a-z][A-Za-z0-9_]*(?::[a-z][A-Za-z0-9_]*)?)/);
|
|
628
|
+
return match?.[1] ?? "anonymous";
|
|
629
|
+
}
|
|
630
|
+
addDiagnosticStage(message, goal, diagnostics) {
|
|
631
|
+
if (this.goalLabel(goal) !== "kb_commit_upsert")
|
|
632
|
+
return message;
|
|
633
|
+
const stage = this.lastDiagnosticStage(diagnostics);
|
|
634
|
+
return stage === null ? message : `${message} (stage=${stage})`;
|
|
635
|
+
}
|
|
636
|
+
lastDiagnosticStage(text) {
|
|
637
|
+
const matches = [...text.matchAll(/__KIBI_STAGE__:([^\s\r\n]+)/g)];
|
|
638
|
+
return matches.at(-1)?.[1] ?? null;
|
|
639
|
+
}
|
|
640
|
+
signalProcessTree(child, signal) {
|
|
641
|
+
const pid = child.pid;
|
|
642
|
+
if (pid === undefined || pid <= 0)
|
|
643
|
+
return;
|
|
644
|
+
if (process.platform !== "win32") {
|
|
645
|
+
try {
|
|
646
|
+
process.kill(-pid, signal);
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
catch {
|
|
650
|
+
// Fall back to the direct child when a process group is unavailable.
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
try {
|
|
654
|
+
child.kill(signal);
|
|
655
|
+
}
|
|
656
|
+
catch {
|
|
657
|
+
// The child may have exited between the group and direct kill attempts.
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
async terminateProcessTree(child) {
|
|
661
|
+
let closed = false;
|
|
662
|
+
const exited = new Promise((resolve) => {
|
|
663
|
+
const markExited = () => {
|
|
664
|
+
closed = true;
|
|
665
|
+
resolve();
|
|
666
|
+
};
|
|
667
|
+
child.once("close", markExited);
|
|
668
|
+
child.once("error", markExited);
|
|
669
|
+
});
|
|
670
|
+
if (child.exitCode === null)
|
|
671
|
+
this.signalProcessTree(child, "SIGTERM");
|
|
672
|
+
await Promise.race([
|
|
673
|
+
exited,
|
|
674
|
+
new Promise((resolve) => setTimeout(resolve, 1000)),
|
|
675
|
+
]);
|
|
676
|
+
if (!closed) {
|
|
677
|
+
this.signalProcessTree(child, "SIGKILL");
|
|
678
|
+
await Promise.race([
|
|
679
|
+
exited,
|
|
680
|
+
new Promise((resolve) => setTimeout(resolve, 1000)),
|
|
681
|
+
]);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
481
684
|
// implements REQ-009
|
|
482
685
|
isProcessUsable() {
|
|
483
686
|
return Boolean(this.process?.stdin &&
|
|
@@ -500,26 +703,39 @@ export class PrologProcess {
|
|
|
500
703
|
}
|
|
501
704
|
// implements REQ-core-prolog-process-management
|
|
502
705
|
translateError(errorText) {
|
|
706
|
+
// Diagnostic markers intentionally contain words such as `lock` and the
|
|
707
|
+
// audit path. Remove them before classifying the actual Prolog error so a
|
|
708
|
+
// contradiction at the check stage is not mistaken for an audit lock.
|
|
709
|
+
const cleanError = errorText.replace(/^__KIBI_(?:STAGE|RUNTIME)__:[^\r\n]*\r?\n?/gm, "");
|
|
710
|
+
if (cleanError.includes("stale_snapshot")) {
|
|
711
|
+
return "KB snapshot is stale; reattach or refresh the runtime before retrying (stale_snapshot)";
|
|
712
|
+
}
|
|
713
|
+
if ((cleanError.includes("audit_log") ||
|
|
714
|
+
cleanError.includes("audit.log") ||
|
|
715
|
+
cleanError.includes("Resource temporarily unavailable")) &&
|
|
716
|
+
(cleanError.includes("lock") || cleanError.includes("permission"))) {
|
|
717
|
+
return "Audit journal is locked by another Kibi runtime; restart the stale MCP/CLI session before retrying";
|
|
718
|
+
}
|
|
503
719
|
// SWI-Prolog print_message/2 formats errors as human-readable messages,
|
|
504
720
|
// not raw Prolog terms. Match the actual output format.
|
|
505
|
-
if (
|
|
506
|
-
/entity [`'"].+?[`'"]/.test(
|
|
721
|
+
if (cleanError.includes("does not exist") &&
|
|
722
|
+
/entity [`'"].+?[`'"]/.test(cleanError)) {
|
|
507
723
|
// SWI-Prolog doubles single quotes in formatted messages: ''REQ-TEST''
|
|
508
|
-
const entityIdMatch =
|
|
724
|
+
const entityIdMatch = cleanError.match(/entity [`'"]+(.+?)[`'"]+ does not exist/);
|
|
509
725
|
const matchedEntityId = entityIdMatch?.[1];
|
|
510
726
|
const entityId = matchedEntityId !== undefined
|
|
511
727
|
? matchedEntityId.replace(/^`?'+|'+`?$/g, "")
|
|
512
728
|
: "unknown";
|
|
513
|
-
if (
|
|
729
|
+
if (cleanError.includes("Target entity does not exist")) {
|
|
514
730
|
return `Target entity does not exist: ${entityId}`;
|
|
515
731
|
}
|
|
516
|
-
if (
|
|
732
|
+
if (cleanError.includes("Source entity does not exist")) {
|
|
517
733
|
return `Source entity does not exist: ${entityId}`;
|
|
518
734
|
}
|
|
519
735
|
return `Entity does not exist: ${entityId}`;
|
|
520
736
|
}
|
|
521
|
-
if (
|
|
522
|
-
const relMatch =
|
|
737
|
+
if (cleanError.includes("Type error: `relationship' expected")) {
|
|
738
|
+
const relMatch = cleanError.match(/\(Invalid relationship: ([^)]+)\)/);
|
|
523
739
|
const invalidRelationship = relMatch?.[1];
|
|
524
740
|
if (invalidRelationship !== undefined) {
|
|
525
741
|
return `Invalid relationship: ${invalidRelationship.trim()}`;
|
|
@@ -527,21 +743,21 @@ export class PrologProcess {
|
|
|
527
743
|
return "Invalid relationship type or direction";
|
|
528
744
|
}
|
|
529
745
|
// Fallback: check for raw Prolog error terms (used by other tools)
|
|
530
|
-
if (
|
|
531
|
-
|
|
746
|
+
if (cleanError.includes("existence_error") ||
|
|
747
|
+
cleanError.includes("Unknown procedure")) {
|
|
532
748
|
return "Predicate or file not found";
|
|
533
749
|
}
|
|
534
|
-
if (
|
|
750
|
+
if (cleanError.includes("permission_error")) {
|
|
535
751
|
return "Access denied or KB locked";
|
|
536
752
|
}
|
|
537
|
-
if (
|
|
538
|
-
|
|
753
|
+
if (cleanError.includes("syntax_error") ||
|
|
754
|
+
cleanError.includes("Operator expected")) {
|
|
539
755
|
return "Invalid query syntax";
|
|
540
756
|
}
|
|
541
|
-
if (
|
|
757
|
+
if (cleanError.includes("timeout_error")) {
|
|
542
758
|
return `Operation exceeded ${this.timeout / 1000}s timeout`;
|
|
543
759
|
}
|
|
544
|
-
const simpleError = (
|
|
760
|
+
const simpleError = (cleanError
|
|
545
761
|
.replace(/ERROR:\s*/g, "")
|
|
546
762
|
.replace(/^\*\*.*\*\*$/gm, "")
|
|
547
763
|
.replace(/^\s+/gm, "")
|
|
@@ -564,22 +780,16 @@ export class PrologProcess {
|
|
|
564
780
|
this.onProcessExit = null;
|
|
565
781
|
}
|
|
566
782
|
const current = this.process;
|
|
783
|
+
const oneShots = [...this.oneShotProcesses];
|
|
567
784
|
this.process = null;
|
|
568
785
|
this.clearQueryBuffers();
|
|
569
|
-
if (current) {
|
|
786
|
+
if (current || oneShots.length > 0) {
|
|
570
787
|
this.terminationPromise = (async () => {
|
|
571
|
-
current
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
resolve(undefined);
|
|
577
|
-
}, 1000);
|
|
578
|
-
current.on("exit", () => {
|
|
579
|
-
clearTimeout(timeout);
|
|
580
|
-
resolve(undefined);
|
|
581
|
-
});
|
|
582
|
-
});
|
|
788
|
+
if (current) {
|
|
789
|
+
current.stdin?.end();
|
|
790
|
+
await this.terminateProcessTree(current);
|
|
791
|
+
}
|
|
792
|
+
await Promise.all(oneShots.map((child) => this.terminateProcessTree(child)));
|
|
583
793
|
})();
|
|
584
794
|
try {
|
|
585
795
|
await this.terminationPromise;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface DiagnosticUsageInput {
|
|
2
|
+
readonly workspaceRoot: string;
|
|
3
|
+
readonly tool: string;
|
|
4
|
+
readonly businessArgs: Readonly<Record<string, unknown>>;
|
|
5
|
+
readonly telemetry: Readonly<Record<string, unknown>> | null;
|
|
6
|
+
readonly startedAt: Date;
|
|
7
|
+
readonly finishedAt?: Date;
|
|
8
|
+
readonly status: "success" | "error";
|
|
9
|
+
readonly result?: unknown;
|
|
10
|
+
readonly error?: string;
|
|
11
|
+
readonly requestId?: string;
|
|
12
|
+
readonly logPath?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function diagnosticMutationFingerprint(args: Readonly<Record<string, unknown>>): string;
|
|
15
|
+
export declare function deriveDiagnosticUsageFields(tool: string, args: Readonly<Record<string, unknown>>, telemetry: Readonly<Record<string, unknown>> | null, result: unknown): Record<string, unknown>;
|
|
16
|
+
export declare function appendCliDiagnosticUsage(input: DiagnosticUsageInput): void;
|
|
17
|
+
//# sourceMappingURL=diagnostic-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic-usage.d.ts","sourceRoot":"","sources":["../../src/public/diagnostic-usage.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7D,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AA4BD,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACtC,MAAM,CAIR;AAiED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACvC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,EACnD,MAAM,EAAE,OAAO,GACd,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmDzB;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAgC1E"}
|