@ponraaj/dimple-sdk 0.0.0-alpha.4 → 0.0.0-alpha.5
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 +198 -5
- package/dist/dimple.d.ts +101 -3
- package/dist/errors.d.ts +23 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +948 -210
- package/dist/indexer.d.ts +9 -0
- package/dist/internal/config/schema.d.ts +18 -0
- package/dist/internal/embedder/auto-install.d.ts +35 -0
- package/dist/internal/embedder/transformers.d.ts +10 -1
- package/dist/internal/extractor/models/extraction.d.ts +14 -0
- package/dist/internal/logger/index.d.ts +1 -1
- package/dist/internal/logger/service.d.ts +15 -7
- package/dist/internal/store/db-backend.d.ts +14 -2
- package/dist/internal/store/graph/candidates.d.ts +3 -1
- package/dist/internal/store/models.d.ts +4 -3
- package/dist/internal/store/schema/graph.d.ts +7 -7
- package/dist/internal/store/schema/libsql.d.ts +4 -4
- package/dist/internal/store/schema/metadata.d.ts +4 -1
- package/dist/internal/store/service.d.ts +45 -1
- package/dist/make.d.ts +21 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -12,6 +12,25 @@ thin facade over it.
|
|
|
12
12
|
|
|
13
13
|
> **Status**: alpha (`0.0.0-alpha.n`). The API is stabilizing but may change.
|
|
14
14
|
|
|
15
|
+
### The one-liner
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { makeDimple } from "@ponraaj/dimple-sdk"; // ← makeDimple, not dimple
|
|
19
|
+
|
|
20
|
+
const dimple = await makeDimple({ config: "./dimple.jsonc" });
|
|
21
|
+
const hits = await dimple.query("what did we decide about X", {
|
|
22
|
+
limit: 5,
|
|
23
|
+
contentType: "text/plain", // ← code-vs-message separation
|
|
24
|
+
}); // query(text, options) — text is the FIRST positional argument
|
|
25
|
+
await dimple.dispose();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Calling conventions: every method takes **plain arguments** (`query(text,
|
|
29
|
+
opts)`, `write(input, opts)`, `index({ paths })`), every failure is a
|
|
30
|
+
rejected promise with a closed `_tag` (`"Sdk.NotFound"`, `"Sdk.InputError"`,
|
|
31
|
+
…), and `dispose()` is **required** before `process.exit(0)` — the durable
|
|
32
|
+
worker keeps the event loop alive (`dispose()` stops it; it is idempotent).
|
|
33
|
+
|
|
15
34
|
## Install
|
|
16
35
|
|
|
17
36
|
```bash
|
|
@@ -38,7 +57,9 @@ const mem = await dimple.write({
|
|
|
38
57
|
});
|
|
39
58
|
|
|
40
59
|
// hybrid semantic + FTS search
|
|
41
|
-
const results = await dimple.query("how does the pipeline deploy", {
|
|
60
|
+
const results = await dimple.query("how does the pipeline deploy", {
|
|
61
|
+
limit: 3,
|
|
62
|
+
});
|
|
42
63
|
|
|
43
64
|
// index real code — files + extracted functions/classes/methods become memories
|
|
44
65
|
const indexed = await dimple.index({ paths: ["./src"] });
|
|
@@ -116,6 +137,53 @@ const dimple = await makeDimple({
|
|
|
116
137
|
| `defaultK` / `defaultLimit` | numbers | retrieval defaults |
|
|
117
138
|
| `defaultTtlSecs` | number | write TTL default |
|
|
118
139
|
|
|
140
|
+
### Remote databases (Turso)
|
|
141
|
+
|
|
142
|
+
`storeUrl` and `jobs.dbUrl` accept **remote libSQL URLs** (`libsql://`,
|
|
143
|
+
`https://`, `ws://` — Turso or any libsql-compatible host). The same
|
|
144
|
+
engine runs everything the local file does — FTS5, vector search, the
|
|
145
|
+
topic tree, durable jobs — over the wire. Verified end-to-end against
|
|
146
|
+
the real Turso service (`tests/store/turso-remote.test.ts`).
|
|
147
|
+
|
|
148
|
+
Turso tokens are **per-database**, so each URL carries its own token.
|
|
149
|
+
`dimple.jsonc` resolves `${ENV_VAR}` in values, so tokens stay out of
|
|
150
|
+
config files:
|
|
151
|
+
|
|
152
|
+
```jsonc
|
|
153
|
+
{
|
|
154
|
+
"storeUrl": "libsql://<org>-<memdb>.turso.io?authToken=${TURSO_MEMORIES_TOKEN}",
|
|
155
|
+
"jobs": {
|
|
156
|
+
"dbUrl": "libsql://<org>-<jobsdb>.turso.io?authToken=${TURSO_JOBS_TOKEN}",
|
|
157
|
+
},
|
|
158
|
+
"embedding": {
|
|
159
|
+
/* hosted providers for serverless — local models are
|
|
160
|
+
local-only (auto-install needs Node) */
|
|
161
|
+
},
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Notes:
|
|
166
|
+
|
|
167
|
+
- The **jobs DB must also be remote** when the store is remote (the
|
|
168
|
+
durable queue + workflow state are cross-invocation)
|
|
169
|
+
- `file:`-only behaviors (parent-dir creation, migration lock) skip
|
|
170
|
+
for remote URLs
|
|
171
|
+
- A single-DB setup can share one URL + one token (`TURSO_TOKEN`)
|
|
172
|
+
- For Cloudflare Workers the client swaps to the pure-JS entry
|
|
173
|
+
(`@libsql/client/web` — one bundler alias, no source changes)
|
|
174
|
+
|
|
175
|
+
### Embedding models
|
|
176
|
+
|
|
177
|
+
Local embeddings (`provider: "transformers"`) auto-install on first
|
|
178
|
+
use — `@huggingface/transformers` is an **optional peer** so hosted-only
|
|
179
|
+
consumers never pull its tree (the `sharp` + `onnxruntime-node`
|
|
180
|
+
postinstall scripts that abort npm 11 installs). The first `embed()`
|
|
181
|
+
installs it with the project's own package manager, scripts skipped
|
|
182
|
+
(proven unnecessary for embedding), and retries in-process. Offline or
|
|
183
|
+
restricted environments get a typed `Sdk.Embedding` error with the manual
|
|
184
|
+
command. Set `autoInstall: false` on the model to disable:
|
|
185
|
+
`embedding.models[].autoInstall: false`
|
|
186
|
+
|
|
119
187
|
### Embedding models
|
|
120
188
|
|
|
121
189
|
Two providers — **local** (Transformers.js ONNX, runs on your CPU, no
|
|
@@ -223,6 +291,11 @@ active `logicalKey` → `Sdk.DuplicateKey` (carries `logicalKey`/`namespace`).
|
|
|
223
291
|
**Memory expiry**: `ttlSecs` (or the config `defaultTtlSecs`) schedules
|
|
224
292
|
expiry; a sweep job retires expired memories in the background.
|
|
225
293
|
|
|
294
|
+
`query(text, { budget: { maxUnits, maxChars, maxMs } })` — LLM-facing
|
|
295
|
+
context guardrail: caps the row count, truncates result content to the
|
|
296
|
+
total char budget, and marks `results.truncated` when the soft time cap
|
|
297
|
+
is exceeded.
|
|
298
|
+
|
|
226
299
|
### `get(id)` / `forget(id)`
|
|
227
300
|
|
|
228
301
|
Fetch one memory; soft-delete (cascades edges, rebalances the tree).
|
|
@@ -260,7 +333,7 @@ await dimple.index({
|
|
|
260
333
|
maxChunkBytes?: 8 * 1024,
|
|
261
334
|
extensions?: [".ts", ".tsx", ".js", ".jsx", …],
|
|
262
335
|
});
|
|
263
|
-
// → { files, indexed,
|
|
336
|
+
// → { files, indexed, updated, reconciled, skipped, commit, unsupported, failed }
|
|
264
337
|
```
|
|
265
338
|
|
|
266
339
|
- Tree-sitter parse (TypeScript/JavaScript/TSX/JSX) → the extractor
|
|
@@ -271,8 +344,27 @@ await dimple.index({
|
|
|
271
344
|
- AST-derived graph: relative imports resolve to indexed files and
|
|
272
345
|
class→method containment become **confirmed `memory_supports` edges**
|
|
273
346
|
(`source: "rule"`)
|
|
274
|
-
- **Idempotent**: keys are cwd-anchored + deterministic
|
|
275
|
-
|
|
347
|
+
- **Idempotent + upserting**: keys are cwd-anchored + deterministic
|
|
348
|
+
(chunk keys drop the line number, so edits ABOVE a definition update
|
|
349
|
+
it instead of duplicating it). Re-indexing skips unchanged units
|
|
350
|
+
(`skipped`), and changed units are **superseded + rewritten under the
|
|
351
|
+
same key** (`updated`) with a confirmed identity `memory_supersedes`
|
|
352
|
+
edge — stale copies never accumulate
|
|
353
|
+
- **Edges re-form after `forget`**: phase-2 resolves endpoints by logical
|
|
354
|
+
key against the store (not just the current run), so a re-created unit
|
|
355
|
+
re-connects to its pre-existing dependencies
|
|
356
|
+
- **Reconcile + rename detection**: units whose source vanished (deleted
|
|
357
|
+
file/definition) are demoted (`reconciled`, `source_removed` — gone
|
|
358
|
+
from search; domain-scoped to the walked roots, so `index lib` never
|
|
359
|
+
touches other files). A vanished unit whose embedding is a near-duplicate
|
|
360
|
+
of a new unit becomes a PENDING `memory_supersedes` (reason rename) —
|
|
361
|
+
`graph confirm` completes it. Code units are TTL-exempt
|
|
362
|
+
(`ttlSecs: null` — the index owns their lifecycle); `commit` stamps the
|
|
363
|
+
repo HEAD into every unit's metadata as `codeVersion`
|
|
364
|
+
- **`code_calls` edges**: every call site inside a definition resolves to
|
|
365
|
+
the callee's chunk (same file, then imported files) → confirmed edges —
|
|
366
|
+
`explain(id, { edgeKinds: ["code_calls"] })` gives one-hop impact
|
|
367
|
+
analysis
|
|
276
368
|
- Per-file failures are collected, never fatal
|
|
277
369
|
|
|
278
370
|
### `updateEmbedding(id, embedding, modelKey?)` / `embed(text)`
|
|
@@ -288,13 +380,19 @@ requires the `llm` config section) or the graph repair pass. Each call
|
|
|
288
380
|
gets a fresh run id (always executes). Failures are typed:
|
|
289
381
|
`Sdk.LLMNotConfigured`, `Sdk.JobFailed`.
|
|
290
382
|
|
|
291
|
-
### `explain({ kind: "memory" | "topic" | "concept", id })`
|
|
383
|
+
### `explain({ kind: "memory" | "topic" | "concept", id }, options?)`
|
|
292
384
|
|
|
293
385
|
Graph neighborhood traversal — `{ nodes: [{ kind, id, depth, edgeKind }] }`.
|
|
386
|
+
`options.edgeKinds` scopes the answer (memory-only navigation: pass the
|
|
387
|
+
`memory_*` kinds; `code_calls` shows the call graph).
|
|
294
388
|
|
|
295
389
|
### `health(modelKey)` / `graph.*`
|
|
296
390
|
|
|
297
391
|
- `health` — topic-tree invariant sweep (`warnCount` + violation strings)
|
|
392
|
+
- `graph.confirm(id)` / `graph.reject(id)` / `graph.expire(id)` — the
|
|
393
|
+
pending-edge lifecycle: promote to confirmed (a `memory_supersedes`
|
|
394
|
+
confirm demotes the old endpoint in the same transaction), reject, or
|
|
395
|
+
soft-delete. `Sdk.EdgeNotFound` for stale ids
|
|
298
396
|
- `graph.addEdge({ fromMemoryId, toMemoryId, edgeKind: "memory_supports" |
|
|
299
397
|
"memory_supersedes" | "memory_contradicts", source: "rule" | "llm" |
|
|
300
398
|
"agent", weight?, confidence?, confirmed? })` — explicit edges; typed
|
|
@@ -302,6 +400,42 @@ Graph neighborhood traversal — `{ nodes: [{ kind, id, depth, edgeKind }] }`.
|
|
|
302
400
|
- `graph.candidates()` — pending structural candidates + isolated count
|
|
303
401
|
- `graph.coverage(modelKey)` — coverage %, pending, concept count
|
|
304
402
|
|
|
403
|
+
### `reload(input?)` — apply a config change
|
|
404
|
+
|
|
405
|
+
Pauses and re-boots with the re-resolved config:
|
|
406
|
+
|
|
407
|
+
1. the config source is re-resolved **typed** — a `dimple.jsonc` path is
|
|
408
|
+
re-read from disk, an inline object re-validated (a bad config rejects
|
|
409
|
+
the reload with **zero impact** — nothing pauses);
|
|
410
|
+
2. an **identical** config resolves as `{ reloaded: false }` — no pause,
|
|
411
|
+
no restart (safe to call from a file watcher);
|
|
412
|
+
3. new calls wait, in-flight calls settle on the old stack;
|
|
413
|
+
4. a fresh stack boots (new worker fleet, embedders, logger — jobs are
|
|
414
|
+
durable, so an interrupted handler's lease expires and re-claims after
|
|
415
|
+
boot);
|
|
416
|
+
5. the swap: the old stack is disposed, the new one serves.
|
|
417
|
+
|
|
418
|
+
Resolves with `{ config, changed, reloaded }` — `changed` flags which
|
|
419
|
+
sections actually moved (`storeUrl` / `jobsUrl` / `rest`).
|
|
420
|
+
|
|
421
|
+
Works for `{ config: … }`-built dimples (reload with no argument re-reads
|
|
422
|
+
the original source). `{ core: … }`-built dimples have no config source
|
|
423
|
+
and reject with `Sdk.Reload`. Boot failure leaves the previous system
|
|
424
|
+
running (blue-green); a drain that cannot settle in-flight calls (30s)
|
|
425
|
+
rejects with `Sdk.Reload` and nothing is torn down.
|
|
426
|
+
|
|
427
|
+
**What happens to data when the database URL changes:** the old database
|
|
428
|
+
file is preserved on disk but no longer served — nothing is migrated or
|
|
429
|
+
merged, the new db is bootstrapped empty (a warning is logged for the
|
|
430
|
+
switch; roll back with `reload(oldConfig)`). Pending jobs in a switched
|
|
431
|
+
`jobs.dbUrl` stay durable in the old db, re-claimable by switching back
|
|
432
|
+
or draining it externally.
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
await dimple.reload(); // re-read dimple.jsonc
|
|
436
|
+
await dimple.reload({ storeUrl: "file:…", … }); // or a fresh config
|
|
437
|
+
```
|
|
438
|
+
|
|
305
439
|
### `dispose()`
|
|
306
440
|
|
|
307
441
|
Stops the worker, closes sinks + the store. Idempotent; post-dispose calls
|
|
@@ -355,6 +489,65 @@ query history, persisted asynchronously (never blocks the query).
|
|
|
355
489
|
Every release creates a GitHub Release with the per-version changes (the
|
|
356
490
|
tag-based publish workflow): repo → **Releases** page.
|
|
357
491
|
|
|
492
|
+
## Agent integration patterns
|
|
493
|
+
|
|
494
|
+
These are the shapes that work well when the consumer is another agent
|
|
495
|
+
(a harness) rather than a human with a REPL.
|
|
496
|
+
|
|
497
|
+
### Session-start injection
|
|
498
|
+
|
|
499
|
+
The guaranteed-usage path: a warmup query returns a compact memory block
|
|
500
|
+
the harness injects as context, and the pending-graph review list rides
|
|
501
|
+
along:
|
|
502
|
+
|
|
503
|
+
```ts
|
|
504
|
+
const [context, pending] = await Promise.all([
|
|
505
|
+
dimple.query("ongoing work and decisions", { limit: 8, budget: { maxChars: 4000 } }),
|
|
506
|
+
dimple.graph.candidates(),
|
|
507
|
+
]);
|
|
508
|
+
// context → inject the top-N content strings into the system prompt
|
|
509
|
+
// pending → offer each candidate as a confirm/reject decision
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
`graph.candidates()` pending `memory_supersedes` edges from the rename
|
|
513
|
+
scanner (rule 0.9x near-duplicates) are the highest-value batch to review.
|
|
514
|
+
|
|
515
|
+
### Supersedes recipe
|
|
516
|
+
|
|
517
|
+
`addEdge({ … edgeKind: "memory_supersedes", confirmed: true })` performs
|
|
518
|
+
the full state flip in one transaction (the old memory demotes
|
|
519
|
+
immediately) — it is safe to use directly. For human-gated flows the
|
|
520
|
+
pending → confirm pair keeps the old memory ranking until a reviewer
|
|
521
|
+
agrees:
|
|
522
|
+
|
|
523
|
+
```ts
|
|
524
|
+
const edge = await dimple.graph.addEdge({
|
|
525
|
+
fromMemoryId: oldId,
|
|
526
|
+
toMemoryId: newId,
|
|
527
|
+
edgeKind: "memory_supersedes",
|
|
528
|
+
source: "agent",
|
|
529
|
+
}); // pending — nothing changed yet
|
|
530
|
+
await dimple.graph.confirm(edge.id); // ← the flip happens here
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### Namespaces as the code/message partition
|
|
534
|
+
|
|
535
|
+
Until a query-time content-type filter exists, namespaces give clean
|
|
536
|
+
isolation: `index({ paths, namespace: "code" })` and
|
|
537
|
+
`write({ …, namespace: "messages" })` partition the store; query with
|
|
538
|
+
`namespace: "code"` for code and `namespace: "messages"` for
|
|
539
|
+
conversations. (`query({ contentType })` now does the same within one
|
|
540
|
+
namespace — the two levers compose.)
|
|
541
|
+
|
|
542
|
+
### Remember
|
|
543
|
+
|
|
544
|
+
- `dimple.reload(newConfig)` swaps the whole stack blue-green (validate →
|
|
545
|
+
pause → boot → drain → swap); a failed boot leaves the old stack
|
|
546
|
+
serving.
|
|
547
|
+
- JSON output is compact by default: CLI `--json` omits embeddings (pass
|
|
548
|
+
`--embedding` to include them); the SDK always keeps them on
|
|
549
|
+
`memory.embedding`.
|
|
550
|
+
|
|
358
551
|
## Notes
|
|
359
552
|
|
|
360
553
|
- Determinism: same data + same config ⇒ same tree, same clusters, same
|
package/dist/dimple.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Effect } from "effect";
|
|
2
2
|
import type { QueryProfile } from "./internal/retriever/index.js";
|
|
3
3
|
import type { CoreInterface } from "./internal/core/index.js";
|
|
4
4
|
import type { CodeExtractor } from "./internal/extractor/index.js";
|
|
5
5
|
import type { CodeParser } from "./internal/parser/index.js";
|
|
6
|
+
import type { DimpleConfig } from "./internal/config/index.js";
|
|
6
7
|
import type { AddEdgeInput, AugmentedMemory, ExplainResult, GraphCandidatesResult, GraphCoverage, MemoryUnit, TopicHealth, WriteMemoryInput } from "./internal/store/index.js";
|
|
8
|
+
import type { ConfigInput } from "./config.ts";
|
|
7
9
|
import { type DimpleError } from "./errors.ts";
|
|
8
10
|
/** Options for a `query` call — mirrors the hybrid retriever's options. */
|
|
9
11
|
export interface QueryOptions {
|
|
@@ -16,6 +18,19 @@ export interface QueryOptions {
|
|
|
16
18
|
readonly topics?: {
|
|
17
19
|
readonly topicKeys?: ReadonlyArray<string>;
|
|
18
20
|
};
|
|
21
|
+
/** Content-type filter: one kind or a list (e.g. `"text/x-typescript"`
|
|
22
|
+
* or `["text/plain", "text/markdown"]`) — the code-vs-message
|
|
23
|
+
* separation lever at query time. */
|
|
24
|
+
readonly contentType?: string | readonly string[];
|
|
25
|
+
/** Retrieval context budget (LLM-facing guardrail): `maxUnits` caps the
|
|
26
|
+
* row count, `maxChars` truncates result content to fit the total char
|
|
27
|
+
* budget, `maxMs` marks the result truncated when the query exceeds it.
|
|
28
|
+
* Truncation is surfaced as `results.truncated` on the returned array. */
|
|
29
|
+
readonly budget?: {
|
|
30
|
+
readonly maxUnits?: number;
|
|
31
|
+
readonly maxChars?: number;
|
|
32
|
+
readonly maxMs?: number;
|
|
33
|
+
};
|
|
19
34
|
}
|
|
20
35
|
/** Options for a `write` call. */
|
|
21
36
|
export interface WriteOptions {
|
|
@@ -49,22 +64,58 @@ export interface IndexResult {
|
|
|
49
64
|
readonly files: number;
|
|
50
65
|
/** Memory units written (file unit + extracted chunks). */
|
|
51
66
|
readonly indexed: number;
|
|
52
|
-
/** Units
|
|
67
|
+
/** Units whose active copy changed content — the old unit was
|
|
68
|
+
* superseded (confirmed `memory_supersedes` edge) and the new unit
|
|
69
|
+
* written under the same key. */
|
|
70
|
+
readonly updated: number;
|
|
71
|
+
/** Units whose source vanished from disk (deleted/moved file or
|
|
72
|
+
* definition) — demoted to superseded (`source_removed`); they no
|
|
73
|
+
* longer match queries. */
|
|
74
|
+
readonly reconciled: number;
|
|
75
|
+
/** The repo HEAD at index time (null outside a git tree) — stamped into
|
|
76
|
+
* every file/chunk unit's metadata as `codeVersion`. */
|
|
77
|
+
/** Units skipped as already-indexed (unchanged content under the same
|
|
78
|
+
* logical key). */
|
|
53
79
|
readonly skipped: number;
|
|
54
80
|
/** Files skipped because the extension is not indexable. */
|
|
55
81
|
readonly unsupported: number;
|
|
82
|
+
readonly commit: string | null;
|
|
56
83
|
/** Files that could not be walked/read/parsed/extracted/written. */
|
|
57
84
|
readonly failed: readonly {
|
|
58
85
|
readonly filePath: string;
|
|
59
86
|
readonly message: string;
|
|
60
87
|
}[];
|
|
61
88
|
}
|
|
89
|
+
/** What a `reload` actually changed — so callers can react (alert, log,
|
|
90
|
+
* refuse) instead of guessing. */
|
|
91
|
+
export interface ReloadChanges {
|
|
92
|
+
/** The store database URL changed — the new db was bootstrapped (empty
|
|
93
|
+
* schema); the old db file is preserved on disk but no longer served.
|
|
94
|
+
* Nothing is migrated or merged. */
|
|
95
|
+
readonly storeUrl: boolean;
|
|
96
|
+
/** The jobs database URL changed — pending jobs stay durable in the
|
|
97
|
+
* old db (re-claimable by switching back or draining it externally). */
|
|
98
|
+
readonly jobsUrl: boolean;
|
|
99
|
+
/** Any other section changed (models, topics, graph, logging, …). */
|
|
100
|
+
readonly rest: boolean;
|
|
101
|
+
}
|
|
102
|
+
/** Result of a `reload`. */
|
|
103
|
+
export interface ReloadResult {
|
|
104
|
+
readonly config: DimpleConfig;
|
|
105
|
+
readonly changed: ReloadChanges;
|
|
106
|
+
/** `false` when the resolved config was identical to the live one —
|
|
107
|
+
* nothing was paused, booted, or restarted (safe for watchers). */
|
|
108
|
+
readonly reloaded: boolean;
|
|
109
|
+
}
|
|
62
110
|
/**
|
|
63
111
|
* The promise-based SDK facade — the ONLY surface app code touches.
|
|
64
112
|
* Every method runs the underlying Effect at the boundary, remaps errors
|
|
65
113
|
* onto the closed `DimpleError` hierarchy, and never leaks Effect types.
|
|
66
114
|
*/
|
|
67
115
|
export interface Dimple {
|
|
116
|
+
/** The config-default embedding model's key — what `dream`/`repair`/
|
|
117
|
+
* `stats` use when no model is passed. */
|
|
118
|
+
readonly defaultModelId: string;
|
|
68
119
|
readonly write: (input: WriteMemoryInput, options?: WriteOptions) => Promise<MemoryUnit>;
|
|
69
120
|
readonly get: (id: string) => Promise<MemoryUnit>;
|
|
70
121
|
readonly query: (text: string, options?: QueryOptions) => Promise<AugmentedMemory[]>;
|
|
@@ -83,19 +134,66 @@ export interface Dimple {
|
|
|
83
134
|
readonly embed: (text: string) => Promise<number[]>;
|
|
84
135
|
readonly dream: (modelKey: string) => Promise<void>;
|
|
85
136
|
readonly repair: (modelKey: string) => Promise<void>;
|
|
137
|
+
/** The store's tables + columns (snake_case DB names — the SDK exposes
|
|
138
|
+
* camelCase domain names; `dimple db-schema` prints this map). */
|
|
139
|
+
readonly dbSchema: () => Promise<ReadonlyArray<{
|
|
140
|
+
readonly table: string;
|
|
141
|
+
readonly columns: ReadonlyArray<{
|
|
142
|
+
readonly name: string;
|
|
143
|
+
readonly type: string;
|
|
144
|
+
}>;
|
|
145
|
+
}>>;
|
|
146
|
+
/** Options for `explain` — pass `edgeKinds` for a scoped answer (the
|
|
147
|
+
* common ask is memory-only navigation: the three `memory_*` kinds keep
|
|
148
|
+
* the topic/concept legs out). */
|
|
86
149
|
readonly explain: (input: {
|
|
87
150
|
readonly kind: "memory" | "topic" | "concept";
|
|
88
151
|
readonly id: string;
|
|
152
|
+
}, options?: {
|
|
153
|
+
readonly edgeKinds?: readonly string[];
|
|
154
|
+
readonly maxDepth?: number;
|
|
155
|
+
readonly maxNeighbors?: number;
|
|
156
|
+
readonly maxTotal?: number;
|
|
157
|
+
readonly includePending?: boolean;
|
|
89
158
|
}) => Promise<ExplainResult>;
|
|
90
159
|
readonly health: (modelKey: string) => Promise<TopicHealth>;
|
|
91
160
|
readonly graph: {
|
|
92
161
|
readonly addEdge: (input: AddEdgeInput) => Promise<unknown>;
|
|
93
162
|
readonly candidates: () => Promise<GraphCandidatesResult>;
|
|
94
163
|
readonly coverage: (modelKey: string) => Promise<GraphCoverage>;
|
|
164
|
+
/** Promote a pending edge to confirmed (for `memory_supersedes` the
|
|
165
|
+
* old endpoint flips to superseded in the same transaction). */
|
|
166
|
+
readonly confirm: (id: string) => Promise<void>;
|
|
167
|
+
/** Reject a pending edge (removed from the pending review set). */
|
|
168
|
+
readonly reject: (id: string) => Promise<void>;
|
|
169
|
+
/** Soft-delete an edge (`expired_at` set; excluded from traversal). */
|
|
170
|
+
readonly expire: (id: string) => Promise<void>;
|
|
95
171
|
};
|
|
172
|
+
/**
|
|
173
|
+
* Apply a config change: pause (new calls wait, in-flight calls settle),
|
|
174
|
+
* boot a fresh stack with the re-resolved config, and swap it in.
|
|
175
|
+
*
|
|
176
|
+
* With no argument the ORIGINAL config source is re-resolved — a
|
|
177
|
+
* `dimple.jsonc` FILE PATH is re-read from disk, an inline object is
|
|
178
|
+
* re-validated. A config that fails validation or boot rejects the
|
|
179
|
+
* reload and leaves the current system untouched. An identical config
|
|
180
|
+
* resolves as `{ reloaded: false }` — no pause, no restart.
|
|
181
|
+
*/
|
|
182
|
+
readonly reload: (input?: ConfigInput) => Promise<ReloadResult>;
|
|
96
183
|
/** Stops the worker, closes the sinks and the store — idempotent. */
|
|
97
184
|
readonly dispose: () => Promise<void>;
|
|
98
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* The live handles the facade reads at call time. `makeDimple` swaps the
|
|
188
|
+
* stack under this state on `reload`, so methods always hit the stack that
|
|
189
|
+
* is current when they run.
|
|
190
|
+
*/
|
|
191
|
+
export interface FacadeState {
|
|
192
|
+
readonly run: <A, E>(effect: Effect.Effect<A, E>) => Promise<A>;
|
|
193
|
+
readonly core: () => CoreInterface;
|
|
194
|
+
readonly parser: () => CodeParser["Service"];
|
|
195
|
+
readonly extractor: () => CodeExtractor["Service"];
|
|
196
|
+
}
|
|
99
197
|
/** Build the promise facade over the booted core + runtime. */
|
|
100
|
-
export declare const makeFacade:
|
|
198
|
+
export declare const makeFacade: (state: FacadeState, reload: (input?: ConfigInput) => Promise<ReloadResult>, dispose: () => Promise<void>) => Dimple;
|
|
101
199
|
export type { DimpleError };
|
package/dist/errors.d.ts
CHANGED
|
@@ -45,19 +45,41 @@ declare const DuplicateEdgeError_base: Schema.Class<DuplicateEdgeError, Schema.T
|
|
|
45
45
|
/** A duplicate memory↔memory edge (same from/to/kind already exists). */
|
|
46
46
|
export declare class DuplicateEdgeError extends DuplicateEdgeError_base {
|
|
47
47
|
}
|
|
48
|
+
declare const EdgeNotFoundError_base: Schema.Class<EdgeNotFoundError, Schema.TaggedStruct<"Sdk.EdgeNotFound", {
|
|
49
|
+
readonly id: Schema.optional<Schema.String>;
|
|
50
|
+
readonly message: Schema.String;
|
|
51
|
+
}>, import("effect/Cause").YieldableError>;
|
|
52
|
+
/** The edge does not exist (confirm/reject/expire on a stale id). */
|
|
53
|
+
export declare class EdgeNotFoundError extends EdgeNotFoundError_base {
|
|
54
|
+
}
|
|
48
55
|
declare const StoreFailure_base: Schema.Class<StoreFailure, Schema.TaggedStruct<"Sdk.StoreFailure", {
|
|
49
56
|
readonly message: Schema.String;
|
|
50
57
|
}>, import("effect/Cause").YieldableError>;
|
|
51
58
|
/** Anything else — the typed fallback that keeps the union closed. */
|
|
52
59
|
export declare class StoreFailure extends StoreFailure_base {
|
|
53
60
|
}
|
|
61
|
+
declare const ReloadError_base: Schema.Class<ReloadError, Schema.TaggedStruct<"Sdk.Reload", {
|
|
62
|
+
readonly message: Schema.String;
|
|
63
|
+
}>, import("effect/Cause").YieldableError>;
|
|
64
|
+
/** `reload` was unavailable (no config source, disposed) or failed to
|
|
65
|
+
* drain in-flight calls before the swap. */
|
|
66
|
+
export declare class ReloadError extends ReloadError_base {
|
|
67
|
+
}
|
|
68
|
+
declare const EmbeddingFailure_base: Schema.Class<EmbeddingFailure, Schema.TaggedStruct<"Sdk.Embedding", {
|
|
69
|
+
readonly message: Schema.String;
|
|
70
|
+
}>, import("effect/Cause").YieldableError>;
|
|
71
|
+
/** Embedding pipeline failure — the `@huggingface/transformers` package is
|
|
72
|
+
* missing (local embeddings), the model failed to load, or the output
|
|
73
|
+
* dimensions mismatch the config. */
|
|
74
|
+
export declare class EmbeddingFailure extends EmbeddingFailure_base {
|
|
75
|
+
}
|
|
54
76
|
declare const InputError_base: Schema.Class<InputError, Schema.TaggedStruct<"Sdk.InputError", {
|
|
55
77
|
readonly message: Schema.String;
|
|
56
78
|
}>, import("effect/Cause").YieldableError>;
|
|
57
79
|
/** Invalid SDK call input (bad `limit`, `k`, profile shape, …). */
|
|
58
80
|
export declare class InputError extends InputError_base {
|
|
59
81
|
}
|
|
60
|
-
export type DimpleError = ConfigError | NotFoundError | DuplicateKeyError | DuplicateEdgeError | LLMNotConfiguredError | JobFailedError | StoreFailure | InputError;
|
|
82
|
+
export type DimpleError = ConfigError | NotFoundError | DuplicateKeyError | DuplicateEdgeError | EdgeNotFoundError | LLMNotConfiguredError | EmbeddingFailure | JobFailedError | StoreFailure | ReloadError | InputError;
|
|
61
83
|
/** Map an underlying failure onto the closed SDK hierarchy. */
|
|
62
84
|
export declare const remapError: (error: unknown) => DimpleError;
|
|
63
85
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { makeDimple, type MakeDimpleOptions } from "./make.ts";
|
|
2
2
|
export { type ConfigInput } from "./config.ts";
|
|
3
|
-
export
|
|
4
|
-
export {
|
|
3
|
+
export type { DimpleConfig } from "./internal/config/index.js";
|
|
4
|
+
export { type Dimple, type QueryOptions, type IndexOptions, type IndexResult, type ReloadChanges, type ReloadResult, } from "./dimple.ts";
|
|
5
|
+
export { ConfigError, NotFoundError, DuplicateKeyError, DuplicateEdgeError, EdgeNotFoundError, LLMNotConfiguredError, JobFailedError, StoreFailure, ReloadError, EmbeddingFailure, InputError, remapError, type DimpleError, } from "./errors.ts";
|