lossless-core 0.1.1 → 0.1.3
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/CHANGELOG.md +17 -0
- package/dist/index.d.mts +153 -12
- package/dist/index.mjs +3638 -2782
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -4
- package/skills/lossless-core/SKILL.md +91 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# lossless-core
|
|
2
2
|
|
|
3
|
+
## 0.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 470a7b7: Verify file bytes and sha256 against the linked message text before inserting file rows on import. A repeated entry id with different text, or a file row whose text differs from the stored message, also refuses the import without writing. Existing rows stay untouched.
|
|
8
|
+
- 470a7b7: Signal a watermark miss on the ingest path. A full rescan now writes one `ingest-rescan` metric row and, in interactive sessions, one UI warning. Empty entries stay silent and ingest behavior is unchanged.
|
|
9
|
+
- 470a7b7: Add a mechanical tier for noisy tools. Name tools in `mechanicalTools` in summarizer-config, `/lcm` config, or the OpenCode plugin options. Their spans compact into deterministic `mechanical` leaves with zero summarizer spend at compaction time. Every message stays stored verbatim and covered, so the integrity coverage check passes, and heal re-derives a skipped leaf from provenance on demand. There is no ingest filtering.
|
|
10
|
+
- 470a7b7: Report orphan sidecars in doctor. `integritySnapshot` now lists sidecar files and stale `wal` and `shm` files with no live session (`.sqlite` by default, `.db` for Pi). `checkIntegrity` reports them as a read-only `orphan-sidecar` finding through `lcm doctor` and the diagnose bundle. Report only. Deletion stays manual.
|
|
11
|
+
- 470a7b7: Upgrade recall search. `lcm_grep` takes `role`, `date_start`/`date_end`, and `tool_name` filters. Role and time are SQL predicates on the stored columns with a covering index. Tool scope is an FTS rewrite against `[tool:Name]` markers with no new table or index. `lcm_expand` takes an `anchor` entry id that centers the listing window with edge clamping. The recall manifest and the retrieval brief order by stop-word stripped query-word overlap over summary headers. A read-only files view lists each linked file once with an incomplete-coverage flag and a `large-inline` mark. No migration and no new writer.
|
|
12
|
+
- 0c70748: Ask providers for a whole number of tokens. A leaf target was half of the calibrated chunk budget, so it was fractional whenever that budget was odd, and a provider that validates `max_tokens` as an unsigned integer rejected the call with a 422. The ladder then stored the deterministic truncate: in one week of Pi sessions that was 1,315 of 5,358 summaries, with 540 rejected calls naming values such as `max_tokens: 5543.5`. The request builder now rounds to nearest, never below one, and treats a non-finite budget as that floor, before the reasoning headroom is added. Integer budgets produce the same request as before. No config key, migration or metric row changes.
|
|
13
|
+
|
|
14
|
+
## 0.1.2
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- de419eb: Ship a versioned Intent skill with each package (`skills/<name>/SKILL.md` in the published tarball): install, command and recall vocabulary, config essentials, and common mistakes, stamped with the package version on release. Adds `skills` to each package's published files and validates skills on publish and in CI.
|
|
19
|
+
|
|
3
20
|
## 0.1.1
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -198,6 +198,15 @@ export interface IntegritySnapshot {
|
|
|
198
198
|
foreignKeyViolations: number;
|
|
199
199
|
schemaVersion: number;
|
|
200
200
|
uncoveredMessages: number;
|
|
201
|
+
/** Full paths, sorted, so doctor can name what a manual drop would remove. */
|
|
202
|
+
orphanSidecars: string[];
|
|
203
|
+
}
|
|
204
|
+
export interface IntegritySnapshotOptions {
|
|
205
|
+
/** Paths with an open store in this process; every other sidecar file in
|
|
206
|
+
* `sidecarDir` reports as unopened, even when its session still exists. */
|
|
207
|
+
liveSidecarPaths?: readonly string[];
|
|
208
|
+
sidecarDir?: string;
|
|
209
|
+
sidecarExtension?: string;
|
|
201
210
|
}
|
|
202
211
|
/** A fresh row, or the row that already owns the span; `existingTokens` comes
|
|
203
212
|
* from that row, so a caller reports the collision, not its intended write.
|
|
@@ -454,14 +463,23 @@ export declare class LcmStore {
|
|
|
454
463
|
offset?: number;
|
|
455
464
|
withinMessageIds?: ReadonlySet<number>;
|
|
456
465
|
includeRemoved?: boolean;
|
|
466
|
+
role?: LcmRole;
|
|
467
|
+
dateStart?: number;
|
|
468
|
+
dateEnd?: number;
|
|
457
469
|
}): GrepHit[];
|
|
458
470
|
grepCount(pattern: string, opts?: {
|
|
459
471
|
withinMessageIds?: ReadonlySet<number>;
|
|
460
472
|
includeRemoved?: boolean;
|
|
473
|
+
role?: LcmRole;
|
|
474
|
+
dateStart?: number;
|
|
475
|
+
dateEnd?: number;
|
|
461
476
|
}): number | undefined;
|
|
462
477
|
messagePage(afterRowId: number, limit: number, opts?: {
|
|
463
478
|
withinMessageIds?: ReadonlySet<number>;
|
|
464
479
|
includeRemoved?: boolean;
|
|
480
|
+
role?: LcmRole;
|
|
481
|
+
dateStart?: number;
|
|
482
|
+
dateEnd?: number;
|
|
465
483
|
}): ScannedRow[];
|
|
466
484
|
coveringSummaryId(entryId: string): number | undefined;
|
|
467
485
|
messageByEntryId(entryId: string): StoredMessage | undefined;
|
|
@@ -478,7 +496,7 @@ export declare class LcmStore {
|
|
|
478
496
|
getSummary(id: number, run?: string): SummaryNode | undefined;
|
|
479
497
|
/** Bounded by a visited set, so a corrupt cycle cannot recurse forever. */
|
|
480
498
|
coveredMessageIds(summaryId: number, seen?: Set<number>): number[];
|
|
481
|
-
integritySnapshot(): IntegritySnapshot;
|
|
499
|
+
integritySnapshot(opts?: IntegritySnapshotOptions): IntegritySnapshot;
|
|
482
500
|
/** Restore the full-text index. The schema is re-applied first, because a
|
|
483
501
|
* dropped virtual table cannot be rebuilt, only recreated, and the DDL that
|
|
484
502
|
* knows how is the schema itself. Everything in it is `IF NOT EXISTS` apart
|
|
@@ -538,10 +556,12 @@ export declare const NO_STORE = "LCM: no stored history for this session yet (no
|
|
|
538
556
|
export declare const RECALL_SCOPES: readonly ["session", "sessions", "all_sessions"];
|
|
539
557
|
/** One of `RECALL_SCOPES`; `sessions` and `all_sessions` are equivalent and both read past sidecars. */
|
|
540
558
|
export type RecallScope = (typeof RECALL_SCOPES)[number];
|
|
541
|
-
/** What `lcm_expand` reads: a summary listing by id
|
|
559
|
+
/** What `lcm_expand` reads: a summary listing by id (optionally centered on an
|
|
560
|
+
* anchor entry), or one message by entry id with an optional summary check. */
|
|
542
561
|
export type Address = {
|
|
543
562
|
readonly kind: "summary";
|
|
544
563
|
readonly id: number;
|
|
564
|
+
readonly anchor?: string;
|
|
545
565
|
} | {
|
|
546
566
|
readonly kind: "entry";
|
|
547
567
|
readonly entryId: string;
|
|
@@ -569,18 +589,27 @@ export interface RecallToolDeps {
|
|
|
569
589
|
readonly record?: (row: Record<string, unknown>) => void;
|
|
570
590
|
readonly sessionOf?: (sessionId: string) => string;
|
|
571
591
|
readonly isReader?: (sessionId: string) => boolean;
|
|
572
|
-
readonly searchPast?: (session: string, query: string, scope: Exclude<RecallScope, "session">, limit: unknown) => RecallPastSearchResult;
|
|
592
|
+
readonly searchPast?: (session: string, query: string, scope: Exclude<RecallScope, "session">, limit: unknown, filters?: GrepFilterArgs) => RecallPastSearchResult;
|
|
573
593
|
readonly openPast?: (session: string, pastSession: string) => OpenPastResult;
|
|
574
594
|
readonly pastSearchUnreachableText?: string;
|
|
575
595
|
readonly pastReadUnreachableText?: string;
|
|
576
596
|
}
|
|
577
597
|
/** Answer `lcm_grep`: the session `grepView`, or past sidecars when the scope names them; readers stay session-scoped. */
|
|
578
598
|
export declare function grepAnswer(deps: RecallToolDeps, callerSessionID: string, input: unknown): string;
|
|
599
|
+
/** Optional `lcm_grep` filters, shared by the session search and the past-session
|
|
600
|
+
* scan. Unknown roles and bad timestamps are caller errors; an empty tool name
|
|
601
|
+
* is too, while an unknown-but-well-formed tool name simply matches nothing. */
|
|
602
|
+
export interface GrepFilterArgs {
|
|
603
|
+
role?: "user" | "assistant" | "toolResult" | "custom";
|
|
604
|
+
dateStart?: number;
|
|
605
|
+
dateEnd?: number;
|
|
606
|
+
toolName?: string;
|
|
607
|
+
}
|
|
579
608
|
/** Answer `lcm_describe`: the redacted cost and contents of one summary id, or why it missed. */
|
|
580
609
|
export declare function describeAnswer(deps: RecallToolDeps, callerSessionID: string, input: unknown): string;
|
|
581
610
|
/** Answer `lcm_expand`: list a summary or read one message, capped at `MAX_EXPAND_CHARS`; a foreign `session` id reads a past sidecar read-only. */
|
|
582
611
|
export declare function expandAnswer(deps: RecallToolDeps, callerSessionID: string, input: unknown): string;
|
|
583
|
-
/** Parse `id`/`entry_id` args into an `Address`: error text when malformed, undefined when neither is present. */
|
|
612
|
+
/** Parse `id`/`entry_id`/`anchor` args into an `Address`: error text when malformed, undefined when neither is present. */
|
|
584
613
|
export declare function readAddress(args: Record<string, unknown>): Address | string | undefined;
|
|
585
614
|
/** Refusal text when an address names no stored summary or message, else undefined. */
|
|
586
615
|
export declare function addressProblem(store: LcmStore, address: Address): string | undefined;
|
|
@@ -1239,6 +1268,12 @@ export type BranchRemovedRow = LcmRowBase & {
|
|
|
1239
1268
|
removed: number;
|
|
1240
1269
|
restored: number;
|
|
1241
1270
|
};
|
|
1271
|
+
/** A watermark miss forced a full rescan. Empty deltas never write one. */
|
|
1272
|
+
export type IngestRescanRow = LcmRowBase & {
|
|
1273
|
+
kind: "ingest-rescan";
|
|
1274
|
+
watermark: string;
|
|
1275
|
+
entries: number;
|
|
1276
|
+
};
|
|
1242
1277
|
export type FileExternalizedRow = LcmRowBase & {
|
|
1243
1278
|
kind: "file-externalized";
|
|
1244
1279
|
entryId: string;
|
|
@@ -1310,7 +1345,7 @@ export type ImportRow = MetricBase & {
|
|
|
1310
1345
|
summariesInserted: number;
|
|
1311
1346
|
summariesSkipped: number;
|
|
1312
1347
|
});
|
|
1313
|
-
export type LcmMetricRecord = ContextDecisionRow | ProjectionOverBudgetRow | SwapAppliedRow | SwapBlockedRow | PiCompactionRow | EstimateCalibratedRow | WindowCorrectedRow | WindowFloorRow | ConfigProblemRow | SummaryInputClippedRow | SummaryFallbackStoredRow | SummaryStoredRow | SummarySkippedCoveredRow | SummarySkippedExistingRow | SummaryOversizedRow | SummaryReplacedRow | SummaryFinalTruncatedRow | CondensationStalledRow | CondensationReducedRow | CompactionCompleteRow | HealStartRow | HealNodeRow | HealCompleteRow | SummarizerErrorRow | SummarizerCappedRow | SummarizerFallbackRow | SummarizerModelRow | SummarizerUsageRow | CompactionErrorRow | CompactionAwaitedRow | CompactionQueuedRow | CompactionQueuedDroppedRow | CompactionTimeoutClearedRow | CompactionStaleRow | CompactionAbandonedRow | CompactionNoopRow | GcDeletedRow | StoreMigratedRow | BranchRemovedRow | FileExternalizedRow | LargeInlineRow | RecallRow | RetrievalRow | EvalRow | ImportRow;
|
|
1348
|
+
export type LcmMetricRecord = ContextDecisionRow | ProjectionOverBudgetRow | SwapAppliedRow | SwapBlockedRow | PiCompactionRow | EstimateCalibratedRow | WindowCorrectedRow | WindowFloorRow | ConfigProblemRow | SummaryInputClippedRow | SummaryFallbackStoredRow | SummaryStoredRow | SummarySkippedCoveredRow | SummarySkippedExistingRow | SummaryOversizedRow | SummaryReplacedRow | SummaryFinalTruncatedRow | CondensationStalledRow | CondensationReducedRow | CompactionCompleteRow | HealStartRow | HealNodeRow | HealCompleteRow | SummarizerErrorRow | SummarizerCappedRow | SummarizerFallbackRow | SummarizerModelRow | SummarizerUsageRow | CompactionErrorRow | CompactionAwaitedRow | CompactionQueuedRow | CompactionQueuedDroppedRow | CompactionTimeoutClearedRow | CompactionStaleRow | CompactionAbandonedRow | CompactionNoopRow | GcDeletedRow | StoreMigratedRow | BranchRemovedRow | IngestRescanRow | FileExternalizedRow | LargeInlineRow | RecallRow | RetrievalRow | EvalRow | ImportRow;
|
|
1314
1349
|
export type MetricRecord = UsageRow | LcmMetricRecord;
|
|
1315
1350
|
export interface LlmComplete {
|
|
1316
1351
|
(systemPrompt: string, userText: string, maxTokens: number): Promise<string>;
|
|
@@ -1336,6 +1371,8 @@ export declare function summarizeTerse(items: Array<{
|
|
|
1336
1371
|
role: string;
|
|
1337
1372
|
text: string;
|
|
1338
1373
|
}>, targetTokens: number, llm: LlmComplete, session?: string): Promise<EscalationResult>;
|
|
1374
|
+
/** Same budget the ladder falls back to, so heal sees one shape. */
|
|
1375
|
+
export declare const LEVEL3_TOKENS = 512;
|
|
1339
1376
|
export declare function deterministicTruncate(text: string, targetTokens: number): string;
|
|
1340
1377
|
export interface SummarizerConfig {
|
|
1341
1378
|
/** One model id, or an ordered fallback chain. `auto` is the session model. */
|
|
@@ -1439,7 +1476,32 @@ export interface SummarizerOptions {
|
|
|
1439
1476
|
readonly summarizerTokensPerPass?: number;
|
|
1440
1477
|
/** Tokens one on-demand heal run may spend across all of its calls. */
|
|
1441
1478
|
readonly summarizerTokensPerHeal?: number;
|
|
1442
|
-
|
|
1479
|
+
/** Fires at compaction time only; ingest still stores every message verbatim. */
|
|
1480
|
+
readonly mechanicalTools?: readonly string[];
|
|
1481
|
+
}
|
|
1482
|
+
/** Empty default: callers opt in and existing passes keep their spend. */
|
|
1483
|
+
export declare const DEFAULT_MECHANICAL_TOOLS: readonly string[];
|
|
1484
|
+
export declare function normalizeMechanicalTools(tools: readonly string[] | undefined): string[];
|
|
1485
|
+
/** The tool name a message carries, if any. Reads both hosts: `tool <name>`
|
|
1486
|
+
* (OpenCode), `[tool:<name>]` (core), `tool-call: <name>`, plus a JSON
|
|
1487
|
+
* payload that names the call. Lowercased, else undefined.
|
|
1488
|
+
*
|
|
1489
|
+
* A marker only counts at a block start: `entryToText` joins content blocks
|
|
1490
|
+
* with newlines, so a genuine call marker opens a line while prose quoting one
|
|
1491
|
+
* sits mid-line. The caller may pass the stored role: `user` and `custom` rows
|
|
1492
|
+
* never carry calls, and an `assistant` row mixing prose with a call keeps the
|
|
1493
|
+
* prose on the summarizer path (tool-only rows still skip). */
|
|
1494
|
+
export declare function mechanicalToolNameOf(message: {
|
|
1495
|
+
text: string;
|
|
1496
|
+
payload?: string;
|
|
1497
|
+
role?: string;
|
|
1498
|
+
}): string | undefined;
|
|
1499
|
+
/** Normalized here, so callers may pass raw config values. */
|
|
1500
|
+
export declare function isMechanicalToolMessage(message: {
|
|
1501
|
+
text: string;
|
|
1502
|
+
payload?: string;
|
|
1503
|
+
role?: string;
|
|
1504
|
+
}, tools: readonly string[]): boolean;
|
|
1443
1505
|
/** The engine config for these options. An unresolved budget keeps the core
|
|
1444
1506
|
* default, which is also what a direct caller that passes no options gets. */
|
|
1445
1507
|
export declare function summarizerConfig(options: SummarizerOptions): SummarizerConfig;
|
|
@@ -1674,6 +1736,8 @@ export interface CompactionInput {
|
|
|
1674
1736
|
targetTokens?: number;
|
|
1675
1737
|
/** Where the returned summary must reach back to; defaults to the span start. */
|
|
1676
1738
|
frontierFrom?: string;
|
|
1739
|
+
/** Read at compaction time only; ingest stores every message verbatim. */
|
|
1740
|
+
mechanicalTools?: readonly string[];
|
|
1677
1741
|
}
|
|
1678
1742
|
export type CompactionOutcome = {
|
|
1679
1743
|
kind: "stored";
|
|
@@ -1681,6 +1745,10 @@ export type CompactionOutcome = {
|
|
|
1681
1745
|
leafSummaryIds: number[];
|
|
1682
1746
|
condensedSummaryIds: number[];
|
|
1683
1747
|
ingested: number;
|
|
1748
|
+
/** Leaves stored without a model call on the configured mechanical path. */
|
|
1749
|
+
mechanicalLeaves?: number;
|
|
1750
|
+
/** Condensed nodes built without a model call from mechanical children. */
|
|
1751
|
+
mechanicalCondensed?: number;
|
|
1684
1752
|
} |
|
|
1685
1753
|
/** No text, and why. A span another live run claimed, a span an existing node
|
|
1686
1754
|
* already covers, and a span the store holds no row for are all states a pass
|
|
@@ -1705,6 +1773,8 @@ export declare function runCompaction(store: PassStore, input: CompactionInput,
|
|
|
1705
1773
|
session?: string;
|
|
1706
1774
|
maxDepth?: number;
|
|
1707
1775
|
stage?: CompactionStage;
|
|
1776
|
+
/** Empty keeps the LLM path. */
|
|
1777
|
+
mechanicalTools?: readonly string[];
|
|
1708
1778
|
}): Promise<CompactionOutcome>;
|
|
1709
1779
|
/** The next group to condense: the oldest run of adjacent same-depth nodes, at
|
|
1710
1780
|
* the shallowest depth with a run of two or more, capped at MAX_DAG_FANOUT.
|
|
@@ -1820,7 +1890,7 @@ export interface CompactionBounds {
|
|
|
1820
1890
|
* not message text, so bash and branch-summary rows align. An unknown
|
|
1821
1891
|
* firstKeptEntryId yields an empty span, so the caller falls back to Pi. */
|
|
1822
1892
|
export declare function resolveCompactionSpan(branchMsgs: readonly AlignedEntry[], bounds: CompactionBounds): AlignedEntry[];
|
|
1823
|
-
export type FindingKind = "fts-index" | "summary-span" | "summary-shape" | "orphan-child" | "duplicate-span" | "foreign-key" | "schema-version" | "dead-run" | "coverage";
|
|
1893
|
+
export type FindingKind = "fts-index" | "summary-span" | "summary-shape" | "orphan-child" | "duplicate-span" | "foreign-key" | "schema-version" | "dead-run" | "orphan-sidecar" | "coverage";
|
|
1824
1894
|
export interface Finding {
|
|
1825
1895
|
kind: FindingKind;
|
|
1826
1896
|
/** `violation` is an invariant the DAG depends on; `coverage` is a count. */
|
|
@@ -1834,7 +1904,7 @@ export interface IntegrityReport {
|
|
|
1834
1904
|
checks: number;
|
|
1835
1905
|
findings: Finding[];
|
|
1836
1906
|
}
|
|
1837
|
-
export declare function checkIntegrity(store: LcmStore): IntegrityReport;
|
|
1907
|
+
export declare function checkIntegrity(store: LcmStore, opts?: IntegritySnapshotOptions): IntegrityReport;
|
|
1838
1908
|
/** Fix what can be fixed without guessing: the derived index, rows whose span no
|
|
1839
1909
|
* longer exists, nodes whose child no longer resolves, rows a run whose writer is
|
|
1840
1910
|
* gone left behind, and predated duplicate spans. An inverted span is left
|
|
@@ -2328,6 +2398,40 @@ export type ViewResult = {
|
|
|
2328
2398
|
ok: false;
|
|
2329
2399
|
text: string;
|
|
2330
2400
|
};
|
|
2401
|
+
declare const LCM_ROLES: readonly ["user", "assistant", "toolResult", "custom"];
|
|
2402
|
+
type GrepFilter = {
|
|
2403
|
+
role?: (typeof LCM_ROLES)[number];
|
|
2404
|
+
dateStart?: number;
|
|
2405
|
+
dateEnd?: number;
|
|
2406
|
+
toolName?: string;
|
|
2407
|
+
};
|
|
2408
|
+
/** The `[tool:Name]` marker in front of a tool call's arguments, so a scoped
|
|
2409
|
+
* search needs no table or index. */
|
|
2410
|
+
export declare function toolMarker(toolName: string): string;
|
|
2411
|
+
/** Quote a string as one FTS5 phrase. Embedded quotes double; JSON.stringify
|
|
2412
|
+
* emits backslash escapes which FTS5 rejects. */
|
|
2413
|
+
export declare function ftsPhrase(text: string): string;
|
|
2414
|
+
/** Rewrite an FTS5 query to its tool-scoped form. The marker passes as a quoted
|
|
2415
|
+
* phrase, which the FTS5 tokenizer splits the same way as the stored text, so
|
|
2416
|
+
* prose with the same adjacent words (for example "which tool read the file")
|
|
2417
|
+
* can also match. Anchoring to the row start would miss mixed blocks because
|
|
2418
|
+
* entryToText appends blocks in order, so the scoped search keeps this broader
|
|
2419
|
+
* match and callers read the hit to confirm the tool. */
|
|
2420
|
+
export declare function withToolScope(query: string, toolName: string): string;
|
|
2421
|
+
/** Row ids a tool scope covers: the call rows that name the tool plus the
|
|
2422
|
+
* toolResult rows that follow them. Pi stores a call and its result in
|
|
2423
|
+
* separate rows, so a same-row `query AND marker` FTS misses a word found
|
|
2424
|
+
* only in the result. A trailing run of toolResult rows after a marker row
|
|
2425
|
+
* belongs to that call batch; any other role ends the run, as does a
|
|
2426
|
+
* toolResult row that names a different tool. Bracket text is checked
|
|
2427
|
+
* directly so one row naming two tools anchors both, and
|
|
2428
|
+
* mechanicalToolNameOf covers the `tool <name>` and payload forms. User and
|
|
2429
|
+
* custom rows never open a scope, so quoting a marker in chat pulls in no
|
|
2430
|
+
* results; a mixed assistant block still opens through its literal marker. */
|
|
2431
|
+
export declare function toolScopeMessageIds(store: LcmStore, toolName: string, opts?: {
|
|
2432
|
+
includeRemoved?: boolean;
|
|
2433
|
+
withinMessageIds?: ReadonlySet<number>;
|
|
2434
|
+
}): Set<number>;
|
|
2331
2435
|
export declare function grepView(store: LcmStore, redact: (text: string) => string, params: {
|
|
2332
2436
|
query?: string;
|
|
2333
2437
|
pattern?: string;
|
|
@@ -2342,17 +2446,37 @@ export declare function grepView(store: LcmStore, redact: (text: string) => stri
|
|
|
2342
2446
|
now?: () => number;
|
|
2343
2447
|
/** Tool the continuation marker names. Defaults to `lcm_expand_query`. */
|
|
2344
2448
|
expandTool?: string;
|
|
2449
|
+
role?: GrepFilter["role"];
|
|
2450
|
+
dateStart?: number;
|
|
2451
|
+
dateEnd?: number;
|
|
2452
|
+
/** Query searches only; with a pattern it is refused. */
|
|
2453
|
+
toolName?: string;
|
|
2345
2454
|
}): ViewResult;
|
|
2455
|
+
/** A scoped FTS search that stays complete. `store.grep` applies its SQL
|
|
2456
|
+
* LIMIT before it intersects the id set, so one bounded call can miss rows
|
|
2457
|
+
* that rank past the window. The unscoped count bounds the rank order, so one
|
|
2458
|
+
* fetch of that size holds every in-scope match and the caller pages the
|
|
2459
|
+
* filtered set. Rank order is preserved. Throws on invalid FTS5 syntax, like
|
|
2460
|
+
* `store.grep`, so callers keep their quoted-phrase fallback. */
|
|
2461
|
+
export declare function scopedGrepAll(store: LcmStore, pattern: string, opts: {
|
|
2462
|
+
includeRemoved: boolean;
|
|
2463
|
+
role?: GrepFilter["role"];
|
|
2464
|
+
dateStart?: number;
|
|
2465
|
+
dateEnd?: number;
|
|
2466
|
+
scoped: ReadonlySet<number>;
|
|
2467
|
+
}): ReturnType<LcmStore["grep"]>;
|
|
2346
2468
|
export declare function describeView(store: LcmStore, redact: (text: string) => string, id: number): ViewResult;
|
|
2347
|
-
/** List
|
|
2348
|
-
*
|
|
2349
|
-
* entry
|
|
2469
|
+
/** List a summary's messages, or read one as a window. Without a summary an
|
|
2470
|
+
* entry id reads directly; with `anchor` and offset 0 the window centers on
|
|
2471
|
+
* that entry, clamped at the span edges. A nonzero offset with `anchor` is an
|
|
2472
|
+
* absolute message index, so the next page starts from the reported offset. */
|
|
2350
2473
|
export type ExpandParams = {
|
|
2351
2474
|
mode: "list";
|
|
2352
2475
|
id: number;
|
|
2353
2476
|
offset: number;
|
|
2354
2477
|
limit: number;
|
|
2355
2478
|
maxChars: number;
|
|
2479
|
+
anchor?: string;
|
|
2356
2480
|
} | {
|
|
2357
2481
|
mode: "message";
|
|
2358
2482
|
id?: number;
|
|
@@ -2361,7 +2485,20 @@ export type ExpandParams = {
|
|
|
2361
2485
|
maxChars: number;
|
|
2362
2486
|
};
|
|
2363
2487
|
export declare function expandView(store: LcmStore, redact: (text: string) => string, params: ExpandParams): ViewResult;
|
|
2364
|
-
|
|
2488
|
+
/** Sort headers the caller already holds, so FTS plus regex stay the recall
|
|
2489
|
+
* path and no score is stored. Ties keep input order. */
|
|
2490
|
+
export declare function orderSummariesByOverlap<T extends {
|
|
2491
|
+
text: string;
|
|
2492
|
+
}>(query: string, nodes: readonly T[]): T[];
|
|
2493
|
+
/** At or above this length with no linked file a body reads as `large-inline`,
|
|
2494
|
+
* matching the ingest default, so view and writer agree. */
|
|
2495
|
+
export declare const LARGE_INLINE_CHARS = 32000;
|
|
2496
|
+
/** A read-only files manifest, built at read time, so nothing is stored and
|
|
2497
|
+
* no model is called. */
|
|
2498
|
+
export declare function filesView(store: LcmStore, redact: (text: string) => string, opts?: {
|
|
2499
|
+
summaryId?: number;
|
|
2500
|
+
}): ViewResult;
|
|
2501
|
+
export declare function historyManifest(store: LcmStore, limit: number, query?: string): string;
|
|
2365
2502
|
/** Redactor that re-reads the flag on every call, so a cockpit toggle takes
|
|
2366
2503
|
* effect immediately: a getter, because patchConfig replaces the config object
|
|
2367
2504
|
* and closing over it would pin the session-start value. */
|
|
@@ -2508,6 +2645,10 @@ export declare function searchSessions(refs: readonly SessionRef[], query: strin
|
|
|
2508
2645
|
deadlineMs?: number;
|
|
2509
2646
|
perSession?: number;
|
|
2510
2647
|
now?: () => number;
|
|
2648
|
+
role?: "user" | "assistant" | "toolResult" | "custom";
|
|
2649
|
+
dateStart?: number;
|
|
2650
|
+
dateEnd?: number;
|
|
2651
|
+
toolName?: string;
|
|
2511
2652
|
}): SessionSearchResult;
|
|
2512
2653
|
export declare const SEARCH_SCOPE_HELP = "session (default) searches this session. sessions searches past sessions in this project's working directory. all_sessions searches past sessions in every project. A cross-session hit is a pointer labelled [lcm:session <hash>] that lcm_expand_query({session, entry_id}) reads, so a past session's text is never injected into the context on its own.";
|
|
2513
2654
|
/** The cross-session hits as one labelled block, plus what the scan did not read.
|