@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/README.md +65 -1
- package/dist/cli.js +732 -37
- package/dist/cli.js.map +1 -1
- package/dist/express.cjs +205 -21
- package/dist/express.cjs.map +1 -1
- package/dist/express.js +205 -21
- package/dist/express.js.map +1 -1
- package/dist/fastify.cjs +205 -21
- package/dist/fastify.cjs.map +1 -1
- package/dist/fastify.js +205 -21
- package/dist/fastify.js.map +1 -1
- package/dist/hono.cjs +205 -21
- package/dist/hono.cjs.map +1 -1
- package/dist/hono.js +205 -21
- package/dist/hono.js.map +1 -1
- package/dist/index.cjs +755 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +276 -3
- package/dist/index.d.ts +276 -3
- package/dist/index.js +749 -39
- package/dist/index.js.map +1 -1
- package/dist/{mcp-BKSmxayM.d.cts → mcp-uirRbluA.d.cts} +4 -0
- package/dist/{mcp-BKSmxayM.d.ts → mcp-uirRbluA.d.ts} +4 -0
- package/dist/mcp.cjs +50 -10
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.d.cts +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +50 -10
- package/dist/mcp.js.map +1 -1
- package/dist/skills/context-engine/SKILL.md +54 -1
- package/package.json +1 -1
- package/src/skills/context-engine/SKILL.md +54 -1
|
@@ -117,6 +117,10 @@ type Engine$1 = {
|
|
|
117
117
|
getChunks?: (id: string, opts?: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
118
118
|
getDocuments?: (ids: string[], opts?: Record<string, unknown>) => Promise<Array<Record<string, unknown>>>;
|
|
119
119
|
mapReduce?: (instruction: string, opts?: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
120
|
+
spreadsheetSchema: (opts: Record<string, unknown>) => Promise<unknown[]>;
|
|
121
|
+
documentStructure: (opts: Record<string, unknown>) => Promise<Record<string, Record<string, unknown>>>;
|
|
122
|
+
documentTypes: (opts?: Record<string, unknown>) => Promise<unknown[]>;
|
|
123
|
+
fieldSummary: (opts?: Record<string, unknown>) => Promise<unknown[]>;
|
|
120
124
|
};
|
|
121
125
|
type KnowledgeToolArgs = {
|
|
122
126
|
action: string;
|
|
@@ -117,6 +117,10 @@ type Engine$1 = {
|
|
|
117
117
|
getChunks?: (id: string, opts?: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
118
118
|
getDocuments?: (ids: string[], opts?: Record<string, unknown>) => Promise<Array<Record<string, unknown>>>;
|
|
119
119
|
mapReduce?: (instruction: string, opts?: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
120
|
+
spreadsheetSchema: (opts: Record<string, unknown>) => Promise<unknown[]>;
|
|
121
|
+
documentStructure: (opts: Record<string, unknown>) => Promise<Record<string, Record<string, unknown>>>;
|
|
122
|
+
documentTypes: (opts?: Record<string, unknown>) => Promise<unknown[]>;
|
|
123
|
+
fieldSummary: (opts?: Record<string, unknown>) => Promise<unknown[]>;
|
|
120
124
|
};
|
|
121
125
|
type KnowledgeToolArgs = {
|
|
122
126
|
action: string;
|
package/dist/mcp.cjs
CHANGED
|
@@ -409,7 +409,7 @@ var KNOWLEDGE_ACTIONS = [
|
|
|
409
409
|
"get_neighbors",
|
|
410
410
|
"community_summary"
|
|
411
411
|
];
|
|
412
|
-
var KNOWLEDGE_TOOL_DESCRIPTION = "The knowledge base \u2014 the ingested documents and data files (PDF, Word, Excel, CSV and the rest) \u2014 as ONE tool with actions. Nothing is searched for you: use it before answering anything that should come from those documents, and do not use it for general knowledge. Call action 'discover' FIRST when you do not already know what is there: it lists the documents
|
|
412
|
+
var KNOWLEDGE_TOOL_DESCRIPTION = "The knowledge base \u2014 the ingested documents and data files (PDF, Word, Excel, CSV and the rest) \u2014 as ONE tool with actions. Nothing is searched for you: use it before answering anything that should come from those documents, and do not use it for general knowledge. Call action 'discover' FIRST when you do not already know what is there: it lists the documents and says what is INSIDE each one \u2014 a spreadsheet's sheet names, column headers and row counts; a document's section titles and last page; a JSON file's top-level keys \u2014 plus the extracted field names grouped by document type with each field's data type and how many documents carry it, a census of the whole corpus, and which actions this deployment can run. Use those names verbatim: they are what compute, query_meta and get_chunks match on, so one discover is enough and you never have to go looking for a column, a section or a field name. A long list is shortened there, with the rest reported as a count and, when it is worth the trip, the exact call that returns it in full \u2014 discover again with document_ids set to that one document, which answers whole. When it is not worth the trip the payload says so and says what to do instead: a sheet with hundreds of columns is one to compute over, never one to read back. Then match the action to the task. 'search' finds passages by meaning or keywords \u2014 for questions answered by reading text. Looking up an identifier (an ID, code, SKU or invoice number) is the exception: search the BARE identifier alone, e.g. '2525', never the whole question. Those are CONTENT identifiers \u2014 written inside a document \u2014 and they belong in a query; a document_id is a system id (a uuid) that only discover, list or a search hit can give you, so never search a uuid as text and never hand an invoice number to get_doc. 'get_doc' reads one whole document by id, 'get_docs' reads several at once, and 'get_chunks' walks one long document in order a piece at a time when you need more of it than an excerpt; 'list' browses the documents without searching. 'map_reduce' asks the SAME question of every document in scope and answers once per document \u2014 for 'which contracts mention X', where search would return a handful of passages and miss the rest. 'query_meta' filters and aggregates documents by their structured fields (dates, amounts, categories) \u2014 usually the right action for a question about spreadsheet data. 'compute' runs code over the spreadsheets for any figure DERIVED from them \u2014 a total, average, count, ranking, margin or comparison across rows \u2014 AND for finding the exact row matching one id or value. In a large table, search cannot reliably locate an individual row; compute can. When the question is about how things are CONNECTED rather than what a document says \u2014 who works with whom, what belongs to what, what a change touches \u2014 use the graph actions: 'get_neighbors' for what is one step from one thing, 'traverse' for everything within a few steps of it, 'find_related' for connections of a kind across the corpus, and 'community_summary' for the themes the corpus groups into. They are available only where a graph was built; discover says so. Searching with mode='graph' ranks passages by those same connections instead of by wording alone, which finds a passage that never repeats your words. Rules that decide answers: search returns EXCERPTS, and rows of a spreadsheet are not arithmetic \u2014 never add up, average or rank rows yourself from what search returned, and never say a figure is not available before computing over the sheet that holds it. A listing that says has_more has MORE: send its next_cursor back as 'cursor' for the next page, and never conclude a document is absent from a first page that was truncated. Search again with different words before saying a document is missing. A result may carry a next_action (or next_page): it is the call to make next, already filled in \u2014 follow it rather than guessing the next step. Cite document names.";
|
|
413
413
|
var ACTION_PARAM_DESCRIPTION = "Match it to the task: reading questions -> search (a bare identifier for an ID or code); spreadsheet analysis, or the exact row for one id or value -> query_meta or compute; how things connect -> get_neighbors, traverse, find_related or community_summary; browse everything -> list; unsure what exists -> discover first.";
|
|
414
414
|
var ACTION_HELP = {
|
|
415
415
|
search: "passages by meaning or keywords; an ID, code or number as the BARE identifier",
|
|
@@ -432,7 +432,7 @@ var OFF = {
|
|
|
432
432
|
graph: "the graph actions are off: this deployment has no graph configured, so nothing has been linked up. Use search, get_doc or list instead."
|
|
433
433
|
};
|
|
434
434
|
var GRAPH_ACTIONS = ["traverse", "find_related", "get_neighbors", "community_summary"];
|
|
435
|
-
var DOCUMENT_ID_ACTIONS = ["search", "compute", "get_docs", "map_reduce"];
|
|
435
|
+
var DOCUMENT_ID_ACTIONS = ["search", "compute", "get_docs", "map_reduce", "discover", "list"];
|
|
436
436
|
var DEFAULT_GET_DOCS_CHARS = 2e5;
|
|
437
437
|
var INPUT_PROPERTIES = {
|
|
438
438
|
action: { type: "string", enum: [...KNOWLEDGE_ACTIONS], description: ACTION_PARAM_DESCRIPTION },
|
|
@@ -452,7 +452,7 @@ var INPUT_PROPERTIES = {
|
|
|
452
452
|
document_ids: {
|
|
453
453
|
type: "array",
|
|
454
454
|
items: { type: "string" },
|
|
455
|
-
description: "Narrows to these documents, using ids from discover, list or a search hit. It INTERSECTS with source_ids, so a document outside the sources you named returns nothing. (for search, compute)"
|
|
455
|
+
description: "Narrows to these documents, using ids from discover, list or a search hit. It INTERSECTS with source_ids, so a document outside the sources you named returns nothing. On discover it also asks for those documents' structure IN FULL, past the shortening a whole-page discover applies. (for search, compute, get_docs, map_reduce, discover, list)"
|
|
456
456
|
},
|
|
457
457
|
entity: {
|
|
458
458
|
type: "string",
|
|
@@ -568,11 +568,16 @@ function parseCursor(cursor) {
|
|
|
568
568
|
}
|
|
569
569
|
return parsed;
|
|
570
570
|
}
|
|
571
|
-
async function listPage(engine, sourceIds, principals, action, limit, cursor, ceiling, redaction) {
|
|
571
|
+
async function listPage(engine, sourceIds, principals, action, limit, cursor, documentIds, ceiling, redaction) {
|
|
572
572
|
const page = await engine.listDocuments({
|
|
573
573
|
// `!= null`, NOT truthiness: an EMPTY array means "nothing is in scope"
|
|
574
574
|
// and collapsing it to null would list the whole corpus.
|
|
575
575
|
sourceIds: sourceIds != null ? [...new Set(sourceIds)] : null,
|
|
576
|
+
// Already intersected with the host's ceiling by `narrowToCeiling`, and
|
|
577
|
+
// filtered in SQL rather than after the page is built — three named
|
|
578
|
+
// documents sitting on page four must come back as themselves, not as an
|
|
579
|
+
// empty page.
|
|
580
|
+
documentIds: documentIds != null ? [...new Set(documentIds)] : null,
|
|
576
581
|
principals,
|
|
577
582
|
cursor,
|
|
578
583
|
limit: Math.max(1, Math.min(limit, MAX_LIST_LIMIT)),
|
|
@@ -582,7 +587,9 @@ async function listPage(engine, sourceIds, principals, action, limit, cursor, ce
|
|
|
582
587
|
id: String(raw.id),
|
|
583
588
|
name: raw.name,
|
|
584
589
|
source_id: raw.sourceId ?? raw.source_id,
|
|
585
|
-
kind: documentKind(raw)
|
|
590
|
+
kind: documentKind(raw),
|
|
591
|
+
document_type: raw.documentType ?? raw.document_type ?? null,
|
|
592
|
+
mode: raw.mode ?? null
|
|
586
593
|
}));
|
|
587
594
|
if (ceiling.documentIds != null) {
|
|
588
595
|
const allowed = new Set(ceiling.documentIds);
|
|
@@ -635,30 +642,62 @@ async function callKnowledgeTool(engine, args) {
|
|
|
635
642
|
action,
|
|
636
643
|
args.limit ?? 50,
|
|
637
644
|
parseCursor(args.cursor),
|
|
645
|
+
documentIds,
|
|
638
646
|
ceiling,
|
|
639
647
|
args.redaction
|
|
640
648
|
);
|
|
641
649
|
if (action === "list") return { success: true, ...page };
|
|
642
|
-
const
|
|
650
|
+
const structures = await engine.documentStructure({
|
|
651
|
+
documentIds: page.documents.map((d) => d.id),
|
|
652
|
+
sourceIds,
|
|
653
|
+
principals,
|
|
654
|
+
// The cap is for the call that did NOT name its documents. A caller
|
|
655
|
+
// that asked about specific documents asked for all of them, and the
|
|
656
|
+
// truncated payload tells it to make exactly this call — so answering
|
|
657
|
+
// it truncated again would be a loop.
|
|
658
|
+
bounded: !requestedDocumentIds?.length,
|
|
659
|
+
redaction: args.redaction
|
|
660
|
+
});
|
|
661
|
+
for (const doc of page.documents) doc.structure = structures[doc.id] ?? {};
|
|
662
|
+
const hasSpreadsheet = page.documents.some((d) => d.kind === "spreadsheet");
|
|
663
|
+
const fieldsByType = await engine.fieldSummary({
|
|
664
|
+
sourceIds,
|
|
665
|
+
documentIds,
|
|
666
|
+
principals,
|
|
667
|
+
redaction: args.redaction
|
|
668
|
+
});
|
|
669
|
+
const census = await engine.documentTypes({
|
|
670
|
+
sourceIds,
|
|
671
|
+
documentIds,
|
|
672
|
+
principals,
|
|
673
|
+
redaction: args.redaction
|
|
674
|
+
});
|
|
643
675
|
const forAFact = { action: "search", query: "<bare identifier or key words>" };
|
|
644
676
|
const nextAction = {};
|
|
645
|
-
if (
|
|
677
|
+
if (hasSpreadsheet && available.compute) {
|
|
646
678
|
nextAction["for a figure from a spreadsheet"] = {
|
|
647
679
|
action: "compute",
|
|
648
|
-
query: "<what to compute, columns as named>"
|
|
680
|
+
query: "<what to compute, columns as named above>"
|
|
649
681
|
};
|
|
650
682
|
}
|
|
651
683
|
nextAction["for a clause or a fact"] = forAFact;
|
|
684
|
+
if (fieldsByType.length && available.query_meta) {
|
|
685
|
+
nextAction["for documents by a field value"] = {
|
|
686
|
+
action: "query_meta",
|
|
687
|
+
query: "<a question naming a field from fields_by_type>"
|
|
688
|
+
};
|
|
689
|
+
}
|
|
652
690
|
if (available.get_neighbors) {
|
|
653
691
|
nextAction["for how things connect"] = {
|
|
654
692
|
action: "get_neighbors",
|
|
655
693
|
entity: "<a name that appears in the documents>"
|
|
656
694
|
};
|
|
657
695
|
}
|
|
658
|
-
|
|
696
|
+
const discovered = {
|
|
659
697
|
success: true,
|
|
660
698
|
...page,
|
|
661
|
-
|
|
699
|
+
document_types: census,
|
|
700
|
+
fields_by_type: fieldsByType,
|
|
662
701
|
available_actions: Object.fromEntries(
|
|
663
702
|
Object.keys(ACTION_HELP).map((name) => [
|
|
664
703
|
name,
|
|
@@ -667,6 +706,7 @@ async function callKnowledgeTool(engine, args) {
|
|
|
667
706
|
),
|
|
668
707
|
next_action: nextAction
|
|
669
708
|
};
|
|
709
|
+
return discovered;
|
|
670
710
|
}
|
|
671
711
|
if (action === "search") {
|
|
672
712
|
if (!text) return { success: false, error: "search needs a query" };
|