@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/dist/index.d.cts CHANGED
@@ -12,6 +12,31 @@ export { c as ToolKind, d as configSchema } from './governance-P9pRb4Ol.cjs';
12
12
  import 'zod';
13
13
  import 'node:http';
14
14
 
15
+ /**
16
+ * Tool result formats — one helper every tool kind shares. Mirrors
17
+ * `context_engine/tools/response_mode.py`.
18
+ *
19
+ * `formatResult(result, responseMode)` hands a JSON-ish tool result back
20
+ * unchanged for `"json"`, and for `"tsv"` turns every outermost non-empty
21
+ * array of objects in it into a TSV string under the same key. A result that
22
+ * IS such an array becomes the string; a result holding none comes back
23
+ * unchanged.
24
+ *
25
+ * The cell encoding is PostgreSQL's COPY TEXT convention, not CSV quoting:
26
+ * `\N` is NULL, and tab, newline, CR and backslash inside a value are
27
+ * backslash-escaped. Quoting would leave a real newline inside a quoted
28
+ * value, so one row could span several lines — which breaks cutting a table
29
+ * at whole rows (`shapeResult`) and is harder for a model to read. Values
30
+ * that are not strings are written as compact JSON (dates as ISO strings).
31
+ */
32
+ declare const RESPONSE_MODES: readonly ["json", "tsv"];
33
+ type ResponseMode = (typeof RESPONSE_MODES)[number];
34
+ /** A list of objects as one TSV string, header first. */
35
+ declare function rowsToTsv(rows: Array<Record<string, unknown>>): string;
36
+ /** `result` unchanged for `"json"` (the default); every array of objects in
37
+ * it as TSV for `"tsv"`. Throws for an unknown mode. */
38
+ declare function formatResult(result: unknown, responseMode?: ResponseMode): unknown;
39
+
15
40
  type Mode$1 = "hybrid" | "graph";
16
41
  interface IngestRequest {
17
42
  content?: Buffer | null;
@@ -855,6 +880,13 @@ declare class ContextEngine implements ToolEngine {
855
880
  /** Opaque claim scope for approvals (e.g. a run id) — separate from
856
881
  * `sourceId`. See `governance.executeTool`. */
857
882
  approvalScope?: string | null;
883
+ /** Budget for the returned `result`: omitted = 8,000 chars / 100 rows,
884
+ * `null` = no limit. See `governance.executeTool`. */
885
+ resultMaxChars?: number | null;
886
+ resultMaxRows?: number | null;
887
+ /** `"json"` or `"tsv"` — every array of objects in the result as a TSV
888
+ * string. Omitted, an http tool uses its config's `response_mode`, else json. */
889
+ responseMode?: ResponseMode | null;
858
890
  }): Promise<Record<string, unknown>>;
859
891
  }
860
892
 
@@ -1174,4 +1206,4 @@ declare function functionTool(fn: (...args: never[]) => unknown): CanonicalTool;
1174
1206
  /** Bumped by CI on every main merge; 0.0.0 = pre-first-release. */
1175
1207
  declare const __version__ = "0.0.0";
1176
1208
 
