bikky 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -26
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +7 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +22 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +61 -6
- package/dist/config.js.map +1 -1
- package/dist/config.test.js +17 -9
- package/dist/config.test.js.map +1 -1
- package/dist/daemon/capture-policy.d.ts +95 -0
- package/dist/daemon/capture-policy.d.ts.map +1 -0
- package/dist/daemon/capture-policy.js +139 -0
- package/dist/daemon/capture-policy.js.map +1 -0
- package/dist/daemon/capture-policy.test.d.ts +2 -0
- package/dist/daemon/capture-policy.test.d.ts.map +1 -0
- package/dist/daemon/capture-policy.test.js +46 -0
- package/dist/daemon/capture-policy.test.js.map +1 -0
- package/dist/daemon/consolidation.d.ts.map +1 -1
- package/dist/daemon/consolidation.js +84 -98
- package/dist/daemon/consolidation.js.map +1 -1
- package/dist/daemon/episode-summary.d.ts +77 -0
- package/dist/daemon/episode-summary.d.ts.map +1 -0
- package/dist/daemon/episode-summary.js +239 -0
- package/dist/daemon/episode-summary.js.map +1 -0
- package/dist/daemon/episode-summary.test.d.ts +2 -0
- package/dist/daemon/episode-summary.test.d.ts.map +1 -0
- package/dist/daemon/episode-summary.test.js +101 -0
- package/dist/daemon/episode-summary.test.js.map +1 -0
- package/dist/daemon/extraction.d.ts +25 -0
- package/dist/daemon/extraction.d.ts.map +1 -1
- package/dist/daemon/extraction.js +244 -124
- package/dist/daemon/extraction.js.map +1 -1
- package/dist/daemon/extraction.test.d.ts +2 -0
- package/dist/daemon/extraction.test.d.ts.map +1 -0
- package/dist/daemon/extraction.test.js +106 -0
- package/dist/daemon/extraction.test.js.map +1 -0
- package/dist/daemon/loop.d.ts.map +1 -1
- package/dist/daemon/loop.js +8 -6
- package/dist/daemon/loop.js.map +1 -1
- package/dist/daemon/qdrant.d.ts +59 -8
- package/dist/daemon/qdrant.d.ts.map +1 -1
- package/dist/daemon/qdrant.js +74 -23
- package/dist/daemon/qdrant.js.map +1 -1
- package/dist/daemon/qdrant.test.js +2 -2
- package/dist/daemon/qdrant.test.js.map +1 -1
- package/dist/daemon/relations.d.ts +6 -1
- package/dist/daemon/relations.d.ts.map +1 -1
- package/dist/daemon/relations.js +44 -63
- package/dist/daemon/relations.js.map +1 -1
- package/dist/daemon/session-index.d.ts +60 -0
- package/dist/daemon/session-index.d.ts.map +1 -0
- package/dist/daemon/session-index.js +136 -0
- package/dist/daemon/session-index.js.map +1 -0
- package/dist/daemon/session-index.test.d.ts +2 -0
- package/dist/daemon/session-index.test.d.ts.map +1 -0
- package/dist/daemon/session-index.test.js +54 -0
- package/dist/daemon/session-index.test.js.map +1 -0
- package/dist/daemon/session-summary.d.ts +69 -0
- package/dist/daemon/session-summary.d.ts.map +1 -0
- package/dist/daemon/session-summary.js +200 -0
- package/dist/daemon/session-summary.js.map +1 -0
- package/dist/daemon/session-summary.test.d.ts +2 -0
- package/dist/daemon/session-summary.test.d.ts.map +1 -0
- package/dist/daemon/session-summary.test.js +160 -0
- package/dist/daemon/session-summary.test.js.map +1 -0
- package/dist/daemon/staleness.test.d.ts +7 -0
- package/dist/daemon/staleness.test.d.ts.map +1 -0
- package/dist/daemon/staleness.test.js +128 -0
- package/dist/daemon/staleness.test.js.map +1 -0
- package/dist/daemon/workstream-summary.d.ts +68 -0
- package/dist/daemon/workstream-summary.d.ts.map +1 -0
- package/dist/daemon/workstream-summary.js +253 -0
- package/dist/daemon/workstream-summary.js.map +1 -0
- package/dist/daemon/workstream-summary.test.d.ts +2 -0
- package/dist/daemon/workstream-summary.test.d.ts.map +1 -0
- package/dist/daemon/workstream-summary.test.js +86 -0
- package/dist/daemon/workstream-summary.test.js.map +1 -0
- package/dist/lib/qdrant-client.d.ts +6 -1
- package/dist/lib/qdrant-client.d.ts.map +1 -1
- package/dist/lib/qdrant-client.js +3 -4
- package/dist/lib/qdrant-client.js.map +1 -1
- package/dist/lib/qdrant-client.test.js +21 -2
- package/dist/lib/qdrant-client.test.js.map +1 -1
- package/dist/lifecycle.test.d.ts +8 -0
- package/dist/lifecycle.test.d.ts.map +1 -0
- package/dist/lifecycle.test.js +74 -0
- package/dist/lifecycle.test.js.map +1 -0
- package/dist/llm/embedding/index.d.ts +42 -0
- package/dist/llm/embedding/index.d.ts.map +1 -0
- package/dist/llm/embedding/index.js +78 -0
- package/dist/llm/embedding/index.js.map +1 -0
- package/dist/llm/embedding/index.test.d.ts +8 -0
- package/dist/llm/embedding/index.test.d.ts.map +1 -0
- package/dist/llm/embedding/index.test.js +100 -0
- package/dist/llm/embedding/index.test.js.map +1 -0
- package/dist/llm/embedding/providers/bedrock.d.ts +16 -0
- package/dist/llm/embedding/providers/bedrock.d.ts.map +1 -0
- package/dist/llm/embedding/providers/bedrock.js +90 -0
- package/dist/llm/embedding/providers/bedrock.js.map +1 -0
- package/dist/llm/embedding/providers/bedrock.test.d.ts +2 -0
- package/dist/llm/embedding/providers/bedrock.test.d.ts.map +1 -0
- package/dist/llm/embedding/providers/bedrock.test.js +24 -0
- package/dist/llm/embedding/providers/bedrock.test.js.map +1 -0
- package/dist/llm/embedding/providers/index.d.ts +9 -0
- package/dist/llm/embedding/providers/index.d.ts.map +1 -0
- package/dist/llm/embedding/providers/index.js +9 -0
- package/dist/llm/embedding/providers/index.js.map +1 -0
- package/dist/llm/embedding/providers/ollama.d.ts +6 -0
- package/dist/llm/embedding/providers/ollama.d.ts.map +1 -0
- package/dist/llm/embedding/providers/ollama.js +39 -0
- package/dist/llm/embedding/providers/ollama.js.map +1 -0
- package/dist/llm/embedding/providers/ollama.test.d.ts +2 -0
- package/dist/llm/embedding/providers/ollama.test.d.ts.map +1 -0
- package/dist/llm/embedding/providers/ollama.test.js +54 -0
- package/dist/llm/embedding/providers/ollama.test.js.map +1 -0
- package/dist/llm/embedding/providers/openai.d.ts +6 -0
- package/dist/llm/embedding/providers/openai.d.ts.map +1 -0
- package/dist/llm/embedding/providers/openai.js +44 -0
- package/dist/llm/embedding/providers/openai.js.map +1 -0
- package/dist/llm/embedding/providers/openai.test.d.ts +2 -0
- package/dist/llm/embedding/providers/openai.test.d.ts.map +1 -0
- package/dist/llm/embedding/providers/openai.test.js +48 -0
- package/dist/llm/embedding/providers/openai.test.js.map +1 -0
- package/dist/llm/embedding/providers/portkey.d.ts +15 -0
- package/dist/llm/embedding/providers/portkey.d.ts.map +1 -0
- package/dist/llm/embedding/providers/portkey.js +58 -0
- package/dist/llm/embedding/providers/portkey.js.map +1 -0
- package/dist/llm/embedding/providers/portkey.test.d.ts +2 -0
- package/dist/llm/embedding/providers/portkey.test.d.ts.map +1 -0
- package/dist/llm/embedding/providers/portkey.test.js +56 -0
- package/dist/llm/embedding/providers/portkey.test.js.map +1 -0
- package/dist/llm/embedding/registry.d.ts +14 -0
- package/dist/llm/embedding/registry.d.ts.map +1 -0
- package/dist/llm/embedding/registry.js +27 -0
- package/dist/llm/embedding/registry.js.map +1 -0
- package/dist/llm/embedding/registry.test.d.ts +7 -0
- package/dist/llm/embedding/registry.test.d.ts.map +1 -0
- package/dist/llm/embedding/registry.test.js +68 -0
- package/dist/llm/embedding/registry.test.js.map +1 -0
- package/dist/llm/embedding/types.d.ts +55 -0
- package/dist/llm/embedding/types.d.ts.map +1 -0
- package/dist/llm/embedding/types.js +12 -0
- package/dist/llm/embedding/types.js.map +1 -0
- package/dist/llm/errors.d.ts +95 -0
- package/dist/llm/errors.d.ts.map +1 -0
- package/dist/llm/errors.js +164 -0
- package/dist/llm/errors.js.map +1 -0
- package/dist/llm/errors.test.d.ts +2 -0
- package/dist/llm/errors.test.d.ts.map +1 -0
- package/dist/llm/errors.test.js +103 -0
- package/dist/llm/errors.test.js.map +1 -0
- package/dist/llm/fetch.d.ts +39 -0
- package/dist/llm/fetch.d.ts.map +1 -0
- package/dist/llm/fetch.js +52 -0
- package/dist/llm/fetch.js.map +1 -0
- package/dist/llm/index.d.ts +6 -3
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +2 -2
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/inference/index.d.ts +39 -0
- package/dist/llm/inference/index.d.ts.map +1 -0
- package/dist/llm/inference/index.js +118 -0
- package/dist/llm/inference/index.js.map +1 -0
- package/dist/llm/inference/index.test.d.ts +6 -0
- package/dist/llm/inference/index.test.d.ts.map +1 -0
- package/dist/llm/inference/index.test.js +109 -0
- package/dist/llm/inference/index.test.js.map +1 -0
- package/dist/llm/inference/providers/bedrock.d.ts +18 -0
- package/dist/llm/inference/providers/bedrock.d.ts.map +1 -0
- package/dist/llm/inference/providers/bedrock.js +105 -0
- package/dist/llm/inference/providers/bedrock.js.map +1 -0
- package/dist/llm/inference/providers/bedrock.test.d.ts +2 -0
- package/dist/llm/inference/providers/bedrock.test.d.ts.map +1 -0
- package/dist/llm/inference/providers/bedrock.test.js +21 -0
- package/dist/llm/inference/providers/bedrock.test.js.map +1 -0
- package/dist/llm/inference/providers/index.d.ts +10 -0
- package/dist/llm/inference/providers/index.d.ts.map +1 -0
- package/dist/llm/inference/providers/index.js +10 -0
- package/dist/llm/inference/providers/index.js.map +1 -0
- package/dist/llm/inference/providers/ollama.d.ts +8 -0
- package/dist/llm/inference/providers/ollama.d.ts.map +1 -0
- package/dist/llm/inference/providers/ollama.js +63 -0
- package/dist/llm/inference/providers/ollama.js.map +1 -0
- package/dist/llm/inference/providers/ollama.test.d.ts +2 -0
- package/dist/llm/inference/providers/ollama.test.d.ts.map +1 -0
- package/dist/llm/inference/providers/ollama.test.js +57 -0
- package/dist/llm/inference/providers/ollama.test.js.map +1 -0
- package/dist/llm/inference/providers/openai.d.ts +11 -0
- package/dist/llm/inference/providers/openai.d.ts.map +1 -0
- package/dist/llm/inference/providers/openai.js +73 -0
- package/dist/llm/inference/providers/openai.js.map +1 -0
- package/dist/llm/inference/providers/openai.test.d.ts +2 -0
- package/dist/llm/inference/providers/openai.test.d.ts.map +1 -0
- package/dist/llm/inference/providers/openai.test.js +46 -0
- package/dist/llm/inference/providers/openai.test.js.map +1 -0
- package/dist/llm/inference/providers/portkey.d.ts +13 -0
- package/dist/llm/inference/providers/portkey.d.ts.map +1 -0
- package/dist/llm/inference/providers/portkey.js +80 -0
- package/dist/llm/inference/providers/portkey.js.map +1 -0
- package/dist/llm/inference/providers/portkey.test.d.ts +2 -0
- package/dist/llm/inference/providers/portkey.test.d.ts.map +1 -0
- package/dist/llm/inference/providers/portkey.test.js +48 -0
- package/dist/llm/inference/providers/portkey.test.js.map +1 -0
- package/dist/llm/inference/registry.d.ts +15 -0
- package/dist/llm/inference/registry.d.ts.map +1 -0
- package/dist/llm/inference/registry.js +28 -0
- package/dist/llm/inference/registry.js.map +1 -0
- package/dist/llm/inference/registry.test.d.ts +6 -0
- package/dist/llm/inference/registry.test.d.ts.map +1 -0
- package/dist/llm/inference/registry.test.js +63 -0
- package/dist/llm/inference/registry.test.js.map +1 -0
- package/dist/llm/inference/types.d.ts +84 -0
- package/dist/llm/inference/types.d.ts.map +1 -0
- package/dist/llm/inference/types.js +9 -0
- package/dist/llm/inference/types.js.map +1 -0
- package/dist/llm/telemetry.d.ts +25 -0
- package/dist/llm/telemetry.d.ts.map +1 -0
- package/dist/llm/telemetry.js +43 -0
- package/dist/llm/telemetry.js.map +1 -0
- package/dist/llm/telemetry.test.d.ts +5 -0
- package/dist/llm/telemetry.test.d.ts.map +1 -0
- package/dist/llm/telemetry.test.js +89 -0
- package/dist/llm/telemetry.test.js.map +1 -0
- package/dist/llm/types.d.ts +4 -37
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/llm/types.js +4 -1
- package/dist/llm/types.js.map +1 -1
- package/dist/logger.d.ts +18 -3
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +102 -20
- package/dist/logger.js.map +1 -1
- package/dist/logger.test.d.ts +5 -0
- package/dist/logger.test.d.ts.map +1 -0
- package/dist/logger.test.js +103 -0
- package/dist/logger.test.js.map +1 -0
- package/dist/mcp/api.d.ts +15 -1
- package/dist/mcp/api.d.ts.map +1 -1
- package/dist/mcp/api.js +44 -19
- package/dist/mcp/api.js.map +1 -1
- package/dist/mcp/api.test.d.ts +6 -0
- package/dist/mcp/api.test.d.ts.map +1 -0
- package/dist/mcp/api.test.js +130 -0
- package/dist/mcp/api.test.js.map +1 -0
- package/dist/mcp/helpers.d.ts +1 -0
- package/dist/mcp/helpers.d.ts.map +1 -1
- package/dist/mcp/helpers.js +62 -6
- package/dist/mcp/helpers.js.map +1 -1
- package/dist/mcp/helpers.test.js +71 -10
- package/dist/mcp/helpers.test.js.map +1 -1
- package/dist/mcp/index.d.ts +7 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +38 -20
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/taxonomy.d.ts +237 -31
- package/dist/mcp/taxonomy.d.ts.map +1 -1
- package/dist/mcp/taxonomy.js +533 -171
- package/dist/mcp/taxonomy.js.map +1 -1
- package/dist/mcp/taxonomy.test.d.ts +1 -1
- package/dist/mcp/taxonomy.test.js +141 -302
- package/dist/mcp/taxonomy.test.js.map +1 -1
- package/dist/mcp/tools.d.ts +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.integration.itest.d.ts +23 -0
- package/dist/mcp/tools.integration.itest.d.ts.map +1 -0
- package/dist/mcp/tools.integration.itest.js +172 -0
- package/dist/mcp/tools.integration.itest.js.map +1 -0
- package/dist/mcp/tools.js +338 -302
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp/tools.test.d.ts +16 -0
- package/dist/mcp/tools.test.d.ts.map +1 -0
- package/dist/mcp/tools.test.js +472 -0
- package/dist/mcp/tools.test.js.map +1 -0
- package/dist/mcp/types.d.ts +63 -8
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/prompts/brief.d.ts +19 -0
- package/dist/prompts/brief.d.ts.map +1 -0
- package/dist/prompts/brief.js +67 -0
- package/dist/prompts/brief.js.map +1 -0
- package/dist/prompts/contradiction.d.ts +24 -0
- package/dist/prompts/contradiction.d.ts.map +1 -0
- package/dist/prompts/contradiction.js +73 -0
- package/dist/prompts/contradiction.js.map +1 -0
- package/dist/prompts/distill.d.ts +21 -0
- package/dist/prompts/distill.d.ts.map +1 -0
- package/dist/prompts/distill.js +74 -0
- package/dist/prompts/distill.js.map +1 -0
- package/dist/prompts/extraction.d.ts +14 -0
- package/dist/prompts/extraction.d.ts.map +1 -0
- package/dist/prompts/extraction.js +87 -0
- package/dist/prompts/extraction.js.map +1 -0
- package/dist/prompts/index.d.ts +50 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +102 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/prompts.test.d.ts +8 -0
- package/dist/prompts/prompts.test.d.ts.map +1 -0
- package/dist/prompts/prompts.test.js +140 -0
- package/dist/prompts/prompts.test.js.map +1 -0
- package/dist/prompts/relations.d.ts +17 -0
- package/dist/prompts/relations.d.ts.map +1 -0
- package/dist/prompts/relations.js +72 -0
- package/dist/prompts/relations.js.map +1 -0
- package/dist/render.d.ts +41 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +173 -0
- package/dist/render.js.map +1 -0
- package/dist/render.test.d.ts +8 -0
- package/dist/render.test.d.ts.map +1 -0
- package/dist/render.test.js +212 -0
- package/dist/render.test.js.map +1 -0
- package/package.json +9 -2
- package/dist/llm/embedding.d.ts +0 -13
- package/dist/llm/embedding.d.ts.map +0 -1
- package/dist/llm/embedding.js +0 -127
- package/dist/llm/embedding.js.map +0 -1
- package/dist/llm/embedding.test.d.ts +0 -8
- package/dist/llm/embedding.test.d.ts.map +0 -1
- package/dist/llm/embedding.test.js +0 -117
- package/dist/llm/embedding.test.js.map +0 -1
- package/dist/llm/inference.d.ts +0 -12
- package/dist/llm/inference.d.ts.map +0 -1
- package/dist/llm/inference.js +0 -146
- package/dist/llm/inference.js.map +0 -1
- package/dist/llm/inference.test.d.ts +0 -8
- package/dist/llm/inference.test.d.ts.map +0 -1
- package/dist/llm/inference.test.js +0 -117
- package/dist/llm/inference.test.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.test.d.ts","sourceRoot":"","sources":["../../src/llm/telemetry.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for LLM telemetry — JSONL append, rotation, error swallowing.
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import os from "node:os";
|
|
9
|
+
import { estimateTokens, writeTelemetry } from "./telemetry.js";
|
|
10
|
+
describe("llm/telemetry", () => {
|
|
11
|
+
let dir;
|
|
12
|
+
let file;
|
|
13
|
+
const noopLog = () => undefined;
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), "bikky-telemetry-"));
|
|
16
|
+
file = path.join(dir, "llm.jsonl");
|
|
17
|
+
process.env.BIKKY_LLM_LOG = file;
|
|
18
|
+
delete process.env.BIKKY_LLM_LOG_MAX_BYTES;
|
|
19
|
+
});
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
delete process.env.BIKKY_LLM_LOG;
|
|
22
|
+
delete process.env.BIKKY_LLM_LOG_MAX_BYTES;
|
|
23
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
24
|
+
});
|
|
25
|
+
function makeRecord(overrides = {}) {
|
|
26
|
+
return {
|
|
27
|
+
ts: new Date().toISOString(),
|
|
28
|
+
prompt: "extraction",
|
|
29
|
+
model: "gpt-4o-mini",
|
|
30
|
+
provider: "openai",
|
|
31
|
+
ok: true,
|
|
32
|
+
latency_ms: 123,
|
|
33
|
+
tokens_in_est: 10,
|
|
34
|
+
tokens_out_est: 20,
|
|
35
|
+
...overrides,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
describe("estimateTokens", () => {
|
|
39
|
+
it("returns ceil(len/4) for non-empty input", () => {
|
|
40
|
+
assert.equal(estimateTokens(""), 0);
|
|
41
|
+
assert.equal(estimateTokens("abcd"), 1);
|
|
42
|
+
assert.equal(estimateTokens("abcde"), 2);
|
|
43
|
+
assert.equal(estimateTokens("a".repeat(100)), 25);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe("writeTelemetry", () => {
|
|
47
|
+
it("appends a JSONL record to the configured log path", async () => {
|
|
48
|
+
await writeTelemetry(makeRecord({ prompt: "first" }), noopLog);
|
|
49
|
+
await writeTelemetry(makeRecord({ prompt: "second" }), noopLog);
|
|
50
|
+
const lines = fs.readFileSync(file, "utf-8").trim().split("\n");
|
|
51
|
+
assert.equal(lines.length, 2);
|
|
52
|
+
const first = JSON.parse(lines[0]);
|
|
53
|
+
const second = JSON.parse(lines[1]);
|
|
54
|
+
assert.equal(first.prompt, "first");
|
|
55
|
+
assert.equal(second.prompt, "second");
|
|
56
|
+
assert.equal(first.provider, "openai");
|
|
57
|
+
});
|
|
58
|
+
it("creates the parent directory if missing", async () => {
|
|
59
|
+
const nested = path.join(dir, "a", "b", "c", "llm.jsonl");
|
|
60
|
+
process.env.BIKKY_LLM_LOG = nested;
|
|
61
|
+
await writeTelemetry(makeRecord(), noopLog);
|
|
62
|
+
assert.ok(fs.existsSync(nested));
|
|
63
|
+
});
|
|
64
|
+
it("rotates to .1 when the file exceeds max bytes", async () => {
|
|
65
|
+
process.env.BIKKY_LLM_LOG_MAX_BYTES = "200";
|
|
66
|
+
// Seed an oversize file
|
|
67
|
+
fs.writeFileSync(file, "x".repeat(500));
|
|
68
|
+
await writeTelemetry(makeRecord(), noopLog);
|
|
69
|
+
assert.ok(fs.existsSync(`${file}.1`), "rotated file should exist");
|
|
70
|
+
const active = fs.readFileSync(file, "utf-8");
|
|
71
|
+
// Active file should only contain the new record after rotation
|
|
72
|
+
assert.equal(active.trim().split("\n").length, 1);
|
|
73
|
+
});
|
|
74
|
+
it("never throws when the path is unwritable; warns once via the logger", async () => {
|
|
75
|
+
// Point at a path that cannot be created (parent is a file, not a dir)
|
|
76
|
+
const blocker = path.join(dir, "blocker");
|
|
77
|
+
fs.writeFileSync(blocker, "not-a-dir");
|
|
78
|
+
process.env.BIKKY_LLM_LOG = path.join(blocker, "llm.jsonl");
|
|
79
|
+
const warnings = [];
|
|
80
|
+
const log = (_level, msg) => { warnings.push(String(msg)); };
|
|
81
|
+
await writeTelemetry(makeRecord(), log);
|
|
82
|
+
await writeTelemetry(makeRecord(), log);
|
|
83
|
+
// Module-level `warned` flag may already be set from a previous test;
|
|
84
|
+
// assert at most one warning was added in this call sequence.
|
|
85
|
+
assert.ok(warnings.length <= 1, "should warn at most once per process");
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=telemetry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.test.js","sourceRoot":"","sources":["../../src/llm/telemetry.test.ts"],"names":[],"mappings":"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"}
|
package/dist/llm/types.d.ts
CHANGED
|
@@ -1,41 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Cross-cutting types not specific to embedding or inference.
|
|
3
|
+
* Embedding types live in ./embedding/types.ts.
|
|
4
|
+
* Inference types (ChatCompletionOpts, ResponseFormat, JsonSchemaSpec, etc.)
|
|
5
|
+
* live in ./inference/types.ts.
|
|
3
6
|
*/
|
|
4
7
|
export type LogFn = (level: string, ...args: unknown[]) => void;
|
|
5
|
-
export interface EmbeddingProviderConfig {
|
|
6
|
-
provider: "ollama" | "openai" | "bedrock";
|
|
7
|
-
baseUrl: string;
|
|
8
|
-
model: string;
|
|
9
|
-
dimensions: number;
|
|
10
|
-
apiKey: string | null;
|
|
11
|
-
}
|
|
12
|
-
export interface InferenceProviderConfig {
|
|
13
|
-
provider: "ollama" | "openai" | "bedrock";
|
|
14
|
-
ollama_url: string;
|
|
15
|
-
ollama_model: string;
|
|
16
|
-
openai_api_key: string | null;
|
|
17
|
-
openai_model: string;
|
|
18
|
-
bedrock_region: string;
|
|
19
|
-
bedrock_model: string;
|
|
20
|
-
}
|
|
21
|
-
export interface ChatCompletionOpts {
|
|
22
|
-
messages: Array<{
|
|
23
|
-
role: string;
|
|
24
|
-
content: string;
|
|
25
|
-
}>;
|
|
26
|
-
temperature?: number;
|
|
27
|
-
max_tokens?: number;
|
|
28
|
-
response_format?: ResponseFormat;
|
|
29
|
-
}
|
|
30
|
-
export type ResponseFormat = {
|
|
31
|
-
type: "json_object";
|
|
32
|
-
} | {
|
|
33
|
-
type: "json_schema";
|
|
34
|
-
json_schema: JsonSchemaSpec;
|
|
35
|
-
};
|
|
36
|
-
export interface JsonSchemaSpec {
|
|
37
|
-
name: string;
|
|
38
|
-
strict?: boolean;
|
|
39
|
-
schema: Record<string, unknown>;
|
|
40
|
-
}
|
|
41
8
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/llm/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC"}
|
package/dist/llm/types.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Cross-cutting types not specific to embedding or inference.
|
|
3
|
+
* Embedding types live in ./embedding/types.ts.
|
|
4
|
+
* Inference types (ChatCompletionOpts, ResponseFormat, JsonSchemaSpec, etc.)
|
|
5
|
+
* live in ./inference/types.ts.
|
|
3
6
|
*/
|
|
4
7
|
export {};
|
|
5
8
|
//# sourceMappingURL=types.js.map
|
package/dist/llm/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/llm/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Structured logger backed by pino.
|
|
3
|
+
*
|
|
4
|
+
* Output is JSON-lines written to a rotating log file. We do NOT log to
|
|
5
|
+
* stdout/stderr because the MCP server reserves stdio for its transport.
|
|
6
|
+
*
|
|
7
|
+
* The exported `LogFn` signature is preserved for backward compatibility:
|
|
8
|
+
* callers continue to invoke `log("INFO", "msg", ...args)` and pino emits
|
|
9
|
+
* a structured record `{level, time, name, msg, ...extra}`. New code can
|
|
10
|
+
* pass a plain object as the first arg to attach structured fields:
|
|
11
|
+
*
|
|
12
|
+
* log("INFO", { event: "embed_request", provider: "openai" }, "ok");
|
|
13
|
+
*
|
|
14
|
+
* We rotate the file in-process (no worker threads) by checking size after
|
|
15
|
+
* each write and recreating the pino destination when the threshold is
|
|
16
|
+
* exceeded.
|
|
4
17
|
*/
|
|
5
18
|
export type LogLevel = "DEBUG" | "INFO" | "WARN" | "ERROR";
|
|
6
|
-
export type LogFn = (level: LogLevel, ...args: unknown[]) => void;
|
|
19
|
+
export type LogFn = (level: LogLevel | string, ...args: unknown[]) => void;
|
|
7
20
|
interface LoggerOpts {
|
|
21
|
+
/** Bytes before rotation (default 2MB). */
|
|
8
22
|
maxSize?: number;
|
|
23
|
+
/** Rotated files to keep (default 3). */
|
|
9
24
|
maxFiles?: number;
|
|
10
25
|
}
|
|
11
26
|
export declare function createLogger(name: string, filePath: string, opts?: LoggerOpts): LogFn;
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAC3D,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAE3E,UAAU,UAAU;IAClB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAyCD,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,UAAe,GACpB,KAAK,CAsEP"}
|
package/dist/logger.js
CHANGED
|
@@ -1,41 +1,123 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Structured logger backed by pino.
|
|
3
|
+
*
|
|
4
|
+
* Output is JSON-lines written to a rotating log file. We do NOT log to
|
|
5
|
+
* stdout/stderr because the MCP server reserves stdio for its transport.
|
|
6
|
+
*
|
|
7
|
+
* The exported `LogFn` signature is preserved for backward compatibility:
|
|
8
|
+
* callers continue to invoke `log("INFO", "msg", ...args)` and pino emits
|
|
9
|
+
* a structured record `{level, time, name, msg, ...extra}`. New code can
|
|
10
|
+
* pass a plain object as the first arg to attach structured fields:
|
|
11
|
+
*
|
|
12
|
+
* log("INFO", { event: "embed_request", provider: "openai" }, "ok");
|
|
13
|
+
*
|
|
14
|
+
* We rotate the file in-process (no worker threads) by checking size after
|
|
15
|
+
* each write and recreating the pino destination when the threshold is
|
|
16
|
+
* exceeded.
|
|
4
17
|
*/
|
|
5
18
|
import fs from "node:fs";
|
|
6
19
|
import path from "node:path";
|
|
20
|
+
import pino from "pino";
|
|
21
|
+
const LEVEL_MAP = {
|
|
22
|
+
DEBUG: "debug",
|
|
23
|
+
INFO: "info",
|
|
24
|
+
WARN: "warn",
|
|
25
|
+
ERROR: "error",
|
|
26
|
+
debug: "debug",
|
|
27
|
+
info: "info",
|
|
28
|
+
warn: "warn",
|
|
29
|
+
error: "error",
|
|
30
|
+
};
|
|
31
|
+
function buildPino(name, filePath) {
|
|
32
|
+
const dest = pino.destination({ dest: filePath, sync: true, append: true, mkdir: true });
|
|
33
|
+
return pino({
|
|
34
|
+
name,
|
|
35
|
+
level: "debug",
|
|
36
|
+
// Omit pid / hostname — every line carries `name` instead.
|
|
37
|
+
base: { name },
|
|
38
|
+
timestamp: pino.stdTimeFunctions.isoTime,
|
|
39
|
+
formatters: {
|
|
40
|
+
// Emit human-readable level strings ("info") rather than numeric codes.
|
|
41
|
+
level(label) {
|
|
42
|
+
return { level: label };
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}, dest);
|
|
46
|
+
}
|
|
47
|
+
function safeSize(filePath) {
|
|
48
|
+
try {
|
|
49
|
+
return fs.statSync(filePath).size;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
7
55
|
export function createLogger(name, filePath, opts = {}) {
|
|
8
56
|
const maxSize = opts.maxSize ?? 2 * 1024 * 1024;
|
|
9
57
|
const maxFiles = opts.maxFiles ?? 3;
|
|
10
58
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
11
|
-
let
|
|
12
|
-
let
|
|
13
|
-
try {
|
|
14
|
-
currentSize = fs.fstatSync(fd).size;
|
|
15
|
-
}
|
|
16
|
-
catch { /* new file */ }
|
|
59
|
+
let logger = buildPino(name, filePath);
|
|
60
|
+
let writtenSinceCheck = 0;
|
|
17
61
|
function rotate() {
|
|
18
|
-
|
|
62
|
+
try {
|
|
63
|
+
logger.flush();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
/* ignore — pino sync mode flushes on every write */
|
|
67
|
+
}
|
|
19
68
|
for (let i = maxFiles - 1; i >= 1; i--) {
|
|
20
69
|
const from = i === 1 ? filePath : `${filePath}.${i - 1}`;
|
|
21
70
|
const to = `${filePath}.${i}`;
|
|
22
71
|
try {
|
|
23
72
|
fs.renameSync(from, to);
|
|
24
73
|
}
|
|
25
|
-
catch {
|
|
74
|
+
catch {
|
|
75
|
+
/* missing file is fine */
|
|
76
|
+
}
|
|
26
77
|
}
|
|
27
|
-
|
|
28
|
-
|
|
78
|
+
logger = buildPino(name, filePath);
|
|
79
|
+
writtenSinceCheck = 0;
|
|
29
80
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (currentSize > maxSize)
|
|
81
|
+
function maybeRotate() {
|
|
82
|
+
// Cheap heuristic: only stat the file once we've written enough bytes
|
|
83
|
+
// to plausibly cross the threshold. Avoids a stat on every log line.
|
|
84
|
+
if (writtenSinceCheck < 4096)
|
|
85
|
+
return;
|
|
86
|
+
writtenSinceCheck = 0;
|
|
87
|
+
if (safeSize(filePath) > maxSize)
|
|
38
88
|
rotate();
|
|
89
|
+
}
|
|
90
|
+
return (level, ...args) => {
|
|
91
|
+
const lvl = LEVEL_MAP[level] ?? "info";
|
|
92
|
+
const fn = logger[lvl].bind(logger);
|
|
93
|
+
let approxBytes = 0;
|
|
94
|
+
const first = args[0];
|
|
95
|
+
if (first !== null &&
|
|
96
|
+
typeof first === "object" &&
|
|
97
|
+
!Array.isArray(first) &&
|
|
98
|
+
!(first instanceof Error)) {
|
|
99
|
+
// Structured form: log("INFO", {fields}, "msg", ...)
|
|
100
|
+
const rest = args.slice(1);
|
|
101
|
+
const msg = rest
|
|
102
|
+
.map((a) => (typeof a === "string" ? a : a instanceof Error ? a.message : JSON.stringify(a)))
|
|
103
|
+
.join(" ");
|
|
104
|
+
fn(first, msg);
|
|
105
|
+
try {
|
|
106
|
+
approxBytes = JSON.stringify(first).length + msg.length;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
approxBytes = msg.length;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const msg = args
|
|
114
|
+
.map((a) => (typeof a === "string" ? a : a instanceof Error ? a.message : JSON.stringify(a)))
|
|
115
|
+
.join(" ");
|
|
116
|
+
fn(msg);
|
|
117
|
+
approxBytes = msg.length;
|
|
118
|
+
}
|
|
119
|
+
writtenSinceCheck += approxBytes + 80; // +80 for JSON envelope (level/time/name/...)
|
|
120
|
+
maybeRotate();
|
|
39
121
|
};
|
|
40
122
|
}
|
|
41
123
|
//# sourceMappingURL=logger.js.map
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.test.d.ts","sourceRoot":"","sources":["../src/logger.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the pino-backed structured file logger.
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import os from "node:os";
|
|
9
|
+
import { createLogger } from "./logger.js";
|
|
10
|
+
function readLines(file) {
|
|
11
|
+
return fs
|
|
12
|
+
.readFileSync(file, "utf-8")
|
|
13
|
+
.trim()
|
|
14
|
+
.split("\n")
|
|
15
|
+
.filter((l) => l.length > 0)
|
|
16
|
+
.map((l) => JSON.parse(l));
|
|
17
|
+
}
|
|
18
|
+
describe("logger (pino-backed)", () => {
|
|
19
|
+
let dir;
|
|
20
|
+
let file;
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), "bikky-logger-"));
|
|
23
|
+
file = path.join(dir, "nested", "test.log");
|
|
24
|
+
});
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
27
|
+
});
|
|
28
|
+
it("creates the parent directory and writes a JSON line with name + msg", () => {
|
|
29
|
+
const log = createLogger("svc", file);
|
|
30
|
+
log("INFO", "hello", { a: 1 });
|
|
31
|
+
const lines = readLines(file);
|
|
32
|
+
assert.equal(lines.length, 1);
|
|
33
|
+
assert.equal(lines[0].level, "info");
|
|
34
|
+
assert.equal(lines[0].name, "svc");
|
|
35
|
+
assert.equal(lines[0].msg, 'hello {"a":1}');
|
|
36
|
+
assert.match(lines[0].time, /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
|
|
37
|
+
});
|
|
38
|
+
it("maps DEBUG/INFO/WARN/ERROR levels to pino lowercase labels", () => {
|
|
39
|
+
const log = createLogger("svc", file);
|
|
40
|
+
log("DEBUG", "d");
|
|
41
|
+
log("INFO", "i");
|
|
42
|
+
log("WARN", "w");
|
|
43
|
+
log("ERROR", "e");
|
|
44
|
+
const lines = readLines(file);
|
|
45
|
+
assert.equal(lines.length, 4);
|
|
46
|
+
assert.deepEqual(lines.map((l) => [l.level, l.msg]), [
|
|
47
|
+
["debug", "d"],
|
|
48
|
+
["info", "i"],
|
|
49
|
+
["warn", "w"],
|
|
50
|
+
["error", "e"],
|
|
51
|
+
]);
|
|
52
|
+
});
|
|
53
|
+
it("merges a leading object arg as structured fields", () => {
|
|
54
|
+
const log = createLogger("svc", file);
|
|
55
|
+
log("INFO", { event: "embed_request", provider: "openai" }, "ok");
|
|
56
|
+
const lines = readLines(file);
|
|
57
|
+
assert.equal(lines.length, 1);
|
|
58
|
+
assert.equal(lines[0].event, "embed_request");
|
|
59
|
+
assert.equal(lines[0].provider, "openai");
|
|
60
|
+
assert.equal(lines[0].msg, "ok");
|
|
61
|
+
});
|
|
62
|
+
it("serialises non-string args into msg via JSON.stringify", () => {
|
|
63
|
+
const log = createLogger("svc", file);
|
|
64
|
+
log("INFO", "msg", [1, 2], 42);
|
|
65
|
+
const lines = readLines(file);
|
|
66
|
+
assert.equal(lines[0].msg, "msg [1,2] 42");
|
|
67
|
+
});
|
|
68
|
+
it("renders Error args via .message rather than {}", () => {
|
|
69
|
+
const log = createLogger("svc", file);
|
|
70
|
+
log("ERROR", "boom", new Error("kaboom"));
|
|
71
|
+
const lines = readLines(file);
|
|
72
|
+
assert.match(lines[0].msg, /boom kaboom/);
|
|
73
|
+
});
|
|
74
|
+
it("rotates when the file exceeds maxSize", () => {
|
|
75
|
+
const log = createLogger("svc", file, { maxSize: 200, maxFiles: 3 });
|
|
76
|
+
for (let i = 0; i < 50; i++)
|
|
77
|
+
log("INFO", "x".repeat(80));
|
|
78
|
+
assert.ok(fs.existsSync(file), "active log file exists");
|
|
79
|
+
assert.ok(fs.existsSync(`${file}.1`), "rotated file .1 exists");
|
|
80
|
+
const active = fs.statSync(file).size;
|
|
81
|
+
const rotated = fs.statSync(`${file}.1`).size;
|
|
82
|
+
assert.ok(active <= rotated);
|
|
83
|
+
});
|
|
84
|
+
it("caps the number of rotated files at maxFiles", () => {
|
|
85
|
+
const log = createLogger("svc", file, { maxSize: 100, maxFiles: 2 });
|
|
86
|
+
for (let i = 0; i < 100; i++)
|
|
87
|
+
log("INFO", "x".repeat(80));
|
|
88
|
+
assert.ok(fs.existsSync(`${file}.1`));
|
|
89
|
+
assert.ok(!fs.existsSync(`${file}.3`), "should not keep .3");
|
|
90
|
+
});
|
|
91
|
+
it("appends to an existing log file", () => {
|
|
92
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
93
|
+
fs.writeFileSync(file, '{"pre":"existing"}\n');
|
|
94
|
+
const log = createLogger("svc", file);
|
|
95
|
+
log("INFO", "after");
|
|
96
|
+
const contents = fs.readFileSync(file, "utf-8");
|
|
97
|
+
assert.ok(contents.startsWith('{"pre":"existing"}\n'));
|
|
98
|
+
const lines = contents.trim().split("\n");
|
|
99
|
+
const last = JSON.parse(lines[lines.length - 1]);
|
|
100
|
+
assert.equal(last.msg, "after");
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=logger.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.test.js","sourceRoot":"","sources":["../src/logger.test.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/api.d.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { QdrantFilter, QdrantGetResult, QdrantScrollResult, QdrantSearchResult } from "./types.js";
|
|
6
6
|
import { embed, getEmbeddingDimensions, getEmbeddingConfig, initEmbedding } from "../llm/index.js";
|
|
7
|
-
|
|
7
|
+
import type { ChatCompletionOpts } from "../llm/index.js";
|
|
8
|
+
export type { ResolvedEmbeddingConfig } from "../llm/index.js";
|
|
8
9
|
export { embed, getEmbeddingDimensions, getEmbeddingConfig, initEmbedding };
|
|
9
10
|
export declare const MEMORY_DIR: string;
|
|
10
11
|
export declare function getCollection(): string;
|
|
@@ -12,11 +13,24 @@ export declare function setCollection(name: string): void;
|
|
|
12
13
|
export declare let qdrantUrl: string | null;
|
|
13
14
|
export declare let qdrantApiKey: string | null;
|
|
14
15
|
export declare let ready: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Reason the system is not ready, when known. Set by `setSetupError` from the
|
|
18
|
+
* MCP boot path if `initEmbedding`/`ensureCollection` fails. Surfaced in
|
|
19
|
+
* `requireReady()` and `get_setup_status` so users see an actionable message
|
|
20
|
+
* instead of a generic "setup_required".
|
|
21
|
+
*/
|
|
22
|
+
export declare let setupError: string | null;
|
|
15
23
|
export declare function setQdrantUrl(v: string | null): void;
|
|
16
24
|
export declare function setQdrantApiKey(v: string | null): void;
|
|
17
25
|
export declare function setReady(v: boolean): void;
|
|
26
|
+
export declare function setSetupError(v: string | null): void;
|
|
18
27
|
export declare const log: import("../logger.js").LogFn;
|
|
19
28
|
export declare function chatComplete(systemPrompt: string, userPrompt: string): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Run a pre-rendered prompt (from src/prompts/*) through the LLM. The
|
|
31
|
+
* RenderedPrompt already carries messages, response_format, temperature, etc.
|
|
32
|
+
*/
|
|
33
|
+
export declare function chatCompleteRendered(opts: ChatCompletionOpts): Promise<string>;
|
|
20
34
|
export declare function qdrantReq<T>(method: string, urlPath: string, body?: unknown): Promise<T>;
|
|
21
35
|
export declare function ensureCollection(indexes: Array<{
|
|
22
36
|
field_name: string;
|
package/dist/mcp/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/mcp/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACxG,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,aAAa,EAA2B,MAAM,iBAAiB,CAAC;AAC5H,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAU5E,eAAO,MAAM,UAAU,QAAY,CAAC;AAGpC,wBAAgB,aAAa,IAAI,MAAM,CAA2B;AAClE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGhD;AAWD,eAAO,IAAI,SAAS,EAAE,MAAM,GAAG,IAAW,CAAC;AAC3C,eAAO,IAAI,YAAY,EAAE,MAAM,GAAG,IAAW,CAAC;AAC9C,eAAO,IAAI,KAAK,SAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/mcp/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACxG,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,aAAa,EAA2B,MAAM,iBAAiB,CAAC;AAC5H,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAU5E,eAAO,MAAM,UAAU,QAAY,CAAC;AAGpC,wBAAgB,aAAa,IAAI,MAAM,CAA2B;AAClE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGhD;AAWD,eAAO,IAAI,SAAS,EAAE,MAAM,GAAG,IAAW,CAAC;AAC3C,eAAO,IAAI,YAAY,EAAE,MAAM,GAAG,IAAW,CAAC;AAC9C,eAAO,IAAI,KAAK,SAAQ,CAAC;AACzB;;;;;GAKG;AACH,eAAO,IAAI,UAAU,EAAE,MAAM,GAAG,IAAW,CAAC;AAI5C,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGnD;AACD,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGtD;AACD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAAe;AACzD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAoB;AAMzE,eAAO,MAAM,GAAG,8BAGd,CAAC;AA0BH,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAa5F;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAKpF;AAqCD,wBAAsB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAE9F;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlH;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAInH;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAO7H;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAMhG;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAKxG;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAK7E"}
|
package/dist/mcp/api.js
CHANGED
|
@@ -28,6 +28,13 @@ let llmInitialized = false;
|
|
|
28
28
|
export let qdrantUrl = null;
|
|
29
29
|
export let qdrantApiKey = null;
|
|
30
30
|
export let ready = false;
|
|
31
|
+
/**
|
|
32
|
+
* Reason the system is not ready, when known. Set by `setSetupError` from the
|
|
33
|
+
* MCP boot path if `initEmbedding`/`ensureCollection` fails. Surfaced in
|
|
34
|
+
* `requireReady()` and `get_setup_status` so users see an actionable message
|
|
35
|
+
* instead of a generic "setup_required".
|
|
36
|
+
*/
|
|
37
|
+
export let setupError = null;
|
|
31
38
|
let client = null;
|
|
32
39
|
export function setQdrantUrl(v) {
|
|
33
40
|
qdrantUrl = v ? v.replace(/\/+$/, "") : v;
|
|
@@ -38,6 +45,7 @@ export function setQdrantApiKey(v) {
|
|
|
38
45
|
rebuildClient();
|
|
39
46
|
}
|
|
40
47
|
export function setReady(v) { ready = v; }
|
|
48
|
+
export function setSetupError(v) { setupError = v; }
|
|
41
49
|
// ---------------------------------------------------------------------------
|
|
42
50
|
// Logging (to file only — stdout/stderr are MCP stdio transport)
|
|
43
51
|
// ---------------------------------------------------------------------------
|
|
@@ -48,7 +56,7 @@ export const log = createLogger("memory-mcp", path.join(LOG_DIR, "mcp.log"), {
|
|
|
48
56
|
// Adapter to bridge QdrantClient's QdrantLogFn signature to our file logger.
|
|
49
57
|
const qdrantLogAdapter = (level, msg) => log(level, msg);
|
|
50
58
|
function rebuildClient() {
|
|
51
|
-
if (qdrantUrl &&
|
|
59
|
+
if (qdrantUrl && collectionName) {
|
|
52
60
|
const cfg = loadConfig();
|
|
53
61
|
client = new QdrantClient({
|
|
54
62
|
url: qdrantUrl,
|
|
@@ -68,22 +76,7 @@ function rebuildClient() {
|
|
|
68
76
|
// LLM Chat Completion (for distillation)
|
|
69
77
|
// ---------------------------------------------------------------------------
|
|
70
78
|
export async function chatComplete(systemPrompt, userPrompt) {
|
|
71
|
-
|
|
72
|
-
const cfg = loadConfig();
|
|
73
|
-
initLLM({
|
|
74
|
-
config: {
|
|
75
|
-
provider: cfg.llm.provider,
|
|
76
|
-
ollama_url: cfg.llm.base_url,
|
|
77
|
-
ollama_model: cfg.llm.model,
|
|
78
|
-
openai_api_key: cfg.llm.api_key ?? null,
|
|
79
|
-
openai_model: cfg.llm.model,
|
|
80
|
-
bedrock_region: cfg.llm.bedrock_region,
|
|
81
|
-
bedrock_model: cfg.llm.model,
|
|
82
|
-
},
|
|
83
|
-
logger: log,
|
|
84
|
-
});
|
|
85
|
-
llmInitialized = true;
|
|
86
|
-
}
|
|
79
|
+
ensureLLMInitialized();
|
|
87
80
|
const result = await chatCompletion({
|
|
88
81
|
messages: [
|
|
89
82
|
{ role: "system", content: systemPrompt },
|
|
@@ -96,13 +89,45 @@ export async function chatComplete(systemPrompt, userPrompt) {
|
|
|
96
89
|
throw new Error("LLM chat completion failed");
|
|
97
90
|
return result;
|
|
98
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Run a pre-rendered prompt (from src/prompts/*) through the LLM. The
|
|
94
|
+
* RenderedPrompt already carries messages, response_format, temperature, etc.
|
|
95
|
+
*/
|
|
96
|
+
export async function chatCompleteRendered(opts) {
|
|
97
|
+
ensureLLMInitialized();
|
|
98
|
+
const result = await chatCompletion(opts);
|
|
99
|
+
if (!result)
|
|
100
|
+
throw new Error("LLM chat completion failed");
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
function ensureLLMInitialized() {
|
|
104
|
+
if (llmInitialized)
|
|
105
|
+
return;
|
|
106
|
+
const cfg = loadConfig();
|
|
107
|
+
initLLM({
|
|
108
|
+
config: {
|
|
109
|
+
provider: cfg.llm.provider,
|
|
110
|
+
model: cfg.llm.model,
|
|
111
|
+
baseUrl: cfg.llm.base_url,
|
|
112
|
+
apiKey: cfg.llm.api_key ?? null,
|
|
113
|
+
fallback: cfg.llm.fallback_provider ?? null,
|
|
114
|
+
extra: cfg.llm.extra ?? {},
|
|
115
|
+
timeoutMs: cfg.llm.timeout_ms,
|
|
116
|
+
retries: cfg.llm.retries,
|
|
117
|
+
retryBaseDelayMs: cfg.llm.retry_base_delay_ms,
|
|
118
|
+
},
|
|
119
|
+
logger: log,
|
|
120
|
+
});
|
|
121
|
+
llmInitialized = true;
|
|
122
|
+
}
|
|
99
123
|
// ---------------------------------------------------------------------------
|
|
100
124
|
// Qdrant REST Client
|
|
101
125
|
// ---------------------------------------------------------------------------
|
|
102
126
|
function getClient() {
|
|
103
127
|
if (!client) {
|
|
104
|
-
throw new Error("Qdrant client not initialized —
|
|
105
|
-
"Use configure_credentials or set QDRANT_URL +
|
|
128
|
+
throw new Error("Qdrant client not initialized — URL missing. " +
|
|
129
|
+
"Use configure_credentials or set QDRANT_URL " +
|
|
130
|
+
"(QDRANT_API_KEY is optional for local / self-hosted instances).");
|
|
106
131
|
}
|
|
107
132
|
return client;
|
|
108
133
|
}
|