@autorag/librarian 2.13.7 → 2.13.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +15 -0
  2. package/dist/agent/agent.d.ts +31 -1
  3. package/dist/agent/calculator-tool.d.ts +39 -0
  4. package/dist/agent/evidence-ledger.d.ts +11 -0
  5. package/dist/agent/index-schedule.d.ts +45 -0
  6. package/dist/agent/index.d.ts +1 -0
  7. package/dist/agent/result-render.d.ts +43 -0
  8. package/dist/agent/search-all-tool.d.ts +2 -1
  9. package/dist/agent/search-minsync-tool.d.ts +2 -1
  10. package/dist/agent/search-single-datasource-tool.d.ts +2 -1
  11. package/dist/agent/watch-refresh.d.ts +2 -0
  12. package/dist/calculator/civil.d.ts +27 -0
  13. package/dist/calculator/decimal.d.ts +47 -0
  14. package/dist/calculator/errors.d.ts +4 -0
  15. package/dist/calculator/expression.d.ts +11 -0
  16. package/dist/calculator/index.d.ts +17 -0
  17. package/dist/calculator/operations.d.ts +36 -0
  18. package/dist/calculator/temporal.d.ts +18 -0
  19. package/dist/calculator/timezone.d.ts +19 -0
  20. package/dist/cli/commands/index.d.ts +1 -1
  21. package/dist/cli/commands/lite-refresh.d.ts +1 -1
  22. package/dist/cli/commands/refresh.d.ts +4 -0
  23. package/dist/cli/commands/watch.d.ts +2 -1
  24. package/dist/cli/index.js +2278 -255
  25. package/dist/cli/signal-abort.d.ts +21 -0
  26. package/dist/core.d.ts +2 -0
  27. package/dist/core.js +2108 -181
  28. package/dist/index.js +2144 -220
  29. package/dist/mcp/index.js +2143 -220
  30. package/dist/minsync/method.d.ts +7 -0
  31. package/dist/mirror/sync.d.ts +9 -0
  32. package/dist/profiles.js +2131 -209
  33. package/dist/retrieval/engine.d.ts +7 -0
  34. package/dist/retrieval/merger.d.ts +6 -0
  35. package/dist/retrieval/record-cut.d.ts +101 -0
  36. package/package.json +1 -1
  37. package/skills/autorag/SKILL.md +28 -0
  38. package/skills/autorag-setup/SKILL.md +39 -0
package/README.md CHANGED
@@ -207,6 +207,7 @@ AutoRAG Agent orchestrates five integrated subsystems:
207
207
  - **Jikji Find-First Discovery:** Local CLI-backed fast discovery answer packs.