1177
- export { ApprovalExpired, ApprovalNotPending, type ApprovalRecord, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, type ComputeDocument, type ComputeFrames, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, ExtractionConfig, type ExtractionResult, GraphLegUnavailable, type Hit, Hooks, InProcessRunner, IngestReport, KnowledgeComputeFn, LLMClient, LLMConfig, Principals, ProgressEvent, RedactionPolicy, RerankerConfig, ScopeInput, type SearchResult, StorageBackend, type TaskRunner, type TaskStatus, ToolConfig, Trusted, Unset, UsageEvent, __version__, buildLlmClient, callLlm, compute, computeOverFrames, decryptDict, documentStructure, documentTypes, encryptDict, extract, extractStructuredData, fieldSummary, functionTool, getDocumentText, getSecretKey, listDocuments, queryStructured, redactHits, rerank, resolveApproval, resolveFields, rrfFuse, runMigrate, runSearch, shouldRequireApproval, spreadsheetSchema, spreadsheetSchemaFromText, upsertRegistry };
1209
+ export { ApprovalExpired, ApprovalNotPending, type ApprovalRecord, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, type ComputeDocument, type ComputeFrames, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, ExtractionConfig, type ExtractionResult, GraphLegUnavailable, type Hit, Hooks, InProcessRunner, IngestReport, KnowledgeComputeFn, LLMClient, LLMConfig, Principals, ProgressEvent, RedactionPolicy, RerankerConfig, type ResponseMode, ScopeInput, type SearchResult, StorageBackend, type TaskRunner, type TaskStatus, ToolConfig, Trusted, Unset, UsageEvent, __version__, buildLlmClient, callLlm, compute, computeOverFrames, decryptDict, documentStructure, documentTypes, encryptDict, extract, extractStructuredData, fieldSummary, formatResult, functionTool, getDocumentText, getSecretKey, listDocuments, queryStructured, redactHits, rerank, resolveApproval, resolveFields, rowsToTsv, rrfFuse, runMigrate, runSearch, shouldRequireApproval, spreadsheetSchema, spreadsheetSchemaFromText, upsertRegistry };
package/dist/index.d.ts CHANGED
@@ -12,6 +12,31 @@ export { c as ToolKind, d as configSchema } from './governance-BLPK7NMe.js';
12
12
  import 'zod';
13
13
  import 'node:http';
14
14
 
15
+ /**
16
+ * Tool result formats — one helper every tool kind shares. Mirrors
17
+ * `context_engine/tools/response_mode.py`.
18
+ *
19
+ * `formatResult(result, responseMode)` hands a JSON-ish tool result back
20
+ * unchanged for `"json"`, and for `"tsv"` turns every outermost non-empty
21
+ * array of objects in it into a TSV string under the same key. A result that
22
+ * IS such an array becomes the string; a result holding none comes back
23
+ * unchanged.
24
+ *
25
+ * The cell encoding is PostgreSQL's COPY TEXT convention, not CSV quoting:
26
+ * `\N` is NULL, and tab, newline, CR and backslash inside a value are
27
+ * backslash-escaped. Quoting would leave a real newline inside a quoted
28
+ * value, so one row could span several lines — which breaks cutting a table
29
+ * at whole rows (`shapeResult`) and is harder for a model to read. Values
30
+ * that are not strings are written as compact JSON (dates as ISO strings).
31
+ */
32
+ declare const RESPONSE_MODES: readonly ["json", "tsv"];
33
+ type ResponseMode = (typeof RESPONSE_MODES)[number];
34
+ /** A list of objects as one TSV string, header first. */
35
+ declare function rowsToTsv(rows: Array<Record<string, unknown>>): string;
36
+ /** `result` unchanged for `"json"` (the default); every array of objects in
37
+ * it as TSV for `"tsv"`. Throws for an unknown mode. */
38
+ declare function formatResult(result: unknown, responseMode?: ResponseMode): unknown;
39
+
15
40
  type Mode$1 = "hybrid" | "graph";
16
41
  interface IngestRequest {
17
42
  content?: Buffer | null;
@@ -855,6 +880,13 @@ declare class ContextEngine implements ToolEngine {
855
880
  /** Opaque claim scope for approvals (e.g. a run id) — separate from
856
881
  * `sourceId`. See `governance.executeTool`. */
857
882
  approvalScope?: string | null;
883
+ /** Budget for the returned `result`: omitted = 8,000 chars / 100 rows,
884
+ * `null` = no limit. See `governance.executeTool`. */
885
+ resultMaxChars?: number | null;
886
+ resultMaxRows?: number | null;
887
+ /** `"json"` or `"tsv"` — every array of objects in the result as a TSV
888
+ * string. Omitted, an http tool uses its config's `response_mode`, else json. */
889
+ responseMode?: ResponseMode | null;
858
890
  }): Promise<Record<string, unknown>>;
859
891
  }
860
892
 
@@ -1174,4 +1206,4 @@ declare function functionTool(fn: (...args: never[]) => unknown): CanonicalTool;
1174
1206
  /** Bumped by CI on every main merge; 0.0.0 = pre-first-release. */
1175
1207
  declare const __version__ = "0.0.0";
1176
1208
 
