UNPKG

@hashbrownai/core

Version:

Runtime helpers for Hashbrown AI

1,464 lines (1,438 loc) 111 kB
/* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-explicit-any */ /** * Synchronous “trampoline” scheduler. * * All work executes in the same macrotask, but stack-safe: * tasks scheduled from inside other tasks are queued * and processed after the current one finishes. */ class TrampolineScheduler { constructor() { this.nextId = 0; this.queue = new Map(); this.active = false; } flush() { if (this.active) return; this.active = true; while (this.queue.size) { const entry = this.queue.entries().next().value; if (!entry) break; const [id, task] = entry; this.queue.delete(id); try { task(); } catch (err) { // Surface errors asynchronously so one failure // doesn’t prevent later tasks from running setTimeout(() => { throw err; }, 0); } } this.active = false; } scheduleTask(fn) { const id = ++this.nextId; this.queue.set(id, fn); this.flush(); return id; } cancelTask(id) { this.queue.delete(id); } } /** * Creates a payload projector function that returns its argument. * * @template T - The payload type. * @returns {(payload: T) => T} Function that returns the provided payload. */ function props() { return payload => payload; } /** * Creates an action creator with no payload. * * @returns {() => void} Function that produces an action with only a type. */ function emptyProps() { return () => {}; } /** * Generates a group of action creator functions with a common type prefix. * * @template GroupName - The modifier for action types (e.g., feature name). * @template T - An object whose values are payload creator functions. * @param {GroupName} name - The group prefix name. * @param {T} group - An object mapping action names to payload functions. * @returns {ActionCreators<GroupName, T>} A set of action creators. */ function createActionGroup(name, group) { return Object.fromEntries(Object.entries(group).map(([key, value]) => [key, Object.assign(typeof value === 'function' ? payload => ({ type: `[${name}] ${key}`, payload }) : () => ({ type: `[${name}] ${key}` }), { type: `[${name}] ${key}` })])); } /** * ================================ * === Reducers === * ================================ */ /** * Creates a reducer function that responds to specified action types. * * @template State - The type of the slice of state. * @template Actions - An array of ActionCreator types to handle. * @param {...Actions, Handler} params - One or more action creators followed by a reducer handler. * @returns {(state: State, action: AnyAction) => State} A reducer function. */ function on(...params) { const actionFns = params.slice(0, -1); const reducerFn = params[params.length - 1]; return (state, action) => { const shouldReduceState = actionFns.some(param => param.type === action.type); if (!shouldReduceState) { return state; } return reducerFn(state, action); }; } /** * Combines multiple reducer functions into a single root reducer. * * @template State - The combined state shape. * @param {State} initialState - The initial state when undefined is passed. * @param {...Function} reducers - One or more reducer functions. * @returns {(state: State|undefined, action: { type: string }) => State} The root reducer. */ function createReducer(initialState, ...reducers) { return (state, action) => { return reducers.reduce((acc, reducer) => reducer(acc, action), state === undefined ? initialState : state); }; } /** * Creates an effect function that can subscribe to store actions and return a cleanup function. * * @param {EffectFn} effectFn - Function that receives the store and returns a teardown callback. * @returns {EffectFn} The provided effect function. */ function createEffect(effectFn) { return effectFn; } function select(...params) { let inputs = params.slice(0, -1); let selectFn = params[params.length - 1]; let config; if (typeof selectFn !== 'function') { config = selectFn; selectFn = params[params.length - 2]; inputs = params.slice(0, -2); } let lastInputValues = []; let lastOutput; return state => { const inputValues = inputs.map(input => input(state)); if (inputValues.some((value, index) => { const isMismatched = value !== lastInputValues[index]; if (isMismatched && config && config.debugName) { console.log('Select Argument Mismatch:', config.debugName, `input[${index}]`, 'last:', lastInputValues[index], 'now:', value); } return isMismatched; })) { lastInputValues = inputValues; lastOutput = selectFn(...inputValues); } return lastOutput; }; } /** * ================================ * === Store === * ================================ */ /** * Creates a store with reducers and effects. * @template Reducers - An object mapping keys to reducer functions. * @template State - The resulting state shape inferred from Reducers. * @param {{ reducers: Reducers; effects: EffectFn[] }} config - Configuration object. * @returns {Store<State>} The initialized store instance. */ function createStore(config) { const scheduler = new TrampolineScheduler(); const devtools = config.debugName ? connectToChromeExtension({ name: config.debugName }) : undefined; const reducerFnEntries = Object.entries(config.reducers); const reducerFn = function (state, action) { return reducerFnEntries.reduce((acc, [key, value]) => { return Object.assign(Object.assign({}, acc), { [key]: value(acc === null || acc === void 0 ? void 0 : acc[key], action) }); }, state); }; const whenCallbackFnMap = new Map(); const selectCallbackFns = []; let state = reducerFn(undefined, { type: '@@init' }); function dispatch(action) { scheduler.scheduleTask(() => { var _a, _b, _c; state = reducerFn(state, action); const whenCallbackFns = (_a = whenCallbackFnMap.get(action.type)) !== null && _a !== void 0 ? _a : []; whenCallbackFns.forEach(callback => callback(action)); selectCallbackFns.forEach(callback => callback()); devtools === null || devtools === void 0 ? void 0 : devtools.send(action, (_c = (_b = config.projectStateForDevtools) === null || _b === void 0 ? void 0 : _b.call(config, state)) !== null && _c !== void 0 ? _c : state); }); } function when(...params) { const actionFns = params.slice(0, -1); const callbackFn = params[params.length - 1]; actionFns.forEach(actionFn => { var _a; if (!whenCallbackFnMap.has(actionFn.type)) { whenCallbackFnMap.set(actionFn.type, []); } (_a = whenCallbackFnMap.get(actionFn.type)) === null || _a === void 0 ? void 0 : _a.push(callbackFn); }); return () => { actionFns.forEach(actionFn => { var _a; const callbacks = (_a = whenCallbackFnMap.get(actionFn.type)) !== null && _a !== void 0 ? _a : []; whenCallbackFnMap.set(actionFn.type, callbacks.filter(cb => cb !== callbackFn)); }); }; } function whenOnce(...params) { const actionFns = params.slice(0, -1); const callbackFn = params[params.length - 1]; const cleanupFn = when(...actionFns, action => { callbackFn(action); cleanupFn(); }); return cleanupFn; } function read(selector) { return selector(state); } function select(selector, onChange) { let currentValue = read(selector); onChange(currentValue); const callback = () => { const newValue = read(selector); if (newValue !== currentValue) { currentValue = newValue; onChange(newValue); } }; selectCallbackFns.push(callback); return () => { selectCallbackFns.splice(selectCallbackFns.indexOf(callback), 1); }; } function createSignal(selector) { return Object.assign(() => read(selector), { subscribe: onChange => select(selector, onChange) }); } function runEffects() { var _a, _b; devtools === null || devtools === void 0 ? void 0 : devtools.init((_b = (_a = config.projectStateForDevtools) === null || _a === void 0 ? void 0 : _a.call(config, state)) !== null && _b !== void 0 ? _b : state); const cleanupFns = config.effects.map(effect => effect(store)); return () => { cleanupFns.forEach(fn => fn()); devtools === null || devtools === void 0 ? void 0 : devtools.unsubscribe(); }; } const store = { dispatch, read, select, when: when, whenOnce: whenOnce, createSignal, runEffects }; return store; } /** * Creates an EntityAdapter for performing immutable updates on entity collections. * @template Entity - The entity type. * @param {{ selectId: (entity: Entity) => string }} config - Configuration with a selectId function. * @returns {EntityAdapter<Entity>} Adapter with CRUD methods for entity state. */ function createEntityAdapter(config) { const { selectId } = config; function updateOne(state, changes) { return Object.assign(Object.assign({}, state), { entities: Object.assign(Object.assign({}, state.entities), { [changes.id]: Object.assign(Object.assign({}, state.entities[changes.id]), changes.updates) }) }); } function updateMany(state, changes) { return changes.reduce((acc, change) => updateOne(acc, change), state); } function addOne(state, entity) { return Object.assign(Object.assign({}, state), { ids: [...state.ids, selectId(entity)], entities: Object.assign(Object.assign({}, state.entities), { [selectId(entity)]: entity }) }); } function addMany(state, entities) { return entities.reduce((acc, entity) => addOne(acc, entity), state); } function removeOne(state, idToRemove) { const updatedEntities = Object.assign({}, state.entities); delete updatedEntities[idToRemove]; return Object.assign(Object.assign({}, state), { ids: state.ids.filter(id => id !== idToRemove), entities: updatedEntities }); } function removeMany(state, ids) { return Object.assign(Object.assign({}, state), { ids: state.ids.filter(id => !ids.includes(id)), entities: Object.fromEntries(Object.entries(state.entities).filter(([id]) => !ids.includes(id))) }); } return { updateOne, updateMany, addOne, addMany, removeOne, removeMany }; } function connectToChromeExtension(options) { if (typeof window === 'undefined') { return; } const extension = window.__REDUX_DEVTOOLS_EXTENSION__; if (!extension) { return; } return extension.connect({ name: options.name }); } var devActions = createActionGroup('dev', { init: props(), setMessages: props(), sendMessage: props(), resendMessages: props, updateOptions: props(), stopMessageGeneration: props() }); var apiActions = createActionGroup('api', { generateMessageStart: emptyProps(), generateMessageChunk: props(), generateMessageSuccess: props(), generateMessageError: props(), generateMessageExhaustedRetries: props() }); var internalActions = createActionGroup('internal', { sizzle: emptyProps(), runToolCallsSuccess: props(), runToolCallsError: props(), skippedToolCalls: emptyProps() }); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __await(v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } function __asyncGenerator(thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } } function __asyncValues(o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; /** * Skillet is an LLM-optimized streaming JSON Parser - perfectly suited for streaming hot and fresh JSON. * * Portions of this code are derived from Zod (MIT License) (https://github.com/colinhacks/zod). * See the LICENSE file in the project root for full license text. * * @license MIT * @author LiveLoveApp, LLC * @see https://github.com/liveloveapp/hashbrown * @see https://github.com/colinhacks/zod */ const internal = '~schema'; const PRIMITIVE_WRAPPER_FIELD_NAME = '__wrappedPrimitive'; const HashbrownTypeCtor = (name, initializer, toJsonSchemaImpl, parseJsonSchemaImpl, toTypeScriptImpl) => { class Class { constructor(definition) { Class.init(this, definition); this.toJsonSchemaImpl = toJsonSchemaImpl; this.parseJsonSchemaImpl = parseJsonSchemaImpl; this.toTypeScriptImpl = toTypeScriptImpl; } static init(instance, definition) { var _a; (_a = instance[internal]) !== null && _a !== void 0 ? _a : instance[internal] = { definition: { description: '', streaming: false } }; initializer(instance, definition); instance[internal].definition = definition; } toJsonSchema() { return this.toJsonSchemaImpl(this); } parseJsonSchema(object, path = []) { return this.parseJsonSchemaImpl(this, object, path); } validateJsonSchema(object) { this.parseJsonSchema(object, []); } toTypeScript(pathSeen = new Set()) { return this.toTypeScriptImpl(this, pathSeen); } } Object.defineProperty(Class, 'name', { value: name }); return Class; }; const HashbrownType = HashbrownTypeCtor('HashbrownType', (inst, def) => { inst !== null && inst !== void 0 ? inst : inst = {}; inst[internal].definition = def; }, () => { return; }, () => { return; }, () => { return ''; }); const StringType = HashbrownTypeCtor('String', (inst, def) => { HashbrownType.init(inst, def); }, schema => { return { type: 'string', description: schema[internal].definition.description }; }, (schema, object, path) => { // Is this a wrapped primitive? if (object != null && typeof object === 'object' && Object.keys(object).includes(PRIMITIVE_WRAPPER_FIELD_NAME)) { object = object[PRIMITIVE_WRAPPER_FIELD_NAME]; } if (typeof object !== 'string') throw new Error(`Expected a string at: ${path.join('.')}, got ${object}`); return object; }, schema => { return `/* ${schema[internal].definition.description} */ string`; }); function isStringType(type) { return type[internal].definition.type === 'string'; } function string$1(description) { return new StringType({ type: 'string', description, streaming: false }); } const LiteralType = HashbrownTypeCtor('Literal', (inst, def) => { HashbrownType.init(inst, def); }, schema => { const isString = typeof schema[internal].definition.value === 'string'; const isNumber = typeof schema[internal].definition.value === 'number'; typeof schema[internal].definition.value === 'boolean'; return { type: isString ? 'string' : isNumber ? 'number' : 'boolean', const: schema[internal].definition.value, description: schema[internal].definition.description }; }, (schema, object, path) => { // Is this a wrapped primitive? if (object != null && typeof object === 'object' && Object.keys(object).includes(PRIMITIVE_WRAPPER_FIELD_NAME)) { object = object[PRIMITIVE_WRAPPER_FIELD_NAME]; } const isString = typeof object === 'string'; const isNumber = typeof object === 'number'; const isBoolean = typeof object === 'boolean'; if (!isString && !isNumber && !isBoolean) throw new Error(`Expected a string, number, or boolean at: ${path.join('.')}, got ${object}, received ${schema[internal].definition.value}`); return object; }, schema => { return JSON.stringify(schema[internal].definition.value); }); function isLiteralType(type) { return type[internal].definition.type === 'literal'; } function literal(value) { return new LiteralType({ type: 'literal', description: `${value}`, value, streaming: false }); } const NumberType = HashbrownTypeCtor('Number', (inst, def) => { HashbrownType.init(inst, def); }, schema => { return { type: 'number', description: schema[internal].definition.description }; }, (schema, object, path) => { // Is this a wrapped primitive? if (object != null && typeof object === 'object' && Object.keys(object).includes(PRIMITIVE_WRAPPER_FIELD_NAME)) { object = object[PRIMITIVE_WRAPPER_FIELD_NAME]; } if (typeof object !== 'number') throw new Error(`Expected a number at: ${path.join('.')}`); return object; }, schema => { return `/* ${schema[internal].definition.description} */ number`; }); function isNumberType(type) { return type[internal].definition.type === 'number'; } function number(description) { return new NumberType({ type: 'number', description, streaming: false }); } const BooleanType = HashbrownTypeCtor('Boolean', (inst, def) => { HashbrownType.init(inst, def); }, schema => { return { type: 'boolean', description: schema[internal].definition.description }; }, (schema, object, path) => { // Is this a wrapped primitive? if (object != null && typeof object === 'object' && Object.keys(object).includes(PRIMITIVE_WRAPPER_FIELD_NAME)) { object = object[PRIMITIVE_WRAPPER_FIELD_NAME]; } if (typeof object !== 'boolean') throw new Error(`Expected a boolean at: ${path.join('.')}`); return object; }, schema => { return `/* ${schema[internal].definition.description} */ boolean`; }); function isBooleanType(type) { return type[internal].definition.type === 'boolean'; } function boolean(description) { return new BooleanType({ type: 'boolean', description, streaming: false }); } const IntegerType = HashbrownTypeCtor('Integer', (inst, def) => { HashbrownType.init(inst, def); }, schema => { return { type: 'integer', description: schema[internal].definition.description }; }, (schema, object, path) => { // Is this a wrapped primitive? if (object != null && typeof object === 'object' && Object.keys(object).includes(PRIMITIVE_WRAPPER_FIELD_NAME)) { object = object[PRIMITIVE_WRAPPER_FIELD_NAME]; } if (typeof object !== 'number') throw new Error(`Expected a number at: ${path.join('.')}`); if (!Number.isInteger(object)) throw new Error(`Expected an integer at: ${path.join('.')}`); return object; }, schema => { return `/* ${schema[internal].definition.description} */ integer`; }); function isIntegerType(type) { return type[internal].definition.type === 'integer'; } function integer(description) { return new IntegerType({ type: 'integer', description, streaming: false }); } const ObjectType = HashbrownTypeCtor('Object', (inst, def) => { HashbrownType.init(inst, def); }, schema => { return { type: 'object', // Properties is populated externally because we need to find loops properties: {}, required: Object.keys(schema[internal].definition.shape), additionalProperties: false, description: schema[internal].definition.description }; }, (schema, object, path) => { if (typeof object !== 'object' || object === null) throw new Error(`Expected an object at: ${path.join('.')}`); const { shape } = schema[internal].definition; Object.entries(shape).forEach(([key, child]) => { // AnyOf unwrapping can change the desired form of the result object, so // update the object as we parse object[key] = child.parseJsonSchema(object[key], [...path, key]); }); return object; }, (schema, pathSeen) => { if (pathSeen.has(schema)) { const desc = schema[internal].definition.description || '<anonymous>'; throw new Error(`Cycle detected in schema at "${desc}"`); } pathSeen.add(schema); const depth = pathSeen.size - 1; const entries = Object.entries(schema[internal].definition.shape); const lines = entries.map(([key, child]) => { // clone pathSeen for each branch return `${' '.repeat(depth + 2)}${key}: ${child.toTypeScript(new Set(pathSeen))};`; }); return `/* ${schema[internal].definition.description} */ { ${lines.join('\n')} ${' '.repeat(depth)}}`; }); function isObjectType(type) { return type[internal].definition.type === 'object'; } function object$1(description, shape) { return new ObjectType({ type: 'object', description, streaming: false, shape }); } const ArrayType = HashbrownTypeCtor('Array', (inst, def) => { HashbrownType.init(inst, def); }, schema => { return { type: 'array', // items is populated externally since we find loops and duplicated sections // through the whole schema items: [], description: schema[internal].definition.description }; }, (schema, object, path) => { // Is this a wrapped primitive? if (object != null && typeof object === 'object' && Object.keys(object).includes(PRIMITIVE_WRAPPER_FIELD_NAME)) { object = object[PRIMITIVE_WRAPPER_FIELD_NAME]; } if (!Array.isArray(object)) throw new Error(`Expected an array at: ${path.join('.')}`); // AnyOf unwrapping can change the desired form of the result object, so // update the object as we parse object.forEach(item => { item = schema[internal].definition.element.parseJsonSchema(item, path); }); return object; }, (schema, pathSeen) => { if (pathSeen.has(schema)) { const desc = schema[internal].definition.description || '<anonymous>'; throw new Error(`Cycle detected in schema at "${desc}"`); } pathSeen.add(schema); return `/* ${schema[internal].definition.description} */ Array<${schema[internal].definition.element.toTypeScript(new Set(pathSeen))}>`; }); function isArrayType(type) { return type[internal].definition.type === 'array'; } function array$1(description, item) { return new ArrayType({ type: 'array', description, streaming: false, element: item }); } const AnyOfType = HashbrownTypeCtor('AnyOfType', (inst, def) => { HashbrownType.init(inst, def); }, schema => { return { anyOf: [] }; }, (schema, object, path) => { const options = schema[internal].definition.options; let parsedObject = undefined; for (let i = 0; i < options.length; i++) { try { if (needsDiscriminatorWrapperInAnyOf(options[i])) { if (typeof object !== 'object' || object === null) { throw new Error(`Expected an object at: ${path.join('.')}`); } const anyOfKeys = Object.keys(object); if (anyOfKeys.length !== 1) { throw new Error(`Malformed anyOf wrapper at ${path.join('.')}`); } const anyOfIndex = anyOfKeys[0]; if (anyOfIndex !== i.toString()) { throw new Error(`Unexpected discriminator value ${anyOfIndex} for option ${i}`); } parsedObject = options[i].parseJsonSchema(object[anyOfIndex]); } else { parsedObject = options[i].parseJsonSchema(object); } break; } catch (e) { // console.log(e); // Parsing failed, but that is not unexpected due to the looping. // Just try the next option. continue; } } if (parsedObject == null) { throw new Error(`All options in anyOf failed parsing at: ${path.join('.')}`); } return parsedObject; }, (schema, pathSeen) => { if (pathSeen.has(schema)) { const desc = schema[internal].definition.description || '<anonymous>'; throw new Error(`Cycle detected in schema at "${desc}"`); } pathSeen.add(schema); return `/* ${schema[internal].definition.description} */ (${schema[internal].definition.options.map(opt => opt.toTypeScript(new Set(pathSeen))).join(' | ')})`; }); function isAnyOfType(type) { return type[internal].definition.type === 'any-of'; } function anyOf(options) { return new AnyOfType({ type: 'any-of', description: 'any-of', options, streaming: false }); } const EnumType = HashbrownTypeCtor('Enum', (inst, def) => { HashbrownType.init(inst, def); }, schema => { return { type: 'string', enum: schema[internal].definition.entries, description: schema[internal].definition.description }; }, (schema, object, path) => { // Is this a wrapped primitive? if (object != null && typeof object === 'object' && Object.keys(object).includes(PRIMITIVE_WRAPPER_FIELD_NAME)) { object = object[PRIMITIVE_WRAPPER_FIELD_NAME]; } if (typeof object !== 'string') throw new Error(`Expected a string at: ${path.join('.')}`); if (!schema[internal].definition.entries.includes(object)) throw new Error(`Expected an enum value at: ${path.join('.')}`); return object; }, schema => { return schema[internal].definition.entries.map(e => `"${e}"`).join(' | '); }); function isEnumType(type) { return type[internal].definition.type === 'enum'; } function enumeration(description, entries) { return new EnumType({ type: 'enum', description, entries, streaming: false }); } const NullType = HashbrownTypeCtor('Null', (inst, def) => { HashbrownType.init(inst, def); }, schema => { return { type: 'null', const: schema[internal].definition.value, description: schema[internal].definition.description }; }, (schema, object, path) => { // Is this a wrapped primitive? if (object != null && typeof object === 'object' && Object.keys(object).includes(PRIMITIVE_WRAPPER_FIELD_NAME)) { object = object[PRIMITIVE_WRAPPER_FIELD_NAME]; } if (object !== null) throw new Error(`Expected a null at: ${path.join('.')}`); return object; }, schema => { return `/* ${schema[internal].definition.description} */ null`; }); function isNullType(type) { return type[internal].definition.type === 'null'; } function nullish() { return new NullType({ type: 'null', description: '', streaming: false }); } /** * -------------------------------------- * -------------------------------------- * Streaming Helpers * -------------------------------------- * -------------------------------------- */ function needsDiscriminatorWrapperInAnyOf(schema) { if (isAnyOfType(schema) || isArrayType(schema) || isObjectType(schema) || isStringType(schema) && isStreaming(schema)) { return true; } return false; } function isStreaming(schema) { return schema[internal].definition.streaming; } function getDescription(schema) { return schema[internal].definition.description; } /* eslint-disable @typescript-eslint/no-explicit-any */ function string(description) { return new StringType({ type: 'string', description, streaming: true }); } function object(description, shape) { return new ObjectType({ type: 'object', description, streaming: true, shape }); } function array(description, item) { return new ArrayType({ type: 'array', description, streaming: true, element: item }); } var streaming = /*#__PURE__*/Object.freeze({ __proto__: null, array: array, object: object, string: string }); /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-explicit-any */ /** * Convert an arbitrary description into a camelCase identifier. * * - Strips out any non-alphanumeric characters * - Splits on whitespace * - Lowercases all words, then uppercases the first letter of each subsequent word * - Prefixes with `_` if the result would start with a digit */ function descriptionToCamelCase(description) { const cleaned = description.replace(/[^a-zA-Z0-9]+/g, ' ').trim(); const words = cleaned.split(/\s+/).map(w => w.toLowerCase()); if (words.length === 0) return ''; const [first, ...rest] = words; const core = first + rest.map(w => w[0].toUpperCase() + w.slice(1)).join(''); return /^\d/.test(core) ? `_${core}` : core; } /** * Walks the HashbrownType graph, finds any sub-schemas seen more than once * (excluding the root), assigns each a unique name, and emits a draft-07 JSON Schema * with a $defs section. Cycles always become $refs. */ function toJsonSchema(schema) { const rootNode = schema; // 1) Collect repeated nodes const seen = new Set(); const repeats = new Set(); (function visit(n, path) { if (seen.has(n)) { repeats.add(n); return; } seen.add(n); if (isObjectType(n)) { Object.values(n[internal].definition.shape).forEach(child => visit(child, [...path, n])); } else if (isArrayType(n)) { visit(n[internal].definition.element, [...path, n]); } else if (isAnyOfType(n)) { n[internal].definition.options.forEach(opt => visit(opt, [...path, n])); } })(rootNode, []); // never put the root itself into $defs repeats.delete(rootNode); // 2) Assign each repeated node a unique camelCase name const defNameMap = new Map(); const usedNames = new Set(); let anon = 1; for (const node of repeats) { const desc = node[internal].definition.description || `def${anon++}`; let name = descriptionToCamelCase(desc) || `def${anon++}`; if (usedNames.has(name)) { let i = 1; while (usedNames.has(`${name}${i}`)) i++; name = `${name}${i}`; } usedNames.add(name); defNameMap.set(node, name); } /** * Recursive printer. * * @param n current node * @param isRoot true only for the very top-level schema * @param inDef if non-null, we're printing $defs[inDef] — any other def becomes $ref * @param pathSeen tracks the chain of inlined nodes to catch cycles */ function printNode(n, isRoot = false, inDef = null, pathSeen = new Set()) { // a) cycle back to the root if (!isRoot && n === rootNode) { return { $ref: '#' }; } // b) any other shared def becomes a $ref if (defNameMap.has(n) && n !== inDef) { const nm = defNameMap.get(n); return { $ref: `#/$defs/${nm}` }; } // c) catch self-cycles or mutual cycles in inline portions if (pathSeen.has(n)) { // if it’s named, ref it; otherwise point at root if (defNameMap.has(n)) { const nm = defNameMap.get(n); return { $ref: `#/$defs/${nm}` }; } else { return { $ref: '#' }; } } // d) inline this node pathSeen.add(n); let result; if (isObjectType(n)) { // Sort props so that streaming ones are at the end const shapeWithStreamingAtEnd = Object.entries(n[internal].definition.shape).sort((a, b) => { if (!isStreaming(a[1]) && isStreaming(b[1])) { return -1; } if (isStreaming(a[1]) && !isStreaming(b[1])) { return 1; } return 0; }); const props = {}; for (const [k, child] of shapeWithStreamingAtEnd) { props[k] = printNode(child, false, inDef, pathSeen); } result = n.toJsonSchema(); result.properties = props; } else if (isArrayType(n)) { result = n.toJsonSchema(); result.items = printNode(n[internal].definition.element, false, inDef, pathSeen); if (isRoot) { result = { type: 'object', additionalProperties: false, required: [PRIMITIVE_WRAPPER_FIELD_NAME], properties: { [PRIMITIVE_WRAPPER_FIELD_NAME]: result } }; } } else if (isAnyOfType(n)) { result = n.toJsonSchema(); result.anyOf = n[internal].definition.options.map((opt, index) => { if (needsDiscriminatorWrapperInAnyOf(opt)) { const indexAsStr = `${index}`; return { type: 'object', additionalProperties: false, required: [indexAsStr], properties: { [indexAsStr]: printNode(opt, false, inDef, pathSeen) } }; } else { return printNode(opt, false, inDef, pathSeen); } }); } else { result = n.toJsonSchema(); if (isRoot) { result = { type: 'object', additionalProperties: false, required: [PRIMITIVE_WRAPPER_FIELD_NAME], properties: { [PRIMITIVE_WRAPPER_FIELD_NAME]: result } }; } } pathSeen.delete(n); return result; } // 3) Build the $defs section const defs = {}; for (const [node, name] of defNameMap.entries()) { // isRoot=false, inDef=node, fresh pathSeen defs[name] = printNode(node, false, node, new Set()); } // 4) Print the root schema const rootPrinted = printNode(rootNode, true, null, new Set()); // 5) Assemble and return return Object.assign(Object.assign({ $schema: 'http://json-schema.org/draft-07/schema#' }, rootPrinted), Object.keys(defs).length > 0 ? { $defs: defs } : {}); } var public_api$1 = /*#__PURE__*/Object.freeze({ __proto__: null, AnyOfType: AnyOfType, ArrayType: ArrayType, BooleanType: BooleanType, ConstStringType: LiteralType, EnumType: EnumType, HashbrownType: HashbrownType, IntegerType: IntegerType, NullType: NullType, NumberType: NumberType, ObjectType: ObjectType, StringType: StringType, anyOf: anyOf, array: array$1, boolean: boolean, enumeration: enumeration, getDescription: getDescription, integer: integer, isAnyOfType: isAnyOfType, isArrayType: isArrayType, isBooleanType: isBooleanType, isEnumType: isEnumType, isIntegerType: isIntegerType, isLiteralType: isLiteralType, isNullType: isNullType, isNumberType: isNumberType, isObjectType: isObjectType, isStringType: isStringType, literal: literal, nullish: nullish, number: number, object: object$1, streaming: streaming, string: string$1, toJsonSchema: toJsonSchema }); function sleep(timeout, abortSignal) { return __awaiter(this, void 0, void 0, function* () { yield new Promise(resolve => { const timeoutId = setTimeout(resolve, timeout); if (abortSignal) { abortSignal.addEventListener('abort', () => { clearTimeout(timeoutId); }); } }); }); } function switchAsync(fn, outerSignal) { let abortController; if (outerSignal) { outerSignal.addEventListener('abort', () => { if (abortController) { abortController.abort('cancelled'); } }); } return () => { if (abortController) { abortController.abort('cancelled'); } const controller = new AbortController(); abortController = controller; return fn(controller.signal).finally(() => { if (abortController === controller) { abortController = undefined; } }); }; } /** * Decode a ReadableStream<Uint8Array> of length-prefixed JSON frames into a stream of T. * * Frame format: [4-byte BE length][UTF-8 JSON payload] * * @param stream ReadableStream producing Uint8Array chunks * @param options decoding options * @yields parsed JSON objects of type T */ function decodeFrames(stream, options) { return __asyncGenerator(this, arguments, function* decodeFrames_1() { const { signal } = options; const reader = stream.getReader(); const textDecoder = new TextDecoder(); let buffer = new Uint8Array(0); signal.addEventListener('abort', () => { reader.cancel().catch(() => { // ignore }); }, { once: true }); if (signal.aborted) { yield __await(reader.cancel()); return yield __await(void 0); } try { while (true) { if (signal.aborted) { throw new Error('Decoding aborted'); } const { value: chunk, done } = yield __await(reader.read()); if (done) break; const newBuffer = new Uint8Array(buffer.length + chunk.length); newBuffer.set(buffer); newBuffer.set(chunk, buffer.length); buffer = newBuffer; let offset = 0; const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); while (buffer.length - offset >= 4) { const length = view.getUint32(offset, /* Big Endian */false); if (buffer.length - offset < 4 + length) { break; } const start = offset + 4; const end = start + length; try { const payloadBytes = buffer.subarray(start, end); const json = textDecoder.decode(payloadBytes); const frame = JSON.parse(json); yield yield __await(frame); if (frame.type === 'finish') { return yield __await(void 0); } } catch (err) { throw new Error(`Invalid JSON payload: ${err.message}`); } offset = end; } if (offset > 0) { buffer = buffer.subarray(offset); } } if (buffer.length > 0) { throw new Error(`Stream ended with ${buffer.length} leftover bytes`); } } finally { reader.releaseLock(); } }); } var api_models = /*#__PURE__*/Object.freeze({ __proto__: null }); var internal_models = /*#__PURE__*/Object.freeze({ __proto__: null }); const TRACE_LEVEL = 0; const DEBUG_LEVEL = 1; const INFO_LEVEL = 2; const WARN_LEVEL = 3; const ERROR_LEVEL = 4; const NONE_LEVEL = 5; class Logger { constructor(logPathsEnabled) { var _a; this.logPathsEnabled = {}; this.logPathsEnabled = logPathsEnabled; this.allLevel = (_a = logPathsEnabled['all']) !== null && _a !== void 0 ? _a : NONE_LEVEL; } for(loggerName) { return { trace: args => { if (this.allLevel <= TRACE_LEVEL || this.logPathsEnabled[loggerName] && this.logPathsEnabled[loggerName] <= TRACE_LEVEL) { console.trace(args); } }, debug: args => { if (this.allLevel <= DEBUG_LEVEL || this.logPathsEnabled[loggerName] && this.logPathsEnabled[loggerName] <= DEBUG_LEVEL) { console.log(args); } }, info: args => { if (this.allLevel <= INFO_LEVEL || this.logPathsEnabled[loggerName] && this.logPathsEnabled[loggerName] <= INFO_LEVEL) { console.info(args); } }, warn: args => { if (this.allLevel <= WARN_LEVEL || this.logPathsEnabled[loggerName] && this.logPathsEnabled[loggerName] <= ERROR_LEVEL) { console.warn(args); } }, error: args => { if (this.allLevel <= ERROR_LEVEL || this.logPathsEnabled[loggerName] && this.logPathsEnabled[loggerName] <= TRACE_LEVEL) { console.error(args); } } }; } } /* eslint-disable @typescript-eslint/no-explicit-any */ /** * Skillet is an LLM-optimized streaming JSON Parser - perfectly suited for streaming hot and fresh JSON. * * Portions of this code are derived from partial-json (MIT License) (https://github.com/promplate/partial-json-parser-js). * See the LICENSE file in the project root for full license text. * * @license MIT * @author LiveLoveApp, LLC * @see https://github.com/liveloveapp/hashbrown * @see https://github.com/promplate/partial-json-parser-js */ const LOG_SETTINGS = { all: NONE_LEVEL }; class PartialJSON extends Error {} class MalformedJSON extends Error {} class IncompleteNonStreamingObject extends Error {} class UnexpectedStreamingType extends Error {} function shouldBeWrappedPrimitive(schema) { if (isAnyOfType(schema) || isObjectType(schema)) { return false; } return true; } function parseJSON(jsonString, schema, assumeFinishedMessage) { if (typeof jsonString !== 'string') { throw new TypeError(`expecting str, got ${typeof jsonString}`); } if (!jsonString.trim()) { return ''; } return _parseJSON(jsonString.trim(), schema, assumeFinishedMessage); } const _parseJSON = (jsonString, schema, assumeFinishedMessage) => { const logger = new Logger(LOG_SETTINGS); logger.for('_parseJSON').info('In _parseJson'); // Since each parse run is effectively starting over, this string should indicate // how far we can expect to get this time logger.for('_parseJSON').info(jsonString); const length = jsonString.length; let index = 0; // Track current object/array so we can move up and down the document stack as we go const containerStack = [schema]; const markPartialJSON = msg => { throw new PartialJSON(`${msg} at position ${index}`); }; const throwMalformedError = msg => { throw new MalformedJSON(`${msg} at position ${index}`); }; const parseAny = (currentKey, allowsIncomplete, insideArray) => { skipBlank(); logger.for('parseAny').info(`Remaining string: ${jsonString.slice(index)}`); const currentLastContainer = containerStack[containerStack.length - 1]; logger.for('parseAny').debug('Current last container:'); logger.for('parseAny').debug(currentLastContainer); if (index >= length) markPartialJSON('Unexpected end of input'); if (jsonString[index] === '"') return parseStr(allowsIncomplete); if (jsonString[index] === '{') { /* If the top-level schema is a primitive that should be object-wrapped, we assume a wrapped primitive is starting If the current container is an array, we assume an anyOf wrapper is starting. Else, we parse as a regular object. */ if (Array.isArray(currentLastContainer)) { return parseAnyOf(currentKey); } else if (shouldBeWrappedPrimitive(currentLastContainer)) { return parseWrappedPrimitive(); } else { return parseObj(currentKey, insideArray); } } if (jsonString[index] === '[') return parseArr(currentKey, allowsIncomplete); if (jsonString.substring(index, index + 4) === 'null') { index += 4; return null; } if (jsonString.substring(index, index + 4) === 'true') { index += 4; return true; } if (jsonString.substring(index, index + 5) === 'false') { index += 5; return false; } return parseNum(); }; const parseStr = allowsIncomplete => { if (containerStack.length === 1) { // String literal at top level, so see if the the schema allows streaming allowsIncomplete = isStreaming(schema); } const start = index; // Is the next character a string? // parseAny checks before calling parseStr, but functions parsing // key names (i.e. parseObj) do not, and we need to detect potentially // malformed JSON immediately following a comma if (jsonString[start] !== '"') { throwMalformedError('String expected but not started'); } let escape = false; index++; // skip initial quote 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 (allowsIncomplete) { try { return JSON.parse(jsonString.substring(start, index - Number(escape)) + '"'); } catch (_a) { // SyntaxError: Invalid escape sequence return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf('\\')) + '"'); } } markPartialJSON('Unterminated string literal'); }; const handleIncompleteWrappedPrimitive = val => { if (val == null) { throw new IncompleteNonStreamingObject('Incomplete wrapped primitive object found'); } return val; }; const parseWrappedPrimitive = () => { logger.for('parseWrappedPrimitive').info(`Parsing wrapped primitive object`); index++; // skip initial brace skipBlank(); let value = undefined; try { while (jsonString[index] !== '}') { skipBlank(); if (index >= length) { return handleIncompleteWrappedPrimitive(value); } const key = parseStr(false); if (key !== PRIMITIVE_WRAPPER_FIELD_NAME) { // How did we get here if this isn't really a wrapped primitive? throwMalformedError(`Wrapped primitive has unexpected key name: ${key}`); } skipBlank(); index++; // skip colon try { logger.for('parseWrappedPrimitive').debug(`Handling key: ${key}`); const matchingSchema = containerStack[containerStack.length - 1]; logger.for('parseWrappedPrimitive').debug('Found top-level schema:'); logger.for('parseWrappedPrimitive').debug(matchingSchema); // This isn't a real object, so don't pass the key name value = parseAny('', isStreaming(matchingSchema), false); logger.for('parseWrappedPrimitive').debug('Value:'); logger.for('parseWrappedPrimitive').debug(value); } catch (e) { logger.for('parseWrappedPrimitive').error(e); return handleIncompleteWrappedPrimitive(value); } skipBlank(); if (jsonString[index] === ',') index++; // skip comma } } catch (e) { logger.for('parseWrappedPrimitive').error(e); return handleIncompleteWrappedPrimitive(value); } index++; // skip final brace const completedContainer = containerStack.pop(); logger.for('parseWrappedPrimitive').info(`Completed wrapped primitive container: ${completedContainer === null || completedContainer === void 0 ? void 0 : completedContainer[internal].definition.description}`); return value; }; const handleIncompleteAnyOf = val => { if (val == null) { throw new IncompleteNonStreamingObject('Incomplete anyOf object found'); } return val; }; const parseAnyOf = parentKey => { logger.for('parseAnyOf').info(`Parsing anyOf with parent: ${parentKey}`); index++; // skip initial brace skipBlank(); let value = undefined; let currentContainerStackIndex = containerStack.length - 1; try { while (jsonString[index] !== '}') { skipBlank(); if (index >= length) { return handleIncompleteAnyOf(value); } const key = parseStr(false); skipBlank(); index++; // skip colon try { logger.for('parseAnyOf').debug(`Handling discriminator: ${key}`); const matchingSchema = containerStack[currentContainerStackIndex][parseInt(key)]; logger.for('parseAnyOf').debug(`Found matching schema in current container for ${key}: ${!!matchingSchema}`); if (matchingSche