Files
sausage/host/js/p4-test-bundle.js
T

1731 lines
59 KiB
JavaScript

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
try {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
} catch (e) {
throw mod = 0, e;
}
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// host/js/node_modules/partial-json/dist/options.js
var require_options = __commonJS({
"host/js/node_modules/partial-json/dist/options.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Allow = exports.ALL = exports.COLLECTION = exports.ATOM = exports.SPECIAL = exports.INF = exports._INFINITY = exports.INFINITY = exports.NAN = exports.BOOL = exports.NULL = exports.OBJ = exports.ARR = exports.NUM = exports.STR = void 0;
exports.STR = 1;
exports.NUM = 2;
exports.ARR = 4;
exports.OBJ = 8;
exports.NULL = 16;
exports.BOOL = 32;
exports.NAN = 64;
exports.INFINITY = 128;
exports._INFINITY = 256;
exports.INF = exports.INFINITY | exports._INFINITY;
exports.SPECIAL = exports.NULL | exports.BOOL | exports.INF | exports.NAN;
exports.ATOM = exports.STR | exports.NUM | exports.SPECIAL;
exports.COLLECTION = exports.ARR | exports.OBJ;
exports.ALL = exports.ATOM | exports.COLLECTION;
exports.Allow = { STR: exports.STR, NUM: exports.NUM, ARR: exports.ARR, OBJ: exports.OBJ, NULL: exports.NULL, BOOL: exports.BOOL, NAN: exports.NAN, INFINITY: exports.INFINITY, _INFINITY: exports._INFINITY, INF: exports.INF, SPECIAL: exports.SPECIAL, ATOM: exports.ATOM, COLLECTION: exports.COLLECTION, ALL: exports.ALL };
exports.default = exports.Allow;
}
});
// host/js/node_modules/partial-json/dist/index.js
var require_dist = __commonJS({
"host/js/node_modules/partial-json/dist/index.js"(exports) {
"use strict";
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
if (k2 === void 0) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() {
return m[k];
} };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === void 0) k2 = k;
o[k2] = m[k];
}));
var __exportStar = exports && exports.__exportStar || function(m, exports2) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Allow = exports.MalformedJSON = exports.PartialJSON = exports.parseJSON = exports.parse = void 0;
var options_1 = require_options();
Object.defineProperty(exports, "Allow", { enumerable: true, get: function() {
return options_1.Allow;
} });
__exportStar(require_options(), exports);
var PartialJSON = class extends Error {
};
exports.PartialJSON = PartialJSON;
var MalformedJSON = class extends Error {
};
exports.MalformedJSON = MalformedJSON;
function parseJSON(jsonString, allowPartial = options_1.Allow.ALL) {
if (typeof jsonString !== "string") {
throw new TypeError(`expecting str, got ${typeof jsonString}`);
}
if (!jsonString.trim()) {
throw new Error(`${jsonString} is empty`);
}
return _parseJSON(jsonString.trim(), allowPartial);
}
exports.parseJSON = parseJSON;
var _parseJSON = (jsonString, allow) => {
const length = jsonString.length;
let index = 0;
const markPartialJSON = (msg) => {
throw new PartialJSON(`${msg} at position ${index}`);
};
const throwMalformedError = (msg) => {
throw new MalformedJSON(`${msg} at position ${index}`);
};
const parseAny = () => {
skipBlank();
if (index >= length)
markPartialJSON("Unexpected end of input");
if (jsonString[index] === '"')
return parseStr();
if (jsonString[index] === "{")
return parseObj();
if (jsonString[index] === "[")
return parseArr();
if (jsonString.substring(index, index + 4) === "null" || options_1.Allow.NULL & allow && length - index < 4 && "null".startsWith(jsonString.substring(index))) {
index += 4;
return null;
}
if (jsonString.substring(index, index + 4) === "true" || options_1.Allow.BOOL & allow && length - index < 4 && "true".startsWith(jsonString.substring(index))) {
index += 4;
return true;
}
if (jsonString.substring(index, index + 5) === "false" || options_1.Allow.BOOL & allow && length - index < 5 && "false".startsWith(jsonString.substring(index))) {
index += 5;
return false;
}
if (jsonString.substring(index, index + 8) === "Infinity" || options_1.Allow.INFINITY & allow && length - index < 8 && "Infinity".startsWith(jsonString.substring(index))) {
index += 8;
return Infinity;
}
if (jsonString.substring(index, index + 9) === "-Infinity" || options_1.Allow._INFINITY & allow && 1 < length - index && length - index < 9 && "-Infinity".startsWith(jsonString.substring(index))) {
index += 9;
return -Infinity;
}
if (jsonString.substring(index, index + 3) === "NaN" || options_1.Allow.NAN & allow && length - index < 3 && "NaN".startsWith(jsonString.substring(index))) {
index += 3;
return NaN;
}
return parseNum();
};
const parseStr = () => {
const start = index;
let escape = false;
index++;
while (index < length && (jsonString[index] !== '"' || escape && jsonString[index - 1] === "\\")) {
escape = jsonString[index] === "\\" ? !escape : false;
index++;
}
if (jsonString.charAt(index) == '"') {
try {
return JSON.parse(jsonString.substring(start, ++index - Number(escape)));
} catch (e) {
throwMalformedError(String(e));
}
} else if (options_1.Allow.STR & allow) {
try {
return JSON.parse(jsonString.substring(start, index - Number(escape)) + '"');
} catch (e) {
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("\\")) + '"');
}
}
markPartialJSON("Unterminated string literal");
};
const parseObj = () => {
index++;
skipBlank();
const obj = {};
try {
while (jsonString[index] !== "}") {
skipBlank();
if (index >= length && options_1.Allow.OBJ & allow)
return obj;
const key = parseStr();
skipBlank();
index++;
try {
const value = parseAny();
obj[key] = value;
} catch (e) {
if (options_1.Allow.OBJ & allow)
return obj;
else
throw e;
}
skipBlank();
if (jsonString[index] === ",")
index++;
}
} catch (e) {
if (options_1.Allow.OBJ & allow)
return obj;
else
markPartialJSON("Expected '}' at end of object");
}
index++;
return obj;
};
const parseArr = () => {
index++;
const arr = [];
try {
while (jsonString[index] !== "]") {
arr.push(parseAny());
skipBlank();
if (jsonString[index] === ",") {
index++;
}
}
} catch (e) {
if (options_1.Allow.ARR & allow) {
return arr;
}
markPartialJSON("Expected ']' at end of array");
}
index++;
return arr;
};
const parseNum = () => {
if (index === 0) {
if (jsonString === "-")
throwMalformedError("Not sure what '-' is");
try {
return JSON.parse(jsonString);
} catch (e) {
if (options_1.Allow.NUM & allow)
try {
return JSON.parse(jsonString.substring(0, jsonString.lastIndexOf("e")));
} catch (e2) {
}
throwMalformedError(String(e));
}
}
const start = index;
if (jsonString[index] === "-")
index++;
while (jsonString[index] && ",]}".indexOf(jsonString[index]) === -1)
index++;
if (index == length && !(options_1.Allow.NUM & allow))
markPartialJSON("Unterminated number literal");
try {
return JSON.parse(jsonString.substring(start, index));
} catch (e) {
if (jsonString.substring(start, index) === "-")
markPartialJSON("Not sure what '-' is");
try {
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("e")));
} catch (e2) {
throwMalformedError(String(e2));
}
}
};
const skipBlank = () => {
while (index < length && " \n\r ".includes(jsonString[index])) {
index++;
}
};
return parseAny();
};
var parse = parseJSON;
exports.parse = parse;
}
});
// host/js/node_modules/@earendil-works/pi-ai/dist/utils/event-stream.js
var FifoQueue = class {
incoming = [];
outgoing = [];
get length() {
return this.incoming.length + this.outgoing.length;
}
enqueue(value) {
this.incoming.push(value);
}
dequeue() {
if (this.outgoing.length === 0) {
while (this.incoming.length > 0) {
this.outgoing.push(this.incoming.pop());
}
}
return this.outgoing.pop();
}
};
var EventStream = class {
queue = new FifoQueue();
waiting = new FifoQueue();
done = false;
finalResultPromise;
resolveFinalResult;
isComplete;
extractResult;
constructor(isComplete, extractResult) {
this.isComplete = isComplete;
this.extractResult = extractResult;
this.finalResultPromise = new Promise((resolve) => {
this.resolveFinalResult = resolve;
});
}
push(event) {
if (this.done)
return;
if (this.isComplete(event)) {
this.done = true;
this.resolveFinalResult(this.extractResult(event));
}
const waiter = this.waiting.dequeue();
if (waiter) {
waiter({ value: event, done: false });
} else {
this.queue.enqueue(event);
}
}
end(result) {
this.done = true;
if (result !== void 0) {
this.resolveFinalResult(result);
}
while (this.waiting.length > 0) {
const waiter = this.waiting.dequeue();
waiter({ value: void 0, done: true });
}
}
async *[Symbol.asyncIterator]() {
while (true) {
if (this.queue.length > 0) {
yield this.queue.dequeue();
} else if (this.done) {
return;
} else {
const result = await new Promise((resolve) => this.waiting.enqueue(resolve));
if (result.done)
return;
yield result.value;
}
}
}
result() {
return this.finalResultPromise;
}
};
var AssistantMessageEventStream = class extends EventStream {
#startedAt = Date.now();
#startedAtMonotonic = performance.now();
constructor() {
super((event) => event.type === "done" || event.type === "error", (event) => {
if (event.type === "done") {
return event.message;
} else if (event.type === "error") {
return event.error;
}
throw new Error("Unexpected event type for final result");
});
}
push(event) {
if (event.type === "done")
this.#time(event.message);
else if (event.type === "error")
this.#time(event.error);
super.push(event);
}
end(result) {
if (result !== void 0)
this.#time(result);
super.end(result);
}
#time(message) {
if (this.done || message.durationMs !== void 0 || message.timestamp < this.#startedAt)
return;
message.durationMs = Math.max(0, Math.round(performance.now() - this.#startedAtMonotonic));
}
};
function createAssistantMessageEventStream() {
return new AssistantMessageEventStream();
}
// host/js/node_modules/@earendil-works/pi-ai/dist/api/lazy.js
function createSetupErrorMessage(model, error, timestamp) {
return {
role: "assistant",
content: [],
api: model.api,
provider: model.provider,
model: model.id,
usage: {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0,
totalTokens: 0,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
},
stopReason: "error",
errorMessage: error instanceof Error ? error.message : String(error),
timestamp
};
}
function hasResult(source) {
return typeof source.result === "function";
}
async function forwardStream(target, source, observer, observeResult) {
let result;
for await (const event of source) {
target.push(event);
observer?.onEvent?.(event);
if (event.type === "done")
result = event.message;
else if (event.type === "error")
result = event.error;
}
if (hasResult(source))
result = await source.result();
target.end(result);
observeResult(result);
}
function lazyStream(model, setup, observer) {
const startedAt = Date.now();
const outer = new AssistantMessageEventStream();
let observedResult = false;
const observeResult = (result) => {
if (observedResult)
return;
observedResult = true;
observer?.onResult?.(result);
};
setup().then((inner) => forwardStream(outer, inner, observer, observeResult)).catch((error) => {
const message = createSetupErrorMessage(model, error, startedAt);
const event = { type: "error", reason: "error", error: message };
outer.push(event);
observer?.onEvent?.(event);
outer.end(message);
observeResult(message);
});
return outer;
}
// host/js/node_modules/@earendil-works/pi-ai/dist/utils/diagnostics.js
function formatThrownValue(value) {
if (value instanceof Error)
return value.message || value.name;
if (typeof value === "string")
return value;
return String(value);
}
// host/js/node_modules/@earendil-works/pi-ai/dist/utils/models-error.js
var ModelsError = class extends Error {
code;
constructor(code, message, options) {
super(withCauseDetail(message, options?.cause), options);
this.name = "ModelsError";
this.code = code;
}
};
function withCauseDetail(message, cause) {
if (cause === void 0 || cause === null)
return message;
const detail = formatThrownValue(cause).trim();
if (!detail || message.includes(detail))
return message;
return `${message}: ${detail}`;
}
// host/js/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js
var DEFAULT_OAUTH_MINIMUM_VALIDITY_MS = 5 * 60 * 1e3;
// host/js/node_modules/@earendil-works/pi-ai/dist/utils/text.js
function contentText(content, separator = "\n") {
if (typeof content === "string")
return content;
return content.filter((block) => block.type === "text").map((block) => block.text).join(separator);
}
function getSystemMessageText(message) {
const parts = [contentText(message.content)];
for (const text of Object.values(message.sections ?? {})) {
if (text !== null)
parts.push(text);
}
return parts.filter((part) => part.length > 0).join("\n\n");
}
// host/js/node_modules/@earendil-works/pi-ai/dist/utils/model-operations.js
function getModelType(model) {
return model.type ?? "chat";
}
function isModelType(model, type) {
return getModelType(model) === type;
}
function imageErrorResult(model, error, aborted = false) {
return {
api: model.api,
provider: model.provider,
model: model.id,
output: [],
stopReason: aborted ? "aborted" : "error",
errorMessage: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
}
function classifierErrorResult(model, error, aborted = false) {
return {
api: model.api,
provider: model.provider,
model: model.id,
answers: {},
stopReason: aborted ? "aborted" : "error",
errorMessage: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
}
// host/js/node_modules/@earendil-works/pi-ai/dist/models.js
var KNOWN_MODEL_TYPES = { chat: true, image: true, classifier: true };
function hasKnownModelType(model) {
return Object.hasOwn(KNOWN_MODEL_TYPES, getModelType(model));
}
function createProvider(input) {
const single = input.api && typeof input.api.stream === "function" ? input.api : void 0;
const byApi = single || !input.api ? void 0 : input.api;
const images = input.images;
const classifiers = input.classifiers;
const streams = single ? [single] : Object.values(byApi ?? {}).filter((entry) => entry !== void 0);
const imageImplementations = Object.values(images ?? {}).filter((entry) => entry !== void 0);
const classifierImplementations = Object.values(classifiers ?? {}).filter((entry) => entry !== void 0);
if (streams.length === 0 && imageImplementations.length === 0 && classifierImplementations.length === 0) {
throw new Error(`Provider ${input.id}: at least one of "api", "images", or "classifiers" is required.`);
}
const baselineModels = input.models;
let dynamicModels = [];
const fetchModels = input.fetchModels;
const currentModels = () => {
const merged = [...baselineModels];
for (const model of dynamicModels) {
const index = merged.findIndex((entry) => getModelType(entry) === getModelType(model) && entry.id === model.id);
if (index >= 0)
merged[index] = model;
else
merged.push(model);
}
return merged;
};
const apiFor = (model) => single ?? byApi?.[model.api];
const dispatch = (model, run) => {
const streams2 = apiFor(model);
if (!streams2) {
return lazyStream(model, async () => {
throw new ModelsError("stream", `Provider ${input.id} has no API implementation for "${model.api}"`);
});
}
return run(streams2);
};
const provider = {
id: input.id,
name: input.name ?? input.id,
baseUrl: input.baseUrl,
headers: input.headers,
auth: input.auth,
getModels: () => currentModels().filter((model) => isModelType(model, "chat")),
getAllModels: currentModels,
refreshModels: fetchModels ? async (context) => {
if (context.stored) {
const restored = context.stored.models.filter((model) => model.provider === input.id).map((model) => model);
if (!await context.publish({
update: () => {
dynamicModels = restored;
}
})) {
return;
}
}
if (!context.allowNetwork || context.signal.aborted)
return;
const fetched = await fetchModels(context);
if (context.signal.aborted)
return;
const refreshed = fetched.filter(hasKnownModelType);
await context.publish({
persist: { models: refreshed, checkedAt: Date.now() },
update: () => {
dynamicModels = refreshed;
}
});
} : void 0,
filterModels: input.filterModels,
filterAllModels: input.filterAllModels,
stream: (model, context, options) => dispatch(model, (streams2) => streams2.stream(model, context, options)),
streamSimple: (model, context, options) => dispatch(model, (streams2) => streams2.streamSimple(model, context, options))
};
if (streams.some((entry) => entry.fetchDeferred !== void 0)) {
provider.fetchDeferred = (model, handle, options) => lazyStream(model, async () => {
const implementation = apiFor(model);
if (!implementation?.fetchDeferred) {
throw new ModelsError("provider", `Provider ${input.id} does not support deferred responses for "${model.api}"`);
}
return implementation.fetchDeferred(model, handle, options);
});
}
if (streams.some((entry) => entry.cancelDeferred !== void 0)) {
provider.cancelDeferred = async (model, handle, options) => {
const implementation = apiFor(model);
if (!implementation?.cancelDeferred) {
throw new ModelsError("provider", `Provider ${input.id} cannot cancel deferred responses for "${model.api}"`);
}
await implementation.cancelDeferred(model, handle, options);
};
}
if (images && imageImplementations.length > 0) {
provider.generateImages = async (model, context, options) => {
const implementation = images[model.api];
if (!implementation) {
return imageErrorResult(model, new ModelsError("provider", `Provider ${input.id} has no image generation implementation for "${model.api}"`));
}
return implementation.generateImages(model, context, options);
};
}
if (classifiers && classifierImplementations.length > 0) {
provider.classify = async (model, context, options) => {
const implementation = classifiers[model.api];
if (!implementation) {
return classifierErrorResult(model, new ModelsError("provider", `Provider ${input.id} has no classifier implementation for "${model.api}"`));
}
return implementation.classify(model, context, options);
};
}
return provider;
}
// host/js/node_modules/@earendil-works/pi-ai/dist/utils/json-parse.js
var import_partial_json = __toESM(require_dist(), 1);
var VALID_JSON_ESCAPES = /* @__PURE__ */ new Set(['"', "\\", "/", "b", "f", "n", "r", "t"]);
function isControlCharacter(char) {
const codePoint = char.codePointAt(0);
return codePoint !== void 0 && codePoint >= 0 && codePoint <= 31;
}
function escapeControlCharacter(char) {
switch (char) {
case "\b":
return "\\b";
case "\f":
return "\\f";
case "\n":
return "\\n";
case "\r":
return "\\r";
case " ":
return "\\t";
default:
return `\\u${char.codePointAt(0)?.toString(16).padStart(4, "0") ?? "0000"}`;
}
}
function repairJson(json) {
let repaired = "";
let inString = false;
for (let index = 0; index < json.length; index++) {
const char = json[index];
if (!inString) {
repaired += char;
if (char === '"') {
inString = true;
}
continue;
}
if (char === '"') {
repaired += char;
inString = false;
continue;
}
if (char === "\\") {
const nextChar = json[index + 1];
if (nextChar === void 0) {
repaired += "\\\\";
continue;
}
if (nextChar === "u") {
const unicodeDigits = json.slice(index + 2, index + 6);
if (/^[0-9a-fA-F]{4}$/.test(unicodeDigits)) {
repaired += `\\u${unicodeDigits}`;
index += 5;
continue;
}
}
if (VALID_JSON_ESCAPES.has(nextChar)) {
repaired += `\\${nextChar}`;
index += 1;
continue;
}
repaired += "\\\\";
continue;
}
repaired += isControlCharacter(char) ? escapeControlCharacter(char) : char;
}
return repaired;
}
function parseJsonWithRepair(json) {
try {
return JSON.parse(json);
} catch (error) {
const repairedJson = repairJson(json);
if (repairedJson !== json) {
return JSON.parse(repairedJson);
}
throw error;
}
}
function parseToolCallArguments(json) {
if (!json?.trim())
return { arguments: {} };
try {
const parsed = parseJsonWithRepair(json);
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
throw new Error("Tool arguments must be a JSON object");
}
return { arguments: parsed };
} catch (error) {
return {
arguments: {},
argumentsError: `${error instanceof Error ? error.message : String(error)}
Received arguments:
${json}`
};
}
}
// host/js/node_modules/@earendil-works/pi-ai/dist/utils/streaming-json.js
var MAX_REPORTED_DEPTH = 32;
var ROOT_SLOT = { kind: "root" };
var CREDIT_PER_APPEND = 256;
var CREDIT_PER_CHARACTER = 8;
var MAX_PENDING_SCALAR_LENGTH = 64;
var NUMBER = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
var NUMBER_WITHOUT_EXPONENT_DIGITS = /^(-?(?:0|[1-9]\d*)(?:\.\d+)?)[eE][+-]?$/;
var LITERALS = [
["true", true],
["false", false],
["null", null]
];
var QUOTE = 34;
var BACKSLASH = 92;
var StreamingJsonParser = class {
#root = void 0;
#done = false;
#stack = [];
#string = void 0;
#scalar = "";
#scalarSlot = void 0;
/** Sum of `size + 1` over the open path: what a fresh snapshot copies. */
#pathCost = 0;
#credit = 0;
#dirty = false;
#snapshot = void 0;
/** Changes of the piece being read. */
#changes = [];
/**
* Read the next piece of text; returns the changes it made, in order. Costs time linear in `text.length`.
*/
append(text) {
this.#credit += CREDIT_PER_APPEND + CREDIT_PER_CHARACTER * text.length;
this.#changes = [];
if (this.#string !== void 0)
this.#string.change = void 0;
let index = 0;
while (index < text.length && !this.#done) {
const open = this.#string;
if (open !== void 0)
index = this.#readString(open, text, index);
else if (this.#scalar !== "")
index = this.#readScalar(text, index);
else
this.#structural(text[index++]);
}
return this.#changes;
}
/**
* The value of the text read so far: `undefined` before a value starts, otherwise a plain JSON value that never
* changes afterwards. Returns the previous snapshot while the text read since did not change the value, or while a
* fresh copy of the open path is not yet paid for (see the module comment).
*/
snapshot() {
if (!this.#dirty)
return this.#snapshot;
const pending = this.#pendingScalar();
const cost = this.#pathCost + (pending === void 0 ? 0 : 1);
if (cost > this.#credit)
return this.#snapshot;
this.#credit -= cost;
this.#dirty = false;
this.#snapshot = this.#copyOpenPath(pending);
return this.#snapshot;
}
/** Read string characters from `start` until the string ends or the text does; returns the next index. */
#readString(open, text, start) {
let runStart = start;
for (let index = start; index < text.length; index++) {
const code = text.charCodeAt(index);
if (open.escape !== "") {
if (this.#continueEscape(open, text[index])) {
runStart = index + 1;
continue;
}
runStart = index;
}
if (code === QUOTE) {
if (index > runStart)
this.#appendString(open, text.slice(runStart, index));
this.#endString(open);
return index + 1;
}
if (code === BACKSLASH) {
if (index > runStart)
this.#appendString(open, text.slice(runStart, index));
open.escape = "\\";
runStart = index + 1;
}
}
if (text.length > runStart)
this.#appendString(open, text.slice(runStart));
return text.length;
}
/** Read number or literal characters from `start` up to the next delimiter; returns the delimiter's index. */
#readScalar(text, start) {
let end = start;
while (end < text.length && !isDelimiter(text[end]))
end++;
if (end > start) {
this.#scalar += text.slice(start, end);
if (this.#scalarSlot !== void 0)
this.#dirty = true;
}
if (end < text.length)
this.#endScalar();
return end;
}
/** Handle one character outside strings. */
#structural(char) {
switch (char) {
case " ":
case " ":
case "\n":
case "\r":
return;
case '"':
this.#startString();
return;
case "{":
case "[":
this.#openContainer(char === "{" ? {} : []);
return;
case "}":
case "]":
this.#closeContainer();
return;
case ":": {
const frame = this.#stack.at(-1);
if (frame !== void 0 && !Array.isArray(frame.container) && frame.phase === "colon")
frame.phase = "value";
return;
}
case ",": {
const frame = this.#stack.at(-1);
if (frame !== void 0)
frame.phase = Array.isArray(frame.container) ? "value" : "key";
return;
}
default:
this.#scalar = char;
this.#scalarSlot = this.#valueSlot();
if (this.#scalarSlot !== void 0)
this.#dirty = true;
}
}
/** Where a value starting now goes, or `undefined` when this position takes no value. */
#valueSlot() {
const frame = this.#stack.at(-1);
if (frame === void 0)
return this.#root === void 0 ? ROOT_SLOT : void 0;
if (Array.isArray(frame.container))
return { kind: "element", index: frame.container.length };
if ((frame.phase === "value" || frame.phase === "colon") && frame.key !== void 0) {
return { kind: "member", key: frame.key };
}
return void 0;
}
#startString() {
const frame = this.#stack.at(-1);
if (frame !== void 0 && !Array.isArray(frame.container) && (frame.phase === "key" || frame.phase === "comma")) {
this.#string = { target: "key", slot: void 0, text: "", escape: "", path: void 0, change: void 0 };
return;
}
const slot = this.#valueSlot();
const path = this.#reportedPath(slot);
this.#string = { target: "value", slot, text: "", escape: "", path, change: void 0 };
this.#place(slot, "");
if (path !== void 0)
this.#string.change = this.#report({ kind: "set", path, value: "" });
}
/** The path of a value at `slot` in the innermost open container, when its changes are reported. */
#reportedPath(slot) {
if (slot === void 0)
return void 0;
if (slot.kind === "root")
return [];
const frame = this.#stack.at(-1);
if (!frame.reportsInside)
return void 0;
return [...frame.path, slot.kind === "member" ? slot.key : slot.index];
}
#report(change) {
this.#changes.push(change);
return change;
}
/** Continue an escape with `char`; returns false when `char` is not part of it and must be read normally. */
#continueEscape(open, char) {
if (open.escape === "\\") {
const decoded = SIMPLE_ESCAPES[char];
if (decoded !== void 0) {
open.escape = "";
this.#appendString(open, decoded);
return true;
}
if (char === "u") {
open.escape = "\\u";
return true;
}
open.escape = "";
this.#appendString(open, "\\");
return false;
}
if (isHexDigit(char)) {
open.escape += char;
if (open.escape.length < 6)
return true;
const decoded = String.fromCharCode(Number.parseInt(open.escape.slice(2), 16));
open.escape = "";
this.#appendString(open, decoded);
return true;
}
const literal = open.escape;
open.escape = "";
this.#appendString(open, literal);
return false;
}
#appendString(open, text) {
open.text += text;
if (open.target !== "value")
return;
this.#place(open.slot, open.text);
if (open.path === void 0)
return;
const change = open.change;
if (change !== void 0 && this.#changes.at(-1) === change) {
if (change.kind === "set")
change.value = change.value + text;
else
change.text += text;
return;
}
open.change = this.#report({ kind: "append", path: open.path, text });
}
#endString(open) {
this.#string = void 0;
const frame = this.#stack.at(-1);
if (open.target === "key") {
if (frame === void 0)
return;
frame.key = open.text;
frame.phase = "colon";
return;
}
this.#valueEnded(frame);
}
#endScalar() {
const token = this.#scalar;
const slot = this.#scalarSlot;
this.#scalar = "";
this.#scalarSlot = void 0;
const value = scalarValue(token);
if (value !== void 0) {
this.#place(slot, value);
const path = this.#reportedPath(slot);
if (path !== void 0)
this.#report({ kind: "set", path, value });
}
this.#valueEnded(this.#stack.at(-1));
}
/** The value of the unterminated scalar at the end of the text, if it shows. */
#pendingScalar() {
const slot = this.#scalarSlot;
const token = this.#scalar;
if (slot === void 0 || token === "" || token.length > MAX_PENDING_SCALAR_LENGTH)
return void 0;
const value = pendingScalarValue(token);
return value === void 0 ? void 0 : { slot, value };
}
#openContainer(container) {
const slot = this.#valueSlot();
const path = this.#reportedPath(slot);
this.#place(slot, container);
this.#stack.push({
container,
slot,
path,
reportsInside: path !== void 0 && path.length < MAX_REPORTED_DEPTH,
size: 0,
key: void 0,
phase: Array.isArray(container) ? "value" : "key"
});
this.#pathCost += 1;
this.#dirty = true;
if (path !== void 0)
this.#report({ kind: "set", path, value: Array.isArray(container) ? [] : {} });
}
#closeContainer() {
const frame = this.#stack.pop();
if (frame === void 0)
return;
this.#pathCost -= frame.size + 1;
this.#dirty = true;
if (frame.path !== void 0 && !frame.reportsInside) {
this.#report({ kind: "set", path: frame.path, value: frame.container });
}
this.#valueEnded(this.#stack.at(-1));
}
/** A value in `frame`, or the root value when there is no frame, has ended. */
#valueEnded(frame) {
if (frame === void 0) {
if (this.#root !== void 0)
this.#done = true;
return;
}
frame.phase = "comma";
}
/** Set the value at `slot` in the open path; nothing for a value in an invalid position. */
#place(slot, value) {
if (slot === void 0)
return;
this.#dirty = true;
if (slot.kind === "root") {
this.#root = value;
return;
}
const frame = this.#stack.at(-1);
if (slot.kind === "element") {
const elements = frame.container;
if (slot.index === elements.length) {
frame.size++;
this.#pathCost++;
}
elements[slot.index] = value;
return;
}
const members = frame.container;
if (!Object.hasOwn(members, slot.key)) {
frame.size++;
this.#pathCost++;
}
setMember(members, slot.key, value);
}
/** A fresh snapshot: copies of the open containers, innermost first, each holding the copy of its open child. */
#copyOpenPath(pending) {
if (this.#stack.length === 0)
return pending?.slot.kind === "root" ? pending.value : this.#root;
let child;
let childSlot;
for (let depth = this.#stack.length - 1; depth >= 0; depth--) {
const frame = this.#stack[depth];
const copy = Array.isArray(frame.container) ? frame.container.slice() : { ...frame.container };
if (depth === this.#stack.length - 1 && pending !== void 0)
setSlot(copy, pending.slot, pending.value);
if (child !== void 0 && childSlot !== void 0)
setSlot(copy, childSlot, child);
child = copy;
childSlot = frame.slot;
}
return childSlot?.kind === "root" ? child : this.#root;
}
};
var ToolCallArgumentsStream = class {
#text = "";
#parser = new StreamingJsonParser();
#snapshot = void 0;
#arguments = {};
/** The raw argument text received so far. */
get text() {
return this.#text;
}
/** Append a piece of argument text; returns the partial arguments, a new object whenever they changed. */
append(delta) {
this.#text += delta;
this.#parser.append(delta);
return this.#partial();
}
/**
* Take the provider's complete argument text. When it continues the text so far, returns the missing piece as
* `delta`; otherwise starts over with `text`. Either way returns the partial arguments of `text`.
*/
replace(text) {
if (text.startsWith(this.#text)) {
const delta = text.slice(this.#text.length);
return { delta, arguments: delta === "" ? this.#partial() : this.append(delta) };
}
this.#text = "";
this.#parser = new StreamingJsonParser();
return { delta: void 0, arguments: this.append(text) };
}
/** The final arguments: one full parse of the complete text, which reports malformed arguments. */
finish() {
return parseToolCallArguments(this.#text);
}
#partial() {
const snapshot = this.#parser.snapshot();
if (snapshot === this.#snapshot)
return this.#arguments;
this.#snapshot = snapshot;
this.#arguments = typeof snapshot === "object" && snapshot !== null && !Array.isArray(snapshot) ? snapshot : {};
return this.#arguments;
}
};
var SIMPLE_ESCAPES = {
'"': '"',
"\\": "\\",
"/": "/",
b: "\b",
f: "\f",
n: "\n",
r: "\r",
t: " "
};
function isDelimiter(char) {
return char === " " || char === " " || char === "\n" || char === "\r" || char === "," || char === ":" || char === "{" || char === "}" || char === "[" || char === "]" || char === '"';
}
function isHexDigit(char) {
return char >= "0" && char <= "9" || char >= "a" && char <= "f" || char >= "A" && char <= "F";
}
function scalarValue(token) {
for (const [literal, value] of LITERALS)
if (token === literal)
return value;
return NUMBER.test(token) ? Number(token) : void 0;
}
function pendingScalarValue(token) {
for (const [literal, value] of LITERALS)
if (literal.startsWith(token))
return value;
if (NUMBER.test(token))
return Number(token);
const mantissa = NUMBER_WITHOUT_EXPONENT_DIGITS.exec(token);
return mantissa === null ? void 0 : Number(mantissa[1]);
}
function setSlot(container, slot, value) {
if (slot.kind === "element")
container[slot.index] = value;
else if (slot.kind === "member")
setMember(container, slot.key, value);
}
function setMember(members, key, value) {
if (key === "__proto__") {
Object.defineProperty(members, key, { value, writable: true, enumerable: true, configurable: true });
} else {
members[key] = value;
}
}
// host/js/node_modules/@earendil-works/pi-ai/dist/providers/faux.js
var DEFAULT_API = "faux";
var DEFAULT_PROVIDER = "faux";
var DEFAULT_MODEL_ID = "faux-1";
var DEFAULT_MODEL_NAME = "Faux Model";
var DEFAULT_BASE_URL = "http://localhost:0";
var DEFAULT_MIN_TOKEN_SIZE = 3;
var DEFAULT_MAX_TOKEN_SIZE = 5;
var DEFAULT_USAGE = {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0,
totalTokens: 0,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
};
function fauxText(text) {
return { type: "text", text };
}
function fauxToolCall(name, arguments_, options = {}) {
return {
type: "toolCall",
id: options.id ?? randomId("tool"),
name,
arguments: arguments_
};
}
function normalizeFauxAssistantContent(content) {
if (typeof content === "string") {
return [fauxText(content)];
}
return Array.isArray(content) ? content : [content];
}
function fauxAssistantMessage(content, options = {}) {
return {
role: "assistant",
content: normalizeFauxAssistantContent(content),
api: DEFAULT_API,
provider: DEFAULT_PROVIDER,
model: DEFAULT_MODEL_ID,
usage: DEFAULT_USAGE,
stopReason: options.stopReason ?? "stop",
...options.deferred === void 0 ? {} : { deferred: options.deferred },
...options.errorMessage === void 0 ? {} : { errorMessage: options.errorMessage },
...options.responseId === void 0 ? {} : { responseId: options.responseId },
timestamp: options.timestamp ?? Date.now()
};
}
function estimateTokens(text) {
return Math.ceil(text.length / 4);
}
function randomId(prefix) {
return `${prefix}:${Date.now()}:${Math.random().toString(36).slice(2)}`;
}
function contentToText(content) {
if (typeof content === "string") {
return content;
}
return content.map((block) => {
if (block.type === "text") {
return block.text;
}
return `[image:${block.mimeType}:${block.data.length}]`;
}).join("\n");
}
function assistantContentToText(content) {
return content.map((block) => {
if (block.type === "text") {
return block.text;
}
if (block.type === "thinking") {
return block.thinking;
}
return `${block.name}:${JSON.stringify(block.arguments)}`;
}).join("\n");
}
function toolResultToText(message) {
return [message.toolName, ...message.content.map((block) => contentToText([block]))].join("\n");
}
function messageToText(message) {
if (message.role === "system") {
return [
getSystemMessageText(message),
...message.toolsRemoved?.map((tool) => `tool-:${JSON.stringify(tool)}`) ?? [],
...message.toolsAdded?.map((tool) => `tool+:${JSON.stringify(tool)}`) ?? []
].filter((part) => part.length > 0).join("\n");
}
if (message.role === "user") {
return contentToText(message.content);
}
if (message.role === "assistant") {
return assistantContentToText(message.content);
}
return toolResultToText(message);
}
function joinedLength(messages, count = messages.length) {
let length = count > 0 ? (count - 1) * 2 : 0;
for (let index = 0; index < count; index++)
length += messages[index].length;
return length;
}
function commonPromptPrefixLength(previous, current) {
let index = 0;
while (index < previous.length && index < current.length && previous[index] === current[index])
index++;
const rest = (messages) => index === messages.length ? "" : (index > 0 ? "\n\n" : "") + messages.slice(index).join("\n\n");
return joinedLength(previous, index) + commonPrefixLength(rest(previous), rest(current));
}
function commonPrefixLength(a, b) {
const length = Math.min(a.length, b.length);
let index = 0;
while (index < length && a[index] === b[index]) {
index++;
}
return index;
}
function withUsageEstimate(message, context, options, promptCache) {
const prompt = context.messages.map((message2) => `${message2.role}:${messageToText(message2)}`);
const promptLength = joinedLength(prompt);
const promptTokens = Math.ceil(promptLength / 4);
const outputTokens = estimateTokens(assistantContentToText(message.content));
let input = promptTokens;
let cacheRead = 0;
let cacheWrite = 0;
const sessionId = options?.sessionId;
if (sessionId && options?.cacheRetention !== "none") {
const previousPrompt = promptCache.get(sessionId);
if (previousPrompt) {
const cachedChars = commonPromptPrefixLength(previousPrompt, prompt);
cacheRead = Math.ceil(cachedChars / 4);
cacheWrite = Math.max(0, promptTokens - cacheRead);
} else {
cacheWrite = promptTokens;
}
input = 0;
promptCache.set(sessionId, prompt);
}
return {
...message,
usage: {
input,
output: outputTokens,
cacheRead,
cacheWrite,
totalTokens: input + outputTokens + cacheRead + cacheWrite,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
}
};
}
function splitStringByTokenSize(text, minTokenSize, maxTokenSize) {
const chunks = [];
let index = 0;
while (index < text.length) {
const tokenSize = minTokenSize + Math.floor(Math.random() * (maxTokenSize - minTokenSize + 1));
const charSize = Math.max(1, tokenSize * 4);
chunks.push(text.slice(index, index + charSize));
index += charSize;
}
return chunks.length > 0 ? chunks : [""];
}
function cloneMessage(message, api, provider, modelId) {
const cloned = structuredClone(message);
return {
...cloned,
api,
provider,
model: modelId,
timestamp: cloned.timestamp ?? Date.now(),
usage: cloned.usage ?? DEFAULT_USAGE
};
}
function createDeferredMessage(model, handle) {
return {
role: "assistant",
content: [],
api: model.api,
provider: model.provider,
model: model.id,
usage: DEFAULT_USAGE,
stopReason: "deferred",
deferred: handle,
timestamp: Date.now()
};
}
function createErrorMessage(error, api, provider, modelId) {
return {
role: "assistant",
content: [],
api,
provider,
model: modelId,
usage: DEFAULT_USAGE,
stopReason: "error",
errorMessage: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
}
function createAbortedMessage(partial) {
return {
...partial,
stopReason: "aborted",
errorMessage: "Request was aborted",
timestamp: Date.now()
};
}
function scheduleChunk(chunk, tokensPerSecond) {
if (!tokensPerSecond || tokensPerSecond <= 0) {
return new Promise((resolve) => queueMicrotask(resolve));
}
const delayMs = estimateTokens(chunk) / tokensPerSecond * 1e3;
return new Promise((resolve) => setTimeout(resolve, delayMs));
}
async function streamWithDeltas(stream, message, minTokenSize, maxTokenSize, tokensPerSecond, signal) {
const partial = { ...message, content: [], stopReason: "pending" };
if (signal?.aborted) {
const aborted = createAbortedMessage(partial);
stream.push({ type: "error", reason: "aborted", error: aborted });
stream.end(aborted);
return;
}
stream.push({ type: "start", partial: { ...partial } });
for (let index = 0; index < message.content.length; index++) {
if (signal?.aborted) {
const aborted = createAbortedMessage(partial);
stream.push({ type: "error", reason: "aborted", error: aborted });
stream.end(aborted);
return;
}
const block = message.content[index];
if (block.type === "thinking") {
partial.content = [...partial.content, { type: "thinking", thinking: "" }];
stream.push({ type: "thinking_start", contentIndex: index, partial: { ...partial } });
for (const chunk of splitStringByTokenSize(block.thinking, minTokenSize, maxTokenSize)) {
await scheduleChunk(chunk, tokensPerSecond);
if (signal?.aborted) {
const aborted = createAbortedMessage(partial);
stream.push({ type: "error", reason: "aborted", error: aborted });
stream.end(aborted);
return;
}
partial.content[index].thinking += chunk;
stream.push({ type: "thinking_delta", contentIndex: index, delta: chunk, partial: { ...partial } });
}
stream.push({
type: "thinking_end",
contentIndex: index,
content: block.thinking,
partial: { ...partial }
});
continue;
}
if (block.type === "text") {
partial.content = [...partial.content, { type: "text", text: "" }];
stream.push({ type: "text_start", contentIndex: index, partial: { ...partial } });
for (const chunk of splitStringByTokenSize(block.text, minTokenSize, maxTokenSize)) {
await scheduleChunk(chunk, tokensPerSecond);
if (signal?.aborted) {
const aborted = createAbortedMessage(partial);
stream.push({ type: "error", reason: "aborted", error: aborted });
stream.end(aborted);
return;
}
partial.content[index].text += chunk;
stream.push({ type: "text_delta", contentIndex: index, delta: chunk, partial: { ...partial } });
}
stream.push({ type: "text_end", contentIndex: index, content: block.text, partial: { ...partial } });
continue;
}
partial.content = [...partial.content, { type: "toolCall", id: block.id, name: block.name, arguments: {} }];
stream.push({ type: "toolcall_start", contentIndex: index, partial: { ...partial } });
const toolArguments = new ToolCallArgumentsStream();
for (const chunk of splitStringByTokenSize(JSON.stringify(block.arguments), minTokenSize, maxTokenSize)) {
await scheduleChunk(chunk, tokensPerSecond);
if (signal?.aborted) {
const aborted = createAbortedMessage(partial);
stream.push({ type: "error", reason: "aborted", error: aborted });
stream.end(aborted);
return;
}
partial.content[index].arguments = toolArguments.append(chunk);
stream.push({ type: "toolcall_delta", contentIndex: index, delta: chunk, partial: { ...partial } });
}
partial.content[index].arguments = block.arguments;
stream.push({ type: "toolcall_end", contentIndex: index, toolCall: block, partial: { ...partial } });
}
if (message.stopReason === "pending") {
throw new Error("Faux response ended without a stop reason");
}
if (message.stopReason === "error" || message.stopReason === "aborted") {
stream.push({ type: "error", reason: message.stopReason, error: message });
stream.end(message);
return;
}
stream.push({ type: "done", reason: message.stopReason, message });
stream.end(message);
}
function createFauxCore(options) {
const api = options.api ?? randomId(DEFAULT_API);
const provider = options.provider ?? DEFAULT_PROVIDER;
const minTokenSize = Math.max(1, Math.min(options.tokenSize?.min ?? DEFAULT_MIN_TOKEN_SIZE, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE));
const maxTokenSize = Math.max(minTokenSize, options.tokenSize?.max ?? DEFAULT_MAX_TOKEN_SIZE);
let pendingResponses = [];
const tokensPerSecond = options.tokensPerSecond;
const state = { callCount: 0, deferredFetchCount: 0, cancelledDeferred: [] };
const promptCache = /* @__PURE__ */ new Map();
const deferredResponses = /* @__PURE__ */ new Map();
const modelDefinitions = options.models?.length ? options.models : [
{
id: DEFAULT_MODEL_ID,
name: DEFAULT_MODEL_NAME,
reasoning: false,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 128e3,
maxTokens: 16384
}
];
const models = modelDefinitions.map((definition) => ({
id: definition.id,
name: definition.name ?? definition.id,
api,
provider,
baseUrl: DEFAULT_BASE_URL,
reasoning: definition.reasoning ?? false,
input: definition.input ?? ["text", "image"],
inputLimits: definition.inputLimits,
cost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: definition.contextWindow ?? 128e3,
maxTokens: definition.maxTokens ?? 16384
}));
const resolveResponse = async (step, context, streamOptions, requestModel) => {
const resolved = typeof step === "function" ? await step(context, streamOptions, state, requestModel) : step;
return withUsageEstimate(cloneMessage(resolved, api, provider, requestModel.id), context, streamOptions, promptCache);
};
const stream = (requestModel, context, streamOptions) => {
const outer = createAssistantMessageEventStream();
const step = pendingResponses.shift();
state.callCount++;
queueMicrotask(async () => {
try {
await streamOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);
if (!step) {
let message2 = createErrorMessage(new Error("No more faux responses queued"), api, provider, requestModel.id);
message2 = withUsageEstimate(message2, context, streamOptions, promptCache);
outer.push({ type: "error", reason: "error", error: message2 });
outer.end(message2);
return;
}
if (streamOptions?.deferred) {
const handle = {
provider: requestModel.provider,
modelId: requestModel.id,
api: requestModel.api,
id: randomId("deferred"),
...options.deferred?.pollAfterMs !== void 0 ? { pollAfterMs: options.deferred.pollAfterMs } : {}
};
deferredResponses.set(handle.id, {
handle,
step,
context,
options: streamOptions,
model: requestModel,
pendingFetches: Math.max(0, Math.floor(options.deferred?.pendingFetches ?? 0)),
cancelled: false
});
await streamWithDeltas(outer, createDeferredMessage(requestModel, handle), minTokenSize, maxTokenSize, tokensPerSecond, streamOptions.signal);
return;
}
const message = await resolveResponse(step, context, streamOptions, requestModel);
await streamWithDeltas(outer, message, minTokenSize, maxTokenSize, tokensPerSecond, streamOptions?.signal);
} catch (error) {
const message = createErrorMessage(error, api, provider, requestModel.id);
outer.push({ type: "error", reason: "error", error: message });
outer.end(message);
}
});
return outer;
};
const streamSimple = (streamModel, context, streamOptions) => stream(streamModel, context, streamOptions);
const fetchDeferred = (requestModel, handle, fetchOptions) => {
const outer = createAssistantMessageEventStream();
state.deferredFetchCount++;
queueMicrotask(async () => {
try {
await fetchOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);
const entry = deferredResponses.get(handle.id);
if (!entry || entry.handle.provider !== handle.provider || entry.handle.modelId !== handle.modelId || entry.handle.api !== handle.api) {
throw new Error(`Unknown faux deferred response: ${handle.id}`);
}
if (entry.cancelled)
throw new Error(`Faux deferred response was cancelled: ${handle.id}`);
if (entry.pendingFetches > 0) {
entry.pendingFetches--;
await streamWithDeltas(outer, createDeferredMessage(requestModel, entry.handle), minTokenSize, maxTokenSize, tokensPerSecond, fetchOptions?.signal);
return;
}
if (!entry.final) {
const { deferred: _deferred, signal: _submissionSignal, onResponse: _submissionOnResponse, ...submissionOptions } = entry.options ?? {};
try {
entry.final = await resolveResponse(entry.step, entry.context, submissionOptions, entry.model);
} catch (error) {
entry.final = createErrorMessage(error, api, provider, entry.model.id);
}
}
await streamWithDeltas(outer, entry.final, minTokenSize, maxTokenSize, tokensPerSecond, fetchOptions?.signal);
} catch (error) {
const message = createErrorMessage(error, api, provider, requestModel.id);
outer.push({ type: "error", reason: "error", error: message });
outer.end(message);
}
});
return outer;
};
const cancelDeferred = async (requestModel, handle, cancelOptions) => {
state.cancelledDeferred.push(structuredClone(handle));
const entry = deferredResponses.get(handle.id);
if (entry)
entry.cancelled = true;
await cancelOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);
};
function getModel(requestedModelId) {
if (!requestedModelId) {
return models[0];
}
return models.find((candidate) => candidate.id === requestedModelId);
}
return {
api,
provider,
models,
stream,
streamSimple,
fetchDeferred,
cancelDeferred,
getModel,
state,
setResponses(responses) {
pendingResponses = [...responses];
},
appendResponses(responses) {
pendingResponses.push(...responses);
},
getPendingResponseCount() {
return pendingResponses.length;
}
};
}
function fauxProvider(options = {}) {
const core = createFauxCore(options);
const provider = createProvider({
id: core.provider,
auth: { apiKey: { name: "Faux", resolve: async () => ({ auth: {} }) } },
models: core.models,
api: {
stream: core.stream,
streamSimple: core.streamSimple,
fetchDeferred: core.fetchDeferred,
cancelDeferred: core.cancelDeferred
}
});
return {
provider,
api: core.api,
models: core.models,
getModel: core.getModel,
state: core.state,
setResponses: core.setResponses,
appendResponses: core.appendResponses,
getPendingResponseCount: core.getPendingResponseCount
};
}
// host/js/p4-test.ts
var main = `fn greeting(name: &str) -> String { format!("hello {name}") }
fn main() {
let Some(name) = std::env::args().nth(1) else { std::process::exit(7) };
println!("{}", serde_json::json!({"greeting": greeting(&name)}));
}
#[test]
fn greeting_test() { assert_eq!(greeting("world"), "hello world", "P4_expected_failure"); }
`;
var write = (path, text) => `cat > ${path} <<'P4_FILE'
${text}
P4_FILE
`;
var phases = [
`set -e
mkdir -p /src/demo-cli/src /src/demo-node /tmp
cd /src/demo-cli
if test -d target; then cargo clean; fi
${write("Cargo.toml", '[package]\nname="demo-cli"\nversion="0.1.0"\nedition="2024"\n[workspace]\n')}
${write("src/main.rs", main.replace('"hello world", "P4_expected_failure"', '"hello wrong", "P4_expected_failure"'))}
cargo add serde_json
cargo fmt
set +e
cargo test -- --nocapture > /tmp/p4-fail.stdout 2> /tmp/p4-fail.stderr
code=$?
set -e
cat /tmp/p4-fail.stdout /tmp/p4-fail.stderr
test "$code" = 101
case "$(cat /tmp/p4-fail.stderr)" in *P4_expected_failure*) ;; *) exit 1 ;; esac
printf 'P4_PHASE_0_OK
'`,
`set -e
cd /src/demo-cli
${write("src/main.rs", main)}
cargo fmt
cargo test -- --nocapture
cargo build --release
test -f target/wasm32-wasip2/release/demo-cli.wasm
sh -c '/src/demo-cli/target/wasm32-wasip2/release/demo-cli.wasm world' > /tmp/p4-cli.json
case "$(cat /tmp/p4-cli.json)" in *'"greeting":"hello world"'*) ;; *) exit 1 ;; esac
set +e
sh -c '/src/demo-cli/target/wasm32-wasip2/release/demo-cli.wasm'
code=$?
set -e
test "$code" = 7
printf 'P4_PHASE_1_OK
'`,
`set -e
${write("/src/demo-node/package.json", '{"scripts":{"test":"node test.cjs"}}')}
${write("/src/demo-node/test.cjs", 'const fs = require("node:fs");\nrequire("node:assert/strict").equal(2 + 2, 4);\nfs.writeFileSync("result.txt", "P4 npm test passed\\n");')}
id=$(box create --ttl 600)
printf '%s
' "$id" > /tmp/p4-box-id
trap 'box rm "$id"' EXIT
box put "$id" /src/demo-node /work
box exec "$id" --timeout 120 -- sh -c 'cd /work && npm test'
box get "$id" /work/result.txt /src/demo-node/result.txt
test "$(cat /src/demo-node/result.txt)" = 'P4 npm test passed'
box rm "$id"
trap - EXIT
printf 'P4_PHASE_2_OK
'`,
`set -e
undo list --conversation 1 > /tmp/p4-undo.json
box ls > /tmp/p4-boxes
printf 'P4_PHASE_3_OK
'`
];
function p4(host) {
const faux = fauxProvider({ provider: "openai", models: [{ id: "gpt-6.1-sol" }], tokensPerSecond: 1e6 });
const respond = (transcript) => {
faux.appendResponses([respond]);
const messages = transcript.messages;
const input = messages.findLast((message) => message.role === "user");
const text = (message) => typeof message.content === "string" ? message.content : (message.content ?? []).filter((part) => part.type === "text").map((part) => part.text).join("\n");
const round = /P4 start (\d+)/.exec(text(input))?.[1];
if (!round) throw new Error(`Unexpected P4 input: ${JSON.stringify(input)}`);
const last = messages.findLast((message) => message.role !== "system");
let phase = 0;
if (last.role !== "user") {
const prior = /p4-\d+-(\d+)/.exec(last.toolCallId)?.[1];
if (last.isError || prior === void 0 || !text(last).includes(`P4_PHASE_${prior}_OK`)) throw new Error(`P4 bash failed: ${JSON.stringify(last)}`);
phase = Number(prior) + 1;
}
if (phase === phases.length) return fauxAssistantMessage(`P4_COMPLETE_${round}`);
return fauxAssistantMessage([fauxToolCall("bash", { command: phases[phase], timeout: 300 }, { id: `p4-${round}-${phase}` })], { stopReason: "toolUse" });
};
faux.setResponses([respond]);
host.models().setProvider(faux.provider);
return { name: "p4" };
}
export {
p4 as default
};