@konneal/engine 0.2.150 → 0.2.153
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/{ask-KVGDQTF7.js → ask-UIIE5LD2.js} +1 -1
- package/dist/{chunk-CPPIKASJ.js → chunk-I6HU3EM6.js} +910 -874
- package/dist/mcp-proto.d.ts +3 -0
- package/dist/worker_public/src/index.js +31 -3
- package/docs/AGENT-MODE-STREAM-FIRST.md +84 -0
- package/package.json +1 -1
- package/workers/worker_public/src/ask.ts +229 -163
- package/workers/worker_public/src/mcp-proto.ts +39 -1
|
@@ -94,6 +94,44 @@ export function buildTools(): McpTool[] {
|
|
|
94
94
|
];
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
// The tool-result budget (the cloudflare/mcp pattern, 2026-10-19): an
|
|
98
|
+
// MCP client spends its own context reading tool results, so an
|
|
99
|
+
// unbounded payload (a broad db.find over the register, a large
|
|
100
|
+
// retrieve) can eat an agent's window. An oversized result comes back
|
|
101
|
+
// size-bounded and still valid JSON: short fields (names, numbers,
|
|
102
|
+
// metadata) stay whole, long strings clip, every cut is marked.
|
|
103
|
+
export const TOOL_RESULT_CHAR_CAP = 24000; // ≈6k tokens
|
|
104
|
+
export const TRUNCATION_MARK = "--- TRUNCATED ---";
|
|
105
|
+
|
|
106
|
+
const jsonLen = (x: unknown): number => JSON.stringify(x)?.length ?? 0;
|
|
107
|
+
|
|
108
|
+
function clipStrings(value: unknown, budget: number): unknown {
|
|
109
|
+
if (typeof value === "string") return value.length <= budget ? value : `${value.slice(0, budget)}\n${TRUNCATION_MARK}`;
|
|
110
|
+
if (Array.isArray(value)) return value.map((v) => clipStrings(v, budget));
|
|
111
|
+
if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, clipStrings(v, budget)]));
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function capToolResult(payload: unknown, cap: number = TOOL_RESULT_CHAR_CAP): unknown {
|
|
116
|
+
if (jsonLen(payload) <= cap) return payload;
|
|
117
|
+
// the per-string budget shrinks until the whole payload fits
|
|
118
|
+
let lo = 200;
|
|
119
|
+
let hi = cap;
|
|
120
|
+
let best = clipStrings(payload, lo);
|
|
121
|
+
while (lo <= hi) {
|
|
122
|
+
const mid = (lo + hi) >> 1;
|
|
123
|
+
const candidate = clipStrings(payload, mid);
|
|
124
|
+
if (jsonLen(candidate) <= cap) {
|
|
125
|
+
best = candidate;
|
|
126
|
+
lo = mid + 1;
|
|
127
|
+
} else {
|
|
128
|
+
hi = mid - 1;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (jsonLen(best) <= cap) return best;
|
|
132
|
+
return { truncation: `the tool result exceeded the ${cap}-character budget and was withheld` };
|
|
133
|
+
}
|
|
134
|
+
|
|
97
135
|
export type McpResult =
|
|
98
136
|
| { ok: true; result: unknown }
|
|
99
137
|
| { ok: true; accepted: true }
|
|
@@ -120,7 +158,7 @@ export function dispatch(
|
|
|
120
158
|
return Promise.resolve({ ok: false, code: -32602, message: `unknown tool: ${name}` });
|
|
121
159
|
}
|
|
122
160
|
return callTool(registryName(name), params?.arguments ?? {}).then(
|
|
123
|
-
(payload) => ({ ok: true, result: { content: [{ type: "text", text: JSON.stringify(payload) }] } }) as McpResult,
|
|
161
|
+
(payload) => ({ ok: true, result: { content: [{ type: "text", text: JSON.stringify(capToolResult(payload)) }] } }) as McpResult,
|
|
124
162
|
);
|
|
125
163
|
}
|
|
126
164
|
default:
|