208
208
  - **Everything File-Name Search (Windows):** The bundled [voidtools Everything](https://www.voidtools.com/) indexes file and folder names under your search roots so the agent finds files by name, extension, path, size, or date instantly (`everything_search`).
209
209
  - **FSearch File-Name Search (macOS/Linux):** [fsearch-cli](https://github.com/NomaDamas/fsearch-mac) (FSearch) keeps a live, per-workspace name index of your search roots so the agent finds files by name, extension, path, size, or date instantly (`fsearch_search`); without fsearch-cli installed it degrades to a slow filesystem walk.
210
+ - **Calculator:** Exact decimal arithmetic (40 significant digits, no floating-point drift) plus calendar and clock math — days between dates, date offsets with month-end clamping, weekdays, ISO weeks, business days with holidays, the current time, and DST-aware time zone conversion — through the `calculator` tool. The system prompt, including the fast-answer phase, orders the model to compute every number and date with it instead of in its head. It runs in-process, reads no files, and needs no configuration.
210
211
  - **Datasource Skills:** Federated retrieval across every configured external datasource.
211
212
  3. **Result Merger & Scope Narrowing:** Cross-method deduplication, score normalization, and ordinary query-scope narrowing.
212
213
  4. **Direct Evidence Reading (`bash`):** The agent directly opens and inspects promising files with `cat`, `grep`, or `find` to verify facts against ground truth.
@@ -286,6 +287,20 @@ autorag refresh
286
287
  autorag status
287
288
  ```
288
289
 
290
+ ### Indexing only when you want it (power and time schedule)
291
+
292
+ Background indexing (`autorag watch`, auto-refresh, the fs watcher) can be limited by power source and local time. An explicit `autorag refresh` is never gated.
293
+
294
+ ```jsonc
295
+ // ~/.autorag/config.json
296
+ { "refresh": { "schedule": { "power": "ac", "windows": ["22:00-07:00"], "days": ["mon","tue","wed","thu","fri"] } } }
297
+ ```
298
+
299
+ - `power`: `any` (default) or `ac` (index only while plugged in; pauses on battery). An unknown power source (desktop, probe failure) counts as plugged in.
300
+ - `windows`: local `HH:MM-HH:MM`, start inclusive, end exclusive; `22:00-07:00` wraps midnight and belongs to the day it starts on.
301
+ - `days`: `sun`..`sat`. Omit for every day.
302
+ - `autorag watch --power ac --window 22:00-07:00 --days mon,tue` overrides the config. `--once` while closed prints `skipped` and exits 0; a long-running watcher defers changes and indexes once the schedule opens.
303
+
289
304
  ### Excluding files and folders
290
305
 
291
306
  Leave generated workspaces or archives out when initializing:
@@ -14,12 +14,14 @@ import { type MinSyncSyncProgress, type MinSyncSyncResult, type MinSyncVectorMet
14
14
  import { type ParsedMirrorSyncOptions, type ParsedMirrorSyncResult } from "../mirror/sync.js";
15
15
  import { type DefaultParserRegistryOptions } from "../parser/index.js";
16
16
  import { RetrievalEngine } from "../retrieval/engine.js";
17
+ import { type RecordCutOptions } from "../retrieval/record-cut.js";
17
18
  import { RetrievalMethodRegistry } from "../retrieval/registry.js";
18
19
  import type { DatasourceCatalogEntry } from "../retrieval/selection.js";
19
20
  import type { RetrievalDiagnostic, RetrievalOptions, RetrievalResult } from "../retrieval/types.js";
20
21
  import { type ConvertFilesDetails } from "./convert-tool.js";
21
22
  import { type DatasourceAgentSkill } from "./datasource-skill.js";
22
23
  import { type ScanDuplicateDocumentsDetails } from "./dupey-tool.js";
24
+ import { type IndexSchedule, type ScheduleDecision } from "./index-schedule.js";
23
25
  import { type JevToolOptions } from "./jev-extension.js";
24
26
  import { type JikjiFindProviderResult } from "./jikji-find-tool.js";
25
27
  import { type PackagedAgentSkill } from "./packaged-skill.js";
@@ -65,6 +67,12 @@ export interface AutoRAGRefreshLimits {
65
67
  * disk and `cloud-evict-failed` is reported. `0` tries once. Default 3.
66
68
  */
67
69
  readonly cloudEvictRetries?: number;
70
+ /**
71
+ * When background indexing (auto-refresh, fs watch, `autorag watch`) may run: power (`any`/`ac`),
72
+ * local-time `windows` (`HH:MM-HH:MM`) and weekdays. Omitted = always.
73
+ * An explicit `refresh()` call is never gated. See {@link IndexSchedule}.
74
+ */
75
+ readonly schedule?: IndexSchedule;
68
76
  }
69
77
  /**
70
78
  * Hard caps on retrieval, baseline prefetch, and the candidate lists handed to
@@ -99,6 +107,13 @@ export interface AutoRAGRetrievalLimits {
99
107
  /** Max results rendered per baseline section. Default 100. */
100
108
  readonly sectionLimit?: number;
101
109
  };
110
+ /**
111
+ * Spread each search's hits across documents instead of cutting by chunk, so one long document cannot take
112
+ * every slot (PipesHub's FUSION_RECORD_CUT). Off unless `enabled` is true: when on, MinSync and the merger ask
113
+ * for `depth` x the requested count, a chunk shown earlier in the run is not resent, and each search result
114
+ * is held to `resultChars` with the budget split fairly across its chunks.
115
+ */
116
+ readonly recordCut?: RecordCutOptions;
102
117
  }
103
118
  export interface AutoRefreshOptions {
104
119
  readonly intervalMs: number;
@@ -215,6 +230,10 @@ export interface AutoRAGWatchRefreshOptions {
215
230
  readonly debounceMs?: number;
216
231
  readonly force?: boolean;
217
232
  readonly maxWatchers?: number;
233
+ /** Replaces the configured `refresh.schedule` for this watcher. */
234
+ readonly schedule?: IndexSchedule;
235
+ /** How often a watcher with a closed schedule re-checks it (default 60000). */
236
+ readonly scheduleRecheckMs?: number;
218
237
  /** Injectable watcher factory (defaults to a recursive fs.watch). Primarily for tests. */
219
238
  readonly watcherFactory?: WatcherFactory;
220
239
  }
@@ -727,6 +746,11 @@ export declare class AutoRAGAgent {
727
746
  immediate?: boolean;
728
747
  }): void;
729
748
  stopAutoRefresh(): void;
749
+ /**
750
+ * Whether the configured index schedule lets a background refresh run now. `override` replaces the
751
+ * configured schedule (CLI flags). Probes the power source only when the policy depends on it.
752
+ */
753
+ indexScheduleDecision(override?: IndexSchedule, now?: Date): Promise<ScheduleDecision>;
730
754
  private runAutoRefreshTick;
731
755
  searchDocuments(query: string, options?: RetrievalOptions): Promise<SearchDocumentsResponse>;
732
756
  /**
@@ -954,10 +978,16 @@ export declare class AutoRAGAgent {
954
978
  private defaultWatcherFactory;
955
979
  syncParsedMirrors(force?: boolean, options?: Pick<ParsedMirrorSyncOptions, "signal" | "onProgress" | "retrySkipped" | "onBatch" | "batchSize">): Promise<ParsedMirrorSyncResult>;
956
980
  /**
957
- * Lightweight stat-only staleness scan used when `refresh` is called with
981
+ * Lightweight stat-only staleness scan used by status and when `refresh` is called with
958
982
  * methods that exclude parsed mirrors (e.g. only `datasources` or `jikji`).
959
983
  * Returns a zero-count `ParsedMirrorSyncResult` carrying fresh diagnostics
960
984
  * so the refresh result and status remain consistent.
985
+ *
986
+ * It never runs a duplicate scan: that reads every file under every root and costs seconds
987
+ * on a large corpus. It reuses the exclusions the last refresh recorded instead, so it
988
+ * differs from a fresh scan in two narrow ways: an indexed file that has since become an
989
+ * older exact duplicate is not reported (the next refresh drops it), and a newly added file
990
+ * that is already a duplicate is reported stale until the next refresh excludes it.
961
991
  */
962
992
  private scanMirrorStaleness;
963
993
  /** The machine's non-physical roots, resolved once; a probe failure reads as no roots, never an error. */
@@ -0,0 +1,39 @@
1
+ import type { AgentTool } from "@earendil-works/pi-agent-core";
2
+ import { Type } from "typebox";
3
+ export declare const CALCULATOR_TOOL_NAME = "calculator";
4
+ /** The standing order every prompt repeats: calculations belong to the tool, never to the model. */
5
+ export declare const CALCULATOR_PROMPT_RULE = "Never do arithmetic, date, time, or time zone math yourself: use calculator for every sum, percentage, average, unit conversion, day count, date offset, weekday, and \"what time is it in\u2026\", and copy its result unchanged. The current date in your instructions is a starting point, not a substitute for the tool.";
6
+ /** The fast phase forbids tools; this carves out the one that reads no sources and cannot slow the answer down. */
7
+ export declare const CALCULATOR_FAST_PHASE_RULE = "calculator is allowed: Never do arithmetic, date, time, or time zone math yourself: use calculator for every sum, percentage, average, unit conversion, day count, date offset, weekday, and \"what time is it in\u2026\", and copy its result unchanged. The current date in your instructions is a starting point, not a substitute for the tool.";
8
+ export interface CalculatorToolOptions {
9
+ /** The instant "now" and "today" mean. Tests pin it; the default reads the system clock on every call. */
10
+ readonly now?: () => Date;
11
+ /** Zone used when a call names none. Defaults to the host's zone. */
12
+ readonly hostTimeZone?: string;
13
+ }
14
+ declare const calculatorSchema: Type.TObject<{
15
+ operation: Type.TEnum<["evaluate", "now", "date_diff", "date_add", "date_info", "convert_timezone", "business_days_between", "add_business_days"]>;
16
+ expression: Type.TOptional<Type.TString>;
17
+ timeZone: Type.TOptional<Type.TString>;
18
+ toTimeZone: Type.TOptional<Type.TString>;
19
+ date: Type.TOptional<Type.TString>;
20
+ datetime: Type.TOptional<Type.TString>;
21
+ from: Type.TOptional<Type.TString>;
22
+ to: Type.TOptional<Type.TString>;
23
+ years: Type.TOptional<Type.TInteger>;
24
+ months: Type.TOptional<Type.TInteger>;
25
+ weeks: Type.TOptional<Type.TInteger>;
26
+ days: Type.TOptional<Type.TInteger>;
27
+ hours: Type.TOptional<Type.TInteger>;
28
+ minutes: Type.TOptional<Type.TInteger>;
29
+ seconds: Type.TOptional<Type.TInteger>;
30
+ holidays: Type.TOptional<Type.TArray<Type.TString>>;
31
+ inclusive: Type.TOptional<Type.TBoolean>;
32
+ }>;
33
+ export type CalculatorDetails = Record<string, string | number | boolean>;
34
+ /**
35
+ * The model's calculator: exact decimal arithmetic and calendar/clock math. Language models miscount days,
36
+ * drop digits and forget daylight saving, so every numeric or date answer comes from this tool, not from the model.
37
+ */
38
+ export declare function createCalculatorTool(options?: CalculatorToolOptions): AgentTool<typeof calculatorSchema, CalculatorDetails>;
39
+ export {};
@@ -77,6 +77,17 @@ export declare class EvidenceLedger {
77
77
  * at e1 would let a stale id silently resolve to a different chunk.
78
78
  */
79
79
  private lastOrdinal;
80
+ /** Ids whose text a search tool already put in front of the model during the current run. */
81
+ private readonly shown;
82
+ /** Whether a search already showed this evidence's text in the current run. */
83
+ hasShown(id: string): boolean;
84
+ /** Record that this evidence's text reached the model; returns whether it had already. */
85
+ markShown(id: string): boolean;
86
+ /**
87
+ * Start a run: nothing has been shown yet. A new question may follow a compaction that dropped the
88
+ * earlier tool output, so a repeat is only ever "already shown" within one run.
89
+ */
90
+ beginRun(): void;
80
91
  /** Record evidence and return its id. The same chunk always gets the same id. */
81
92
  register(input: LedgerEvidenceInput): string;
82
93
  /** Record one retrieval result as returned by `tool`; backend metadata is carried over. */
@@ -0,0 +1,45 @@
1
+ export type PowerPolicy = "any" | "ac";
2
+ export type PowerSource = "ac" | "battery" | "unknown";
3
+ export type ScheduleDay = "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat";
4
+ export interface IndexSchedule {
5
+ /** `any` (default) ignores power; `ac` pauses while on battery and runs only when plugged in. */
6
+ readonly power?: PowerPolicy;
7
+ /** Local-time windows `HH:MM-HH:MM`; indexing is allowed inside any of them. Omitted = all day. */
8
+ readonly windows?: readonly string[];
9
+ /** Local weekdays indexing is allowed on. Omitted = every day. */
10
+ readonly days?: readonly ScheduleDay[];
11
+ }
12
+ export type ScheduleDenyReason = "battery" | "outside-window" | "outside-day";
13
+ export type ScheduleDecision = {
14
+ readonly allowed: true;
15
+ } | {
16
+ readonly allowed: false;
17
+ readonly reason: ScheduleDenyReason;
18
+ };
19
+ /** Validate and normalize a raw `refresh.schedule` value. Throws a plain Error naming the field. */
20
+ export declare function validateIndexSchedule(raw: unknown): IndexSchedule;
21
+ /** Decide whether a background refresh may run at `now` given the detected `source`. */
22
+ export declare function evaluateIndexSchedule(schedule: IndexSchedule | undefined, now: Date, source: PowerSource): ScheduleDecision;
23
+ /** Map raw probe output to a power source. Returns `unknown` for anything unrecognized. */
24
+ export declare function parsePowerSourceOutput(platform: string, output: string): PowerSource;
25
+ export interface PowerProbeDeps {
26
+ readonly platform?: NodeJS.Platform;
27
+ /** Run a command and return stdout. */
28
+ readonly run?: (command: string, args: readonly string[]) => Promise<string>;
29
+ readonly read?: (path: string) => Promise<string>;
30
+ readonly list?: (dir: string) => Promise<string[]>;
31
+ }
32
+ /** Detect the current power source. Never throws: any probe failure yields `unknown`. */
33
+ export declare function detectPowerSource(deps?: PowerProbeDeps): Promise<PowerSource>;
34
+ export interface CheckIndexScheduleOptions {
35
+ readonly now?: Date;
36
+ /** Replaces the platform power probe (tests). */
37
+ readonly detect?: () => Promise<PowerSource>;
38
+ }
39
+ /**
40
+ * Decide from a raw config object (`refresh.schedule`) whether a background refresh may run now. For hosts
41
+ * that run their own scheduler, such as the desktop app's OS job. Probes the power source only when the policy
42
+ * asks for AC. A malformed schedule fails open: a bad edit must not silently stop indexing, and the config
43
+ * loader already rejects it loudly where the user can see it.
44
+ */
45
+ export declare function checkIndexSchedule(rawConfig: Record<string, unknown>, options?: CheckIndexScheduleOptions): Promise<ScheduleDecision>;
@@ -1,5 +1,6 @@
1
1
  export type { AutoRAGAgentOptions, AutoRefreshOptions } from "./agent.js";
2
2
  export { AutoRAGAgent } from "./agent.js";
3
+ export { CALCULATOR_FAST_PHASE_RULE, CALCULATOR_PROMPT_RULE, CALCULATOR_TOOL_NAME, type CalculatorDetails, type CalculatorToolOptions, createCalculatorTool, } from "./calculator-tool.js";
3
4
  export { CONVERT_FILES_TOOL_NAME, type ConvertFilesDetails, createConvertFilesTool, createListFileConversionsTool, type FileConversionProvider, LIST_FILE_CONVERSIONS_TOOL_NAME, } from "./convert-tool.js";
4
5
  export { buildDatasourceSkillsPrompt, createLoadDatasourceSkillTool, type DatasourceSkillProvider, datasourceSkillLocation, formatDatasourceSkillInvocation, LOAD_DATASOURCE_SKILL_TOOL_NAME, type LoadDatasourceSkillDetails, toDatasourceAgentSkill, } from "./datasource-skill.js";
5
6
  export { DECISION_PROVIDER_DEFAULT_MODELS, type DecisionModelRuntime, PiDecisionBackend, type PiDecisionBackendOptions, } from "./decision-backends.js";
@@ -0,0 +1,43 @@
1
+ import type { RecordCut } from "../retrieval/record-cut.js";
2
+ import type { RetrievalResult } from "../retrieval/types.js";
3
+ import type { EvidenceLedger } from "./evidence-ledger.js";
4
+ /** One retrieved chunk as a search tool shows it to the model. */
5
+ export interface EvidenceRow {
6
+ /** Ledger id, cited as `[eN]`. */
7
+ readonly id: string;
8
+ /** Everything after the id on the first line: source, score, location. */
9
+ readonly header: string;
10
+ readonly content: string;
11
+ /** A search earlier in this run already put this chunk's text in front of the model. */
12
+ readonly repeat: boolean;
13
+ }
14
+ export interface RenderedEvidence {
15
+ readonly text: string;
16
+ /** Ids whose text is in `text`; the caller marks these as shown so a later search does not resend them. */
17
+ readonly delivered: ReadonlySet<string>;
18
+ }
19
+ export declare const REPEAT_NOTE = "(already shown earlier in this run; text not repeated)";
20
+ export declare const NOT_READ_NOTE = "(not read: result budget used up; narrow the query to read it)";
21
+ /**
22
+ * Render search results for the model.
23
+ *
24
+ * Without a record cut every row is shown in full, exactly as before. With one,
25
+ * a chunk an earlier search of this run already showed is named without its
26
+ * text, and the rest share `recordCut.resultChars` max-min fairly: a long chunk
27
+ * is cut and says how much, a short one keeps all of it, and when the budget
28
+ * cannot give every chunk a useful share the lowest-ranked ones are listed as
29
+ * not read rather than every chunk being clipped to a stub.
30
+ */
31
+ export declare function renderEvidenceRows(rows: readonly EvidenceRow[], recordCut: RecordCut | undefined): RenderedEvidence;
32
+ /** Options a search tool takes for the record cut; absent means the legacy rendering. */
33
+ export interface RecordCutToolOptions {
34
+ readonly recordCut?: RecordCut;
35
+ }
36
+ /**
37
+ * Register `results` in the ledger and render them. With a record cut, a chunk an earlier search of this run
38
+ * already showed is not resent, and only chunks whose text reached the model are marked as shown.
39
+ */
40
+ export declare function registerAndRender(ledger: EvidenceLedger, tool: string, results: readonly RetrievalResult[], header: (result: RetrievalResult) => string, recordCut: RecordCut | undefined): {
41
+ readonly evidenceIds: string[];
42
+ readonly text: string;
43
+ };
@@ -2,6 +2,7 @@ import type { AgentTool } from "@earendil-works/pi-agent-core";
2
2
  import { Type } from "typebox";
3
3
  import type { RetrievalDiagnostic, RetrievalResult } from "../retrieval/types.js";
4
4
  import { EvidenceLedger } from "./evidence-ledger.js";
5
+ import { type RecordCutToolOptions } from "./result-render.js";
5
6
  import { type SearchDocumentRetrievalTraceResult } from "./search-documents.js";
6
7
  export declare const SEARCH_ALL_DOCUMENTS_TOOL_NAME = "search_all_documents";
7
8
  declare const searchAllSchema: Type.TObject<{
@@ -36,5 +37,5 @@ export interface SearchAllDocumentsDetails {
36
37
  * properties are not part of the schema and are never forwarded to the
37
38
  * provider — only `query`, `topK`, and `scope` are passed through.
38
39
  */
39
- export declare function createSearchAllDocumentsTool(provider: SearchAllDocumentsProvider, ledger?: EvidenceLedger): AgentTool<typeof searchAllSchema, SearchAllDocumentsDetails>;
40
+ export declare function createSearchAllDocumentsTool(provider: SearchAllDocumentsProvider, ledger?: EvidenceLedger, options?: RecordCutToolOptions): AgentTool<typeof searchAllSchema, SearchAllDocumentsDetails>;
40
41
  export {};
@@ -2,6 +2,7 @@ import type { AgentTool } from "@earendil-works/pi-agent-core";
2
2
  import { Type } from "typebox";
3
3
  import type { MinSyncVectorMethod } from "../minsync/method.js";
4
4
  import { EvidenceLedger } from "./evidence-ledger.js";
5
+ import { type RecordCutToolOptions } from "./result-render.js";
5
6
  import { type SearchDocumentRetrievalTraceResult } from "./search-documents.js";
6
7
  export declare const SEARCH_MINSYNC_DOCUMENTS_TOOL_NAME = "semantic_search_local_docs";
7
8
  declare const searchMinSyncSchema: Type.TObject<{
@@ -23,5 +24,5 @@ export interface SearchMinSyncDocumentsDetails {
23
24
  * into an "unavailable" result: the error propagates with its own message and
24
25
  * the harness reports it as a failed tool call.
25
26
  */
26
- export declare function createSearchMinSyncDocumentsTool(getMethod: () => MinSyncVectorMethod, resolveScope?: (scope: string | undefined) => string | undefined, ledger?: EvidenceLedger): AgentTool<typeof searchMinSyncSchema, SearchMinSyncDocumentsDetails>;
27
+ export declare function createSearchMinSyncDocumentsTool(getMethod: () => MinSyncVectorMethod, resolveScope?: (scope: string | undefined) => string | undefined, ledger?: EvidenceLedger, options?: RecordCutToolOptions): AgentTool<typeof searchMinSyncSchema, SearchMinSyncDocumentsDetails>;
27
28
  export {};
@@ -2,6 +2,7 @@ import type { AgentTool } from "@earendil-works/pi-agent-core";
2
2
  import { Type } from "typebox";
3
3
  import type { RetrievalDiagnostic, RetrievalResult } from "../retrieval/types.js";
4
4
  import { EvidenceLedger } from "./evidence-ledger.js";
5
+ import { type RecordCutToolOptions } from "./result-render.js";
5
6
  import { type SearchDocumentRetrievalTraceResult } from "./search-documents.js";
6
7
  /**
7
8
  * Per-datasource search tools.
@@ -54,7 +55,7 @@ export interface SearchSingleDatasourceDetails {
54
55
  /** Top candidates in traceable shape (additive; used for the run's retrieval trace). */
55
56
  readonly results?: readonly SearchDocumentRetrievalTraceResult[];
56
57
  }
57
- export declare function createSingleDatasourceSearchTools(provider: SingleDatasourceSearchProvider, specs: readonly SingleDatasourceToolSpec[], ledger?: EvidenceLedger): AgentTool<typeof searchSingleDatasourceSchema, SearchSingleDatasourceDetails>[];
58
+ export declare function createSingleDatasourceSearchTools(provider: SingleDatasourceSearchProvider, specs: readonly SingleDatasourceToolSpec[], ledger?: EvidenceLedger, options?: RecordCutToolOptions): AgentTool<typeof searchSingleDatasourceSchema, SearchSingleDatasourceDetails>[];
58
59
  declare const searchSingleDatasourceSchema: Type.TObject<{
59
60
  query: Type.TString;
60
61
  topK: Type.TOptional<Type.TInteger>;
@@ -24,6 +24,8 @@ export interface WatchRefreshDeps {
24
24
  readonly onLimit?: () => void;
25
25
  }
26
26
  export interface WatchRefreshHandle {
27
+ /** Schedule a (debounced) refresh as if a change had been seen, e.g. for a deferred initial refresh. */
28
+ trigger(): void;
27
29
  stop(): void;
28
30
  }
29
31
  export declare function createWatchRefresh(deps: WatchRefreshDeps): WatchRefreshHandle;
@@ -0,0 +1,27 @@
1
+ /** Proleptic Gregorian calendar arithmetic on whole days since 1970-01-01. No time zones, no `Date`. */
2
+ export declare const MS_PER_DAY = 86400000;
3
+ export declare const MIN_YEAR = 1;
4
+ export declare const MAX_YEAR = 9999;
5
+ export declare const WEEKDAYS: readonly ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
6
+ export interface Civil {
7
+ readonly y: number;
8
+ readonly m: number;
9
+ readonly d: number;
10
+ }
11
+ export declare function pad(value: number, width?: number): string;
12
+ export declare function floorDiv(a: number, b: number): number;
13
+ export declare function mod(a: number, b: number): number;
14
+ export declare function isLeapYear(y: number): boolean;
15
+ export declare function daysInMonth(y: number, m: number): number;
16
+ export declare function isRealDate(y: number, m: number, d: number): boolean;
17
+ /** Days since 1970-01-01 (Howard Hinnant's days_from_civil). */
18
+ export declare function daysFromCivil(y: number, m: number, d: number): number;
19
+ export declare function civilFromDays(days: number): Civil;
20
+ /** 1 = Monday … 7 = Sunday. 1970-01-01 was a Thursday. */
21
+ export declare function isoWeekday(days: number): number;
22
+ export declare function dayOfYear(c: Civil): number;
23
+ /** ISO 8601 week date, e.g. `2026-W45-7`. */
24
+ export declare function isoWeekDate(days: number): string;
25
+ /** Adds calendar months, clamping the day to the end of a shorter month (Jan 31 + 1 month = Feb 28). */
26
+ export declare function addMonths(c: Civil, months: number): Civil;
27
+ export declare function formatDate(days: number): string;
@@ -0,0 +1,47 @@
1
+ /** Significant digits every intermediate result keeps. */
2
+ export declare const WORK_DIGITS = 60;
3
+ /** Significant digits a final result keeps. */
4
+ export declare const RESULT_DIGITS = 40;
5
+ export declare const MAX_INTEGER_EXPONENT = 10000;
6
+ /** `n × 10^e`. Normalized: no trailing zeros in `n`, and zero is `{0n, 0}`. */
7
+ export interface Dec {
8
+ readonly n: bigint;
9
+ readonly e: number;
10
+ }
11
+ /** Whether any step rounded or approximated, so the answer is not the exact mathematical value. */
12
+ export interface Precision {
13
+ inexact: boolean;
14
+ }
15
+ export declare const ZERO: Dec;
16
+ export declare const ONE: Dec;
17
+ export type RoundingMode = "half-away" | "floor" | "ceil" | "trunc";
18
+ export declare function digitCount(n: bigint): number;
19
+ export declare function normalize(n: bigint, e: number): Dec;
20
+ export declare function parseDecimal(text: string): Dec;
21
+ export declare function fromInteger(value: number): Dec;
22
+ /** A finite double rounded to 15 significant digits: transcendental results are only that accurate. */
23
+ export declare function fromDouble(value: number, precision: Precision, name: string): Dec;
24
+ export declare function toDouble(value: Dec): number;
25
+ export declare function sign(value: Dec): -1 | 0 | 1;
26
+ export declare function negate(value: Dec): Dec;
27
+ export declare function isInteger(value: Dec): boolean;
28
+ /** Drops every digit below `10^target`, rounding as `mode` says. */
29
+ export declare function roundAtExponent(value: Dec, target: number, mode: RoundingMode, precision: Precision): Dec;
30
+ /** Rounds to `digits` significant digits, half away from zero. */
31
+ export declare function roundSignificant(value: Dec, digits: number, precision: Precision): Dec;
32
+ export declare function compare(a: Dec, b: Dec): -1 | 0 | 1;
33
+ export declare function add(a: Dec, b: Dec, precision: Precision): Dec;
34
+ export declare function subtract(a: Dec, b: Dec, precision: Precision): Dec;
35
+ export declare function multiply(a: Dec, b: Dec, precision: Precision): Dec;
36
+ export declare function divide(a: Dec, b: Dec, precision: Precision): Dec;
37
+ /** `a mod b` with the sign of `a`, like JavaScript's `%` but exact. */
38
+ export declare function remainder(a: Dec, b: Dec, precision: Precision): Dec;
39
+ /** Exact total of every term; only the final result is rounded. */
40
+ export declare function sumExact(terms: readonly Dec[], precision: Precision): Dec;
41
+ /** Square root to WORK_DIGITS digits; exact when the root is a terminating decimal. */
42
+ export declare function squareRoot(value: Dec, precision: Precision): Dec;
43
+ export declare function cubeRoot(value: Dec, precision: Precision): Dec;
44
+ /** `base ^ exponent`. Integer exponents are exact up to WORK_DIGITS; fractional ones are double precision. */
45
+ export declare function power(base: Dec, exponent: Dec, precision: Precision): Dec;
46
+ /** Plain digits up to 10^40, scientific notation beyond (and below 1e-7), trailing zeros trimmed. */
47
+ export declare function formatDecimal(value: Dec): string;
@@ -0,0 +1,4 @@
1
+ /** A calculation the calculator refuses: bad input or a result it cannot give honestly. The message is for the model. */
2
+ export declare class CalculatorError extends Error {
3
+ constructor(message: string);
4
+ }
@@ -0,0 +1,11 @@
1
+ import { digitCount, normalize, ZERO } from "./decimal.js";
2
+ export declare const MAX_EXPRESSION_LENGTH = 4096;
3
+ export interface ExpressionResult {
4
+ readonly expression: string;
5
+ readonly value: string | string[];
6
+ /** False when any step rounded or approximated, so the digits are the best 40-digit answer rather than the exact one. */
7
+ readonly exact: boolean;
8
+ }
9
+ /** Evaluates one expression, or one flat `[a, b, …]` list of expressions, with exact decimal arithmetic. */
10
+ export declare function evaluateExpression(source: string): ExpressionResult;
11
+ export { digitCount, normalize, ZERO };
@@ -0,0 +1,17 @@
1
+ import { type CalculatorRequest, type Fields } from "./operations.js";
2
+ export { CalculatorError } from "./errors.js";
3
+ export { MAX_EXPRESSION_LENGTH } from "./expression.js";
4
+ export type { CalculatorRequest, Fields } from "./operations.js";
5
+ export declare const CALCULATOR_OPERATIONS: readonly ["evaluate", "now", "date_diff", "date_add", "date_info", "convert_timezone", "business_days_between", "add_business_days"];
6
+ export interface CalculatorOptions {
7
+ /** The instant "now" and "today" mean. Defaults to the system clock. */
8
+ readonly now?: Date;
9
+ /** Zone used when the request names none. Defaults to the host's zone. */
10
+ readonly hostTimeZone?: string;
11
+ }
12
+ export interface CalculatorOutput {
13
+ readonly fields: Fields;
14
+ /** One `name: value` line per field: the text the model reads. */
15
+ readonly text: string;
16
+ }
17
+ export declare function calculate(request: CalculatorRequest, options?: CalculatorOptions): CalculatorOutput;
@@ -0,0 +1,36 @@
1
+ import { type Zone } from "./timezone.js";
2
+ export type FieldValue = string | number | boolean;
3
+ export type Fields = Record<string, FieldValue>;
4
+ export interface CalculatorRequest {
5
+ readonly operation: string;
6
+ readonly expression?: string;
7
+ /** Zone a date or time is read in and shown in; for convert_timezone, the source zone. */
8
+ readonly timeZone?: string;
9
+ readonly toTimeZone?: string;
10
+ readonly date?: string;
11
+ readonly datetime?: string;
12
+ readonly from?: string;
13
+ readonly to?: string;
14
+ readonly years?: number;
15
+ readonly months?: number;
16
+ readonly weeks?: number;
17
+ readonly days?: number;
18
+ readonly hours?: number;
19
+ readonly minutes?: number;
20
+ readonly seconds?: number;
21
+ readonly holidays?: readonly string[];
22
+ readonly inclusive?: boolean;
23
+ }
24
+ export interface Clock {
25
+ readonly now: Date;
26
+ readonly zone: Zone;
27
+ readonly zoneSource: "requested" | "host default";
28
+ }
29
+ export declare function need<T>(operation: string, name: string, value: T | undefined): T;
30
+ export declare function now(clock: Clock): Fields;
31
+ export declare function dateDiff(request: CalculatorRequest, clock: Clock): Fields;
32
+ export declare function dateAdd(request: CalculatorRequest, clock: Clock): Fields;
33
+ export declare function convertTimeZone(request: CalculatorRequest, clock: Clock, sourceGiven: boolean): Fields;
34
+ export declare function dateInfo(request: CalculatorRequest, clock: Clock): Fields;
35
+ export declare function businessDaysBetween(request: CalculatorRequest, clock: Clock): Fields;
36
+ export declare function addBusinessDays(request: CalculatorRequest, clock: Clock): Fields;
@@ -0,0 +1,18 @@
1
+ import { type Zone } from "./timezone.js";
2
+ /** A date with no time of day, or one instant on the timeline. */
3
+ export type Temporal = {
4
+ readonly kind: "date";
5
+ readonly days: number;
6
+ }
7
+ /** `zoneless` marks a wall-clock time that was placed in the zone by assumption, not by its own offset. */
8
+ | {
9
+ readonly kind: "instant";
10
+ readonly epochMs: number;
11
+ readonly zoneless: boolean;
12
+ };
13
+ export declare function todayIn(zone: Zone, now: Date): number;
14
+ export declare function parseTemporal(input: string, zone: Zone, now: Date): Temporal;
15
+ /** Calendar day of a value: a date as is, an instant as the date on the wall clock in `zone`. */
16
+ export declare function dayOf(value: Temporal, zone: Zone): number;
17
+ /** The instant of a value: a date means midnight in `zone`. */
18
+ export declare function instantOf(value: Temporal, zone: Zone): number;
@@ -0,0 +1,19 @@
1
+ /** A UTC offset in force at every instant (`fixed`, seconds), or an IANA zone whose offset changes over time. */
2
+ export interface Zone {
3
+ readonly name: string;
4
+ readonly fixed?: number;
5
+ }
6
+ export declare function formatOffset(seconds: number): string;
7
+ export declare function fixedZone(offsetSeconds: number): Zone;
8
+ export declare function parseZone(input: string): Zone;
9
+ /** Seconds east of UTC in force at `epochMs`. */
10
+ export declare function offsetAt(zone: Zone, epochMs: number): number;
11
+ /** Wall-clock time in the zone, as milliseconds counted from 1970-01-01T00:00 with no zone attached. */
12
+ export declare function toNaive(zone: Zone, epochMs: number): number;
13
+ /**
14
+ * The instant a wall-clock time denotes. A time that occurs twice (clocks turn back) is its first
15
+ * occurrence; a time that never occurs (clocks jump ahead) moves forward by the length of the gap.
16
+ */
17
+ export declare function fromNaive(zone: Zone, naiveMs: number): number;
18
+ /** `YYYY-MM-DDTHH:MM:SS[.mmm]±HH:MM` for an instant in the zone. */
19
+ export declare function formatIso(zone: Zone, epochMs: number): string;
@@ -4,6 +4,6 @@ import type { CommandContext } from "./types.js";
4
4
  * and MinSync indexes
5
5
  * (preserving `bin`, `datasources`, and the memory file). `rebuild` resets then re-runs a forced
6
6
  * refresh. Returns 0 on success, 2 for usage/decline errors, 1 for runtime
7
- * errors including path-escape guard violations.
7
+ * errors including path-escape guard violations, and 130/143 when a rebuild is stopped by SIGINT/SIGTERM.
8
8
  */
9
9
  export declare function runIndex(ctx: CommandContext): Promise<number>;
@@ -5,6 +5,6 @@ import type { CommandContext } from "./types.js";
5
5
  * Delegates to the agent's refresh pipeline (parsed mirrors, MinSync,
6
6
  * datasources, Jikji) without requiring any model configuration.
7
7
  *
8
- * Exit codes: 0 on success, 2 on config error, 1 on runtime error.
8
+ * Exit codes: 0 on success, 2 on config error, 1 on runtime error, 130/143 when stopped by SIGINT/SIGTERM.
9
9
  */
10
10
  export declare function runLiteRefresh(ctx: CommandContext): Promise<number>;
@@ -8,6 +8,10 @@ import type { CommandContext } from "./types.js";
8
8
  *
9
9
  * `--method minsync,parsed` restricts which methods run. When omitted, all
10
10
  * methods run. Parsed mirrors are always synced when MinSync is selected.
11
+ *
12
+ * SIGINT and SIGTERM abort the refresh: the MinSync and parser children are stopped, the run is recorded as
13
+ * failed, and the command exits 130 or 143 like any process a signal ended. A long first index can run for
14
+ * hours, so an operator or a service manager needs to be able to stop it.
11
15
  */
12
16
  export declare function runRefresh(ctx: CommandContext): Promise<number>;
13
17
  /**
@@ -5,6 +5,7 @@ import type { CommandContext } from "./types.js";
5
5
  * - default: long-running recursive fs watch with debounced refresh
6
6
  * - `--once`: single refresh tick (for cron / launchd / Task Scheduler)
7
7
  *
8
- * Exit codes: 0 on success, 2 on config error, 1 on runtime error.
8
+ * Exit codes: 0 on success, 2 on config error, 1 on runtime error, 130/143 when a one-shot tick is stopped by
9
+ * SIGINT/SIGTERM. The long-running watch handles those signals itself and exits 0.
9
10
  */
10
11
  export declare function runWatch(ctx: CommandContext): Promise<number>;