@promptev/context-engine 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -1
- package/dist/cli.js +732 -37
- package/dist/cli.js.map +1 -1
- package/dist/express.cjs +205 -21
- package/dist/express.cjs.map +1 -1
- package/dist/express.js +205 -21
- package/dist/express.js.map +1 -1
- package/dist/fastify.cjs +205 -21
- package/dist/fastify.cjs.map +1 -1
- package/dist/fastify.js +205 -21
- package/dist/fastify.js.map +1 -1
- package/dist/hono.cjs +205 -21
- package/dist/hono.cjs.map +1 -1
- package/dist/hono.js +205 -21
- package/dist/hono.js.map +1 -1
- package/dist/index.cjs +755 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +276 -3
- package/dist/index.d.ts +276 -3
- package/dist/index.js +749 -39
- package/dist/index.js.map +1 -1
- package/dist/{mcp-BKSmxayM.d.cts → mcp-uirRbluA.d.cts} +4 -0
- package/dist/{mcp-BKSmxayM.d.ts → mcp-uirRbluA.d.ts} +4 -0
- package/dist/mcp.cjs +50 -10
- package/dist/mcp.cjs.map +1 -1
- package/dist/mcp.d.cts +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +50 -10
- package/dist/mcp.js.map +1 -1
- package/dist/skills/context-engine/SKILL.md +54 -1
- package/package.json +1 -1
- package/src/skills/context-engine/SKILL.md +54 -1
package/dist/hono.cjs
CHANGED
|
@@ -947,7 +947,7 @@ var SCHEMAS = {
|
|
|
947
947
|
url: { type: "string", description: "Endpoint URL, may contain {path} params" },
|
|
948
948
|
method: {
|
|
949
949
|
type: "string",
|
|
950
|
-
enum: ["GET", "POST", "PUT", "PATCH", "DELETE"],
|
|
950
|
+
enum: ["GET", "POST", "PUT", "PATCH", "DELETE", "QUERY"],
|
|
951
951
|
default: "GET"
|
|
952
952
|
},
|
|
953
953
|
headers: {
|
|
@@ -983,6 +983,15 @@ var SCHEMAS = {
|
|
|
983
983
|
llmQueryParameters: {
|
|
984
984
|
type: "object",
|
|
985
985
|
description: "LLM-filled parameters sent as the query string"
|
|
986
|
+
},
|
|
987
|
+
// How the response comes back to the caller, whatever the method. `tsv`
|
|
988
|
+
// turns every array of objects in it into a TSV string (`formatResult`
|
|
989
|
+
// in tools/response-mode.ts); a caller's explicit `responseMode` wins.
|
|
990
|
+
response_mode: {
|
|
991
|
+
type: "string",
|
|
992
|
+
enum: ["json", "tsv"],
|
|
993
|
+
default: "json",
|
|
994
|
+
description: "Return the response as JSON, or its arrays of objects as TSV"
|
|
986
995
|
}
|
|
987
996
|
},
|
|
988
997
|
required: ["url", "method"]
|
|
@@ -2510,6 +2519,77 @@ function findTool(tools, callName) {
|
|
|
2510
2519
|
return tools.find((t) => t.callName === callName);
|
|
2511
2520
|
}
|
|
2512
2521
|
|
|
2522
|
+
// src/tools/response-mode.ts
|
|
2523
|
+
var RESPONSE_MODES = ["json", "tsv"];
|
|
2524
|
+
function validateResponseMode(value, name = "responseMode") {
|
|
2525
|
+
if (!RESPONSE_MODES.includes(value)) {
|
|
2526
|
+
throw new Error(`${name} must be one of json, tsv, got ${JSON.stringify(value)}`);
|
|
2527
|
+
}
|
|
2528
|
+
return value;
|
|
2529
|
+
}
|
|
2530
|
+
function tsvCell(value) {
|
|
2531
|
+
if (value === null || value === void 0) return "\\N";
|
|
2532
|
+
let text;
|
|
2533
|
+
if (typeof value === "string") text = value;
|
|
2534
|
+
else if (value instanceof Date) text = value.toISOString();
|
|
2535
|
+
else if (typeof value === "bigint") text = value.toString();
|
|
2536
|
+
else {
|
|
2537
|
+
try {
|
|
2538
|
+
text = JSON.stringify(value) ?? String(value);
|
|
2539
|
+
} catch {
|
|
2540
|
+
text = String(value);
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
return text.replaceAll("\\", "\\\\").replaceAll(" ", "\\t").replaceAll("\n", "\\n").replaceAll("\r", "\\r");
|
|
2544
|
+
}
|
|
2545
|
+
function isPlainObject2(value) {
|
|
2546
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2547
|
+
const proto = Object.getPrototypeOf(value);
|
|
2548
|
+
return proto === Object.prototype || proto === null;
|
|
2549
|
+
}
|
|
2550
|
+
function isTable(value) {
|
|
2551
|
+
return Array.isArray(value) && value.length > 0 && value.every(isPlainObject2);
|
|
2552
|
+
}
|
|
2553
|
+
function tsvLines(rows) {
|
|
2554
|
+
const columns = [];
|
|
2555
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2556
|
+
for (const row of rows) {
|
|
2557
|
+
for (const key of Object.keys(row)) {
|
|
2558
|
+
if (!seen.has(key)) {
|
|
2559
|
+
seen.add(key);
|
|
2560
|
+
columns.push(key);
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
return [
|
|
2565
|
+
columns.map(tsvCell).join(" "),
|
|
2566
|
+
...rows.map((row) => columns.map((c) => tsvCell(row[c])).join(" "))
|
|
2567
|
+
];
|
|
2568
|
+
}
|
|
2569
|
+
function collectTables(value, path, out) {
|
|
2570
|
+
if (isTable(value)) {
|
|
2571
|
+
out.set(JSON.stringify(path), { path, lines: tsvLines(value) });
|
|
2572
|
+
} else if (isPlainObject2(value)) {
|
|
2573
|
+
for (const [key, child] of Object.entries(value)) collectTables(child, [...path, key], out);
|
|
2574
|
+
} else if (Array.isArray(value)) {
|
|
2575
|
+
value.forEach((child, index) => {
|
|
2576
|
+
collectTables(child, [...path, index], out);
|
|
2577
|
+
});
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
function buildTsv(value, path, tables, kept) {
|
|
2581
|
+
const id = JSON.stringify(path);
|
|
2582
|
+
const table = tables.get(id);
|
|
2583
|
+
if (table) return table.lines.slice(0, (kept.get(id) ?? 0) + 1).join("\n");
|
|
2584
|
+
if (isPlainObject2(value)) {
|
|
2585
|
+
const out = {};
|
|
2586
|
+
for (const [k, v] of Object.entries(value)) out[k] = buildTsv(v, [...path, k], tables, kept);
|
|
2587
|
+
return out;
|
|
2588
|
+
}
|
|
2589
|
+
if (Array.isArray(value)) return value.map((v, i) => buildTsv(v, [...path, i], tables, kept));
|
|
2590
|
+
return value;
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2513
2593
|
// src/tools/governance.ts
|
|
2514
2594
|
var RESULT_MAX_CHARS = 8e3;
|
|
2515
2595
|
var RESULT_MAX_ROWS = 100;
|
|
@@ -2541,12 +2621,90 @@ function stripUnderscoreArgs(args) {
|
|
|
2541
2621
|
}
|
|
2542
2622
|
return out;
|
|
2543
2623
|
}
|
|
2624
|
+
function validateResultBudget(name, value, fallback) {
|
|
2625
|
+
if (value === void 0) return fallback;
|
|
2626
|
+
if (value === null) return null;
|
|
2627
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
2628
|
+
throw new TypeError(`${name} must be a positive integer or null, got ${typeof value}`);
|
|
2629
|
+
}
|
|
2630
|
+
if (value < 1) throw new Error(`${name} must be a positive integer or null, got ${value}`);
|
|
2631
|
+
return value;
|
|
2632
|
+
}
|
|
2633
|
+
function serialize(value) {
|
|
2634
|
+
try {
|
|
2635
|
+
return JSON.stringify(value) ?? JSON.stringify(String(value));
|
|
2636
|
+
} catch {
|
|
2637
|
+
return JSON.stringify(String(value));
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
function clip(serialized, maxChars) {
|
|
2641
|
+
return {
|
|
2642
|
+
_truncated: serialized.slice(0, maxChars),
|
|
2643
|
+
_original_size: serialized.length,
|
|
2644
|
+
_note: "tool result exceeded the context budget and was truncated"
|
|
2645
|
+
};
|
|
2646
|
+
}
|
|
2647
|
+
function shapeTsv(result, maxChars, maxRows) {
|
|
2648
|
+
const wrapped = !isPlainObject2(result);
|
|
2649
|
+
const root = wrapped ? { result } : result;
|
|
2650
|
+
const tables = /* @__PURE__ */ new Map();
|
|
2651
|
+
collectTables(root, [], tables);
|
|
2652
|
+
if (!tables.size) return null;
|
|
2653
|
+
const sizes = new Map([...tables].map(([id, t]) => [id, t.lines.length - 1]));
|
|
2654
|
+
const kept = new Map([...sizes].map(([id, n]) => [id, maxRows === null ? n : Math.min(n, maxRows)]));
|
|
2655
|
+
const render = () => {
|
|
2656
|
+
const built = buildTsv(root, [], tables, kept);
|
|
2657
|
+
const notes = {};
|
|
2658
|
+
for (const [id, t] of tables) {
|
|
2659
|
+
const k = kept.get(id);
|
|
2660
|
+
const n = sizes.get(id);
|
|
2661
|
+
if (k < n) notes[t.path.join(".")] = { rows_returned: k, rows_omitted: n - k };
|
|
2662
|
+
}
|
|
2663
|
+
if (Object.keys(notes).length) {
|
|
2664
|
+
built._result_shaping = notes;
|
|
2665
|
+
return built;
|
|
2666
|
+
}
|
|
2667
|
+
return wrapped ? built.result : built;
|
|
2668
|
+
};
|
|
2669
|
+
const fits = () => maxChars === null || serialize(render()).length <= maxChars;
|
|
2670
|
+
const capped = [...tables.keys()].some((id) => kept.get(id) < sizes.get(id));
|
|
2671
|
+
if (fits()) return [render(), capped];
|
|
2672
|
+
const initial = new Map(kept);
|
|
2673
|
+
const tableSize = (id) => tables.get(id).lines.slice(0, kept.get(id) + 1).join("\n").length;
|
|
2674
|
+
const bySize = [...tables.keys()].sort((a, b) => tableSize(b) - tableSize(a));
|
|
2675
|
+
for (const id of bySize) {
|
|
2676
|
+
let lo = 0;
|
|
2677
|
+
let hi = kept.get(id) - 1;
|
|
2678
|
+
let best = null;
|
|
2679
|
+
while (lo <= hi) {
|
|
2680
|
+
const mid = Math.floor((lo + hi) / 2);
|
|
2681
|
+
kept.set(id, mid);
|
|
2682
|
+
if (fits()) {
|
|
2683
|
+
best = mid;
|
|
2684
|
+
lo = mid + 1;
|
|
2685
|
+
} else {
|
|
2686
|
+
hi = mid - 1;
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
if (best !== null) {
|
|
2690
|
+
kept.set(id, best);
|
|
2691
|
+
return [render(), true];
|
|
2692
|
+
}
|
|
2693
|
+
kept.set(id, 0);
|
|
2694
|
+
}
|
|
2695
|
+
for (const [id, n] of initial) kept.set(id, n);
|
|
2696
|
+
return [clip(serialize(render()), maxChars), true];
|
|
2697
|
+
}
|
|
2544
2698
|
function shapeResult(result, opts = {}) {
|
|
2545
|
-
const maxChars = opts.maxChars
|
|
2546
|
-
const maxRows = opts.maxRows
|
|
2699
|
+
const maxChars = opts.maxChars === void 0 ? RESULT_MAX_CHARS : opts.maxChars;
|
|
2700
|
+
const maxRows = opts.maxRows === void 0 ? RESULT_MAX_ROWS : opts.maxRows;
|
|
2701
|
+
if (opts.responseMode === "tsv") {
|
|
2702
|
+
const tsv = shapeTsv(result, maxChars, maxRows);
|
|
2703
|
+
if (tsv) return tsv;
|
|
2704
|
+
}
|
|
2547
2705
|
let truncated = false;
|
|
2548
2706
|
let shaped = result;
|
|
2549
|
-
if (result && typeof result === "object" && Array.isArray(result.rows) && result.rows.length > maxRows) {
|
|
2707
|
+
if (maxRows !== null && result && typeof result === "object" && Array.isArray(result.rows) && result.rows.length > maxRows) {
|
|
2550
2708
|
const rows = result.rows;
|
|
2551
2709
|
const kept = rows.slice(0, maxRows);
|
|
2552
2710
|
shaped = {
|
|
@@ -2556,22 +2714,9 @@ function shapeResult(result, opts = {}) {
|
|
|
2556
2714
|
};
|
|
2557
2715
|
truncated = true;
|
|
2558
2716
|
}
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
} catch {
|
|
2563
|
-
serialized = JSON.stringify(String(shaped));
|
|
2564
|
-
}
|
|
2565
|
-
if (serialized.length > maxChars) {
|
|
2566
|
-
return [
|
|
2567
|
-
{
|
|
2568
|
-
_truncated: serialized.slice(0, maxChars),
|
|
2569
|
-
_original_size: serialized.length,
|
|
2570
|
-
_note: "tool result exceeded the context budget and was truncated"
|
|
2571
|
-
},
|
|
2572
|
-
true
|
|
2573
|
-
];
|
|
2574
|
-
}
|
|
2717
|
+
if (maxChars === null) return [shaped, truncated];
|
|
2718
|
+
const serialized = serialize(shaped);
|
|
2719
|
+
if (serialized.length > maxChars) return [clip(serialized, maxChars), true];
|
|
2575
2720
|
return [shaped, truncated];
|
|
2576
2721
|
}
|
|
2577
2722
|
function redactToolResult(result, policy, opts) {
|
|
@@ -2674,9 +2819,29 @@ async function mergedTools(engine, sourceId) {
|
|
|
2674
2819
|
const functions = Object.values(engine._functionTools ?? {});
|
|
2675
2820
|
return [...persisted, ...functions];
|
|
2676
2821
|
}
|
|
2822
|
+
function configuredResponseMode(ct, config) {
|
|
2823
|
+
if (ct.kind !== "http" || config.response_mode == null) return "json";
|
|
2824
|
+
try {
|
|
2825
|
+
return validateResponseMode(config.response_mode, "config.response_mode");
|
|
2826
|
+
} catch {
|
|
2827
|
+
console.warn(
|
|
2828
|
+
`tool ${ct.callName} has an unknown config response_mode ${JSON.stringify(config.response_mode)}; returning json`
|
|
2829
|
+
);
|
|
2830
|
+
return "json";
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
function checkConfigResponseMode(kind, config) {
|
|
2834
|
+
if (kind !== "http" || !config || config.response_mode == null) return;
|
|
2835
|
+
try {
|
|
2836
|
+
validateResponseMode(config.response_mode, "config.response_mode");
|
|
2837
|
+
} catch (exc) {
|
|
2838
|
+
throw new ConfigTemplateError(exc.message);
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2677
2841
|
async function registerTool(engine, tc) {
|
|
2678
2842
|
canonicalFromConfig(tc);
|
|
2679
2843
|
const config = tc.config ?? {};
|
|
2844
|
+
checkConfigResponseMode(tc.kind, config);
|
|
2680
2845
|
if (containsSentinel(config)) {
|
|
2681
2846
|
throw new ConfigTemplateError(
|
|
2682
2847
|
`config contains the ${JSON.stringify(REDACTED_SENTINEL)} placeholder \u2014 a redacted template cannot be registered as a new tool; re-enter the secret values`
|
|
@@ -2712,6 +2877,12 @@ async function updateTool(engine, id, opts) {
|
|
|
2712
2877
|
if (!row || !aclVisible(row.acl != null ? [...row.acl] : null, principals)) {
|
|
2713
2878
|
throw new EngineActionError(`tool not found: ${id}`);
|
|
2714
2879
|
}
|
|
2880
|
+
if ("config" in fields) {
|
|
2881
|
+
checkConfigResponseMode(
|
|
2882
|
+
"kind" in fields ? fields.kind : row.kind,
|
|
2883
|
+
fields.config
|
|
2884
|
+
);
|
|
2885
|
+
}
|
|
2715
2886
|
const sets = [];
|
|
2716
2887
|
const params = [];
|
|
2717
2888
|
let i = 1;
|
|
@@ -3002,6 +3173,9 @@ function warnUnscopedApproval(callName) {
|
|
|
3002
3173
|
async function executeTool(engine, callName, args, opts = {}) {
|
|
3003
3174
|
const runtimeArgs = args ?? {};
|
|
3004
3175
|
const approvalScope = validateApprovalScope(opts.approvalScope);
|
|
3176
|
+
const resultMaxChars = validateResultBudget("resultMaxChars", opts.resultMaxChars, RESULT_MAX_CHARS);
|
|
3177
|
+
const resultMaxRows = validateResultBudget("resultMaxRows", opts.resultMaxRows, RESULT_MAX_ROWS);
|
|
3178
|
+
let responseMode = opts.responseMode === void 0 || opts.responseMode === null ? null : validateResponseMode(opts.responseMode);
|
|
3005
3179
|
const ct = findTool(await mergedTools(engine, opts.sourceId ?? null), callName);
|
|
3006
3180
|
if (!ct) throw new EngineActionError(`tool not found: ${callName}`);
|
|
3007
3181
|
if (!toolVisible(ct, opts.principals ?? null)) {
|
|
@@ -3044,6 +3218,7 @@ async function executeTool(engine, callName, args, opts = {}) {
|
|
|
3044
3218
|
if (ct.kind !== "function" && ct.id != null) {
|
|
3045
3219
|
config = await decryptCtConfig(engine, ct.id);
|
|
3046
3220
|
}
|
|
3221
|
+
responseMode ??= configuredResponseMode(ct, config);
|
|
3047
3222
|
const actorType = opts.actor?.type ?? null;
|
|
3048
3223
|
const actorId = opts.actor?.id ?? null;
|
|
3049
3224
|
let rawResult = null;
|
|
@@ -3067,7 +3242,16 @@ async function executeTool(engine, callName, args, opts = {}) {
|
|
|
3067
3242
|
hooks: engine.hooks
|
|
3068
3243
|
});
|
|
3069
3244
|
rawResult = redacted;
|
|
3070
|
-
|
|
3245
|
+
let toShape = rawResult;
|
|
3246
|
+
if (responseMode === "tsv" && ct.kind === "db" && isPlainObject2(rawResult)) {
|
|
3247
|
+
const { text: _preview, ...rest } = rawResult;
|
|
3248
|
+
toShape = rest;
|
|
3249
|
+
}
|
|
3250
|
+
[shaped, truncated] = shapeResult(toShape, {
|
|
3251
|
+
maxChars: resultMaxChars,
|
|
3252
|
+
maxRows: resultMaxRows,
|
|
3253
|
+
responseMode
|
|
3254
|
+
});
|
|
3071
3255
|
} catch (e) {
|
|
3072
3256
|
exc = e;
|
|
3073
3257
|
success = false;
|