run402-mcp
Version:
MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.
66 lines • 2.81 kB
JavaScript
/**
* How a `run` value is paged: by items, never by text lines.
*
* A value that fits the inline budget is returned whole. A larger one is paged
* by the unit a reader thinks in:
*
* - an array: its elements (`path: "$"`);
* - an object holding arrays: the elements of its largest top-level array,
* e.g. the `rows` of a SQL result (`path: "$.rows"`), with the object's
* other fields kept whole beside the window (`rest`);
* - any other object: its entries as `{ key, value }` (`path: "$entries"`);
* - a long string: its lines (`path: "$lines"`).
*
* The window is whole items only: as many leading items as fit the budget,
* and always at least one, so a page never ends in the middle of a row.
*/
/** A value whose pretty-printed JSON fits in this many lines is returned whole. */
export const VALUE_INLINE_LINES = 200;
function prettyLines(value) {
const text = JSON.stringify(value, null, 2);
return text === undefined ? 1 : text.split("\n").length;
}
/** True when the whole value fits the inline budget. */
export function fitsInline(value, budget = VALUE_INLINE_LINES) {
return prettyLines(value) <= budget;
}
/** The items a value pages by, and where they live. */
export function pageableItems(value) {
if (Array.isArray(value))
return { path: "$", items: value };
if (value !== null && typeof value === "object") {
const obj = value;
let best = null;
for (const [key, v] of Object.entries(obj)) {
if (Array.isArray(v) && (best === null || v.length > obj[best].length))
best = key;
}
if (best !== null && obj[best].length > 0) {
const rest = {};
for (const [key, v] of Object.entries(obj))
if (key !== best)
rest[key] = v;
return { path: `$.${best}`, items: obj[best], rest };
}
return { path: "$entries", items: Object.entries(obj).map(([key, v]) => ({ key, value: v })) };
}
if (typeof value === "string")
return { path: "$lines", items: value.split("\n") };
return { path: "$", items: [value] };
}
/** Page a value that does not fit inline: every item, and the leading window of whole items. */
export function pageValue(value, budget = VALUE_INLINE_LINES) {
const { path, items, rest } = pageableItems(value);
const restLines = rest ? prettyLines(rest) : 0;
const window = [];
let used = restLines + 2; // the brackets around the window
for (const item of items) {
const cost = prettyLines(item);
if (window.length > 0 && used + cost > budget)
break;
window.push(item);
used += cost;
}
return { path, items, window, ...(rest ? { rest } : {}) };
}
//# sourceMappingURL=value-paging.js.map