@avantf/dsh-mem 0.3.1 → 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.
- package/README.md +89 -28
- package/cordis.patch.yml +17 -0
- package/lib/client.js +155 -14
- package/lib/engine/mem/config/config_files.d.ts +26 -0
- package/lib/engine/mem/config/domains.d.ts +20 -0
- package/lib/engine/mem/config/loader.d.ts +35 -0
- package/lib/engine/mem/config/paths.d.ts +53 -0
- package/lib/engine/mem/db/chunk.d.ts +26 -0
- package/lib/engine/mem/db/conn.d.ts +13 -0
- package/lib/engine/mem/db/dao/chunks.d.ts +150 -0
- package/lib/engine/mem/db/dao/contradictions.d.ts +98 -0
- package/lib/engine/mem/db/dao/documents.d.ts +51 -0
- package/lib/engine/mem/db/dao/entities.d.ts +67 -0
- package/lib/engine/mem/db/dao/facts.d.ts +472 -0
- package/lib/engine/mem/db/dao/stats.d.ts +14 -0
- package/lib/engine/mem/db/dao/triples.d.ts +80 -0
- package/lib/engine/mem/db/hash.d.ts +2 -0
- package/lib/engine/mem/db/knowledge.d.ts +17 -0
- package/lib/engine/mem/db/migrations.d.ts +71 -0
- package/lib/engine/mem/db/port.d.ts +57 -0
- package/lib/engine/mem/db/schema.d.ts +26 -0
- package/lib/engine/mem/db/sqlite.d.ts +89 -0
- package/lib/engine/mem/db/store.d.ts +35 -0
- package/lib/engine/mem/db/tokenizer.d.ts +61 -0
- package/lib/engine/mem/db/vectors.d.ts +50 -0
- package/lib/engine/mem/dispatch.d.ts +51 -0
- package/lib/engine/mem/entities/extract.d.ts +84 -0
- package/lib/engine/mem/eval/loader.d.ts +19 -0
- package/lib/engine/mem/eval/metrics.d.ts +25 -0
- package/lib/engine/mem/eval/runner.d.ts +10 -0
- package/lib/engine/mem/eval/write_metrics.d.ts +88 -0
- package/lib/engine/mem/git.d.ts +73 -0
- package/lib/engine/mem/hrr/algebra.d.ts +30 -0
- package/lib/engine/mem/hrr/atoms.d.ts +22 -0
- package/lib/engine/mem/hrr/encode.d.ts +32 -0
- package/lib/engine/mem/hrr/index.d.ts +3 -0
- package/lib/engine/mem/index.d.ts +27 -0
- package/lib/engine/mem/lifecycle/contradiction.d.ts +156 -0
- package/lib/engine/mem/lifecycle/index.d.ts +5 -0
- package/lib/engine/mem/lifecycle/maintenance.d.ts +48 -0
- package/lib/engine/mem/lifecycle/presence.d.ts +29 -0
- package/lib/engine/mem/lifecycle/tick.d.ts +43 -0
- package/lib/engine/mem/lifecycle/trust.d.ts +90 -0
- package/lib/engine/mem/modelBootstrap.d.ts +207 -0
- package/lib/engine/mem/router.d.ts +51 -0
- package/lib/engine/mem/runtime.d.ts +232 -0
- package/lib/engine/mem/store/common.d.ts +82 -0
- package/lib/engine/mem/store/doc_files.d.ts +125 -0
- package/lib/engine/mem/store/document_text.d.ts +47 -0
- package/lib/engine/mem/store/floors.d.ts +191 -0
- package/lib/engine/mem/store/hybrid.d.ts +232 -0
- package/lib/engine/mem/store/ingest_guard.d.ts +25 -0
- package/lib/engine/mem/store/knowledge.d.ts +483 -0
- package/lib/engine/mem/store/lexical.d.ts +67 -0
- package/lib/engine/mem/store/memory.d.ts +543 -0
- package/lib/engine/mem/store/source_picker.d.ts +43 -0
- package/lib/engine/mem-contract/config.d.ts +129 -0
- package/lib/engine/mem-contract/env.d.ts +31 -0
- package/lib/engine/mem-contract/family.d.ts +25 -0
- package/lib/engine/mem-contract/index.d.ts +8 -0
- package/lib/engine/mem-contract/log.d.ts +29 -0
- package/lib/engine/mem-contract/remote.d.ts +80 -0
- package/lib/engine/mem-contract/text.d.ts +92 -0
- package/lib/engine/mem-contract/tools.d.ts +284 -0
- package/lib/engine/mem-contract/types.d.ts +615 -0
- package/lib/engine/mem-retrieval/adapters/auto_vstore.d.ts +47 -0
- package/lib/engine/mem-retrieval/adapters/hnswlib.d.ts +174 -0
- package/lib/engine/mem-retrieval/adapters/local_bge.d.ts +121 -0
- package/lib/engine/mem-retrieval/adapters/local_numpy.d.ts +28 -0
- package/lib/engine/mem-retrieval/adapters/local_reranker.d.ts +52 -0
- package/lib/engine/mem-retrieval/adapters/none_reranker.d.ts +10 -0
- package/lib/engine/mem-retrieval/adapters/warm_gate.d.ts +46 -0
- package/lib/engine/mem-retrieval/budget.d.ts +30 -0
- package/lib/engine/mem-retrieval/fusion.d.ts +53 -0
- package/lib/engine/mem-retrieval/index.d.ts +14 -0
- package/lib/engine/mem-retrieval/interfaces.d.ts +82 -0
- package/lib/engine/mem-retrieval/log.d.ts +11 -0
- package/lib/engine/mem-retrieval/registry.d.ts +23 -0
- package/lib/engine/mem-retrieval/rerank.d.ts +13 -0
- package/lib/engine/mem-retrieval/stats.d.ts +64 -0
- package/lib/engine/mem-retrieval/text_budget.d.ts +52 -0
- package/lib/index.js +1773 -473
- package/lib/interface-version.json +2 -2
- package/lib/types/client/domains.d.ts +5 -4
- package/lib/types/client/domains.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/ingest.d.ts +1 -1
- package/lib/types/client/wire.d.ts +36 -0
- package/lib/types/client/wire.d.ts.map +1 -0
- package/lib/types/envinit-bootstrap.d.ts +3 -2
- package/lib/types/envinit.d.ts +2 -19
- package/lib/types/envinit.d.ts.map +1 -1
- package/lib/types/hints.d.ts +1 -1
- package/lib/types/index.d.ts +8 -3
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/open.d.ts +61 -11
- package/lib/types/open.d.ts.map +1 -1
- package/lib/types/prompt.d.ts +19 -1
- package/lib/types/prompt.d.ts.map +1 -1
- package/lib/types/provision.d.ts +1 -1
- package/lib/types/provision.d.ts.map +1 -1
- package/lib/types/reconcile.d.ts +64 -0
- package/lib/types/reconcile.d.ts.map +1 -0
- package/lib/types/remote.d.ts +53 -0
- package/lib/types/remote.d.ts.map +1 -1
- package/lib/types/render.d.ts +35 -0
- package/lib/types/render.d.ts.map +1 -0
- package/lib/types/tool_schema.d.ts +3 -13
- package/lib/types/tool_schema.d.ts.map +1 -1
- package/package.json +24 -15
- package/lib/client.js.map +0 -1
- package/lib/types/client/domains.js +0 -25
- package/lib/types/client/domains.js.map +0 -1
- package/lib/types/client/index.js +0 -1371
- package/lib/types/client/index.js.map +0 -1
- package/lib/types/client/ingest.js +0 -30
- package/lib/types/client/ingest.js.map +0 -1
- package/lib/types/client/paging.js +0 -36
- package/lib/types/client/paging.js.map +0 -1
- package/lib/types/client/summarize.js +0 -79
- package/lib/types/client/summarize.js.map +0 -1
- package/lib/types/data_home.js +0 -26
- package/lib/types/data_home.js.map +0 -1
- package/lib/types/envinit-bootstrap.js +0 -333
- package/lib/types/envinit.js +0 -402
- package/lib/types/envinit.js.map +0 -1
- package/lib/types/hints.js +0 -53
- package/lib/types/hints.js.map +0 -1
- package/lib/types/index.js +0 -755
- package/lib/types/index.js.map +0 -1
- package/lib/types/inject.js +0 -14
- package/lib/types/inject.js.map +0 -1
- package/lib/types/interface_gate.js +0 -84
- package/lib/types/interface_gate.js.map +0 -1
- package/lib/types/open.js +0 -133
- package/lib/types/open.js.map +0 -1
- package/lib/types/prompt.js +0 -148
- package/lib/types/prompt.js.map +0 -1
- package/lib/types/provision.js +0 -177
- package/lib/types/provision.js.map +0 -1
- package/lib/types/remote.js +0 -247
- package/lib/types/remote.js.map +0 -1
- package/lib/types/tool_schema.js +0 -149
- package/lib/types/tool_schema.js.map +0 -1
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
import { type Config, type ContradictionRecord, type FactDetail, type FactPage, type FloorProfile, type RecallResult, type RememberResult, type TrustDiagnostic, type VectorsDiagnostic, type VectorsFixReport } from '../../mem-contract/index.js';
|
|
2
|
+
import type { Reranker, SemanticBackend, VectorStore } from '../../mem-retrieval/index.js';
|
|
3
|
+
import type { Db } from '../db/conn.js';
|
|
4
|
+
import { type LexicalProbe } from './lexical.js';
|
|
5
|
+
import { type FloorLeg } from './floors.js';
|
|
6
|
+
import { type TriplePattern } from '../entities/extract.js';
|
|
7
|
+
import { type Sig } from '../lifecycle/contradiction.js';
|
|
8
|
+
import { type MaintenanceResult } from '../lifecycle/maintenance.js';
|
|
9
|
+
import { type TickResult } from '../lifecycle/tick.js';
|
|
10
|
+
/**
|
|
11
|
+
* Result shapes live in `@avantf/mem-contract` (single source for tool/UI payloads); these
|
|
12
|
+
* aliases keep the long-standing `@avantf/mem` export names working for consumers.
|
|
13
|
+
*/
|
|
14
|
+
export type { DetectedContradiction, RememberResult as AddResult } from '../../mem-contract/index.js';
|
|
15
|
+
/**
|
|
16
|
+
* Facts one derived-state sweep pass may rebuild (`reindexEntities`'s default budget).
|
|
17
|
+
*
|
|
18
|
+
* Bounds MEMORY, not only mission: the pass selects `content` for every row it takes, so an
|
|
19
|
+
* "unbounded" pass (the CLI used to ask for `Number.MAX_SAFE_INTEGER`) builds an array of every
|
|
20
|
+
* stale fact's text before rebuilding the first one. Callers that want the corpus drained loop
|
|
21
|
+
* until `deferred === 0` instead.
|
|
22
|
+
*/
|
|
23
|
+
export declare const ENTITY_SWEEP_BATCH = 2000;
|
|
24
|
+
/** What one derived-state sweep pass did (see `MemoryStore.reindexEntities`). */
|
|
25
|
+
export interface EntitySweepReport {
|
|
26
|
+
/**
|
|
27
|
+
* Facts this pass RE-EXTRACTED, i.e. its batch size when it filled it. Counts rows VISITED and
|
|
28
|
+
* re-stamped, not rows whose extraction output differs — the stamp is what makes the corpus
|
|
29
|
+
* current, so a row re-extracted to the same names still counts (and is not rebuilt again).
|
|
30
|
+
*/
|
|
31
|
+
rebuilt: number;
|
|
32
|
+
/** Facts still written by older rules after this pass. */
|
|
33
|
+
deferred: number;
|
|
34
|
+
/** Another pass was already running, so this one did nothing (`deferred` is still current). */
|
|
35
|
+
skipped: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** What one bounded conflict-drain pass did (see `MemoryStore.drainConflicts`). */
|
|
38
|
+
export interface ConflictDrainReport {
|
|
39
|
+
/** Pairs newly logged by this pass. */
|
|
40
|
+
logged: Sig[];
|
|
41
|
+
/**
|
|
42
|
+
* Rows the pass COMPLETED — the embedding leg held their vector in the live index, so the stamp
|
|
43
|
+
* moved. Deliberately not the batch size: a row whose vector the index cannot serve stays queued
|
|
44
|
+
* (see `CheckResult`), which is why this can be 0 while `pending` is not.
|
|
45
|
+
*/
|
|
46
|
+
checked: number;
|
|
47
|
+
/** Rows still queued after this pass (including any it could not complete). */
|
|
48
|
+
pending: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Counts-only view of one conflict pass, for the `maintenance` payload: the pairs themselves are
|
|
52
|
+
* the `contradict_check` payload, and a settings-page click has no use for a list of them.
|
|
53
|
+
*/
|
|
54
|
+
export interface ConflictSweepCounts {
|
|
55
|
+
/** Rows the pass completed (the embedding leg held their vector). */
|
|
56
|
+
checked: number;
|
|
57
|
+
/** Pairs it logged. */
|
|
58
|
+
logged: number;
|
|
59
|
+
/** Rows still queued afterwards. */
|
|
60
|
+
pending: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Outcome of adjudicating a conflict (see `MemoryStore.resolveContradiction`). `reason` is
|
|
64
|
+
* present only on a refusal, so a caller can tell "the pair is closed" from "your request
|
|
65
|
+
* named a fact that is not in the pair".
|
|
66
|
+
*/
|
|
67
|
+
export interface ContradictionResolution {
|
|
68
|
+
resolved: boolean;
|
|
69
|
+
contradiction_id: number;
|
|
70
|
+
/** The fact that was archived as the loser, when the verdict named one. */
|
|
71
|
+
archived_loser: number | null;
|
|
72
|
+
/**
|
|
73
|
+
* Why the verdict was refused. `already_resolved` means the pair carries a verdict already — see
|
|
74
|
+
* {@link MemoryStore.resolveContradiction} for why a second one is refused rather than applied.
|
|
75
|
+
*/
|
|
76
|
+
reason?: 'not_found' | 'already_resolved' | 'loser_not_in_pair' | 'loser_requires_true_positive';
|
|
77
|
+
}
|
|
78
|
+
export interface SearchInput {
|
|
79
|
+
query: string;
|
|
80
|
+
category?: string;
|
|
81
|
+
limit?: number;
|
|
82
|
+
/** Also fuse the HRR entity-probe path (used by `recall.probe`). */
|
|
83
|
+
includeHrr?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Record retrieval stats for the returned facts (default true). Cross-store
|
|
86
|
+
* `kb_query` sets this false and marks only the hits it actually returns, so
|
|
87
|
+
* router-side filtering cannot refresh the dormancy clock of unseen facts.
|
|
88
|
+
*/
|
|
89
|
+
track?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Pre-encoded query vector, when the caller already has one. `runtime.query` encodes a
|
|
92
|
+
* cross-store query ONCE and hands the same vector to both stores (they share the same
|
|
93
|
+
* backend and model), instead of each leg paying for its own encode. The store does not
|
|
94
|
+
* verify it, so it must come from the same backend.
|
|
95
|
+
*/
|
|
96
|
+
queryVector?: Float32Array;
|
|
97
|
+
/** Per-call output token budget; `0` = unlimited, omitted = `retriever.max_output_tokens`. */
|
|
98
|
+
maxTokens?: number;
|
|
99
|
+
/**
|
|
100
|
+
* Relevance-floor profile for this query. Omitted = the default policy: the configured (strict)
|
|
101
|
+
* floors, and if they empty the result while having dropped candidates, ONE relaxed pass
|
|
102
|
+
* (`store/floors.ts`'s `LOOSE_FLOORS`) before answering. `'strict'` asserts the configured floors
|
|
103
|
+
* with no fallback — what the UI's 严格 mode asks for, so the panel can show the honest strict
|
|
104
|
+
* outcome and the drop count. `'loose'` applies the relaxed floors outright.
|
|
105
|
+
*/
|
|
106
|
+
floors?: FloorProfile;
|
|
107
|
+
/**
|
|
108
|
+
* Which legs a `'loose'` pass may lower (see `store/floors.ts`). Internal: an omitted value lets
|
|
109
|
+
* the default policy derive it from the strict pass's own drop report, while the cross-store
|
|
110
|
+
* router pins the MERGED strict pass's dropping legs on its second call — only the merged result
|
|
111
|
+
* knows which legs were the problem for the user's one question.
|
|
112
|
+
*/
|
|
113
|
+
relaxLegs?: readonly FloorLeg[];
|
|
114
|
+
/**
|
|
115
|
+
* Emit a `kind: 'memory'` health event for this search (default true). The cross-store router
|
|
116
|
+
* sets it false: it fuses this leg with the knowledge leg and records ONE `kind: 'cross'`
|
|
117
|
+
* event, so `queries` counts user questions instead of legs (DESIGN §20.5). Distinct from
|
|
118
|
+
* `track`, which is about the dormancy clock — a caller may want one without the other.
|
|
119
|
+
*/
|
|
120
|
+
recordStats?: boolean;
|
|
121
|
+
}
|
|
122
|
+
export declare class MemoryStore {
|
|
123
|
+
private readonly db;
|
|
124
|
+
private readonly config;
|
|
125
|
+
private readonly semantic;
|
|
126
|
+
private readonly vstore;
|
|
127
|
+
private readonly reranker;
|
|
128
|
+
private readonly contradictions;
|
|
129
|
+
private readonly facts;
|
|
130
|
+
private readonly entities;
|
|
131
|
+
private readonly triples;
|
|
132
|
+
/**
|
|
133
|
+
* The tokenizer `facts_fts` was ACTUALLY built with, read from the database at open.
|
|
134
|
+
*
|
|
135
|
+
* Not `resolveFtsTokenizer()`: `CREATE VIRTUAL TABLE IF NOT EXISTS` never rebuilds an existing
|
|
136
|
+
* table, so a database created under another SQLite build keeps the tokenizer it was born with,
|
|
137
|
+
* and building MATCH expressions for the wrong one is silent zero recall (see `db/tokenizer.ts`).
|
|
138
|
+
*/
|
|
139
|
+
private readonly ftsTokenizer;
|
|
140
|
+
/** In-flight guard for `reindexEntities` (see there: the periodic callers can overlap). */
|
|
141
|
+
private entitySweepInFlight;
|
|
142
|
+
/**
|
|
143
|
+
* Where the next conflict drain resumes (see `checkContradictions`). A scheduling cursor, not
|
|
144
|
+
* derived state: nothing is lost when it resets, and the queue itself is in the database.
|
|
145
|
+
*/
|
|
146
|
+
private conflictDrainCursor;
|
|
147
|
+
constructor(db: Db, config: Config, semantic: SemanticBackend, vstore: VectorStore, reranker: Reranker,
|
|
148
|
+
/** The store's database path, used ONLY to name the vector index snapshot beside it. */
|
|
149
|
+
dbPath?: string);
|
|
150
|
+
/**
|
|
151
|
+
* One automatic trust/lifecycle pass (spec §5): advance the active-day clock
|
|
152
|
+
* (when trust is enabled), run the tick, and evict archived/purged vectors from
|
|
153
|
+
* the live index. Called at startup, from the heartbeat, and by `maintenance()`.
|
|
154
|
+
*/
|
|
155
|
+
trustTick(opts?: {
|
|
156
|
+
budget?: number | null;
|
|
157
|
+
}): TickResult;
|
|
158
|
+
/** Identity of the vector space this store currently writes into (`vectorSpaceId`). */
|
|
159
|
+
private vectorSpace;
|
|
160
|
+
/**
|
|
161
|
+
* Rebuild the in-memory vstore from persisted `facts.semantic_vector` BLOBs.
|
|
162
|
+
* Without this the semantic path is silently empty after every process restart
|
|
163
|
+
* (the DB is the authoritative vector store; the vstore is a derived read model).
|
|
164
|
+
*
|
|
165
|
+
* Only ACTIVE facts are indexed: archived facts are filtered out of every
|
|
166
|
+
* retrieval path anyway, so loading them would only grow the index forever.
|
|
167
|
+
* `archive()` evicts and `restore()` re-adds, keeping the invariant.
|
|
168
|
+
*/
|
|
169
|
+
private reloadIndex;
|
|
170
|
+
add(content: string, category?: string, ttlDays?: number): Promise<RememberResult>;
|
|
171
|
+
/**
|
|
172
|
+
* Write-path contradiction detection (DESIGN §11): check the fact that was just
|
|
173
|
+
* written against the corpus, then report its FULL open-conflict set.
|
|
174
|
+
*
|
|
175
|
+
* The check's own return value is not enough: `maybeLog` skips pairs that are already
|
|
176
|
+
* open, so what it returns is "what this pass inserted" — while the caller's question is
|
|
177
|
+
* "what does this write conflict with?". Reporting only the new rows made an update that
|
|
178
|
+
* merged into an already-conflicting fact look clean.
|
|
179
|
+
*
|
|
180
|
+
* Best-effort — a detection failure must never fail the write, and the fact stays PENDING for
|
|
181
|
+
* the next `contradict_check`. `complete` is what enforces that second half: it is true only
|
|
182
|
+
* when nothing went wrong AND the pass held this fact's vector, so a caught failure can never
|
|
183
|
+
* be mistaken for a finished check (an earlier version returned `[]` for both and the caller
|
|
184
|
+
* stamped the marker anyway — a permanent, silent exemption).
|
|
185
|
+
*/
|
|
186
|
+
private detectContradictions;
|
|
187
|
+
/** Best-effort semantic indexing: encode the fact and add it to the vstore. */
|
|
188
|
+
private maybeIndexSemantic;
|
|
189
|
+
update(fact_id: number, content: string, category?: string, ttlDays?: number): Promise<RememberResult>;
|
|
190
|
+
remove(fact_id: number, reason?: string): boolean;
|
|
191
|
+
archive(fact_id: number, reason?: string): boolean;
|
|
192
|
+
/**
|
|
193
|
+
* Bring an archived fact back (spec §2.6): a `forgot` fact is lifted to
|
|
194
|
+
* `recall_floor` (otherwise the very next tick would re-archive it, R4), the
|
|
195
|
+
* idle clock is refreshed (otherwise an `idle`-archived fact dies again, R18),
|
|
196
|
+
* and `settle_clock` moves to now so the downtime is not charged.
|
|
197
|
+
*/
|
|
198
|
+
restore(fact_id: number): boolean;
|
|
199
|
+
helpful(fact_id: number): number | null;
|
|
200
|
+
unhelpful(fact_id: number): number | null;
|
|
201
|
+
/**
|
|
202
|
+
* Explicit feedback (spec §2.4). Pinned/archived rows only move `helpful_count`
|
|
203
|
+
* (R7); otherwise the decay is settled first, then `±feedback_delta`, pin at the
|
|
204
|
+
* permanent threshold (snap to 1.0) or archive immediately at the forget line.
|
|
205
|
+
*/
|
|
206
|
+
private applyFeedback;
|
|
207
|
+
/** Permanent-memory administration (spec §6). */
|
|
208
|
+
pin(fact_id: number): boolean;
|
|
209
|
+
unpin(fact_id: number): boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Trust/forgetting diagnostics (spec §6, R17/R24): the quota is PER FACT, so the
|
|
212
|
+
* report exposes "facts that consumed quota today" and "total effective gains"
|
|
213
|
+
* rather than a meaningless global remaining.
|
|
214
|
+
*/
|
|
215
|
+
trustDiagnose(): TrustDiagnostic;
|
|
216
|
+
get(fact_id: number): FactDetail | null;
|
|
217
|
+
private triplesOf;
|
|
218
|
+
/**
|
|
219
|
+
* One page of facts, newest first.
|
|
220
|
+
* @param category - optional category filter.
|
|
221
|
+
* @param status - `active` (default) or `archived`.
|
|
222
|
+
* @param limit - page size.
|
|
223
|
+
* @param offset - page offset (0-based).
|
|
224
|
+
* @returns the page, the page size (`count`), the matching total, and whether
|
|
225
|
+
* more rows remain after this page.
|
|
226
|
+
*/
|
|
227
|
+
list(category?: string, status?: string, limit?: number, offset?: number): FactPage;
|
|
228
|
+
countByStatus(): {
|
|
229
|
+
active: number;
|
|
230
|
+
archived: number;
|
|
231
|
+
};
|
|
232
|
+
/** Run one incremental contradiction-detection pass; returns newly logged pairs. */
|
|
233
|
+
/**
|
|
234
|
+
* Drain the DURABLE pending queue, bounded by `budget`.
|
|
235
|
+
*
|
|
236
|
+
* These are facts whose embedding-leg check could not run when they were written (no vector —
|
|
237
|
+
* the embedder was unavailable). The queue is `facts.conflict_checked`, not an in-process Set, so
|
|
238
|
+
* it survives a restart and cannot grow without bound as a memory structure.
|
|
239
|
+
*
|
|
240
|
+
* The stamp follows the CHECK, not the selection: a row is marked checked only when the pass
|
|
241
|
+
* actually held its vector (see `CheckResult`). The queue predicate asks the DATABASE for
|
|
242
|
+
* `semantic_vector IS NOT NULL`, which is a different question from "the live index can serve
|
|
243
|
+
* it" — a vector written by another process, or dropped while this one rebuilt its index, is in
|
|
244
|
+
* the column and not in the index. Stamping those was a permanent exemption dressed up as a
|
|
245
|
+
* completed check; leaving them queued keeps `conflict_pending` honest, and `vectors_fix` (which
|
|
246
|
+
* resets the marker when it re-encodes) is what clears them.
|
|
247
|
+
*
|
|
248
|
+
* What the drain guarantees instead of "every selected row is stamped" is that it always MOVES:
|
|
249
|
+
* rows are taken above `conflictDrainCursor`, so an un-completable row cannot hold up the ones
|
|
250
|
+
* behind it. A restart resets the cursor, which costs one extra pass over the head and is why
|
|
251
|
+
* this is a scheduling cursor rather than derived state.
|
|
252
|
+
*
|
|
253
|
+
* A throw keeps the batch queued too — `checkMany` never returns, so nothing is stamped.
|
|
254
|
+
*/
|
|
255
|
+
drainConflicts(budget?: number): ConflictDrainReport;
|
|
256
|
+
/** {@link drainConflicts}, reduced to the pairs it logged (the `contradict_check` payload). */
|
|
257
|
+
checkContradictions(budget?: number): Sig[];
|
|
258
|
+
/**
|
|
259
|
+
* One bounded conflict pass for {@link maintenance}, reduced to COUNTS.
|
|
260
|
+
*
|
|
261
|
+
* `maintenance` is the surfaces' "clean up now" entry (the settings page and the MCP tool call
|
|
262
|
+
* it), and the conflict queue is the other half of the derived state the entity sweep handles: a
|
|
263
|
+
* database upgraded from v5 has every vector-bearing row queued at once, and without this the
|
|
264
|
+
* only way to drain it was the explicit `contradict_check` action. Bounded like the entity sweep
|
|
265
|
+
* (one batch), so a settings-page click stays a click; the CLI is the surface that loops.
|
|
266
|
+
*/
|
|
267
|
+
private sweepConflicts;
|
|
268
|
+
/** Async bootstrap the semantic backend (download/config model) without blocking. */
|
|
269
|
+
warmupSemantic(): Promise<boolean>;
|
|
270
|
+
/** List contradiction candidates (`resolved` 0 = open, 1 = closed with a recorded verdict). */
|
|
271
|
+
listContradictions(opts?: {
|
|
272
|
+
resolved?: number;
|
|
273
|
+
category?: string;
|
|
274
|
+
threshold?: number;
|
|
275
|
+
limit?: number;
|
|
276
|
+
}): ContradictionRecord[];
|
|
277
|
+
/**
|
|
278
|
+
* Adjudicate one logged conflict — the outlet the detector never had.
|
|
279
|
+
*
|
|
280
|
+
* Detection was complete but one-way: a pair was recorded and `resolveForFact` retired it when
|
|
281
|
+
* a fact left the ACTIVE corpus, yet nothing could say "this pair is decided" while both
|
|
282
|
+
* revisions stayed put. The DAO even had `resolve()` with no caller, so the open list could
|
|
283
|
+
* only grow. Two verdicts are meaningful:
|
|
284
|
+
*
|
|
285
|
+
* - `false_positive`: both statements are true, the pair is closed and both facts stay;
|
|
286
|
+
* - `true_positive` + `loser_fact_id`: the loser was wrong, so it is ARCHIVED — which is also
|
|
287
|
+
* what retires every other open conflict naming it, and why the loser must be one of the
|
|
288
|
+
* two facts in this pair.
|
|
289
|
+
*
|
|
290
|
+
* The verdict is recorded on this row either way: `archive()` short-circuits for a fact that
|
|
291
|
+
* is already archived, and the row would otherwise stay open on a technicality.
|
|
292
|
+
*/
|
|
293
|
+
resolveContradiction(id: number, resolution: 'true_positive' | 'false_positive', loserFactId?: number): ContradictionResolution;
|
|
294
|
+
/**
|
|
295
|
+
* Semantic-index health for the ACTIVE corpus (the only thing the index serves):
|
|
296
|
+
* - `missing` active facts with no persisted vector at all;
|
|
297
|
+
* - `stale` active facts whose persisted vector has the wrong dim
|
|
298
|
+
* (semantic.dim changed) — needs a re-encode;
|
|
299
|
+
* - `indexed` vectors currently in the live index;
|
|
300
|
+
* - `unindexed` active facts with a usable persisted vector that the live
|
|
301
|
+
* index does not hold (restart/index loss);
|
|
302
|
+
* - `store` the backend actually serving reads (`auto` migrates at a threshold).
|
|
303
|
+
* - `space_stale` vectors written in a DIFFERENT vector space (another model, or a store
|
|
304
|
+
* upgraded past the space id) — usable bytes, incomparable scores.
|
|
305
|
+
* `total`/`with_semantic` still describe the whole table (including archived).
|
|
306
|
+
*/
|
|
307
|
+
vectorsDiagnose(): VectorsDiagnostic;
|
|
308
|
+
/**
|
|
309
|
+
* ONE read+decode pass over the persisted vectors, shared by diagnose and fix
|
|
310
|
+
* (the two methods used to re-scan and re-decode the same blobs 4-5× per call).
|
|
311
|
+
*/
|
|
312
|
+
private classifyVectors;
|
|
313
|
+
/**
|
|
314
|
+
* Repair the semantic read model:
|
|
315
|
+
* (a) reload persisted, dim-valid vectors missing from the live index
|
|
316
|
+
* (restart / index loss — needs no model),
|
|
317
|
+
* (b) drop persisted vectors whose dim no longer matches `semantic.dim` so a
|
|
318
|
+
* re-encode can replace them (never `add()` a stale vector — the store
|
|
319
|
+
* throws on dim mismatch),
|
|
320
|
+
* (c) encode active facts that have no vector yet (needs the semantic backend),
|
|
321
|
+
* (d) re-encode vectors written in ANOTHER vector space (a model swap, or the one-time
|
|
322
|
+
* adoption of a store predating the space id). Deliberately here and not at open: this is
|
|
323
|
+
* the only path that re-encodes the whole table, so it is an explicit, counted action.
|
|
324
|
+
* `dry_run` previews every count without writing — and without loading the model, which is why
|
|
325
|
+
* the preview also reports `would_warm` (see the contract's `VectorsFixReport`).
|
|
326
|
+
*/
|
|
327
|
+
vectorsFix(dryRun?: boolean): Promise<VectorsFixReport>;
|
|
328
|
+
/**
|
|
329
|
+
* One lifecycle pass, owned by the store so the DB writes and the live-index
|
|
330
|
+
* invariant (ACTIVE vectors only) are maintained in ONE place — the runtime no
|
|
331
|
+
* longer has to patch the index behind the store's back.
|
|
332
|
+
*
|
|
333
|
+
* It also runs ONE bounded derived-state sweep pass, which is why it is async: `entities` is
|
|
334
|
+
* what the sweep rebuilt and what it still owes (`deferred`). One pass, not a loop — this is
|
|
335
|
+
* reachable from a settings-page button and an MCP call, so it must not block on a whole stale
|
|
336
|
+
* corpus; operators who want it drained loop on `reindexEntities` until `deferred === 0` (the
|
|
337
|
+
* CLI does). It deliberately does not sit behind `heartbeat_minutes`, which can be 0.
|
|
338
|
+
*/
|
|
339
|
+
maintenance(): Promise<MaintenanceResult & {
|
|
340
|
+
entities: EntitySweepReport;
|
|
341
|
+
conflicts: ConflictSweepCounts;
|
|
342
|
+
}>;
|
|
343
|
+
/**
|
|
344
|
+
* Re-extract the entity/triple rows of facts written by OLDER extraction rules (bounded).
|
|
345
|
+
*
|
|
346
|
+
* The memory-side counterpart of `KnowledgeStore.reindex`'s entity leg, and the reason
|
|
347
|
+
* `facts.entities_version` exists: without it a change to the extraction rules could only reach
|
|
348
|
+
* facts written afterwards, so the corpus would carry two vintages indefinitely and retrieval
|
|
349
|
+
* quality would depend on when a fact happened to be written. The version covers the RULES, not
|
|
350
|
+
* which tagger happened to produce the tokens — the tagger is an optional dependency loaded
|
|
351
|
+
* asynchronously, and a process that fails to load it falls back to regex; folding that into the
|
|
352
|
+
* version would make a capability failure schedule a corpus-wide rebuild with the WORSE extractor.
|
|
353
|
+
*
|
|
354
|
+
* One transaction per fact: the entity rows, the triple rows, the HRR bundle (which is derived
|
|
355
|
+
* FROM the entity names) and the version stamp all move together or not at all. The semantic
|
|
356
|
+
* vector is untouched — it encodes the CONTENT, which is unchanged — but `conflict_checked` is
|
|
357
|
+
* RESET, because both legs of the conflict check read exactly what this rebuilt (see
|
|
358
|
+
* `requeueConflictCheck`).
|
|
359
|
+
*
|
|
360
|
+
* Awaited by `maintenance` (one batch), so the caller knows the batch is done when it returns;
|
|
361
|
+
* `deferred` is what the next pass still has to do. Callers that want the whole corpus drained
|
|
362
|
+
* loop until `deferred === 0` — `budget` bounds MEMORY as well as mission, since the pass reads
|
|
363
|
+
* every selected row's `content` before rebuilding the first one.
|
|
364
|
+
*
|
|
365
|
+
* The in-flight guard is here rather than at the callers because the callers CAN overlap: the
|
|
366
|
+
* plugin's heartbeat and `maintenance` are both periodic, and `staleEntityRows` is ORDERED, so
|
|
367
|
+
* two concurrent passes would select the same rows and re-tag them twice. Overlap is not
|
|
368
|
+
* corruption (each fact is stamped in its own transaction) — it is duplicated mission in a
|
|
369
|
+
* single-threaded process. A pass that finds one running reports `skipped` and does nothing.
|
|
370
|
+
*
|
|
371
|
+
* `budget` is clamped at 0: SQLite reads a negative LIMIT as "no limit" (`LIMIT -1`), so a
|
|
372
|
+
* caller asking for "-1 rows" would silently get the whole corpus — the opposite of bounded.
|
|
373
|
+
*/
|
|
374
|
+
reindexEntities(budget?: number): Promise<EntitySweepReport>;
|
|
375
|
+
/**
|
|
376
|
+
* A fact left the ACTIVE corpus: retire the open conflicts that name it, so
|
|
377
|
+
* `contradict` never reports a pair whose revision is archived and repeated
|
|
378
|
+
* archive/restore cycles cannot stack duplicates (see
|
|
379
|
+
* `ContradictionsDao.resolveForFact`).
|
|
380
|
+
*/
|
|
381
|
+
private retireConflicts;
|
|
382
|
+
/** Drop vectors of archived/purged facts from the live index (batched). */
|
|
383
|
+
private evictVectors;
|
|
384
|
+
/**
|
|
385
|
+
* Entities that co-occur with `entity` across ACTIVE facts, ranked by occurrence
|
|
386
|
+
* count. Archived (incl. superseded) facts are excluded — their entities are not
|
|
387
|
+
* part of the live graph.
|
|
388
|
+
*/
|
|
389
|
+
related(entity: string, limit?: number, category?: string): {
|
|
390
|
+
entity: string;
|
|
391
|
+
count: number;
|
|
392
|
+
}[];
|
|
393
|
+
/** Two-hop traversal: subj -pred-> mid, mid -second_pred-> obj. Returns the second-hop facts. */
|
|
394
|
+
chain(subj: string, pred?: string, secondPred?: string, limit?: number): Promise<RecallResult>;
|
|
395
|
+
/** Facts whose entity set contains ALL given entities (AND-join). */
|
|
396
|
+
reason(entities: string[], limit?: number): Promise<RecallResult>;
|
|
397
|
+
/** Hybrid search over the memory corpus (semantic + FTS + entity Jaccard [+ HRR probe] via fusion). */
|
|
398
|
+
search(input: SearchInput): Promise<RecallResult>;
|
|
399
|
+
/**
|
|
400
|
+
* This store's half of the shared orchestration (`store/hybrid.ts`): the legs, the text load, the
|
|
401
|
+
* fact→hit mapping, and what to do with the hits the caller actually receives.
|
|
402
|
+
*/
|
|
403
|
+
private hybridDeps;
|
|
404
|
+
/**
|
|
405
|
+
* The memory legs: semantic, FTS, entity Jaccard, and — for `recall.probe` — the HRR probe.
|
|
406
|
+
*
|
|
407
|
+
* Every non-semantic leg is CAPPED. Fusion only ever keeps `overFetch` entries, so a leg returning
|
|
408
|
+
* the whole matching corpus (measured: the FTS leg returned all 33000 facts for a common phrase,
|
|
409
|
+
* the entity leg 6600) made `fuse` normalize and sort the corpus per query. 4× the pool is
|
|
410
|
+
* deliberate headroom: each leg must be able to fill the pool on its own.
|
|
411
|
+
*
|
|
412
|
+
* The cap is score-transparent for a leg that hands its entries over in ITS OWN SCORE ORDER —
|
|
413
|
+
* `fuse` scales by each leg's maximum, an entry no cap can remove, so a trimmed tail cannot
|
|
414
|
+
* rescale the survivors. That covers the Jaccard and FTS legs. It does NOT cover the HRR leg, whose
|
|
415
|
+
* candidates arrive in the JACCARD leg's order (or by recency in its fallback), so its cap can
|
|
416
|
+
* remove its own highest scorer and `v / max` really does move. Accepted — the cap bounds per-query
|
|
417
|
+
* mission and the pool is reranked afterwards — but do not read these scores as comparable across
|
|
418
|
+
* different cap/over-fetch settings; see `docs/PROVENANCE_REVIEW.md` N5 for the missing differential.
|
|
419
|
+
*/
|
|
420
|
+
private searchLegs;
|
|
421
|
+
/**
|
|
422
|
+
* Whether the configured reranker is actually in use — the two flags a retrieval event
|
|
423
|
+
* carries. Exposed so the cross-store router can report ONE event for a merged query with the
|
|
424
|
+
* same honesty as a single-store search (both stores share this adapter, and the derivation lives
|
|
425
|
+
* in `store/hybrid.ts` rather than being re-spelled per store).
|
|
426
|
+
*/
|
|
427
|
+
rerankState(): {
|
|
428
|
+
used: boolean;
|
|
429
|
+
fallback: boolean;
|
|
430
|
+
};
|
|
431
|
+
/**
|
|
432
|
+
* The one fact→RecallHit mapper (kind/source_ref/entities shape lives here ONLY;
|
|
433
|
+
* chain/reason/ask/search all used to carry byte-identical copies, three of them
|
|
434
|
+
* with an N+1 entity load each). Facts have no knowledge-base taxonomy, so
|
|
435
|
+
* `domain`/`source` are null — that is what keeps a `domain`-filtered cross query
|
|
436
|
+
* from ever matching a memory hit.
|
|
437
|
+
*/
|
|
438
|
+
private factHits;
|
|
439
|
+
/**
|
|
440
|
+
* Record a RECALL and reinforce the facts (spec §2.3): usage stats always move,
|
|
441
|
+
* the trust bonus is quota-limited (per fact, calendar 24h), zero-gain recalls
|
|
442
|
+
* cost nothing, and a recall can never push a fact to permanent (D11).
|
|
443
|
+
*
|
|
444
|
+
* Public so `runtime.query` can reinforce ONLY the merged hits it actually
|
|
445
|
+
* returns, after the router's kind/domain/source filtering (R5/R21).
|
|
446
|
+
*/
|
|
447
|
+
reinforce(ids: number[]): void;
|
|
448
|
+
/**
|
|
449
|
+
* Load the persisted retrieval-health counters, and write the current ones back.
|
|
450
|
+
*
|
|
451
|
+
* A snapshot written by an older build (or a corrupt row) must not break startup, so a parse
|
|
452
|
+
* failure leaves the live counters alone — `restoreRetrievalHealth` validates the shape.
|
|
453
|
+
*/
|
|
454
|
+
private restoreHealth;
|
|
455
|
+
/**
|
|
456
|
+
* Flush the counters so a restart does not reset the picture (see `RETRIEVAL_HEALTH_KEY`).
|
|
457
|
+
*
|
|
458
|
+
* Called by `maintenance()` and by the runtime on shutdown — NOT from a `close()`, because the
|
|
459
|
+
* runtime owns the database handle.
|
|
460
|
+
*/
|
|
461
|
+
flushHealth(): void;
|
|
462
|
+
/** Retrieval bookkeeping: `retrieval_count` + the "last used" clock (spec §2.5). */
|
|
463
|
+
private touchUsage;
|
|
464
|
+
/**
|
|
465
|
+
* Semantic leg. `queryVector` short-circuits the encode when the caller already
|
|
466
|
+
* encoded this exact query (the cross-store router does, for both stores at once);
|
|
467
|
+
* `onVector` publishes the vector this leg actually used, so the relaxed retry pass can reuse it
|
|
468
|
+
* instead of re-encoding (performance review §7.7 / P8).
|
|
469
|
+
*/
|
|
470
|
+
private semanticPath;
|
|
471
|
+
/**
|
|
472
|
+
* HRR entity-probe path: phase similarity between the query's entity bundle and
|
|
473
|
+
* each active fact's persisted HRR vector. Recalls facts whose entities relate to
|
|
474
|
+
* the probe even when surface text shares no FTS trigrams.
|
|
475
|
+
*/
|
|
476
|
+
private hrrPath;
|
|
477
|
+
/**
|
|
478
|
+
* Direction-aware question answering over SPO triples.
|
|
479
|
+
* Parse the query into a TriplePattern, match triples by the filled slots
|
|
480
|
+
* (unfilled = wildcard), and rank the owning facts. Direction is preserved by
|
|
481
|
+
* the triple's (subj, pred, obj) roles.
|
|
482
|
+
*/
|
|
483
|
+
ask(query: string, limit?: number): Promise<RecallResult>;
|
|
484
|
+
/** Direction-aware answer over SPO triples from an explicit pattern. */
|
|
485
|
+
askByPattern(pattern: TriplePattern, limit?: number): Promise<RecallResult>;
|
|
486
|
+
/** One-shot flag for the probe fallback warning (see `hrrPath`). */
|
|
487
|
+
private hrrFallbackWarned;
|
|
488
|
+
/**
|
|
489
|
+
* Sync relevance probe for the plugin's conditional hint (DESIGN §12): how many of `text`'s
|
|
490
|
+
* terms this store already holds. `store/lexical.ts` carries why it is lexical rather than
|
|
491
|
+
* semantic, why it must be synchronous, and how the bar itself was measured.
|
|
492
|
+
*/
|
|
493
|
+
lexicalProbe(text: string, stopAt?: number): LexicalProbe;
|
|
494
|
+
private ftsPath;
|
|
495
|
+
/**
|
|
496
|
+
* Jaccard leg over the precomputed candidate set (see `search`): the candidates are the facts
|
|
497
|
+
* sharing at least one query entity, pre-ranked by how many they share and already capped.
|
|
498
|
+
*/
|
|
499
|
+
private jaccardPath;
|
|
500
|
+
/**
|
|
501
|
+
* Insert (or resolve to) a fact row.
|
|
502
|
+
*
|
|
503
|
+
* `category` / `ttlDays` are `undefined` when the CALLER specified nothing — the
|
|
504
|
+
* distinction is load-bearing. A duplicate-content hit must not clobber the existing
|
|
505
|
+
* row's values with the insert defaults: re-adding a fact without a category used to
|
|
506
|
+
* reset it to `general`, and reviving an archived one silently cleared an explicit TTL.
|
|
507
|
+
* The rule for all three branches is therefore: an explicitly provided value lands, an
|
|
508
|
+
* omitted one keeps what the row already has, and a brand-new row falls back to the
|
|
509
|
+
* defaults (`general` / `0`).
|
|
510
|
+
*/
|
|
511
|
+
private persistFact;
|
|
512
|
+
/**
|
|
513
|
+
* Link the revision chain and archive the superseded fact — on both the fresh-insert
|
|
514
|
+
* and duplicate-content branches.
|
|
515
|
+
*
|
|
516
|
+
* @returns the superseded fact id whose vector must leave the live index, or null.
|
|
517
|
+
* The caller evicts it AFTER the surrounding transaction commits: evicting inside
|
|
518
|
+
* would desync the index from the DB on a rollback.
|
|
519
|
+
*/
|
|
520
|
+
private applySupersede;
|
|
521
|
+
private linkEntities;
|
|
522
|
+
/**
|
|
523
|
+
* Normalize the SPO slots of extracted triples through the same write entry as fact content.
|
|
524
|
+
*
|
|
525
|
+
* The triples are DERIVED (from an already-normalized content string, in `add`/`update`), but a
|
|
526
|
+
* tokenizer is free to hand back a half code unit, and a future truncation rule could split a
|
|
527
|
+
* surrogate pair — so the derived rows cross the same entry instead of trusting the producer.
|
|
528
|
+
*/
|
|
529
|
+
private normalizeTriples;
|
|
530
|
+
private insertTriples;
|
|
531
|
+
private getRow;
|
|
532
|
+
private entityNames;
|
|
533
|
+
private entityBags;
|
|
534
|
+
private loadTexts;
|
|
535
|
+
/**
|
|
536
|
+
* Summary projection. `trust_score` follows the R11 display rule: the EFFECTIVE
|
|
537
|
+
* (decayed) value for active facts and the STORED one for non-active rows;
|
|
538
|
+
* `remaining_days` is null for pinned / non-active rows (spec §6) so it can never
|
|
539
|
+
* go negative.
|
|
540
|
+
*/
|
|
541
|
+
private toSummary;
|
|
542
|
+
private toDetail;
|
|
543
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { BrowseEntry, BrowseListing, SourceClassification, SourceKind } from '../../mem-contract/index.js';
|
|
2
|
+
import { type IngestLimits } from './ingest_guard.js';
|
|
3
|
+
/**
|
|
4
|
+
* The shapes come from the CONTRACT, and core re-exports them for its own callers.
|
|
5
|
+
*
|
|
6
|
+
* The engine owns the behaviour, but the browser half needs the types WITHOUT the engine, so the
|
|
7
|
+
* contract owns them (see `SourceClassification` / `BrowseListing` there). No hand-mirror left to
|
|
8
|
+
* drift, which is why the re-export below exists: `export type { X } from '…'` alone does NOT put `X`
|
|
9
|
+
* in this module's scope, so the separate `import type` above is what the rest of this file uses.
|
|
10
|
+
*/
|
|
11
|
+
export type { BrowseEntry, BrowseListing, SourceClassification, SourceKind };
|
|
12
|
+
/** Split one source string the way `kb import` does: whitespace or comma separated. */
|
|
13
|
+
export declare function splitSourceInput(raw: string): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Walk one directory for ingestable files: text formats plus PDF.
|
|
16
|
+
*
|
|
17
|
+
* Everything else is reported as SKIPPED rather than dropped silently — a directory of 200 files
|
|
18
|
+
* where 3 were ingested and 197 ignored used to look exactly like a directory of 3 files.
|
|
19
|
+
*/
|
|
20
|
+
export declare function listTextFiles(dir: string): {
|
|
21
|
+
files: string[];
|
|
22
|
+
skipped: string[];
|
|
23
|
+
};
|
|
24
|
+
/** Would ingestion take this file name? */
|
|
25
|
+
export declare function isIngestableFile(name: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Classify one source input without ingesting anything.
|
|
28
|
+
*
|
|
29
|
+
* The order matters: a URL wins outright, then anything that resolves on disk (several paths, a
|
|
30
|
+
* directory, a file), then a path-SHAPED input that does not resolve is `missing` (a typo, or a
|
|
31
|
+
* path outside the boundary — the reason says which), and only then is it pasted text. Long or
|
|
32
|
+
* many-token inputs skip the filesystem probes entirely: prose is not a path list, and a paragraph
|
|
33
|
+
* should not cost thousands of `stat` calls.
|
|
34
|
+
*/
|
|
35
|
+
export declare function classifySource(raw: string, limits: IngestLimits): SourceClassification;
|
|
36
|
+
/**
|
|
37
|
+
* List one directory for the picker.
|
|
38
|
+
*
|
|
39
|
+
* `requested` empty ⇒ the first allowed root. Every requested path goes through
|
|
40
|
+
* {@link resolveLocalSource}, so the picker can never show (or hand back) a directory that
|
|
41
|
+
* ingestion would refuse; `parent` stops at a root for the same reason.
|
|
42
|
+
*/
|
|
43
|
+
export declare function browseDirectory(requested: string | undefined, limits: IngestLimits): BrowseListing;
|