@promptev/context-engine 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -180,6 +180,87 @@ const router = createHonoRouter(engine, { auth: myAuth, principals: myPrincipals
180
180
 
181
181
  `auth` and `principals` are required. Identical routes exist for Express and Fastify.
182
182
 
183
+ ## The knowledge tool
184
+
185
+ One tool with actions:
186
+
187
+ | Action | What it is for |
188
+ |---|---|
189
+ | `discover` | what documents there are and what is inside each one — sheets and columns, sections and pages, or JSON keys — plus the extracted fields by document type, a census of the corpus, and what each action can do. Call it first |
190
+ | `search` | passages by meaning or keywords |
191
+ | `get_doc` / `get_docs` | one whole document by id, or several at once |
192
+ | `get_chunks` | walk one long document in order, a piece at a time |
193
+ | `list` | browse the documents without searching |
194
+ | `query_meta` | filter documents by their structured fields |
195
+ | `compute` | a figure derived from the spreadsheets, over every row |
196
+ | `map_reduce` | the same question asked of every document in scope |
197
+ | `get_neighbors` / `traverse` | what is one step, or a few steps, from a named thing |
198
+ | `find_related` | connections of a kind across the corpus |
199
+ | `community_summary` | the themes the corpus groups into |
200
+
201
+ One description carries the decision rules once and there is one name for a
202
+ model to route through. An action this deployment cannot service is advertised
203
+ as off rather than hidden, and called anyway it answers `{ success: false,
204
+ error }` the model can relay. A truncated answer carries the `next_page` call
205
+ that reads the rest.
206
+
207
+ `discover` answers with the SCHEMA, not an inventory, so one call is enough to
208
+ write one correct `compute` or `query_meta` call instead of three exploratory
209
+ ones. Every listed document carries `document_type`, `mode`, and a `structure`
210
+ whose shape follows the type — `sheets` (name, column headers, row count) for
211
+ a workbook, `sections` and `last_page` for a document with headings, `keys`
212
+ for JSON, and `chunks` as the floor for anything else. Beside them,
213
+ `fields_by_type` lists the extracted structured field names with each field's
214
+ data type and how many in-scope documents carry it, and `document_types` is a
215
+ census of the corpus. Both are keyed by `(kind, type)`: `kind` comes from the
216
+ mime and is always known, while `document_type` is free text an LLM wrote and
217
+ exists only where `extractStructured` was enabled — so a PDF invoice and a
218
+ spreadsheet of invoice rows stay separate rather than merging under one label.
219
+
220
+ Lists inside a `structure` are capped, with the remainder reported as
221
+ `more_columns` / `more_sections` / `more_keys` / `more_sheets`, because
222
+ `discover` is the first call of a conversation and an unbounded list lands in
223
+ the model's context before it has asked anything. **The cap is for the call
224
+ that did not name its documents:** `discover` and `list` take `document_ids`,
225
+ and a `discover` scoped to specific documents answers their structure whole
226
+ and narrows the field grouping and the census to them too. While the remainder
227
+ is small enough to be worth fetching, the truncated structure carries that
228
+ call already filled in; past that it says what to do instead, because a sheet
229
+ with hundreds of columns is one to compute over rather than read back.
230
+
231
+ Omit `mode` on a search and it is worked out from the documents in scope — the
232
+ graph leg is added when the deployment has a graph and something in scope was
233
+ ingested that way, and it runs beside the other legs rather than ahead of
234
+ them. Naming `"hybrid"` or `"graph"` forces one.
235
+
236
+ ```ts
237
+ import { UNSCOPED } from "@promptev/context-engine";
238
+
239
+ const answer = await engine.searchKnowledgeBase({
240
+ action: "search",
241
+ query: "annual leave",
242
+ principals: caller,
243
+ scope: ["hr"],
244
+ });
245
+ ```
246
+
247
+ `createMcpApp` serves that same function, so an application driving its own
248
+ agent loop needs no MCP and cannot get a different answer.
249
+ `knowledgeToolDefinition()` exports the tool as data — name, description and
250
+ input schema as JSON Schema — so a host never hand-writes it. `createMcpApp`
251
+ also takes `redaction` (applied per call), and `compute` / `mapReduce`
252
+ callables that REPLACE the built-in ones, which is where a host applies its own
253
+ rules for permission, billing and approval.
254
+
255
+ `scope` is REQUIRED on both: the ceiling of source ids (or a `Scope` with
256
+ document ids) the tool may ever reach. It is host-supplied and resolved per
257
+ call like `principals`, and never a tool argument — a model can name any
258
+ source id, and a tool that believed it would let one caller read another's
259
+ documents. Map your own word onto it: a project, a matter, a customer. A
260
+ caller narrows within the ceiling and never past it; an id outside is dropped
261
+ silently; a request left with nothing in scope returns nothing. A host with
262
+ one shared corpus writes `scope: UNSCOPED` on purpose.
263
+
183
264
  ## Tools
184
265
 
185
266
  Register a governed tool — HTTP, SQL, MCP, or a plain function — and every call