1177
- export { ApprovalExpired, ApprovalNotPending, type ApprovalRecord, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, type ComputeDocument, type ComputeFrames, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, ExtractionConfig, type ExtractionResult, GraphLegUnavailable, type Hit, Hooks, InProcessRunner, IngestReport, KnowledgeComputeFn, LLMClient, LLMConfig, Principals, ProgressEvent, RedactionPolicy, RerankerConfig, ScopeInput, type SearchResult, StorageBackend, type TaskRunner, type TaskStatus, ToolConfig, Trusted, Unset, UsageEvent, __version__, buildLlmClient, callLlm, compute, computeOverFrames, decryptDict, documentStructure, documentTypes, encryptDict, extract, extractStructuredData, fieldSummary, functionTool, getDocumentText, getSecretKey, listDocuments, queryStructured, redactHits, rerank, resolveApproval, resolveFields, rrfFuse, runMigrate, runSearch, shouldRequireApproval, spreadsheetSchema, spreadsheetSchemaFromText, upsertRegistry };
1209
+ export { ApprovalExpired, ApprovalNotPending, type ApprovalRecord, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, type ComputeDocument, type ComputeFrames, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, ExtractionConfig, type ExtractionResult, GraphLegUnavailable, type Hit, Hooks, InProcessRunner, IngestReport, KnowledgeComputeFn, LLMClient, LLMConfig, Principals, ProgressEvent, RedactionPolicy, RerankerConfig, type ResponseMode, ScopeInput, type SearchResult, StorageBackend, type TaskRunner, type TaskStatus, ToolConfig, Trusted, Unset, UsageEvent, __version__, buildLlmClient, callLlm, compute, computeOverFrames, decryptDict, documentStructure, documentTypes, encryptDict, extract, extractStructuredData, fieldSummary, formatResult, functionTool, getDocumentText, getSecretKey, listDocuments, queryStructured, redactHits, rerank, resolveApproval, resolveFields, rowsToTsv, rrfFuse, runMigrate, runSearch, shouldRequireApproval, spreadsheetSchema, spreadsheetSchemaFromText, upsertRegistry };
package/dist/index.js CHANGED
@@ -11822,7 +11822,7 @@ var SCHEMAS = {
11822
11822
  url: { type: "string", description: "Endpoint URL, may contain {path} params" },
11823
11823
  method: {
11824
11824
  type: "string",
11825
- enum: ["GET", "POST", "PUT", "PATCH", "DELETE"],
11825
+ enum: ["GET", "POST", "PUT", "PATCH", "DELETE", "QUERY"],
11826
11826
  default: "GET"
11827
11827
  },
11828
11828
  headers: {
@@ -11858,6 +11858,15 @@ var SCHEMAS = {
11858
11858
  llmQueryParameters: {
11859
11859
  type: "object",
11860
11860
  description: "LLM-filled parameters sent as the query string"
11861
+ },
11862
+ // How the response comes back to the caller, whatever the method. `tsv`
11863
+ // turns every array of objects in it into a TSV string (`formatResult`
11864
+ // in tools/response-mode.ts); a caller's explicit `responseMode` wins.
11865
+ response_mode: {
11866
+ type: "string",
11867
+ enum: ["json", "tsv"],
11868
+ default: "json",
11869
+ description: "Return the response as JSON, or its arrays of objects as TSV"
11861
11870
  }
11862
11871
  },
11863
11872
  required: ["url", "method"]
@@ -13023,6 +13032,89 @@ function findTool(tools, callName) {
13023
13032
  return tools.find((t) => t.callName === callName);
13024
13033
  }
13025
13034
 
13035
+ // src/tools/response-mode.ts
13036
+ var RESPONSE_MODES = ["json", "tsv"];
13037
+ function validateResponseMode(value, name = "responseMode") {
13038
+ if (!RESPONSE_MODES.includes(value)) {
13039
+ throw new Error(`${name} must be one of json, tsv, got ${JSON.stringify(value)}`);
13040
+ }
13041
+ return value;
13042
+ }
13043
+ function tsvCell(value) {
13044
+ if (value === null || value === void 0) return "\\N";
13045
+ let text;
13046
+ if (typeof value === "string") text = value;
13047
+ else if (value instanceof Date) text = value.toISOString();
13048
+ else if (typeof value === "bigint") text = value.toString();
13049
+ else {
13050
+ try {
13051
+ text = JSON.stringify(value) ?? String(value);
13052
+ } catch {
13053
+ text = String(value);
13054
+ }
13055
+ }
13056
+ return text.replaceAll("\\", "\\\\").replaceAll(" ", "\\t").replaceAll("\n", "\\n").replaceAll("\r", "\\r");
13057
+ }
13058
+ function isPlainObject2(value) {
13059
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
13060
+ const proto = Object.getPrototypeOf(value);
13061
+ return proto === Object.prototype || proto === null;
13062
+ }
13063
+ function isTable(value) {
13064
+ return Array.isArray(value) && value.length > 0 && value.every(isPlainObject2);
13065
+ }
13066
+ function tsvLines(rows) {
13067
+ const columns = [];
13068
+ const seen = /* @__PURE__ */ new Set();
13069
+ for (const row of rows) {
13070
+ for (const key of Object.keys(row)) {
13071
+ if (!seen.has(key)) {
13072
+ seen.add(key);
13073
+ columns.push(key);
13074
+ }
13075
+ }
13076
+ }
13077
+ return [
13078
+ columns.map(tsvCell).join(" "),
13079
+ ...rows.map((row) => columns.map((c) => tsvCell(row[c])).join(" "))
13080
+ ];
13081
+ }
13082
+ function rowsToTsv(rows) {
13083
+ return rows.length ? tsvLines(rows).join("\n") : "";
13084
+ }
13085
+ function collectTables(value, path, out) {
13086
+ if (isTable(value)) {
13087
+ out.set(JSON.stringify(path), { path, lines: tsvLines(value) });
13088
+ } else if (isPlainObject2(value)) {
13089
+ for (const [key, child] of Object.entries(value)) collectTables(child, [...path, key], out);
13090
+ } else if (Array.isArray(value)) {
13091
+ value.forEach((child, index) => {
13092
+ collectTables(child, [...path, index], out);
13093
+ });
13094
+ }
13095
+ }
13096
+ function buildTsv(value, path, tables, kept) {
13097
+ const id = JSON.stringify(path);
13098
+ const table = tables.get(id);
13099
+ if (table) return table.lines.slice(0, (kept.get(id) ?? 0) + 1).join("\n");
13100
+ if (isPlainObject2(value)) {
13101
+ const out = {};
13102
+ for (const [k, v] of Object.entries(value)) out[k] = buildTsv(v, [...path, k], tables, kept);
13103
+ return out;
13104
+ }
13105
+ if (Array.isArray(value)) return value.map((v, i) => buildTsv(v, [...path, i], tables, kept));
13106
+ return value;
13107
+ }
13108
+ function formatResult(result, responseMode = "json") {
13109
+ if (validateResponseMode(responseMode) === "json") return result;
13110
+ const root = { result };
13111
+ const tables = /* @__PURE__ */ new Map();
13112
+ collectTables(root, [], tables);
13113
+ if (!tables.size) return result;
13114
+ const kept = new Map([...tables].map(([id, t]) => [id, t.lines.length - 1]));
13115
+ return buildTsv(root, [], tables, kept).result;
13116
+ }
13117
+
13026
13118
  // src/tools/governance.ts
13027
13119
  var RESULT_MAX_CHARS = 8e3;
13028
13120
  var RESULT_MAX_ROWS = 100;
@@ -13054,12 +13146,90 @@ function stripUnderscoreArgs(args) {
13054
13146
  }
13055
13147
  return out;
13056
13148
  }
13149
+ function validateResultBudget(name, value, fallback) {
13150
+ if (value === void 0) return fallback;
13151
+ if (value === null) return null;
13152
+ if (typeof value !== "number" || !Number.isInteger(value)) {
13153
+ throw new TypeError(`${name} must be a positive integer or null, got ${typeof value}`);
13154
+ }
13155
+ if (value < 1) throw new Error(`${name} must be a positive integer or null, got ${value}`);
13156
+ return value;
13157
+ }
13158
+ function serialize(value) {
13159
+ try {
13160
+ return JSON.stringify(value) ?? JSON.stringify(String(value));
13161
+ } catch {
13162
+ return JSON.stringify(String(value));
13163
+ }
13164
+ }
13165
+ function clip(serialized, maxChars) {
13166
+ return {
13167
+ _truncated: serialized.slice(0, maxChars),
13168
+ _original_size: serialized.length,
13169
+ _note: "tool result exceeded the context budget and was truncated"
13170
+ };
13171
+ }
13172
+ function shapeTsv(result, maxChars, maxRows) {
13173
+ const wrapped = !isPlainObject2(result);
13174
+ const root = wrapped ? { result } : result;
13175
+ const tables = /* @__PURE__ */ new Map();
13176
+ collectTables(root, [], tables);
13177
+ if (!tables.size) return null;
13178
+ const sizes = new Map([...tables].map(([id, t]) => [id, t.lines.length - 1]));
13179
+ const kept = new Map([...sizes].map(([id, n]) => [id, maxRows === null ? n : Math.min(n, maxRows)]));
13180
+ const render = () => {
13181
+ const built = buildTsv(root, [], tables, kept);
13182
+ const notes = {};
13183
+ for (const [id, t] of tables) {
13184
+ const k = kept.get(id);
13185
+ const n = sizes.get(id);
13186
+ if (k < n) notes[t.path.join(".")] = { rows_returned: k, rows_omitted: n - k };
13187
+ }
13188
+ if (Object.keys(notes).length) {
13189
+ built._result_shaping = notes;
13190
+ return built;
13191
+ }
13192
+ return wrapped ? built.result : built;
13193
+ };
13194
+ const fits = () => maxChars === null || serialize(render()).length <= maxChars;
13195
+ const capped2 = [...tables.keys()].some((id) => kept.get(id) < sizes.get(id));
13196
+ if (fits()) return [render(), capped2];
13197
+ const initial = new Map(kept);
13198
+ const tableSize = (id) => tables.get(id).lines.slice(0, kept.get(id) + 1).join("\n").length;
13199
+ const bySize = [...tables.keys()].sort((a, b) => tableSize(b) - tableSize(a));
13200
+ for (const id of bySize) {
13201
+ let lo = 0;
13202
+ let hi = kept.get(id) - 1;
13203
+ let best = null;
13204
+ while (lo <= hi) {
13205
+ const mid = Math.floor((lo + hi) / 2);
13206
+ kept.set(id, mid);
13207
+ if (fits()) {
13208
+ best = mid;
13209
+ lo = mid + 1;
13210
+ } else {
13211
+ hi = mid - 1;
13212
+ }
13213
+ }
13214
+ if (best !== null) {
13215
+ kept.set(id, best);
13216
+ return [render(), true];
13217
+ }
13218
+ kept.set(id, 0);
13219
+ }
13220
+ for (const [id, n] of initial) kept.set(id, n);
13221
+ return [clip(serialize(render()), maxChars), true];
13222
+ }
13057
13223
  function shapeResult(result, opts = {}) {
13058
- const maxChars = opts.maxChars ?? RESULT_MAX_CHARS;
13059
- const maxRows = opts.maxRows ?? RESULT_MAX_ROWS;
13224
+ const maxChars = opts.maxChars === void 0 ? RESULT_MAX_CHARS : opts.maxChars;
13225
+ const maxRows = opts.maxRows === void 0 ? RESULT_MAX_ROWS : opts.maxRows;
13226
+ if (opts.responseMode === "tsv") {
13227
+ const tsv = shapeTsv(result, maxChars, maxRows);
13228
+ if (tsv) return tsv;
13229
+ }
13060
13230
  let truncated = false;
13061
13231
  let shaped = result;
13062
- if (result && typeof result === "object" && Array.isArray(result.rows) && result.rows.length > maxRows) {
13232
+ if (maxRows !== null && result && typeof result === "object" && Array.isArray(result.rows) && result.rows.length > maxRows) {
13063
13233
  const rows = result.rows;
13064
13234
  const kept = rows.slice(0, maxRows);
13065
13235
  shaped = {
@@ -13069,22 +13239,9 @@ function shapeResult(result, opts = {}) {
13069
13239
  };
13070
13240
  truncated = true;
13071
13241
  }
13072
- let serialized;
13073
- try {
13074
- serialized = JSON.stringify(shaped);
13075
- } catch {
13076
- serialized = JSON.stringify(String(shaped));
13077
- }
13078
- if (serialized.length > maxChars) {
13079
- return [
13080
- {
13081
- _truncated: serialized.slice(0, maxChars),
13082
- _original_size: serialized.length,
13083
- _note: "tool result exceeded the context budget and was truncated"
13084
- },
13085
- true
13086
- ];
13087
- }
13242
+ if (maxChars === null) return [shaped, truncated];
13243
+ const serialized = serialize(shaped);
13244
+ if (serialized.length > maxChars) return [clip(serialized, maxChars), true];
13088
13245
  return [shaped, truncated];
13089
13246
  }
13090
13247
  function redactToolResult(result, policy, opts) {
@@ -13195,9 +13352,29 @@ function canonicalToPublic(ct) {
13195
13352
  params_schema: ct.paramsSchema
13196
13353
  };
13197
13354
  }
13355
+ function configuredResponseMode(ct, config) {
13356
+ if (ct.kind !== "http" || config.response_mode == null) return "json";
13357
+ try {
13358
+ return validateResponseMode(config.response_mode, "config.response_mode");
13359
+ } catch {
13360
+ console.warn(
13361
+ `tool ${ct.callName} has an unknown config response_mode ${JSON.stringify(config.response_mode)}; returning json`
13362
+ );
13363
+ return "json";
13364
+ }
13365
+ }
13366
+ function checkConfigResponseMode(kind, config) {
13367
+ if (kind !== "http" || !config || config.response_mode == null) return;
13368
+ try {
13369
+ validateResponseMode(config.response_mode, "config.response_mode");
13370
+ } catch (exc) {
13371
+ throw new ConfigTemplateError(exc.message);
13372
+ }
13373
+ }
13198
13374
  async function registerTool(engine, tc) {
13199
13375
  canonicalFromConfig(tc);
13200
13376
  const config = tc.config ?? {};
13377
+ checkConfigResponseMode(tc.kind, config);
13201
13378
  if (containsSentinel(config)) {
13202
13379
  throw new ConfigTemplateError(
13203
13380
  `config contains the ${JSON.stringify(REDACTED_SENTINEL)} placeholder \u2014 a redacted template cannot be registered as a new tool; re-enter the secret values`
@@ -13233,6 +13410,12 @@ async function updateTool(engine, id, opts) {
13233
13410
  if (!row || !aclVisible(row.acl != null ? [...row.acl] : null, principals)) {
13234
13411
  throw new EngineActionError(`tool not found: ${id}`);
13235
13412
  }
13413
+ if ("config" in fields) {
13414
+ checkConfigResponseMode(
13415
+ "kind" in fields ? fields.kind : row.kind,
13416
+ fields.config
13417
+ );
13418
+ }
13236
13419
  const sets = [];
13237
13420
  const params = [];
13238
13421
  let i = 1;
@@ -13542,6 +13725,9 @@ function warnUnscopedApproval(callName) {
13542
13725
  async function executeTool(engine, callName, args, opts = {}) {
13543
13726
  const runtimeArgs = args ?? {};
13544
13727
  const approvalScope = validateApprovalScope(opts.approvalScope);
13728
+ const resultMaxChars = validateResultBudget("resultMaxChars", opts.resultMaxChars, RESULT_MAX_CHARS);
13729
+ const resultMaxRows = validateResultBudget("resultMaxRows", opts.resultMaxRows, RESULT_MAX_ROWS);
13730
+ let responseMode = opts.responseMode === void 0 || opts.responseMode === null ? null : validateResponseMode(opts.responseMode);
13545
13731
  const ct = findTool(await mergedTools(engine, opts.sourceId ?? null), callName);
13546
13732
  if (!ct) throw new EngineActionError(`tool not found: ${callName}`);
13547
13733
  if (!toolVisible(ct, opts.principals ?? null)) {
@@ -13584,6 +13770,7 @@ async function executeTool(engine, callName, args, opts = {}) {
13584
13770
  if (ct.kind !== "function" && ct.id != null) {
13585
13771
  config = await decryptCtConfig(engine, ct.id);
13586
13772
  }
13773
+ responseMode ??= configuredResponseMode(ct, config);
13587
13774
  const actorType = opts.actor?.type ?? null;
13588
13775
  const actorId = opts.actor?.id ?? null;
13589
13776
  let rawResult = null;
@@ -13607,7 +13794,16 @@ async function executeTool(engine, callName, args, opts = {}) {
13607
13794
  hooks: engine.hooks
13608
13795
  });
13609
13796
  rawResult = redacted;
13610
- [shaped, truncated] = shapeResult(rawResult);
13797
+ let toShape = rawResult;
13798
+ if (responseMode === "tsv" && ct.kind === "db" && isPlainObject2(rawResult)) {
13799
+ const { text: _preview, ...rest } = rawResult;
13800
+ toShape = rest;
13801
+ }
13802
+ [shaped, truncated] = shapeResult(toShape, {
13803
+ maxChars: resultMaxChars,
13804
+ maxRows: resultMaxRows,
13805
+ responseMode
13806
+ });
13611
13807
  } catch (e) {
13612
13808
  exc = e;
13613
13809
  success = false;
@@ -14263,7 +14459,10 @@ var ContextEngine = class _ContextEngine {
14263
14459
  principals: resolvePrincipals(opts.principals, "executeTool"),
14264
14460
  actor: opts.actor,
14265
14461
  source: opts.source ?? "api",
14266
- approvalScope: opts.approvalScope
14462
+ approvalScope: opts.approvalScope,
14463
+ resultMaxChars: opts.resultMaxChars,
14464
+ resultMaxRows: opts.resultMaxRows,
14465
+ responseMode: opts.responseMode
14267
14466
  });
14268
14467
  }
14269
14468
  };
@@ -14553,6 +14752,6 @@ init_sentinels();
14553
14752
  init_structured();
14554
14753
  init_usage();
14555
14754
 
14556
- export { ApprovalExpired, ApprovalNotPending, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, GraphLegUnavailable, InProcessRunner, KNOWLEDGE_ACTIONS, KNOWLEDGE_TOOL_DESCRIPTION, LLMClient, PostgresBackend, RedactionPolicy, RedactionRule, TRUSTED, ToolConfig, UNSCOPED, UNSET, __version__, applyRedaction, buildEmbedder, buildLlmClient, callKnowledgeTool, callLlm, compute, computeOverFrames, configSchema, createMcpApp, decryptDict, documentStructure, documentTypes, emitError, emitProgress, emitToolCall, emitUsage, encryptDict, extract2 as extract, extractStructuredData, fieldSummary, functionTool, getDocumentText, getSecretKey, graphUnits, knowledgeToolDefinition, listDocuments, narrowToCeiling, queryStructured, redactHits, rerank, resolveApproval, resolveFields, resolvePrincipals, resolveScope, rrfFuse, runMigrate, runSearch, shouldRequireApproval, spreadsheetSchema, spreadsheetSchemaFromText, unitsForFile, upsertRegistry };
14755
+ export { ApprovalExpired, ApprovalNotPending, CeleryRunner, CodeExecutionError, CodeExecutionTimeout, ContextEngine, ContextEngineConfig, DEFAULT_LEG_WEIGHT, DocumentNotFoundError, EXTRACTION_VERSION, Embedder, EngineActionError, ExtraMissingError, Extracted, GraphLegUnavailable, InProcessRunner, KNOWLEDGE_ACTIONS, KNOWLEDGE_TOOL_DESCRIPTION, LLMClient, PostgresBackend, RedactionPolicy, RedactionRule, TRUSTED, ToolConfig, UNSCOPED, UNSET, __version__, applyRedaction, buildEmbedder, buildLlmClient, callKnowledgeTool, callLlm, compute, computeOverFrames, configSchema, createMcpApp, decryptDict, documentStructure, documentTypes, emitError, emitProgress, emitToolCall, emitUsage, encryptDict, extract2 as extract, extractStructuredData, fieldSummary, formatResult, functionTool, getDocumentText, getSecretKey, graphUnits, knowledgeToolDefinition, listDocuments, narrowToCeiling, queryStructured, redactHits, rerank, resolveApproval, resolveFields, resolvePrincipals, resolveScope, rowsToTsv, rrfFuse, runMigrate, runSearch, shouldRequireApproval, spreadsheetSchema, spreadsheetSchemaFromText, unitsForFile, upsertRegistry };
14557
14756
  //# sourceMappingURL=index.js.map
14558
14757
  //# sourceMappingURL=index.js.map