bikky 0.3.13 → 0.4.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.
Files changed (64) hide show
  1. package/CONTRIBUTING.md +206 -0
  2. package/README.md +64 -20
  3. package/dist/config.d.ts +49 -1
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +125 -4
  6. package/dist/config.js.map +1 -1
  7. package/dist/daemon/loop.d.ts.map +1 -1
  8. package/dist/daemon/loop.js +15 -1
  9. package/dist/daemon/loop.js.map +1 -1
  10. package/dist/daemon/qdrant.d.ts.map +1 -1
  11. package/dist/daemon/qdrant.js +0 -1
  12. package/dist/daemon/qdrant.js.map +1 -1
  13. package/dist/lib/qdrant-pool.d.ts +57 -0
  14. package/dist/lib/qdrant-pool.d.ts.map +1 -0
  15. package/dist/lib/qdrant-pool.js +104 -0
  16. package/dist/lib/qdrant-pool.js.map +1 -0
  17. package/dist/mcp/api.d.ts +56 -19
  18. package/dist/mcp/api.d.ts.map +1 -1
  19. package/dist/mcp/api.js +133 -72
  20. package/dist/mcp/api.js.map +1 -1
  21. package/dist/mcp/helpers.d.ts +0 -1
  22. package/dist/mcp/helpers.d.ts.map +1 -1
  23. package/dist/mcp/helpers.js +2 -15
  24. package/dist/mcp/helpers.js.map +1 -1
  25. package/dist/mcp/helpers.test.js +3 -21
  26. package/dist/mcp/helpers.test.js.map +1 -1
  27. package/dist/mcp/index.d.ts.map +1 -1
  28. package/dist/mcp/index.js +29 -14
  29. package/dist/mcp/index.js.map +1 -1
  30. package/dist/mcp/tools.d.ts +0 -7
  31. package/dist/mcp/tools.d.ts.map +1 -1
  32. package/dist/mcp/tools.js +337 -219
  33. package/dist/mcp/tools.js.map +1 -1
  34. package/dist/mcp/types.d.ts +0 -3
  35. package/dist/mcp/types.d.ts.map +1 -1
  36. package/dist/routing.d.ts +53 -0
  37. package/dist/routing.d.ts.map +1 -0
  38. package/dist/routing.js +129 -0
  39. package/dist/routing.js.map +1 -0
  40. package/dist/routing.test.d.ts +2 -0
  41. package/dist/routing.test.d.ts.map +1 -0
  42. package/dist/routing.test.js +79 -0
  43. package/dist/routing.test.js.map +1 -0
  44. package/docs/config/fully-hosted.md +57 -0
  45. package/docs/config/hosted-models.md +50 -0
  46. package/docs/config/hosted-qdrant-local-models.md +39 -0
  47. package/docs/config/local.md +34 -0
  48. package/docs/configuration.md +374 -0
  49. package/docs/screenshots/dashboard.png +0 -0
  50. package/docs/screenshots/graph.png +0 -0
  51. package/docs/screenshots/memory.png +0 -0
  52. package/package.json +6 -3
  53. package/dist/mcp/api.test.d.ts +0 -6
  54. package/dist/mcp/api.test.d.ts.map +0 -1
  55. package/dist/mcp/api.test.js +0 -130
  56. package/dist/mcp/api.test.js.map +0 -1
  57. package/dist/mcp/tools.integration.itest.d.ts +0 -23
  58. package/dist/mcp/tools.integration.itest.d.ts.map +0 -1
  59. package/dist/mcp/tools.integration.itest.js +0 -171
  60. package/dist/mcp/tools.integration.itest.js.map +0 -1
  61. package/dist/mcp/tools.test.d.ts +0 -16
  62. package/dist/mcp/tools.test.d.ts.map +0 -1
  63. package/dist/mcp/tools.test.js +0 -908
  64. package/dist/mcp/tools.test.js.map +0 -1
