@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/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
- // src/mcp.ts
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 ExtraMissingError = class extends Error {
7
- constructor(extra, pkg, what) {
8
- super(`${what} requires the '${pkg}' package (optional extra: ${extra}): npm install ${pkg}`);
9
- this.name = "ExtraMissingError";
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,863 @@ 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/routing-core.ts
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 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.";
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", "discover", "list"];
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. 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)"
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, documentIds, 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
+ // Already intersected with the host's ceiling by `narrowToCeiling`, and
575
+ // filtered in SQL rather than after the page is built — three named
576
+ // documents sitting on page four must come back as themselves, not as an
577
+ // empty page.
578
+ documentIds: documentIds != null ? [...new Set(documentIds)] : null,
579
+ principals,
580
+ cursor,
581
+ limit: Math.max(1, Math.min(limit, MAX_LIST_LIMIT)),
582
+ redaction
583
+ });
584
+ let documents = (page.documents ?? []).map((raw) => ({
585
+ id: String(raw.id),
586
+ name: raw.name,
587
+ source_id: raw.sourceId ?? raw.source_id,
588
+ kind: documentKind(raw),
589
+ document_type: raw.documentType ?? raw.document_type ?? null,
590
+ mode: raw.mode ?? null
591
+ }));
592
+ if (ceiling.documentIds != null) {
593
+ const allowed = new Set(ceiling.documentIds);
594
+ documents = documents.filter((d) => allowed.has(d.id));
595
+ }
596
+ const out = {
597
+ documents,
598
+ count: documents.length,
599
+ has_more: Boolean(page.hasMore ?? page.has_more)
600
+ };
601
+ const next = page.nextCursor ?? page.next_cursor;
602
+ if (next != null) {
603
+ out.next_cursor = JSON.stringify(next);
604
+ out.next_page = { action, cursor: out.next_cursor };
605
+ }
606
+ return out;
607
+ }
608
+ async function callKnowledgeTool(engine, args) {
609
+ const action = args.action;
610
+ const principals = args.principals;
611
+ const ceiling = resolveScope(args.scope);
612
+ const requestedDocumentIds = args.document_ids;
613
+ const sourceIds = narrowToCeiling(args.source_ids, ceiling.sourceIds);
614
+ const documentIds = narrowToCeiling(args.document_ids, ceiling.documentIds);
615
+ const text = String(args.query ?? "").trim();
616
+ const available = knowledgeActionsAvailable(engine, {
617
+ compute: args.compute,
618
+ mapReduce: args.map_reduce
619
+ });
620
+ if (!KNOWLEDGE_ACTIONS.includes(action)) {
621
+ return {
622
+ success: false,
623
+ error: `unknown action '${action}' \u2014 use one of: ${KNOWLEDGE_ACTIONS.join(", ")}`
624
+ };
625
+ }
626
+ if (requestedDocumentIds?.length && !DOCUMENT_ID_ACTIONS.includes(action)) {
627
+ return {
628
+ success: false,
629
+ 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.`
630
+ };
631
+ }
632
+ if (GRAPH_ACTIONS.includes(action) && !available[action]) {
633
+ return { success: false, error: OFF.graph };
634
+ }
635
+ if (action === "discover" || action === "list") {
636
+ const page = await listPage(
637
+ engine,
638
+ sourceIds,
639
+ principals,
640
+ action,
641
+ args.limit ?? 50,
642
+ parseCursor(args.cursor),
643
+ documentIds,
644
+ ceiling,
645
+ args.redaction
646
+ );
647
+ if (action === "list") return { success: true, ...page };
648
+ const structures = await engine.documentStructure({
649
+ documentIds: page.documents.map((d) => d.id),
650
+ sourceIds,
651
+ principals,
652
+ // The cap is for the call that did NOT name its documents. A caller
653
+ // that asked about specific documents asked for all of them, and the
654
+ // truncated payload tells it to make exactly this call — so answering
655
+ // it truncated again would be a loop.
656
+ bounded: !requestedDocumentIds?.length,
657
+ redaction: args.redaction
658
+ });
659
+ for (const doc of page.documents) doc.structure = structures[doc.id] ?? {};
660
+ const hasSpreadsheet = page.documents.some((d) => d.kind === "spreadsheet");
661
+ const fieldsByType = await engine.fieldSummary({
662
+ sourceIds,
663
+ documentIds,
664
+ principals,
665
+ redaction: args.redaction
666
+ });
667
+ const census = await engine.documentTypes({
668
+ sourceIds,
669
+ documentIds,
670
+ principals,
671
+ redaction: args.redaction
672
+ });
673
+ const forAFact = { action: "search", query: "<bare identifier or key words>" };
674
+ const nextAction = {};
675
+ if (hasSpreadsheet && available.compute) {
676
+ nextAction["for a figure from a spreadsheet"] = {
677
+ action: "compute",
678
+ query: "<what to compute, columns as named above>"
679
+ };
680
+ }
681
+ nextAction["for a clause or a fact"] = forAFact;
682
+ if (fieldsByType.length && available.query_meta) {
683
+ nextAction["for documents by a field value"] = {
684
+ action: "query_meta",
685
+ query: "<a question naming a field from fields_by_type>"
686
+ };
687
+ }
688
+ if (available.get_neighbors) {
689
+ nextAction["for how things connect"] = {
690
+ action: "get_neighbors",
691
+ entity: "<a name that appears in the documents>"
692
+ };
693
+ }
694
+ const discovered = {
695
+ success: true,
696
+ ...page,
697
+ document_types: census,
698
+ fields_by_type: fieldsByType,
699
+ available_actions: Object.fromEntries(
700
+ Object.keys(ACTION_HELP).map((name) => [
701
+ name,
702
+ available[name] ? ACTION_HELP[name] : `${ACTION_HELP[name]} (OFF)`
703
+ ])
704
+ ),
705
+ next_action: nextAction
706
+ };
707
+ return discovered;
708
+ }
709
+ if (action === "search") {
710
+ if (!text) return { success: false, error: "search needs a query" };
711
+ const result = await engine.search(text, {
712
+ sourceIds,
713
+ documentIds,
714
+ principals,
715
+ topK: args.top_k ?? 10,
716
+ // Omitted means "work it out from the documents in scope".
717
+ mode: args.mode ?? null,
718
+ redaction: args.redaction
719
+ });
720
+ return {
721
+ success: true,
722
+ hits: (result.hits ?? []).map((hit) => {
723
+ const h = hit;
724
+ return {
725
+ document_id: h.document_id ?? h.documentId,
726
+ document_name: h.document_name ?? h.documentName,
727
+ chunk_text: h.chunk_text ?? h.chunkText,
728
+ score: h.score,
729
+ source_id: h.source_id ?? h.sourceId
730
+ };
731
+ }),
732
+ usage: result.usage
733
+ };
734
+ }
735
+ if (action === "get_doc") {
736
+ const documentId = args.document_id;
737
+ if (!documentId) return { success: false, error: "get_doc needs a document_id" };
738
+ if (!withinCeiling(documentId, ceiling)) {
739
+ return { success: false, error: `document not found: ${documentId}` };
740
+ }
741
+ try {
742
+ const document = await engine.getDocument(documentId, {
743
+ principals,
744
+ redaction: args.redaction
745
+ });
746
+ const src = document?.sourceId ?? document?.source_id;
747
+ if (ceiling.sourceIds != null && !ceiling.sourceIds.includes(String(src))) {
748
+ return { success: false, error: `document not found: ${documentId}` };
749
+ }
750
+ return { success: true, document };
751
+ } catch (err) {
752
+ if (err instanceof DocumentNotFoundError) return { success: false, error: err.message };
753
+ throw err;
754
+ }
755
+ }
756
+ if (action === "query_meta") {
757
+ if (!available.query_meta || !engine.queryStructured) return { success: false, error: OFF.query_meta };
758
+ if (!text) return { success: false, error: "query_meta needs a query" };
759
+ const out = await engine.queryStructured(text, {
760
+ sourceIds,
761
+ principals,
762
+ limit: Math.max(1, Math.min(args.limit ?? 20, 100)),
763
+ redaction: args.redaction
764
+ });
765
+ return { success: true, ...out };
766
+ }
767
+ if (action === "compute") {
768
+ if (!available.compute) return { success: false, error: OFF.compute };
769
+ if (!text) return { success: false, error: "compute needs a query: what to compute, in plain words" };
770
+ const runner = args.compute ?? engine.compute;
771
+ if (!runner) return { success: false, error: OFF.compute };
772
+ try {
773
+ const out = await runner(text, { sourceIds, documentIds, principals });
774
+ return { success: true, ...out };
775
+ } catch (err) {
776
+ if (err instanceof EngineActionError) return { success: false, error: err.message };
777
+ throw err;
778
+ }
779
+ }
780
+ if (action === "get_chunks") {
781
+ const documentId = args.document_id;
782
+ if (!documentId) return { success: false, error: "get_chunks needs a document_id" };
783
+ if (!withinCeiling(documentId, ceiling)) {
784
+ return { success: false, error: `document not found: ${documentId}` };
785
+ }
786
+ try {
787
+ const page = await engine.getChunks(documentId, {
788
+ principals,
789
+ start: args.start,
790
+ end: args.end,
791
+ redaction: args.redaction
792
+ });
793
+ if (ceiling.sourceIds != null) {
794
+ const doc = await engine.getDocument(documentId, { principals });
795
+ const src = doc?.sourceId ?? doc?.source_id;
796
+ if (!ceiling.sourceIds.includes(String(src))) {
797
+ return { success: false, error: `document not found: ${documentId}` };
798
+ }
799
+ }
800
+ const out = { success: true, ...page };
801
+ if (page.has_more) {
802
+ out.next_page = {
803
+ action: "get_chunks",
804
+ document_id: String(documentId),
805
+ start: page.next_start
806
+ };
807
+ }
808
+ return out;
809
+ } catch (err) {
810
+ if (err instanceof DocumentNotFoundError) return { success: false, error: err.message };
811
+ throw err;
812
+ }
813
+ }
814
+ if (action === "get_docs") {
815
+ if (!documentIds?.length) return { success: false, error: "get_docs needs document_ids" };
816
+ const docs = await engine.getDocuments(documentIds, { principals, redaction: args.redaction });
817
+ const budget = Math.max(1e3, Math.trunc(args.max_chars || DEFAULT_GET_DOCS_CHARS));
818
+ const kept = [];
819
+ let used = 0;
820
+ for (const doc of docs) {
821
+ const size = String(doc.text ?? "").length;
822
+ if (kept.length && used + size > budget) break;
823
+ kept.push(doc);
824
+ used += size;
825
+ }
826
+ const returned = new Set(kept.map((d) => String(d.id)));
827
+ const remaining = (args.document_ids ?? []).filter((d) => !returned.has(String(d)));
828
+ const out = { success: true, documents: kept, count: kept.length };
829
+ if (remaining.length) {
830
+ out.remaining_document_ids = remaining;
831
+ out.next_page = { action: "get_docs", document_ids: remaining };
832
+ }
833
+ return out;
834
+ }
835
+ if (action === "map_reduce") {
836
+ if (!available.map_reduce) return { success: false, error: OFF.map_reduce };
837
+ if (!text) {
838
+ return {
839
+ success: false,
840
+ error: "map_reduce needs a query: the question to ask of each document"
841
+ };
842
+ }
843
+ const runner = args.map_reduce ?? engine.mapReduce;
844
+ if (!runner) return { success: false, error: OFF.map_reduce };
845
+ try {
846
+ const out = await runner(text, {
847
+ sourceIds,
848
+ documentIds,
849
+ principals,
850
+ limit: args.limit
851
+ });
852
+ return { success: true, ...out };
853
+ } catch (err) {
854
+ if (err instanceof EngineActionError) return { success: false, error: err.message };
855
+ throw err;
856
+ }
857
+ }
858
+ return callGraphAction(engine, args, { sourceIds, principals, text });
859
+ }
860
+ async function callGraphAction(engine, args, ctx) {
861
+ const nav = await Promise.resolve().then(() => (init_navigation(), navigation_exports));
862
+ const pool = await engine.ensurePool?.();
863
+ const principals = ctx.principals ?? null;
864
+ const scoped = { sourceIds: ctx.sourceIds, principals };
865
+ if (args.action === "community_summary") {
866
+ if (!ctx.text) return { success: false, error: "community_summary needs a query" };
867
+ const out2 = await nav.communitySummary(pool, {
868
+ embedder: engine.embedder,
869
+ query: ctx.text,
870
+ limit: args.limit,
871
+ sourceIds: ctx.sourceIds,
872
+ principals
873
+ });
874
+ if (!out2.available) return { success: false, error: out2.error };
875
+ return { success: true, communities: out2.communities, count: out2.count };
876
+ }
877
+ if (args.action === "find_related") {
878
+ if (!(args.category || args.label || args.entity_type)) {
879
+ return {
880
+ success: false,
881
+ error: "find_related needs a category, a label or an entity_type to look for"
882
+ };
883
+ }
884
+ const out2 = await nav.findRelated(pool, {
885
+ ...scoped,
886
+ category: args.category,
887
+ label: args.label,
888
+ entityType: args.entity_type,
889
+ limit: args.limit
890
+ });
891
+ return { success: true, relationships: out2.relationships, count: out2.count };
892
+ }
893
+ if (!args.entity) {
894
+ return {
895
+ success: false,
896
+ error: `${args.action} needs an entity: the name of a thing to start from`
897
+ };
898
+ }
899
+ if (args.action === "get_neighbors") {
900
+ const out2 = await nav.getNeighbors(pool, { ...scoped, entity: args.entity, limit: args.limit });
901
+ if (!out2.found) return { success: false, error: out2.error };
902
+ return { success: true, entity: out2.entity, neighbors: out2.neighbors, count: out2.count };
903
+ }
904
+ const out = await nav.traverse(pool, {
905
+ ...scoped,
906
+ entity: args.entity,
907
+ depth: args.depth,
908
+ category: args.category,
909
+ limit: args.limit
910
+ });
911
+ if (!out.found) return { success: false, error: out.error };
912
+ return { success: true, entity: out.entity, paths: out.paths, count: out.count };
913
+ }
26
914
  var HandlerError = class extends Error {
27
915
  status;
28
916
  detail;
@@ -131,6 +1019,9 @@ function registerToolGateway(mcp, engine, principals, approvalScope = null) {
131
1019
  var __version__ = "0.0.0";
132
1020
 
133
1021
  // src/mcp.ts
1022
+ function described(name) {
1023
+ return String(INPUT_PROPERTIES[name]?.description ?? "");
1024
+ }
134
1025
  function asMcpResult(data) {
135
1026
  return { content: [{ type: "text", text: JSON.stringify(data) }] };
136
1027
  }
@@ -138,6 +1029,11 @@ async function createMcpApp(engine, opts) {
138
1029
  if (!opts?.principals) {
139
1030
  throw new TypeError("createMcpApp requires principals");
140
1031
  }
1032
+ if (opts.scope === void 0 || opts.scope === null) {
1033
+ throw new TypeError(
1034
+ "createMcpApp requires scope: the source ids this tool may reach, or UNSCOPED (from @promptev/context-engine) to say the whole corpus on purpose."
1035
+ );
1036
+ }
141
1037
  let McpServer;
142
1038
  let StreamableHTTPServerTransport;
143
1039
  try {
@@ -164,83 +1060,53 @@ async function createMcpApp(engine, opts) {
164
1060
  };
165
1061
  tool(
166
1062
  "search_knowledge_base",
167
- `Hybrid search (full-text + trigram + vector, RRF-fused) over the ingested corpus. Returns the top-matching chunks with their source document.${SCOPE_NOTE}`,
1063
+ `${KNOWLEDGE_TOOL_DESCRIPTION}${SCOPE_NOTE}`,
168
1064
  {
169
1065
  // Zod RAW SHAPES, not JSON schema: the SDK's isZodRawShape test
170
1066
  // rejects a plain schema object — on current SDK versions that made
171
1067
  // registration THROW at startup, and on 1.12.0 the object was consumed
172
1068
  // as annotations and every handler ran with NO arguments.
173
- query: z.string(),
174
- source_ids: z.array(z.string()).optional(),
175
- document_ids: z.array(z.string()).optional(),
176
- top_k: z.number().int().optional(),
177
- mode: z.enum(["hybrid", "graph"]).optional()
1069
+ // Every `.describe()` comes from the ONE property table, so the schema
1070
+ // a model reads over the protocol and the exported JSON Schema cannot
1071
+ // say different things.
1072
+ action: z.enum(KNOWLEDGE_ACTIONS).describe(described("action")),
1073
+ query: z.string().optional().describe(described("query")),
1074
+ document_id: z.string().optional().describe(described("document_id")),
1075
+ source_ids: z.array(z.string()).optional().describe(described("source_ids")),
1076
+ document_ids: z.array(z.string()).optional().describe(described("document_ids")),
1077
+ entity: z.string().optional().describe(described("entity")),
1078
+ depth: z.number().int().optional().describe(described("depth")),
1079
+ category: z.enum(RELATIONSHIP_CATEGORY_VALUES).optional().describe(described("category")),
1080
+ label: z.string().optional().describe(described("label")),
1081
+ entity_type: z.enum(ENTITY_TYPES).optional().describe(described("entity_type")),
1082
+ top_k: z.number().int().optional().describe(described("top_k")),
1083
+ mode: z.enum(["hybrid", "graph"]).optional().describe(described("mode")),
1084
+ limit: z.number().int().optional().describe(described("limit")),
1085
+ cursor: z.union([z.string(), z.record(z.unknown())]).optional().describe(described("cursor")),
1086
+ start: z.number().int().optional().describe(described("start")),
1087
+ end: z.number().int().optional().describe(described("end")),
1088
+ max_chars: z.number().int().optional().describe(described("max_chars"))
178
1089
  },
179
1090
  async (args) => {
180
- for (const did of args.document_ids ?? []) {
1091
+ const documentIds = args.document_ids;
1092
+ const documentId = args.document_id;
1093
+ for (const did of [...documentIds ?? [], ...documentId ? [documentId] : []]) {
181
1094
  requireValidUuid(did);
182
1095
  }
183
1096
  const callerPrincipals = await resolvePrincipalsFn(opts.principals);
184
- const result = await engine.search(String(args.query ?? ""), {
185
- sourceIds: args.source_ids,
186
- documentIds: args.document_ids,
1097
+ const ceiling = typeof opts.scope === "function" ? await opts.scope() : opts.scope;
1098
+ const policy = typeof opts.redaction === "function" ? await opts.redaction() : opts.redaction;
1099
+ return callKnowledgeTool(engine, {
1100
+ ...args,
1101
+ action: String(args.action),
187
1102
  principals: callerPrincipals,
188
- topK: args.top_k ?? 10,
189
- mode: args.mode ?? "hybrid"
1103
+ scope: ceiling,
1104
+ redaction: policy,
1105
+ compute: opts.compute ?? null,
1106
+ map_reduce: opts.mapReduce ?? null
190
1107
  });
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
1108
  }
204
1109
  );
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
- }
213
- );
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
1110
  registerToolGateway(
245
1111
  {
246
1112
  tool: (name, description, schema, handler2) => {