@promptev/context-engine 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -0
- package/dist/cli.js +12013 -11061
- package/dist/cli.js.map +1 -1
- package/dist/express.cjs.map +1 -1
- package/dist/express.js.map +1 -1
- package/dist/fastify.cjs.map +1 -1
- package/dist/fastify.js.map +1 -1
- package/dist/graph/index.cjs +6 -5
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.js +6 -5
- package/dist/graph/index.js.map +1 -1
- package/dist/hono.cjs.map +1 -1
- package/dist/hono.js.map +1 -1
- package/dist/index.cjs +7567 -6557
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -26
- package/dist/index.d.ts +93 -26
- package/dist/index.js +7552 -6543
- package/dist/index.js.map +1 -1
- package/dist/mcp-BKSmxayM.d.cts +204 -0
- package/dist/mcp-BKSmxayM.d.ts +204 -0
- package/dist/mcp.cjs +896 -70
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.d.cts +2 -31
- package/dist/mcp.d.ts +2 -31
- package/dist/mcp.js +896 -70
- package/dist/mcp.js.map +1 -1
- package/dist/skills/context-engine/SKILL.md +30 -2
- package/package.json +1 -1
- package/src/skills/context-engine/SKILL.md +30 -2
package/dist/mcp.js
CHANGED
|
@@ -1,14 +1,50 @@
|
|
|
1
|
+
import 'franc';
|
|
2
|
+
import 'openai';
|
|
3
|
+
import 'crypto';
|
|
4
|
+
import 'jsonrepair';
|
|
5
|
+
import 'cheerio';
|
|
6
|
+
import 'exceljs';
|
|
7
|
+
import 'jszip';
|
|
8
|
+
import 'mammoth';
|
|
9
|
+
import 'postal-mime';
|
|
1
10
|
import { z } from 'zod';
|
|
11
|
+
import 'fs';
|
|
12
|
+
import 'path';
|
|
2
13
|
|
|
3
|
-
|
|
14
|
+
var __defProp = Object.defineProperty;
|
|
15
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
16
|
+
var __esm = (fn, res) => function __init() {
|
|
17
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
18
|
+
};
|
|
19
|
+
var __export = (target, all) => {
|
|
20
|
+
for (var name in all)
|
|
21
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
22
|
+
};
|
|
4
23
|
|
|
5
24
|
// src/errors.ts
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
25
|
+
var EngineActionError, DocumentNotFoundError, ExtraMissingError;
|
|
26
|
+
var init_errors = __esm({
|
|
27
|
+
"src/errors.ts"() {
|
|
28
|
+
EngineActionError = class extends Error {
|
|
29
|
+
constructor(message) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = "EngineActionError";
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
DocumentNotFoundError = class extends Error {
|
|
35
|
+
constructor(documentId) {
|
|
36
|
+
super(`document not found: ${documentId}`);
|
|
37
|
+
this.name = "DocumentNotFoundError";
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
ExtraMissingError = class extends Error {
|
|
41
|
+
constructor(extra, pkg, what) {
|
|
42
|
+
super(`${what} requires the '${pkg}' package (optional extra: ${extra}): npm install ${pkg}`);
|
|
43
|
+
this.name = "ExtraMissingError";
|
|
44
|
+
}
|
|
45
|
+
};
|
|
10
46
|
}
|
|
11
|
-
};
|
|
47
|
+
});
|
|
12
48
|
|
|
13
49
|
// src/extras.ts
|
|
14
50
|
async function requireExtra(specifier, extra, what) {
|
|
@@ -18,11 +54,823 @@ async function requireExtra(specifier, extra, what) {
|
|
|
18
54
|
throw new ExtraMissingError(extra, specifier, what);
|
|
19
55
|
}
|
|
20
56
|
}
|
|
57
|
+
var init_extras = __esm({
|
|
58
|
+
"src/extras.ts"() {
|
|
59
|
+
init_errors();
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
var UNICODE_NAME_RANGES;
|
|
63
|
+
var init_text = __esm({
|
|
64
|
+
"src/text.ts"() {
|
|
65
|
+
UNICODE_NAME_RANGES = `41,5a,124;61,7a,124;aa,aa,74;b5,b5,156;ba,ba,148;c0,d6,124;d8,f6,124;f8,2af,124;2b0,2c1,159;2c6,2c6,159;2c7,2c7,34;2c8,2d1,159;2e0,2e4,159;2ec,2ec,159;2ee,2ee,159;300,300,84;301,301,0;302,302,41;303,303,239;304,304,137;305,305,184;306,306,26;307,307,59;308,308,55;309,309,100;30a,30a,202;30b,30b,61;30c,30c,34;30d,30d,252;30e,30f,61;310,310,32;311,311,107;312,312,243;313,313,44;314,314,199;315,315,44;316,316,84;317,317,0;318,318,125;319,319,200;31a,31a,125;31b,31b,101;31c,31c,125;31d,31d,245;31e,31e,64;31f,31f,194;320,320,157;321,321,186;322,322,197;323,323,59;324,324,55;325,325,202;326,326,44;327,327,36;328,328,176;329,329,252;32a,32a,28;32b,32b,107;32c,32c,34;32d,32d,41;32e,32e,26;32f,32f,107;330,330,239;331,331,137;332,332,134;333,333,61;334,334,239;335,335,211;336,336,133;337,337,211;338,338,133;339,339,200;33a,33a,107;33b,33b,219;33c,33c,208;33d,33d,259;33e,33e,252;33f,33f,61;340,340,84;341,341,0;342,345,87;346,346,28;347,347,71;348,348,61;349,349,125;34a,34a,171;34b,34b,99;34c,34c,6;34d,34d,125;34e,34e,246;34f,34f,83;350,350,200;351,351,125;352,352,75;353,353,259;354,354,125;355,357,200;358,358,59;359,359,13;35a,35a,61;35b,35b,264;35c,362,61;363,36f,124;370,374,87;376,377,87;37a,37d,87;37f,37f,87;386,386,87;388,38a,87;38c,38c,87;38e,3a1,87;3a3,3e1,87;3e2,3ef,46;3f0,3f5,87;3f7,3ff,87;400,481,50;483,52f,50;531,556,12;559,559,12;560,588,12;591,5bd,96;5bf,5bf,96;5c1,5c2,96;5c4,5c5,96;5c7,5c7,96;5d0,5ea,96;5ef,5f2,96;610,61a,11;620,65f,11;66e,6d3,11;6d5,6dc,11;6df,6e8,11;6ea,6ef,11;6fa,6fc,11;6ff,6ff,11;710,74a,225;74d,74f,225;750,77f,11;780,7b1,234;7ca,7f5,170;7fa,7fa,170;7fd,7fd,170;800,82d,205;840,85b,144;860,86a,225;870,887,11;889,88e,11;898,8e1,11;8e3,8ff,11;900,963,54;971,97f,54;980,983,19;985,98c,19;98f,990,19;993,9a8,19;9aa,9b0,19;9b2,9b2,19;9b6,9b9,19;9bc,9c4,19;9c7,9c8,19;9cb,9ce,19;9d7,9d7,19;9dc,9dd,19;9df,9e3,19;9f0,9f1,19;9fc,9fc,19;9fe,9fe,19;a01,a03,90;a05,a0a,90;a0f,a10,90;a13,a28,90;a2a,a30,90;a32,a33,90;a35,a36,90;a38,a39,90;a3c,a3c,90;a3e,a42,90;a47,a48,90;a4b,a4d,90;a51,a51,90;a59,a5c,90;a5e,a5e,90;a70,a75,90;a81,a83,88;a85,a8d,88;a8f,a91,88;a93,aa8,88;aaa,ab0,88;ab2,ab3,88;ab5,ab9,88;abc,ac5,88;ac7,ac9,88;acb,acd,88;ad0,ad0,88;ae0,ae3,88;af9,aff,88;b01,b03,181;b05,b0c,181;b0f,b10,181;b13,b28,181;b2a,b30,181;b32,b33,181;b35,b39,181;b3c,b44,181;b47,b48,181;b4b,b4d,181;b55,b57,181;b5c,b5d,181;b5f,b63,181;b71,b71,181;b82,b83,230;b85,b8a,230;b8e,b90,230;b92,b95,230;b99,b9a,230;b9c,b9c,230;b9e,b9f,230;ba3,ba4,230;ba8,baa,230;bae,bb9,230;bbe,bc2,230;bc6,bc8,230;bca,bcd,230;bd0,bd0,230;bd7,bd7,230;c00,c0c,233;c0e,c10,233;c12,c28,233;c2a,c39,233;c3c,c44,233;c46,c48,233;c4a,c4d,233;c55,c56,233;c58,c5a,233;c5d,c5d,233;c60,c63,233;c80,c83,111;c85,c8c,111;c8e,c90,111;c92,ca8,111;caa,cb3,111;cb5,cb9,111;cbc,cc4,111;cc6,cc8,111;cca,ccd,111;cd5,cd6,111;cdd,cde,111;ce0,ce3,111;cf1,cf3,111;d00,d0c,143;d0e,d10,143;d12,d44,143;d46,d48,143;d4a,d4e,143;d54,d57,143;d5f,d63,143;d7a,d7f,143;d81,d83,214;d85,d96,214;d9a,db1,214;db3,dbb,214;dbd,dbd,214;dc0,dc6,214;dca,dca,214;dcf,dd4,214;dd6,dd6,214;dd8,ddf,214;df2,df3,214;e01,e3a,235;e40,e4e,235;e81,e82,123;e84,e84,123;e86,e8a,123;e8c,ea3,123;ea5,ea5,123;ea7,ebd,123;ec0,ec4,123;ec6,ec6,123;ec8,ece,123;edc,edf,123;f00,f00,237;f18,f19,237;f35,f35,237;f37,f37,237;f39,f39,237;f3e,f47,237;f49,f6c,237;f71,f84,237;f86,f97,237;f99,fbc,237;fc6,fc6,237;1000,103f,164;1050,108f,164;109a,109d,164;10a0,10c5,78;10c7,10c7,78;10cd,10cd,78;10d0,10fa,78;10fc,10fc,159;10fd,10ff,78;1100,11ff,92;1200,1248,72;124a,124d,72;1250,1256,72;1258,1258,72;125a,125d,72;1260,1288,72;128a,128d,72;1290,12b0,72;12b2,12b5,72;12b8,12be,72;12c0,12c0,72;12c2,12c5,72;12c8,12d6,72;12d8,1310,72;1312,1315,72;1318,135a,72;135d,135f,72;1380,138f,72;13a0,13f5,39;13f8,13fd,39;1401,166c,31;166f,167f,31;1681,169a,175;16a0,16ea,204;16f1,16f8,204;1700,1715,226;171f,171f,226;1720,1734,94;1740,1753,30;1760,176c,227;176e,1770,227;1772,1773,227;1780,17d3,120;17d7,17d7,120;17dc,17dd,120;180b,180d,160;180f,180f,160;1820,1878,160;1880,18aa,160;18b0,18f5,31;1900,191e,130;1920,192b,130;1930,193b,130;1950,196d,228;1970,1974,228;1980,19ab,168;19b0,19c9,168;1a00,1a1b,29;1a20,1a5e,228;1a60,1a7c,228;1a7f,1a7f,228;1aa7,1aa7,228;1ab0,1ab0,63;1ab1,1ab1,56;1ab2,1ab2,104;1ab3,1ab3,65;1ab4,1ab4,242;1ab5,1ab5,260;1ab6,1ab6,258;1ab7,1ab7,180;1ab8,1ab8,61;1ab9,1ab9,129;1aba,1aba,220;1abb,1abb,188;1abc,1abc,61;1abd,1abe,188;1abf,1ac0,124;1ac1,1ac1,125;1ac2,1ac2,200;1ac3,1ac3,125;1ac4,1ac4,200;1ac5,1ac5,219;1ac6,1ac6,172;1ac7,1ac7,107;1ac8,1ac8,194;1ac9,1aca,61;1acb,1acb,242;1acc,1ace,124;1b00,1b4c,15;1b6b,1b73,15;1b80,1baf,221;1bba,1bbf,221;1bc0,1bf3,18;1c00,1c37,127;1c4d,1c4f,127;1c5a,1c7d,178;1c80,1c88,50;1c90,1cba,78;1cbd,1cbf,78;1cd0,1cd2,251;1cd4,1cfa,251;1d00,1d25,124;1d26,1d2a,87;1d2b,1d2b,50;1d2c,1d61,159;1d62,1d65,124;1d66,1d6a,87;1d6b,1d77,124;1d78,1d78,159;1d79,1d9a,124;1d9b,1dbf,159;1dc0,1dc1,60;1dc2,1dc2,215;1dc3,1dc3,223;1dc4,1dc4,138;1dc5,1dc5,86;1dc6,1dc6,140;1dc7,1dc7,2;1dc8,1dc8,85;1dc9,1dc9,1;1dca,1dca,124;1dcb,1dcb,27;1dcc,1dcc,139;1dcd,1dcd,61;1dce,1dce,176;1dcf,1dcf,264;1dd0,1dd0,108;1dd1,1dd1,247;1dd2,1dd2,248;1dd3,1df4,124;1df5,1df5,245;1df6,1df7,114;1df8,1df8,59;1df9,1df9,257;1dfa,1dfa,59;1dfb,1dfb,52;1dfc,1dfc,61;1dfd,1dfd,6;1dfe,1dfe,125;1dff,1dff,200;1e00,1eff,124;1f00,1f15,87;1f18,1f1d,87;1f20,1f45,87;1f48,1f4d,87;1f50,1f57,87;1f59,1f59,87;1f5b,1f5b,87;1f5d,1f5d,87;1f5f,1f7d,87;1f80,1fb4,87;1fb6,1fbc,87;1fbe,1fbe,87;1fc2,1fc4,87;1fc6,1fcc,87;1fd0,1fd3,87;1fd6,1fdb,87;1fe0,1fec,87;1ff2,1ff4,87;1ff6,1ffc,87;2071,2071,222;207f,207f,222;2090,209c,124;20d0,20d0,125;20d1,20d1,200;20d2,20d2,133;20d3,20d3,211;20d4,20d4,10;20d5,20d5,43;20d6,20d6,125;20d7,20d7,200;20d8,20d8,202;20d9,20d9,43;20da,20da,10;20db,20db,236;20dc,20dc,76;20dd,20e0,70;20e1,20e1,125;20e2,20e4,70;20e5,20e5,198;20e6,20e6,61;20e7,20e7,9;20e8,20e8,242;20e9,20e9,257;20ea,20ea,126;20eb,20eb,133;20ec,20ec,201;20ed,20ed,126;20ee,20ee,125;20ef,20ef,200;20f0,20f0,13;2102,2102,62;2107,2107,73;210a,210b,207;210c,210c,23;210d,210d,62;210e,210f,193;2110,2110,207;2111,2111,23;2112,2113,207;2115,2115,62;2119,211a,62;211b,211b,207;211c,211c,23;211d,211d,62;2124,2124,62;2126,2126,177;2128,2128,23;212a,212a,117;212b,212b,8;212c,212c,207;212d,212d,23;212f,2131,207;2132,2132,243;2133,2134,207;2135,2135,5;2136,2136,20;2137,2137,79;2138,2138,51;2139,2139,105;213c,213f,62;2145,2149,62;214e,214e,243;2183,2183,203;2184,2184,124;2c00,2c5f,80;2c60,2c7c,124;2c7d,2c7d,159;2c7e,2c7f,124;2c80,2ce4,46;2ceb,2cf3,46;2d00,2d25,78;2d27,2d27,78;2d2d,2d2d,78;2d30,2d67,238;2d6f,2d6f,238;2d7f,2d7f,238;2d80,2d96,72;2da0,2da6,72;2da8,2dae,72;2db0,2db6,72;2db8,2dbe,72;2dc0,2dc6,72;2dc8,2dce,72;2dd0,2dd6,72;2dd8,2dde,72;2de0,2dff,50;2e2f,2e2f,252;3005,3006,102;302a,302d,102;302e,302f,92;3031,3035,252;303b,303b,252;303c,303c,149;3041,3096,98;3099,309a,113;309d,309f,98;30a1,30fa,112;30fc,30fc,113;30fd,30ff,112;3105,312f,24;3131,318e,92;31a0,31bf,24;31f0,31ff,112;3400,4dbf,42;4e00,9fff,42;a000,a48c,262;a4d0,a4fd,132;a500,a60c,249;a610,a61f,249;a62a,a62b,249;a640,a672,50;a674,a67d,50;a67f,a69b,50;a69c,a69d,159;a69e,a69f,50;a6a0,a6e5,16;a6f0,a6f1,16;a717,a71f,159;a722,a76f,124;a770,a770,159;a771,a787,124;a788,a788,159;a78b,a7ca,124;a7d0,a7d1,124;a7d3,a7d3,124;a7d5,a7d9,124;a7f2,a7f4,159;a7f5,a7f7,124;a7f8,a7f9,159;a7fa,a7ff,124;a800,a827,224;a82c,a82c,224;a840,a873,190;a880,a8c5,206;a8e0,a8f7,54;a8fb,a8fb,54;a8fd,a8ff,54;a90a,a92d,116;a930,a953,196;a960,a97c,92;a980,a9c0,109;a9cf,a9cf,109;a9e0,a9ef,164;a9fa,a9fe,164;aa00,aa36,38;aa40,aa4d,38;aa60,aa76,164;aa7a,aa7f,164;aa80,aac2,228;aadb,aadd,228;aae0,aaef,152;aaf2,aaf6,152;ab01,ab06,72;ab09,ab0e,72;ab11,ab16,72;ab20,ab26,72;ab28,ab2e,72;ab30,ab5a,124;ab5c,ab5f,159;ab60,ab64,124;ab65,ab65,87;ab66,ab68,124;ab69,ab69,159;ab70,abbf,39;abc0,abea,152;abec,abed,152;ac00,d7a3,92;d7b0,d7c6,92;d7cb,d7fb,92;f900,fa6d,42;fa70,fad9,42;fb00,fb06,124;fb13,fb17,12;fb1d,fb28,96;fb2a,fb36,96;fb38,fb3c,96;fb3e,fb3e,96;fb40,fb41,96;fb43,fb44,96;fb46,fb4f,96;fb50,fbb1,11;fbd3,fd3d,11;fd50,fd8f,11;fd92,fdc7,11;fdf0,fdfb,11;fe00,fe0f,250;fe20,fe21,128;fe22,fe23,61;fe24,fe25,137;fe26,fe26,45;fe27,fe28,128;fe29,fe2a,239;fe2b,fe2c,137;fe2d,fe2d,45;fe2e,fe2f,50;fe70,fe74,11;fe76,fefc,11;ff21,ff3a,77;ff41,ff5a,77;ff66,ffbe,91;ffc2,ffc7,91;ffca,ffcf,91;ffd2,ffd7,91;ffda,ffdc,91;10000,1000b,131;1000d,10026,131;10028,1003a,131;1003c,1003d,131;1003f,1004d,131;10050,1005d,131;10080,100fa,131;101fd,101fd,191;10280,1029c,135;102a0,102d0,33;102e0,102e0,46;10300,1031f,179;1032d,1032f,179;10330,10340,81;10342,10349,81;10350,1037a,179;10380,1039d,244;103a0,103c3,179;103c8,103cf,179;10400,1044f,53;10450,1047f,210;10480,1049d,183;104b0,104d3,182;104d8,104fb,182;10500,10527,68;10530,10563,35;10570,1057a,254;1057c,1058a,254;1058c,10592,254;10594,10595,254;10597,105a1,254;105a3,105b1,254;105b3,105b9,254;105bb,105bc,254;10600,10736,131;10740,10755,131;10760,10767,131;10780,10785,159;10787,107b0,159;107b2,107ba,159;10800,10805,48;10808,10808,48;1080a,10835,48;10837,10838,48;1083c,1083c,48;1083f,1083f,48;10840,10855,103;10860,10876,187;10880,1089e,165;108e0,108f2,95;108f4,108f5,95;10900,10915,192;10920,10939,136;10980,109b7,154;109be,109bf,154;10a00,10a03,118;10a05,10a06,118;10a0c,10a13,118;10a15,10a17,118;10a19,10a35,118;10a38,10a3a,118;10a3f,10a3f,118;10a60,10a7c,179;10a80,10a9c,179;10ac0,10ac7,145;10ac9,10ae6,145;10b00,10b35,14;10b40,10b55,106;10b60,10b72,106;10b80,10b91,195;10c00,10c48,179;10c80,10cb2,179;10cc0,10cf2,179;10d00,10d27,93;10e80,10ea9,261;10eab,10eac,261;10eb0,10eb1,261;10efd,10eff,11;10f00,10f1c,179;10f27,10f27,179;10f30,10f50,216;10f70,10f85,179;10fb0,10fc4,40;10fe0,10ff6,69;11000,11046,25;11070,11075,25;1107f,1107f,25;11080,110ba,110;110c2,110c2,110;110d0,110e8,217;11100,11134,37;11144,11147,37;11150,11173,141;11176,11176,141;11180,111c4,209;111c9,111cc,209;111ce,111cf,209;111da,111da,209;111dc,111dc,209;11200,11211,121;11213,11237,121;1123e,11241,121;11280,11286,162;11288,11288,162;1128a,1128d,162;1128f,1129d,162;1129f,112a8,162;112b0,112ea,122;11300,11303,82;11305,1130c,82;1130f,11310,82;11313,11328,82;1132a,11330,82;11332,11333,82;11335,11339,82;1133b,1133b,22;1133c,11344,82;11347,11348,82;1134b,1134d,82;11350,11350,82;11357,11357,82;1135d,11363,82;11366,1136c,82;11370,11374,82;11400,1144a,169;1145e,11461,169;11480,114c5,240;114c7,114c7,240;11580,115b5,212;115b8,115c0,212;115d8,115dd,212;11600,11640,158;11644,11644,158;11680,116b8,229;11700,1171a,4;1171d,1172b,4;11740,11746,4;11800,1183a,58;118a0,118df,256;118ff,118ff,256;11900,11906,57;11909,11909,57;1190c,11913,57;11915,11916,57;11918,11935,57;11937,11938,57;1193b,11943,57;119a0,119a7,167;119aa,119d7,167;119da,119e1,167;119e3,119e4,167;11a00,11a3e,263;11a47,11a47,263;11a50,11a99,218;11a9d,11a9d,218;11ab0,11abf,31;11ac0,11af8,189;11c00,11c08,21;11c0a,11c36,21;11c38,11c40,21;11c72,11c8f,146;11c92,11ca7,146;11ca9,11cb6,146;11d00,11d06,147;11d08,11d09,147;11d0b,11d36,147;11d3a,11d3a,147;11d3c,11d3d,147;11d3f,11d47,147;11d60,11d65,89;11d67,11d68,89;11d6a,11d8e,89;11d90,11d91,89;11d93,11d98,89;11ee0,11ef6,142;11f00,11f10,115;11f12,11f3a,115;11f3e,11f42,115;11fb0,11fb0,132;12000,12399,47;12480,12543,47;12f90,12ff0,49;13000,1342f,67;13440,13455,67;14400,14646,7;16800,16a38,16;16a40,16a5e,161;16a70,16abe,231;16ad0,16aed,17;16af0,16af4,17;16b00,16b36,185;16b40,16b43,185;16b63,16b77,185;16b7d,16b8f,185;16e40,16e7f,151;16f00,16f4a,155;16f4f,16f87,155;16f8f,16f9f,155;16fe0,16fe0,232;16fe1,16fe1,173;16fe3,16fe3,179;16fe4,16fe4,119;16ff0,16ff1,253;18800,18aff,232;18b00,18cd5,119;1aff0,1aff3,112;1aff5,1affb,112;1affd,1affe,112;1b000,1b000,112;1b001,1b001,98;1b002,1b11e,97;1b11f,1b11f,98;1b120,1b122,112;1b132,1b132,98;1b150,1b152,98;1b155,1b155,112;1b164,1b167,112;1b170,1b2fb,173;1bc00,1bc6a,66;1bc70,1bc7c,66;1bc80,1bc88,66;1bc90,1bc99,66;1bc9d,1bc9e,66;1cf00,1cf2d,265;1cf30,1cf46,265;1d165,1d169,163;1d16d,1d172,163;1d17b,1d182,163;1d185,1d18b,163;1d1aa,1d1ad,163;1d242,1d244,87;1d400,1d454,150;1d456,1d49c,150;1d49e,1d49f,150;1d4a2,1d4a2,150;1d4a5,1d4a6,150;1d4a9,1d4ac,150;1d4ae,1d4b9,150;1d4bb,1d4bb,150;1d4bd,1d4c3,150;1d4c5,1d505,150;1d507,1d50a,150;1d50d,1d514,150;1d516,1d51c,150;1d51e,1d539,150;1d53b,1d53e,150;1d540,1d544,150;1d546,1d546,150;1d54a,1d550,150;1d552,1d6a5,150;1d6a8,1d6c0,150;1d6c2,1d6da,150;1d6dc,1d6fa,150;1d6fc,1d714,150;1d716,1d734,150;1d736,1d74e,150;1d750,1d76e,150;1d770,1d788,150;1d78a,1d7a8,150;1d7aa,1d7c2,150;1d7c4,1d7cb,150;1da00,1da36,213;1da3b,1da6c,213;1da75,1da75,213;1da84,1da84,213;1da9b,1da9f,213;1daa1,1daaf,213;1df00,1df1e,124;1df25,1df2a,124;1e000,1e006,80;1e008,1e018,80;1e01b,1e021,80;1e023,1e024,80;1e026,1e02a,80;1e030,1e050,159;1e051,1e06a,50;1e06b,1e06d,159;1e08f,1e08f,50;1e100,1e12c,174;1e130,1e13d,174;1e14e,1e14e,174;1e290,1e2ae,241;1e2c0,1e2ef,255;1e4d0,1e4ef,166;1e7e0,1e7e6,72;1e7e8,1e7eb,72;1e7ed,1e7ee,72;1e7f0,1e7fe,72;1e800,1e8c4,153;1e8d0,1e8d6,153;1e900,1e94b,3;1ee00,1ee03,11;1ee05,1ee1f,11;1ee21,1ee22,11;1ee24,1ee24,11;1ee27,1ee27,11;1ee29,1ee32,11;1ee34,1ee37,11;1ee39,1ee39,11;1ee3b,1ee3b,11;1ee42,1ee42,11;1ee47,1ee47,11;1ee49,1ee49,11;1ee4b,1ee4b,11;1ee4d,1ee4f,11;1ee51,1ee52,11;1ee54,1ee54,11;1ee57,1ee57,11;1ee59,1ee59,11;1ee5b,1ee5b,11;1ee5d,1ee5d,11;1ee5f,1ee5f,11;1ee61,1ee62,11;1ee64,1ee64,11;1ee67,1ee6a,11;1ee6c,1ee72,11;1ee74,1ee77,11;1ee79,1ee7c,11;1ee7e,1ee7e,11;1ee80,1ee89,11;1ee8b,1ee9b,11;1eea1,1eea3,11;1eea5,1eea9,11;1eeab,1eebb,11;20000,2a6df,42;2a700,2b739,42;2b740,2b81d,42;2b820,2cea1,42;2ceb0,2ebe0,42;2ebf0,2ee5d,42;2f800,2fa1d,42;30000,3134a,42;31350,323af,42;e0100,e01ef,250`;
|
|
66
|
+
UNICODE_NAME_RANGES.split(";").map((entry) => {
|
|
67
|
+
const [start, end, word] = entry.split(",");
|
|
68
|
+
return { start: Number.parseInt(start, 16), end: Number.parseInt(end, 16), word: Number(word) };
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// src/hooks.ts
|
|
74
|
+
var init_hooks = __esm({
|
|
75
|
+
"src/hooks.ts"() {
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// src/providers/google.ts
|
|
80
|
+
var init_google = __esm({
|
|
81
|
+
"src/providers/google.ts"() {
|
|
82
|
+
init_errors();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
var init_llm = __esm({
|
|
86
|
+
"src/providers/llm.ts"() {
|
|
87
|
+
init_errors();
|
|
88
|
+
init_google();
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
var init_crypto = __esm({
|
|
92
|
+
"src/crypto.ts"() {
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
var init_redaction = __esm({
|
|
96
|
+
"src/redaction.ts"() {
|
|
97
|
+
init_crypto();
|
|
98
|
+
init_hooks();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
var init_json = __esm({
|
|
102
|
+
"src/extraction/json.ts"() {
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
var init_files = __esm({
|
|
106
|
+
"src/extraction/files.ts"() {
|
|
107
|
+
Buffer.from([80, 75, 3, 4]);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
var init_extraction = __esm({
|
|
111
|
+
"src/extraction/index.ts"() {
|
|
112
|
+
init_extras();
|
|
113
|
+
init_hooks();
|
|
114
|
+
init_files();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// src/graph/retrieval.ts
|
|
119
|
+
async function corpusIsAclUniform(pool, sourceIds) {
|
|
120
|
+
const result = await pool.query(
|
|
121
|
+
`SELECT EXISTS(SELECT 1 FROM context_engine_chunks c
|
|
122
|
+
WHERE c.acl IS NOT NULL AND ($1::text[] IS NULL OR c.source_id = ANY($1::text[]))) AS has_acl`,
|
|
123
|
+
[sourceIds]
|
|
124
|
+
);
|
|
125
|
+
return !result.rows[0]?.has_acl;
|
|
126
|
+
}
|
|
127
|
+
async function shouldUseCommunitySummaries(pool, opts) {
|
|
128
|
+
if (opts.principals == null) return true;
|
|
129
|
+
return corpusIsAclUniform(pool, opts.sourceIds);
|
|
130
|
+
}
|
|
131
|
+
var init_retrieval = __esm({
|
|
132
|
+
"src/graph/retrieval.ts"() {
|
|
133
|
+
init_hooks();
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// src/graph/navigation.ts
|
|
138
|
+
var navigation_exports = {};
|
|
139
|
+
__export(navigation_exports, {
|
|
140
|
+
SUMMARIES_WITHHELD: () => SUMMARIES_WITHHELD,
|
|
141
|
+
communitySummary: () => communitySummary,
|
|
142
|
+
findRelated: () => findRelated,
|
|
143
|
+
getNeighbors: () => getNeighbors,
|
|
144
|
+
traverse: () => traverse
|
|
145
|
+
});
|
|
146
|
+
function clamp(value, fallback, ceiling) {
|
|
147
|
+
const n = typeof value === "number" && Number.isFinite(value) ? Math.trunc(value) : fallback;
|
|
148
|
+
return Math.max(1, Math.min(n, ceiling));
|
|
149
|
+
}
|
|
150
|
+
function scopeArgs(opts) {
|
|
151
|
+
return [opts.sourceIds ?? null, opts.documentIds ?? null, opts.principals ?? null];
|
|
152
|
+
}
|
|
153
|
+
async function resolveEntity(pool, name, opts) {
|
|
154
|
+
const result = await pool.query(
|
|
155
|
+
`SELECT e.id::text, e.name, e.type FROM context_engine_entities e
|
|
156
|
+
WHERE e.normalized_name = $4 AND ${ENTITY_VISIBLE} LIMIT 1`,
|
|
157
|
+
[...scopeArgs(opts), (name ?? "").trim().toLowerCase()]
|
|
158
|
+
);
|
|
159
|
+
const row = result.rows[0];
|
|
160
|
+
return row ? { id: String(row.id), name: row.name, type: row.type } : null;
|
|
161
|
+
}
|
|
162
|
+
async function getNeighbors(pool, opts) {
|
|
163
|
+
const start = await resolveEntity(pool, opts.entity, opts);
|
|
164
|
+
if (!start) return { found: false, error: NOT_FOUND, neighbors: [], count: 0 };
|
|
165
|
+
const result = await pool.query(
|
|
166
|
+
`SELECT other.name, other.type, r.category, r.label, r.evidence,
|
|
167
|
+
CASE WHEN r.source_entity_id = $4::uuid THEN 'outgoing' ELSE 'incoming' END AS direction
|
|
168
|
+
FROM context_engine_entity_relationships r
|
|
169
|
+
JOIN context_engine_entities other ON other.id =
|
|
170
|
+
CASE WHEN r.source_entity_id = $4::uuid THEN r.target_entity_id ELSE r.source_entity_id END
|
|
171
|
+
WHERE (r.source_entity_id = $4::uuid OR r.target_entity_id = $4::uuid)
|
|
172
|
+
${EDGE_VISIBLE}
|
|
173
|
+
ORDER BY other.name LIMIT $5`,
|
|
174
|
+
[...scopeArgs(opts), start.id, clamp(opts.limit, 20, MAX_LIMIT)]
|
|
175
|
+
);
|
|
176
|
+
const neighbors = result.rows.map((r) => ({
|
|
177
|
+
name: r.name,
|
|
178
|
+
type: r.type,
|
|
179
|
+
category: r.category,
|
|
180
|
+
label: r.label,
|
|
181
|
+
evidence: r.evidence,
|
|
182
|
+
direction: r.direction
|
|
183
|
+
}));
|
|
184
|
+
return {
|
|
185
|
+
found: true,
|
|
186
|
+
entity: { name: start.name, type: start.type },
|
|
187
|
+
neighbors,
|
|
188
|
+
count: neighbors.length
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
async function traverse(pool, opts) {
|
|
192
|
+
const start = await resolveEntity(pool, opts.entity, opts);
|
|
193
|
+
if (!start) return { found: false, error: NOT_FOUND, paths: [], count: 0 };
|
|
194
|
+
const result = await pool.query(
|
|
195
|
+
`WITH RECURSIVE walk AS (
|
|
196
|
+
SELECT r.id AS rel_id,
|
|
197
|
+
CASE WHEN r.source_entity_id = $4::uuid THEN r.target_entity_id ELSE r.source_entity_id END AS node_id,
|
|
198
|
+
r.category, r.label, r.evidence, 1 AS hop,
|
|
199
|
+
ARRAY[r.source_entity_id, r.target_entity_id] AS visited
|
|
200
|
+
FROM context_engine_entity_relationships r
|
|
201
|
+
WHERE (r.source_entity_id = $4::uuid OR r.target_entity_id = $4::uuid)
|
|
202
|
+
${EDGE_VISIBLE}
|
|
203
|
+
UNION ALL
|
|
204
|
+
SELECT r.id,
|
|
205
|
+
CASE WHEN r.source_entity_id = w.node_id THEN r.target_entity_id ELSE r.source_entity_id END,
|
|
206
|
+
r.category, r.label, r.evidence, w.hop + 1,
|
|
207
|
+
w.visited || CASE WHEN r.source_entity_id = w.node_id THEN r.target_entity_id ELSE r.source_entity_id END
|
|
208
|
+
FROM walk w
|
|
209
|
+
JOIN context_engine_entity_relationships r
|
|
210
|
+
ON (r.source_entity_id = w.node_id OR r.target_entity_id = w.node_id)
|
|
211
|
+
WHERE w.hop < $5
|
|
212
|
+
AND NOT (CASE WHEN r.source_entity_id = w.node_id THEN r.target_entity_id ELSE r.source_entity_id END = ANY(w.visited))
|
|
213
|
+
${EDGE_VISIBLE}
|
|
214
|
+
)
|
|
215
|
+
SELECT DISTINCT ON (w.node_id, w.category, w.label)
|
|
216
|
+
e.name, e.type, w.category, w.label, w.evidence, w.hop
|
|
217
|
+
FROM walk w JOIN context_engine_entities e ON e.id = w.node_id
|
|
218
|
+
WHERE ($6::text IS NULL OR w.category = $6::text)
|
|
219
|
+
ORDER BY w.node_id, w.category, w.label, w.hop ASC
|
|
220
|
+
LIMIT $7`,
|
|
221
|
+
[
|
|
222
|
+
...scopeArgs(opts),
|
|
223
|
+
start.id,
|
|
224
|
+
clamp(opts.depth, 2, MAX_DEPTH),
|
|
225
|
+
opts.category ?? null,
|
|
226
|
+
clamp(opts.limit, 50, MAX_LIMIT)
|
|
227
|
+
]
|
|
228
|
+
);
|
|
229
|
+
const paths = result.rows.map((r) => ({
|
|
230
|
+
target: r.name,
|
|
231
|
+
target_type: r.type,
|
|
232
|
+
category: r.category,
|
|
233
|
+
label: r.label,
|
|
234
|
+
evidence: r.evidence,
|
|
235
|
+
hops: r.hop
|
|
236
|
+
}));
|
|
237
|
+
paths.sort((a, b) => a.hops - b.hops || String(a.target).localeCompare(String(b.target)));
|
|
238
|
+
return { found: true, entity: { name: start.name, type: start.type }, paths, count: paths.length };
|
|
239
|
+
}
|
|
240
|
+
async function findRelated(pool, opts) {
|
|
241
|
+
const result = await pool.query(
|
|
242
|
+
`SELECT src.name AS src_name, src.type AS src_type, tgt.name AS tgt_name, tgt.type AS tgt_type,
|
|
243
|
+
r.category, r.label, r.evidence
|
|
244
|
+
FROM context_engine_entity_relationships r
|
|
245
|
+
JOIN context_engine_entities src ON src.id = r.source_entity_id
|
|
246
|
+
JOIN context_engine_entities tgt ON tgt.id = r.target_entity_id
|
|
247
|
+
WHERE ($4::text IS NULL OR r.category = $4::text)
|
|
248
|
+
AND ($5::text IS NULL OR r.label = $5::text)
|
|
249
|
+
AND ($6::text IS NULL OR src.type = $6::text OR tgt.type = $6::text)
|
|
250
|
+
${EDGE_VISIBLE}
|
|
251
|
+
ORDER BY src.name, tgt.name LIMIT $7`,
|
|
252
|
+
[
|
|
253
|
+
...scopeArgs(opts),
|
|
254
|
+
opts.category ?? null,
|
|
255
|
+
opts.label ?? null,
|
|
256
|
+
opts.entityType ?? null,
|
|
257
|
+
clamp(opts.limit, 50, MAX_LIMIT)
|
|
258
|
+
]
|
|
259
|
+
);
|
|
260
|
+
const relationships = result.rows.map((r) => ({
|
|
261
|
+
source: r.src_name,
|
|
262
|
+
source_type: r.src_type,
|
|
263
|
+
target: r.tgt_name,
|
|
264
|
+
target_type: r.tgt_type,
|
|
265
|
+
category: r.category,
|
|
266
|
+
label: r.label,
|
|
267
|
+
evidence: r.evidence
|
|
268
|
+
}));
|
|
269
|
+
return { found: true, relationships, count: relationships.length };
|
|
270
|
+
}
|
|
271
|
+
async function communitySummary(pool, opts) {
|
|
272
|
+
const allowed = await shouldUseCommunitySummaries(pool, {
|
|
273
|
+
sourceIds: opts.sourceIds ?? null,
|
|
274
|
+
principals: opts.principals ?? null
|
|
275
|
+
});
|
|
276
|
+
if (!allowed) {
|
|
277
|
+
return { available: false, error: SUMMARIES_WITHHELD, communities: [], count: 0 };
|
|
278
|
+
}
|
|
279
|
+
const vectors = await opts.embedder.embed([opts.query ?? ""], "query");
|
|
280
|
+
const vector = vectors?.[0];
|
|
281
|
+
if (!vector) return { available: true, communities: [], count: 0 };
|
|
282
|
+
const result = await pool.query(
|
|
283
|
+
`SELECT summary, entity_count, relationship_count, level,
|
|
284
|
+
1 - (embedding <=> CAST($1 AS vector))::float AS sim
|
|
285
|
+
FROM context_engine_communities
|
|
286
|
+
WHERE embedding IS NOT NULL AND summary IS NOT NULL
|
|
287
|
+
ORDER BY embedding <=> CAST($1 AS vector) LIMIT $2`,
|
|
288
|
+
[`[${vector.map((x) => Number(x)).join(",")}]`, clamp(opts.limit, 3, 10)]
|
|
289
|
+
);
|
|
290
|
+
const communities = result.rows.filter((r) => Number(r.sim) > MIN_COMMUNITY_RELEVANCE).map((r) => ({
|
|
291
|
+
summary: r.summary,
|
|
292
|
+
entity_count: r.entity_count,
|
|
293
|
+
relationship_count: r.relationship_count,
|
|
294
|
+
hierarchy_level: r.level,
|
|
295
|
+
relevance: Math.round(Number(r.sim) * 1e4) / 1e4
|
|
296
|
+
}));
|
|
297
|
+
return { available: true, communities, count: communities.length };
|
|
298
|
+
}
|
|
299
|
+
var SCOPE, EDGE_VISIBLE, ENTITY_VISIBLE, NOT_FOUND, MAX_DEPTH, MAX_LIMIT, MIN_COMMUNITY_RELEVANCE, SUMMARIES_WITHHELD;
|
|
300
|
+
var init_navigation = __esm({
|
|
301
|
+
"src/graph/navigation.ts"() {
|
|
302
|
+
init_retrieval();
|
|
303
|
+
SCOPE = `
|
|
304
|
+
AND ($1::text[] IS NULL OR c.source_id = ANY($1::text[]))
|
|
305
|
+
AND ($2::uuid[] IS NULL OR c.document_id = ANY($2::uuid[]))
|
|
306
|
+
AND ($3::text[] IS NULL OR c.acl IS NULL OR c.acl && $3::text[])
|
|
307
|
+
`;
|
|
308
|
+
EDGE_VISIBLE = `
|
|
309
|
+
AND (
|
|
310
|
+
($3::text[] IS NULL AND r.chunk_id IS NULL)
|
|
311
|
+
OR EXISTS (
|
|
312
|
+
SELECT 1 FROM context_engine_chunks c
|
|
313
|
+
WHERE c.id = r.chunk_id ${SCOPE}
|
|
314
|
+
)
|
|
315
|
+
)
|
|
316
|
+
`;
|
|
317
|
+
ENTITY_VISIBLE = `
|
|
318
|
+
EXISTS (
|
|
319
|
+
SELECT 1 FROM context_engine_chunk_entities ce
|
|
320
|
+
JOIN context_engine_chunks c ON c.id = ce.chunk_id
|
|
321
|
+
WHERE ce.entity_id = e.id ${SCOPE}
|
|
322
|
+
)
|
|
323
|
+
`;
|
|
324
|
+
NOT_FOUND = "entity not found";
|
|
325
|
+
MAX_DEPTH = 5;
|
|
326
|
+
MAX_LIMIT = 200;
|
|
327
|
+
MIN_COMMUNITY_RELEVANCE = 0.25;
|
|
328
|
+
SUMMARIES_WITHHELD = "community summaries are withheld: this corpus mixes access-controlled and open documents, and a community summary is computed over the whole corpus, so it cannot be shown to a caller who can only see part of it. Use search, traverse or get_neighbors instead \u2014 those are filtered per document.";
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// src/mcp.ts
|
|
333
|
+
init_errors();
|
|
334
|
+
init_extras();
|
|
335
|
+
var ENTITY_TYPES = [
|
|
336
|
+
"PERSON",
|
|
337
|
+
"ORG",
|
|
338
|
+
"PRODUCT",
|
|
339
|
+
"LOCATION",
|
|
340
|
+
"REFERENCE",
|
|
341
|
+
"TEMPORAL",
|
|
342
|
+
"CONCEPT"
|
|
343
|
+
];
|
|
344
|
+
var RELATIONSHIP_CATEGORY_VALUES = [
|
|
345
|
+
"HIERARCHICAL",
|
|
346
|
+
"MEMBERSHIP",
|
|
347
|
+
"CREATION",
|
|
348
|
+
"TEMPORAL",
|
|
349
|
+
"SPATIAL",
|
|
350
|
+
"REFERENCE",
|
|
351
|
+
"FUNCTIONAL",
|
|
352
|
+
"QUANTITATIVE"
|
|
353
|
+
];
|
|
354
|
+
new Set(RELATIONSHIP_CATEGORY_VALUES);
|
|
355
|
+
|
|
356
|
+
// src/chunkers.ts
|
|
357
|
+
init_text();
|
|
358
|
+
new Set(
|
|
359
|
+
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ \n\r\v\f"
|
|
360
|
+
);
|
|
361
|
+
function isTabularMime(mime) {
|
|
362
|
+
if (!mime) return false;
|
|
363
|
+
const m = mime.toLowerCase();
|
|
364
|
+
return ["csv", "sheet", "excel", "spreadsheetml", "tab-separated"].some((k) => m.includes(k));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// src/actions.ts
|
|
368
|
+
init_errors();
|
|
369
|
+
init_hooks();
|
|
370
|
+
init_llm();
|
|
371
|
+
init_redaction();
|
|
372
|
+
|
|
373
|
+
// src/sandbox.ts
|
|
374
|
+
init_errors();
|
|
375
|
+
|
|
376
|
+
// src/structured.ts
|
|
377
|
+
init_json();
|
|
378
|
+
init_llm();
|
|
379
|
+
init_text();
|
|
21
380
|
|
|
22
381
|
// src/sentinels.ts
|
|
23
382
|
var TRUSTED = /* @__PURE__ */ Symbol.for("context_engine.TRUSTED");
|
|
383
|
+
var UNSCOPED = /* @__PURE__ */ Symbol.for("context_engine.UNSCOPED");
|
|
384
|
+
init_extraction();
|
|
385
|
+
init_hooks();
|
|
386
|
+
|
|
387
|
+
// src/ingest.ts
|
|
388
|
+
init_redaction();
|
|
24
389
|
|
|
25
|
-
// src/
|
|
390
|
+
// src/actions.ts
|
|
391
|
+
var MAX_LIST_LIMIT = 200;
|
|
392
|
+
|
|
393
|
+
// src/knowledge-tool.ts
|
|
394
|
+
init_errors();
|
|
395
|
+
var KNOWLEDGE_ACTIONS = [
|
|
396
|
+
"discover",
|
|
397
|
+
"search",
|
|
398
|
+
"get_doc",
|
|
399
|
+
"list",
|
|
400
|
+
"query_meta",
|
|
401
|
+
"compute",
|
|
402
|
+
"get_chunks",
|
|
403
|
+
"get_docs",
|
|
404
|
+
"map_reduce",
|
|
405
|
+
"traverse",
|
|
406
|
+
"find_related",
|
|
407
|
+
"get_neighbors",
|
|
408
|
+
"community_summary"
|
|
409
|
+
];
|
|
410
|
+
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, says which are spreadsheets, and says which actions this deployment can run. 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.";
|
|
411
|
+
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.";
|
|
412
|
+
var ACTION_HELP = {
|
|
413
|
+
search: "passages by meaning or keywords; an ID, code or number as the BARE identifier",
|
|
414
|
+
get_doc: "one whole document by id \u2014 a clause, a policy, the full text",
|
|
415
|
+
list: "browse the documents without searching",
|
|
416
|
+
query_meta: "filter documents by structured fields (dates, amounts, categories)",
|
|
417
|
+
compute: "a figure DERIVED from the spreadsheets \u2014 total, average, count, ranking, margin, comparison, or the one row matching a value. Say what you want in plain words, not code: it runs over EVERY ROW of the sheets in scope, not a sample and not the excerpts search returned, so name the columns the way the sheet spells them and say which sheet if more than one could match. Never retype a figure from memory or from an excerpt \u2014 ask for it here",
|
|
418
|
+
get_chunks: "read one document in order, a range at a time \u2014 the long ones",
|
|
419
|
+
get_docs: "several whole documents at once, by id",
|
|
420
|
+
map_reduce: "ask the SAME question of every document in scope, one answer per document \u2014 for 'which contracts mention X', not for a figure (that is compute)",
|
|
421
|
+
get_neighbors: "what is ONE step from a named thing, and which way each link points",
|
|
422
|
+
traverse: "everything within a few steps of a named thing",
|
|
423
|
+
find_related: "connections of a given kind across the corpus, with no starting thing",
|
|
424
|
+
community_summary: "the themes the corpus groups into, ranked against a question"
|
|
425
|
+
};
|
|
426
|
+
var OFF = {
|
|
427
|
+
query_meta: "query_meta is off: this deployment has no LLM configured.",
|
|
428
|
+
compute: "compute is off: code execution is not enabled on this deployment. Quote the rows you found instead.",
|
|
429
|
+
map_reduce: "map_reduce is off: this deployment has no LLM configured. Use search, or read the documents with get_docs.",
|
|
430
|
+
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."
|
|
431
|
+
};
|
|
432
|
+
var GRAPH_ACTIONS = ["traverse", "find_related", "get_neighbors", "community_summary"];
|
|
433
|
+
var DOCUMENT_ID_ACTIONS = ["search", "compute", "get_docs", "map_reduce"];
|
|
434
|
+
var DEFAULT_GET_DOCS_CHARS = 2e5;
|
|
435
|
+
var INPUT_PROPERTIES = {
|
|
436
|
+
action: { type: "string", enum: [...KNOWLEDGE_ACTIONS], description: ACTION_PARAM_DESCRIPTION },
|
|
437
|
+
query: {
|
|
438
|
+
type: "string",
|
|
439
|
+
description: "What you are looking for, in words \u2014 or a BARE content identifier when you are looking one up. (for search, query_meta, compute, community_summary)"
|
|
440
|
+
},
|
|
441
|
+
document_id: {
|
|
442
|
+
type: "string",
|
|
443
|
+
description: "One document's id, as returned by discover, list, or a search hit. A system id, never something written inside a document. (for get_doc)"
|
|
444
|
+
},
|
|
445
|
+
source_ids: {
|
|
446
|
+
type: "array",
|
|
447
|
+
items: { type: "string" },
|
|
448
|
+
description: "Narrows to these sources, using ids from discover or a search hit. Intersected with what this deployment allows: ids outside it are ignored, not refused. (for discover, list, search, query_meta, compute, and the graph actions)"
|
|
449
|
+
},
|
|
450
|
+
document_ids: {
|
|
451
|
+
type: "array",
|
|
452
|
+
items: { type: "string" },
|
|
453
|
+
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)"
|
|
454
|
+
},
|
|
455
|
+
entity: {
|
|
456
|
+
type: "string",
|
|
457
|
+
description: "The NAME of a thing to start from \u2014 a person, an organisation, a product \u2014 spelled as it appears in the documents. A name, NOT AN ID: take one from discover's graph section, from a search hit, or from an earlier get_neighbors answer. (for traverse, get_neighbors)"
|
|
458
|
+
},
|
|
459
|
+
depth: {
|
|
460
|
+
type: "integer",
|
|
461
|
+
description: "How many hops out to walk, 1 to 5. Default 2. (for traverse)"
|
|
462
|
+
},
|
|
463
|
+
category: {
|
|
464
|
+
type: "string",
|
|
465
|
+
enum: [...RELATIONSHIP_CATEGORY_VALUES],
|
|
466
|
+
description: "The kind of connection to follow or look for. These are the only values the graph holds; see discover for which occur in this corpus. (for traverse, find_related)"
|
|
467
|
+
},
|
|
468
|
+
label: {
|
|
469
|
+
type: "string",
|
|
470
|
+
description: "The exact relationship wording, as extracted \u2014 for example reports_to, works_for, owns. Narrower than category; use it when you know the phrasing, otherwise use category. (for find_related)"
|
|
471
|
+
},
|
|
472
|
+
entity_type: {
|
|
473
|
+
type: "string",
|
|
474
|
+
enum: [...ENTITY_TYPES],
|
|
475
|
+
description: "Keep only relationships with an entity of this type on one end. (for find_related)"
|
|
476
|
+
},
|
|
477
|
+
top_k: {
|
|
478
|
+
type: "integer",
|
|
479
|
+
description: "How many passages to return. Default 10. (for search)"
|
|
480
|
+
},
|
|
481
|
+
mode: {
|
|
482
|
+
type: "string",
|
|
483
|
+
enum: ["hybrid", "graph"],
|
|
484
|
+
description: "How to rank. OMIT IT and the right one is worked out from the documents in scope: wording and meaning, plus how things are connected whenever those documents were linked up \u2014 which finds a passage that never repeats your words. Name 'hybrid' to force wording only, or 'graph' to force the connection signal on. (for search)"
|
|
485
|
+
},
|
|
486
|
+
limit: {
|
|
487
|
+
type: "integer",
|
|
488
|
+
description: "How many rows to return: documents for discover and list (default 50), candidates for query_meta (20), relationships or paths for the graph actions (50), communities for community_summary (3). (for discover, list, query_meta, and the graph actions)"
|
|
489
|
+
},
|
|
490
|
+
cursor: {
|
|
491
|
+
type: "string",
|
|
492
|
+
description: "The next_cursor a previous page returned, sent back verbatim to read the rest. (for discover, list)"
|
|
493
|
+
},
|
|
494
|
+
start: {
|
|
495
|
+
type: "integer",
|
|
496
|
+
description: "First chunk position to read, 0-based. Use the next_start a previous answer returned to continue. (for get_chunks)"
|
|
497
|
+
},
|
|
498
|
+
end: {
|
|
499
|
+
type: "integer",
|
|
500
|
+
description: "Last chunk position to read, inclusive. At most 25 chunks come back at a time whatever you ask for. (for get_chunks)"
|
|
501
|
+
},
|
|
502
|
+
max_chars: {
|
|
503
|
+
type: "integer",
|
|
504
|
+
description: "How much document text to return in total before stopping and handing back the ids it did not reach. (for get_docs)"
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
function resolveScope(value) {
|
|
508
|
+
if (value === UNSCOPED) return { sourceIds: null, documentIds: null };
|
|
509
|
+
if (value == null) {
|
|
510
|
+
throw new Error(
|
|
511
|
+
"scope is required: pass the source ids this tool may reach, or UNSCOPED (from @promptev/context-engine) to say the whole corpus on purpose."
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
if (Array.isArray(value)) {
|
|
515
|
+
return { sourceIds: [...new Set(value.map(String))], documentIds: null };
|
|
516
|
+
}
|
|
517
|
+
if (typeof value === "object") {
|
|
518
|
+
return {
|
|
519
|
+
sourceIds: value.sourceIds != null ? [...new Set(value.sourceIds.map(String))] : null,
|
|
520
|
+
documentIds: value.documentIds != null ? [...new Set(value.documentIds.map(String))] : null
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
throw new Error(`scope must be UNSCOPED, an array of source ids, or a Scope \u2014 got ${typeof value}`);
|
|
524
|
+
}
|
|
525
|
+
function narrowToCeiling(requested, ceiling) {
|
|
526
|
+
if (ceiling == null) return requested != null ? [...new Set(requested)] : null;
|
|
527
|
+
if (requested == null) return [...ceiling];
|
|
528
|
+
const allowed = new Set(ceiling);
|
|
529
|
+
return [...new Set(requested)].filter((r) => allowed.has(r));
|
|
530
|
+
}
|
|
531
|
+
function withinCeiling(documentId, ceiling) {
|
|
532
|
+
return ceiling.documentIds == null || ceiling.documentIds.includes(String(documentId));
|
|
533
|
+
}
|
|
534
|
+
function knowledgeActionsAvailable(engine, opts = {}) {
|
|
535
|
+
const hasLlm = engine.config.llm != null;
|
|
536
|
+
const graphOn = Boolean(engine.config.graph?.enabled);
|
|
537
|
+
return {
|
|
538
|
+
search: true,
|
|
539
|
+
get_doc: true,
|
|
540
|
+
list: true,
|
|
541
|
+
query_meta: hasLlm,
|
|
542
|
+
compute: opts.compute != null || hasLlm && Boolean(engine.config.enableCodeExecution),
|
|
543
|
+
get_chunks: true,
|
|
544
|
+
get_docs: true,
|
|
545
|
+
map_reduce: opts.mapReduce != null || hasLlm,
|
|
546
|
+
traverse: graphOn,
|
|
547
|
+
find_related: graphOn,
|
|
548
|
+
get_neighbors: graphOn,
|
|
549
|
+
community_summary: graphOn
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
function documentKind(doc) {
|
|
553
|
+
return isTabularMime(String(doc.mimeType ?? doc.mime_type ?? "")) ? "spreadsheet" : "text";
|
|
554
|
+
}
|
|
555
|
+
function parseCursor(cursor) {
|
|
556
|
+
if (cursor == null || cursor === "") return null;
|
|
557
|
+
if (typeof cursor === "object" && !Array.isArray(cursor)) return cursor;
|
|
558
|
+
let parsed = null;
|
|
559
|
+
try {
|
|
560
|
+
parsed = JSON.parse(String(cursor));
|
|
561
|
+
} catch {
|
|
562
|
+
parsed = null;
|
|
563
|
+
}
|
|
564
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
565
|
+
throw new Error(`invalid cursor: ${JSON.stringify(cursor)}`);
|
|
566
|
+
}
|
|
567
|
+
return parsed;
|
|
568
|
+
}
|
|
569
|
+
async function listPage(engine, sourceIds, principals, action, limit, cursor, ceiling, redaction) {
|
|
570
|
+
const page = await engine.listDocuments({
|
|
571
|
+
// `!= null`, NOT truthiness: an EMPTY array means "nothing is in scope"
|
|
572
|
+
// and collapsing it to null would list the whole corpus.
|
|
573
|
+
sourceIds: sourceIds != null ? [...new Set(sourceIds)] : null,
|
|
574
|
+
principals,
|
|
575
|
+
cursor,
|
|
576
|
+
limit: Math.max(1, Math.min(limit, MAX_LIST_LIMIT)),
|
|
577
|
+
redaction
|
|
578
|
+
});
|
|
579
|
+
let documents = (page.documents ?? []).map((raw) => ({
|
|
580
|
+
id: String(raw.id),
|
|
581
|
+
name: raw.name,
|
|
582
|
+
source_id: raw.sourceId ?? raw.source_id,
|
|
583
|
+
kind: documentKind(raw)
|
|
584
|
+
}));
|
|
585
|
+
if (ceiling.documentIds != null) {
|
|
586
|
+
const allowed = new Set(ceiling.documentIds);
|
|
587
|
+
documents = documents.filter((d) => allowed.has(d.id));
|
|
588
|
+
}
|
|
589
|
+
const out = {
|
|
590
|
+
documents,
|
|
591
|
+
count: documents.length,
|
|
592
|
+
has_more: Boolean(page.hasMore ?? page.has_more)
|
|
593
|
+
};
|
|
594
|
+
const next = page.nextCursor ?? page.next_cursor;
|
|
595
|
+
if (next != null) {
|
|
596
|
+
out.next_cursor = JSON.stringify(next);
|
|
597
|
+
out.next_page = { action, cursor: out.next_cursor };
|
|
598
|
+
}
|
|
599
|
+
return out;
|
|
600
|
+
}
|
|
601
|
+
async function callKnowledgeTool(engine, args) {
|
|
602
|
+
const action = args.action;
|
|
603
|
+
const principals = args.principals;
|
|
604
|
+
const ceiling = resolveScope(args.scope);
|
|
605
|
+
const requestedDocumentIds = args.document_ids;
|
|
606
|
+
const sourceIds = narrowToCeiling(args.source_ids, ceiling.sourceIds);
|
|
607
|
+
const documentIds = narrowToCeiling(args.document_ids, ceiling.documentIds);
|
|
608
|
+
const text = String(args.query ?? "").trim();
|
|
609
|
+
const available = knowledgeActionsAvailable(engine, {
|
|
610
|
+
compute: args.compute,
|
|
611
|
+
mapReduce: args.map_reduce
|
|
612
|
+
});
|
|
613
|
+
if (!KNOWLEDGE_ACTIONS.includes(action)) {
|
|
614
|
+
return {
|
|
615
|
+
success: false,
|
|
616
|
+
error: `unknown action '${action}' \u2014 use one of: ${KNOWLEDGE_ACTIONS.join(", ")}`
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
if (requestedDocumentIds?.length && !DOCUMENT_ID_ACTIONS.includes(action)) {
|
|
620
|
+
return {
|
|
621
|
+
success: false,
|
|
622
|
+
error: `document_ids is not honored by ${action} \u2014 only by ${DOCUMENT_ID_ACTIONS.join(", ")}. Narrow a listing with source_ids, or read one document with get_doc.`
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
if (GRAPH_ACTIONS.includes(action) && !available[action]) {
|
|
626
|
+
return { success: false, error: OFF.graph };
|
|
627
|
+
}
|
|
628
|
+
if (action === "discover" || action === "list") {
|
|
629
|
+
const page = await listPage(
|
|
630
|
+
engine,
|
|
631
|
+
sourceIds,
|
|
632
|
+
principals,
|
|
633
|
+
action,
|
|
634
|
+
args.limit ?? 50,
|
|
635
|
+
parseCursor(args.cursor),
|
|
636
|
+
ceiling,
|
|
637
|
+
args.redaction
|
|
638
|
+
);
|
|
639
|
+
if (action === "list") return { success: true, ...page };
|
|
640
|
+
const spreadsheets = page.documents.filter((d) => d.kind === "spreadsheet").map((d) => d.name);
|
|
641
|
+
const forAFact = { action: "search", query: "<bare identifier or key words>" };
|
|
642
|
+
const nextAction = {};
|
|
643
|
+
if (spreadsheets.length && available.compute) {
|
|
644
|
+
nextAction["for a figure from a spreadsheet"] = {
|
|
645
|
+
action: "compute",
|
|
646
|
+
query: "<what to compute, columns as named>"
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
nextAction["for a clause or a fact"] = forAFact;
|
|
650
|
+
if (available.get_neighbors) {
|
|
651
|
+
nextAction["for how things connect"] = {
|
|
652
|
+
action: "get_neighbors",
|
|
653
|
+
entity: "<a name that appears in the documents>"
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
return {
|
|
657
|
+
success: true,
|
|
658
|
+
...page,
|
|
659
|
+
spreadsheets,
|
|
660
|
+
available_actions: Object.fromEntries(
|
|
661
|
+
Object.keys(ACTION_HELP).map((name) => [
|
|
662
|
+
name,
|
|
663
|
+
available[name] ? ACTION_HELP[name] : `${ACTION_HELP[name]} (OFF)`
|
|
664
|
+
])
|
|
665
|
+
),
|
|
666
|
+
next_action: nextAction
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
if (action === "search") {
|
|
670
|
+
if (!text) return { success: false, error: "search needs a query" };
|
|
671
|
+
const result = await engine.search(text, {
|
|
672
|
+
sourceIds,
|
|
673
|
+
documentIds,
|
|
674
|
+
principals,
|
|
675
|
+
topK: args.top_k ?? 10,
|
|
676
|
+
// Omitted means "work it out from the documents in scope".
|
|
677
|
+
mode: args.mode ?? null,
|
|
678
|
+
redaction: args.redaction
|
|
679
|
+
});
|
|
680
|
+
return {
|
|
681
|
+
success: true,
|
|
682
|
+
hits: (result.hits ?? []).map((hit) => {
|
|
683
|
+
const h = hit;
|
|
684
|
+
return {
|
|
685
|
+
document_id: h.document_id ?? h.documentId,
|
|
686
|
+
document_name: h.document_name ?? h.documentName,
|
|
687
|
+
chunk_text: h.chunk_text ?? h.chunkText,
|
|
688
|
+
score: h.score,
|
|
689
|
+
source_id: h.source_id ?? h.sourceId
|
|
690
|
+
};
|
|
691
|
+
}),
|
|
692
|
+
usage: result.usage
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
if (action === "get_doc") {
|
|
696
|
+
const documentId = args.document_id;
|
|
697
|
+
if (!documentId) return { success: false, error: "get_doc needs a document_id" };
|
|
698
|
+
if (!withinCeiling(documentId, ceiling)) {
|
|
699
|
+
return { success: false, error: `document not found: ${documentId}` };
|
|
700
|
+
}
|
|
701
|
+
try {
|
|
702
|
+
const document = await engine.getDocument(documentId, {
|
|
703
|
+
principals,
|
|
704
|
+
redaction: args.redaction
|
|
705
|
+
});
|
|
706
|
+
const src = document?.sourceId ?? document?.source_id;
|
|
707
|
+
if (ceiling.sourceIds != null && !ceiling.sourceIds.includes(String(src))) {
|
|
708
|
+
return { success: false, error: `document not found: ${documentId}` };
|
|
709
|
+
}
|
|
710
|
+
return { success: true, document };
|
|
711
|
+
} catch (err) {
|
|
712
|
+
if (err instanceof DocumentNotFoundError) return { success: false, error: err.message };
|
|
713
|
+
throw err;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
if (action === "query_meta") {
|
|
717
|
+
if (!available.query_meta || !engine.queryStructured) return { success: false, error: OFF.query_meta };
|
|
718
|
+
if (!text) return { success: false, error: "query_meta needs a query" };
|
|
719
|
+
const out = await engine.queryStructured(text, {
|
|
720
|
+
sourceIds,
|
|
721
|
+
principals,
|
|
722
|
+
limit: Math.max(1, Math.min(args.limit ?? 20, 100)),
|
|
723
|
+
redaction: args.redaction
|
|
724
|
+
});
|
|
725
|
+
return { success: true, ...out };
|
|
726
|
+
}
|
|
727
|
+
if (action === "compute") {
|
|
728
|
+
if (!available.compute) return { success: false, error: OFF.compute };
|
|
729
|
+
if (!text) return { success: false, error: "compute needs a query: what to compute, in plain words" };
|
|
730
|
+
const runner = args.compute ?? engine.compute;
|
|
731
|
+
if (!runner) return { success: false, error: OFF.compute };
|
|
732
|
+
try {
|
|
733
|
+
const out = await runner(text, { sourceIds, documentIds, principals });
|
|
734
|
+
return { success: true, ...out };
|
|
735
|
+
} catch (err) {
|
|
736
|
+
if (err instanceof EngineActionError) return { success: false, error: err.message };
|
|
737
|
+
throw err;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
if (action === "get_chunks") {
|
|
741
|
+
const documentId = args.document_id;
|
|
742
|
+
if (!documentId) return { success: false, error: "get_chunks needs a document_id" };
|
|
743
|
+
if (!withinCeiling(documentId, ceiling)) {
|
|
744
|
+
return { success: false, error: `document not found: ${documentId}` };
|
|
745
|
+
}
|
|
746
|
+
try {
|
|
747
|
+
const page = await engine.getChunks(documentId, {
|
|
748
|
+
principals,
|
|
749
|
+
start: args.start,
|
|
750
|
+
end: args.end,
|
|
751
|
+
redaction: args.redaction
|
|
752
|
+
});
|
|
753
|
+
if (ceiling.sourceIds != null) {
|
|
754
|
+
const doc = await engine.getDocument(documentId, { principals });
|
|
755
|
+
const src = doc?.sourceId ?? doc?.source_id;
|
|
756
|
+
if (!ceiling.sourceIds.includes(String(src))) {
|
|
757
|
+
return { success: false, error: `document not found: ${documentId}` };
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
const out = { success: true, ...page };
|
|
761
|
+
if (page.has_more) {
|
|
762
|
+
out.next_page = {
|
|
763
|
+
action: "get_chunks",
|
|
764
|
+
document_id: String(documentId),
|
|
765
|
+
start: page.next_start
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
return out;
|
|
769
|
+
} catch (err) {
|
|
770
|
+
if (err instanceof DocumentNotFoundError) return { success: false, error: err.message };
|
|
771
|
+
throw err;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
if (action === "get_docs") {
|
|
775
|
+
if (!documentIds?.length) return { success: false, error: "get_docs needs document_ids" };
|
|
776
|
+
const docs = await engine.getDocuments(documentIds, { principals, redaction: args.redaction });
|
|
777
|
+
const budget = Math.max(1e3, Math.trunc(args.max_chars || DEFAULT_GET_DOCS_CHARS));
|
|
778
|
+
const kept = [];
|
|
779
|
+
let used = 0;
|
|
780
|
+
for (const doc of docs) {
|
|
781
|
+
const size = String(doc.text ?? "").length;
|
|
782
|
+
if (kept.length && used + size > budget) break;
|
|
783
|
+
kept.push(doc);
|
|
784
|
+
used += size;
|
|
785
|
+
}
|
|
786
|
+
const returned = new Set(kept.map((d) => String(d.id)));
|
|
787
|
+
const remaining = (args.document_ids ?? []).filter((d) => !returned.has(String(d)));
|
|
788
|
+
const out = { success: true, documents: kept, count: kept.length };
|
|
789
|
+
if (remaining.length) {
|
|
790
|
+
out.remaining_document_ids = remaining;
|
|
791
|
+
out.next_page = { action: "get_docs", document_ids: remaining };
|
|
792
|
+
}
|
|
793
|
+
return out;
|
|
794
|
+
}
|
|
795
|
+
if (action === "map_reduce") {
|
|
796
|
+
if (!available.map_reduce) return { success: false, error: OFF.map_reduce };
|
|
797
|
+
if (!text) {
|
|
798
|
+
return {
|
|
799
|
+
success: false,
|
|
800
|
+
error: "map_reduce needs a query: the question to ask of each document"
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
const runner = args.map_reduce ?? engine.mapReduce;
|
|
804
|
+
if (!runner) return { success: false, error: OFF.map_reduce };
|
|
805
|
+
try {
|
|
806
|
+
const out = await runner(text, {
|
|
807
|
+
sourceIds,
|
|
808
|
+
documentIds,
|
|
809
|
+
principals,
|
|
810
|
+
limit: args.limit
|
|
811
|
+
});
|
|
812
|
+
return { success: true, ...out };
|
|
813
|
+
} catch (err) {
|
|
814
|
+
if (err instanceof EngineActionError) return { success: false, error: err.message };
|
|
815
|
+
throw err;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return callGraphAction(engine, args, { sourceIds, principals, text });
|
|
819
|
+
}
|
|
820
|
+
async function callGraphAction(engine, args, ctx) {
|
|
821
|
+
const nav = await Promise.resolve().then(() => (init_navigation(), navigation_exports));
|
|
822
|
+
const pool = await engine.ensurePool?.();
|
|
823
|
+
const principals = ctx.principals ?? null;
|
|
824
|
+
const scoped = { sourceIds: ctx.sourceIds, principals };
|
|
825
|
+
if (args.action === "community_summary") {
|
|
826
|
+
if (!ctx.text) return { success: false, error: "community_summary needs a query" };
|
|
827
|
+
const out2 = await nav.communitySummary(pool, {
|
|
828
|
+
embedder: engine.embedder,
|
|
829
|
+
query: ctx.text,
|
|
830
|
+
limit: args.limit,
|
|
831
|
+
sourceIds: ctx.sourceIds,
|
|
832
|
+
principals
|
|
833
|
+
});
|
|
834
|
+
if (!out2.available) return { success: false, error: out2.error };
|
|
835
|
+
return { success: true, communities: out2.communities, count: out2.count };
|
|
836
|
+
}
|
|
837
|
+
if (args.action === "find_related") {
|
|
838
|
+
if (!(args.category || args.label || args.entity_type)) {
|
|
839
|
+
return {
|
|
840
|
+
success: false,
|
|
841
|
+
error: "find_related needs a category, a label or an entity_type to look for"
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
const out2 = await nav.findRelated(pool, {
|
|
845
|
+
...scoped,
|
|
846
|
+
category: args.category,
|
|
847
|
+
label: args.label,
|
|
848
|
+
entityType: args.entity_type,
|
|
849
|
+
limit: args.limit
|
|
850
|
+
});
|
|
851
|
+
return { success: true, relationships: out2.relationships, count: out2.count };
|
|
852
|
+
}
|
|
853
|
+
if (!args.entity) {
|
|
854
|
+
return {
|
|
855
|
+
success: false,
|
|
856
|
+
error: `${args.action} needs an entity: the name of a thing to start from`
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
if (args.action === "get_neighbors") {
|
|
860
|
+
const out2 = await nav.getNeighbors(pool, { ...scoped, entity: args.entity, limit: args.limit });
|
|
861
|
+
if (!out2.found) return { success: false, error: out2.error };
|
|
862
|
+
return { success: true, entity: out2.entity, neighbors: out2.neighbors, count: out2.count };
|
|
863
|
+
}
|
|
864
|
+
const out = await nav.traverse(pool, {
|
|
865
|
+
...scoped,
|
|
866
|
+
entity: args.entity,
|
|
867
|
+
depth: args.depth,
|
|
868
|
+
category: args.category,
|
|
869
|
+
limit: args.limit
|
|
870
|
+
});
|
|
871
|
+
if (!out.found) return { success: false, error: out.error };
|
|
872
|
+
return { success: true, entity: out.entity, paths: out.paths, count: out.count };
|
|
873
|
+
}
|
|
26
874
|
var HandlerError = class extends Error {
|
|
27
875
|
status;
|
|
28
876
|
detail;
|
|
@@ -131,6 +979,9 @@ function registerToolGateway(mcp, engine, principals, approvalScope = null) {
|
|
|
131
979
|
var __version__ = "0.0.0";
|
|
132
980
|
|
|
133
981
|
// src/mcp.ts
|
|
982
|
+
function described(name) {
|
|
983
|
+
return String(INPUT_PROPERTIES[name]?.description ?? "");
|
|
984
|
+
}
|
|
134
985
|
function asMcpResult(data) {
|
|
135
986
|
return { content: [{ type: "text", text: JSON.stringify(data) }] };
|
|
136
987
|
}
|
|
@@ -138,6 +989,11 @@ async function createMcpApp(engine, opts) {
|
|
|
138
989
|
if (!opts?.principals) {
|
|
139
990
|
throw new TypeError("createMcpApp requires principals");
|
|
140
991
|
}
|
|
992
|
+
if (opts.scope === void 0 || opts.scope === null) {
|
|
993
|
+
throw new TypeError(
|
|
994
|
+
"createMcpApp requires scope: the source ids this tool may reach, or UNSCOPED (from @promptev/context-engine) to say the whole corpus on purpose."
|
|
995
|
+
);
|
|
996
|
+
}
|
|
141
997
|
let McpServer;
|
|
142
998
|
let StreamableHTTPServerTransport;
|
|
143
999
|
try {
|
|
@@ -164,83 +1020,53 @@ async function createMcpApp(engine, opts) {
|
|
|
164
1020
|
};
|
|
165
1021
|
tool(
|
|
166
1022
|
"search_knowledge_base",
|
|
167
|
-
|
|
1023
|
+
`${KNOWLEDGE_TOOL_DESCRIPTION}${SCOPE_NOTE}`,
|
|
168
1024
|
{
|
|
169
1025
|
// Zod RAW SHAPES, not JSON schema: the SDK's isZodRawShape test
|
|
170
1026
|
// rejects a plain schema object — on current SDK versions that made
|
|
171
1027
|
// registration THROW at startup, and on 1.12.0 the object was consumed
|
|
172
1028
|
// as annotations and every handler ran with NO arguments.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
1029
|
+
// Every `.describe()` comes from the ONE property table, so the schema
|
|
1030
|
+
// a model reads over the protocol and the exported JSON Schema cannot
|
|
1031
|
+
// say different things.
|
|
1032
|
+
action: z.enum(KNOWLEDGE_ACTIONS).describe(described("action")),
|
|
1033
|
+
query: z.string().optional().describe(described("query")),
|
|
1034
|
+
document_id: z.string().optional().describe(described("document_id")),
|
|
1035
|
+
source_ids: z.array(z.string()).optional().describe(described("source_ids")),
|
|
1036
|
+
document_ids: z.array(z.string()).optional().describe(described("document_ids")),
|
|
1037
|
+
entity: z.string().optional().describe(described("entity")),
|
|
1038
|
+
depth: z.number().int().optional().describe(described("depth")),
|
|
1039
|
+
category: z.enum(RELATIONSHIP_CATEGORY_VALUES).optional().describe(described("category")),
|
|
1040
|
+
label: z.string().optional().describe(described("label")),
|
|
1041
|
+
entity_type: z.enum(ENTITY_TYPES).optional().describe(described("entity_type")),
|
|
1042
|
+
top_k: z.number().int().optional().describe(described("top_k")),
|
|
1043
|
+
mode: z.enum(["hybrid", "graph"]).optional().describe(described("mode")),
|
|
1044
|
+
limit: z.number().int().optional().describe(described("limit")),
|
|
1045
|
+
cursor: z.union([z.string(), z.record(z.unknown())]).optional().describe(described("cursor")),
|
|
1046
|
+
start: z.number().int().optional().describe(described("start")),
|
|
1047
|
+
end: z.number().int().optional().describe(described("end")),
|
|
1048
|
+
max_chars: z.number().int().optional().describe(described("max_chars"))
|
|
178
1049
|
},
|
|
179
1050
|
async (args) => {
|
|
180
|
-
|
|
1051
|
+
const documentIds = args.document_ids;
|
|
1052
|
+
const documentId = args.document_id;
|
|
1053
|
+
for (const did of [...documentIds ?? [], ...documentId ? [documentId] : []]) {
|
|
181
1054
|
requireValidUuid(did);
|
|
182
1055
|
}
|
|
183
1056
|
const callerPrincipals = await resolvePrincipalsFn(opts.principals);
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
1057
|
+
const ceiling = typeof opts.scope === "function" ? await opts.scope() : opts.scope;
|
|
1058
|
+
const policy = typeof opts.redaction === "function" ? await opts.redaction() : opts.redaction;
|
|
1059
|
+
return callKnowledgeTool(engine, {
|
|
1060
|
+
...args,
|
|
1061
|
+
action: String(args.action),
|
|
187
1062
|
principals: callerPrincipals,
|
|
188
|
-
|
|
189
|
-
|
|
1063
|
+
scope: ceiling,
|
|
1064
|
+
redaction: policy,
|
|
1065
|
+
compute: opts.compute ?? null,
|
|
1066
|
+
map_reduce: opts.mapReduce ?? null
|
|
190
1067
|
});
|
|
191
|
-
return {
|
|
192
|
-
hits: (result.hits ?? []).map((hit) => {
|
|
193
|
-
const h = hit;
|
|
194
|
-
return {
|
|
195
|
-
document_name: h.document_name ?? h.documentName,
|
|
196
|
-
chunk_text: h.chunk_text ?? h.chunkText,
|
|
197
|
-
score: h.score,
|
|
198
|
-
source_id: h.source_id ?? h.sourceId
|
|
199
|
-
};
|
|
200
|
-
}),
|
|
201
|
-
usage: result.usage
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
);
|
|
205
|
-
tool(
|
|
206
|
-
"get_document",
|
|
207
|
-
`Fetch one document's full text and metadata by id.${SCOPE_NOTE}`,
|
|
208
|
-
{ document_id: z.string() },
|
|
209
|
-
async (args) => {
|
|
210
|
-
const callerPrincipals = await resolvePrincipalsFn(opts.principals);
|
|
211
|
-
return engine.getDocument(String(args.document_id), { principals: callerPrincipals });
|
|
212
1068
|
}
|
|
213
1069
|
);
|
|
214
|
-
if (engine.config.llm != null) {
|
|
215
|
-
tool(
|
|
216
|
-
"query_structured",
|
|
217
|
-
`Answer a question against documents' extracted structured data (only documents with structured data are candidates).${SCOPE_NOTE}`,
|
|
218
|
-
{ question: z.string(), source_ids: z.array(z.string()).optional() },
|
|
219
|
-
async (args) => {
|
|
220
|
-
const callerPrincipals = await resolvePrincipalsFn(opts.principals);
|
|
221
|
-
if (!engine.queryStructured) throw new Error("queryStructured is not available on this engine");
|
|
222
|
-
return engine.queryStructured(String(args.question), {
|
|
223
|
-
sourceIds: args.source_ids,
|
|
224
|
-
principals: callerPrincipals
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
);
|
|
228
|
-
if (engine.config.enableCodeExecution) {
|
|
229
|
-
tool(
|
|
230
|
-
"compute",
|
|
231
|
-
`Run LLM-authored JavaScript over in-scope spreadsheet documents and return the computed result.${SCOPE_NOTE}`,
|
|
232
|
-
{ instruction: z.string(), source_ids: z.array(z.string()).optional() },
|
|
233
|
-
async (args) => {
|
|
234
|
-
const callerPrincipals = await resolvePrincipalsFn(opts.principals);
|
|
235
|
-
if (!engine.compute) throw new Error("compute is not available on this engine");
|
|
236
|
-
return engine.compute(String(args.instruction), {
|
|
237
|
-
sourceIds: args.source_ids,
|
|
238
|
-
principals: callerPrincipals
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
1070
|
registerToolGateway(
|
|
245
1071
|
{
|
|
246
1072
|
tool: (name, description, schema, handler2) => {
|