@@ -0,0 +1,79 @@
1
+ import { describe, it } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { resolveDestination, buildResolver, DestinationNotFoundError, NoDestinationsConfiguredError, } from "./routing.js";
4
+ const dst = (name, extra = {}) => ({
5
+ name,
6
+ qdrant_url: `https://${name}.example`,
7
+ qdrant_api_key: "k",
8
+ collection: "bikky",
9
+ ...extra,
10
+ });
11
+ describe("routing.resolveDestination", () => {
12
+ it("throws NoDestinationsConfiguredError when list is empty", () => {
13
+ assert.throws(() => resolveDestination({}, []), NoDestinationsConfiguredError);
14
+ });
15
+ it("respects explicit override by name", () => {
16
+ const a = dst("a");
17
+ const b = dst("b");
18
+ assert.equal(resolveDestination({ destination: "b" }, [a, b]).name, "b");
19
+ });
20
+ it("throws DestinationNotFoundError when override doesn't match", () => {
21
+ const a = dst("a");
22
+ assert.throws(() => resolveDestination({ destination: "ghost" }, [a]), DestinationNotFoundError);
23
+ });
24
+ it("matches by cwd regex", () => {
25
+ const work = dst("work", { match: { cwd: ["/repos/work"] } });
26
+ const personal = dst("personal", { default: true });
27
+ assert.equal(resolveDestination({ cwd: "/repos/work/api" }, [work, personal]).name, "work");
28
+ });
29
+ it("matches by entity regex", () => {
30
+ const acme = dst("acme", { match: { entity: ["^acme-"] } });
31
+ const fallback = dst("fallback", { default: true });
32
+ assert.equal(resolveDestination({ entities: ["acme-billing"] }, [acme, fallback]).name, "acme");
33
+ });
34
+ it("matches by content regex", () => {
35
+ const secrets = dst("secrets", { match: { content: ["password|secret"] } });
36
+ const fallback = dst("fallback", { default: true });
37
+ assert.equal(resolveDestination({ content: "rotated the secret" }, [secrets, fallback]).name, "secrets");
38
+ });
39
+ it("matches by metadata regex", () => {
40
+ const project = dst("project", { match: { metadata: { project: ["^acme$"] } } });
41
+ const fallback = dst("fallback", { default: true });
42
+ assert.equal(resolveDestination({ metadata: { project: "acme" } }, [project, fallback]).name, "project");
43
+ });
44
+ it("first matching destination wins (array order)", () => {
45
+ const a = dst("a", { match: { entity: ["foo"] } });
46
+ const b = dst("b", { match: { entity: ["foo"] } });
47
+ assert.equal(resolveDestination({ entities: ["foo"] }, [a, b]).name, "a");
48
+ });
49
+ it("falls back to default-flagged destination when no match", () => {
50
+ const a = dst("a", { match: { entity: ["nope"] } });
51
+ const b = dst("b", { default: true });
52
+ const c = dst("c");
53
+ assert.equal(resolveDestination({ entities: ["other"] }, [a, b, c]).name, "b");
54
+ });
55
+ it("falls back to first destination when no default flagged", () => {
56
+ const a = dst("a", { match: { entity: ["nope"] } });
57
+ const b = dst("b");
58
+ assert.equal(resolveDestination({ entities: ["other"] }, [a, b]).name, "a");
59
+ });
60
+ it("override beats matching", () => {
61
+ const a = dst("a", { match: { entity: ["foo"] } });
62
+ const b = dst("b");
63
+ assert.equal(resolveDestination({ destination: "b", entities: ["foo"] }, [a, b]).name, "b");
64
+ });
65
+ });
66
+ describe("routing.buildResolver", () => {
67
+ it("returns a closure that resolves consistently", () => {
68
+ const a = dst("a", { match: { entity: ["foo"] } });
69
+ const b = dst("b", { default: true });
70
+ const resolve = buildResolver([a, b]);
71
+ assert.equal(resolve({ entities: ["foo"] }).name, "a");
72
+ assert.equal(resolve({ entities: ["bar"] }).name, "b");
73
+ });
74
+ it("closure throws on empty destinations", () => {
75
+ const resolve = buildResolver([]);
76
+ assert.throws(() => resolve({}), NoDestinationsConfiguredError);
77
+ });
78
+ });
79
+ //# sourceMappingURL=routing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routing.test.js","sourceRoot":"","sources":["../src/routing.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ # Fully hosted config
2
+
3
+ Best for performance and teams. This setup uses Qdrant Cloud for managed vector storage and OpenAI-compatible hosted models for extraction, curation, and recall.
4
+
5
+ ## What you need
6
+
7
+ - A Qdrant Cloud cluster URL.
8
+ - A Qdrant API key.
9
+ - An OpenAI API key, or another hosted provider configured in the full configuration guide.
10
+
11
+ For both `embedding.provider` and `llm.provider`, possible values are `openai`, `bedrock`, or `portkey` for hosted models. `ollama` is also supported when you want local model calls.
12
+
13
+ ## Config
14
+
15
+ Save this as `~/.bikky/config.json`:
16
+
17
+ ```json
18
+ {
19
+ "qdrant_url": "https://your-cluster.cloud.qdrant.io:6333",
20
+ "qdrant_api_key": "your-qdrant-api-key",
21
+ "embedding": {
22
+ "provider": "openai",
23
+ "model": "text-embedding-3-small",
24
+ "dimensions": 1536,
25
+ "api_key": "sk-..."
26
+ },
27
+ "llm": {
28
+ "provider": "openai",
29
+ "model": "gpt-4.1-mini",
30
+ "api_key": "sk-..."
31
+ }
32
+ }
33
+ ```
34
+
35
+ `qdrant_api_key` is optional only for unauthenticated self-hosted Qdrant. Qdrant Cloud usually requires it.
36
+
37
+ Prefer not to store hosted model keys in the config file? Omit `api_key` above and set:
38
+
39
+ ```bash
40
+ export OPENAI_API_KEY="sk-..."
41
+ ```
42
+
43
+ ## Check it
44
+
45
+ ```bash
46
+ bikky status
47
+ ```
48
+
49
+ After changing Qdrant or provider settings, restart long-running processes:
50
+
51
+ ```bash
52
+ bikky stop && bikky start
53
+ ```
54
+
55
+ Then restart your editor so its MCP process reloads.
56
+
57
+ For Bedrock, Portkey, custom base URLs, or model-specific dimensions, see the [full configuration guide](../configuration.md).
@@ -0,0 +1,50 @@
1
+ # Local Qdrant + hosted models config
2
+
3
+ This setup keeps Qdrant local while hosted embeddings and LLM calls handle extraction, curation, and recall.
4
+
5
+ ## What you need
6
+
7
+ - Qdrant running locally, usually with Docker.
8
+ - An OpenAI API key, or another hosted provider configured in the full configuration guide.
9
+
10
+ For both `embedding.provider` and `llm.provider`, possible values are `openai`, `bedrock`, or `portkey` for hosted models. `ollama` is also supported when you want local model calls.
11
+
12
+ ## Config
13
+
14
+ Save this as `~/.bikky/config.json`:
15
+
16
+ ```json
17
+ {
18
+ "qdrant_url": "http://localhost:6333",
19
+ "qdrant_api_key": "",
20
+ "embedding": {
21
+ "provider": "openai",
22
+ "model": "text-embedding-3-small",
23
+ "dimensions": 1536,
24
+ "api_key": "sk-..."
25
+ },
26
+ "llm": {
27
+ "provider": "openai",
28
+ "model": "gpt-4.1-mini",
29
+ "api_key": "sk-..."
30
+ }
31
+ }
32
+ ```
33
+
34
+ `qdrant_api_key` is optional. Leave it empty or omit it for local or unauthenticated self-hosted Qdrant.
35
+
36
+ Prefer not to store hosted model keys in the config file? Omit `api_key` above and set:
37
+
38
+ ```bash
39
+ export OPENAI_API_KEY="sk-..."
40
+ ```
41
+
42
+ ## Check it
43
+
44
+ ```bash
45
+ bikky status
46
+ ```
47
+
48
+ If you started from a fresh install, run `bikky setup` after writing the config, then restart your editor so its MCP process reloads.
49
+
50
+ For Bedrock, Portkey, custom base URLs, or model-specific dimensions, see the [full configuration guide](../configuration.md).
@@ -0,0 +1,39 @@
1
+ # Hosted Qdrant + local models
2
+
3
+ Use this path when you want memory shared across machines, but you still want embeddings and background curation to run through local Ollama.
4
+
5
+ ## What you need
6
+
7
+ - A Qdrant Cloud cluster URL.
8
+ - A Qdrant API key.
9
+ - Ollama installed locally.
10
+ - The default embedding model pulled with `ollama pull qwen3-embedding:0.6b`.
11
+
12
+ ## Config
13
+
14
+ Save this as `~/.bikky/config.json`:
15
+
16
+ ```json
17
+ {
18
+ "qdrant_url": "https://your-cluster.cloud.qdrant.io:6333",
19
+ "qdrant_api_key": "your-qdrant-api-key"
20
+ }
21
+ ```
22
+
23
+ bikky will store memory in hosted Qdrant and keep model calls local through Ollama.
24
+
25
+ `qdrant_api_key` is optional only for unauthenticated self-hosted Qdrant. Qdrant Cloud usually requires it.
26
+
27
+ ## Check it
28
+
29
+ ```bash
30
+ bikky status
31
+ ```
32
+
33
+ After changing Qdrant settings, restart long-running processes:
34
+
35
+ ```bash
36
+ bikky stop && bikky start
37
+ ```
38
+
39
+ Then restart your editor so its MCP process reloads.
@@ -0,0 +1,34 @@
1
+ # Local and free config
2
+
3
+ Use this path if you want a private, free setup: Qdrant runs on your machine, and Ollama handles local models.
4
+
5
+ This setup is best for private/free testing rather than long-term team use. Extraction, embedding, and curation performance depends on the local models and hardware you run.
6
+
7
+ ## What you need
8
+
9
+ - Qdrant running locally, usually with Docker.
10
+ - Ollama installed locally.
11
+ - The default embedding model pulled with `ollama pull qwen3-embedding:0.6b`.
12
+
13
+ ## Config
14
+
15
+ Save this as `~/.bikky/config.json`:
16
+
17
+ ```json
18
+ {
19
+ "qdrant_url": "http://localhost:6333",
20
+ "qdrant_api_key": ""
21
+ }
22
+ ```
23
+
24
+ That's the whole config. bikky uses local Ollama defaults for embeddings and background curation.
25
+
26
+ `qdrant_api_key` is optional. Leave it empty or omit it for local or unauthenticated self-hosted Qdrant.
27
+
28
+ ## Check it
29
+
30
+ ```bash
31
+ bikky status
32
+ ```
33
+
34
+ If you started from a fresh install, run `bikky setup` after writing the config, then restart your editor so its MCP process reloads.
@@ -0,0 +1,374 @@
1
+ # Configuration
2
+
3
+ bikky is designed to keep setup small. The example below keeps Qdrant local and uses hosted models; the focused guides list the other common setup shapes.
4
+
5
+ ```bash
6
+ mkdir -p ~/.bikky
7
+ cat > ~/.bikky/config.json <<'JSON'
8
+ {
9
+ "qdrant_url": "http://localhost:6333",
10
+ "qdrant_api_key": "",
11
+ "embedding": {
12
+ "provider": "openai",
13
+ "model": "text-embedding-3-small",
14
+ "dimensions": 1536,
15
+ "api_key": "sk-..."
16
+ },
17
+ "llm": {
18
+ "provider": "openai",
19
+ "model": "gpt-4.1-mini",
20
+ "api_key": "sk-..."
21
+ }
22
+ }
23
+ JSON
24
+ bikky status
25
+ ```
26
+
27
+ Config lives at `~/.bikky/config.json`, or at `BIKKY_HOME/config.json` when `BIKKY_HOME` is set. Environment variables override the config file.
28
+
29
+ ## Common setups
30
+
31
+ If you know which path you want, start with the focused guide:
32
+
33
+ | Setup | Best for | Guide |
34
+ | ----------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------ |
35
+ | Fully hosted | Best performance and teams; managed vector storage and models | [Fully hosted config](config/fully-hosted.md) |
36
+ | Local Qdrant + hosted models | Local vector storage with hosted extraction and embedding | [Hosted models config](config/hosted-models.md) |
37
+ | Local and free | Local evaluation; quality depends on local models | [Local config guide](config/local.md) |
38
+ | Hosted Qdrant + local models | Shared vector storage while keeping model calls local | [Hosted Qdrant + local models](config/hosted-qdrant-local-models.md) |
39
+
40
+ ### Fully hosted
41
+
42
+ Best for performance and teams. Qdrant Cloud stores vectors, and hosted embeddings + LLM calls handle extraction, curation, and recall.
43
+
44
+ ```json
45
+ {
46
+ "qdrant_url": "https://your-cluster.cloud.qdrant.io:6333",
47
+ "qdrant_api_key": "your-key",
48
+ "embedding": {
49
+ "provider": "openai",
50
+ "model": "text-embedding-3-small",
51
+ "dimensions": 1536,
52
+ "api_key": "sk-..."
53
+ },
54
+ "llm": {
55
+ "provider": "openai",
56
+ "model": "gpt-4.1-mini",
57
+ "api_key": "sk-..."
58
+ }
59
+ }
60
+ ```
61
+
62
+ `qdrant_api_key` is optional only for unauthenticated self-hosted Qdrant. Qdrant Cloud usually requires it.
63
+
64
+ ### Local Qdrant + hosted models
65
+
66
+ Best for local vector storage with hosted extraction and embedding quality.
67
+
68
+ ```json
69
+ {
70
+ "qdrant_url": "http://localhost:6333",
71
+ "qdrant_api_key": "",
72
+ "embedding": {
73
+ "provider": "openai",
74
+ "model": "text-embedding-3-small",
75
+ "dimensions": 1536,
76
+ "api_key": "sk-..."
77
+ },
78
+ "llm": {
79
+ "provider": "openai",
80
+ "model": "gpt-4.1-mini",
81
+ "api_key": "sk-..."
82
+ }
83
+ }
84
+ ```
85
+
86
+ `qdrant_api_key` is optional. Leave it empty or omit it for local or unauthenticated self-hosted Qdrant. Prefer env vars for hosted model auth? Omit `api_key` above and set `OPENAI_API_KEY` instead.
87
+
88
+ ### Local and free
89
+
90
+ Use this for local, free, account-free evaluation. Qdrant runs locally and Ollama provides the default embedding + LLM models.
91
+
92
+ This setup is usually not the best long-term choice for teams. Extraction, embedding, and curation performance depends on the local models and hardware you run.
93
+
94
+ ```json
95
+ {
96
+ "qdrant_url": "http://localhost:6333",
97
+ "qdrant_api_key": ""
98
+ }
99
+ ```
100
+
101
+ `qdrant_api_key` is optional. Leave it empty or omit it for local or unauthenticated self-hosted Qdrant.
102
+
103
+ ### Hosted Qdrant, local models
104
+
105
+ Use this when you want the memory database shared across machines, but still want embeddings and LLM calls to stay local.
106
+
107
+ ```json
108
+ {
109
+ "qdrant_url": "https://your-cluster.cloud.qdrant.io:6333",
110
+ "qdrant_api_key": "your-key"
111
+ }
112
+ ```
113
+
114
+ `qdrant_api_key` is optional only for unauthenticated self-hosted Qdrant. Qdrant Cloud usually requires it.
115
+
116
+ After changing Qdrant or provider settings, restart long-running processes:
117
+
118
+ ```bash
119
+ bikky stop && bikky start
120
+ ```
121
+
122
+ Then restart your editor so its MCP server process reloads the config.
123
+
124
+ ## Environment variables
125
+
126
+ Use env vars when you do not want to write credentials to the config file:
127
+
128
+ ```bash
129
+ export QDRANT_URL="http://localhost:6333"
130
+ export QDRANT_API_KEY="..." # only needed for Qdrant Cloud or authenticated self-hosted Qdrant
131
+ ```
132
+
133
+ Useful basics:
134
+
135
+ | Env var | Config field | Notes |
136
+ | ---------------- | ---------------- | --------------------------------------------------------------------------- |
137
+ | `QDRANT_URL` | `qdrant_url` | Required unless set in config |
138
+ | `QDRANT_API_KEY` | `qdrant_api_key` | Optional for local/unauthenticated Qdrant; usually needed for Qdrant Cloud |
139
+ | `BIKKY_HOME` | — | Moves the config/log/state directory from `~/.bikky` |
140
+
141
+ ## Provider options
142
+
143
+ Use these exact values in `embedding.provider` and `llm.provider`. Both fields accept the same provider values, and you can choose them independently.
144
+
145
+ | Provider value | Works for embeddings | Works for LLM | Best for | Auth |
146
+ | -------------- | -------------------- | ------------- | ------------------------------------ | --------------------------------- |
147
+ | `ollama` | Yes | Yes | Local and free defaults | None |
148
+ | `openai` | Yes | Yes | Simple hosted models | `OPENAI_API_KEY` or `api_key` |
149
+ | `bedrock` | Yes | Yes | AWS-managed models | AWS credentials or IAM role |
150
+ | `portkey` | Yes | Yes | Gateway/routing over other providers | Portkey API key |
151
+
152
+ ## Advanced configuration
153
+
154
+ These sections are optional references for custom providers, tuning, scoping, and daemon internals.
155
+
156
+ ### Full setting reference
157
+
158
+ #### Qdrant
159
+
160
+ | Setting | Env var | Default | Notes |
161
+ | ---------------- | ------------------ | ------- | ------------------------------ |
162
+ | `qdrant_url` | `QDRANT_URL` | none | Qdrant REST URL |
163
+ | `qdrant_api_key` | `QDRANT_API_KEY` | none | API key for authenticated Qdrant |
164
+ | `collection` | `BIKKY_COLLECTION` | `bikky` | Collection name |
165
+
166
+ `qdrant_api_key` is optional for local or unauthenticated self-hosted Qdrant. Qdrant Cloud usually requires it.
167
+
168
+ #### Embeddings
169
+
170
+ | Setting | Env var | Default | Notes |
171
+ | ---------------------- | ---------------------- | ------------------------ | ----------------------------------------------- |
172
+ | `embedding.provider` | `EMBEDDING_PROVIDER` | `ollama` | One of `ollama`, `openai`, `bedrock`, `portkey` |
173
+ | `embedding.model` | `EMBEDDING_MODEL` | `qwen3-embedding:0.6b` | Embedding model name |
174
+ | `embedding.dimensions` | `EMBEDDING_DIMENSIONS` | `1024` | Must match the selected model output |
175
+ | `embedding.base_url` | `EMBEDDING_BASE_URL` | `http://localhost:11434` | Used by local or OpenAI-compatible providers |
176
+ | `embedding.api_key` | `OPENAI_API_KEY` | — | Provider API key; can also be set in config |
177
+
178
+ Common model dimensions:
179
+
180
+ | Provider | Model | Dimensions |
181
+ | --------- | -------------------------------- | ---------- |
182
+ | `ollama` | `qwen3-embedding:0.6b` | `1024` |
183
+ | `ollama` | `nomic-embed-text` | `768` |
184
+ | `openai` | `text-embedding-3-small` | `1536` |
185
+ | `openai` | `text-embedding-3-large` | `3072` |
186
+ | `bedrock` | `amazon.titan-embed-text-v2:0` | `1024` |
187
+
188
+ If you change the embedding model, make sure `embedding.dimensions` matches the model output.
189
+
190
+ #### LLM
191
+
192
+ The LLM is used by background maintenance features. Ollama is the default.
193
+
194
+ | Setting | Env var | Default | Notes |
195
+ | ------------------ | ------------------------------------ | ------------------------ | -------------------------------------------- |
196
+ | `llm.provider` | `LLM_PROVIDER` | `ollama` | One of `ollama`, `openai`, `bedrock`, `portkey` |
197
+ | `llm.model` | `LLM_MODEL` | `qwen2.5:7b` | LLM model name |
198
+ | `llm.base_url` | `LLM_BASE_URL` | `http://localhost:11434` | Used by local or OpenAI-compatible providers |
199
+ | `llm.api_key` | `OPENAI_API_KEY` | — | Provider API key; can also be set in config |
200
+ | `llm.extra.region` | `AWS_BEDROCK_REGION` / `AWS_REGION` | `us-east-1` | AWS Bedrock region |
201
+
202
+ #### Timeouts and retries
203
+
204
+ | Setting | Env var | Default |
205
+ | ------------------------------- | ---------------------------------------- | ------- |
206
+ | `embedding.timeout_ms` | `BIKKY_EMBEDDING_TIMEOUT_MS` | `30000` |
207
+ | `embedding.retries` | `BIKKY_EMBEDDING_RETRIES` | `2` |
208
+ | `embedding.retry_base_delay_ms` | `BIKKY_EMBEDDING_RETRY_BASE_DELAY_MS` | `250` |
209
+ | `llm.timeout_ms` | `BIKKY_LLM_TIMEOUT_MS` | `30000` |
210
+ | `llm.retries` | `BIKKY_LLM_RETRIES` | `2` |
211
+ | `llm.retry_base_delay_ms` | `BIKKY_LLM_RETRY_BASE_DELAY_MS` | `250` |
212
+
213
+ Retries use jittered exponential backoff for transient errors, rate limits, and timeouts. Authentication and bad-request errors fail fast.
214
+
215
+ ### Portkey and Bedrock examples
216
+
217
+ #### Portkey gateway
218
+
219
+ ```json
220
+ {
221
+ "qdrant_url": "https://your-cluster.cloud.qdrant.io:6333",
222
+ "qdrant_api_key": "your-key",
223
+ "embedding": {
224
+ "provider": "portkey",
225
+ "model": "@openai/text-embedding-3-small",
226
+ "dimensions": 1536,
227
+ "api_key": "pk-..."
228
+ },
229
+ "llm": {
230
+ "provider": "portkey",
231
+ "model": "@openai/gpt-4o-mini",
232
+ "api_key": "pk-...",
233
+ "extra": { "virtual_key": "openai-prod" }
234
+ }
235
+ }
236
+ ```
237
+
238
+ #### AWS Bedrock
239
+
240
+ ```json
241
+ {
242
+ "qdrant_url": "https://your-cluster.cloud.qdrant.io:6333",
243
+ "qdrant_api_key": "your-key",
244
+ "embedding": {
245
+ "provider": "bedrock",
246
+ "model": "amazon.titan-embed-text-v2:0",
247
+ "dimensions": 1024
248
+ },
249
+ "llm": {
250
+ "provider": "bedrock",
251
+ "model": "us.anthropic.claude-sonnet-4-20250514",
252
+ "extra": { "region": "us-east-1" }
253
+ }
254
+ }
255
+ ```
256
+
257
+ Bedrock reads `embedding.extra.region` and `llm.extra.region`. `AWS_BEDROCK_REGION` populates both, falling back to `AWS_REGION`; `aws_profile` or `AWS_PROFILE` selects the shared AWS profile when you are not using direct env credentials.
258
+
259
+ ### Multi-destination routing
260
+
261
+ Most users only need one Qdrant destination. Use `destinations[]` when you want one bikky install and one editor MCP connection to read or write separate memory stores for different teams, clients, or environments.
262
+
263
+ Each destination has its own Qdrant credentials and collection. A destination can also include a `match` block with JavaScript `RegExp` strings for `cwd`, `entity`, `content`, or `metadata`. Destinations are evaluated in array order; the first destination with any matching pattern wins. If no pattern matches, bikky uses the destination marked `default: true`, or the first destination.
264
+
265
+ ```jsonc
266
+ {
267
+ "embedding": {
268
+ "provider": "openai",
269
+ "model": "text-embedding-3-small",
270
+ "dimensions": 1536
271
+ },
272
+ "llm": {
273
+ "provider": "openai",
274
+ "model": "gpt-4.1-mini"
275
+ },
276
+ "destinations": [
277
+ {
278
+ "name": "client-a",
279
+ "qdrant_url": "https://client-a.cloud.qdrant.io:6333",
280
+ "qdrant_api_key": "...",
281
+ "collection": "bikky-client-a",
282
+ "match": {
283
+ "cwd": ["^/Users/me/code/client-a"],
284
+ "entity": ["^client-a-"],
285
+ "content": ["client-a", "CLIENTA-\\d+"],
286
+ "metadata": { "project": ["^client-a$"] }
287
+ }
288
+ },
289
+ {
290
+ "name": "research-cloud",
291
+ "qdrant_url": "https://research.cloud.qdrant.io:6333",
292
+ "qdrant_api_key": "...",
293
+ "collection": "bikky-research",
294
+ "match": {
295
+ "content": ["[Rr]esearch[- ][Ll]ab"]
296
+ }
297
+ },
298
+ {
299
+ "name": "platform",
300
+ "qdrant_url": "http://localhost:6333",
301
+ "qdrant_api_key": "",
302
+ "collection": "bikky-platform",
303
+ "default": true
304
+ }
305
+ ]
306
+ }
307
+ ```
308
+
309
+ Matching details:
310
+
311
+ - `match.cwd`, `match.entity`, and `match.content` are lists of JavaScript `RegExp` strings.
312
+ - `match.metadata` maps metadata keys to lists of JavaScript `RegExp` strings matched against that key's value.
313
+ - Matching uses OR logic across fields and within each list; any matching pattern selects the destination.
314
+ - Put the most specific destinations first because first match wins.
315
+ - JavaScript regex flags are not supported in config strings. Use character classes like `[Bb]ikky` for case-insensitive matching.
316
+ - Tool calls can override routing with an explicit destination name, for example `memory_store({ ..., destination: "client-a" })`.
317
+ - All destinations share one embedding provider, so every destination collection must use the same vector dimensions.
318
+
319
+ Migrating from `workspace_id` pre-v0.4:
320
+
321
+ - Existing top-level `qdrant_url`, `qdrant_api_key`, and `collection` configs still work as a single synthesized destination.
322
+ - The `workspace_id` argument on memory tools is a no-op for compatibility.
323
+ - Replace `default_workspace` scoping with named destinations when you need isolation.
324
+
325
+ ### Daemon, watchers, and logs
326
+
327
+ You normally do not need to tune these. `bikky setup` starts the daemon and registers supported MCP clients.
328
+
329
+ #### Daemon settings
330
+
331
+ | Setting | Default | Description |
332
+ | ------------------------------------ | ------- | ------------------------------------------------ |
333
+ | `daemon.tick_interval_sec` | `5` | Seconds between daemon loop ticks |
334
+ | `daemon.extract_every_sec` | `300` | Seconds between extraction runs |
335
+ | `daemon.extract_min_events` | `10` | Minimum events before extraction |
336
+ | `daemon.consolidation_enabled` | `true` | Consolidate summaries into durable patterns |
337
+ | `daemon.relation_inference_enabled` | `true` | Infer entity relationships |
338
+ | `daemon.entity_typing_enabled` | `true` | Classify entities for UI/graph filtering |
339
+ | `daemon.staleness_threshold_days` | `30` | Days before a fact is flagged as stale |
340
+
341
+ #### Watcher settings
342
+
343
+ | Setting | Default | Description |
344
+ | -------------------------- | -------------------------- | --------------------------------- |
345
+ | `watchers.copilot.enabled` | `true` | Watch GitHub Copilot session logs |
346
+ | `watchers.copilot.path` | `~/.copilot/session-state` | Path to Copilot session directory |
347
+ | `watchers.claude.enabled` | `true` | Watch Claude Code project logs |
348
+ | `watchers.claude.path` | `~/.claude/projects` | Path to Claude Code projects |
349
+
350
+ #### Logs
351
+
352
+ bikky writes logs to `~/.bikky/logs/`:
353
+
354
+ | File | Written by |
355
+ | ------------ | ----------------- |
356
+ | `mcp.log` | MCP server |
357
+ | `daemon.log` | Background daemon |
358
+ | `llm.jsonl` | LLM telemetry |
359
+
360
+ Pretty-print logs with:
361
+
362
+ ```bash
363
+ tail -f ~/.bikky/logs/daemon.log | npx pino-pretty
364
+ ```
365
+
366
+ ## Troubleshooting
367
+
368
+ Run:
369
+
370
+ ```bash
371
+ bikky status
372
+ ```
373
+
374
+ `bikky status` is read-only. It checks the config, Qdrant connection, collection readiness, embedding connectivity, daemon state, and local UI health. If something is missing or misconfigured, it exits non-zero and prints the next fix to make.
Binary file
Binary file
Binary file