@promptev/context-engine 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -5,13 +5,38 @@ import { H as Hooks, R as RedactionPolicy, U as UsageEvent, P as ProgressEvent,
5
5
  export { D as DocumentReport, a as RedactionRule, b as RedactionRuleInit, c as applyRedaction, e as emitError, d as emitProgress, f as emitToolCall, g as emitUsage, h as graphUnits, u as unitsForFile } from './redaction-BqD_DEUQ.cjs';
6
6
  import { E as Embedder, S as StorageBackend, F as FetchImpl } from './storage-Dvpq2xAC.cjs';
7
7
  export { C as ChunkRow, a as EmbedKind, P as PostgresBackend, b as SearchScope, c as buildEmbedder } from './storage-Dvpq2xAC.cjs';
8
- import { P as Principals, U as Unset, S as ScopeInput, K as KnowledgeComputeFn, T as Trusted } from './mcp-BKSmxayM.cjs';
9
- export { a as KNOWLEDGE_ACTIONS, b as KNOWLEDGE_TOOL_DESCRIPTION, c as KnowledgeAction, d as Scope, e as TRUSTED, f as UNSCOPED, g as UNSET, h as callKnowledgeTool, i as createMcpApp, k as knowledgeToolDefinition, n as narrowToCeiling, r as resolvePrincipals, j as resolveScope } from './mcp-BKSmxayM.cjs';
8
+ import { P as Principals, U as Unset, S as ScopeInput, K as KnowledgeComputeFn, T as Trusted } from './mcp-uirRbluA.cjs';
9
+ export { a as KNOWLEDGE_ACTIONS, b as KNOWLEDGE_TOOL_DESCRIPTION, c as KnowledgeAction, d as Scope, e as TRUSTED, f as UNSCOPED, g as UNSET, h as callKnowledgeTool, i as createMcpApp, k as knowledgeToolDefinition, n as narrowToCeiling, r as resolvePrincipals, j as resolveScope } from './mcp-uirRbluA.cjs';
10
10
  import { T as ToolEngine, C as CanonicalTool, b as ToolHttpClient, a as ToolConfig } from './governance-P9pRb4Ol.cjs';
11
11
  export { c as ToolKind, d as configSchema } from './governance-P9pRb4Ol.cjs';
12
12
  import 'zod';
13
13
  import 'node:http';
14
14
 
15
+ /**
16
+ * Tool result formats — one helper every tool kind shares. Mirrors
17
+ * `context_engine/tools/response_mode.py`.
18
+ *
19
+ * `formatResult(result, responseMode)` hands a JSON-ish tool result back
20
+ * unchanged for `"json"`, and for `"tsv"` turns every outermost non-empty
21
+ * array of objects in it into a TSV string under the same key. A result that
22
+ * IS such an array becomes the string; a result holding none comes back
23
+ * unchanged.
24
+ *
25
+ * The cell encoding is PostgreSQL's COPY TEXT convention, not CSV quoting:
26
+ * `\N` is NULL, and tab, newline, CR and backslash inside a value are
27
+ * backslash-escaped. Quoting would leave a real newline inside a quoted
28
+ * value, so one row could span several lines — which breaks cutting a table
29
+ * at whole rows (`shapeResult`) and is harder for a model to read. Values
30
+ * that are not strings are written as compact JSON (dates as ISO strings).
31
+ */
32
+ declare const RESPONSE_MODES: readonly ["json", "tsv"];
33
+ type ResponseMode = (typeof RESPONSE_MODES)[number];
34
+ /** A list of objects as one TSV string, header first. */
35
+ declare function rowsToTsv(rows: Array<Record<string, unknown>>): string;
36
+ /** `result` unchanged for `"json"` (the default); every array of objects in
37
+ * it as TSV for `"tsv"`. Throws for an unknown mode. */
38
+ declare function formatResult(result: unknown, responseMode?: ResponseMode): unknown;
39
+
15
40
  type Mode$1 = "hybrid" | "graph";
16
41
  interface IngestRequest {
17
42
  content?: Buffer | null;
@@ -71,6 +96,13 @@ declare function listDocuments(opts: {
71
96
  sourceId?: string | null;
72
97
  /** OR-of-many, ONE keyset-paged query across all of them; with `sourceId`, their union. */
73
98
  sourceIds?: string[] | null;
99
+ /**
100
+ * Narrows to specific documents IN SQL, not after the page is built: three
101
+ * named documents that happen to sit on page four would otherwise come back
102
+ * as an empty page rather than as themselves. An empty array means nothing
103
+ * is in scope and stays empty.
104
+ */
105
+ documentIds?: string[] | null;
74
106
  principals?: string[] | null;
75
107
  cursor?: unknown;
76
108
  limit?: number;
@@ -78,6 +110,167 @@ declare function listDocuments(opts: {
78
110
  secretKey?: string | Buffer | null;
79
111
  hooks?: Hooks;
80
112
  }): Promise<Record<string, unknown>>;
113
+ type SpreadsheetDescription = {
114
+ document_id: string;
115
+ name: unknown;
116
+ source_id: unknown;
117
+ sheets: SheetSchema[] | null;
118
+ schema_unavailable?: string;
119
+ };
120
+ /**
121
+ * Sheet names, column headers and row counts for the named spreadsheets.
122
+ *
123
+ * `documentIds` comes from a listing the caller has already been shown, but
124
+ * the ACL and the source scope are applied AGAIN here: "we already filtered
125
+ * the list" is exactly how a batch read ends up reading one row it should
126
+ * not have. A document that is not visible, is not in scope, or is not
127
+ * tabular simply does not appear in the result.
128
+ *
129
+ * Reading document bodies is the cost, so it is bounded twice: the caller
130
+ * passes only the page it is describing, and `budget` caps the total
131
+ * characters of stored text this will pull. Documents past the budget are
132
+ * still LISTED, with `sheets: null` and a reason — a silently shortened
133
+ * schema would read as "that workbook has no sheets".
134
+ *
135
+ * `redaction` masks sheet names and column headers, which are derived from
136
+ * the document body exactly like `search`'s chunk text. The document `name`
137
+ * is not masked, matching `listDocuments`: it is caller-set at ingest.
138
+ */
139
+ declare function spreadsheetSchema(opts: {
140
+ pool: Pool;
141
+ documentIds: string[];
142
+ sourceIds?: string[] | null;
143
+ principals?: string[] | null;
144
+ budget?: number;
145
+ redaction?: RedactionPolicy | null;
146
+ secretKey?: string | Buffer | null;
147
+ hooks?: Hooks;
148
+ }): Promise<SpreadsheetDescription[]>;
149
+ type DocumentStructure = Record<string, unknown>;
150
+ /**
151
+ * What is INSIDE each of the named documents, whatever its type.
152
+ *
153
+ * Returns `{documentId: structure}`. The shape of `structure` follows the
154
+ * document, because the thing a model needs to know differs by type:
155
+ *
156
+ * | document | structure |
157
+ * |---|---|
158
+ * | CSV / XLSX / TSV | `sheets: [{name, columns, row_count}]` |
159
+ * | markdown, Word, HTML, a transcribed PDF | `sections: [...]`, `last_page` |
160
+ * | JSON | `keys: [...]` |
161
+ * | anything else | just `chunks` |
162
+ *
163
+ * `chunks` is on every one of them, and is the floor: a plain `.txt` has no
164
+ * headings to report, but a model still has to know whether `get_chunks` is
165
+ * worth calling. A document that is present but described by nothing at all
166
+ * reads as an empty document, which is why there is no "no structure" case.
167
+ *
168
+ * Everything but the spreadsheet columns comes from `meta_data` on the chunk
169
+ * rows, which the chunkers already wrote at ingest (`section_title`, `page`,
170
+ * `top_level_key`) — one grouped query over small rows, no document body read
171
+ * and no LLM. Columns are the exception: the header row is not in chunk
172
+ * metadata, so the tabular half still parses stored text, under the same
173
+ * budget (see `spreadsheetSchema`).
174
+ */
175
+ declare function documentStructure(opts: {
176
+ pool: Pool;
177
+ documentIds: string[];
178
+ sourceIds?: string[] | null;
179
+ principals?: string[] | null;
180
+ budget?: number;
181
+ /**
182
+ * Cap every list at `MAX_STRUCTURE_ITEMS` and report the remainder as a
183
+ * count. One rule decides it, and the caller above applies it: **the cap is
184
+ * for the call that did NOT name its documents.** A `discover` describing a
185
+ * whole page has a context budget to keep; a caller that asked about one
186
+ * document asked for all of it, exactly like `spreadsheetSchema`.
187
+ */
188
+ bounded?: boolean;
189
+ redaction?: RedactionPolicy | null;
190
+ secretKey?: string | Buffer | null;
191
+ hooks?: Hooks;
192
+ }): Promise<Record<string, DocumentStructure>>;
193
+ type DocumentTypeCount = {
194
+ kind: "spreadsheet" | "text";
195
+ type: string | null;
196
+ documents: number;
197
+ with_fields: number;
198
+ };
199
+ /**
200
+ * The corpus census: `[{kind, type, documents, with_fields}]`.
201
+ *
202
+ * Keyed by TWO things, because only one of them is always known:
203
+ *
204
+ * - `kind` is derived from the mime (`isTabularMime`, the same predicate
205
+ * `compute` selects on), so it is known for every document ever ingested.
206
+ * - `type` is the document's `document_type`, which is unconstrained free
207
+ * text an LLM wrote during structured extraction — and extraction is
208
+ * opt-in (`extractStructured`, off by default). On a deployment that never
209
+ * enabled it, `type` is null on every row. A census keyed on `type` alone
210
+ * would therefore be a single null bucket, which tells a model nothing
211
+ * about a corpus it is about to query.
212
+ *
213
+ * `with_fields` counts documents whose `structured_data` is a non-empty
214
+ * object. Extraction that ran and legitimately found nothing stores `{}`, and
215
+ * counting that as coverage would point a model at `query_meta` for a type
216
+ * that has nothing to filter on.
217
+ */
218
+ declare function documentTypes(opts: {
219
+ pool: Pool;
220
+ sourceIds?: string[] | null;
221
+ principals?: string[] | null;
222
+ documentIds?: string[] | null;
223
+ limit?: number;
224
+ redaction?: RedactionPolicy | null;
225
+ secretKey?: string | Buffer | null;
226
+ hooks?: Hooks;
227
+ }): Promise<DocumentTypeCount[]>;
228
+ type FieldDescription = {
229
+ field: string;
230
+ type: string;
231
+ documents: number;
232
+ };
233
+ type FieldGroup = {
234
+ kind: "spreadsheet" | "text";
235
+ type: string | null;
236
+ fields: FieldDescription[];
237
+ more_fields?: string[];
238
+ };
239
+ /**
240
+ * Extracted structured field names grouped by document kind AND type.
241
+ *
242
+ * Returns `[{kind, type, fields: [{field, type, documents}], more_fields}]` —
243
+ * one row per group, keyed by the SAME pair `documentTypes` is keyed by. That
244
+ * pairing is the point: `document_type` is a label an LLM wrote, so two
245
+ * different kinds can share one ("invoice" for both a PDF and a CSV of
246
+ * invoice rows). Keyed on the label alone, their fields merge into one group
247
+ * and a model reads a spreadsheet's columns as a PDF's extracted fields.
248
+ *
249
+ * `more_fields` holds the NAMES the per-group detail cap left out, not a
250
+ * count: nothing is dropped silently, and a name is all a caller needs to
251
+ * reach a field through `query_meta`. It is absent when nothing was left out.
252
+ *
253
+ * Counted over the documents the CALLER can see, not over the learned field
254
+ * registry (`context_engine_structured_keys`), which carries no ACL: a
255
+ * registry-wide answer would tell an anonymous caller the field names of
256
+ * every restricted document in the corpus. Counting from `structured_data`
257
+ * also makes `documents` mean what it says — how many in-scope documents
258
+ * actually carry the field.
259
+ *
260
+ * The type is `inferDataType`, the same function that labelled the registry,
261
+ * so the vocabulary a model reads here is the one the rest of the engine
262
+ * uses.
263
+ */
264
+ declare function fieldSummary(opts: {
265
+ pool: Pool;
266
+ sourceIds?: string[] | null;
267
+ principals?: string[] | null;
268
+ documentIds?: string[] | null;
269
+ maxFieldsPerType?: number;
270
+ redaction?: RedactionPolicy | null;
271
+ secretKey?: string | Buffer | null;
272
+ hooks?: Hooks;
273
+ }): Promise<FieldGroup[]>;
81
274
  /**
82
275
  * Answer a natural-language question against documents' `structuredData`.
83
276
  *
@@ -102,6 +295,24 @@ declare function queryStructured(question: string, opts: {
102
295
  secretKey?: string | Buffer | null;
103
296
  hooks?: Hooks;
104
297
  }): Promise<Record<string, unknown>>;
298
+ type SheetSchema = {
299
+ name: string;
300
+ columns: string[];
301
+ row_count: number;
302
+ };
303
+ /**
304
+ * The schema of one stored spreadsheet: `[{name, columns, row_count}]`.
305
+ *
306
+ * Header row and row count per SHEET, not unioned across the workbook — two
307
+ * sheets that both have an `amount` column are two different frames to
308
+ * `compute`, and a union would hide which one has the column a question
309
+ * needs. `row_count` counts DATA rows (the header is not one of them).
310
+ *
311
+ * Needs no danfo: `discover` must stay callable on an install that never
312
+ * enabled code execution, which is exactly the install where a model most
313
+ * needs the columns before it writes a query.
314
+ */
315
+ declare function spreadsheetSchemaFromText(text: string | null | undefined): SheetSchema[];
105
316
  /**
106
317
  * Compute an answer to `instruction` over in-scope spreadsheet documents.
107
318
  *
@@ -569,11 +780,66 @@ declare class ContextEngine implements ToolEngine {
569
780
  listDocuments(opts?: {
570
781
  sourceId?: string | null;
571
782
  sourceIds?: string[] | null;
783
+ documentIds?: string[] | null;
572
784
  principals?: Principals;
573
785
  cursor?: unknown;
574
786
  limit?: number;
575
787
  redaction?: RedactionPolicy | null;
576
788
  }): Promise<Record<string, unknown>>;
789
+ /**
790
+ * Sheet names, columns and row counts for the named spreadsheets.
791
+ *
792
+ * See `actions.spreadsheetSchema`. This is the half of `discover` that lets
793
+ * a model write ONE `compute` call: sheet names here are the keys it will
794
+ * index `dfs` by, and columns are the names it will use inside the code it
795
+ * writes.
796
+ */
797
+ spreadsheetSchema(opts: {
798
+ documentIds: string[];
799
+ sourceIds?: string[] | null;
800
+ principals?: Principals;
801
+ redaction?: RedactionPolicy | null;
802
+ }): Promise<SpreadsheetDescription[]>;
803
+ /**
804
+ * What is inside each of the named documents, whatever its type.
805
+ *
806
+ * See `actions.documentStructure`. Sheets and columns for a workbook,
807
+ * sections and the last page for a document with headings, top-level keys
808
+ * for JSON, and a chunk count for everything — so `discover` describes the
809
+ * whole corpus rather than only the spreadsheets in it.
810
+ */
811
+ documentStructure(opts: {
812
+ documentIds: string[];
813
+ sourceIds?: string[] | null;
814
+ principals?: Principals;
815
+ bounded?: boolean;
816
+ redaction?: RedactionPolicy | null;
817
+ }): Promise<Record<string, DocumentStructure>>;
818
+ /**
819
+ * The corpus census — `[{kind, type, documents, with_fields}]`.
820
+ *
821
+ * See `actions.documentTypes`. `kind` comes from the mime and is always
822
+ * known; `type` is the LLM-written document type and exists only where
823
+ * structured extraction was opted into.
824
+ */
825
+ documentTypes(opts?: {
826
+ sourceIds?: string[] | null;
827
+ principals?: Principals;
828
+ documentIds?: string[] | null;
829
+ redaction?: RedactionPolicy | null;
830
+ }): Promise<DocumentTypeCount[]>;
831
+ /**
832
+ * Extracted structured field names grouped by document kind and type.
833
+ *
834
+ * See `actions.fieldSummary`. One row per group, keyed by the same
835
+ * `(kind, type)` pair `documentTypes` uses.
836
+ */
837
+ fieldSummary(opts?: {
838
+ sourceIds?: string[] | null;
839
+ principals?: Principals;
840
+ documentIds?: string[] | null;
841
+ redaction?: RedactionPolicy | null;
842
+ }): Promise<FieldGroup[]>;
577
843
  queryStructured(question: string, opts?: {
578
844
  sourceIds?: string[] | null;
579
845
  principals?: Principals;
@@ -614,6 +880,13 @@ declare class ContextEngine implements ToolEngine {
614
880
  /** Opaque claim scope for approvals (e.g. a run id) — separate from
615
881
  * `sourceId`. See `governance.executeTool`. */
616
882
  approvalScope?: string | null;
883
+ /** Budget for the returned `result`: omitted = 8,000 chars / 100 rows,
884
+ * `null` = no limit. See `governance.executeTool`. */
885
+ resultMaxChars?: number | null;
886
+ resultMaxRows?: number | null;
887
+ /** `"json"` or `"tsv"` — every array of objects in the result as a TSV
888
+ * string. Omitted, an http tool uses its config's `response_mode`, else json. */
889
+ responseMode?: ResponseMode | null;
617
890
  }): Promise<Record<string, unknown>>;
618
891
  }
619
892
 
@@ -933,4 +1206,4 @@ declare function functionTool(fn: (...args: never[]) => unknown): CanonicalTool;
933
1206
  /** Bumped by CI on every main merge; 0.0.0 = pre-first-release. */
934
1207
  declare const __version__ = "0.0.0";
935
1208
 
936
- export { ApprovalExpired, ApprovalNotPending, type ApprovalRecord, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, type ComputeDocument, type ComputeFrames, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, ExtractionConfig, type ExtractionResult, GraphLegUnavailable, type Hit, Hooks, InProcessRunner, IngestReport, KnowledgeComputeFn, LLMClient, LLMConfig, Principals, ProgressEvent, RedactionPolicy, RerankerConfig, ScopeInput, type SearchResult, StorageBackend, type TaskRunner, type TaskStatus, ToolConfig, Trusted, Unset, UsageEvent, __version__, buildLlmClient, callLlm, compute, computeOverFrames, decryptDict, encryptDict, extract, extractStructuredData, functionTool, getDocumentText, getSecretKey, listDocuments, queryStructured, redactHits, rerank, resolveApproval, resolveFields, rrfFuse, runMigrate, runSearch, shouldRequireApproval, upsertRegistry };
1209
+ export { ApprovalExpired, ApprovalNotPending, type ApprovalRecord, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, type ComputeDocument, type ComputeFrames, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, ExtractionConfig, type ExtractionResult, GraphLegUnavailable, type Hit, Hooks, InProcessRunner, IngestReport, KnowledgeComputeFn, LLMClient, LLMConfig, Principals, ProgressEvent, RedactionPolicy, RerankerConfig, type ResponseMode, ScopeInput, type SearchResult, StorageBackend, type TaskRunner, type TaskStatus, ToolConfig, Trusted, Unset, UsageEvent, __version__, buildLlmClient, callLlm, compute, computeOverFrames, decryptDict, documentStructure, documentTypes, encryptDict, extract, extractStructuredData, fieldSummary, formatResult, functionTool, getDocumentText, getSecretKey, listDocuments, queryStructured, redactHits, rerank, resolveApproval, resolveFields, rowsToTsv, rrfFuse, runMigrate, runSearch, shouldRequireApproval, spreadsheetSchema, spreadsheetSchemaFromText, upsertRegistry };
package/dist/index.d.ts CHANGED
@@ -5,13 +5,38 @@ import { H as Hooks, R as RedactionPolicy, U as UsageEvent, P as ProgressEvent,
5
5
  export { D as DocumentReport, a as RedactionRule, b as RedactionRuleInit, c as applyRedaction, e as emitError, d as emitProgress, f as emitToolCall, g as emitUsage, h as graphUnits, u as unitsForFile } from './redaction-BqD_DEUQ.js';
6
6
  import { E as Embedder, S as StorageBackend, F as FetchImpl } from './storage-CJrKgJeJ.js';
7
7
  export { C as ChunkRow, a as EmbedKind, P as PostgresBackend, b as SearchScope, c as buildEmbedder } from './storage-CJrKgJeJ.js';
8
- import { P as Principals, U as Unset, S as ScopeInput, K as KnowledgeComputeFn, T as Trusted } from './mcp-BKSmxayM.js';
9
- export { a as KNOWLEDGE_ACTIONS, b as KNOWLEDGE_TOOL_DESCRIPTION, c as KnowledgeAction, d as Scope, e as TRUSTED, f as UNSCOPED, g as UNSET, h as callKnowledgeTool, i as createMcpApp, k as knowledgeToolDefinition, n as narrowToCeiling, r as resolvePrincipals, j as resolveScope } from './mcp-BKSmxayM.js';
8
+ import { P as Principals, U as Unset, S as ScopeInput, K as KnowledgeComputeFn, T as Trusted } from './mcp-uirRbluA.js';
9
+ export { a as KNOWLEDGE_ACTIONS, b as KNOWLEDGE_TOOL_DESCRIPTION, c as KnowledgeAction, d as Scope, e as TRUSTED, f as UNSCOPED, g as UNSET, h as callKnowledgeTool, i as createMcpApp, k as knowledgeToolDefinition, n as narrowToCeiling, r as resolvePrincipals, j as resolveScope } from './mcp-uirRbluA.js';
10
10
  import { T as ToolEngine, C as CanonicalTool, b as ToolHttpClient, a as ToolConfig } from './governance-BLPK7NMe.js';
11
11
  export { c as ToolKind, d as configSchema } from './governance-BLPK7NMe.js';
12
12
  import 'zod';
13
13
  import 'node:http';
14
14
 
15
+ /**
16
+ * Tool result formats — one helper every tool kind shares. Mirrors
17
+ * `context_engine/tools/response_mode.py`.
18
+ *
19
+ * `formatResult(result, responseMode)` hands a JSON-ish tool result back
20
+ * unchanged for `"json"`, and for `"tsv"` turns every outermost non-empty
21
+ * array of objects in it into a TSV string under the same key. A result that
22
+ * IS such an array becomes the string; a result holding none comes back
23
+ * unchanged.
24
+ *
25
+ * The cell encoding is PostgreSQL's COPY TEXT convention, not CSV quoting:
26
+ * `\N` is NULL, and tab, newline, CR and backslash inside a value are
27
+ * backslash-escaped. Quoting would leave a real newline inside a quoted
28
+ * value, so one row could span several lines — which breaks cutting a table
29
+ * at whole rows (`shapeResult`) and is harder for a model to read. Values
30
+ * that are not strings are written as compact JSON (dates as ISO strings).
31
+ */
32
+ declare const RESPONSE_MODES: readonly ["json", "tsv"];
33
+ type ResponseMode = (typeof RESPONSE_MODES)[number];
34
+ /** A list of objects as one TSV string, header first. */
35
+ declare function rowsToTsv(rows: Array<Record<string, unknown>>): string;
36
+ /** `result` unchanged for `"json"` (the default); every array of objects in
37
+ * it as TSV for `"tsv"`. Throws for an unknown mode. */
38
+ declare function formatResult(result: unknown, responseMode?: ResponseMode): unknown;
39
+
15
40
  type Mode$1 = "hybrid" | "graph";
16
41
  interface IngestRequest {
17
42
  content?: Buffer | null;
@@ -71,6 +96,13 @@ declare function listDocuments(opts: {
71
96
  sourceId?: string | null;
72
97
  /** OR-of-many, ONE keyset-paged query across all of them; with `sourceId`, their union. */
73
98
  sourceIds?: string[] | null;
99
+ /**
100
+ * Narrows to specific documents IN SQL, not after the page is built: three
101
+ * named documents that happen to sit on page four would otherwise come back
102
+ * as an empty page rather than as themselves. An empty array means nothing
103
+ * is in scope and stays empty.
104
+ */
105
+ documentIds?: string[] | null;
74
106
  principals?: string[] | null;
75
107
  cursor?: unknown;
76
108
  limit?: number;
@@ -78,6 +110,167 @@ declare function listDocuments(opts: {
78
110
  secretKey?: string | Buffer | null;
79
111
  hooks?: Hooks;
80
112
  }): Promise<Record<string, unknown>>;
113
+ type SpreadsheetDescription = {
114
+ document_id: string;
115
+ name: unknown;
116
+ source_id: unknown;
117
+ sheets: SheetSchema[] | null;
118
+ schema_unavailable?: string;
119
+ };
120
+ /**
121
+ * Sheet names, column headers and row counts for the named spreadsheets.
122
+ *
123
+ * `documentIds` comes from a listing the caller has already been shown, but
124
+ * the ACL and the source scope are applied AGAIN here: "we already filtered
125
+ * the list" is exactly how a batch read ends up reading one row it should
126
+ * not have. A document that is not visible, is not in scope, or is not
127
+ * tabular simply does not appear in the result.
128
+ *
129
+ * Reading document bodies is the cost, so it is bounded twice: the caller
130
+ * passes only the page it is describing, and `budget` caps the total
131
+ * characters of stored text this will pull. Documents past the budget are
132
+ * still LISTED, with `sheets: null` and a reason — a silently shortened
133
+ * schema would read as "that workbook has no sheets".
134
+ *
135
+ * `redaction` masks sheet names and column headers, which are derived from
136
+ * the document body exactly like `search`'s chunk text. The document `name`
137
+ * is not masked, matching `listDocuments`: it is caller-set at ingest.
138
+ */
139
+ declare function spreadsheetSchema(opts: {
140
+ pool: Pool;
141
+ documentIds: string[];
142
+ sourceIds?: string[] | null;
143
+ principals?: string[] | null;
144
+ budget?: number;
145
+ redaction?: RedactionPolicy | null;
146
+ secretKey?: string | Buffer | null;
147
+ hooks?: Hooks;
148
+ }): Promise<SpreadsheetDescription[]>;
149
+ type DocumentStructure = Record<string, unknown>;
150
+ /**
151
+ * What is INSIDE each of the named documents, whatever its type.
152
+ *
153
+ * Returns `{documentId: structure}`. The shape of `structure` follows the
154
+ * document, because the thing a model needs to know differs by type:
155
+ *
156
+ * | document | structure |
157
+ * |---|---|
158
+ * | CSV / XLSX / TSV | `sheets: [{name, columns, row_count}]` |
159
+ * | markdown, Word, HTML, a transcribed PDF | `sections: [...]`, `last_page` |
160
+ * | JSON | `keys: [...]` |
161
+ * | anything else | just `chunks` |
162
+ *
163
+ * `chunks` is on every one of them, and is the floor: a plain `.txt` has no
164
+ * headings to report, but a model still has to know whether `get_chunks` is
165
+ * worth calling. A document that is present but described by nothing at all
166
+ * reads as an empty document, which is why there is no "no structure" case.
167
+ *
168
+ * Everything but the spreadsheet columns comes from `meta_data` on the chunk
169
+ * rows, which the chunkers already wrote at ingest (`section_title`, `page`,
170
+ * `top_level_key`) — one grouped query over small rows, no document body read
171
+ * and no LLM. Columns are the exception: the header row is not in chunk
172
+ * metadata, so the tabular half still parses stored text, under the same
173
+ * budget (see `spreadsheetSchema`).
174
+ */
175
+ declare function documentStructure(opts: {
176
+ pool: Pool;
177
+ documentIds: string[];
178
+ sourceIds?: string[] | null;
179
+ principals?: string[] | null;
180
+ budget?: number;
181
+ /**
182
+ * Cap every list at `MAX_STRUCTURE_ITEMS` and report the remainder as a
183
+ * count. One rule decides it, and the caller above applies it: **the cap is
184
+ * for the call that did NOT name its documents.** A `discover` describing a
185
+ * whole page has a context budget to keep; a caller that asked about one
186
+ * document asked for all of it, exactly like `spreadsheetSchema`.
187
+ */
188
+ bounded?: boolean;
189
+ redaction?: RedactionPolicy | null;
190
+ secretKey?: string | Buffer | null;
191
+ hooks?: Hooks;
192
+ }): Promise<Record<string, DocumentStructure>>;
193
+ type DocumentTypeCount = {
194
+ kind: "spreadsheet" | "text";
195
+ type: string | null;
196
+ documents: number;
197
+ with_fields: number;
198
+ };
199
+ /**
200
+ * The corpus census: `[{kind, type, documents, with_fields}]`.
201
+ *
202
+ * Keyed by TWO things, because only one of them is always known:
203
+ *
204
+ * - `kind` is derived from the mime (`isTabularMime`, the same predicate
205
+ * `compute` selects on), so it is known for every document ever ingested.
206
+ * - `type` is the document's `document_type`, which is unconstrained free
207
+ * text an LLM wrote during structured extraction — and extraction is
208
+ * opt-in (`extractStructured`, off by default). On a deployment that never
209
+ * enabled it, `type` is null on every row. A census keyed on `type` alone
210
+ * would therefore be a single null bucket, which tells a model nothing
211
+ * about a corpus it is about to query.
212
+ *
213
+ * `with_fields` counts documents whose `structured_data` is a non-empty
214
+ * object. Extraction that ran and legitimately found nothing stores `{}`, and
215
+ * counting that as coverage would point a model at `query_meta` for a type
216
+ * that has nothing to filter on.
217
+ */
218
+ declare function documentTypes(opts: {
219
+ pool: Pool;
220
+ sourceIds?: string[] | null;
221
+ principals?: string[] | null;
222
+ documentIds?: string[] | null;
223
+ limit?: number;
224
+ redaction?: RedactionPolicy | null;
225
+ secretKey?: string | Buffer | null;
226
+ hooks?: Hooks;
227
+ }): Promise<DocumentTypeCount[]>;
228
+ type FieldDescription = {
229
+ field: string;
230
+ type: string;
231
+ documents: number;
232
+ };
233
+ type FieldGroup = {
234
+ kind: "spreadsheet" | "text";
235
+ type: string | null;
236
+ fields: FieldDescription[];
237
+ more_fields?: string[];
238
+ };
239
+ /**
240
+ * Extracted structured field names grouped by document kind AND type.
241
+ *
242
+ * Returns `[{kind, type, fields: [{field, type, documents}], more_fields}]` —
243
+ * one row per group, keyed by the SAME pair `documentTypes` is keyed by. That
244
+ * pairing is the point: `document_type` is a label an LLM wrote, so two
245
+ * different kinds can share one ("invoice" for both a PDF and a CSV of
246
+ * invoice rows). Keyed on the label alone, their fields merge into one group
247
+ * and a model reads a spreadsheet's columns as a PDF's extracted fields.
248
+ *
249
+ * `more_fields` holds the NAMES the per-group detail cap left out, not a
250
+ * count: nothing is dropped silently, and a name is all a caller needs to
251
+ * reach a field through `query_meta`. It is absent when nothing was left out.
252
+ *
253
+ * Counted over the documents the CALLER can see, not over the learned field
254
+ * registry (`context_engine_structured_keys`), which carries no ACL: a
255
+ * registry-wide answer would tell an anonymous caller the field names of
256
+ * every restricted document in the corpus. Counting from `structured_data`
257
+ * also makes `documents` mean what it says — how many in-scope documents
258
+ * actually carry the field.
259
+ *
260
+ * The type is `inferDataType`, the same function that labelled the registry,
261
+ * so the vocabulary a model reads here is the one the rest of the engine
262
+ * uses.
263
+ */
264
+ declare function fieldSummary(opts: {
265
+ pool: Pool;
266
+ sourceIds?: string[] | null;
267
+ principals?: string[] | null;
268
+ documentIds?: string[] | null;
269
+ maxFieldsPerType?: number;
270
+ redaction?: RedactionPolicy | null;
271
+ secretKey?: string | Buffer | null;
272
+ hooks?: Hooks;
273
+ }): Promise<FieldGroup[]>;
81
274
  /**
82
275
  * Answer a natural-language question against documents' `structuredData`.
83
276
  *
@@ -102,6 +295,24 @@ declare function queryStructured(question: string, opts: {
102
295
  secretKey?: string | Buffer | null;
103
296
  hooks?: Hooks;
104
297
  }): Promise<Record<string, unknown>>;
298
+ type SheetSchema = {
299
+ name: string;
300
+ columns: string[];
301
+ row_count: number;
302
+ };
303
+ /**
304
+ * The schema of one stored spreadsheet: `[{name, columns, row_count}]`.
305
+ *
306
+ * Header row and row count per SHEET, not unioned across the workbook — two
307
+ * sheets that both have an `amount` column are two different frames to
308
+ * `compute`, and a union would hide which one has the column a question
309
+ * needs. `row_count` counts DATA rows (the header is not one of them).
310
+ *
311
+ * Needs no danfo: `discover` must stay callable on an install that never
312
+ * enabled code execution, which is exactly the install where a model most
313
+ * needs the columns before it writes a query.
314
+ */
315
+ declare function spreadsheetSchemaFromText(text: string | null | undefined): SheetSchema[];
105
316
  /**
106
317
  * Compute an answer to `instruction` over in-scope spreadsheet documents.
107
318
  *
@@ -569,11 +780,66 @@ declare class ContextEngine implements ToolEngine {
569
780
  listDocuments(opts?: {
570
781
  sourceId?: string | null;
571
782
  sourceIds?: string[] | null;
783
+ documentIds?: string[] | null;
572
784
  principals?: Principals;
573
785
  cursor?: unknown;
574
786
  limit?: number;
575
787
  redaction?: RedactionPolicy | null;
576
788
  }): Promise<Record<string, unknown>>;
789
+ /**
790
+ * Sheet names, columns and row counts for the named spreadsheets.
791
+ *
792
+ * See `actions.spreadsheetSchema`. This is the half of `discover` that lets
793
+ * a model write ONE `compute` call: sheet names here are the keys it will
794
+ * index `dfs` by, and columns are the names it will use inside the code it
795
+ * writes.
796
+ */
797
+ spreadsheetSchema(opts: {
798
+ documentIds: string[];
799
+ sourceIds?: string[] | null;
800
+ principals?: Principals;
801
+ redaction?: RedactionPolicy | null;
802
+ }): Promise<SpreadsheetDescription[]>;
803
+ /**
804
+ * What is inside each of the named documents, whatever its type.
805
+ *
806
+ * See `actions.documentStructure`. Sheets and columns for a workbook,
807
+ * sections and the last page for a document with headings, top-level keys
808
+ * for JSON, and a chunk count for everything — so `discover` describes the
809
+ * whole corpus rather than only the spreadsheets in it.
810
+ */
811
+ documentStructure(opts: {
812
+ documentIds: string[];
813
+ sourceIds?: string[] | null;
814
+ principals?: Principals;
815
+ bounded?: boolean;
816
+ redaction?: RedactionPolicy | null;
817
+ }): Promise<Record<string, DocumentStructure>>;
818
+ /**
819
+ * The corpus census — `[{kind, type, documents, with_fields}]`.
820
+ *
821
+ * See `actions.documentTypes`. `kind` comes from the mime and is always
822
+ * known; `type` is the LLM-written document type and exists only where
823
+ * structured extraction was opted into.
824
+ */
825
+ documentTypes(opts?: {
826
+ sourceIds?: string[] | null;
827
+ principals?: Principals;
828
+ documentIds?: string[] | null;
829
+ redaction?: RedactionPolicy | null;
830
+ }): Promise<DocumentTypeCount[]>;
831
+ /**
832
+ * Extracted structured field names grouped by document kind and type.
833
+ *
834
+ * See `actions.fieldSummary`. One row per group, keyed by the same
835
+ * `(kind, type)` pair `documentTypes` uses.
836
+ */
837
+ fieldSummary(opts?: {
838
+ sourceIds?: string[] | null;
839
+ principals?: Principals;
840
+ documentIds?: string[] | null;
841
+ redaction?: RedactionPolicy | null;
842
+ }): Promise<FieldGroup[]>;
577
843
  queryStructured(question: string, opts?: {
578
844
  sourceIds?: string[] | null;
579
845
  principals?: Principals;
@@ -614,6 +880,13 @@ declare class ContextEngine implements ToolEngine {
614
880
  /** Opaque claim scope for approvals (e.g. a run id) — separate from
615
881
  * `sourceId`. See `governance.executeTool`. */
616
882
  approvalScope?: string | null;
883
+ /** Budget for the returned `result`: omitted = 8,000 chars / 100 rows,
884
+ * `null` = no limit. See `governance.executeTool`. */
885
+ resultMaxChars?: number | null;
886
+ resultMaxRows?: number | null;
887
+ /** `"json"` or `"tsv"` — every array of objects in the result as a TSV
888
+ * string. Omitted, an http tool uses its config's `response_mode`, else json. */
889
+ responseMode?: ResponseMode | null;
617
890
  }): Promise<Record<string, unknown>>;
618
891
  }
619
892
 
@@ -933,4 +1206,4 @@ declare function functionTool(fn: (...args: never[]) => unknown): CanonicalTool;
933
1206
  /** Bumped by CI on every main merge; 0.0.0 = pre-first-release. */
934
1207
  declare const __version__ = "0.0.0";
935
1208
 
936
- export { ApprovalExpired, ApprovalNotPending, type ApprovalRecord, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, type ComputeDocument, type ComputeFrames, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, ExtractionConfig, type ExtractionResult, GraphLegUnavailable, type Hit, Hooks, InProcessRunner, IngestReport, KnowledgeComputeFn, LLMClient, LLMConfig, Principals, ProgressEvent, RedactionPolicy, RerankerConfig, ScopeInput, type SearchResult, StorageBackend, type TaskRunner, type TaskStatus, ToolConfig, Trusted, Unset, UsageEvent, __version__, buildLlmClient, callLlm, compute, computeOverFrames, decryptDict, encryptDict, extract, extractStructuredData, functionTool, getDocumentText, getSecretKey, listDocuments, queryStructured, redactHits, rerank, resolveApproval, resolveFields, rrfFuse, runMigrate, runSearch, shouldRequireApproval, upsertRegistry };
1209
+ export { ApprovalExpired, ApprovalNotPending, type ApprovalRecord, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, type ComputeDocument, type ComputeFrames, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, ExtractionConfig, type ExtractionResult, GraphLegUnavailable, type Hit, Hooks, InProcessRunner, IngestReport, KnowledgeComputeFn, LLMClient, LLMConfig, Principals, ProgressEvent, RedactionPolicy, RerankerConfig, type ResponseMode, ScopeInput, type SearchResult, StorageBackend, type TaskRunner, type TaskStatus, ToolConfig, Trusted, Unset, UsageEvent, __version__, buildLlmClient, callLlm, compute, computeOverFrames, decryptDict, documentStructure, documentTypes, encryptDict, extract, extractStructuredData, fieldSummary, formatResult, functionTool, getDocumentText, getSecretKey, listDocuments, queryStructured, redactHits, rerank, resolveApproval, resolveFields, rowsToTsv, rrfFuse, runMigrate, runSearch, shouldRequireApproval, spreadsheetSchema, spreadsheetSchemaFromText, upsertRegistry };