@promptev/context-engine 0.0.4 → 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 +40 -0
- package/dist/cli.js +205 -21
- 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 +223 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +222 -23
- package/dist/index.js.map +1 -1
- package/dist/skills/context-engine/SKILL.md +25 -0
- package/package.json +1 -1
- package/src/skills/context-engine/SKILL.md +25 -0
package/dist/index.cjs
CHANGED
|
@@ -11833,7 +11833,7 @@ var SCHEMAS = {
|
|
|
11833
11833
|
url: { type: "string", description: "Endpoint URL, may contain {path} params" },
|
|
11834
11834
|
method: {
|
|
11835
11835
|
type: "string",
|
|
11836
|
-
enum: ["GET", "POST", "PUT", "PATCH", "DELETE"],
|
|
11836
|
+
enum: ["GET", "POST", "PUT", "PATCH", "DELETE", "QUERY"],
|
|
11837
11837
|
default: "GET"
|
|
11838
11838
|
},
|
|
11839
11839
|
headers: {
|
|
@@ -11869,6 +11869,15 @@ var SCHEMAS = {
|
|
|
11869
11869
|
llmQueryParameters: {
|
|
11870
11870
|
type: "object",
|
|
11871
11871
|
description: "LLM-filled parameters sent as the query string"
|
|
11872
|
+
},
|
|
11873
|
+
// How the response comes back to the caller, whatever the method. `tsv`
|
|
11874
|
+
// turns every array of objects in it into a TSV string (`formatResult`
|
|
11875
|
+
// in tools/response-mode.ts); a caller's explicit `responseMode` wins.
|
|
11876
|
+
response_mode: {
|
|
11877
|
+
type: "string",
|
|
11878
|
+
enum: ["json", "tsv"],
|
|
11879
|
+
default: "json",
|
|
11880
|
+
description: "Return the response as JSON, or its arrays of objects as TSV"
|
|
11872
11881
|
}
|
|
11873
11882
|
},
|
|
11874
11883
|
required: ["url", "method"]
|
|
@@ -13034,6 +13043,89 @@ function findTool(tools, callName) {
|
|
|
13034
13043
|
return tools.find((t) => t.callName === callName);
|
|
13035
13044
|
}
|
|
13036
13045
|
|
|
13046
|
+
// src/tools/response-mode.ts
|
|
13047
|
+
var RESPONSE_MODES = ["json", "tsv"];
|
|
13048
|
+
function validateResponseMode(value, name = "responseMode") {
|
|
13049
|
+
if (!RESPONSE_MODES.includes(value)) {
|
|
13050
|
+
throw new Error(`${name} must be one of json, tsv, got ${JSON.stringify(value)}`);
|
|
13051
|
+
}
|
|
13052
|
+
return value;
|
|
13053
|
+
}
|
|
13054
|
+
function tsvCell(value) {
|
|
13055
|
+
if (value === null || value === void 0) return "\\N";
|
|
13056
|
+
let text;
|
|
13057
|
+
if (typeof value === "string") text = value;
|
|
13058
|
+
else if (value instanceof Date) text = value.toISOString();
|
|
13059
|
+
else if (typeof value === "bigint") text = value.toString();
|
|
13060
|
+
else {
|
|
13061
|
+
try {
|
|
13062
|
+
text = JSON.stringify(value) ?? String(value);
|
|
13063
|
+
} catch {
|
|
13064
|
+
text = String(value);
|
|
13065
|
+
}
|
|
13066
|
+
}
|
|
13067
|
+
return text.replaceAll("\\", "\\\\").replaceAll(" ", "\\t").replaceAll("\n", "\\n").replaceAll("\r", "\\r");
|
|
13068
|
+
}
|
|
13069
|
+
function isPlainObject2(value) {
|
|
13070
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
13071
|
+
const proto = Object.getPrototypeOf(value);
|
|
13072
|
+
return proto === Object.prototype || proto === null;
|
|
13073
|
+
}
|
|
13074
|
+
function isTable(value) {
|
|
13075
|
+
return Array.isArray(value) && value.length > 0 && value.every(isPlainObject2);
|
|
13076
|
+
}
|
|
13077
|
+
function tsvLines(rows) {
|
|
13078
|
+
const columns = [];
|
|
13079
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13080
|
+
for (const row of rows) {
|
|
13081
|
+
for (const key of Object.keys(row)) {
|
|
13082
|
+
if (!seen.has(key)) {
|
|
13083
|
+
seen.add(key);
|
|
13084
|
+
columns.push(key);
|
|
13085
|
+
}
|
|
13086
|
+
}
|
|
13087
|
+
}
|
|
13088
|
+
return [
|
|
13089
|
+
columns.map(tsvCell).join(" "),
|
|
13090
|
+
...rows.map((row) => columns.map((c) => tsvCell(row[c])).join(" "))
|
|
13091
|
+
];
|
|
13092
|
+
}
|
|
13093
|
+
function rowsToTsv(rows) {
|
|
13094
|
+
return rows.length ? tsvLines(rows).join("\n") : "";
|
|
13095
|
+
}
|
|
13096
|
+
function collectTables(value, path, out) {
|
|
13097
|
+
if (isTable(value)) {
|
|
13098
|
+
out.set(JSON.stringify(path), { path, lines: tsvLines(value) });
|
|
13099
|
+
} else if (isPlainObject2(value)) {
|
|
13100
|
+
for (const [key, child] of Object.entries(value)) collectTables(child, [...path, key], out);
|
|
13101
|
+
} else if (Array.isArray(value)) {
|
|
13102
|
+
value.forEach((child, index) => {
|
|
13103
|
+
collectTables(child, [...path, index], out);
|
|
13104
|
+
});
|
|
13105
|
+
}
|
|
13106
|
+
}
|
|
13107
|
+
function buildTsv(value, path, tables, kept) {
|
|
13108
|
+
const id = JSON.stringify(path);
|
|
13109
|
+
const table = tables.get(id);
|
|
13110
|
+
if (table) return table.lines.slice(0, (kept.get(id) ?? 0) + 1).join("\n");
|
|
13111
|
+
if (isPlainObject2(value)) {
|
|
13112
|
+
const out = {};
|
|
13113
|
+
for (const [k, v] of Object.entries(value)) out[k] = buildTsv(v, [...path, k], tables, kept);
|
|
13114
|
+
return out;
|
|
13115
|
+
}
|
|
13116
|
+
if (Array.isArray(value)) return value.map((v, i) => buildTsv(v, [...path, i], tables, kept));
|
|
13117
|
+
return value;
|
|
13118
|
+
}
|
|
13119
|
+
function formatResult(result, responseMode = "json") {
|
|
13120
|
+
if (validateResponseMode(responseMode) === "json") return result;
|
|
13121
|
+
const root = { result };
|
|
13122
|
+
const tables = /* @__PURE__ */ new Map();
|
|
13123
|
+
collectTables(root, [], tables);
|
|
13124
|
+
if (!tables.size) return result;
|
|
13125
|
+
const kept = new Map([...tables].map(([id, t]) => [id, t.lines.length - 1]));
|
|
13126
|
+
return buildTsv(root, [], tables, kept).result;
|
|
13127
|
+
}
|
|
13128
|
+
|
|
13037
13129
|
// src/tools/governance.ts
|
|
13038
13130
|
var RESULT_MAX_CHARS = 8e3;
|
|
13039
13131
|
var RESULT_MAX_ROWS = 100;
|
|
@@ -13065,12 +13157,90 @@ function stripUnderscoreArgs(args) {
|
|
|
13065
13157
|
}
|
|
13066
13158
|
return out;
|
|
13067
13159
|
}
|
|
13160
|
+
function validateResultBudget(name, value, fallback) {
|
|
13161
|
+
if (value === void 0) return fallback;
|
|
13162
|
+
if (value === null) return null;
|
|
13163
|
+
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
13164
|
+
throw new TypeError(`${name} must be a positive integer or null, got ${typeof value}`);
|
|
13165
|
+
}
|
|
13166
|
+
if (value < 1) throw new Error(`${name} must be a positive integer or null, got ${value}`);
|
|
13167
|
+
return value;
|
|
13168
|
+
}
|
|
13169
|
+
function serialize(value) {
|
|
13170
|
+
try {
|
|
13171
|
+
return JSON.stringify(value) ?? JSON.stringify(String(value));
|
|
13172
|
+
} catch {
|
|
13173
|
+
return JSON.stringify(String(value));
|
|
13174
|
+
}
|
|
13175
|
+
}
|
|
13176
|
+
function clip(serialized, maxChars) {
|
|
13177
|
+
return {
|
|
13178
|
+
_truncated: serialized.slice(0, maxChars),
|
|
13179
|
+
_original_size: serialized.length,
|
|
13180
|
+
_note: "tool result exceeded the context budget and was truncated"
|
|
13181
|
+
};
|
|
13182
|
+
}
|
|
13183
|
+
function shapeTsv(result, maxChars, maxRows) {
|
|
13184
|
+
const wrapped = !isPlainObject2(result);
|
|
13185
|
+
const root = wrapped ? { result } : result;
|
|
13186
|
+
const tables = /* @__PURE__ */ new Map();
|
|
13187
|
+
collectTables(root, [], tables);
|
|
13188
|
+
if (!tables.size) return null;
|
|
13189
|
+
const sizes = new Map([...tables].map(([id, t]) => [id, t.lines.length - 1]));
|
|
13190
|
+
const kept = new Map([...sizes].map(([id, n]) => [id, maxRows === null ? n : Math.min(n, maxRows)]));
|
|
13191
|
+
const render = () => {
|
|
13192
|
+
const built = buildTsv(root, [], tables, kept);
|
|
13193
|
+
const notes = {};
|
|
13194
|
+
for (const [id, t] of tables) {
|
|
13195
|
+
const k = kept.get(id);
|
|
13196
|
+
const n = sizes.get(id);
|
|
13197
|
+
if (k < n) notes[t.path.join(".")] = { rows_returned: k, rows_omitted: n - k };
|
|
13198
|
+
}
|
|
13199
|
+
if (Object.keys(notes).length) {
|
|
13200
|
+
built._result_shaping = notes;
|
|
13201
|
+
return built;
|
|
13202
|
+
}
|
|
13203
|
+
return wrapped ? built.result : built;
|
|
13204
|
+
};
|
|
13205
|
+
const fits = () => maxChars === null || serialize(render()).length <= maxChars;
|
|
13206
|
+
const capped2 = [...tables.keys()].some((id) => kept.get(id) < sizes.get(id));
|
|
13207
|
+
if (fits()) return [render(), capped2];
|
|
13208
|
+
const initial = new Map(kept);
|
|
13209
|
+
const tableSize = (id) => tables.get(id).lines.slice(0, kept.get(id) + 1).join("\n").length;
|
|
13210
|
+
const bySize = [...tables.keys()].sort((a, b) => tableSize(b) - tableSize(a));
|
|
13211
|
+
for (const id of bySize) {
|
|
13212
|
+
let lo = 0;
|
|
13213
|
+
let hi = kept.get(id) - 1;
|
|
13214
|
+
let best = null;
|
|
13215
|
+
while (lo <= hi) {
|
|
13216
|
+
const mid = Math.floor((lo + hi) / 2);
|
|
13217
|
+
kept.set(id, mid);
|
|
13218
|
+
if (fits()) {
|
|
13219
|
+
best = mid;
|
|
13220
|
+
lo = mid + 1;
|
|
13221
|
+
} else {
|
|
13222
|
+
hi = mid - 1;
|
|
13223
|
+
}
|
|
13224
|
+
}
|
|
13225
|
+
if (best !== null) {
|
|
13226
|
+
kept.set(id, best);
|
|
13227
|
+
return [render(), true];
|
|
13228
|
+
}
|
|
13229
|
+
kept.set(id, 0);
|
|
13230
|
+
}
|
|
13231
|
+
for (const [id, n] of initial) kept.set(id, n);
|
|
13232
|
+
return [clip(serialize(render()), maxChars), true];
|
|
13233
|
+
}
|
|
13068
13234
|
function shapeResult(result, opts = {}) {
|
|
13069
|
-
const maxChars = opts.maxChars
|
|
13070
|
-
const maxRows = opts.maxRows
|
|
13235
|
+
const maxChars = opts.maxChars === void 0 ? RESULT_MAX_CHARS : opts.maxChars;
|
|
13236
|
+
const maxRows = opts.maxRows === void 0 ? RESULT_MAX_ROWS : opts.maxRows;
|
|
13237
|
+
if (opts.responseMode === "tsv") {
|
|
13238
|
+
const tsv = shapeTsv(result, maxChars, maxRows);
|
|
13239
|
+
if (tsv) return tsv;
|
|
13240
|
+
}
|
|
13071
13241
|
let truncated = false;
|
|
13072
13242
|
let shaped = result;
|
|
13073
|
-
if (result && typeof result === "object" && Array.isArray(result.rows) && result.rows.length > maxRows) {
|
|
13243
|
+
if (maxRows !== null && result && typeof result === "object" && Array.isArray(result.rows) && result.rows.length > maxRows) {
|
|
13074
13244
|
const rows = result.rows;
|
|
13075
13245
|
const kept = rows.slice(0, maxRows);
|
|
13076
13246
|
shaped = {
|
|
@@ -13080,22 +13250,9 @@ function shapeResult(result, opts = {}) {
|
|
|
13080
13250
|
};
|
|
13081
13251
|
truncated = true;
|
|
13082
13252
|
}
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
} catch {
|
|
13087
|
-
serialized = JSON.stringify(String(shaped));
|
|
13088
|
-
}
|
|
13089
|
-
if (serialized.length > maxChars) {
|
|
13090
|
-
return [
|
|
13091
|
-
{
|
|
13092
|
-
_truncated: serialized.slice(0, maxChars),
|
|
13093
|
-
_original_size: serialized.length,
|
|
13094
|
-
_note: "tool result exceeded the context budget and was truncated"
|
|
13095
|
-
},
|
|
13096
|
-
true
|
|
13097
|
-
];
|
|
13098
|
-
}
|
|
13253
|
+
if (maxChars === null) return [shaped, truncated];
|
|
13254
|
+
const serialized = serialize(shaped);
|
|
13255
|
+
if (serialized.length > maxChars) return [clip(serialized, maxChars), true];
|
|
13099
13256
|
return [shaped, truncated];
|
|
13100
13257
|
}
|
|
13101
13258
|
function redactToolResult(result, policy, opts) {
|
|
@@ -13206,9 +13363,29 @@ function canonicalToPublic(ct) {
|
|
|
13206
13363
|
params_schema: ct.paramsSchema
|
|
13207
13364
|
};
|
|
13208
13365
|
}
|
|
13366
|
+
function configuredResponseMode(ct, config) {
|
|
13367
|
+
if (ct.kind !== "http" || config.response_mode == null) return "json";
|
|
13368
|
+
try {
|
|
13369
|
+
return validateResponseMode(config.response_mode, "config.response_mode");
|
|
13370
|
+
} catch {
|
|
13371
|
+
console.warn(
|
|
13372
|
+
`tool ${ct.callName} has an unknown config response_mode ${JSON.stringify(config.response_mode)}; returning json`
|
|
13373
|
+
);
|
|
13374
|
+
return "json";
|
|
13375
|
+
}
|
|
13376
|
+
}
|
|
13377
|
+
function checkConfigResponseMode(kind, config) {
|
|
13378
|
+
if (kind !== "http" || !config || config.response_mode == null) return;
|
|
13379
|
+
try {
|
|
13380
|
+
validateResponseMode(config.response_mode, "config.response_mode");
|
|
13381
|
+
} catch (exc) {
|
|
13382
|
+
throw new ConfigTemplateError(exc.message);
|
|
13383
|
+
}
|
|
13384
|
+
}
|
|
13209
13385
|
async function registerTool(engine, tc) {
|
|
13210
13386
|
canonicalFromConfig(tc);
|
|
13211
13387
|
const config = tc.config ?? {};
|
|
13388
|
+
checkConfigResponseMode(tc.kind, config);
|
|
13212
13389
|
if (containsSentinel(config)) {
|
|
13213
13390
|
throw new ConfigTemplateError(
|
|
13214
13391
|
`config contains the ${JSON.stringify(REDACTED_SENTINEL)} placeholder \u2014 a redacted template cannot be registered as a new tool; re-enter the secret values`
|
|
@@ -13244,6 +13421,12 @@ async function updateTool(engine, id, opts) {
|
|
|
13244
13421
|
if (!row || !aclVisible(row.acl != null ? [...row.acl] : null, principals)) {
|
|
13245
13422
|
throw new exports.EngineActionError(`tool not found: ${id}`);
|
|
13246
13423
|
}
|
|
13424
|
+
if ("config" in fields) {
|
|
13425
|
+
checkConfigResponseMode(
|
|
13426
|
+
"kind" in fields ? fields.kind : row.kind,
|
|
13427
|
+
fields.config
|
|
13428
|
+
);
|
|
13429
|
+
}
|
|
13247
13430
|
const sets = [];
|
|
13248
13431
|
const params = [];
|
|
13249
13432
|
let i = 1;
|
|
@@ -13553,6 +13736,9 @@ function warnUnscopedApproval(callName) {
|
|
|
13553
13736
|
async function executeTool(engine, callName, args, opts = {}) {
|
|
13554
13737
|
const runtimeArgs = args ?? {};
|
|
13555
13738
|
const approvalScope = validateApprovalScope(opts.approvalScope);
|
|
13739
|
+
const resultMaxChars = validateResultBudget("resultMaxChars", opts.resultMaxChars, RESULT_MAX_CHARS);
|
|
13740
|
+
const resultMaxRows = validateResultBudget("resultMaxRows", opts.resultMaxRows, RESULT_MAX_ROWS);
|
|
13741
|
+
let responseMode = opts.responseMode === void 0 || opts.responseMode === null ? null : validateResponseMode(opts.responseMode);
|
|
13556
13742
|
const ct = findTool(await mergedTools(engine, opts.sourceId ?? null), callName);
|
|
13557
13743
|
if (!ct) throw new exports.EngineActionError(`tool not found: ${callName}`);
|
|
13558
13744
|
if (!toolVisible(ct, opts.principals ?? null)) {
|
|
@@ -13595,6 +13781,7 @@ async function executeTool(engine, callName, args, opts = {}) {
|
|
|
13595
13781
|
if (ct.kind !== "function" && ct.id != null) {
|
|
13596
13782
|
config = await decryptCtConfig(engine, ct.id);
|
|
13597
13783
|
}
|
|
13784
|
+
responseMode ??= configuredResponseMode(ct, config);
|
|
13598
13785
|
const actorType = opts.actor?.type ?? null;
|
|
13599
13786
|
const actorId = opts.actor?.id ?? null;
|
|
13600
13787
|
let rawResult = null;
|
|
@@ -13618,7 +13805,16 @@ async function executeTool(engine, callName, args, opts = {}) {
|
|
|
13618
13805
|
hooks: engine.hooks
|
|
13619
13806
|
});
|
|
13620
13807
|
rawResult = redacted;
|
|
13621
|
-
|
|
13808
|
+
let toShape = rawResult;
|
|
13809
|
+
if (responseMode === "tsv" && ct.kind === "db" && isPlainObject2(rawResult)) {
|
|
13810
|
+
const { text: _preview, ...rest } = rawResult;
|
|
13811
|
+
toShape = rest;
|
|
13812
|
+
}
|
|
13813
|
+
[shaped, truncated] = shapeResult(toShape, {
|
|
13814
|
+
maxChars: resultMaxChars,
|
|
13815
|
+
maxRows: resultMaxRows,
|
|
13816
|
+
responseMode
|
|
13817
|
+
});
|
|
13622
13818
|
} catch (e) {
|
|
13623
13819
|
exc = e;
|
|
13624
13820
|
success = false;
|
|
@@ -14274,7 +14470,10 @@ var ContextEngine = class _ContextEngine {
|
|
|
14274
14470
|
principals: resolvePrincipals(opts.principals, "executeTool"),
|
|
14275
14471
|
actor: opts.actor,
|
|
14276
14472
|
source: opts.source ?? "api",
|
|
14277
|
-
approvalScope: opts.approvalScope
|
|
14473
|
+
approvalScope: opts.approvalScope,
|
|
14474
|
+
resultMaxChars: opts.resultMaxChars,
|
|
14475
|
+
resultMaxRows: opts.resultMaxRows,
|
|
14476
|
+
responseMode: opts.responseMode
|
|
14278
14477
|
});
|
|
14279
14478
|
}
|
|
14280
14479
|
};
|
|
@@ -14592,6 +14791,7 @@ exports.encryptDict = encryptDict;
|
|
|
14592
14791
|
exports.extract = extract2;
|
|
14593
14792
|
exports.extractStructuredData = extractStructuredData;
|
|
14594
14793
|
exports.fieldSummary = fieldSummary;
|
|
14794
|
+
exports.formatResult = formatResult;
|
|
14595
14795
|
exports.functionTool = functionTool;
|
|
14596
14796
|
exports.getDocumentText = getDocumentText;
|
|
14597
14797
|
exports.getSecretKey = getSecretKey;
|
|
@@ -14606,6 +14806,7 @@ exports.resolveApproval = resolveApproval;
|
|
|
14606
14806
|
exports.resolveFields = resolveFields;
|
|
14607
14807
|
exports.resolvePrincipals = resolvePrincipals;
|
|
14608
14808
|
exports.resolveScope = resolveScope;
|
|
14809
|
+
exports.rowsToTsv = rowsToTsv;
|
|
14609
14810
|
exports.rrfFuse = rrfFuse;
|
|
14610
14811
|
exports.runMigrate = runMigrate;
|
|
14611
14812
|
exports.runSearch = runSearch;
|