Files
sausage/host/js/bundle.js
T
surma 57a47b069e host: process table, shell, coreutils and harness (T8, T9)
T8: sausage:process WIT (spawn, wait, kill), one store per process over the
shared root, /proc/processes, /run, pipeline and cancellation groups, Exec.
brush and 78 uutils commands; the shared cwd-init object sets the cwd from PWD
and keeps numeric exit codes. The corpus matches native bash.

T9: V8 (deno_core) runs pi-durable, pi-ai and chord; SQLite storage in
<dir>/host/harness.sqlite (WAL, synchronous=FULL); file tools on the VFS, bash
through Exec; resumes after SIGKILL.
2026-11-06 16:34:34 +00:00

44489 lines
1.7 MiB
Plaintext

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 __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
}) : x)(function(x) {
if (typeof require !== "undefined") return require.apply(this, arguments);
throw Error('Dynamic require of "' + x + '" is not supported');
});
var __esm = (fn, res, err) => function __init() {
if (err) throw err[0];
try {
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
} catch (e) {
throw err = [e], e;
}
};
var __commonJS = (cb, mod) => function __require2() {
try {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
} catch (e) {
throw mod = 0, e;
}
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
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
));
// node_modules/@earendil-works/pi-telemetry/dist/metrics.js
function createTypedMetrics(metrics, schemas) {
const definitions = /* @__PURE__ */ new Map();
for (const schema of schemas) {
for (const [name, definition] of Object.entries(schema.metrics ?? {}))
definitions.set(name, definition);
}
return {
counter: (name) => metrics.counter(name, definitions.get(name)),
upDownCounter: (name) => metrics.upDownCounter(name, definitions.get(name)),
histogram: (name) => metrics.histogram(name, definitions.get(name))
};
}
var init_metrics = __esm({
"node_modules/@earendil-works/pi-telemetry/dist/metrics.js"() {
}
});
// node_modules/@earendil-works/pi-telemetry/dist/noop.js
async function startNoopSpan(_options, callback) {
return callback(noopTelemetrySpan);
}
var noopCounter, noopUpDownCounter, noopHistogram, NOOP_TELEMETRY_METRICS, NOOP_TELEMETRY_PROPAGATION, noopTelemetrySpan, NOOP_TELEMETRY_CONTEXT;
var init_noop = __esm({
"node_modules/@earendil-works/pi-telemetry/dist/noop.js"() {
noopCounter = Object.freeze({ add: () => {
} });
noopUpDownCounter = Object.freeze({ add: () => {
} });
noopHistogram = Object.freeze({ record: () => {
} });
NOOP_TELEMETRY_METRICS = Object.freeze({
counter: () => noopCounter,
upDownCounter: () => noopUpDownCounter,
histogram: () => noopHistogram
});
NOOP_TELEMETRY_PROPAGATION = Object.freeze({
inject: () => void 0,
extract: () => NOOP_TELEMETRY_CONTEXT
});
noopTelemetrySpan = {
metrics: NOOP_TELEMETRY_METRICS,
propagation: NOOP_TELEMETRY_PROPAGATION,
startSpan: startNoopSpan,
addLink: () => {
},
addEvent: () => {
},
setAttributes: () => {
},
setStatus: () => {
}
};
Object.freeze(noopTelemetrySpan);
NOOP_TELEMETRY_CONTEXT = noopTelemetrySpan;
}
});
// node_modules/@earendil-works/pi-telemetry/dist/memory.js
var init_memory = __esm({
"node_modules/@earendil-works/pi-telemetry/dist/memory.js"() {
init_noop();
}
});
// node_modules/@earendil-works/pi-telemetry/dist/index.js
function defineTelemetrySchema(schema) {
return schema;
}
function bindTypedSpanStarter(telemetryContext) {
const startSpan = (name, attributes, callback) => telemetryContext.startSpan({ name, attributes }, (span) => callback(span, bindTypedSpanStarter(span)));
return startSpan;
}
function createTypedSpanStarter(telemetryContext, _schemas) {
return bindTypedSpanStarter(telemetryContext);
}
var init_dist = __esm({
"node_modules/@earendil-works/pi-telemetry/dist/index.js"() {
init_metrics();
init_noop();
init_memory();
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/event-stream.js
var FifoQueue, EventStream, AssistantMessageEventStream;
var init_event_stream = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/event-stream.js"() {
FifoQueue = class {
incoming = [];
outgoing = [];
get length() {
return this.incoming.length + this.outgoing.length;
}
enqueue(value2) {
this.incoming.push(value2);
}
dequeue() {
if (this.outgoing.length === 0) {
while (this.incoming.length > 0) {
this.outgoing.push(this.incoming.pop());
}
}
return this.outgoing.pop();
}
};
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((resolve2) => {
this.resolveFinalResult = resolve2;
});
}
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((resolve2) => this.waiting.enqueue(resolve2));
if (result.done)
return;
yield result.value;
}
}
}
result() {
return this.finalResultPromise;
}
};
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));
}
};
}
});
// node_modules/@earendil-works/pi-ai/dist/api/lazy.js
function createSetupErrorMessage(model3, error, timestamp) {
return {
role: "assistant",
content: [],
api: model3.api,
provider: model3.provider,
model: model3.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(model3, 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(model3, error, startedAt);
const event = { type: "error", reason: "error", error: message };
outer.push(event);
observer?.onEvent?.(event);
outer.end(message);
observeResult(message);
});
return outer;
}
function lazyApi(load, capabilities) {
const api = {
stream: (model3, context, options) => lazyStream(model3, async () => (await load()).stream(model3, context, options)),
streamSimple: (model3, context, options) => lazyStream(model3, async () => (await load()).streamSimple(model3, context, options))
};
if (capabilities?.fetchDeferred) {
api.fetchDeferred = (model3, handle, options) => lazyStream(model3, async () => {
const implementation = await load();
if (!implementation.fetchDeferred)
throw new Error("API does not support deferred responses");
return implementation.fetchDeferred(model3, handle, options);
});
}
if (capabilities?.cancelDeferred) {
api.cancelDeferred = async (model3, handle, options) => {
const implementation = await load();
if (!implementation.cancelDeferred)
throw new Error("API cannot cancel deferred responses");
await implementation.cancelDeferred(model3, handle, options);
};
}
return api;
}
var init_lazy = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/lazy.js"() {
init_event_stream();
}
});
// node_modules/@earendil-works/pi-ai/dist/auth/context.js
function getProcessEnv() {
const proc = globalThis.process;
return proc?.env;
}
function defaultProviderAuthContext() {
return {
async env(name) {
const value2 = getProcessEnv()?.[name];
return typeof value2 === "string" && value2.trim().length > 0 ? value2 : void 0;
},
async fileExists(path3) {
try {
const fs = await importNodeModule("node:fs/promises");
let resolved = path3;
if (resolved.startsWith("~")) {
const os = await importNodeModule("node:os");
resolved = os.homedir() + resolved.slice(1);
}
await fs.access(resolved);
return true;
} catch {
return false;
}
}
};
}
var __rewriteRelativeImportExtension, importNodeModule;
var init_context = __esm({
"node_modules/@earendil-works/pi-ai/dist/auth/context.js"() {
__rewriteRelativeImportExtension = function(path3, preserveJsx) {
if (typeof path3 === "string" && /^\.\.?\//.test(path3)) {
return path3.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
});
}
return path3;
};
importNodeModule = (specifier) => import(__rewriteRelativeImportExtension(specifier));
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/abort.js
function abortReason(signal) {
if (signal.reason !== void 0)
return signal.reason;
const error = new Error("The operation was aborted");
error.name = "AbortError";
return error;
}
function operationSignal(signal) {
return signal ?? new AbortController().signal;
}
function raceWithAbortSignal(operation, signal) {
if (signal.aborted) {
void operation.catch(() => {
});
return Promise.reject(abortReason(signal));
}
return new Promise((resolve2, reject2) => {
let settled = false;
const cleanup = () => signal.removeEventListener("abort", onAbort);
const onAbort = () => {
if (settled)
return;
settled = true;
cleanup();
reject2(abortReason(signal));
};
signal.addEventListener("abort", onAbort, { once: true });
void operation.then((value2) => {
if (settled)
return;
settled = true;
cleanup();
resolve2(value2);
}, (error) => {
if (settled)
return;
settled = true;
cleanup();
reject2(error);
});
if (signal.aborted)
onAbort();
});
}
var init_abort = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/abort.js"() {
}
});
// node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js
var InMemoryCredentialStore;
var init_credential_store = __esm({
"node_modules/@earendil-works/pi-ai/dist/auth/credential-store.js"() {
init_abort();
InMemoryCredentialStore = class {
credentials = /* @__PURE__ */ new Map();
chains = /* @__PURE__ */ new Map();
/** Serialize tasks per provider id without releasing the chain before active work settles. */
enqueue(providerId, task, options) {
const signal = operationSignal(options?.signal);
const previous = this.chains.get(providerId) ?? Promise.resolve();
const queued = (async () => {
await previous.catch(() => {
});
signal.throwIfAborted();
return task();
})();
const tail = queued.catch(() => {
});
this.chains.set(providerId, tail);
void tail.then(() => {
if (this.chains.get(providerId) === tail)
this.chains.delete(providerId);
});
return raceWithAbortSignal(queued, signal);
}
async read(providerId, options) {
options?.signal?.throwIfAborted();
return this.credentials.get(providerId);
}
async list(options) {
options?.signal?.throwIfAborted();
return [...this.credentials].map(([providerId, credential]) => ({ providerId, type: credential.type }));
}
modify(providerId, fn, options) {
return this.enqueue(providerId, async () => {
const current = this.credentials.get(providerId);
const next = await fn(current);
options?.signal?.throwIfAborted();
if (next !== void 0)
this.credentials.set(providerId, next);
return next ?? current;
}, options);
}
delete(providerId, options) {
return this.enqueue(providerId, async () => {
this.credentials.delete(providerId);
}, options);
}
};
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/diagnostics.js
function formatThrownValue(value2) {
if (value2 instanceof Error)
return value2.message || value2.name;
if (typeof value2 === "string")
return value2;
return String(value2);
}
var init_diagnostics = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/diagnostics.js"() {
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/models-error.js
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}`;
}
var ModelsError;
var init_models_error = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/models-error.js"() {
init_diagnostics();
ModelsError = class extends Error {
code;
constructor(code, message, options) {
super(withCauseDetail(message, options?.cause), options);
this.name = "ModelsError";
this.code = code;
}
};
}
});
// node_modules/@earendil-works/pi-ai/dist/auth/resolve.js
function resolveProviderAuth(provider3, credentials, authContext, overrides) {
const signal = operationSignal(overrides?.signal);
return raceWithAbortSignal(resolveProviderAuthWithSignal(provider3, credentials, authContext, overrides, signal), signal);
}
async function resolveProviderAuthWithSignal(provider3, credentials, authContext, overrides, signal) {
signal.throwIfAborted();
const requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;
if (overrides?.apiKey !== void 0 && provider3.auth.apiKey) {
return resolveApiKey(requestAuthContext, provider3.auth.apiKey, provider3.id, {
type: "api_key",
key: overrides.apiKey,
env: overrides.env
}, signal);
}
const stored = await readCredential(credentials, provider3.id, signal);
if (stored) {
if (stored.type === "oauth" && provider3.auth.oauth) {
return resolveStoredOAuth(credentials, provider3.id, provider3.auth.oauth, stored, signal, overrides?.minOAuthValidityMs);
}
if (stored.type === "api_key" && provider3.auth.apiKey) {
const credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;
return resolveApiKey(requestAuthContext, provider3.auth.apiKey, provider3.id, credential, signal);
}
return void 0;
}
return provider3.auth.apiKey ? resolveApiKey(requestAuthContext, provider3.auth.apiKey, provider3.id, void 0, signal) : void 0;
}
function overlayEnvAuthContext(base, env) {
return {
env: async (name) => env[name] || await base.env(name),
fileExists: (path3) => base.fileExists(path3)
};
}
async function refreshStoredOAuthCredential(credentials, providerId, oauth, needsRefresh, signal) {
let post;
const lockWait = new AbortController();
const cancelLockWait = () => lockWait.abort(signal.reason);
signal.addEventListener("abort", cancelLockWait, { once: true });
if (signal.aborted)
cancelLockWait();
try {
post = await credentials.modify(providerId, async (current) => {
signal.removeEventListener("abort", cancelLockWait);
signal.throwIfAborted();
if (current?.type !== "oauth")
return void 0;
if (!needsRefresh(current))
return void 0;
try {
return await oauth.refresh(current, AbortSignal.timeout(DEFAULT_OAUTH_REFRESH_TIMEOUT_MS));
} catch (error) {
throw new ModelsError("oauth", `OAuth refresh failed for ${providerId}`, { cause: error });
}
}, { signal: lockWait.signal });
} catch (error) {
if (error instanceof ModelsError)
throw error;
signal.throwIfAborted();
throw new ModelsError("auth", `Credential store modify failed for ${providerId}`, { cause: error });
} finally {
signal.removeEventListener("abort", cancelLockWait);
}
return post?.type === "oauth" ? post : void 0;
}
async function resolveStoredOAuth(credentials, providerId, oauth, stored, signal, minOAuthValidityMs) {
const minimumValidityMs = Math.max(DEFAULT_OAUTH_MINIMUM_VALIDITY_MS, minOAuthValidityMs ?? 0);
const expiresSoon = (credential2) => Date.now() + minimumValidityMs >= credential2.expires;
let credential = stored;
if (expiresSoon(credential)) {
const post = await refreshStoredOAuthCredential(credentials, providerId, oauth, expiresSoon, signal);
if (!post)
return void 0;
credential = post;
if (minOAuthValidityMs !== void 0 && expiresSoon(credential)) {
throw new ModelsError("oauth", `OAuth refresh returned a token that expires too soon for ${providerId}`);
}
}
try {
return { auth: await oauth.toAuth(credential), source: "OAuth" };
} catch (error) {
throw new ModelsError("oauth", `OAuth auth derivation failed for ${providerId}`, { cause: error });
}
}
async function resolveApiKey(authContext, apiKey, providerId, credential, signal) {
try {
return await apiKey.resolve({ ctx: authContext, credential, signal });
} catch (error) {
throw new ModelsError("auth", `API key auth failed for provider ${providerId}`, { cause: error });
}
}
async function readCredential(credentials, providerId, signal) {
try {
return await credentials.read(providerId, { signal });
} catch (error) {
throw new ModelsError("auth", `Credential store read failed for ${providerId}`, { cause: error });
}
}
var DEFAULT_OAUTH_MINIMUM_VALIDITY_MS, DEFAULT_OAUTH_REFRESH_TIMEOUT_MS;
var init_resolve = __esm({
"node_modules/@earendil-works/pi-ai/dist/auth/resolve.js"() {
init_abort();
init_models_error();
init_models_error();
DEFAULT_OAUTH_MINIMUM_VALIDITY_MS = 5 * 60 * 1e3;
DEFAULT_OAUTH_REFRESH_TIMEOUT_MS = 15e3;
}
});
// node_modules/@earendil-works/pi-ai/dist/models-store.js
var InMemoryModelsStore;
var init_models_store = __esm({
"node_modules/@earendil-works/pi-ai/dist/models-store.js"() {
InMemoryModelsStore = class {
entries = /* @__PURE__ */ new Map();
async read(providerId, options) {
options?.signal?.throwIfAborted();
const entry2 = this.entries.get(providerId);
return entry2 ? structuredClone(entry2) : void 0;
}
async write(providerId, entry2, options) {
options?.signal?.throwIfAborted();
this.entries.set(providerId, structuredClone(entry2));
}
async delete(providerId, options) {
options?.signal?.throwIfAborted();
this.entries.delete(providerId);
}
};
}
});
// 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 text2 of Object.values(message.sections ?? {})) {
if (text2 !== null)
parts.push(text2);
}
return parts.filter((part) => part.length > 0).join("\n\n");
}
function renderSystemMessageUpdate(message) {
const parts = [];
const text2 = contentText(message.content);
if (text2.length > 0)
parts.push(text2);
for (const [name, value2] of Object.entries(message.sections ?? {})) {
parts.push(value2 === null ? `Removed system prompt section "${name}".` : `Updated system prompt section "${name}":
${value2}`);
}
return parts.join("\n\n");
}
function ownedSlice(text2, start, end = text2.length) {
return `${text2.slice(start, end)} `.slice(0, -1);
}
var init_text = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/text.js"() {
}
});
// node_modules/@earendil-works/pi-ai/dist/telemetry.js
function createInstruments(adapter) {
const metrics = createTypedMetrics(adapter, [AI_TELEMETRY_SCHEMA]);
return {
requestDuration: metrics.histogram("pi.ai.request.duration"),
firstChunkDuration: metrics.histogram("pi.ai.first_chunk.duration"),
tokens: metrics.counter("pi.ai.tokens"),
cost: metrics.counter("pi.ai.cost")
};
}
function observeModelRequest(requestedModel, options, poll) {
const started = performance.now();
const attributes = { provider: requestedModel.provider, model: requestedModel.id };
const adapter = options?.telemetry?.metrics ?? NOOP_TELEMETRY_METRICS;
let instruments = instrumentCache.get(adapter);
if (!instruments) {
instruments = createInstruments(adapter);
instrumentCache.set(adapter, instruments);
}
const { requestDuration, firstChunkDuration, tokens, cost } = instruments;
let span;
let finish;
let first = true;
const toolChars = /* @__PURE__ */ new Map();
const finished = new Promise((resolve2) => {
finish = resolve2;
});
const run2 = (activeSpan) => {
span = activeSpan;
return finished;
};
const startAttributes = {
...attributes,
api: requestedModel.api,
...typeof options?.reasoning === "string" ? { reasoning: options.reasoning } : {}
};
const start = createTypedSpanStarter(options?.telemetry ?? NOOP_TELEMETRY_CONTEXT, [AI_TELEMETRY_SCHEMA]);
if (poll)
void start("pi.ai.poll", startAttributes, run2);
else
void start("pi.ai.request", startAttributes, run2);
return {
onEvent(event) {
if (first) {
first = false;
span.addEvent("pi.ai.first_chunk");
firstChunkDuration.record(performance.now() - started, attributes, span);
}
if (event.type === "toolcall_delta") {
toolChars.set(event.contentIndex, (toolChars.get(event.contentIndex) ?? 0) + event.delta.length);
} else if (event.type === "text_end" || event.type === "thinking_end") {
span.addEvent("pi.ai.block", {
type: event.type === "text_end" ? "text" : "thinking",
index: event.contentIndex,
chars: event.content.length
});
} else if (event.type === "toolcall_end") {
const chars = toolChars.get(event.contentIndex) ?? 0;
toolChars.delete(event.contentIndex);
span.addEvent("pi.ai.block", {
type: "tool_call",
index: event.contentIndex,
chars,
tool: event.toolCall.name
});
}
},
onResult(message) {
if (message) {
span.setAttributes({
stop: message.stopReason,
"usage.input": message.usage.input,
"usage.output": message.usage.output,
"usage.cache_read": message.usage.cacheRead,
"usage.cache_write": message.usage.cacheWrite,
"cost.total": message.usage.cost.total,
"response.id": message.responseId
});
if (message.stopReason === "error") {
span.setStatus({
status: "error",
error: { name: "provider_error", message: ownedSlice(message.errorMessage ?? "", 0, 500) }
});
}
requestDuration.record(performance.now() - started, { ...attributes, stop: message.stopReason }, span);
if (!poll || message.stopReason !== "pending" && message.stopReason !== "deferred") {
tokens.add(message.usage.input, { ...attributes, kind: "input" });
tokens.add(message.usage.output, { ...attributes, kind: "output" });
tokens.add(message.usage.cacheRead, { ...attributes, kind: "cache_read" });
tokens.add(message.usage.cacheWrite, { ...attributes, kind: "cache_write" });
cost.add(message.usage.cost.total, attributes);
}
}
finish();
}
};
}
var provider, model, stop, request, AI_TELEMETRY_SCHEMA, instrumentCache;
var init_telemetry = __esm({
"node_modules/@earendil-works/pi-ai/dist/telemetry.js"() {
init_dist();
init_text();
provider = { type: "string", description: "Provider identifier.", required: true };
model = { type: "string", description: "Requested model identifier.", required: true };
stop = {
type: "string",
description: "Normalized stop reason.",
values: ["pending", "stop", "length", "toolUse", "error", "aborted", "deferred"]
};
request = {
description: "One logical model request, including authentication and provider setup.",
parents: { kind: "any" },
startAttributes: {
provider,
api: { type: "string", description: "API identifier.", required: true },
model,
reasoning: { type: "string", description: "Scalar requested reasoning level.", required: false }
},
endAttributes: {
stop,
"usage.input": { type: "number", description: "Uncached input tokens." },
"usage.output": { type: "number", description: "Output tokens." },
"usage.cache_read": { type: "number", description: "Cache-read tokens." },
"usage.cache_write": { type: "number", description: "Cache-write tokens." },
"cost.total": { type: "number", description: "Total request cost in USD." },
"response.id": { type: "string", description: "Provider response identifier.", cardinality: "high" }
},
events: {
"pi.ai.first_chunk": { description: "First normalized stream event delivered.", attributes: {} },
"pi.ai.block": {
description: "A completed content block; content is never recorded.",
attributes: {
type: {
type: "string",
description: "Block kind.",
values: ["text", "thinking", "tool_call"],
required: true
},
index: { type: "number", description: "Content block index.", required: true },
chars: { type: "number", description: "UTF-16 character count.", required: true },
tool: { type: "string", description: "Tool name, for tool-call blocks only.", required: false }
}
}
},
status: {
default: "ok",
errorWhen: "Stop reason is error: provider_error with at most 500 error-message characters. Aborted stays ok."
}
};
AI_TELEMETRY_SCHEMA = defineTelemetrySchema({
version: 1,
spans: {
"pi.ai.request": request,
"pi.ai.poll": { ...request, description: "One deferred-response poll, not the deferred request's lifetime." }
},
metrics: {
"pi.ai.request.duration": {
kind: "histogram",
description: "Logical request or poll duration.",
unit: "ms",
attributes: { provider, model, stop: { ...stop, required: true } }
},
"pi.ai.first_chunk.duration": {
kind: "histogram",
description: "Time to the first normalized stream event.",
unit: "ms",
attributes: { provider, model }
},
"pi.ai.tokens": {
kind: "counter",
description: "Reported model token usage; pending and deferred polls are excluded.",
unit: "token",
attributes: {
provider,
model,
kind: {
type: "string",
description: "Token usage category.",
values: ["input", "output", "cache_read", "cache_write"],
required: true
}
}
},
"pi.ai.cost": {
kind: "counter",
description: "Reported model cost; pending and deferred polls are excluded.",
unit: "USD",
attributes: { provider, model }
}
}
});
instrumentCache = /* @__PURE__ */ new WeakMap();
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/version.js
var PI_AI_VERSION;
var init_version = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/version.js"() {
PI_AI_VERSION = "1.5.0";
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/identity.js
function mergeClientIdentity(...sources) {
let merged;
for (const source of sources) {
if (!source)
continue;
merged = { ...merged };
if (source.userAgent !== void 0)
merged.userAgent = source.userAgent;
if (source.attribution !== void 0)
merged.attribution = source.attribution;
if (source.version !== void 0)
merged.version = source.version;
}
return merged;
}
function getClientVersion(identity) {
return identity?.version ?? PI_AI_VERSION;
}
function runtimeDescription() {
if (typeof process === "undefined")
return void 0;
const versions = process.versions;
if (versions?.bun)
return `bun/${versions.bun}`;
if (versions?.node)
return `node/${process.version}`;
return void 0;
}
function formatUserAgent(identity) {
const mode = identity?.userAgent ?? "detailed";
if (typeof mode === "object")
return mode.custom;
if (mode === "short")
return "pi";
const product = `pi/${getClientVersion(identity)}`;
const runtime = runtimeDescription();
return runtime ? `${product} (${process.platform}; ${runtime}; ${process.arch})` : `${product} (browser)`;
}
function matchesHost(baseUrl, expectedHost) {
try {
return new URL(baseUrl).hostname === expectedHost;
} catch {
return false;
}
}
function isOpenRouter(target) {
return target.provider === "openrouter" || target.baseUrl.includes("openrouter.ai");
}
function isNvidiaNim(target) {
return target.provider === "nvidia" || matchesHost(target.baseUrl, NVIDIA_NIM_HOST);
}
function isOpenCode(target) {
return target.provider === "opencode" || target.provider === "opencode-go" || matchesHost(target.baseUrl, OPENCODE_HOST);
}
function getAttributionHeaders(target, identity) {
const attribution = identity?.attribution;
if (!attribution)
return {};
const { name, url, categories } = attribution;
if (isOpenRouter(target)) {
return {
"HTTP-Referer": url,
"X-OpenRouter-Title": name,
...categories === void 0 || categories.length === 0 ? {} : { "X-OpenRouter-Categories": categories.join(",") }
};
}
if (isNvidiaNim(target))
return { "X-BILLING-INVOKE-ORIGIN": name.charAt(0).toUpperCase() + name.slice(1) };
if (isOpenCode(target))
return { "x-opencode-client": name };
return {};
}
function getOpenCodeSessionHeaders(target, sessionId) {
return sessionId && isOpenCode(target) ? { "x-opencode-session": sessionId } : void 0;
}
function getIdentityHeaders(target, identity) {
return { "User-Agent": formatUserAgent(identity), ...getAttributionHeaders(target, identity) };
}
function isMutableModels(models2) {
return "setProvider" in models2 && "deleteProvider" in models2 && "clearProviders" in models2;
}
function withClientIdentity(models2, identity) {
const withIdentity = (options) => ({ ...options, identity: mergeClientIdentity(identity, options?.identity) });
const wrapped = {
getProviders: () => models2.getProviders(),
getProvider: (id) => models2.getProvider(id),
getModels: (provider3) => models2.getModels(provider3),
getModel: (provider3, id) => models2.getModel(provider3, id),
getModelsOfType: (type, provider3) => models2.getModelsOfType(type, provider3),
getModelOfType: (type, provider3, id) => models2.getModelOfType(type, provider3, id),
getAllModels: (provider3) => models2.getAllModels(provider3),
refresh: (options) => models2.refresh(options),
checkAuth: (providerId, options) => models2.checkAuth(providerId, options),
getAvailable: (providerId, options) => models2.getAvailable(providerId, options),
getAvailableOfType: (type, providerId, options) => models2.getAvailableOfType(type, providerId, options),
getAllAvailable: (providerId, options) => models2.getAllAvailable(providerId, options),
getAuth: models2.getAuth.bind(models2),
login: (providerId, type, interaction, options) => models2.login(providerId, type, interaction, options),
logout: (providerId, options) => models2.logout(providerId, options),
stream: (model3, context, options) => models2.stream(model3, context, withIdentity(options)),
complete: (model3, context, options) => models2.complete(model3, context, withIdentity(options)),
streamSimple: (model3, context, options) => models2.streamSimple(model3, context, withIdentity(options)),
completeSimple: (model3, context, options) => models2.completeSimple(model3, context, withIdentity(options)),
streamDeferred: (model3, handle, options) => models2.streamDeferred(model3, handle, withIdentity(options)),
fetchDeferred: (model3, handle, options) => models2.fetchDeferred(model3, handle, withIdentity(options)),
cancelDeferred: (model3, handle, options) => models2.cancelDeferred(model3, handle, withIdentity(options)),
generateImages: (model3, context, options) => models2.generateImages(model3, context, withIdentity(options)),
classify: (model3, context, options) => models2.classify(model3, context, withIdentity(options))
};
if (!isMutableModels(models2))
return wrapped;
const mutable = {
...wrapped,
setProvider: (provider3) => models2.setProvider(provider3),
deleteProvider: (id) => models2.deleteProvider(id),
clearProviders: () => models2.clearProviders()
};
return mutable;
}
var PI_ATTRIBUTION, NVIDIA_NIM_HOST, OPENCODE_HOST;
var init_identity = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/identity.js"() {
init_version();
PI_ATTRIBUTION = { name: "pi", url: "https://pi.dev", categories: ["cli-agent"] };
NVIDIA_NIM_HOST = "integrate.api.nvidia.com";
OPENCODE_HOST = "opencode.ai";
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/model-operations.js
function getModelType(model3) {
return model3.type ?? "chat";
}
function isModelType(model3, type) {
return getModelType(model3) === type;
}
function assertChatModel(model3) {
if (!isModelType(model3, "chat")) {
throw new ModelsError("provider", `Model ${model3.provider}/${model3.id} is not a chat model`);
}
}
function assertImageModel(model3) {
if (!isModelType(model3, "image")) {
throw new ModelsError("provider", `Model ${model3.provider}/${model3.id} is not an image model`);
}
}
function assertClassifierModel(model3) {
if (!isModelType(model3, "classifier")) {
throw new ModelsError("provider", `Model ${model3.provider}/${model3.id} is not a classifier model`);
}
}
function assertClassifierInputSupported(model3, context) {
if (context.images?.length && !model3.input.includes("image")) {
throw new ModelsError("provider", `Model ${model3.provider}/${model3.id} does not accept image input`);
}
}
function imageErrorResult(model3, error, aborted = false) {
return {
api: model3.api,
provider: model3.provider,
model: model3.id,
output: [],
stopReason: aborted ? "aborted" : "error",
errorMessage: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
}
function classifierErrorResult(model3, error, aborted = false) {
return {
api: model3.api,
provider: model3.provider,
model: model3.id,
answers: {},
stopReason: aborted ? "aborted" : "error",
errorMessage: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
}
var init_model_operations = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/model-operations.js"() {
init_models_error();
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/transcript.js
function createInitialSystemMessage(systemPrompt, tools) {
const hasSystemPrompt = systemPrompt !== void 0 && systemPrompt.length > 0;
const hasTools = tools !== void 0 && tools.length > 0;
if (!hasSystemPrompt && !hasTools)
return void 0;
return {
role: "system",
content: systemPrompt ?? "",
...hasTools ? { toolsAdded: tools } : {},
timestamp: 0
};
}
function normalizeContext(context) {
const initialMessage = createInitialSystemMessage(context.systemPrompt, context.tools);
const messages = initialMessage ? [initialMessage, ...context.messages] : context.messages;
return { messages };
}
function isSystemMessage(message) {
return message.role === "system";
}
function getInitialSystemMessage(messages) {
const first = messages[0];
return first && isSystemMessage(first) ? first : void 0;
}
function getCurrentTools(messages) {
const tools = /* @__PURE__ */ new Map();
for (const message of messages) {
if (!isSystemMessage(message))
continue;
for (const tool of message.toolsRemoved ?? [])
tools.delete(tool.name);
for (const tool of message.toolsAdded ?? [])
tools.set(tool.name, tool);
}
return [...tools.values()];
}
function getCurrentSystemMessage(messages) {
const content = [];
const sections = /* @__PURE__ */ new Map();
let timestamp;
for (const message of messages) {
if (!isSystemMessage(message))
continue;
timestamp ??= message.timestamp;
const text2 = contentText(message.content);
if (text2.length > 0)
content.push(text2);
for (const [name, value2] of Object.entries(message.sections ?? {})) {
if (value2 === null)
sections.delete(name);
else
sections.set(name, value2);
}
}
const tools = getCurrentTools(messages);
if (timestamp === void 0 && tools.length === 0)
return void 0;
return {
role: "system",
content: content.join("\n\n"),
...sections.size > 0 ? { sections: Object.fromEntries(sections) } : {},
...tools.length > 0 ? { toolsAdded: tools } : {},
timestamp: timestamp ?? 0
};
}
function collapseSystemMessages(context) {
const head = getCurrentSystemMessage(context.messages);
const messages = context.messages.filter((message) => message.role !== "system");
return { messages: head ? [head, ...messages] : messages };
}
function resolveTranscript(context, supportsMidConvoSystemMessages) {
return supportsMidConvoSystemMessages ? context : collapseSystemMessages(context);
}
function toToolDeclaration(tool) {
return {
name: tool.name,
description: tool.description,
parameters: JSON.parse(JSON.stringify(tool.parameters)),
...tool.constrainedSampling === void 0 ? {} : { constrainedSampling: tool.constrainedSampling }
};
}
function declarationsEqual(left, right) {
return JSON.stringify(toToolDeclaration(left)) === JSON.stringify(toToolDeclaration(right));
}
function getDeclaredTools(messages) {
const definitions = /* @__PURE__ */ new Map();
for (const message of messages) {
if (!isSystemMessage(message))
continue;
for (const tool of message.toolsAdded ?? [])
definitions.set(tool.name, tool);
}
return [...definitions.values()];
}
function findLastNonAdditiveToolChange(systemMessages) {
const declared = /* @__PURE__ */ new Set();
let last = -1;
for (let index = 0; index < systemMessages.length; index++) {
const message = systemMessages[index];
if ((message.toolsRemoved?.length ?? 0) > 0)
last = index;
for (const tool of message.toolsAdded ?? []) {
if (declared.has(tool.name))
last = index;
declared.add(tool.name);
}
}
return last;
}
function resolveTranscriptTools(messages, support) {
const systemMessages = messages.filter(isSystemMessage);
if (support === "none") {
return { requestTools: getCurrentTools(systemMessages), foldedSystemMessages: systemMessages.length };
}
if (support === "changes")
return { requestTools: [], foldedSystemMessages: 0 };
const folded = Math.max(getInitialSystemMessage(messages) ? 1 : 0, findLastNonAdditiveToolChange(systemMessages) + 1);
return { requestTools: getCurrentTools(systemMessages.slice(0, folded)), foldedSystemMessages: folded };
}
var init_transcript = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/transcript.js"() {
init_text();
}
});
// node_modules/@earendil-works/pi-ai/dist/models.js
function hasKnownModelType(model3) {
return Object.hasOwn(KNOWN_MODEL_TYPES, getModelType(model3));
}
function withKnownModelTypes(entry2) {
return { ...entry2, models: entry2.models.filter(hasKnownModelType) };
}
function mergeHeaders(base, override) {
if (!base && !override)
return void 0;
const merged = { ...base };
for (const [name, value2] of Object.entries(override ?? {})) {
const lowerName = name.toLowerCase();
for (const existingName of Object.keys(merged)) {
if (existingName.toLowerCase() === lowerName)
delete merged[existingName];
}
merged[name] = value2;
}
return merged;
}
function createModels(options) {
return new ModelsImpl(options);
}
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((entry2) => entry2 !== void 0);
const imageImplementations = Object.values(images ?? {}).filter((entry2) => entry2 !== void 0);
const classifierImplementations = Object.values(classifiers ?? {}).filter((entry2) => entry2 !== 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 currentModels2 = () => {
const merged = [...baselineModels];
for (const model3 of dynamicModels) {
const index = merged.findIndex((entry2) => getModelType(entry2) === getModelType(model3) && entry2.id === model3.id);
if (index >= 0)
merged[index] = model3;
else
merged.push(model3);
}
return merged;
};
const apiFor = (model3) => single ?? byApi?.[model3.api];
const dispatch = (model3, run2) => {
const streams2 = apiFor(model3);
if (!streams2) {
return lazyStream(model3, async () => {
throw new ModelsError("stream", `Provider ${input.id} has no API implementation for "${model3.api}"`);
});
}
return run2(streams2);
};
const provider3 = {
id: input.id,
name: input.name ?? input.id,
baseUrl: input.baseUrl,
headers: input.headers,
auth: input.auth,
getModels: () => currentModels2().filter((model3) => isModelType(model3, "chat")),
getAllModels: currentModels2,
refreshModels: fetchModels ? async (context) => {
if (context.stored) {
const restored = context.stored.models.filter((model3) => model3.provider === input.id).map((model3) => model3);
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: (model3, context, options) => dispatch(model3, (streams2) => streams2.stream(model3, context, options)),
streamSimple: (model3, context, options) => dispatch(model3, (streams2) => streams2.streamSimple(model3, context, options))
};
if (streams.some((entry2) => entry2.fetchDeferred !== void 0)) {
provider3.fetchDeferred = (model3, handle, options) => lazyStream(model3, async () => {
const implementation = apiFor(model3);
if (!implementation?.fetchDeferred) {
throw new ModelsError("provider", `Provider ${input.id} does not support deferred responses for "${model3.api}"`);
}
return implementation.fetchDeferred(model3, handle, options);
});
}
if (streams.some((entry2) => entry2.cancelDeferred !== void 0)) {
provider3.cancelDeferred = async (model3, handle, options) => {
const implementation = apiFor(model3);
if (!implementation?.cancelDeferred) {
throw new ModelsError("provider", `Provider ${input.id} cannot cancel deferred responses for "${model3.api}"`);
}
await implementation.cancelDeferred(model3, handle, options);
};
}
if (images && imageImplementations.length > 0) {
provider3.generateImages = async (model3, context, options) => {
const implementation = images[model3.api];
if (!implementation) {
return imageErrorResult(model3, new ModelsError("provider", `Provider ${input.id} has no image generation implementation for "${model3.api}"`));
}
return implementation.generateImages(model3, context, options);
};
}
if (classifiers && classifierImplementations.length > 0) {
provider3.classify = async (model3, context, options) => {
const implementation = classifiers[model3.api];
if (!implementation) {
return classifierErrorResult(model3, new ModelsError("provider", `Provider ${input.id} has no classifier implementation for "${model3.api}"`));
}
return implementation.classify(model3, context, options);
};
}
return provider3;
}
function calculateCost(model3, usage) {
const inputTokens = usage.input + usage.cacheRead + usage.cacheWrite;
let rates = model3.cost;
let matchedThreshold = -1;
for (const tier of model3.cost.tiers ?? []) {
if (inputTokens > tier.inputTokensAbove && tier.inputTokensAbove > matchedThreshold) {
rates = tier;
matchedThreshold = tier.inputTokensAbove;
}
}
const longWrite = usage.cacheWrite1h ?? 0;
const shortWrite = usage.cacheWrite - longWrite;
usage.cost.input = rates.input / 1e6 * usage.input;
usage.cost.output = rates.output / 1e6 * usage.output;
usage.cost.cacheRead = rates.cacheRead / 1e6 * usage.cacheRead;
usage.cost.cacheWrite = (rates.cacheWrite * shortWrite + rates.input * 2 * longWrite) / 1e6;
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
usage.cost.totalFromProvider = false;
return usage.cost;
}
function getSupportedThinkingLevels(model3) {
if (!model3.reasoning)
return ["off"];
return EXTENDED_THINKING_LEVELS.filter((level) => {
const mapped = model3.thinkingLevelMap?.[level];
if (mapped === null)
return false;
if (level === "xhigh" || level === "max")
return mapped !== void 0;
return true;
});
}
function clampThinkingLevel(model3, level) {
const availableLevels = getSupportedThinkingLevels(model3);
if (availableLevels.includes(level))
return level;
const requestedIndex = EXTENDED_THINKING_LEVELS.indexOf(level);
if (requestedIndex === -1)
return availableLevels[0] ?? "off";
for (let i = requestedIndex; i < EXTENDED_THINKING_LEVELS.length; i++) {
const candidate = EXTENDED_THINKING_LEVELS[i];
if (availableLevels.includes(candidate))
return candidate;
}
for (let i = requestedIndex - 1; i >= 0; i--) {
const candidate = EXTENDED_THINKING_LEVELS[i];
if (availableLevels.includes(candidate))
return candidate;
}
return availableLevels[0] ?? "off";
}
var KNOWN_MODEL_TYPES, ModelsImpl, EXTENDED_THINKING_LEVELS;
var init_models = __esm({
"node_modules/@earendil-works/pi-ai/dist/models.js"() {
init_lazy();
init_context();
init_credential_store();
init_resolve();
init_models_store();
init_telemetry();
init_abort();
init_identity();
init_model_operations();
init_transcript();
init_model_operations();
KNOWN_MODEL_TYPES = { chat: true, image: true, classifier: true };
ModelsImpl = class {
providers = /* @__PURE__ */ new Map();
credentials;
modelsStore;
authContext;
identity;
refreshGenerations = /* @__PURE__ */ new Map();
refreshControllers = /* @__PURE__ */ new Map();
publicationChains = /* @__PURE__ */ new Map();
constructor(options) {
this.credentials = options?.credentials ?? new InMemoryCredentialStore();
this.modelsStore = options?.modelsStore ?? new InMemoryModelsStore();
this.authContext = options?.authContext ?? defaultProviderAuthContext();
this.identity = options?.identity;
}
setProvider(provider3) {
this.supersedeProviderRefresh(provider3.id);
this.providers.set(provider3.id, provider3);
}
deleteProvider(id) {
this.supersedeProviderRefresh(id);
this.providers.delete(id);
}
clearProviders() {
for (const id of /* @__PURE__ */ new Set([...this.providers.keys(), ...this.refreshControllers.keys()])) {
this.supersedeProviderRefresh(id);
}
this.providers.clear();
}
getProviders() {
return Array.from(this.providers.values());
}
getProvider(id) {
return this.providers.get(id);
}
getModels(provider3) {
if (provider3 !== void 0) {
const entry2 = this.providers.get(provider3);
if (!entry2)
return [];
try {
return entry2.getModels();
} catch {
return [];
}
}
const models2 = [];
for (const entry2 of this.providers.values()) {
try {
models2.push(...entry2.getModels());
} catch {
}
}
return models2;
}
getAllModels(provider3) {
if (provider3 !== void 0) {
const entry2 = this.providers.get(provider3);
if (!entry2)
return [];
try {
return entry2.getAllModels?.() ?? entry2.getModels();
} catch {
return [];
}
}
const models2 = [];
for (const entry2 of this.providers.values()) {
try {
models2.push(...entry2.getAllModels?.() ?? entry2.getModels());
} catch {
}
}
return models2;
}
getModelsOfType(type, provider3) {
return this.getAllModels(provider3).filter((model3) => isModelType(model3, type));
}
getModel(provider3, id) {
return this.getModels(provider3).find((model3) => model3.id === id);
}
getModelOfType(type, provider3, id) {
return this.getModelsOfType(type, provider3).find((model3) => model3.id === id);
}
supersedeProviderRefresh(providerId) {
const generation = (this.refreshGenerations.get(providerId) ?? 0) + 1;
this.refreshGenerations.set(providerId, generation);
const previous = this.refreshControllers.get(providerId);
if (previous) {
this.refreshControllers.delete(providerId);
previous.abort();
}
return generation;
}
beginProviderRefresh(providerId) {
const generation = this.supersedeProviderRefresh(providerId);
const controller = new AbortController();
this.refreshControllers.set(providerId, controller);
return { generation, controller };
}
publishProviderModels(providerId, generation, signal, publication) {
const previous = this.publicationChains.get(providerId) ?? Promise.resolve();
const queued = (async () => {
await previous.catch(() => {
});
if (signal.aborted || this.refreshGenerations.get(providerId) !== generation)
return false;
if (publication.persist === null) {
await this.modelsStore.delete(providerId, { signal });
} else if (publication.persist !== void 0) {
await this.modelsStore.write(providerId, structuredClone(publication.persist), { signal });
}
if (signal.aborted || this.refreshGenerations.get(providerId) !== generation)
return false;
publication.update?.();
return true;
})();
const tail = queued.catch(() => {
});
this.publicationChains.set(providerId, tail);
void tail.then(() => {
if (this.publicationChains.get(providerId) === tail)
this.publicationChains.delete(providerId);
});
return raceWithAbortSignal(queued, signal);
}
async runProviderRefreshPhase(provider3, credential, allowNetwork, force, generation, signal) {
const stored = await this.modelsStore.read(provider3.id, { signal });
await provider3.refreshModels({
credential,
stored: stored ? withKnownModelTypes(structuredClone(stored)) : void 0,
publish: (publication) => this.publishProviderModels(provider3.id, generation, signal, publication),
allowNetwork,
force: allowNetwork ? force : void 0,
signal,
baseUrl: provider3.baseUrl
});
}
async refresh(options = {}) {
const allowNetwork = options.allowNetwork ?? true;
const callerSignal = operationSignal(options.signal);
const errors = /* @__PURE__ */ new Map();
if (callerSignal.aborted)
return { aborted: true, errors };
const selected = options.providers ? new Set(options.providers) : void 0;
const refreshable = Array.from(this.providers.values()).filter((provider3) => provider3.refreshModels !== void 0 && (!selected || selected.has(provider3.id)));
const refresh = Promise.all(refreshable.map(async (provider3) => {
const { generation, controller } = this.beginProviderRefresh(provider3.id);
const signal = AbortSignal.any([callerSignal, controller.signal]);
const operation = (async () => {
let storedCredential;
let credentialError;
try {
storedCredential = await this.readCredential(provider3.id, signal);
} catch (error) {
credentialError = error;
}
await this.runProviderRefreshPhase(provider3, storedCredential, false, void 0, generation, signal);
if (credentialError !== void 0)
throw credentialError;
if (!allowNetwork || signal.aborted)
return;
const credential = await this.resolveRefreshCredential(provider3, storedCredential, signal);
if (!credential)
return;
await this.runProviderRefreshPhase(provider3, credential, true, options.force, generation, signal);
})();
try {
await raceWithAbortSignal(operation, signal);
} catch (error) {
if (!signal.aborted) {
errors.set(provider3.id, error instanceof Error ? error : new ModelsError("model_source", `Model refresh failed for ${provider3.id}`, { cause: error }));
}
} finally {
if (this.refreshControllers.get(provider3.id) === controller) {
this.refreshControllers.delete(provider3.id);
}
}
}));
try {
await raceWithAbortSignal(refresh, callerSignal);
} catch (error) {
if (!callerSignal.aborted)
throw error;
}
return { aborted: callerSignal.aborted, errors: new Map(errors) };
}
async resolveRefreshCredential(provider3, stored, signal) {
if (stored?.type === "oauth") {
const oauth = provider3.auth.oauth;
if (!oauth)
return void 0;
if (Date.now() < stored.expires)
return stored;
if (signal.aborted)
return void 0;
return refreshStoredOAuthCredential(this.credentials, provider3.id, oauth, (current) => Date.now() >= current.expires, signal);
}
const apiKey = provider3.auth.apiKey;
if (!apiKey)
return void 0;
const credential = stored?.type === "api_key" ? stored : void 0;
const result = await apiKey.resolve({ ctx: this.authContext, credential, signal });
if (!result)
return void 0;
return { type: "api_key", key: result.auth.apiKey, env: result.env };
}
async readCredential(providerId, signal) {
try {
return await this.credentials.read(providerId, { signal });
} catch (error) {
throw new ModelsError("auth", `Credential store read failed for ${providerId}`, { cause: error });
}
}
async checkProviderAuth(provider3, credential, signal) {
if (credential?.type === "oauth") {
return provider3.auth.oauth ? { source: "OAuth", type: "oauth" } : void 0;
}
const apiKey = provider3.auth.apiKey;
if (!apiKey)
return void 0;
if (apiKey.check) {
try {
return await apiKey.check({
ctx: this.authContext,
credential: credential?.type === "api_key" ? credential : void 0,
signal
});
} catch (error) {
throw new ModelsError("auth", `API key auth check failed for provider ${provider3.id}`, { cause: error });
}
}
const resolution = await resolveProviderAuth(provider3, this.credentials, this.authContext, { signal });
return resolution ? { source: resolution.source, type: "api_key" } : void 0;
}
checkAuth(providerId, options) {
const signal = operationSignal(options?.signal);
const check = (async () => {
signal.throwIfAborted();
const provider3 = this.providers.get(providerId);
if (!provider3)
return void 0;
return this.checkProviderAuth(provider3, await this.readCredential(providerId, signal), signal);
})();
return raceWithAbortSignal(check, signal);
}
async getAuthenticatedProviders(providerId, signal) {
signal.throwIfAborted();
const providers = providerId ? [this.providers.get(providerId)].filter((entry2) => entry2 !== void 0) : this.getProviders();
const checks = await Promise.all(providers.map(async (provider3) => {
const credential = await this.readCredential(provider3.id, signal);
return { provider: provider3, credential, auth: await this.checkProviderAuth(provider3, credential, signal) };
}));
return checks.filter((entry2) => entry2.auth !== void 0);
}
getAvailable(providerId, options) {
const signal = operationSignal(options?.signal);
const available = (async () => {
const providers = await this.getAuthenticatedProviders(providerId, signal);
return providers.flatMap(({ provider: provider3, credential }) => {
const models2 = provider3.getModels();
return provider3.filterModels?.(models2, credential) ?? models2;
});
})();
return raceWithAbortSignal(available, signal);
}
async getAvailableOfType(type, providerId, options) {
return (await this.getAllAvailable(providerId, options)).filter((model3) => isModelType(model3, type));
}
getAllAvailable(providerId, options) {
const signal = operationSignal(options?.signal);
const available = (async () => {
const providers = await this.getAuthenticatedProviders(providerId, signal);
return providers.flatMap(({ provider: provider3, credential }) => {
const models2 = provider3.getAllModels?.() ?? provider3.getModels();
if (provider3.filterAllModels)
return provider3.filterAllModels(models2, credential);
if (!provider3.filterModels)
return models2;
const availableChatIds = new Set(provider3.filterModels(provider3.getModels(), credential).map((model3) => model3.id));
return models2.filter((model3) => !isModelType(model3, "chat") || availableChatIds.has(model3.id));
});
})();
return raceWithAbortSignal(available, signal);
}
async getAuth(providerOrModel, overrides) {
const signal = operationSignal(overrides?.signal);
const providerId = typeof providerOrModel === "string" ? providerOrModel : providerOrModel.provider;
const provider3 = this.providers.get(providerId);
if (!provider3)
return void 0;
const result = await resolveProviderAuth(provider3, this.credentials, this.authContext, { ...overrides, signal });
if (!result || typeof providerOrModel === "string" || !providerOrModel.headers)
return result;
return {
...result,
auth: {
...result.auth,
headers: mergeHeaders(result.auth.headers, providerOrModel.headers)
}
};
}
async login(providerId, type, interaction, options) {
const signal = operationSignal(interaction.signal);
signal.throwIfAborted();
const provider3 = this.providers.get(providerId);
if (!provider3)
throw new ModelsError("provider", `Unknown provider: ${providerId}`);
const method = type === "oauth" ? provider3.auth.oauth : provider3.auth.apiKey;
if (!method?.login) {
throw new ModelsError("auth", `${provider3.name} does not support ${type} login`);
}
const loginOperation = method.login({ ...interaction, signal }, options);
const credential = await raceWithAbortSignal(loginOperation, signal);
let mutationStarted = false;
let markMutationStarted;
const started = new Promise((resolve2) => {
markMutationStarted = resolve2;
});
const mutation = this.credentials.modify(providerId, async () => {
mutationStarted = true;
markMutationStarted?.();
return credential;
}, { signal });
void mutation.catch(() => {
});
try {
await new Promise((resolve2, reject2) => {
const onAbort = () => {
if (!mutationStarted)
reject2(signal.reason);
};
signal.addEventListener("abort", onAbort, { once: true });
void Promise.race([started, mutation]).then(() => {
signal.removeEventListener("abort", onAbort);
resolve2();
}, (error) => {
signal.removeEventListener("abort", onAbort);
reject2(error);
});
if (signal.aborted)
onAbort();
});
await mutation;
} catch (error) {
signal.throwIfAborted();
throw new ModelsError("auth", `Credential store modify failed for ${providerId}`, { cause: error });
}
return credential;
}
async logout(providerId, options) {
const signal = operationSignal(options?.signal);
signal.throwIfAborted();
try {
await this.credentials.delete(providerId, { signal });
} catch (error) {
signal.throwIfAborted();
throw new ModelsError("auth", `Credential store delete failed for ${providerId}`, { cause: error });
}
}
requireProvider(model3) {
const provider3 = this.providers.get(model3.provider);
if (!provider3) {
throw new ModelsError("provider", `Unknown provider: ${model3.provider}`);
}
return provider3;
}
requireChatProvider(model3) {
assertChatModel(model3);
return this.requireProvider(model3);
}
async applyAuth(model3, options) {
this.requireProvider(model3);
const resolution = await this.getAuth(model3, {
apiKey: options?.apiKey,
env: options?.env,
signal: options?.signal
});
if (!resolution) {
throw new ModelsError("auth", `Provider is not configured: ${model3.provider}`);
}
const auth = resolution.auth;
const apiKey = options?.apiKey ?? auth.apiKey;
const requestModel = auth.baseUrl ? { ...model3, baseUrl: auth.baseUrl } : model3;
const sessionId = options && "sessionId" in options && typeof options.sessionId === "string" ? options.sessionId : void 0;
let headers = mergeHeaders(mergeHeaders(getOpenCodeSessionHeaders(requestModel, sessionId), auth.headers), options?.headers);
if (options?.transformHeaders)
headers = await options.transformHeaders(headers ?? {});
const env = resolution.env || options?.env ? { ...resolution.env ?? {}, ...options?.env ?? {} } : void 0;
const identity = mergeClientIdentity(this.identity, options?.identity);
const { transformHeaders: _transformHeaders, ...providerOptions } = options ?? {};
const requestOptions = {
...providerOptions,
apiKey,
headers,
env,
...identity === void 0 ? {} : { identity }
};
return { requestModel, requestOptions };
}
stream(model3, context, options) {
const transcript = normalizeContext(context);
return lazyStream(model3, async () => {
const provider3 = this.requireChatProvider(model3);
const { requestModel, requestOptions } = await this.applyAuth(model3, options);
return provider3.stream(requestModel, transcript, requestOptions);
}, observeModelRequest(model3, options, false));
}
async complete(model3, context, options) {
return this.stream(model3, context, options).result();
}
streamSimple(model3, context, options) {
const transcript = normalizeContext(context);
return lazyStream(model3, async () => {
const provider3 = this.requireChatProvider(model3);
const { requestModel, requestOptions } = await this.applyAuth(model3, options);
return provider3.streamSimple(requestModel, transcript, requestOptions);
}, observeModelRequest(model3, options, false));
}
async completeSimple(model3, context, options) {
return this.streamSimple(model3, context, options).result();
}
streamDeferred(model3, handle, options) {
return lazyStream(model3, async () => {
const provider3 = this.requireChatProvider(model3);
if (!provider3.fetchDeferred) {
throw new ModelsError("provider", `Provider ${model3.provider} does not support deferred responses`);
}
const { requestModel, requestOptions } = await this.applyAuth(model3, options);
return provider3.fetchDeferred(requestModel, handle, requestOptions);
}, observeModelRequest(model3, options, true));
}
async fetchDeferred(model3, handle, options) {
return this.streamDeferred(model3, handle, options).result();
}
async cancelDeferred(model3, handle, options) {
const provider3 = this.requireChatProvider(model3);
if (!provider3.cancelDeferred) {
throw new ModelsError("provider", `Provider ${model3.provider} does not support deferred responses`);
}
const { requestModel, requestOptions } = await this.applyAuth(model3, options);
await provider3.cancelDeferred(requestModel, handle, requestOptions);
}
async generateImages(model3, context, options) {
try {
assertImageModel(model3);
const provider3 = this.requireProvider(model3);
if (!provider3.generateImages) {
throw new ModelsError("provider", `Provider ${model3.provider} does not support image generation`);
}
const { requestModel, requestOptions } = await this.applyAuth(model3, options);
return await provider3.generateImages(requestModel, context, requestOptions);
} catch (error) {
return imageErrorResult(model3, error, options?.signal?.aborted);
}
}
async classify(model3, context, options) {
try {
assertClassifierModel(model3);
assertClassifierInputSupported(model3, context);
const provider3 = this.requireProvider(model3);
if (!provider3.classify) {
throw new ModelsError("provider", `Provider ${model3.provider} does not support classification`);
}
const { requestModel, requestOptions } = await this.applyAuth(model3, options);
return await provider3.classify(requestModel, context, requestOptions);
} catch (error) {
return classifierErrorResult(model3, error, options?.signal?.aborted);
}
}
};
EXTENDED_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/error-body.js
function normalizeProviderError(error) {
if (!(error instanceof Error)) {
return { message: safeJsonStringify(error), messageCarriesBody: false };
}
const sdkError = error;
const status = extractStatus(sdkError);
const body = extractBody(sdkError);
const messageCarriesBody = body === void 0 || error.message.includes(body);
return {
status,
body,
message: error.message,
messageCarriesBody
};
}
function extractStatus(error) {
if (typeof error.statusCode === "number")
return error.statusCode;
if (typeof error.status === "number")
return error.status;
if (typeof error.$metadata?.httpStatusCode === "number")
return error.$metadata.httpStatusCode;
if (typeof error.$response?.statusCode === "number")
return error.$response.statusCode;
return void 0;
}
function extractBody(error) {
const bodyText = pickBodyText(error);
if (bodyText === void 0)
return void 0;
const trimmed = bodyText.trim();
if (trimmed.length === 0)
return void 0;
return truncateErrorText(trimmed, MAX_PROVIDER_ERROR_BODY_CHARS);
}
function pickBodyText(error) {
if (typeof error.body === "string")
return error.body;
if (isPlainNonEmptyObject(error.error))
return safeJsonStringify(error.error);
const responseBody = error.$response?.body;
if (typeof responseBody === "string")
return responseBody;
if (isReadableStreamLike(responseBody))
return void 0;
if (isPlainNonEmptyObject(responseBody))
return safeJsonStringify(responseBody);
return void 0;
}
function isReadableStreamLike(value2) {
return typeof value2 === "object" && value2 !== null && "pipe" in value2 && typeof value2.pipe === "function";
}
function isPlainNonEmptyObject(value2) {
if (typeof value2 !== "object" || value2 === null)
return false;
const proto = Object.getPrototypeOf(value2);
if (proto !== Object.prototype && proto !== null)
return false;
return Object.keys(value2).length > 0;
}
function formatProviderError(norm, prefix) {
if (norm.messageCarriesBody || norm.status === void 0 || norm.body === void 0) {
return prefix !== void 0 && norm.status !== void 0 ? `${prefix} (${norm.status}): ${norm.message}` : norm.message;
}
return prefix !== void 0 ? `${prefix} (${norm.status}): ${norm.body}` : `${norm.status}: ${norm.body}`;
}
function truncateErrorText(text2, maxChars) {
if (text2.length <= maxChars)
return text2;
return `${ownedSlice(text2, 0, maxChars)}... [truncated ${text2.length - maxChars} chars]`;
}
function safeJsonStringify(value2) {
try {
const serialized = JSON.stringify(value2);
return serialized === void 0 ? String(value2) : serialized;
} catch {
return String(value2);
}
}
var MAX_PROVIDER_ERROR_BODY_CHARS;
var init_error_body = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/error-body.js"() {
init_text();
MAX_PROVIDER_ERROR_BODY_CHARS = 4e3;
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/headers.js
function headersToRecord(headers) {
const result = {};
for (const [key, value2] of headers.entries()) {
result[key] = value2;
}
return result;
}
function providerHeadersToRecord(...headerSources) {
const merged = /* @__PURE__ */ new Map();
for (const source of headerSources) {
for (const [name, value2] of Object.entries(source ?? {})) {
const normalizedName = name.toLowerCase();
merged.delete(normalizedName);
if (value2 !== null)
merged.set(normalizedName, [name, value2]);
}
}
return merged.size > 0 ? Object.fromEntries(merged.values()) : void 0;
}
var init_headers = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/headers.js"() {
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/provider-retry.js
function isProviderError(error) {
if (!(error instanceof Error) || !("status" in error) || !("headers" in error))
return false;
return (error.status === void 0 || typeof error.status === "number") && (error.headers === void 0 || error.headers instanceof Headers);
}
function isRetryableProviderError(error) {
const shouldRetry = error.headers?.get("x-should-retry");
if (shouldRetry === "true")
return true;
if (shouldRetry === "false")
return false;
if (error.status === void 0)
return true;
return error.status === 408 || error.status === 409 || error.status === 429 || typeof error.status === "number" && error.status >= 500;
}
function validateServerRetryDelayMs(delayMs, maxRetryDelayMs, providerErrorMessage) {
const maxDelayMs = maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
if (maxDelayMs > 0 && delayMs > maxDelayMs) {
throw new Error(`Server requested ${Math.ceil(delayMs / 1e3)}s retry delay (max: ${Math.ceil(maxDelayMs / 1e3)}s). ${providerErrorMessage}`);
}
return delayMs;
}
function getRetryDelayMs(error, retryIndex, maxRetryDelayMs) {
const retryAfterMs = error.headers?.get("retry-after-ms");
if (retryAfterMs) {
const value2 = Number.parseFloat(retryAfterMs);
if (Number.isFinite(value2))
return validateServerRetryDelayMs(value2, maxRetryDelayMs, error.message);
}
const retryAfter = error.headers?.get("retry-after");
if (retryAfter) {
const seconds = Number.parseFloat(retryAfter);
const delayMs = Number.isNaN(seconds) ? Date.parse(retryAfter) - Date.now() : seconds * 1e3;
if (Number.isFinite(delayMs))
return validateServerRetryDelayMs(delayMs, maxRetryDelayMs, error.message);
}
const exponentialDelay = Math.min(0.5 * 2 ** retryIndex, 8) * 1e3;
return exponentialDelay * (1 - Math.random() * 0.25);
}
function createAbortError() {
const error = new Error("Request aborted");
error.name = "AbortError";
return error;
}
function abortableSleep(ms, signal) {
return new Promise((resolve2, reject2) => {
if (signal?.aborted) {
reject2(createAbortError());
return;
}
const onAbort = () => {
clearTimeout(timeout);
reject2(createAbortError());
};
const timeout = setTimeout(() => {
signal?.removeEventListener("abort", onAbort);
resolve2();
}, Math.max(0, ms));
signal?.addEventListener("abort", onAbort, { once: true });
});
}
async function retryProviderRequest(request2, options = {}) {
const maxRetries = options.maxRetries ?? 0;
let retriesRemaining = maxRetries;
for (; ; ) {
try {
return await request2();
} catch (error) {
if (options.signal?.aborted)
throw createAbortError();
if (retriesRemaining <= 0 || !isProviderError(error) || !isRetryableProviderError(error))
throw error;
if (error.status !== void 0 && options.noRetryStatuses?.includes(error.status))
throw error;
const retryIndex = maxRetries - retriesRemaining;
retriesRemaining--;
await abortableSleep(getRetryDelayMs(error, retryIndex, options.maxRetryDelayMs), options.signal);
}
}
}
var DEFAULT_MAX_RETRY_DELAY_MS;
var init_provider_retry = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/provider-retry.js"() {
DEFAULT_MAX_RETRY_DELAY_MS = 6e4;
}
});
// node_modules/@earendil-works/pi-ai/dist/api/classifier-shared.js
function httpError(label, response, body) {
const error = new Error(`${label} returned ${response.status}`);
error.status = response.status;
error.headers = response.headers;
error.body = body;
return error;
}
function timeoutError(timeoutMs) {
const error = new Error(`Request timed out after ${timeoutMs}ms`);
error.name = "TimeoutError";
error.status = void 0;
error.headers = void 0;
error.body = "";
return error;
}
function isRecord(value2) {
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
}
function requiredNumber(label, value2, field) {
if (typeof value2 !== "number" || !Number.isFinite(value2)) {
throw new Error(`${label} returned an invalid ${field}`);
}
return value2;
}
function requestHeaders(model3, apiKey, optionsHeaders, identity) {
return providerHeadersToRecord(getIdentityHeaders(model3, identity), { authorization: `Bearer ${apiKey}`, "content-type": "application/json" }, model3.headers, optionsHeaders) ?? {};
}
async function postClassifierRequest(label, url, model3, body, options, noRetryStatuses) {
if (!options?.apiKey)
throw new Error(`No API key for provider: ${model3.provider}`);
const apiKey = options.apiKey;
let payload = body;
const transformed = await options.onPayload?.(payload, model3);
if (transformed !== void 0)
payload = transformed;
const requestFetch = options.fetch ?? globalThis.fetch;
const { response, json } = await retryProviderRequest(async () => {
const timeoutSignal = options.timeoutMs !== void 0 ? AbortSignal.timeout(options.timeoutMs) : void 0;
const signal = options.signal && timeoutSignal ? AbortSignal.any([options.signal, timeoutSignal]) : options.signal ?? timeoutSignal;
try {
const next = await requestFetch(url, {
method: "POST",
headers: requestHeaders(model3, apiKey, options.headers, options.identity),
body: JSON.stringify(payload),
signal
});
if (!next.ok)
throw httpError(label, next, await next.text());
return { response: next, json: await next.json() };
} catch (error) {
if (timeoutSignal?.aborted && !options.signal?.aborted)
throw timeoutError(options.timeoutMs);
throw error;
}
}, {
maxRetries: options.maxRetries ?? 2,
maxRetryDelayMs: options.maxRetryDelayMs,
signal: options.signal,
noRetryStatuses
});
await options.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model3);
return json;
}
function tokenCount(value2) {
return typeof value2 === "number" && Number.isFinite(value2) && value2 > 0 ? value2 : 0;
}
function parseClassifierUsage(value2, model3) {
if (!isRecord(value2) || value2.input_tokens === void 0 && value2.output_tokens === void 0)
return void 0;
const input = tokenCount(value2.input_tokens);
const output = tokenCount(value2.output_tokens);
const usage = {
input,
output,
cacheRead: 0,
cacheWrite: 0,
totalTokens: input + output,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
};
calculateCost(model3, usage);
return usage;
}
var init_classifier_shared = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/classifier-shared.js"() {
init_models();
init_headers();
init_identity();
init_provider_retry();
}
});
// node_modules/@earendil-works/pi-ai/dist/api/openai-decisions.js
var openai_decisions_exports = {};
__export(openai_decisions_exports, {
classify: () => classify
});
function predicateInstructions(question) {
const meanings = [
question.criteria.true ? `True means: ${question.criteria.true}` : "",
question.criteria.false ? `False means: ${question.criteria.false}` : ""
].filter(Boolean);
return meanings.length > 0 ? `${question.instructions}
${meanings.join("\n")}` : question.instructions;
}
function wireQuestion(name, question) {
if (question.type === "choice") {
return {
type: "choice",
name,
instructions: question.instructions,
choices: Object.entries(question.criteria).map(([value2, description]) => description ? { value: value2, description } : { value: value2 })
};
}
if (question.type === "score") {
return {
type: "score",
name,
instructions: question.instructions,
levels: question.criteria.map((label) => ({ label }))
};
}
return { type: "predicate", name, instructions: predicateInstructions(question) };
}
function wireInput(context) {
const state2 = JSON.stringify(context.state);
const images = context.images ?? [];
if (images.length === 0)
return state2;
if (images.length > MAX_IMAGES) {
throw new Error(`${LABEL} accepts at most ${MAX_IMAGES} images, got ${images.length}`);
}
return [
{
role: "user",
content: [
{ type: "input_text", text: state2 },
...images.map((image) => ({
type: "input_image",
image_url: `data:${image.mimeType};base64,${image.data}`
}))
]
}
];
}
function choiceProbabilities(value2, id) {
if (!Array.isArray(value2))
throw new Error(`${LABEL} returned invalid probabilities for ${id}`);
return Object.fromEntries(value2.map((entry2) => {
if (!isRecord(entry2) || typeof entry2.value !== "string") {
throw new Error(`${LABEL} returned invalid probabilities for ${id}`);
}
return [entry2.value, requiredNumber(LABEL, entry2.probability, `probability for ${id}.${entry2.value}`)];
}));
}
function parseAnswer(id, question, answer2) {
if (answer2.type === "refusal")
throw new Error(`${LABEL} refused to answer ${id}`);
if (question.type === "choice") {
if (answer2.type !== "choice" || typeof answer2.choice !== "string") {
throw new Error(`${LABEL} did not return a choice answer for ${id}`);
}
return {
type: "choice",
choice: answer2.choice,
probabilities: choiceProbabilities(answer2.probabilities, id),
confidence: requiredNumber(LABEL, answer2.confidence, `confidence for ${id}`)
};
}
if (question.type === "score") {
if (answer2.type !== "score")
throw new Error(`${LABEL} did not return a score answer for ${id}`);
return {
type: "score",
score: requiredNumber(LABEL, answer2.score, `score for ${id}`),
confidence: requiredNumber(LABEL, answer2.confidence, `confidence for ${id}`)
};
}
if (answer2.type !== "predicate")
throw new Error(`${LABEL} did not return a predicate answer for ${id}`);
return { type: "bool", probability: requiredNumber(LABEL, answer2.probability, `probability for ${id}`) };
}
function parseAnswers(value2, context) {
if (!Array.isArray(value2))
throw new Error(`${LABEL} returned an unexpected response`);
const byName = /* @__PURE__ */ new Map();
for (const answer2 of value2) {
if (isRecord(answer2) && typeof answer2.name === "string")
byName.set(answer2.name, answer2);
}
return Object.fromEntries(Object.entries(context.questions).map(([id, question]) => {
const answer2 = byName.get(id);
if (!answer2)
throw new Error(`${LABEL} did not return an answer for ${id}`);
return [id, parseAnswer(id, question, answer2)];
}));
}
function errorMessage(error) {
if (error.status === 504) {
return `${LABEL} error (504): the request timed out at the gateway. Very large inputs (above roughly 600K tokens) currently exceed its time limit.`;
}
return formatProviderError(normalizeProviderError(error), `${LABEL} error`);
}
var LABEL, MAX_IMAGES, NO_RETRY_STATUSES, classify;
var init_openai_decisions = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/openai-decisions.js"() {
init_error_body();
init_classifier_shared();
LABEL = "OpenAI Decisions";
MAX_IMAGES = 128;
NO_RETRY_STATUSES = [504];
classify = async (model3, context, options) => {
const output = {
api: model3.api,
provider: model3.provider,
model: model3.id,
answers: {},
stopReason: "stop",
timestamp: Date.now()
};
try {
if (model3.api !== "openai-decisions")
throw new Error(`Unsupported classifier API: ${model3.api}`);
const body = await postClassifierRequest(LABEL, new URL("decisions", `${model3.baseUrl.replace(/\/+$/u, "")}/`), model3, {
model: model3.id,
input: wireInput(context),
questions: Object.entries(context.questions).map(([id, question]) => wireQuestion(id, question))
}, options, NO_RETRY_STATUSES);
if (!isRecord(body))
throw new Error(`${LABEL} returned an unexpected response`);
const usage = parseClassifierUsage(body.usage, model3);
if (usage)
output.usage = usage;
output.answers = parseAnswers(body.answers, context);
return output;
} catch (error) {
output.answers = {};
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
output.errorMessage = errorMessage(error);
return output;
}
};
}
});
// node_modules/openai/internal/tslib.mjs
function __classPrivateFieldSet(receiver, state2, value2, kind, f) {
if (kind === "m")
throw new TypeError("Private method is not writable");
if (kind === "a" && !f)
throw new TypeError("Private accessor was defined without a setter");
if (typeof state2 === "function" ? receiver !== state2 || !f : !state2.has(receiver))
throw new TypeError("Cannot write private member to an object whose class did not declare it");
return kind === "a" ? f.call(receiver, value2) : f ? f.value = value2 : state2.set(receiver, value2), value2;
}
function __classPrivateFieldGet(receiver, state2, kind, f) {
if (kind === "a" && !f)
throw new TypeError("Private accessor was defined without a getter");
if (typeof state2 === "function" ? receiver !== state2 || !f : !state2.has(receiver))
throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state2.get(receiver);
}
var init_tslib = __esm({
"node_modules/openai/internal/tslib.mjs"() {
}
});
// node_modules/openai/internal/utils/uuid.mjs
var uuid4;
var init_uuid = __esm({
"node_modules/openai/internal/utils/uuid.mjs"() {
uuid4 = function() {
const { crypto: crypto2 } = globalThis;
if (crypto2?.randomUUID) {
uuid4 = crypto2.randomUUID.bind(crypto2);
return crypto2.randomUUID();
}
const u8 = new Uint8Array(1);
const randomByte = crypto2 ? () => crypto2.getRandomValues(u8)[0] : () => Math.random() * 255 & 255;
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c) => (+c ^ randomByte() & 15 >> +c / 4).toString(16));
};
}
});
// node_modules/openai/internal/errors.mjs
function isAbortError(err) {
return typeof err === "object" && err !== null && // Spec-compliant fetch implementations
("name" in err && err.name === "AbortError" || // Expo fetch
"message" in err && String(err.message).includes("FetchRequestCanceledException"));
}
var castToError;
var init_errors = __esm({
"node_modules/openai/internal/errors.mjs"() {
castToError = (err) => {
if (err instanceof Error)
return err;
if (typeof err === "object" && err !== null) {
try {
if (Object.prototype.toString.call(err) === "[object Error]") {
const hasCause = "cause" in err;
const error = new Error(err.message, hasCause ? { cause: err.cause } : {});
if (err.stack)
error.stack = err.stack;
if (hasCause && !Object.prototype.hasOwnProperty.call(error, "cause"))
error.cause = err.cause;
if (err.name)
error.name = err.name;
return error;
}
} catch {
}
try {
return new Error(JSON.stringify(err));
} catch {
}
}
return new Error(err);
};
}
});
// node_modules/openai/core/error.mjs
var OpenAIError, APIError, APIUserAbortError, APIConnectionError, APIConnectionTimeoutError, BadRequestError, AuthenticationError, PermissionDeniedError, NotFoundError, ConflictError, UnprocessableEntityError, RateLimitError, InternalServerError, LengthFinishReasonError, ContentFilterFinishReasonError, InvalidWebhookSignatureError, OAuthError, SubjectTokenProviderError;
var init_error = __esm({
"node_modules/openai/core/error.mjs"() {
init_errors();
OpenAIError = class extends Error {
};
APIError = class _APIError extends OpenAIError {
constructor(status, error, message, headers) {
super(`${_APIError.makeMessage(status, error, message)}`);
this.status = status;
this.headers = headers;
this.requestID = headers?.get("x-request-id");
this.error = error;
const data = error;
this.code = data?.["code"];
this.param = data?.["param"];
this.type = data?.["type"];
}
static makeMessage(status, error, message) {
const msg = error?.message ? typeof error.message === "string" ? error.message : JSON.stringify(error.message) : error ? JSON.stringify(error) : message;
if (status && msg) {
return `${status} ${msg}`;
}
if (status) {
return `${status} status code (no body)`;
}
if (msg) {
return msg;
}
return "(no status code or body)";
}
static generate(status, errorResponse, message, headers) {
if (!status || !headers) {
return new APIConnectionError({ message, cause: castToError(errorResponse) });
}
const error = errorResponse?.["error"];
if (status === 400) {
return new BadRequestError(status, error, message, headers);
}
if (status === 401) {
return new AuthenticationError(status, error, message, headers);
}
if (status === 403) {
return new PermissionDeniedError(status, error, message, headers);
}
if (status === 404) {
return new NotFoundError(status, error, message, headers);
}
if (status === 409) {
return new ConflictError(status, error, message, headers);
}
if (status === 422) {
return new UnprocessableEntityError(status, error, message, headers);
}
if (status === 429) {
return new RateLimitError(status, error, message, headers);
}
if (status >= 500) {
return new InternalServerError(status, error, message, headers);
}
return new _APIError(status, error, message, headers);
}
};
APIUserAbortError = class extends APIError {
constructor({ message } = {}) {
super(void 0, void 0, message || "Request was aborted.", void 0);
}
};
APIConnectionError = class extends APIError {
constructor({ message, cause }) {
super(void 0, void 0, message || "Connection error.", void 0);
if (cause)
this.cause = cause;
}
};
APIConnectionTimeoutError = class extends APIConnectionError {
constructor({ message } = {}) {
super({ message: message ?? "Request timed out." });
}
};
BadRequestError = class extends APIError {
};
AuthenticationError = class extends APIError {
};
PermissionDeniedError = class extends APIError {
};
NotFoundError = class extends APIError {
};
ConflictError = class extends APIError {
};
UnprocessableEntityError = class extends APIError {
};
RateLimitError = class extends APIError {
};
InternalServerError = class extends APIError {
};
LengthFinishReasonError = class extends OpenAIError {
constructor() {
super(`Could not parse response content as the length limit was reached`);
}
};
ContentFilterFinishReasonError = class extends OpenAIError {
constructor() {
super(`Could not parse response content as the request was rejected by the content filter`);
}
};
InvalidWebhookSignatureError = class extends Error {
constructor(message) {
super(message);
}
};
OAuthError = class extends APIError {
constructor(status, error, headers) {
let finalMessage = "OAuth2 authentication error";
let error_code = void 0;
if (error && typeof error === "object") {
const errorData = error;
error_code = errorData["error"];
const description = errorData["error_description"];
if (description && typeof description === "string") {
finalMessage = description;
} else if (error_code) {
finalMessage = error_code;
}
}
super(status, error, finalMessage, headers);
this.error_code = error_code;
}
};
SubjectTokenProviderError = class extends OpenAIError {
constructor(message, provider3, cause) {
super(message);
this.provider = provider3;
this.cause = cause;
}
};
}
});
// node_modules/openai/internal/utils/values.mjs
function maybeObj(x) {
if (typeof x !== "object") {
return {};
}
return x ?? {};
}
function isEmptyObj(obj2) {
if (!obj2)
return true;
for (const _k in obj2)
return false;
return true;
}
function hasOwn(obj2, key) {
return Object.prototype.hasOwnProperty.call(obj2, key);
}
function isObj(obj2) {
return obj2 != null && typeof obj2 === "object" && !Array.isArray(obj2);
}
var startsWithSchemeRegexp, isAbsoluteURL, isArray, isReadonlyArray, validatePositiveInteger, safeJSON;
var init_values = __esm({
"node_modules/openai/internal/utils/values.mjs"() {
init_error();
startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;
isAbsoluteURL = (url) => {
return startsWithSchemeRegexp.test(url);
};
isArray = (val) => (isArray = Array.isArray, isArray(val));
isReadonlyArray = isArray;
validatePositiveInteger = (name, n) => {
if (typeof n !== "number" || !Number.isInteger(n)) {
throw new OpenAIError(`${name} must be an integer`);
}
if (n < 0) {
throw new OpenAIError(`${name} must be a positive integer`);
}
return n;
};
safeJSON = (text2) => {
try {
return JSON.parse(text2);
} catch (err) {
return void 0;
}
};
}
});
// node_modules/openai/internal/utils/sleep.mjs
var sleep;
var init_sleep = __esm({
"node_modules/openai/internal/utils/sleep.mjs"() {
sleep = (ms, ...signals) => new Promise((resolve2, reject2) => {
const activeSignals = [...new Set(signals.filter((signal) => signal != null))];
let timeout;
let settled = false;
const cleanup = () => {
for (const signal of activeSignals) {
try {
signal.removeEventListener("abort", abort);
} catch {
}
}
};
const settle3 = (callback) => {
if (settled) {
return;
}
settled = true;
if (timeout !== void 0) {
clearTimeout(timeout);
timeout = void 0;
}
cleanup();
callback();
};
const abort = () => {
settle3(() => reject2());
};
if (activeSignals.some((signal) => signal.aborted)) {
abort();
return;
}
timeout = setTimeout(() => {
settle3(resolve2);
}, ms);
for (const signal of activeSignals) {
if (settled) {
break;
}
try {
signal.addEventListener("abort", abort, { once: true });
} catch (error) {
settle3(() => reject2(error));
}
}
if (activeSignals.some((signal) => signal.aborted)) {
abort();
}
});
}
});
// node_modules/openai/internal/utils/abort.mjs
function subscribeWeakly(signal, reference, registry2) {
let subscription = subscriptions.get(signal);
if (!subscription) {
const callbacks = /* @__PURE__ */ new Set();
const abort = () => {
subscriptions.delete(signal);
for (const callback of callbacks) {
registry2.unregister(callback);
callback.deref()?.();
}
callbacks.clear();
};
subscription = { callbacks, abort };
signal.addEventListener("abort", abort, { once: true });
subscriptions.set(signal, subscription);
}
const owner = subscription;
owner.callbacks.add(reference);
return () => {
owner.callbacks.delete(reference);
registry2.unregister(reference);
if (owner.callbacks.size === 0) {
if (subscriptions.get(signal) === owner) {
subscriptions.delete(signal);
}
signal.removeEventListener("abort", owner.abort);
}
};
}
function releaseOnAbort(signal, callbacks, abort) {
signal.addEventListener("abort", () => callbacks.deref()?.delete(abort), { once: true });
}
function retainRequestAbortCallback(owner, abort, requestSignal) {
if (typeof weakGlobals.WeakRef === "function" && finalizer && !requestSignal.aborted) {
let callbacks = callbackOwners.get(owner);
if (!callbacks) {
callbacks = /* @__PURE__ */ new Set();
callbackOwners.set(owner, callbacks);
}
callbacks.add(abort);
releaseOnAbort(requestSignal, new weakGlobals.WeakRef(callbacks), abort);
}
}
function addRequestAbortListener(signal, abort, requestSignal) {
if (signal.aborted) {
abort();
return () => {
};
}
if (typeof weakGlobals.WeakRef !== "function" || !finalizer) {
signal.addEventListener("abort", abort, { once: true });
return () => signal.removeEventListener("abort", abort);
}
const reference = new weakGlobals.WeakRef(abort);
const cleanup = subscribeWeakly(signal, reference, finalizer);
finalizer.register(abort, cleanup, reference);
retainRequestAbortCallback(requestSignal, abort, requestSignal);
return cleanup;
}
var weakGlobals, finalizer, callbackOwners, subscriptions;
var init_abort2 = __esm({
"node_modules/openai/internal/utils/abort.mjs"() {
weakGlobals = globalThis;
finalizer = // oxlint-disable-next-line anti-slop/no-runtime-typeof -- Weak references and finalizers are optional host capabilities, so probe them before constructing either.
typeof weakGlobals.FinalizationRegistry === "function" ? new weakGlobals.FinalizationRegistry((cleanup) => {
try {
cleanup();
} catch {
}
}) : void 0;
callbackOwners = /* @__PURE__ */ new WeakMap();
subscriptions = /* @__PURE__ */ new WeakMap();
}
});
// node_modules/openai/internal/shims.mjs
function getDefaultFetch() {
if (typeof fetch !== "undefined") {
return fetch;
}
throw new Error("`fetch` is not defined as a global; Either pass `fetch` to the client, `new OpenAI({ fetch })` or polyfill the global, `globalThis.fetch = fetch`");
}
function makeReadableStream(...args) {
const ReadableStream2 = globalThis.ReadableStream;
if (typeof ReadableStream2 === "undefined") {
throw new Error("`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`");
}
return new ReadableStream2(...args);
}
function ReadableStreamFrom(iterable) {
let iter = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
return makeReadableStream({
start() {
},
async pull(controller) {
const { done, value: value2 } = await iter.next();
if (done) {
controller.close();
} else {
controller.enqueue(value2);
}
},
async cancel() {
await iter.return?.();
}
});
}
function ReadableStreamToAsyncIterable(stream2) {
if (stream2[Symbol.asyncIterator])
return stream2;
const reader = stream2.getReader();
return {
async next() {
try {
const result = await reader.read();
if (result?.done)
reader.releaseLock();
return result;
} catch (e) {
reader.releaseLock();
throw e;
}
},
async return() {
const cancelPromise = reader.cancel();
reader.releaseLock();
await cancelPromise;
return { done: true, value: void 0 };
},
[Symbol.asyncIterator]() {
return this;
}
};
}
async function CancelReadableStream(stream2) {
if (stream2 === null || typeof stream2 !== "object")
return;
if (stream2[Symbol.asyncIterator]) {
await stream2[Symbol.asyncIterator]().return?.();
return;
}
const reader = stream2.getReader();
const cancelPromise = reader.cancel();
reader.releaseLock();
await cancelPromise;
}
var init_shims = __esm({
"node_modules/openai/internal/shims.mjs"() {
}
});
// node_modules/openai/internal/utils/bytes.mjs
function encodeUTF8(str2) {
let encoder3;
return (encodeUTF8_ ?? (encoder3 = new globalThis.TextEncoder(), encodeUTF8_ = encoder3.encode.bind(encoder3)))(str2);
}
function decodeUTF8(bytes2) {
let decoder2;
return (decodeUTF8_ ?? (decoder2 = new globalThis.TextDecoder(), decodeUTF8_ = decoder2.decode.bind(decoder2)))(bytes2);
}
var encodeUTF8_, decodeUTF8_;
var init_bytes = __esm({
"node_modules/openai/internal/utils/bytes.mjs"() {
}
});
// node_modules/openai/internal/decoders/line.mjs
function findNewlineIndex(buffer, start, end) {
const newline = 10;
const carriage = 13;
for (let i = start; i < end; i++) {
if (buffer[i] === newline) {
return { preceding: i, index: i + 1, carriage: false };
}
if (buffer[i] === carriage) {
return { preceding: i, index: i + 1, carriage: true };
}
}
return null;
}
function findDoubleNewlineIndex(buffer) {
for (let i = 0; i < buffer.length - 1; i++) {
const firstEndingLength = lineEndingLength(buffer, i);
if (firstEndingLength > 0) {
const secondEndingIndex = i + firstEndingLength;
const secondEndingLength = lineEndingLength(buffer, secondEndingIndex);
if (secondEndingLength > 0) {
return secondEndingIndex + secondEndingLength;
}
}
}
return -1;
}
function lineEndingLength(buffer, index) {
const newline = 10;
const carriage = 13;
if (buffer[index] === newline) {
return 1;
}
if (buffer[index] === carriage) {
return buffer[index + 1] === newline ? 2 : 1;
}
return 0;
}
var _LineDecoder_instances, _LineDecoder_buffer, _LineDecoder_start, _LineDecoder_end, _LineDecoder_searchIndex, _LineDecoder_skipLeadingLF, _LineDecoder_append, MAX_RETAINED_BUFFER_BYTES, LineDecoder;
var init_line = __esm({
"node_modules/openai/internal/decoders/line.mjs"() {
init_tslib();
init_bytes();
MAX_RETAINED_BUFFER_BYTES = 64 * 1024;
LineDecoder = class {
/** Creates a decoder with no buffered bytes or pending newline continuation. */
constructor() {
_LineDecoder_instances.add(this);
_LineDecoder_buffer.set(this, void 0);
_LineDecoder_start.set(this, void 0);
_LineDecoder_end.set(this, void 0);
_LineDecoder_searchIndex.set(this, void 0);
_LineDecoder_skipLeadingLF.set(this, void 0);
__classPrivateFieldSet(this, _LineDecoder_buffer, new Uint8Array(), "f");
__classPrivateFieldSet(this, _LineDecoder_start, 0, "f");
__classPrivateFieldSet(this, _LineDecoder_end, 0, "f");
__classPrivateFieldSet(this, _LineDecoder_searchIndex, 0, "f");
__classPrivateFieldSet(this, _LineDecoder_skipLeadingLF, false, "f");
}
/**
* Appends a text or UTF-8 byte chunk and returns every newly completed line.
*
* Incomplete lines remain buffered for the next call. A trailing `\r`
* completes its line immediately, and a following `\n` is consumed as its
* continuation. `null` and `undefined` are ignored and do not flush buffered
* content.
*/
decode(chunk) {
if (chunk == null) {
return [];
}
let binaryChunk;
if (chunk instanceof ArrayBuffer) {
binaryChunk = new Uint8Array(chunk);
} else if (typeof chunk === "string") {
binaryChunk = encodeUTF8(chunk);
} else {
binaryChunk = chunk;
}
if (binaryChunk.length === 0) {
return [];
}
if (__classPrivateFieldGet(this, _LineDecoder_skipLeadingLF, "f")) {
__classPrivateFieldSet(this, _LineDecoder_skipLeadingLF, false, "f");
if (binaryChunk[0] === 10) {
binaryChunk = binaryChunk.subarray(1);
}
if (binaryChunk.length === 0) {
return [];
}
}
__classPrivateFieldGet(this, _LineDecoder_instances, "m", _LineDecoder_append).call(this, binaryChunk);
const lines2 = [];
let patternIndex;
while ((patternIndex = findNewlineIndex(__classPrivateFieldGet(this, _LineDecoder_buffer, "f"), __classPrivateFieldGet(this, _LineDecoder_searchIndex, "f"), __classPrivateFieldGet(this, _LineDecoder_end, "f"))) != null) {
const line = decodeUTF8(__classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(__classPrivateFieldGet(this, _LineDecoder_start, "f"), patternIndex.preceding));
lines2.push(line);
__classPrivateFieldSet(this, _LineDecoder_start, patternIndex.index, "f");
if (patternIndex.carriage) {
if (__classPrivateFieldGet(this, _LineDecoder_start, "f") < __classPrivateFieldGet(this, _LineDecoder_end, "f") && __classPrivateFieldGet(this, _LineDecoder_buffer, "f")[__classPrivateFieldGet(this, _LineDecoder_start, "f")] === 10) {
__classPrivateFieldSet(this, _LineDecoder_start, __classPrivateFieldGet(this, _LineDecoder_start, "f") + 1, "f");
} else if (__classPrivateFieldGet(this, _LineDecoder_start, "f") === __classPrivateFieldGet(this, _LineDecoder_end, "f")) {
__classPrivateFieldSet(this, _LineDecoder_skipLeadingLF, true, "f");
}
}
__classPrivateFieldSet(this, _LineDecoder_searchIndex, __classPrivateFieldGet(this, _LineDecoder_start, "f"), "f");
}
__classPrivateFieldSet(this, _LineDecoder_searchIndex, __classPrivateFieldGet(this, _LineDecoder_end, "f"), "f");
if (__classPrivateFieldGet(this, _LineDecoder_start, "f") === __classPrivateFieldGet(this, _LineDecoder_end, "f")) {
__classPrivateFieldSet(this, _LineDecoder_start, 0, "f");
__classPrivateFieldSet(this, _LineDecoder_end, 0, "f");
__classPrivateFieldSet(this, _LineDecoder_searchIndex, 0, "f");
if (__classPrivateFieldGet(this, _LineDecoder_buffer, "f").length > MAX_RETAINED_BUFFER_BYTES) {
__classPrivateFieldSet(this, _LineDecoder_buffer, new Uint8Array(), "f");
}
} else if (lines2.length > 0 && __classPrivateFieldGet(this, _LineDecoder_buffer, "f").length > MAX_RETAINED_BUFFER_BYTES) {
const length = __classPrivateFieldGet(this, _LineDecoder_end, "f") - __classPrivateFieldGet(this, _LineDecoder_start, "f");
if (length <= MAX_RETAINED_BUFFER_BYTES || __classPrivateFieldGet(this, _LineDecoder_buffer, "f").length > length * 4) {
const capacity = length <= MAX_RETAINED_BUFFER_BYTES ? Math.min(Math.max(length * 2, 256), MAX_RETAINED_BUFFER_BYTES) : length * 2;
const buffer = new Uint8Array(capacity);
buffer.set(__classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(__classPrivateFieldGet(this, _LineDecoder_start, "f"), __classPrivateFieldGet(this, _LineDecoder_end, "f")));
__classPrivateFieldSet(this, _LineDecoder_buffer, buffer, "f");
__classPrivateFieldSet(this, _LineDecoder_start, 0, "f");
__classPrivateFieldSet(this, _LineDecoder_end, length, "f");
__classPrivateFieldSet(this, _LineDecoder_searchIndex, length, "f");
}
}
return lines2;
}
/** Emits the remaining unterminated line, or returns an empty array when idle. */
flush() {
__classPrivateFieldSet(this, _LineDecoder_skipLeadingLF, false, "f");
if (__classPrivateFieldGet(this, _LineDecoder_start, "f") === __classPrivateFieldGet(this, _LineDecoder_end, "f")) {
return [];
}
return this.decode("\n");
}
};
_LineDecoder_buffer = /* @__PURE__ */ new WeakMap(), _LineDecoder_start = /* @__PURE__ */ new WeakMap(), _LineDecoder_end = /* @__PURE__ */ new WeakMap(), _LineDecoder_searchIndex = /* @__PURE__ */ new WeakMap(), _LineDecoder_skipLeadingLF = /* @__PURE__ */ new WeakMap(), _LineDecoder_instances = /* @__PURE__ */ new WeakSet(), _LineDecoder_append = function _LineDecoder_append2(chunk) {
if (__classPrivateFieldGet(this, _LineDecoder_end, "f") + chunk.length > __classPrivateFieldGet(this, _LineDecoder_buffer, "f").length) {
const length = __classPrivateFieldGet(this, _LineDecoder_end, "f") - __classPrivateFieldGet(this, _LineDecoder_start, "f");
if (__classPrivateFieldGet(this, _LineDecoder_start, "f") >= __classPrivateFieldGet(this, _LineDecoder_buffer, "f").length / 2 && length + chunk.length <= __classPrivateFieldGet(this, _LineDecoder_buffer, "f").length) {
__classPrivateFieldGet(this, _LineDecoder_buffer, "f").copyWithin(0, __classPrivateFieldGet(this, _LineDecoder_start, "f"), __classPrivateFieldGet(this, _LineDecoder_end, "f"));
} else {
const capacity = Math.max(__classPrivateFieldGet(this, _LineDecoder_buffer, "f").length * 2, length + chunk.length, 256);
const buffer = new Uint8Array(capacity);
buffer.set(__classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(__classPrivateFieldGet(this, _LineDecoder_start, "f"), __classPrivateFieldGet(this, _LineDecoder_end, "f")));
__classPrivateFieldSet(this, _LineDecoder_buffer, buffer, "f");
}
__classPrivateFieldSet(this, _LineDecoder_searchIndex, __classPrivateFieldGet(this, _LineDecoder_searchIndex, "f") - __classPrivateFieldGet(this, _LineDecoder_start, "f"), "f");
__classPrivateFieldSet(this, _LineDecoder_end, length, "f");
__classPrivateFieldSet(this, _LineDecoder_start, 0, "f");
}
__classPrivateFieldGet(this, _LineDecoder_buffer, "f").set(chunk, __classPrivateFieldGet(this, _LineDecoder_end, "f"));
__classPrivateFieldSet(this, _LineDecoder_end, __classPrivateFieldGet(this, _LineDecoder_end, "f") + chunk.length, "f");
};
LineDecoder.NEWLINE_CHARS = /* @__PURE__ */ new Set(["\n", "\r"]);
LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g;
}
});
// node_modules/openai/internal/utils/log.mjs
function noop() {
}
function makeLogFn(fnLevel, logger, logLevel) {
if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
return noop;
} else {
return logger[fnLevel].bind(logger);
}
}
function loggerFor(client) {
const logger = client.logger;
const logLevel = client.logLevel ?? "off";
if (!logger) {
return noopLogger;
}
const cachedLogger = cachedLoggers.get(logger);
if (cachedLogger && cachedLogger[0] === logLevel) {
return cachedLogger[1];
}
const levelLogger = {
error: makeLogFn("error", logger, logLevel),
warn: makeLogFn("warn", logger, logLevel),
info: makeLogFn("info", logger, logLevel),
debug: makeLogFn("debug", logger, logLevel)
};
cachedLoggers.set(logger, [logLevel, levelLogger]);
return levelLogger;
}
function isSensitiveQueryParameter(name) {
const normalized = name.toLowerCase().replace(/[-_]/gu, "");
return sensitiveQueryNames.has(normalized) || sensitiveQueryNames.has(normalized.replace(/^x/u, ""));
}
function isSensitiveHeader(name) {
return sensitiveHeaderNames.has(name.toLowerCase().replace(/_/gu, "-")) || isSensitiveQueryParameter(name);
}
function redactURL(value2) {
const url = new URL(value2);
url.username = "";
url.password = "";
url.hash = "";
for (const name of url.searchParams.keys()) {
if (isSensitiveQueryParameter(name)) {
url.searchParams.set(name, "***");
}
}
return url.href;
}
var levelNumbers, parseLogLevel, noopLogger, cachedLoggers, sensitiveQueryNames, sensitiveHeaderNames, formatRequestDetails;
var init_log = __esm({
"node_modules/openai/internal/utils/log.mjs"() {
init_values();
levelNumbers = {
off: 0,
error: 200,
warn: 300,
info: 400,
debug: 500
};
parseLogLevel = (maybeLevel, sourceName, client) => {
if (!maybeLevel) {
return void 0;
}
if (hasOwn(levelNumbers, maybeLevel)) {
return maybeLevel;
}
loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`);
return void 0;
};
noopLogger = {
error: noop,
warn: noop,
info: noop,
debug: noop
};
cachedLoggers = /* @__PURE__ */ new WeakMap();
sensitiveQueryNames = /* @__PURE__ */ new Set([
"apikey",
"accesstoken",
"refreshtoken",
"sessiontoken",
"sessionid",
"idtoken",
"authtoken",
"authorization",
"token",
"password",
"clientsecret",
"signingsecret",
"xamzsecuritytoken",
"xamzsignature",
"xamzcredential"
]);
sensitiveHeaderNames = /* @__PURE__ */ new Set([
"authorization",
"proxy-authorization",
"api-key",
"x-api-key",
"x-amz-security-token",
"cookie",
"set-cookie",
"x-session-token",
"x-session-id",
"x-auth-token",
"x-id-token"
]);
formatRequestDetails = (details) => {
if (details.options) {
details.options = { ...details.options };
delete details.options["headers"];
if (details.options.path) {
const path3 = details.options.path;
const redacted = new URL(redactURL(new URL(path3, "https://redacted.invalid").href));
details.options.path = redacted.origin === "https://redacted.invalid" ? `${path3.startsWith("/") ? "/" : ""}${redacted.pathname.slice(1)}${redacted.search}` : redacted.href;
}
if (details.options.query) {
details.options.query = Object.fromEntries(Object.entries(details.options.query).map(([name, value2]) => [
name,
isSensitiveQueryParameter(name) ? "***" : value2
]));
}
}
if (details.url) {
details.url = redactURL(details.url);
}
if (details.headers) {
details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value2]) => [name, isSensitiveHeader(name) ? "***" : value2]));
}
if ("retryOfRequestLogID" in details) {
if (details.retryOfRequestLogID) {
details.retryOf = details.retryOfRequestLogID;
}
delete details.retryOfRequestLogID;
}
return details;
};
}
});
// node_modules/openai/core/streaming.mjs
function isTransportAbortError(error) {
return !(error instanceof APIError) && isAbortError(error);
}
function createStreamTeeQueue() {
let entries2 = [];
let head = 0;
let canceled = false;
return {
get length() {
return entries2.length - head;
},
get canceled() {
return canceled;
},
enqueue(value2) {
if (!canceled) {
entries2.push(value2);
}
},
dequeue() {
if (head === entries2.length) {
return void 0;
}
const value2 = entries2[head];
entries2[head] = void 0;
head += 1;
if (head === entries2.length) {
entries2 = [];
head = 0;
} else if (head >= 1024 && head * 2 >= entries2.length) {
entries2 = entries2.slice(head);
head = 0;
}
return value2;
},
cancel() {
canceled = true;
entries2.length = 0;
head = 0;
}
};
}
function createAbortableSSESource(body, signal) {
const reader = typeof body.getReader === "function" ? body.getReader() : void 0;
const source = reader ? {
next: () => reader.read(),
return: () => reader.cancel()
} : ReadableStreamToAsyncIterable(body)[Symbol.asyncIterator]();
const ended = { value: void 0, done: true };
let closed = false;
let canceled = false;
let cancellation;
let interrupt;
const waitForAbort = () => (
// oxlint-disable-next-line promise/avoid-new -- AbortSignal callbacks need a portable Promise bridge.
new Promise((resolve2) => {
interrupt = resolve2;
})
);
const cancel = () => {
if (canceled || closed) {
return cancellation;
}
canceled = true;
try {
cancellation = Promise.resolve(source.return?.());
} catch (error) {
cancellation = Promise.reject(error);
}
cancellation.catch(() => void 0);
return cancellation;
};
const abort = () => {
queueMicrotask(() => {
interrupt?.();
cancel();
});
};
const iterator = {
async next() {
if (signal.aborted) {
return ended;
}
const aborted = waitForAbort().then(() => ended);
try {
const result = await Promise.race([source.next(), aborted]);
if (signal.aborted) {
return ended;
}
if (result.done) {
closed = true;
return ended;
}
return { value: result.value, done: false };
} catch (error) {
if (signal.aborted && (isAbortError(error) || error === signal.reason)) {
return ended;
}
throw error;
} finally {
interrupt = void 0;
}
},
async return() {
const pending = cancel();
if (pending && !signal.aborted) {
const aborted = waitForAbort();
try {
if (!signal.aborted) {
await Promise.race([pending, aborted]);
}
} finally {
interrupt = void 0;
}
}
return ended;
},
[Symbol.asyncIterator]() {
return this;
}
};
return {
iterator,
start() {
signal.addEventListener("abort", abort, { once: true });
if (signal.aborted) {
abort();
}
},
async cleanup(failed) {
let cleanupError;
try {
signal.removeEventListener("abort", abort);
} catch (error) {
cleanupError = error;
}
if (!closed) {
const pending = cancel();
if (pending && !failed && !signal.aborted) {
try {
await pending;
} catch (error) {
cleanupError ?? (cleanupError = error);
}
}
}
if (reader) {
try {
reader.releaseLock();
} catch (error) {
cleanupError ?? (cleanupError = error);
}
}
if (cleanupError !== void 0 && !failed && !signal.aborted) {
throw cleanupError;
}
}
};
}
async function* _iterSSEMessages(response, controller) {
if (!response.body) {
controller.abort();
if (globalThis.navigator !== void 0 && globalThis.navigator.product === "ReactNative") {
throw new OpenAIError(`The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`);
}
throw new OpenAIError(`Attempted to iterate over a response with no body`);
}
const sseDecoder = new SSEDecoder();
const lineDecoder = new LineDecoder();
const { signal } = controller;
const source = createAbortableSSESource(response.body, signal);
let failed = false;
try {
source.start();
for await (const sseChunk of iterSSEChunks(source.iterator)) {
if (signal.aborted) {
return;
}
for (const line of lineDecoder.decode(sseChunk)) {
if (signal.aborted) {
return;
}
const sse = sseDecoder.decode(line);
if (sse) {
yield sse;
}
}
}
if (signal.aborted) {
return;
}
for (const line of lineDecoder.flush()) {
if (signal.aborted) {
return;
}
const sse = sseDecoder.decode(line);
if (sse) {
yield sse;
}
}
if (signal.aborted) {
return;
}
const pending = sseDecoder.flush();
if (pending) {
yield pending;
}
} catch (error) {
failed = true;
if (!signal.aborted || !isAbortError(error) && error !== signal.reason) {
throw error;
}
} finally {
await source.cleanup(failed);
}
}
async function* iterSSEChunks(iterator) {
let data = new Uint8Array();
let dataStart = 0;
let dataEnd = 0;
let searchStartIndex = 0;
for await (const chunk of iterator) {
if (chunk == null) {
continue;
}
let binaryChunk;
if (chunk instanceof ArrayBuffer) {
binaryChunk = new Uint8Array(chunk);
} else if (typeof chunk === "string") {
binaryChunk = encodeUTF8(chunk);
} else {
binaryChunk = chunk;
}
if (dataEnd + binaryChunk.length > data.length) {
const bufferedLength = dataEnd - dataStart;
if (dataStart >= data.length / 2 && bufferedLength + binaryChunk.length <= data.length) {
data.copyWithin(0, dataStart, dataEnd);
} else {
const newData = new Uint8Array(Math.max(data.length * 2, bufferedLength + binaryChunk.length));
newData.set(data.subarray(dataStart, dataEnd));
data = newData;
}
searchStartIndex -= dataStart;
dataStart = 0;
dataEnd = bufferedLength;
}
data.set(binaryChunk, dataEnd);
dataEnd += binaryChunk.length;
let patternIndex;
while ((patternIndex = findDoubleNewlineIndex(data.subarray(searchStartIndex, dataEnd))) !== -1) {
patternIndex += searchStartIndex;
yield data.slice(dataStart, patternIndex);
dataStart = patternIndex;
searchStartIndex = dataStart;
}
searchStartIndex = Math.max(dataStart, dataEnd - DOUBLE_NEWLINE_DELIMITER_MAX_OVERLAP_BYTES);
}
if (dataEnd > dataStart) {
yield data.slice(dataStart, dataEnd);
}
}
function partition(str2, delimiter) {
const index = str2.indexOf(delimiter);
if (index !== -1) {
return [str2.slice(0, index), delimiter, str2.slice(index + delimiter.length)];
}
return [str2, "", ""];
}
var _Stream_instances, _Stream_client, _Stream_isTeeBranch, _Stream_cancelIterator, Stream, DOUBLE_NEWLINE_DELIMITER_MAX_OVERLAP_BYTES, SSEDecoder;
var init_streaming = __esm({
"node_modules/openai/core/streaming.mjs"() {
init_tslib();
init_error();
init_shims();
init_line();
init_errors();
init_bytes();
init_log();
Stream = class _Stream {
/** Wraps an asynchronous event iterator and the controller that owns its request. */
constructor(iterator, controller, client) {
_Stream_instances.add(this);
_Stream_client.set(this, void 0);
_Stream_isTeeBranch.set(this, false);
this.iterator = iterator;
this.controller = controller;
__classPrivateFieldSet(this, _Stream_client, client, "f");
}
/**
* Decodes an SSE response into parsed JSON events.
*
* The resulting stream can be consumed only once, ignores events after `[DONE]`, and
* surfaces API error payloads as `APIError` instances. When
* `synthesizeEventData` is enabled, each item also includes its SSE event name.
*/
static fromSSEResponse(response, controller, client, synthesizeEventData) {
let consumed = false;
const logger = client ? loggerFor(client) : console;
async function* iterator() {
if (consumed) {
throw new OpenAIError("Cannot iterate over a consumed stream, use `.tee()` to split the stream.");
}
consumed = true;
let done = false;
let receivedCompletionSentinel = false;
const messages = _iterSSEMessages(response, controller);
const closeMessages = messages.return.bind(messages);
messages.return = (value2) => {
if (!receivedCompletionSentinel) {
controller.abort();
}
return closeMessages(value2);
};
try {
for await (const sse of messages) {
if (sse.data === "[DONE]") {
receivedCompletionSentinel = true;
break;
}
if (sse.event === null || !sse.event.startsWith("thread.")) {
let data;
try {
data = JSON.parse(sse.data);
} catch {
logger.error(`Could not parse message into JSON:`);
logger.error(`From chunk:`);
throw new SyntaxError("Error reading response: malformed server-sent event JSON.");
}
if (sse.event === "error") {
throw new APIError(void 0, data?.error ?? data, void 0, response.headers);
}
if (data && data.error) {
throw new APIError(void 0, data.error, void 0, response.headers);
}
yield synthesizeEventData ? { event: sse.event, data } : data;
} else {
let data;
try {
data = JSON.parse(sse.data);
} catch {
logger.error(`Could not parse message into JSON:`);
logger.error(`From chunk:`);
throw new SyntaxError("Error reading response: malformed server-sent event JSON.");
}
yield { event: sse.event, data };
}
}
done = true;
} catch (e) {
if (receivedCompletionSentinel || isTransportAbortError(e) || controller.signal.aborted && e === controller.signal.reason) {
return;
}
throw e;
} finally {
if (!done) {
controller.abort();
}
}
}
return new _Stream(iterator, controller, client);
}
/**
* Generates a Stream from a newline-separated ReadableStream
* where each item is a JSON value.
*/
static fromReadableStream(readableStream, controller, client) {
let consumed = false;
async function* iterLines() {
const lineDecoder = new LineDecoder();
const reader = readableStream.getReader();
let closed = false;
let cancelPromise;
const cancel = () => {
cancelPromise ?? (cancelPromise = reader.cancel());
cancelPromise.catch(() => void 0);
};
controller.signal.addEventListener("abort", cancel, { once: true });
try {
if (controller.signal.aborted) {
cancel();
return;
}
while (true) {
const { value: chunk, done } = await reader.read();
if (done) {
closed = true;
break;
}
if (controller.signal.aborted) {
return;
}
for (const line of lineDecoder.decode(chunk)) {
if (controller.signal.aborted) {
return;
}
yield line;
}
}
if (controller.signal.aborted) {
return;
}
for (const line of lineDecoder.flush()) {
if (controller.signal.aborted) {
return;
}
yield line;
}
} finally {
controller.signal.removeEventListener("abort", cancel);
if (!closed) {
cancel();
}
reader.releaseLock();
}
}
async function* iterator() {
if (consumed) {
throw new OpenAIError("Cannot iterate over a consumed stream, use `.tee()` to split the stream.");
}
consumed = true;
let done = false;
try {
for await (const line of iterLines()) {
if (line) {
let data;
try {
data = JSON.parse(line);
} catch (error) {
if (error instanceof SyntaxError) {
throw new SyntaxError("Error reading response: malformed newline-delimited JSON.");
}
throw error;
}
yield data;
}
}
done = true;
} catch (e) {
if (controller.signal.aborted || isAbortError(e)) {
return;
}
throw e;
} finally {
if (!done) {
controller.abort();
}
}
}
return new _Stream(iterator, controller, client);
}
/** Starts consuming this stream; attempting to consume it again throws. */
[(_Stream_client = /* @__PURE__ */ new WeakMap(), _Stream_isTeeBranch = /* @__PURE__ */ new WeakMap(), _Stream_instances = /* @__PURE__ */ new WeakSet(), Symbol.asyncIterator)]() {
return this.iterator();
}
/**
* Splits the stream into two streams which can be
* independently read from at different speeds.
* Closing a branch discards its buffered events without stopping its sibling.
* Future reads on that branch finish immediately; previously issued `next()`
* promises remain shared with its sibling and may still resolve with events.
* Closing both branches invokes the source iterator's `return()` when available.
* For {@link Stream.fromReadableStream}, closing both branches before iteration
* starts does not cancel the supplied readable; cancel that readable directly.
*/
tee() {
const { controller } = this;
const left = createStreamTeeQueue();
const right = createStreamTeeQueue();
const iterator = this.iterator();
const teeIterator = (queue) => ({
next: () => {
if (queue.canceled) {
return Promise.resolve({ value: void 0, done: true });
}
if (queue.length === 0) {
const result = iterator.next();
left.enqueue(result);
right.enqueue(result);
}
return queue.dequeue();
},
return: async () => {
if (!queue.canceled) {
queue.cancel();
if (left.canceled && right.canceled) {
await __classPrivateFieldGet(this, _Stream_instances, "m", _Stream_cancelIterator).call(this, iterator, controller);
}
}
return { value: void 0, done: true };
}
});
const branch = (queue) => {
const stream2 = new _Stream(() => teeIterator(queue), controller, __classPrivateFieldGet(this, _Stream_client, "f"));
__classPrivateFieldSet(stream2, _Stream_isTeeBranch, true, "f");
return stream2;
};
return [branch(left), branch(right)];
}
/**
* Converts this stream to a newline-separated ReadableStream of
* JSON stringified values in the stream
* which can be turned back into a Stream with `Stream.fromReadableStream()`.
* Canceling a response-backed readable aborts its request. Canceling a tee
* branch discards its buffered events and leaves sibling consumers running.
* Read or serialization failures also release the iterator without replacing the original error.
*/
toReadableStream() {
const { controller } = this;
let iter;
let cancellation;
const cancel = () => cancellation ?? (cancellation = __classPrivateFieldGet(this, _Stream_instances, "m", _Stream_cancelIterator).call(this, iter, controller));
return makeReadableStream({
start: async () => {
iter = this[Symbol.asyncIterator]();
},
async pull(ctrl) {
try {
const { value: value2, done } = await iter.next();
if (done) {
return ctrl.close();
}
const bytes2 = encodeUTF8(JSON.stringify(value2) + "\n");
ctrl.enqueue(bytes2);
} catch (err) {
ctrl.error(err);
void cancel().catch(() => void 0);
}
},
cancel
});
}
};
_Stream_cancelIterator = async function _Stream_cancelIterator2(iterator, controller) {
const returnMethod = iterator.return;
if (returnMethod) {
if (!__classPrivateFieldGet(this, _Stream_isTeeBranch, "f")) {
controller.abort();
}
await Reflect.apply(returnMethod, iterator, []);
}
};
DOUBLE_NEWLINE_DELIMITER_MAX_OVERLAP_BYTES = 3;
SSEDecoder = class {
constructor() {
this.event = null;
this.data = [];
this.chunks = [];
}
decode(line) {
if (line.endsWith("\r")) {
line = line.slice(0, -1);
}
if (!line) {
if (!this.event && !this.data.length) {
return null;
}
const sse = {
event: this.event,
data: this.data.join("\n"),
raw: this.chunks
};
this.event = null;
this.data = [];
this.chunks = [];
return sse;
}
this.chunks.push(line);
if (line.startsWith(":")) {
return null;
}
const [fieldname, , initialValue] = partition(line, ":");
let value2 = initialValue;
if (value2.startsWith(" ")) {
value2 = value2.slice(1);
}
if (fieldname === "event") {
this.event = value2;
} else if (fieldname === "data") {
this.data.push(value2);
}
return null;
}
/**
* Emits a pending event at EOF when the stream omitted the trailing blank
* line. Returns `null` when no event is in progress so a record that already
* ended with a blank line is not delivered twice.
*/
flush() {
return this.decode("");
}
};
}
});
// node_modules/openai/internal/parse.mjs
async function defaultParseResponse(client, props) {
const { response, requestLogID, retryOfRequestLogID, startTime } = props;
let jsonBodyLength;
const body = await (async () => {
if (props.options.stream) {
loggerFor(client).debug("response", response.status, response.url, response.headers, response.body);
if (props.options.__streamClass) {
return props.options.__streamClass.fromSSEResponse(response, props.controller, client, props.options.__synthesizeEventData);
}
return Stream.fromSSEResponse(response, props.controller, client, props.options.__synthesizeEventData);
}
if (response.status === 204) {
return null;
}
if (props.options.__binaryResponse) {
return response;
}
const contentType = response.headers.get("content-type");
const mediaType = contentType?.split(";")[0]?.trim().toLowerCase();
const isJSON = mediaType?.includes("application/json") || mediaType?.endsWith("+json");
if (isJSON) {
const contentLength = response.headers.get("content-length");
if (contentLength === "0") {
return void 0;
}
const bodyText = await response.text();
if (!bodyText) {
return void 0;
}
const json = JSON.parse(bodyText);
jsonBodyLength = bodyText.length;
return addRequestID(json, response);
}
const text2 = await response.text();
return text2;
})().catch((error) => {
throw asAbortError(error, props.controller.signal);
});
if (client.logLevel === "debug") {
loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({
retryOfRequestLogID,
url: response.url,
status: response.status,
body: jsonBodyLength === void 0 ? body : { type: "json", length: jsonBodyLength },
durationMs: Date.now() - startTime
}));
}
return body;
}
function asAbortError(error, signal) {
if (!signal.aborted || error !== signal.reason || isAbortError(error)) {
return error;
}
const message = "This operation was aborted";
const DOMExceptionConstructor = globalThis.DOMException;
return typeof DOMExceptionConstructor === "function" ? new DOMExceptionConstructor(message, "AbortError") : Object.assign(new Error(message), { name: "AbortError" });
}
function addRequestID(value2, response) {
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) {
return value2;
}
return Object.defineProperty(value2, "_request_id", {
value: response.headers.get("x-request-id"),
enumerable: false
});
}
var init_parse = __esm({
"node_modules/openai/internal/parse.mjs"() {
init_streaming();
init_errors();
init_log();
}
});
// node_modules/openai/version.mjs
var VERSION;
var init_version2 = __esm({
"node_modules/openai/version.mjs"() {
VERSION = "7.19.0";
}
});
// node_modules/openai/internal/detect-platform.mjs
function getDetectedPlatform() {
if (typeof Deno !== "undefined" && Deno.build != null) {
return "deno";
}
if (typeof EdgeRuntime !== "undefined") {
return "edge";
}
if (Object.prototype.toString.call(typeof globalThis.process !== "undefined" ? globalThis.process : 0) === "[object process]") {
return "node";
}
return "unknown";
}
function getBrowserInfo() {
if (typeof navigator === "undefined" || !navigator) {
return null;
}
const browserPatterns = [
{ key: "edge", pattern: /\bEdg(?:e|A|iOS)?\b(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
{ key: "ie", pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
{ key: "ie", pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ },
{ key: "chrome", pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
{ key: "firefox", pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
{ key: "safari", pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }
];
for (const { key, pattern } of browserPatterns) {
const match = pattern.exec(navigator.userAgent);
if (match) {
const major = match[1] || 0;
const minor = match[2] || 0;
const patch = match[3] || 0;
return { browser: key, version: `${major}.${minor}.${patch}` };
}
}
return null;
}
var isRunningInBrowser, getPlatformProperties, normalizeArch, normalizePlatform, _platformHeaders, getPlatformHeaders;
var init_detect_platform = __esm({
"node_modules/openai/internal/detect-platform.mjs"() {
init_version2();
isRunningInBrowser = () => {
return (
// @ts-ignore
typeof window !== "undefined" && // @ts-ignore
typeof window.document !== "undefined" && // @ts-ignore
typeof navigator !== "undefined"
);
};
getPlatformProperties = () => {
const detectedPlatform = getDetectedPlatform();
if (detectedPlatform === "deno") {
return {
"X-Stainless-Lang": "js",
"X-Stainless-Package-Version": VERSION,
"X-Stainless-OS": normalizePlatform(Deno.build.os),
"X-Stainless-Arch": normalizeArch(Deno.build.arch),
"X-Stainless-Runtime": "deno",
"X-Stainless-Runtime-Version": typeof Deno.version === "string" ? Deno.version : Deno.version?.deno ?? "unknown"
};
}
if (typeof EdgeRuntime !== "undefined") {
return {
"X-Stainless-Lang": "js",
"X-Stainless-Package-Version": VERSION,
"X-Stainless-OS": "Unknown",
"X-Stainless-Arch": `other:${EdgeRuntime}`,
"X-Stainless-Runtime": "edge",
"X-Stainless-Runtime-Version": globalThis.process?.version ?? "unknown"
};
}
if (detectedPlatform === "node") {
return {
"X-Stainless-Lang": "js",
"X-Stainless-Package-Version": VERSION,
"X-Stainless-OS": normalizePlatform(globalThis.process.platform ?? "unknown"),
"X-Stainless-Arch": normalizeArch(globalThis.process.arch ?? "unknown"),
"X-Stainless-Runtime": "node",
"X-Stainless-Runtime-Version": globalThis.process.version ?? "unknown"
};
}
const browserInfo = getBrowserInfo();
if (browserInfo) {
return {
"X-Stainless-Lang": "js",
"X-Stainless-Package-Version": VERSION,
"X-Stainless-OS": "Unknown",
"X-Stainless-Arch": "unknown",
"X-Stainless-Runtime": `browser:${browserInfo.browser}`,
"X-Stainless-Runtime-Version": browserInfo.version
};
}
return {
"X-Stainless-Lang": "js",
"X-Stainless-Package-Version": VERSION,
"X-Stainless-OS": "Unknown",
"X-Stainless-Arch": "unknown",
"X-Stainless-Runtime": "unknown",
"X-Stainless-Runtime-Version": "unknown"
};
};
normalizeArch = (arch) => {
if (arch === "x32")
return "x32";
if (arch === "x86_64" || arch === "x64")
return "x64";
if (arch === "arm")
return "arm";
if (arch === "aarch64" || arch === "arm64")
return "arm64";
if (arch)
return `other:${arch}`;
return "unknown";
};
normalizePlatform = (platform) => {
platform = platform.toLowerCase();
if (platform.includes("ios"))
return "iOS";
if (platform === "android")
return "Android";
if (platform === "darwin")
return "MacOS";
if (platform === "win32")
return "Windows";
if (platform === "freebsd")
return "FreeBSD";
if (platform === "openbsd")
return "OpenBSD";
if (platform === "linux")
return "Linux";
if (platform)
return `Other:${platform}`;
return "Unknown";
};
getPlatformHeaders = () => {
return _platformHeaders ?? (_platformHeaders = getPlatformProperties());
};
}
});
// node_modules/openai/internal/request-options.mjs
function observeJSONRequestBody(body, observer) {
let observers = jsonRequestBodyObservers.get(body);
if (!observers) {
observers = /* @__PURE__ */ new Set();
jsonRequestBodyObservers.set(body, observers);
}
observers.add(observer);
return () => {
const active = jsonRequestBodyObservers.get(body);
if (!active) {
return;
}
active.delete(observer);
if (active.size === 0) {
jsonRequestBodyObservers.delete(body);
}
};
}
var jsonRequestBodyObservers, FallbackEncoder;
var init_request_options = __esm({
"node_modules/openai/internal/request-options.mjs"() {
jsonRequestBodyObservers = /* @__PURE__ */ new WeakMap();
FallbackEncoder = ({ headers, body }) => {
const observers = typeof body === "object" && body !== null ? jsonRequestBodyObservers.get(body) : void 0;
let encoded;
if (!observers || observers.size === 0) {
encoded = JSON.stringify(body);
} else {
const active = [...observers];
encoded = JSON.stringify(body, function(key, value2) {
let observed = value2;
for (const observer of active) {
const replacement = observer.value(this, key, observed);
if (replacement !== void 0) {
observed = replacement;
}
}
return observed;
});
for (const observer of active) {
observer.complete();
}
}
return {
bodyHeaders: {
"content-type": "application/json"
},
body: encoded
};
};
}
});
// node_modules/openai/internal/qs/formats.mjs
var default_format, default_formatter, formatters, RFC1738;
var init_formats = __esm({
"node_modules/openai/internal/qs/formats.mjs"() {
default_format = "RFC3986";
default_formatter = String;
formatters = {
RFC1738: (v) => String(v).replace(/%20/g, "+"),
RFC3986: default_formatter
};
RFC1738 = "RFC1738";
}
});
// node_modules/openai/internal/qs/utils.mjs
function is_buffer(obj2) {
if (!obj2 || typeof obj2 !== "object") {
return false;
}
return !!(obj2.constructor && obj2.constructor.isBuffer && obj2.constructor.isBuffer(obj2));
}
function maybe_map(val, fn) {
if (isArray(val)) {
const mapped = [];
for (const item of val) {
mapped.push(fn(item));
}
return mapped;
}
return fn(val);
}
var cachedHas, has, hex_table, limit, encode;
var init_utils = __esm({
"node_modules/openai/internal/qs/utils.mjs"() {
init_formats();
init_values();
has = (obj2, key) => {
const resolvedHas = cachedHas ?? Object.hasOwn ?? Function.prototype.call.bind(Object.prototype.hasOwnProperty);
cachedHas = resolvedHas;
return resolvedHas(obj2, key);
};
hex_table = /* @__PURE__ */ (() => {
const array = [];
for (let i = 0; i < 256; ++i) {
array.push("%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase());
}
return array;
})();
limit = 1024;
encode = (str2, _defaultEncoder, charset, _kind, format) => {
if (str2.length === 0) {
return str2;
}
let string = str2;
if (typeof str2 === "symbol") {
string = Symbol.prototype.toString.call(str2);
} else if (typeof str2 !== "string") {
string = String(str2);
}
if (charset === "iso-8859-1") {
return escape(string).replace(/%u[0-9a-f]{4}/gi, ($0) => "%26%23" + Number.parseInt($0.slice(2), 16) + "%3B");
}
let out = "";
for (let j = 0; j < string.length; ) {
let segmentEnd = Math.min((Math.floor(j / limit) + 1) * limit, string.length);
if (segmentEnd < string.length && string.codePointAt(segmentEnd - 1) > 65535) {
segmentEnd += 1;
}
const segment = string.length >= limit ? string.slice(j, segmentEnd) : string;
const arr2 = [];
for (let i = 0; i < segment.length; ++i) {
let c = segment.charCodeAt(i);
if (c === 45 || // -
c === 46 || // .
c === 95 || // _
c === 126 || // ~
c >= 48 && c <= 57 || // 0-9
c >= 65 && c <= 90 || // a-z
c >= 97 && c <= 122 || // A-Z
format === RFC1738 && (c === 40 || c === 41)) {
arr2[arr2.length] = segment.charAt(i);
continue;
}
if (c < 128) {
arr2[arr2.length] = hex_table[c];
continue;
}
if (c < 2048) {
arr2[arr2.length] = hex_table[192 | c >> 6] + hex_table[128 | c & 63];
continue;
}
if (c < 55296 || c >= 57344) {
arr2[arr2.length] = hex_table[224 | c >> 12] + hex_table[128 | c >> 6 & 63] + hex_table[128 | c & 63];
continue;
}
i += 1;
c = 65536 + ((c & 1023) << 10 | segment.charCodeAt(i) & 1023);
arr2[arr2.length] = hex_table[240 | c >> 18] + hex_table[128 | c >> 12 & 63] + hex_table[128 | c >> 6 & 63] + hex_table[128 | c & 63];
}
out += arr2.join("");
j = segmentEnd;
}
return out;
};
}
});
// node_modules/openai/internal/qs/stringify.mjs
function is_non_nullish_primitive(v) {
return typeof v === "string" || typeof v === "number" || typeof v === "boolean" || typeof v === "symbol" || typeof v === "bigint";
}
function inner_stringify(object, prefix, generateArrayPrefix, commaRoundTrip, allowEmptyArrays, strictNullHandling, skipNulls, encodeDotInKeys, encoder3, filter, sort, allowDots, serializeDate, format, formatter, encodeValuesOnly, charset, sideChannel) {
let obj2 = object;
let tmp_sc = sideChannel;
let step = 0;
let find_flag = false;
while ((tmp_sc = tmp_sc.get(sentinel)) !== void 0 && !find_flag) {
const pos = tmp_sc.get(object);
step += 1;
if (pos !== void 0) {
if (pos === step) {
throw new RangeError("Cyclic object value");
} else {
find_flag = true;
}
}
if (tmp_sc.get(sentinel) === void 0) {
step = 0;
}
}
if (typeof filter === "function") {
obj2 = filter(prefix, obj2);
} else if (obj2 instanceof Date) {
obj2 = serializeDate?.(obj2);
} else if (generateArrayPrefix === "comma" && isArray(obj2)) {
obj2 = maybe_map(obj2, (value2) => {
if (value2 instanceof Date) {
return serializeDate?.(value2);
}
return value2;
});
}
if (obj2 === null) {
if (strictNullHandling) {
return encoder3 && !encodeValuesOnly ? (
// @ts-expect-error
encoder3(prefix, defaults.encoder, charset, "key", format)
) : prefix;
}
obj2 = "";
}
if (is_non_nullish_primitive(obj2) || is_buffer(obj2)) {
if (encoder3) {
const key_value = encodeValuesOnly ? prefix : (
// @ts-expect-error
encoder3(prefix, defaults.encoder, charset, "key", format)
);
return [
formatter?.(key_value) + "=" + // @ts-expect-error
formatter?.(encoder3(obj2, defaults.encoder, charset, "value", format))
];
}
return [formatter?.(prefix) + "=" + formatter?.(String(obj2))];
}
const values = [];
if (obj2 === void 0) {
return values;
}
let obj_keys;
if (generateArrayPrefix === "comma" && isArray(obj2)) {
if (encodeValuesOnly && encoder3) {
obj2 = maybe_map(obj2, encoder3);
}
obj_keys = [{ value: obj2.length > 0 ? obj2.join(",") || null : void 0 }];
} else if (isArray(filter)) {
obj_keys = filter;
} else {
const keys = Object.keys(obj2);
if (sort) {
keys.sort(sort);
}
obj_keys = keys;
}
const encoded_prefix = encodeDotInKeys ? String(prefix).replace(/\./g, "%2E") : String(prefix);
const adjusted_prefix = commaRoundTrip && isArray(obj2) && obj2.length === 1 ? encoded_prefix + "[]" : encoded_prefix;
if (allowEmptyArrays && isArray(obj2) && obj2.length === 0) {
return adjusted_prefix + "[]";
}
for (const key of obj_keys) {
const value2 = (
// @ts-ignore
typeof key === "object" && key.value !== void 0 ? key.value : obj2[key]
);
if (skipNulls && value2 === null) {
continue;
}
const encoded_key = allowDots && encodeDotInKeys ? key.replace(/\./g, "%2E") : key;
let key_prefix;
if (isArray(obj2)) {
key_prefix = typeof generateArrayPrefix === "function" ? generateArrayPrefix(adjusted_prefix, encoded_key) : adjusted_prefix;
} else {
key_prefix = adjusted_prefix + (allowDots ? "." + encoded_key : "[" + encoded_key + "]");
}
sideChannel.set(object, step);
const valueSideChannel = new WeakMap([[sentinel, sideChannel]]);
push_to_array(values, inner_stringify(
value2,
key_prefix,
generateArrayPrefix,
commaRoundTrip,
allowEmptyArrays,
strictNullHandling,
skipNulls,
encodeDotInKeys,
// @ts-ignore
generateArrayPrefix === "comma" && encodeValuesOnly && isArray(obj2) ? null : encoder3,
filter,
sort,
allowDots,
serializeDate,
format,
formatter,
encodeValuesOnly,
charset,
valueSideChannel
));
}
return values;
}
function normalize_stringify_options(opts = defaults) {
if (opts.allowEmptyArrays !== void 0 && typeof opts.allowEmptyArrays !== "boolean") {
throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");
}
if (opts.encodeDotInKeys !== void 0 && typeof opts.encodeDotInKeys !== "boolean") {
throw new TypeError("`encodeDotInKeys` option can only be `true` or `false`, when provided");
}
if (opts.encoder !== null && opts.encoder !== void 0 && typeof opts.encoder !== "function") {
throw new TypeError("Encoder has to be a function.");
}
const charset = opts.charset || defaults.charset;
if (opts.charset !== void 0 && opts.charset !== "utf-8" && opts.charset !== "iso-8859-1") {
throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");
}
let format = default_format;
if (opts.format !== void 0) {
if (!has(formatters, opts.format)) {
throw new TypeError("Unknown format option provided.");
}
format = opts.format;
}
const formatter = formatters[format];
let filter = defaults.filter;
if (typeof opts.filter === "function" || isArray(opts.filter)) {
filter = opts.filter;
}
let arrayFormat;
if (opts.arrayFormat && opts.arrayFormat in array_prefix_generators) {
arrayFormat = opts.arrayFormat;
} else if ("indices" in opts) {
arrayFormat = opts.indices ? "indices" : "repeat";
} else {
arrayFormat = defaults.arrayFormat;
}
if ("commaRoundTrip" in opts && typeof opts.commaRoundTrip !== "boolean") {
throw new TypeError("`commaRoundTrip` must be a boolean, or absent");
}
let allowDots;
if (opts.allowDots === void 0) {
allowDots = !!opts.encodeDotInKeys === true ? true : defaults.allowDots;
} else {
allowDots = !!opts.allowDots;
}
return {
addQueryPrefix: typeof opts.addQueryPrefix === "boolean" ? opts.addQueryPrefix : defaults.addQueryPrefix,
// @ts-ignore
allowDots,
allowEmptyArrays: typeof opts.allowEmptyArrays === "boolean" ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
arrayFormat,
charset,
charsetSentinel: typeof opts.charsetSentinel === "boolean" ? opts.charsetSentinel : defaults.charsetSentinel,
commaRoundTrip: !!opts.commaRoundTrip,
delimiter: opts.delimiter === void 0 ? defaults.delimiter : opts.delimiter,
encode: typeof opts.encode === "boolean" ? opts.encode : defaults.encode,
encodeDotInKeys: typeof opts.encodeDotInKeys === "boolean" ? opts.encodeDotInKeys : defaults.encodeDotInKeys,
encoder: typeof opts.encoder === "function" ? opts.encoder : defaults.encoder,
encodeValuesOnly: typeof opts.encodeValuesOnly === "boolean" ? opts.encodeValuesOnly : defaults.encodeValuesOnly,
filter,
format,
formatter,
serializeDate: typeof opts.serializeDate === "function" ? opts.serializeDate : defaults.serializeDate,
skipNulls: typeof opts.skipNulls === "boolean" ? opts.skipNulls : defaults.skipNulls,
// @ts-ignore
sort: typeof opts.sort === "function" ? opts.sort : null,
strictNullHandling: typeof opts.strictNullHandling === "boolean" ? opts.strictNullHandling : defaults.strictNullHandling
};
}
function stringify(object, opts = {}) {
let obj2 = object;
const options = normalize_stringify_options(opts);
let obj_keys;
let filter;
if (typeof options.filter === "function") {
filter = options.filter;
obj2 = filter("", obj2);
} else if (isArray(options.filter)) {
filter = options.filter;
obj_keys = filter;
}
const keys = [];
if (typeof obj2 !== "object" || obj2 === null) {
return "";
}
const generateArrayPrefix = array_prefix_generators[options.arrayFormat];
const commaRoundTrip = generateArrayPrefix === "comma" && options.commaRoundTrip;
if (!obj_keys) {
obj_keys = Object.keys(obj2);
}
if (options.sort) {
obj_keys.sort(options.sort);
}
const sideChannel = /* @__PURE__ */ new WeakMap();
for (const key of obj_keys) {
if (options.skipNulls && obj2[key] === null) {
continue;
}
push_to_array(keys, inner_stringify(
obj2[key],
key,
// @ts-expect-error
generateArrayPrefix,
commaRoundTrip,
options.allowEmptyArrays,
options.strictNullHandling,
options.skipNulls,
options.encodeDotInKeys,
options.encode ? options.encoder : null,
options.filter,
options.sort,
options.allowDots,
options.serializeDate,
options.format,
options.formatter,
options.encodeValuesOnly,
options.charset,
sideChannel
));
}
const joined = keys.join(options.delimiter);
let prefix = options.addQueryPrefix === true ? "?" : "";
if (options.charsetSentinel) {
prefix += options.charset === "iso-8859-1" ? (
// encodeURIComponent('&#10003;'), the "numeric entity" representation of a checkmark
"utf8=%26%2310003%3B&"
) : (
// encodeURIComponent('✓')
"utf8=%E2%9C%93&"
);
}
return joined.length > 0 ? prefix + joined : "";
}
var array_prefix_generators, push_to_array, toISOString, defaults, sentinel;
var init_stringify = __esm({
"node_modules/openai/internal/qs/stringify.mjs"() {
init_utils();
init_formats();
init_values();
array_prefix_generators = {
brackets(prefix) {
return String(prefix) + "[]";
},
comma: "comma",
indices(prefix, key) {
return String(prefix) + "[" + key + "]";
},
repeat(prefix) {
return String(prefix);
}
};
push_to_array = function push_to_array2(arr2, value_or_array) {
Array.prototype.push.apply(arr2, isArray(value_or_array) ? value_or_array : [value_or_array]);
};
defaults = {
addQueryPrefix: false,
allowDots: false,
allowEmptyArrays: false,
arrayFormat: "indices",
charset: "utf-8",
charsetSentinel: false,
delimiter: "&",
encode: true,
encodeDotInKeys: false,
encoder: encode,
encodeValuesOnly: false,
format: default_format,
formatter: default_formatter,
/** @deprecated */
indices: false,
serializeDate(date) {
return (toISOString ?? (toISOString = Function.prototype.call.bind(Date.prototype.toISOString)))(date);
},
skipNulls: false,
strictNullHandling: false
};
sentinel = {};
}
});
// node_modules/openai/internal/utils/query.mjs
function stringifyQuery(query) {
return stringify(query, { arrayFormat: "brackets" });
}
var init_query = __esm({
"node_modules/openai/internal/utils/query.mjs"() {
init_stringify();
}
});
// node_modules/openai/internal/data-residency.mjs
function resolveDataResidency(options) {
if (options.dataResidency === null || options.dataResidency === void 0) {
return void 0;
}
if (hasOwn(options, "baseURL")) {
throw new OpenAIError("The `dataResidency` and `baseURL` options are mutually exclusive.");
}
const endpoint = endpoints.get(options.dataResidency);
if (endpoint === void 0) {
throw new OpenAIError("Invalid `dataResidency`; expected one of: global, us, eu, ae.");
}
return endpoint;
}
var endpoints;
var init_data_residency = __esm({
"node_modules/openai/internal/data-residency.mjs"() {
init_error();
init_values();
endpoints = /* @__PURE__ */ new Map([
["global", "https://api.openai.com/v1"],
["us", "https://us.api.openai.com/v1"],
["eu", "https://eu.api.openai.com/v1"],
["ae", "https://ae.api.openai.com/v1"]
]);
}
});
// node_modules/openai/core/api-promise.mjs
var _APIPromise_client, APIPromise;
var init_api_promise = __esm({
"node_modules/openai/core/api-promise.mjs"() {
init_tslib();
init_parse();
APIPromise = class _APIPromise extends Promise {
constructor(client, responsePromise, parseResponse2 = defaultParseResponse) {
super((resolve2) => {
resolve2(null);
});
this.responsePromise = responsePromise;
this.parseResponse = parseResponse2;
_APIPromise_client.set(this, void 0);
__classPrivateFieldSet(this, _APIPromise_client, client, "f");
}
_thenUnwrap(transform) {
return new _APIPromise(__classPrivateFieldGet(this, _APIPromise_client, "f"), this.responsePromise, async (client, props) => addRequestID(transform(await this.parseResponse(client, props), props), props.response));
}
/**
* Gets the raw `Response` instance instead of parsing the response
* data.
*
* If you want to parse the response body but still get the `Response`
* instance, you can use {@link withResponse()}.
*
* 👋 Getting the wrong TypeScript type for `Response`?
* Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]`
* to your `tsconfig.json`.
*/
asResponse() {
return this.responsePromise.then((p) => p.response);
}
/**
* Gets the parsed response data, the raw `Response` instance and the ID of the request,
* returned via the X-Request-ID header which is useful for debugging requests and reporting
* issues to OpenAI.
*
* If you just want to get the raw `Response` instance without parsing it,
* you can use {@link asResponse()}.
*
* 👋 Getting the wrong TypeScript type for `Response`?
* Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]`
* to your `tsconfig.json`.
*/
async withResponse() {
const [data, response] = await Promise.all([this.parse(), this.asResponse()]);
return { data, response, request_id: response.headers.get("x-request-id") };
}
parse() {
if (!this.parsedPromise) {
this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(__classPrivateFieldGet(this, _APIPromise_client, "f"), data));
}
return this.parsedPromise;
}
then(onfulfilled, onrejected) {
return this.parse().then(onfulfilled, onrejected);
}
catch(onrejected) {
return this.parse().catch(onrejected);
}
finally(onfinally) {
return this.parse().finally(onfinally);
}
};
_APIPromise_client = /* @__PURE__ */ new WeakMap();
}
});
// node_modules/openai/core/pagination.mjs
var _AbstractPage_client, AbstractPage, PagePromise, Page, CursorPage, ConversationCursorPage, NextCursorPage, TokenPage;
var init_pagination = __esm({
"node_modules/openai/core/pagination.mjs"() {
init_tslib();
init_error();
init_parse();
init_api_promise();
init_values();
AbstractPage = class {
constructor(client, response, body, options) {
_AbstractPage_client.set(this, void 0);
__classPrivateFieldSet(this, _AbstractPage_client, client, "f");
this.options = options;
this.response = response;
this.body = body;
}
hasNextPage() {
const items = this.getPaginatedItems();
if (!items.length)
return false;
return this.nextPageRequestOptions() != null;
}
async getNextPage() {
const nextOptions = this.nextPageRequestOptions();
if (!nextOptions) {
throw new OpenAIError("No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.");
}
return await __classPrivateFieldGet(this, _AbstractPage_client, "f").requestAPIList(this.constructor, nextOptions);
}
async *iterPages() {
let page2 = this;
yield page2;
while (page2.hasNextPage()) {
page2 = await page2.getNextPage();
yield page2;
}
}
async *[(_AbstractPage_client = /* @__PURE__ */ new WeakMap(), Symbol.asyncIterator)]() {
for await (const page2 of this.iterPages()) {
for (const item of page2.getPaginatedItems()) {
yield item;
}
}
}
};
PagePromise = class extends APIPromise {
constructor(client, request2, Page2) {
super(client, request2, async (client2, props) => new Page2(client2, props.response, await defaultParseResponse(client2, props), props.options));
}
/**
* Allow auto-paginating iteration on an unawaited list call, eg:
*
* for await (const item of client.items.list()) {
* console.log(item)
* }
*/
async *[Symbol.asyncIterator]() {
const page2 = await this;
for await (const item of page2) {
yield item;
}
}
};
Page = class extends AbstractPage {
constructor(client, response, body, options) {
super(client, response, body, options);
this.data = body.data || [];
this.object = body.object;
}
getPaginatedItems() {
return this.data ?? [];
}
nextPageRequestOptions() {
return null;
}
};
CursorPage = class extends AbstractPage {
constructor(client, response, body, options) {
super(client, response, body, options);
this.data = body.data || [];
this.has_more = body.has_more || false;
}
getPaginatedItems() {
return this.data ?? [];
}
hasNextPage() {
if (this.has_more === false) {
return false;
}
return super.hasNextPage();
}
nextPageRequestOptions() {
const data = this.getPaginatedItems();
const id = data[data.length - 1]?.id;
if (!id) {
return null;
}
return {
...this.options,
query: {
...maybeObj(this.options.query),
after: id
}
};
}
};
ConversationCursorPage = class extends AbstractPage {
constructor(client, response, body, options) {
super(client, response, body, options);
this.data = body.data || [];
this.has_more = body.has_more || false;
this.last_id = body.last_id || "";
}
getPaginatedItems() {
return this.data ?? [];
}
hasNextPage() {
if (this.has_more === false) {
return false;
}
return super.hasNextPage();
}
nextPageRequestOptions() {
const cursor = this.last_id;
if (!cursor) {
return null;
}
return {
...this.options,
query: {
...maybeObj(this.options.query),
after: cursor
}
};
}
};
NextCursorPage = class extends AbstractPage {
constructor(client, response, body, options) {
super(client, response, body, options);
this.data = body.data || [];
this.has_more = body.has_more || false;
this.next = body.next || null;
}
getPaginatedItems() {
return this.data ?? [];
}
hasNextPage() {
if (this.has_more === false) {
return false;
}
return this.nextPageRequestOptions() != null;
}
nextPageRequestOptions() {
const cursor = this.next;
if (!cursor) {
return null;
}
return {
...this.options,
query: {
...maybeObj(this.options.query),
after: cursor
}
};
}
};
TokenPage = class extends AbstractPage {
constructor(client, response, body, options) {
super(client, response, body, options);
this.data = body.data || [];
this.has_more = body.has_more || false;
this.next = body.next || null;
}
getPaginatedItems() {
return this.data ?? [];
}
hasNextPage() {
if (this.has_more === false) {
return false;
}
return this.nextPageRequestOptions() != null;
}
nextPageRequestOptions() {
const cursor = this.next;
if (!cursor) {
return null;
}
return {
...this.options,
query: {
...maybeObj(this.options.query),
page: cursor
}
};
}
};
}
});
// node_modules/openai/auth/workload-identity-auth.mjs
function calculateExpiresAt(expiresIn, exchangeStartedAt) {
if (typeof expiresIn !== "number" || !Number.isFinite(expiresIn) || expiresIn <= 0) {
throw new OpenAIError("Token exchange response has invalid 'expires_in' field");
}
const now = Date.now();
const fullLifetimeDeadline = now + expiresIn * 1e3;
if (!Number.isSafeInteger(fullLifetimeDeadline) || fullLifetimeDeadline <= now) {
throw new OpenAIError("Token exchange response has invalid 'expires_in' field");
}
const expiresAt = fullLifetimeDeadline - (performance.now() - exchangeStartedAt);
if (expiresAt <= now) {
throw new OpenAIError("Workload identity token expired before its exchange completed.");
}
return expiresAt;
}
function calculateRefreshAt(expiresAt, lifetimeSeconds, refreshBufferSeconds) {
const configuredBufferMs = (refreshBufferSeconds ?? 1200) * 1e3;
const effectiveBufferMs = Math.min(configuredBufferMs, lifetimeSeconds * 1e3 * MAX_REFRESH_BUFFER_FRACTION);
return expiresAt - effectiveBufferMs;
}
function isResponsePrototype(response, prototype) {
const constructor = Object.getOwnPropertyDescriptor(prototype, "constructor")?.value;
if (prototype === response || typeof constructor !== "function" || Object.getOwnPropertyDescriptor(constructor, "name")?.value !== "Response" || Object.getOwnPropertyDescriptor(constructor, "prototype")?.value !== prototype) {
return false;
}
const tag = Object.getOwnPropertyDescriptor(prototype, Symbol.toStringTag);
return (tag?.value === "Response" || typeof tag?.get === "function") && typeof Object.getOwnPropertyDescriptor(prototype, "headers")?.get === "function" && typeof Object.getOwnPropertyDescriptor(prototype, "ok")?.get === "function" && typeof Object.getOwnPropertyDescriptor(prototype, "status")?.get === "function";
}
function isResponseBodyPrototype(prototype, responsePrototype) {
if (prototype === responsePrototype) {
return true;
}
const constructor = Object.getOwnPropertyDescriptor(prototype, "constructor")?.value;
return responsePrototype !== null && Object.getPrototypeOf(responsePrototype) === prototype && typeof constructor === "function" && Object.getOwnPropertyDescriptor(constructor, "name")?.value === "Body" && Object.getOwnPropertyDescriptor(constructor, "prototype")?.value === prototype;
}
function decodeNativeResponseBody(body) {
const scope = globalThis;
return new TextDecoder("utf-8", { ignoreBOM: typeof scope.Bun?.version === "string" }).decode(body);
}
async function parseOAuthTokenResponse(response) {
let readText2;
let responsePrototype = null;
for (let depth = 0, prototype = response; prototype !== null && depth < 16; prototype = Object.getPrototypeOf(prototype), depth += 1) {
if (prototype === NATIVE_RESPONSE_PROTOTYPE) {
break;
}
if (isResponsePrototype(response, prototype)) {
responsePrototype = prototype;
}
const parser = Object.getOwnPropertyDescriptor(prototype, "json");
if (!parser) {
continue;
}
if (typeof parser.value !== "function") {
break;
}
const bodyReader = Object.getOwnPropertyDescriptor(prototype, "text")?.value;
if (typeof bodyReader === "function" && isResponseBodyPrototype(prototype, responsePrototype)) {
readText2 = bodyReader;
break;
}
return parser.value.call(response);
}
const body = readText2 === void 0 ? decodeNativeResponseBody(await READ_NATIVE_RESPONSE_BODY.call(response)) : await readText2.call(response);
try {
return JSON.parse(body);
} catch {
throw new SyntaxError("Token exchange response contains invalid JSON");
}
}
function isUnsafeAccessToken(accessToken) {
const scope = globalThis;
if (typeof scope.Bun?.version === "string") {
return /[^\t\u0020-\u007E]|^[\t ]|[\t ]$/u.test(accessToken);
}
return /[^\t\u0020-\u007E\u0080-\u00FF]|^[\t ]|[\t ]$/u.test(accessToken);
}
var SUBJECT_TOKEN_TYPES, TOKEN_EXCHANGE_GRANT_TYPE, MAX_REFRESH_BUFFER_FRACTION, NATIVE_RESPONSE_PROTOTYPE, READ_NATIVE_RESPONSE_BODY, WorkloadIdentityAuth;
var init_workload_identity_auth = __esm({
"node_modules/openai/auth/workload-identity-auth.mjs"() {
init_shims();
init_error();
SUBJECT_TOKEN_TYPES = {
jwt: "urn:ietf:params:oauth:token-type:jwt",
id: "urn:ietf:params:oauth:token-type:id_token"
};
TOKEN_EXCHANGE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:token-exchange";
MAX_REFRESH_BUFFER_FRACTION = 0.5;
NATIVE_RESPONSE_PROTOTYPE = Response.prototype;
READ_NATIVE_RESPONSE_BODY = NATIVE_RESPONSE_PROTOTYPE.arrayBuffer;
WorkloadIdentityAuth = class _WorkloadIdentityAuth {
/**
* Creates a workload-identity token cache and OAuth token-exchange client.
*
* @param config External identity provider, OpenAI service account, and refresh settings.
* @param fetch Optional fetch implementation for calls to the OpenAI token endpoint.
*/
constructor(config, fetch2) {
this.cachedToken = null;
this.refreshPromise = null;
this.tokenGeneration = 0;
this.tokenExchangeUrl = "https://auth.openai.com/oauth/token";
const { identityProviderId, serviceAccountId, clientId, refreshBufferSeconds, provider: provider3 } = config;
this.config = {
identityProviderId,
serviceAccountId,
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...clientId === void 0 ? {} : { clientId },
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...refreshBufferSeconds === void 0 ? {} : { refreshBufferSeconds },
provider: {
tokenType: provider3.tokenType,
getToken: provider3.getToken.bind(provider3)
}
};
this.fetch = fetch2 ?? getDefaultFetch();
}
/**
* Returns a valid OpenAI access token, exchanging or refreshing credentials as needed.
*
* Cached tokens nearing expiration are returned immediately while a background
* refresh runs. Concurrent callers share the same in-flight token exchange.
*
* @throws {OAuthError} When the token endpoint rejects the subject token or identity.
* @throws {APIError} When another unsuccessful HTTP response prevents token exchange.
* @throws {OpenAIError} When a successful exchange has an invalid access token or expiration.
*/
async getToken() {
if (!this.cachedToken || _WorkloadIdentityAuth.isTokenExpired(this.cachedToken)) {
if (this.refreshPromise) {
return await this.refreshPromise;
}
const refreshPromise = this.refreshToken(this.tokenGeneration);
this.refreshPromise = refreshPromise;
try {
return await refreshPromise;
} finally {
if (this.refreshPromise === refreshPromise) {
this.refreshPromise = null;
}
}
}
if (_WorkloadIdentityAuth.needsRefresh(this.cachedToken) && !this.refreshPromise) {
const refreshPromise = this.refreshToken(this.tokenGeneration).finally(() => {
if (this.refreshPromise === refreshPromise) {
this.refreshPromise = null;
}
});
this.refreshPromise = refreshPromise;
void refreshPromise.catch(() => null);
}
return this.cachedToken.token;
}
async refreshToken(generation) {
const subjectToken = await this.config.provider.getToken();
const body = {
grant_type: TOKEN_EXCHANGE_GRANT_TYPE,
subject_token: subjectToken,
subject_token_type: SUBJECT_TOKEN_TYPES[this.config.provider.tokenType],
identity_provider_id: this.config.identityProviderId,
service_account_id: this.config.serviceAccountId
};
if (this.config.clientId) {
body["client_id"] = this.config.clientId;
}
const exchangeStartedAt = performance.now();
const response = await this.fetch(this.tokenExchangeUrl, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(body),
redirect: "manual"
});
if (!response.ok) {
const errorText = await response.text();
let body2 = void 0;
try {
body2 = JSON.parse(errorText);
} catch {
}
if (response.status === 400 || response.status === 401 || response.status === 403) {
throw new OAuthError(response.status, body2, response.headers);
}
throw APIError.generate(response.status, body2, `Token exchange failed with status ${response.status}`, response.headers);
}
const tokenResponse = await parseOAuthTokenResponse(response);
const accessToken = typeof tokenResponse === "object" && tokenResponse !== null && "access_token" in tokenResponse ? tokenResponse.access_token : void 0;
if (typeof accessToken !== "string" || accessToken.trim().length === 0 || isUnsafeAccessToken(accessToken)) {
throw new OpenAIError("Token exchange response missing 'access_token' field");
}
const expiresIn = tokenResponse.expires_in ?? 3600;
const expiresAt = calculateExpiresAt(expiresIn, exchangeStartedAt);
if (this.tokenGeneration === generation) {
this.cachedToken = {
token: accessToken,
expiresAt,
refreshAt: calculateRefreshAt(expiresAt, expiresIn, this.config.refreshBufferSeconds)
};
}
return accessToken;
}
static isTokenExpired(cachedToken) {
return Date.now() >= cachedToken.expiresAt;
}
static needsRefresh(cachedToken) {
return Date.now() >= cachedToken.refreshAt;
}
/** Discards the cached access token so the next request performs a fresh exchange. */
invalidateToken() {
this.tokenGeneration += 1;
this.cachedToken = null;
this.refreshPromise = null;
}
};
}
});
// node_modules/openai/internal/auth/x509-api-origin.mjs
function assertX509APIOrigin(value2) {
let target;
try {
target = new URL(value2);
} catch {
throw new OpenAIError("X.509 workload identity requires the approved global mTLS API origin.");
}
if (target.origin !== "https://mtls.api.openai.com" || target.username || target.password) {
throw new OpenAIError("X.509 workload identity requires the approved global mTLS API origin.");
}
for (const name of target.searchParams.keys()) {
if (isSensitiveQueryParameter(name)) {
throw new OpenAIError("X.509 workload identity cannot send conflicting query authentication credentials.");
}
}
return target;
}
var X509_API_BASE_URL;
var init_x509_api_origin = __esm({
"node_modules/openai/internal/auth/x509-api-origin.mjs"() {
init_error();
init_log();
X509_API_BASE_URL = "https://mtls.api.openai.com/v1";
}
});
// node_modules/openai/internal/headers.mjs
function* iterateHeaders(headers) {
if (!headers)
return;
if (brand_privateNullableHeaders in headers) {
const { values, nulls } = headers;
yield* values.entries();
for (const name of nulls) {
yield [name, null];
}
return;
}
let shouldClear = false;
let iter;
const iterator = Symbol.iterator in headers ? headers[Symbol.iterator] : void 0;
if (typeof iterator === "function") {
iter = { [Symbol.iterator]: () => iterator.call(headers) };
} else {
shouldClear = true;
iter = Object.entries(headers ?? {});
}
for (let row of iter) {
const name = row[0];
if (typeof name !== "string")
throw new TypeError("expected header name to be a string");
const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];
let didClear = false;
for (const value2 of values) {
if (value2 === void 0)
continue;
if (shouldClear && !didClear) {
didClear = true;
yield [name, null];
}
yield [name, value2];
}
}
}
var brand_privateNullableHeaders, httpTokenHeaderName, buildHeaders;
var init_headers2 = __esm({
"node_modules/openai/internal/headers.mjs"() {
init_values();
brand_privateNullableHeaders = /* @__PURE__ */ Symbol("brand.privateNullableHeaders");
httpTokenHeaderName = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
buildHeaders = (newHeaders) => {
const targetHeaders = new Headers();
const nullHeaders = /* @__PURE__ */ new Set();
for (const headers of newHeaders) {
const seenHeaders = /* @__PURE__ */ new Set();
for (const [name, value2] of iterateHeaders(headers)) {
if (!httpTokenHeaderName.test(name)) {
throw new TypeError(`Header name must be a valid HTTP token ["${name}"]`);
}
const lowerName = name.toLowerCase();
if (!seenHeaders.has(lowerName)) {
targetHeaders.delete(lowerName);
seenHeaders.add(lowerName);
}
if (value2 === null) {
targetHeaders.delete(lowerName);
nullHeaders.add(lowerName);
} else {
targetHeaders.append(lowerName, value2);
nullHeaders.delete(lowerName);
}
}
}
return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };
};
}
});
// node_modules/openai/internal/auth/x509-transport-state-browser.mjs
var x509_transport_state_browser_exports = {};
__export(x509_transport_state_browser_exports, {
findRegisteredX509Transport: () => findRegisteredX509Transport,
findX509Credential: () => findX509Credential,
findX509OAuthError: () => findX509OAuthError,
isApprovedX509Client: () => isApprovedX509Client,
isRetryableX509IssuerError: () => isRetryableX509IssuerError,
isTransientX509ConnectionError: () => isTransientX509ConnectionError,
markApprovedX509Client: () => markApprovedX509Client,
markRetryableX509IssuerError: () => markRetryableX509IssuerError,
markTransientX509ConnectionError: () => markTransientX509ConnectionError,
rememberRegisteredX509Transport: () => rememberRegisteredX509Transport,
rememberX509Credential: () => rememberX509Credential,
rememberX509OAuthError: () => rememberX509OAuthError
});
var registeredX509Transports, transientX509ConnectionErrors, retryableX509IssuerErrors, approvedX509Clients, approvedX509OAuthErrors, approvedX509Credentials, findRegisteredX509Transport, rememberRegisteredX509Transport, markTransientX509ConnectionError, isTransientX509ConnectionError, markRetryableX509IssuerError, isRetryableX509IssuerError, markApprovedX509Client, isApprovedX509Client, rememberX509OAuthError, findX509OAuthError, rememberX509Credential, findX509Credential;
var init_x509_transport_state_browser = __esm({
"node_modules/openai/internal/auth/x509-transport-state-browser.mjs"() {
registeredX509Transports = /* @__PURE__ */ new WeakMap();
transientX509ConnectionErrors = /* @__PURE__ */ new WeakSet();
retryableX509IssuerErrors = /* @__PURE__ */ new WeakSet();
approvedX509Clients = /* @__PURE__ */ new WeakSet();
approvedX509OAuthErrors = /* @__PURE__ */ new WeakMap();
approvedX509Credentials = /* @__PURE__ */ new WeakMap();
findRegisteredX509Transport = WeakMap.prototype.get.bind(registeredX509Transports);
rememberRegisteredX509Transport = WeakMap.prototype.set.bind(registeredX509Transports);
markTransientX509ConnectionError = WeakSet.prototype.add.bind(transientX509ConnectionErrors);
isTransientX509ConnectionError = WeakSet.prototype.has.bind(transientX509ConnectionErrors);
markRetryableX509IssuerError = WeakSet.prototype.add.bind(retryableX509IssuerErrors);
isRetryableX509IssuerError = WeakSet.prototype.has.bind(retryableX509IssuerErrors);
markApprovedX509Client = WeakSet.prototype.add.bind(approvedX509Clients);
isApprovedX509Client = WeakSet.prototype.has.bind(approvedX509Clients);
rememberX509OAuthError = WeakMap.prototype.set.bind(approvedX509OAuthErrors);
findX509OAuthError = WeakMap.prototype.get.bind(approvedX509OAuthErrors);
rememberX509Credential = WeakMap.prototype.set.bind(approvedX509Credentials);
findX509Credential = WeakMap.prototype.get.bind(approvedX509Credentials);
}
});
// node_modules/openai/internal/auth/x509-transport-state.js
var require_x509_transport_state = __commonJS({
"node_modules/openai/internal/auth/x509-transport-state.js"(exports, module) {
"use strict";
if (typeof module !== "undefined" && module !== globalThis.module && typeof exports !== "undefined" && module.exports === exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.findX509Credential = exports.rememberX509Credential = exports.findX509OAuthError = exports.rememberX509OAuthError = exports.isApprovedX509Client = exports.markApprovedX509Client = exports.isRetryableX509IssuerError = exports.markRetryableX509IssuerError = exports.isTransientX509ConnectionError = exports.markTransientX509ConnectionError = exports.rememberRegisteredX509Transport = exports.findRegisteredX509Transport = void 0;
const registeredX509Transports2 = /* @__PURE__ */ new WeakMap();
const transientX509ConnectionErrors2 = /* @__PURE__ */ new WeakSet();
const retryableX509IssuerErrors2 = /* @__PURE__ */ new WeakSet();
const approvedX509Clients2 = /* @__PURE__ */ new WeakSet();
const approvedX509OAuthErrors2 = /* @__PURE__ */ new WeakMap();
const approvedX509Credentials2 = /* @__PURE__ */ new WeakMap();
exports.findRegisteredX509Transport = WeakMap.prototype.get.bind(registeredX509Transports2);
exports.rememberRegisteredX509Transport = WeakMap.prototype.set.bind(registeredX509Transports2);
exports.markTransientX509ConnectionError = WeakSet.prototype.add.bind(transientX509ConnectionErrors2);
exports.isTransientX509ConnectionError = WeakSet.prototype.has.bind(transientX509ConnectionErrors2);
exports.markRetryableX509IssuerError = WeakSet.prototype.add.bind(retryableX509IssuerErrors2);
exports.isRetryableX509IssuerError = WeakSet.prototype.has.bind(retryableX509IssuerErrors2);
exports.markApprovedX509Client = WeakSet.prototype.add.bind(approvedX509Clients2);
exports.isApprovedX509Client = WeakSet.prototype.has.bind(approvedX509Clients2);
exports.rememberX509OAuthError = WeakMap.prototype.set.bind(approvedX509OAuthErrors2);
exports.findX509OAuthError = WeakMap.prototype.get.bind(approvedX509OAuthErrors2);
exports.rememberX509Credential = WeakMap.prototype.set.bind(approvedX509Credentials2);
exports.findX509Credential = WeakMap.prototype.get.bind(approvedX509Credentials2);
}
}
});
// node_modules/openai/internal/auth/x509-transport-state.mjs
var nodeState, state, findRegisteredX509Transport3, rememberRegisteredX509Transport2, markTransientX509ConnectionError2, isTransientX509ConnectionError2, markRetryableX509IssuerError2, isRetryableX509IssuerError2, markApprovedX509Client2, isApprovedX509Client2, rememberX509OAuthError2, findX509OAuthError2, rememberX509Credential2, findX509Credential2;
var init_x509_transport_state = __esm({
"node_modules/openai/internal/auth/x509-transport-state.mjs"() {
init_x509_transport_state_browser();
nodeState = __toESM(require_x509_transport_state(), 1);
state = typeof nodeState.findRegisteredX509Transport === "function" ? nodeState : x509_transport_state_browser_exports;
({
findRegisteredX509Transport: findRegisteredX509Transport3,
rememberRegisteredX509Transport: rememberRegisteredX509Transport2,
markTransientX509ConnectionError: markTransientX509ConnectionError2,
isTransientX509ConnectionError: isTransientX509ConnectionError2,
markRetryableX509IssuerError: markRetryableX509IssuerError2,
isRetryableX509IssuerError: isRetryableX509IssuerError2,
markApprovedX509Client: markApprovedX509Client2,
isApprovedX509Client: isApprovedX509Client2,
rememberX509OAuthError: rememberX509OAuthError2,
findX509OAuthError: findX509OAuthError2,
rememberX509Credential: rememberX509Credential2,
findX509Credential: findX509Credential2
} = state);
}
});
// node_modules/openai/internal/auth/x509-transport-registry.mjs
function resolveX509Transport(value2) {
if (!value2 || typeof value2 !== "object") {
throw new OpenAIError("X.509 workload identity requires an approved X.509 transport capability.");
}
const registered = findRegisteredX509Transport3(value2);
if (!registered) {
throw new OpenAIError("X.509 workload identity requires an approved X.509 transport capability.");
}
return registered;
}
var init_x509_transport_registry = __esm({
"node_modules/openai/internal/auth/x509-transport-registry.mjs"() {
init_error();
init_x509_transport_state();
}
});
// node_modules/openai/internal/auth/x509-workload-identity-auth.mjs
function assertSafeHeaders(headers) {
for (const name of Headers.prototype.keys.call(headers)) {
const canonical2 = name.toLowerCase().split("_").join("-");
if (canonical2 !== "authorization" && isSensitiveHeader(canonical2) || canonical2 === "host") {
throw new OpenAIError("X.509 workload identity cannot send conflicting authentication credentials.");
}
}
}
function exchangeDeadline(timeout, callerSignal) {
const deadline = new AbortController();
const timer = timeout === void 0 ? void 0 : setTimeout(() => deadline.abort(new APIConnectionTimeoutError()), timeout);
const timerHandle = timer;
if (typeof timerHandle === "object" && timerHandle !== null && "unref" in timerHandle && typeof timerHandle.unref === "function") {
timerHandle.unref();
}
const cancel = () => deadline.abort(callerSignal?.reason);
callerSignal?.addEventListener("abort", cancel, { once: true });
if (callerSignal?.aborted) {
cancel();
}
return {
signal: deadline.signal,
dispose: () => {
callerSignal?.removeEventListener("abort", cancel);
if (timer) {
clearTimeout(timer);
}
}
};
}
function waitForRefresh(attempt, signal) {
let abort;
const canceled = new Promise((_resolve, reject2) => {
abort = () => reject2(signal.reason);
signal.addEventListener("abort", abort, { once: true });
if (signal.aborted) {
abort();
}
});
return {
result: Promise.race([attempt.promise, canceled]),
dispose: () => {
if (abort) {
signal.removeEventListener("abort", abort);
}
}
};
}
function isX509WorkloadIdentity(identity) {
if (!identity || typeof identity !== "object") {
return false;
}
let providerOwner = identity;
while (providerOwner !== null && providerOwner !== Object.prototype) {
const provider3 = Object.getOwnPropertyDescriptor(providerOwner, "provider");
if (provider3) {
if (!("value" in provider3) || provider3.value !== void 0) {
return false;
}
break;
}
providerOwner = Object.getPrototypeOf(providerOwner);
}
let current = identity;
while (current !== null && current !== Object.prototype) {
const discriminator = Object.getOwnPropertyDescriptor(current, "type");
if (discriminator) {
if (!("value" in discriminator)) {
throw new OpenAIError("X.509 workload identity type must be a plain data property.");
}
return discriminator.value === "x509";
}
current = Object.getPrototypeOf(current);
}
return false;
}
function assertX509FetchOptions(options) {
if (!options) {
return;
}
for (const name of FORBIDDEN_TRANSPORT_OPTIONS) {
if (hasOwn(options, name)) {
throw new OpenAIError("X.509 workload identity cannot override its approved transport capability.");
}
}
const redirect = Object.getOwnPropertyDescriptor(options, "redirect")?.value;
if (redirect !== void 0 && redirect !== "manual") {
throw new OpenAIError("X.509 workload identity requests require manual redirects.");
}
}
function assertX509RequestOptions(options) {
assertX509FetchOptions(options);
if (options && ["body", "headers", "method", "signal"].some((name) => hasOwn(options, name))) {
throw new OpenAIError("X.509 workload identity cannot override its request body, headers, method, or signal through fetch options.");
}
}
function snapshotX509RequestOptions(options) {
assertX509RequestOptions(options);
const snapshot = { ...options };
assertX509RequestOptions(snapshot);
return snapshot;
}
var _X509WorkloadIdentityAuth_instances, _a, _X509WorkloadIdentityAuth_identityProviderId, _X509WorkloadIdentityAuth_serviceAccountId, _X509WorkloadIdentityAuth_configuredRefreshBufferMs, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, _X509WorkloadIdentityAuth_organization, _X509WorkloadIdentityAuth_project, _X509WorkloadIdentityAuth_transport, _X509WorkloadIdentityAuth_refreshBufferMs, _X509WorkloadIdentityAuth_cachedToken, _X509WorkloadIdentityAuth_refresh, _X509WorkloadIdentityAuth_tokenGeneration, _X509WorkloadIdentityAuth_cancelRequestBody, _X509WorkloadIdentityAuth_assignToken, _X509WorkloadIdentityAuth_recoverRefreshFailure, _X509WorkloadIdentityAuth_fallbackToken, _X509WorkloadIdentityAuth_retireRefresh, _X509WorkloadIdentityAuth_beginRefresh, _X509WorkloadIdentityAuth_refreshToken, _X509WorkloadIdentityAuth_preflight, _X509WorkloadIdentityAuth_scope, _X509WorkloadIdentityAuth_assertTenantHeaders, FORBIDDEN_TRANSPORT_OPTIONS, headerValue, DEFAULT_REFRESH_BUFFER_MS, FAILED_REFRESH_COOLDOWN_MS, userAbortError, X509WorkloadIdentityAuth;
var init_x509_workload_identity_auth = __esm({
"node_modules/openai/internal/auth/x509-workload-identity-auth.mjs"() {
init_tslib();
init_error();
init_headers2();
init_shims();
init_log();
init_values();
init_x509_api_origin();
init_x509_transport_registry();
init_x509_transport_state();
FORBIDDEN_TRANSPORT_OPTIONS = ["dispatcher", "agent", "client", "tls", "proxy"];
headerValue = (headers, name) => Headers.prototype.get.call(headers, name);
DEFAULT_REFRESH_BUFFER_MS = 20 * 60 * 1e3;
FAILED_REFRESH_COOLDOWN_MS = 1e3;
userAbortError = (signal) => {
const error = new APIUserAbortError();
Object.defineProperty(error, "cause", { value: signal.reason, writable: true, configurable: true });
return error;
};
X509WorkloadIdentityAuth = class {
/** Captures one registered, immutable certificate identity and its enrolled selectors. */
constructor(identity, transport, organization, project) {
_X509WorkloadIdentityAuth_instances.add(this);
_X509WorkloadIdentityAuth_identityProviderId.set(this, void 0);
_X509WorkloadIdentityAuth_serviceAccountId.set(this, void 0);
_X509WorkloadIdentityAuth_configuredRefreshBufferMs.set(this, void 0);
_X509WorkloadIdentityAuth_configuredRefreshBufferSeconds.set(this, void 0);
_X509WorkloadIdentityAuth_organization.set(this, void 0);
_X509WorkloadIdentityAuth_project.set(this, void 0);
_X509WorkloadIdentityAuth_transport.set(this, void 0);
_X509WorkloadIdentityAuth_refreshBufferMs.set(this, void 0);
_X509WorkloadIdentityAuth_cachedToken.set(this, void 0);
_X509WorkloadIdentityAuth_refresh.set(this, void 0);
_X509WorkloadIdentityAuth_tokenGeneration.set(this, 0);
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_transport, resolveX509Transport(transport), "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_identityProviderId, identity.identityProviderId, "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_serviceAccountId, identity.serviceAccountId, "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferMs, identity.refreshBufferMs, "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, identity.refreshBufferSeconds, "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_organization, organization, "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_project, project, "f");
if (__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferMs, "f") !== void 0 && __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, "f") !== void 0) {
throw new OpenAIError("X.509 workload identity cannot combine refreshBufferSeconds and refreshBufferMs.");
}
if (__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferMs, "f") !== void 0 && (!Number.isSafeInteger(__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferMs, "f")) || __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferMs, "f") < 0)) {
throw new OpenAIError("X.509 workload identity requires a nonnegative integer refreshBufferMs.");
}
if (__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, "f") !== void 0 && (!Number.isSafeInteger(__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, "f")) || __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, "f") < 0 || !Number.isSafeInteger(__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, "f") * 1e3))) {
throw new OpenAIError("X.509 workload identity requires a nonnegative integer refreshBufferSeconds.");
}
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_refreshBufferMs, __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, "f") === void 0 ? __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferMs, "f") ?? DEFAULT_REFRESH_BUFFER_MS : __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, "f") * 1e3, "f");
}
/** Reconstructs the immutable selectors captured before caller-owned identity mutation. */
identitySnapshot() {
return {
type: "x509",
identityProviderId: __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_identityProviderId, "f"),
serviceAccountId: __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_serviceAccountId, "f"),
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferMs, "f") === void 0 ? {} : { refreshBufferMs: __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferMs, "f") },
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, "f") === void 0 ? {} : { refreshBufferSeconds: __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds, "f") }
};
}
/** Preserves explicitly headerless requests without presenting a certificate to the issuer. */
static shouldAuthenticate(options, defaultHeaders, requestHeaders2 = options.headers) {
return !buildHeaders([defaultHeaders, requestHeaders2]).nulls.has("authorization");
}
/** Snapshots each caller-owned header layer once while preserving nulls and precedence. */
snapshotHeaders(defaultHeaders, requestHeaders2) {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
scope.defaultHeaders ?? (scope.defaultHeaders = buildHeaders([defaultHeaders]));
scope.requestHeaders ?? (scope.requestHeaders = buildHeaders([requestHeaders2]));
return this.headerSnapshots();
}
/** Returns the already rendered caller headers without touching mutable inputs again. */
headerSnapshots() {
const { defaultHeaders, requestHeaders: requestHeaders2 } = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
if (!defaultHeaders || !requestHeaders2) {
throw new OpenAIError("X.509 workload identity requires snapshotted request headers.");
}
return { defaultHeaders, requestHeaders: requestHeaders2 };
}
/** Captures enrolled public tenant selectors once before certificate presentation. */
snapshotTenant(organization, project) {
if (organization !== __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_organization, "f") || project !== __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_project, "f")) {
throw new OpenAIError("X.509 workload identity cannot override its enrolled organization or project.");
}
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
scope.tenant = { organization, project };
return scope.tenant;
}
/** Returns the tenant selectors already approved for this logical request. */
tenantSnapshot() {
const { tenant } = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
if (!tenant) {
throw new OpenAIError("X.509 workload identity requires snapshotted tenant selectors.");
}
return tenant;
}
/** Validates and retains the exact destination that authenticated dispatch will use. */
snapshotAPIURL(value2) {
assertX509APIOrigin(value2);
__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this).apiURL = value2;
}
/** Reads the already-approved destination without rerendering caller-owned request options. */
requestAPIURL() {
const { apiURL } = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
if (apiURL === void 0) {
throw new OpenAIError("X.509 workload identity requires a snapshotted API destination.");
}
return apiURL;
}
/** Captures the exact caller settings approved for authenticated dispatch. */
snapshotRequest(signal, timeout, fetchOptions) {
var _b;
(_b = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this)).request ?? (_b.request = { signal, timeout, fetchOptions });
}
/** Returns immutable request settings without invoking caller-owned accessors again. */
requestSnapshot() {
const { request: request2 } = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
if (!request2) {
throw new OpenAIError("X.509 workload identity requires snapshotted request settings.");
}
return request2;
}
/** Suspends an already-running network budget during retry-local asynchronous preparation. */
beginRequestPreparation() {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
if (scope.deadlineArmed && scope.preparationStartedAt === void 0) {
scope.preparationStartedAt = performance.now();
scope.preparationWallStartedAt = Date.now();
}
}
/** Begins local request construction without charging protected hook latency to the network. */
beginRequestPlanning() {
__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this).phase = "planning";
}
/** Arms one absolute network deadline only after all local request preparation completes. */
beginRequestNetwork() {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
if (!scope.deadlineArmed) {
scope.wallStartedAt = Date.now();
scope.monotonicStartedAt = performance.now();
scope.deadlineArmed = true;
} else if (scope.preparationStartedAt !== void 0) {
scope.monotonicStartedAt += performance.now() - scope.preparationStartedAt;
scope.wallStartedAt += Date.now() - (scope.preparationWallStartedAt ?? Date.now());
delete scope.preparationStartedAt;
delete scope.preparationWallStartedAt;
}
}
/** Keeps certificate authentication outside overridable request construction. */
isPlanningRequest() {
return __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this).phase === "planning";
}
/** Approves the final overridden destination and transport before minting a bearer. */
authorizePlannedRequest(url, request2, timeout, allowHookSignal = false) {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
const headers = Object.getOwnPropertyDescriptor(request2, "headers");
const body = Object.getOwnPropertyDescriptor(request2, "body");
const signal = Object.getOwnPropertyDescriptor(request2, "signal");
const redirect = Object.getOwnPropertyDescriptor(request2, "redirect");
if (scope.phase !== "planning" || !headers || !(headers.value instanceof Headers) || !body && "body" in request2 || [body, signal, redirect].some((descriptor) => descriptor && !("value" in descriptor))) {
throw new OpenAIError("X.509 workload identity requires an approved final request.");
}
this.snapshotAPIURL(url);
assertX509FetchOptions(request2);
try {
assertSafeHeaders(headers.value);
} catch {
throw new OpenAIError("X.509 workload identity cannot use caller-supplied authentication credentials.");
}
if (headerValue(headers.value, "Authorization") !== null) {
throw new OpenAIError("X.509 workload identity cannot use caller-supplied authorization credentials.");
}
__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_assertTenantHeaders).call(this, headers.value);
if (!allowHookSignal && (signal?.value ?? void 0) !== (this.requestSnapshot().signal ?? void 0)) {
throw new OpenAIError("X.509 workload identity must preserve its approved request signal.");
}
const approved = this.requestSnapshot();
scope.request = { ...approved, timeout: Math.min(approved.timeout, timeout) };
scope.phase = "authorizing";
}
/** Owns only SDK-created iterator adapters until authenticated dispatch takes responsibility. */
ownRequestBody(body, source) {
if (body instanceof ReadableStream && body !== source) {
__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this).materializedBody = body;
}
}
/** Recognizes every one-shot upload before issuer authentication or request replay. */
static isStreamingRequestBody(body) {
return globalThis.ReadableStream !== void 0 && body instanceof globalThis.ReadableStream || typeof body === "object" && body !== null && (Symbol.asyncIterator in body || Symbol.iterator in body && "next" in body && typeof body.next === "function");
}
/** Retires abandoned upload adapters without masking or blocking their authentication failure. */
retireRequestBody() {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
const body = scope.materializedBody;
delete scope.materializedBody;
if (body) {
void __classPrivateFieldGet(_a, _a, "m", _X509WorkloadIdentityAuth_cancelRequestBody).call(_a, body);
}
}
/** Transfers the dispatched upload while retiring any SDK-owned body replaced by a hook. */
releaseRequestBody(body) {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
if (scope.materializedBody === body) {
delete scope.materializedBody;
} else {
this.retireRequestBody();
}
}
/** Retains caller-only cancellation separately from SDK-created deadline controllers. */
setEffectiveSignal(signal) {
if (signal) {
__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this).effectiveSignal = signal;
} else {
delete __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this).effectiveSignal;
}
}
/** Uses protected-hook cancellation when an authenticated attempt enters retry backoff. */
effectiveSignal() {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
return scope.effectiveSignal ?? scope.request?.signal;
}
/** Establishes an independent scope even when concurrent requests share caller options. */
// oxlint-disable-next-line anti-slop/no-object-parameters -- Logical request owners are opaque identity tokens; their properties are never read.
runRequest(operation, requestOwner) {
return __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").run(async () => {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").current();
if (!scope) {
throw new OpenAIError("X.509 workload identity requires an active certificate request scope.");
}
scope.owner = this;
scope.requestOwner = requestOwner;
try {
return await operation();
} finally {
this.retireRequestBody();
this.releaseRequestCredentials();
delete scope.requestOwner;
delete scope.owner;
}
});
}
/** Reports whether a public request-building call already belongs to an active logical operation. */
// oxlint-disable-next-line anti-slop/no-object-parameters -- Request scope membership compares the opaque caller token by identity only.
inRequest(requestOwner) {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").current();
return scope?.owner === this && scope.requestOwner === requestOwner && scope.phase !== "authorizing";
}
/** Shares a cache only when the complete, privately snapshotted credential identity matches. */
matches(other) {
return __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f") === __classPrivateFieldGet(other, _X509WorkloadIdentityAuth_transport, "f") && __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_identityProviderId, "f") === __classPrivateFieldGet(other, _X509WorkloadIdentityAuth_identityProviderId, "f") && __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_serviceAccountId, "f") === __classPrivateFieldGet(other, _X509WorkloadIdentityAuth_serviceAccountId, "f") && __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_organization, "f") === __classPrivateFieldGet(other, _X509WorkloadIdentityAuth_organization, "f") && __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_project, "f") === __classPrivateFieldGet(other, _X509WorkloadIdentityAuth_project, "f") && __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_refreshBufferMs, "f") === __classPrivateFieldGet(other, _X509WorkloadIdentityAuth_refreshBufferMs, "f");
}
/** Binds deferred response parsing to the original logical request and its unchanged deadline. */
continuation() {
const { wallStartedAt, monotonicStartedAt, deadlineArmed, request: request2, requestOwner, effectiveSignal } = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
const scope = {
wallStartedAt,
monotonicStartedAt,
owner: this,
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...deadlineArmed ? { deadlineArmed } : {},
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...request2 ? { request: request2 } : {},
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...effectiveSignal ? { effectiveSignal } : {},
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...requestOwner ? { requestOwner } : {}
};
return (operation) => __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").resume(scope, async () => {
try {
return await operation();
} finally {
this.releaseRequestCredentials();
delete scope.requestOwner;
delete scope.owner;
}
});
}
/** Removes dispatched bearer material before settled request promises can retain their scope. */
releaseRequestCredentials() {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
delete scope.request;
delete scope.phase;
delete scope.deadlineArmed;
delete scope.preparationStartedAt;
delete scope.preparationWallStartedAt;
delete scope.effectiveSignal;
delete scope.materializedBody;
delete scope.apiURL;
delete scope.tenant;
delete scope.token;
delete scope.defaultHeaders;
delete scope.requestHeaders;
delete scope.tokenGeneration;
delete scope.headers;
delete scope.authorization;
}
/** Returns the original authentication start so response consumption shares its request deadline. */
requestStartedAt(_options) {
return __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").current()?.wallStartedAt;
}
/** Distinguishes issued workload credentials from independent admin or headerless requests. */
usedWorkloadToken(_options) {
return __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").current()?.token !== void 0;
}
/** Returns the budget left after certificate authentication without starting another timeout. */
remainingTimeout(_options, timeout) {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").current();
if (scope === void 0) {
return timeout;
}
const remaining = timeout - (performance.now() - scope.monotonicStartedAt);
if (remaining <= 0) {
throw new APIConnectionTimeoutError();
}
return remaining;
}
/** Cancels active retry timers promptly without changing public caller-abort semantics. */
async waitForRetry(duration, signal) {
try {
await __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").sleep(duration, signal);
} catch (error) {
if (signal?.aborted) {
throw userAbortError(signal);
}
throw error;
}
}
/** Trusts only issuer or connection failures privately branded by the approved transport. */
static isRetryableFailure(error) {
return typeof error === "object" && error !== null && (isTransientX509ConnectionError2(error) || isRetryableX509IssuerError2(error));
}
/** Reads safe retry hints only from a privately branded, sanitized issuer response. */
static retryHeaders(error) {
if (!error || typeof error !== "object" || !isRetryableX509IssuerError2(error)) {
return void 0;
}
const headers = Object.getOwnPropertyDescriptor(error, "headers")?.value;
return headers instanceof Headers ? headers : void 0;
}
/** Exchanges the exact certificate capability selected for the matching API dispatch. */
async getToken(options, context) {
const callerSignal = context ? context.signal : options?.signal;
if (callerSignal?.aborted) {
throw userAbortError(callerSignal);
}
if (options) {
assertX509RequestOptions(context ? context.fetchOptions : options.fetchOptions);
}
__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_preflight).call(this, context);
const scope = options ? __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this) : void 0;
const cached = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_cachedToken, "f");
if (cached && performance.now() < cached.refreshAt && Date.now() < cached.wallRefreshAt) {
return __classPrivateFieldGet(_a, _a, "m", _X509WorkloadIdentityAuth_assignToken).call(_a, scope, cached);
}
const remaining = context && options ? this.remainingTimeout(options, context.timeout) : context?.timeout;
const { signal, dispose } = exchangeDeadline(remaining, callerSignal);
if (callerSignal?.aborted) {
dispose();
throw userAbortError(callerSignal);
}
const attempt = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_refresh, "f") ?? __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_beginRefresh).call(this);
attempt.waiters += 1;
const waiter = waitForRefresh(attempt, signal);
try {
const exchanged = await waiter.result;
const refreshed = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_cachedToken, "f");
if (!refreshed || refreshed.accessToken !== exchanged.accessToken) {
throw new APIUserAbortError();
}
return __classPrivateFieldGet(_a, _a, "m", _X509WorkloadIdentityAuth_assignToken).call(_a, scope, refreshed);
} catch (error) {
return await __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_recoverRefreshFailure).call(this, error, attempt, cached, scope, options, context);
} finally {
waiter.dispose();
dispose();
attempt.waiters -= 1;
__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_retireRefresh).call(this, attempt);
}
}
/** Invalidates only the workload-token generation actually rejected by the current request. */
invalidateToken() {
const rejected = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").current();
if (!rejected?.token || __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_cachedToken, "f")?.accessToken !== rejected.token || __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_cachedToken, "f").generation !== rejected.tokenGeneration) {
return;
}
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_tokenGeneration, __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_tokenGeneration, "f") + 1, "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_cachedToken, void 0, "f");
const refresh = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_refresh, "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_refresh, void 0, "f");
refresh?.controller.abort(new APIUserAbortError());
}
/** Binds the minted credential to the original headers before protected request hooks run. */
bindRequest(options, request2, adminAPIKey) {
if (!(request2.headers instanceof Headers)) {
throw new OpenAIError("X.509 workload identity requires the original workload authorization headers.");
}
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
const { token } = scope;
const security = options.__security ?? { bearerAuth: true };
let approvedAuthorization = token ? `Bearer ${token}` : null;
if (!token && security.adminAPIKeyAuth && adminAPIKey !== null && headerValue(request2.headers, "Authorization") !== null) {
approvedAuthorization = new Headers({ Authorization: `Bearer ${adminAPIKey}` }).get("Authorization");
}
scope.headers = request2.headers;
scope.authorization = approvedAuthorization;
this.assertRequest(request2);
}
/** Rebinds an equivalent protected-hook container without relaxing final dispatch identity checks. */
adoptRequestHeaders(request2) {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_scope).call(this);
const original = scope.headers;
if (!(original instanceof Headers) || !(request2.headers instanceof Headers)) {
throw new OpenAIError("X.509 workload identity must preserve its issued workload authorization.");
}
scope.headers = request2.headers;
try {
this.assertRequest(request2);
} catch (error) {
scope.headers = original;
throw error;
}
}
/** Rejects request hooks that replace the selected bearer or its approved header identity. */
assertRequest(request2) {
const { headers } = request2;
if (!(headers instanceof Headers)) {
throw new OpenAIError("X.509 workload identity must preserve its issued workload authorization.");
}
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").current();
if (!scope || scope.headers !== headers || scope.authorization === void 0 || headerValue(headers, "Authorization") !== scope.authorization) {
throw new OpenAIError("X.509 workload identity must preserve its issued workload authorization.");
}
__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_assertTenantHeaders).call(this, headers);
assertSafeHeaders(headers);
}
/** Returns a guarded final dispatcher while preserving all existing request hook object identities. */
fetch() {
return async (input, init = {}) => {
const target = assertX509APIOrigin(typeof input === "string" || input instanceof URL ? input : input.url);
assertX509FetchOptions(init);
this.assertRequest(init);
const approved = init.headers;
if (!(approved instanceof Headers)) {
throw new OpenAIError("X.509 workload identity must preserve its issued workload authorization.");
}
const headers = new Headers([...Headers.prototype.entries.call(approved)]);
assertSafeHeaders(headers);
init.headers = headers;
init.redirect = "manual";
return await __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").dispatch(target, init);
};
}
};
_a = X509WorkloadIdentityAuth, _X509WorkloadIdentityAuth_identityProviderId = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_serviceAccountId = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_configuredRefreshBufferMs = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_configuredRefreshBufferSeconds = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_organization = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_project = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_transport = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_refreshBufferMs = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_cachedToken = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_refresh = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_tokenGeneration = /* @__PURE__ */ new WeakMap(), _X509WorkloadIdentityAuth_instances = /* @__PURE__ */ new WeakSet(), _X509WorkloadIdentityAuth_cancelRequestBody = async function _X509WorkloadIdentityAuth_cancelRequestBody2(body) {
try {
await CancelReadableStream(body);
} catch {
}
}, _X509WorkloadIdentityAuth_assignToken = function _X509WorkloadIdentityAuth_assignToken2(scope, token) {
if (scope) {
scope.token = token.accessToken;
scope.tokenGeneration = token.generation;
}
return token.accessToken;
}, _X509WorkloadIdentityAuth_recoverRefreshFailure = async function _X509WorkloadIdentityAuth_recoverRefreshFailure2(error, attempt, cached, scope, options, context) {
const callerSignal = context ? context.signal : options?.signal;
if (callerSignal?.aborted) {
throw userAbortError(callerSignal);
}
if (attempt.controller.signal.aborted && attempt.generation !== __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_tokenGeneration, "f")) {
return await this.getToken(options, context);
}
const fallback = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_fallbackToken).call(this, error, cached, scope);
if (fallback !== void 0) {
return fallback;
}
if (error && typeof error === "object" && !(error instanceof OAuthError)) {
const oauth = findX509OAuthError2(error);
if (oauth) {
throw new OAuthError(oauth.status, oauth.error, oauth.headers);
}
}
throw error;
}, _X509WorkloadIdentityAuth_fallbackToken = function _X509WorkloadIdentityAuth_fallbackToken2(error, cached, scope) {
if (!cached || cached !== __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_cachedToken, "f") || performance.now() >= cached.expiresAt || Date.now() >= cached.wallExpiresAt || !_a.isRetryableFailure(error)) {
return void 0;
}
const headers = _a.retryHeaders(error);
const milliseconds = headers?.get("retry-after-ms");
let requested = milliseconds ? Number(milliseconds) : void 0;
const retryAfter = headers?.get("retry-after");
if (retryAfter && (requested === void 0 || Number.isNaN(requested))) {
const seconds = Number(retryAfter);
requested = Number.isNaN(seconds) ? Date.parse(retryAfter) - Date.now() : seconds * 1e3;
}
const cooldown = requested !== void 0 && Number.isFinite(requested) && requested >= 0 && requested <= 6e4 ? Math.max(FAILED_REFRESH_COOLDOWN_MS, requested) : FAILED_REFRESH_COOLDOWN_MS;
cached.refreshAt = Math.min(cached.expiresAt, performance.now() + cooldown);
cached.wallRefreshAt = Math.min(cached.wallExpiresAt, Date.now() + cooldown);
return __classPrivateFieldGet(_a, _a, "m", _X509WorkloadIdentityAuth_assignToken).call(_a, scope, cached);
}, _X509WorkloadIdentityAuth_retireRefresh = function _X509WorkloadIdentityAuth_retireRefresh2(attempt) {
if (attempt.waiters !== 0 || __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_refresh, "f") !== attempt) {
return;
}
queueMicrotask(() => {
if (attempt.waiters === 0 && __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_refresh, "f") === attempt) {
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_refresh, void 0, "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_tokenGeneration, __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_tokenGeneration, "f") + 1, "f");
attempt.controller.abort(new APIUserAbortError());
}
});
}, _X509WorkloadIdentityAuth_beginRefresh = function _X509WorkloadIdentityAuth_beginRefresh2() {
const controller = new AbortController();
const generation = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_tokenGeneration, "f");
const attempt = {
controller,
generation,
waiters: 0,
promise: __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_instances, "m", _X509WorkloadIdentityAuth_refreshToken).call(this, controller, generation)
};
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_refresh, attempt, "f");
return attempt;
}, _X509WorkloadIdentityAuth_refreshToken = async function _X509WorkloadIdentityAuth_refreshToken2(controller, generation) {
const startedAt = performance.now();
const wallStartedAt = Date.now();
try {
const token = await __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").exchange(__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_identityProviderId, "f"), __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_serviceAccountId, "f"), controller.signal);
const lifetime = token.expiresIn * 1e3;
const expiresAt = startedAt + lifetime;
const wallExpiresAt = wallStartedAt + lifetime;
if (performance.now() >= expiresAt || Date.now() >= wallExpiresAt) {
throw new OpenAIError("X.509 workload identity token expired before its exchange completed.");
}
if (__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_tokenGeneration, "f") !== generation || controller.signal.aborted || __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_refresh, "f")?.controller !== controller) {
throw new APIUserAbortError();
}
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_tokenGeneration, __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_tokenGeneration, "f") + 1, "f");
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_cachedToken, {
accessToken: token.accessToken,
generation: __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_tokenGeneration, "f"),
expiresAt,
refreshAt: expiresAt - Math.min(__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_refreshBufferMs, "f"), lifetime / 2),
wallExpiresAt,
wallRefreshAt: wallExpiresAt - Math.min(__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_refreshBufferMs, "f"), lifetime / 2)
}, "f");
return token;
} finally {
if (__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_refresh, "f")?.controller === controller) {
__classPrivateFieldSet(this, _X509WorkloadIdentityAuth_refresh, void 0, "f");
}
}
}, _X509WorkloadIdentityAuth_preflight = function _X509WorkloadIdentityAuth_preflight2(context) {
if (!context) {
return;
}
if (context.organization !== __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_organization, "f") || context.project !== __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_project, "f")) {
throw new OpenAIError("X.509 workload identity cannot override its enrolled organization or project.");
}
assertX509APIOrigin(context.apiURL);
const supplied = buildHeaders([context.defaultHeaders, context.requestHeaders]);
if (__classPrivateFieldGet(this, _X509WorkloadIdentityAuth_organization, "f") !== null && supplied.nulls.has("openai-organization") || __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_project, "f") !== null && supplied.nulls.has("openai-project")) {
throw new OpenAIError("X.509 workload identity cannot omit its enrolled organization or project.");
}
for (const name of supplied.values.keys()) {
const canonical2 = name.toLowerCase().split("_").join("-");
if ((canonical2 === "openai-organization" || canonical2 === "openai-project") && (name !== canonical2 || headerValue(supplied.values, name) !== (canonical2 === "openai-organization" ? context.organization : context.project))) {
throw new OpenAIError("X.509 workload identity cannot override its enrolled organization or project.");
}
if (isSensitiveHeader(canonical2) || canonical2 === "host") {
throw new OpenAIError("X.509 workload identity cannot use caller-supplied authentication credentials.");
}
}
}, _X509WorkloadIdentityAuth_scope = function _X509WorkloadIdentityAuth_scope2() {
const scope = __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_transport, "f").current();
if (!scope || scope.owner !== this) {
throw new OpenAIError("X.509 workload identity requires an active certificate request scope.");
}
return scope;
}, _X509WorkloadIdentityAuth_assertTenantHeaders = function _X509WorkloadIdentityAuth_assertTenantHeaders2(headers) {
if (headerValue(headers, "OpenAI-Organization") !== __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_organization, "f") || headerValue(headers, "OpenAI-Project") !== __classPrivateFieldGet(this, _X509WorkloadIdentityAuth_project, "f")) {
throw new OpenAIError("X.509 workload identity cannot override its enrolled organization or project.");
}
for (const name of Headers.prototype.keys.call(headers)) {
const canonical2 = name.toLowerCase().split("_").join("-");
if ((canonical2 === "openai-organization" || canonical2 === "openai-project") && name !== canonical2) {
throw new OpenAIError("X.509 workload identity cannot override its enrolled organization or project.");
}
}
};
}
});
// node_modules/openai/internal/auth/x509-credential-options.mjs
function normalizeX509CredentialOptions(options) {
const { credential } = options;
if (credential === void 0) {
return { credential, options };
}
const registered = findX509Credential2(credential);
if (!registered) {
throw new OpenAIError("An X.509 credential must be created by the SDK authentication helper.");
}
const conflicting = ["apiKey", "adminAPIKey", "workloadIdentity", "x509Transport"].filter((name) => {
const value2 = options[name];
return value2 !== null && value2 !== void 0;
});
if (conflicting.length > 0) {
throw new OpenAIError(`The \`credential\` option cannot be combined with ${conflicting.map((name) => `\`${name}\``).join(", ")}.`);
}
return {
credential,
options: {
...options,
apiKey: null,
adminAPIKey: null,
baseURL: options.baseURL ?? null,
organization: options.organization ?? null,
project: options.project ?? null,
workloadIdentity: registered.identity,
x509Transport: registered.transport
}
};
}
function overridesOrdinaryAuthentication({ apiKey, adminAPIKey }) {
return apiKey !== null && apiKey !== void 0 || adminAPIKey !== null && adminAPIKey !== void 0;
}
function prepareProviderClone(inherited, overrides) {
const inheritedProvider = inherited.provider;
const replacingProvider = overrides.credential ?? overrides.workloadIdentity;
const provider3 = overrides.provider ?? (replacingProvider ? void 0 : inheritedProvider);
if (provider3 !== inheritedProvider) {
delete inherited.baseURL;
delete inherited.organization;
delete inherited.project;
delete inherited.defaultHeaders;
delete inherited.defaultQuery;
delete inherited.fetchOptions;
delete inherited.fetch;
}
if (provider3) {
delete inherited.apiKey;
delete inherited.adminAPIKey;
delete inherited.credential;
delete inherited.workloadIdentity;
delete inherited.x509Transport;
delete inherited.baseURL;
}
return provider3;
}
function prepareX509ClientClone(inherited, overrides, credential, currentlyX509) {
const nextIdentity = hasOwn(overrides, "workloadIdentity") ? overrides.workloadIdentity : inherited.workloadIdentity;
const dropping = credential !== void 0 && (overridesOrdinaryAuthentication(overrides) && overrides.workloadIdentity === void 0 || overrides.provider !== void 0);
if (credential !== void 0 && hasOwn(overrides, "workloadIdentity")) {
delete inherited.x509Transport;
}
const inheritedCredential = credential !== void 0 && !dropping && overrides.credential === void 0 && !hasOwn(overrides, "workloadIdentity") && !hasOwn(overrides, "x509Transport") ? credential : void 0;
const nextCredential = overrides.credential === void 0 ? inheritedCredential : overrides.credential;
const nextX509 = nextCredential !== void 0 || !dropping && isX509WorkloadIdentity(nextIdentity);
if (currentlyX509 !== nextX509) {
delete inherited.fetch;
delete inherited.baseURL;
delete inherited.organization;
delete inherited.project;
delete inherited.defaultHeaders;
delete inherited.defaultQuery;
delete inherited.fetchOptions;
if (nextX509) {
inherited.apiKey = null;
} else {
delete inherited.x509Transport;
if (dropping) {
delete inherited.workloadIdentity;
}
}
}
if (nextCredential !== void 0) {
delete inherited.apiKey;
delete inherited.adminAPIKey;
delete inherited.workloadIdentity;
delete inherited.x509Transport;
inherited.credential = nextCredential;
if (overrides.credential !== void 0) {
delete inherited.organization;
delete inherited.project;
delete inherited.defaultHeaders;
delete inherited.defaultQuery;
delete inherited.fetchOptions;
}
}
return { credential: nextCredential, provider: prepareProviderClone(inherited, overrides) };
}
var init_x509_credential_options = __esm({
"node_modules/openai/internal/auth/x509-credential-options.mjs"() {
init_error();
init_values();
init_x509_workload_identity_auth();
init_x509_transport_state();
}
});
// node_modules/openai/internal/uploads.mjs
function toStreamingFile(data, name, options) {
if (typeof name !== "string" || !name) {
throw new TypeError("toStreamingFile requires a non-empty file name");
}
const type = options?.type;
if (type) {
validateStreamingFileType(type);
}
return {
[brand_privateStreamingFile]: true,
data,
name,
...type ? { type } : {}
};
}
function makeFile(fileBits, fileName, options) {
checkFileSupport();
return new File(fileBits, fileName ?? "unknown_file", options);
}
function getName(value2, options) {
if (typeof value2 !== "object" || value2 === null) {
return void 0;
}
const name = "name" in value2 ? value2.name : void 0;
const explicitName = name && String(name) || "filename" in value2 && value2.filename && String(value2.filename);
if (explicitName) {
return options?.stripFilename === false ? normalizeFilenamePath(explicitName) : basename(explicitName);
}
const url = "url" in value2 && value2.url && String(value2.url);
if (url) {
try {
return basename(new URL(url).pathname);
} catch {
return basename(url);
}
}
const path3 = "path" in value2 && value2.path && String(value2.path);
return path3 ? basename(path3) : void 0;
}
function basename(value2) {
return value2.split(/[\\/]/).pop() || void 0;
}
function normalizeFilenamePath(value2) {
const normalized = value2.replace(/\\/g, "/");
if (normalized.startsWith("/") || /^[A-Za-z]:/.test(normalized) || normalized.split("/").includes("..")) {
throw new TypeError("Upload file name must be a safe relative path without parent directory segments");
}
return normalized;
}
function isArrayBuffer(value2) {
try {
return arrayBufferByteLengthGetter?.call(value2) !== void 0;
} catch {
return false;
}
}
function supportsFormData(fetchObject) {
const fetch2 = typeof fetchObject === "function" ? fetchObject : fetchObject.fetch;
const cached = supportsFormDataMap.get(fetch2);
if (cached) {
return cached;
}
const promise = (async () => {
try {
let FetchResponse;
if ("Response" in fetch2) {
FetchResponse = fetch2.Response;
} else {
const response = await fetch2("data:,");
await response.arrayBuffer();
FetchResponse = response.constructor;
}
const data = new FormData();
if (data.toString() === await new FetchResponse(data).text()) {
return false;
}
return true;
} catch {
return true;
}
})();
supportsFormDataMap.set(fetch2, promise);
return promise;
}
async function* iterateMultipartBody(entries2, boundary, options, preservedFilenames) {
for await (const { key, value: value2 } of entries2) {
if (isUploadable(value2)) {
const filename = preservedFilenames?.get(value2) ?? getStreamingFileName(value2, options);
const type = getStreamingFileType(value2);
yield encodeUTF8(`--${boundary}\r
`);
yield encodeUTF8(`Content-Disposition: form-data; name="${escapeHeaderValue(key)}"; filename="${escapeHeaderValue(filename)}"\r
Content-Type: ${type}\r
\r
`);
yield* iterateBytes(getStreamingFileData(value2));
} else {
yield encodeUTF8(`--${boundary}\r
`);
yield encodeUTF8(`Content-Disposition: form-data; name="${escapeHeaderValue(key)}"\r
\r
${String(value2)}`);
}
yield encodeUTF8("\r\n");
}
yield encodeUTF8(`--${boundary}--\r
`);
}
function* iterateFormEntries(body) {
if (!body || typeof body !== "object") {
return;
}
for (const [key, value2] of Object.entries(body)) {
yield* iterateFormValue(key, value2);
}
}
function* iterateFormValue(key, value2) {
if (value2 === void 0) {
return;
}
if (value2 == null) {
throw new TypeError(`Received null for "${key}"; to pass null in FormData, you must use the string 'null'`);
}
if (typeof value2 === "string" || typeof value2 === "number" || typeof value2 === "boolean" || isUploadable(value2)) {
yield { key, value: value2 };
} else if (Array.isArray(value2)) {
for (const entry2 of value2) {
yield* iterateFormValue(key + "[]", entry2);
}
} else if (typeof value2 === "object") {
for (const [name, prop] of Object.entries(value2)) {
yield* iterateFormValue(`${key}[${name}]`, prop);
}
} else {
throw new TypeError(`Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value2} instead`);
}
}
function getStreamingFileName(value2, options) {
if (isStreamingFile(value2)) {
const { name } = value2;
if (typeof name !== "string" || !name) {
throw new TypeError("Streaming upload file name must be a non-empty string");
}
return options.stripFilenames === false ? normalizeFilenamePath(name) : basename(name) ?? "unknown_file";
}
return getName(value2, { stripFilename: options.stripFilenames }) ?? "unknown_file";
}
function getStreamingFileType(value2) {
let type;
if (isStreamingFile(value2) || isBlob(value2)) {
({ type } = value2);
} else if (value2 instanceof Response) {
type = value2.headers.get("content-type") ?? void 0;
}
return validateStreamingFileType(type || "application/octet-stream");
}
function validateStreamingFileType(type) {
if (typeof type !== "string") {
throw new TypeError("Streaming upload content type must be a string");
}
for (let index = 0; index < type.length; index += 1) {
const character = type.codePointAt(index) ?? 0;
if (character <= 31 || character === 127) {
throw new TypeError("Streaming upload content type must not contain control characters");
}
}
return type;
}
function getStreamingFileData(value2) {
if (isStreamingFile(value2)) {
return value2.data;
}
return value2;
}
async function* iterateBytes(value2) {
if (typeof value2 === "string") {
yield encodeUTF8(value2);
} else if (ArrayBuffer.isView(value2)) {
yield new Uint8Array(value2.buffer, value2.byteOffset, value2.byteLength);
} else if (isArrayBuffer(value2)) {
yield new Uint8Array(value2);
} else if (value2 instanceof Response) {
yield* iterateBytes(value2.body || await value2.blob());
} else if (value2 instanceof Blob) {
if (typeof value2.stream === "function") {
yield* iterateBytes(value2.stream());
} else {
yield new Uint8Array(await value2.arrayBuffer());
}
} else if (isReadableStream(value2)) {
for await (const chunk of ReadableStreamToAsyncIterable(value2)) {
yield* iterateBytes(chunk);
}
} else if (isAsyncIterable(value2)) {
for await (const chunk of value2) {
yield* iterateBytes(chunk);
}
} else {
throw new TypeError(`Invalid streaming file chunk: ${String(value2)}`);
}
}
function escapeHeaderValue(value2) {
return Array.from(value2, (character) => {
const codePoint = character.codePointAt(0) ?? 0;
return codePoint <= 31 || codePoint === 127 || character === '"' || character === "\\" ? encodeURIComponent(character) : character;
}).join("");
}
var brand_privateStreamingFile, checkFileSupport, arrayBufferByteLengthGetter, isAsyncIterable, maybeMultipartFormRequestOptions, multipartFormRequestOptions, supportsFormDataMap, createForm, isBlob, isReadableStream, isStreamingFile, isUploadable, hasStreamingUploadableValue, hasUploadableValue, snapshotPreservedUploadEntries, createStreamingFormRequestOptions, addFormValue;
var init_uploads = __esm({
"node_modules/openai/internal/uploads.mjs"() {
init_headers2();
init_shims();
init_bytes();
brand_privateStreamingFile = /* @__PURE__ */ Symbol("brand.privateStreamingFile");
checkFileSupport = () => {
if (typeof File === "undefined") {
const { process: process2 } = globalThis;
const isOldNode = typeof process2?.versions?.node === "string" && Number.parseInt(process2.versions.node.split("."), 10) < 20;
throw new Error("`File` is not defined as a global, which is required for file uploads." + (isOldNode ? " Update to a supported Node.js LTS release, or set `globalThis.File` to `import('node:buffer').File`." : ""));
}
};
arrayBufferByteLengthGetter = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength")?.get;
isAsyncIterable = (value2) => value2 != null && typeof value2 === "object" && typeof value2[Symbol.asyncIterator] === "function";
maybeMultipartFormRequestOptions = async (opts, fetch2, formOptions) => {
if (!hasUploadableValue(opts.body)) {
return opts;
}
if (hasStreamingUploadableValue(opts.body)) {
return createStreamingFormRequestOptions(opts, formOptions);
}
return { ...opts, body: await createForm(opts.body, fetch2, formOptions) };
};
multipartFormRequestOptions = async (opts, fetch2, formOptions) => {
if (hasStreamingUploadableValue(opts.body)) {
return createStreamingFormRequestOptions(opts, formOptions);
}
return { ...opts, body: await createForm(opts.body, fetch2, formOptions) };
};
supportsFormDataMap = /* @__PURE__ */ new WeakMap();
createForm = async (body, fetch2, options = {}) => {
if (!await supportsFormData(fetch2)) {
throw new TypeError("The provided fetch function does not support file uploads with the current global FormData class.");
}
const form = new FormData();
await Promise.all(Object.entries(body || {}).map(([key, value2]) => addFormValue(form, key, value2, options)));
return form;
};
isBlob = (value2) => value2 instanceof Blob;
isReadableStream = (value2) => typeof value2 === "object" && value2 !== null && "getReader" in value2 && typeof value2.getReader === "function";
isStreamingFile = (value2) => typeof value2 === "object" && value2 !== null && brand_privateStreamingFile in value2;
isUploadable = (value2) => typeof value2 === "object" && value2 !== null && (value2 instanceof Response || isAsyncIterable(value2) || isReadableStream(value2) || isStreamingFile(value2) || isBlob(value2));
hasStreamingUploadableValue = (value2) => {
if (isStreamingFile(value2) || isAsyncIterable(value2) || isReadableStream(value2)) {
return true;
}
if (Array.isArray(value2)) {
return value2.some(hasStreamingUploadableValue);
}
if (value2 && typeof value2 === "object" && !isBlob(value2) && !(value2 instanceof Response)) {
for (const k of Object.keys(value2)) {
if (hasStreamingUploadableValue(value2[k])) {
return true;
}
}
}
return false;
};
hasUploadableValue = (value2) => {
if (isUploadable(value2)) {
return true;
}
if (Array.isArray(value2)) {
return value2.some(hasUploadableValue);
}
if (value2 && typeof value2 === "object") {
for (const k of Object.keys(value2)) {
if (hasUploadableValue(value2[k])) {
return true;
}
}
}
return false;
};
snapshotPreservedUploadEntries = (entries2, filenames) => {
const snapshot = [];
for (const entry2 of entries2) {
if (isUploadable(entry2.value) && !filenames.has(entry2.value)) {
filenames.set(entry2.value, getStreamingFileName(entry2.value, { stripFilenames: false }));
}
snapshot.push(entry2);
}
return snapshot;
};
createStreamingFormRequestOptions = (opts, options = {}) => {
const entries2 = iterateFormEntries(opts.body);
const preservedFilenames = options.stripFilenames === false ? /* @__PURE__ */ new WeakMap() : void 0;
const multipartEntries = preservedFilenames ? snapshotPreservedUploadEntries(entries2, preservedFilenames) : entries2;
const boundary = `openai-${Math.random().toString(36).slice(2)}`;
const body = ReadableStreamFrom(iterateMultipartBody(multipartEntries, boundary, options, preservedFilenames));
return {
...opts,
body,
headers: buildHeaders([{ "content-type": `multipart/form-data; boundary=${boundary}` }, opts.headers])
};
};
addFormValue = async (form, key, value2, options) => {
if (value2 === void 0) {
return;
}
if (value2 == null) {
throw new TypeError(`Received null for "${key}"; to pass null in FormData, you must use the string 'null'`);
}
if (typeof value2 === "string" || typeof value2 === "number" || typeof value2 === "boolean") {
form.append(key, String(value2));
} else if (value2 instanceof Response) {
const blob = await value2.blob();
form.append(key, makeFile([blob], getName(value2, { stripFilename: options.stripFilenames }), { type: blob.type }));
} else if (isAsyncIterable(value2)) {
form.append(key, makeFile([await new Response(ReadableStreamFrom(value2)).blob()], getName(value2, { stripFilename: options.stripFilenames })));
} else if (isBlob(value2)) {
const filename = getName(value2, { stripFilename: options.stripFilenames });
if (filename === void 0) {
form.append(key, value2);
} else {
form.append(key, value2, filename);
}
} else if (Array.isArray(value2)) {
const entries2 = await Promise.all(value2.map(async (entry2) => {
const entryForm = new FormData();
await addFormValue(entryForm, key + "[]", entry2, options);
return entryForm;
}));
for (const entryForm of entries2) {
if (!entryForm) {
continue;
}
for (const [entryKey2, entryValue] of entryForm.entries()) {
form.append(entryKey2, entryValue);
}
}
} else if (typeof value2 === "object") {
await Promise.all(Object.entries(value2).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop, options)));
} else {
throw new TypeError(`Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value2} instead`);
}
};
}
});
// node_modules/openai/internal/to-file.mjs
async function toFile(value2, name, options) {
checkFileSupport();
value2 = await value2;
if (isFileLike(value2)) {
const fileOptions = {
...options,
type: options?.type ?? value2.type,
lastModified: options?.lastModified ?? value2.lastModified
};
if (value2 instanceof File) {
if (canReuseNativeFile(value2, name, options)) {
return value2;
}
return makeFile([value2], name ?? value2.name, fileOptions);
}
return makeFile([await value2.arrayBuffer()], name ?? value2.name, fileOptions);
}
if (isResponseLike(value2)) {
const blob = await value2.blob();
name ?? (name = getName(value2));
const responseOptions = options?.type === void 0 && blob.type ? { ...options, type: blob.type } : options;
return makeFile(await getBytes(blob), name, responseOptions);
}
const parts = await getBytes(value2);
name ?? (name = getName(value2));
if (options?.type === void 0) {
const typedPart = parts.find((part) => typeof part === "object" && "type" in part && !!part.type);
if (typedPart) {
options = { ...options, type: typedPart.type };
}
}
return makeFile(parts, name, options);
}
async function getBytes(value2) {
const parts = [];
if (typeof value2 === "string" || ArrayBuffer.isView(value2) || // includes Uint8Array, Buffer, etc.
isArrayBuffer(value2)) {
parts.push(value2);
} else if (isBlobLike(value2)) {
parts.push(value2 instanceof Blob ? value2 : new Blob([await value2.arrayBuffer()], { type: value2.type }));
} else if (isAsyncIterable(value2)) {
for await (const chunk of value2) {
parts.push(...await getBytes(chunk));
}
} else {
const constructor = value2?.constructor?.name;
throw new Error(`Unexpected data type: ${typeof value2}${constructor ? `; constructor: ${constructor}` : ""}${propsForError(value2)}`);
}
return parts;
}
function propsForError(value2) {
if (typeof value2 !== "object" || value2 === null) {
return "";
}
const props = Object.getOwnPropertyNames(value2);
return `; props: [${props.map((p) => `"${p}"`).join(", ")}]`;
}
var isBlobLike, isFileLike, isResponseLike, hasFilePropertyOverrides, canReuseNativeFile;
var init_to_file = __esm({
"node_modules/openai/internal/to-file.mjs"() {
init_uploads();
isBlobLike = (value2) => value2 != null && typeof value2 === "object" && typeof value2.size === "number" && typeof value2.type === "string" && typeof value2.text === "function" && typeof value2.slice === "function" && typeof value2.arrayBuffer === "function";
isFileLike = (value2) => value2 != null && typeof value2 === "object" && typeof value2.name === "string" && typeof value2.lastModified === "number" && isBlobLike(value2);
isResponseLike = (value2) => value2 != null && typeof value2 === "object" && typeof value2.url === "string" && typeof value2.blob === "function";
hasFilePropertyOverrides = (value2, options) => options?.type != null && options.type !== value2.type || options?.lastModified != null && options.lastModified !== value2.lastModified || options?.endings != null;
canReuseNativeFile = (value2, name, options) => (name == null || name === value2.name) && !hasFilePropertyOverrides(value2, options);
}
});
// node_modules/openai/core/uploads.mjs
var init_uploads2 = __esm({
"node_modules/openai/core/uploads.mjs"() {
init_uploads();
init_to_file();
}
});
// node_modules/openai/core/resource.mjs
var APIResource;
var init_resource = __esm({
"node_modules/openai/core/resource.mjs"() {
APIResource = class {
constructor(client) {
this._client = client;
}
};
}
});
// node_modules/openai/internal/utils/path.mjs
function encodeURIPath(str2) {
return str2.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
}
var EMPTY, createPathTagFunction, path;
var init_path = __esm({
"node_modules/openai/internal/utils/path.mjs"() {
init_error();
EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
createPathTagFunction = (pathEncoder = encodeURIPath) => function path3(statics, ...params) {
if (statics.length === 1) {
return statics[0];
}
let postPath = false;
const invalidSegments = [];
let path4 = "";
for (let index = 0; index < statics.length; index += 1) {
if (index in statics) {
const currentValue = statics[index];
if (/[?#]/.test(currentValue)) {
postPath = true;
}
const value2 = params[index];
let encoded = (postPath ? encodeURIComponent : pathEncoder)("" + value2);
if (index !== params.length && (value2 == null || // oxlint-disable-next-line anti-slop/no-runtime-typeof -- Path parameters may arrive from JavaScript callers and require runtime validation before URL encoding.
typeof value2 === "object" && // handle values from other realms
value2.toString === Object.getPrototypeOf(Object.getPrototypeOf(value2.hasOwnProperty ?? EMPTY) ?? EMPTY)?.toString)) {
encoded = value2 + "";
invalidSegments.push({
start: path4.length + currentValue.length,
length: encoded.length,
error: `Value of type ${Object.prototype.toString.call(value2).slice(8, -1)} is not a valid path parameter`
});
}
path4 += currentValue + (index === params.length ? "" : encoded);
}
}
const pathOnly = path4.split(/[?#]/, 1)[0];
const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
let match;
while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
invalidSegments.push({
start: match.index,
length: match[0].length,
error: `Value "${match[0]}" can't be safely passed as a path parameter`
});
}
invalidSegments.sort((a, b) => a.start - b.start);
if (invalidSegments.length > 0) {
let lastEnd = 0;
let underline = "";
for (const segment of invalidSegments) {
const spaces = " ".repeat(segment.start - lastEnd);
const arrows = "^".repeat(segment.length);
lastEnd = segment.start + segment.length;
underline += spaces + arrows;
}
throw new OpenAIError(`Path parameters result in path with invalid segments:
${invalidSegments.map((e) => e.error).join("\n")}
${path4}
${underline}`);
}
return path4;
};
path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
}
});
// node_modules/openai/resources/chat/completions/messages.mjs
var Messages;
var init_messages = __esm({
"node_modules/openai/resources/chat/completions/messages.mjs"() {
init_resource();
init_pagination();
init_path();
Messages = class extends APIResource {
/**
* Get the messages in a stored chat completion. Only Chat Completions that have
* been created with the `store` parameter set to `true` will be returned.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const chatCompletionStoreMessage of client.chat.completions.messages.list(
* 'completion_id',
* )) {
* // ...
* }
* ```
*/
list(completionID, query = {}, options) {
return this._client.getAPIList(path`/chat/completions/${completionID}/messages`, CursorPage, { query, ...options, __security: { bearerAuth: true } });
}
};
}
});
// node_modules/openai/error.mjs
var init_error2 = __esm({
"node_modules/openai/error.mjs"() {
init_error();
}
});
// node_modules/openai/lib/parser.mjs
function isChatCompletionFunctionTool(tool) {
return tool !== void 0 && "function" in tool && tool.function !== void 0;
}
function isAutoParsableResponseFormat(response_format) {
return response_format?.["$brand"] === "auto-parseable-response-format";
}
function isParseableResponseFormat(format) {
return isAutoParsableResponseFormat(format) || format?.type === "json_schema";
}
function parseResponseFormatContent(format, content) {
if (!isParseableResponseFormat(format)) {
return null;
}
if (typeof format === "object" && format !== null && "$parseRaw" in format && typeof format.$parseRaw === "function") {
return format.$parseRaw(content);
}
try {
return JSON.parse(content);
} catch (error) {
if (error instanceof SyntaxError) {
throw new SyntaxError("Error reading response: invalid structured output JSON.");
}
throw error;
}
}
function isAutoParsableTool(tool) {
return tool?.["$brand"] === "auto-parseable-tool";
}
function maybeParseChatCompletion(completion, params) {
if (!params || !hasAutoParseableInput(params)) {
return {
...completion,
choices: completion.choices.map((choice) => ({
...choice,
message: {
...choice.message,
parsed: null,
...choice.message.tool_calls ? {
tool_calls: choice.message.tool_calls
} : void 0
}
}))
};
}
return parseChatCompletion(completion, params);
}
function parseChatCompletion(completion, params) {
const choices = completion.choices.map((choice) => {
if (choice.finish_reason === "length") {
throw new LengthFinishReasonError();
}
if (choice.finish_reason === "content_filter") {
throw new ContentFilterFinishReasonError();
}
return {
...choice,
message: {
...choice.message,
...choice.message.tool_calls ? {
tool_calls: choice.message.tool_calls?.map((toolCall) => parseToolCall(params, toolCall)) ?? void 0
} : void 0,
parsed: choice.message.content !== null && choice.message.content !== void 0 && !choice.message.refusal && (choice.message.content !== "" || !choice.message.tool_calls?.length && !choice.message.function_call) ? parseResponseFormat(params, choice.message.content) : null
}
};
});
return { ...completion, choices };
}
function parseResponseFormat(params, content) {
return parseResponseFormatContent(params.response_format, content);
}
function parseToolCall(params, toolCall) {
if (toolCall.type === "custom") {
return toolCall;
}
if (toolCall.type !== "function") {
const unsupportedType = toolCall.type;
throw new OpenAIError(`Currently only \`function\` and \`custom\` tool calls are supported; Received \`${unsupportedType}\``);
}
const inputTool = params.tools?.find((inputTool2) => isChatCompletionFunctionTool(inputTool2) && inputTool2.function?.name === toolCall.function.name);
let parsedArguments = null;
if (isAutoParsableTool(inputTool)) {
parsedArguments = inputTool.$parseRaw(toolCall.function.arguments);
} else if (inputTool?.function.strict) {
parsedArguments = parseResponseFormatContent({ type: "json_schema", $parseRaw: void 0 }, toolCall.function.arguments);
}
return {
...toolCall,
function: {
...toolCall.function,
parsed_arguments: parsedArguments
}
};
}
function shouldParseToolCall(params, toolCall) {
if (!params || !("tools" in params) || !params.tools || toolCall.type !== "function") {
return false;
}
const inputTool = params.tools?.find((inputTool2) => isChatCompletionFunctionTool(inputTool2) && inputTool2.function?.name === toolCall.function?.name);
return isChatCompletionFunctionTool(inputTool) && (isAutoParsableTool(inputTool) || inputTool?.function.strict || false);
}
function hasAutoParseableInput(params) {
if (isParseableResponseFormat(params.response_format)) {
return true;
}
return params.tools?.some((t) => isAutoParsableTool(t) || t.type === "function" && t.function.strict === true) ?? false;
}
function validateInputTools(tools) {
for (const tool of tools ?? []) {
if (tool.type === "custom") {
continue;
}
if (tool.type !== "function") {
const unsupportedType = tool.type;
throw new OpenAIError(`Currently only \`function\` and \`custom\` tool types are supported; Received \`${unsupportedType}\``);
}
if (tool.function.strict !== true) {
throw new OpenAIError(`The \`${tool.function.name}\` tool is not marked with \`strict: true\`. Only strict function tools can be auto-parsed`);
}
}
}
var init_parser = __esm({
"node_modules/openai/lib/parser.mjs"() {
init_error2();
}
});
// node_modules/openai/lib/chatCompletionUtils.mjs
var isAssistantMessage, isToolMessage;
var init_chatCompletionUtils = __esm({
"node_modules/openai/lib/chatCompletionUtils.mjs"() {
isAssistantMessage = (message) => message?.role === "assistant";
isToolMessage = (message) => message?.role === "tool";
}
});
// node_modules/openai/lib/EventStream.mjs
function captureNativeProxyDetector() {
if (typeof process === "undefined") {
return void 0;
}
try {
const loader = Object.getOwnPropertyDescriptor(process, "getBuiltinModule");
if (!loader || !("value" in loader) || typeof loader.value !== "function") {
return void 0;
}
const util = Reflect.apply(loader.value, process, ["node:util"]);
if (typeof util !== "object" || util === null) {
return void 0;
}
const types = Object.getOwnPropertyDescriptor(util, "types");
if (!types || !("value" in types) || typeof types.value !== "object" || types.value === null) {
return void 0;
}
const detector = Object.getOwnPropertyDescriptor(types.value, "isProxy");
if (!detector || !("value" in detector) || typeof detector.value !== "function") {
return void 0;
}
return detector.value;
} catch {
return void 0;
}
}
function rememberTrustedIntrinsic(constructor) {
if (typeof constructor !== "function") {
return;
}
const prototypeDescriptor = Object.getOwnPropertyDescriptor(constructor, "prototype");
if (!prototypeDescriptor || !("value" in prototypeDescriptor) || typeof prototypeDescriptor.value !== "object" && typeof prototypeDescriptor.value !== "function") {
return;
}
trustedIntrinsicPrototypes.add(prototypeDescriptor.value);
const source = functionToString.call(constructor);
if (/^function [A-Za-z_$][\w$]*\(\) \{ \[native code\] \}$/u.test(source) && prototypeDescriptor.configurable === false && prototypeDescriptor.writable === false) {
trustedNativeConstructorSources.add(source);
const descriptors = /* @__PURE__ */ new Map();
for (const key of Reflect.ownKeys(prototypeDescriptor.value)) {
const descriptor = Object.getOwnPropertyDescriptor(prototypeDescriptor.value, key);
if (descriptor) {
descriptors.set(key, descriptor);
}
}
canonicalIntrinsicDescriptors.set(source, descriptors);
}
}
function getTrustedForeignIntrinsic(prototype) {
const descriptor = Object.getOwnPropertyDescriptor(prototype, "constructor");
if (!descriptor || !("value" in descriptor) || typeof descriptor.value !== "function") {
return void 0;
}
const constructor = descriptor.value;
const source = functionToString.call(constructor);
const descriptors = canonicalIntrinsicDescriptors.get(source);
if (!trustedNativeConstructorSources.has(source) || !descriptors) {
return void 0;
}
const constructorPrototype = Object.getOwnPropertyDescriptor(constructor, "prototype");
if (!constructorPrototype || !("value" in constructorPrototype) || constructorPrototype.value !== prototype || constructorPrototype.configurable !== false || constructorPrototype.writable !== false) {
return void 0;
}
return { constructor, descriptors, functionPrototype: Object.getPrototypeOf(constructor) };
}
function isTrustedIntrinsicPrototype(prototype) {
return trustedIntrinsicPrototypes.has(prototype) || getTrustedForeignIntrinsic(prototype) !== void 0;
}
function isCanonicalIntrinsicFunction(value2, canonical2, functionPrototype) {
if (canonical2 === void 0) {
return value2 === void 0;
}
if (typeof value2 !== "function" || typeof canonical2 !== "function") {
return false;
}
const source = functionToString.call(canonical2);
if (functionToString.call(value2) !== source) {
return false;
}
const actualFunctionPrototype = Object.getPrototypeOf(value2);
if (actualFunctionPrototype === functionPrototype) {
return true;
}
if (!/^function [A-Za-z_$][\w$]*\(\) \{ \[native code\] \}$/u.test(source)) {
return false;
}
const intrinsic = getTrustedForeignIntrinsic(actualFunctionPrototype);
return intrinsic !== void 0 && functionToString.call(intrinsic.constructor) === nativeFunctionConstructorSource;
}
function isCanonicalIntrinsicDescriptor(descriptor, canonical2, functionPrototype) {
if (!canonical2 || descriptor.configurable !== canonical2.configurable || descriptor.enumerable !== canonical2.enumerable || "value" in descriptor !== "value" in canonical2) {
return false;
}
if ("value" in descriptor && "value" in canonical2) {
if (descriptor.writable !== canonical2.writable) {
return false;
}
if (typeof canonical2.value === "function") {
return isCanonicalIntrinsicFunction(descriptor.value, canonical2.value, functionPrototype);
}
if (canonical2.value !== null && typeof canonical2.value === "object") {
return false;
}
return Object.is(descriptor.value, canonical2.value);
}
return isCanonicalIntrinsicFunction(descriptor.get, canonical2.get, functionPrototype) && isCanonicalIntrinsicFunction(descriptor.set, canonical2.set, functionPrototype);
}
function hasNativeErrorBrand(current) {
if (nativeErrorBrand) {
return nativeErrorBrand.call(Error, current);
}
let prototype = current;
for (let depth = 0; prototype !== null && depth < MAX_BUFFERED_EVENT_DEPTH; depth += 1) {
if (Object.getOwnPropertyDescriptor(prototype, Symbol.toStringTag)) {
return false;
}
prototype = Object.getPrototypeOf(prototype);
}
return prototype === null && objectToString.call(current) === "[object Error]";
}
function getVerifiedForeignErrorConstructor(current, stackDescriptor) {
if (typeof stackDescriptor.get !== "function" || typeof stackDescriptor.set !== "function") {
return void 0;
}
let prototype = Object.getPrototypeOf(current);
for (let depth = 0; prototype !== null && depth < MAX_BUFFERED_EVENT_DEPTH; depth += 1) {
const descriptor = Object.getOwnPropertyDescriptor(prototype, "constructor");
if (descriptor && "value" in descriptor && typeof descriptor.value === "function") {
const constructor = descriptor.value;
if (functionToString.call(constructor) === nativeErrorConstructorSource && isTrustedIntrinsicPrototype(prototype)) {
const functionPrototype = Object.getPrototypeOf(constructor);
if (Object.getPrototypeOf(stackDescriptor.get) === functionPrototype && Object.getPrototypeOf(stackDescriptor.set) === functionPrototype) {
return { constructor, prototype };
}
return void 0;
}
}
prototype = Object.getPrototypeOf(prototype);
}
return void 0;
}
function isTrustedNativeErrorStack(current, descriptor) {
if (!hasNativeErrorBrand(current)) {
return false;
}
if (errorStackDescriptor && !("value" in errorStackDescriptor) && typeof errorStackDescriptor.get === "function" && Object.prototype.isPrototypeOf.call(Error.prototype, current) && descriptor.get === errorStackDescriptor.get && descriptor.set === errorStackDescriptor.set) {
return true;
}
const verified = getVerifiedForeignErrorConstructor(current, descriptor);
if (!verified) {
return false;
}
let canonicalDescriptor = foreignErrorStackDescriptors.get(verified.prototype);
if (!canonicalDescriptor) {
const canonical2 = Reflect.construct(verified.constructor, []);
if (typeof canonical2 !== "object" || canonical2 === null || !hasNativeErrorBrand(canonical2) || Object.getPrototypeOf(canonical2) !== verified.prototype) {
return false;
}
canonicalDescriptor = Object.getOwnPropertyDescriptor(canonical2, "stack");
if (!canonicalDescriptor || "value" in canonicalDescriptor || typeof canonicalDescriptor.get !== "function" || typeof canonicalDescriptor.set !== "function") {
return false;
}
foreignErrorStackDescriptors.set(verified.prototype, canonicalDescriptor);
}
return descriptor.get === canonicalDescriptor.get && descriptor.set === canonicalDescriptor.set;
}
function createEventQueue() {
let entries2 = [];
let head = 0;
return {
get length() {
return entries2.length - head;
},
enqueue(value2) {
entries2.push(value2);
},
dequeue() {
if (head === entries2.length) {
return void 0;
}
const value2 = entries2[head];
entries2[head] = void 0;
head += 1;
if (head === entries2.length) {
entries2 = [];
head = 0;
} else if (head >= 1024 && head * 2 >= entries2.length) {
entries2 = entries2.slice(head);
head = 0;
}
return value2;
},
clear() {
entries2 = [];
head = 0;
}
};
}
function getRetainedStorageBrand(current) {
let prototype = Object.getPrototypeOf(current);
for (let depth = 0; prototype !== null && depth < MAX_BUFFERED_EVENT_DEPTH; depth += 1) {
if (prototype === Date.prototype) {
return "Date";
}
if (!trustedIntrinsicPrototypes.has(prototype)) {
const constructor = Object.getOwnPropertyDescriptor(prototype, "constructor");
if (constructor && "value" in constructor && typeof constructor.value === "function" && functionToString.call(constructor.value) === nativeDateConstructorSource && getTrustedForeignIntrinsic(prototype)) {
return "Date";
}
}
const descriptor = Object.getOwnPropertyDescriptor(prototype, Symbol.toStringTag);
if (descriptor && "value" in descriptor && typeof descriptor.value === "string" && retainedStorageBrands.has(descriptor.value)) {
return descriptor.value;
}
prototype = Object.getPrototypeOf(prototype);
}
return void 0;
}
function estimateRetainedBufferBytes(current, visit, depth) {
if (ArrayBuffer.isView(current)) {
let buffer;
let kind2 = "typed-array";
try {
buffer = typedArrayBufferGetter?.call(current);
} catch {
kind2 = "data-view";
buffer = dataViewBufferGetter?.call(current);
}
if (typeof buffer !== "object" || buffer === null) {
return { bytes: Number.POSITIVE_INFINITY, kind: kind2 };
}
visit(buffer, depth + 1);
return { bytes: 0, kind: kind2 };
}
const brand = getRetainedStorageBrand(current);
if (!brand) {
return void 0;
}
let getter;
const kind = "buffer";
switch (brand) {
case "ArrayBuffer": {
getter = arrayBufferByteLengthGetter2;
break;
}
case "SharedArrayBuffer": {
getter = sharedArrayBufferByteLengthGetter;
break;
}
case "Blob":
case "File": {
return { bytes: Number.POSITIVE_INFINITY, kind: "blob" };
}
case "Map": {
return { bytes: 0, kind: "map" };
}
case "Date": {
Reflect.apply(dateTimestampGetter, current, []);
return { bytes: 8, kind: "date" };
}
case "Set": {
return { bytes: 0, kind: "set" };
}
case "Headers": {
return { bytes: 0, kind: "headers" };
}
default: {
return void 0;
}
}
const bytes2 = getter?.call(current);
return {
bytes: typeof bytes2 === "number" && Number.isSafeInteger(bytes2) && bytes2 >= 0 ? bytes2 : Number.POSITIVE_INFINITY,
kind
};
}
function visitHiddenEventValues(current, kind, visit) {
if (kind === "map") {
for (const [key, entry2] of mapEntries.call(current)) {
if (!visit(key, 8) || !visit(entry2, 8)) {
return false;
}
}
}
if (kind === "set") {
for (const entry2 of setValues.call(current)) {
if (!visit(entry2, 8)) {
return false;
}
}
}
if (kind === "headers") {
if (!headersEntries) {
return false;
}
for (const [name, value2] of headersEntries.call(current)) {
if (!visit(name, 8) || !visit(value2, 8)) {
return false;
}
}
}
return true;
}
function getInspectableEventKeys(current, kind, availableBytes) {
if (Array.isArray(current)) {
const descriptor = Object.getOwnPropertyDescriptor(current, "length");
const length2 = descriptor && "value" in descriptor ? descriptor.value : void 0;
if (typeof length2 !== "number" || !Number.isSafeInteger(length2) || length2 < 0 || length2 > Math.floor(availableBytes / 16)) {
return void 0;
}
}
if (kind !== "typed-array") {
return Reflect.ownKeys(current);
}
const length = typedArrayLengthGetter?.call(current);
if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || length > MAX_INSPECTABLE_TYPED_ARRAY_ELEMENTS) {
return void 0;
}
return Reflect.ownKeys(current).filter((key) => {
if (typeof key !== "string") {
return true;
}
const index = Number(key);
return !Number.isInteger(index) || index < 0 || index >= length || String(index) !== key;
});
}
function visitInspectableEventProperties(current, kind, depth, availableBytes, charge, visit) {
const keys = getInspectableEventKeys(current, kind, availableBytes());
if (keys === void 0) {
return false;
}
for (const key of keys) {
if (!charge(typeof key === "string" ? key.length * 2 + 8 : 8)) {
return false;
}
if (typeof key === "symbol") {
visit(key, depth + 1);
}
const descriptor = Object.getOwnPropertyDescriptor(current, key);
if (!descriptor) {
return false;
}
if (!("value" in descriptor)) {
if (key === "stack" && isTrustedNativeErrorStack(current, descriptor)) {
continue;
}
return false;
}
visit(descriptor.value, depth + 1, kind === "blob");
}
return true;
}
function visitRetainedEventPrototypes(current, depth, isBlobInternalHandle, visited, availableBytes, charge, visit, retainPrototype) {
let prototype = Object.getPrototypeOf(current);
for (let prototypeDepth = depth + 1; prototype !== null; prototypeDepth += 1) {
if (prototypeDepth >= MAX_BUFFERED_EVENT_DEPTH) {
return false;
}
if (trustedIntrinsicPrototypes.has(prototype) || isBlobInternalHandle && prototype === blobInternalHandlePrototype) {
return true;
}
if (visited.has(prototype)) {
visit(prototype, prototypeDepth);
return availableBytes() >= 0;
}
visited.add(prototype);
const retainedPrototype = prototype;
const retained = retainPrototype(retainedPrototype, () => {
if (!charge(16)) {
return false;
}
const intrinsic = getTrustedForeignIntrinsic(retainedPrototype);
if (!intrinsic) {
return visitInspectableEventProperties(retainedPrototype, void 0, prototypeDepth, availableBytes, charge, visit);
}
for (const key of Reflect.ownKeys(retainedPrototype)) {
const descriptor = Object.getOwnPropertyDescriptor(retainedPrototype, key);
if (!descriptor) {
return false;
}
if (isCanonicalIntrinsicDescriptor(descriptor, intrinsic.descriptors.get(key), intrinsic.functionPrototype)) {
continue;
}
if (!charge(typeof key === "string" ? key.length * 2 + 8 : 8) || !("value" in descriptor)) {
return false;
}
if (typeof key === "symbol") {
visit(key, prototypeDepth + 1);
}
visit(descriptor.value, prototypeDepth + 1);
}
return availableBytes() >= 0;
});
if (!retained) {
return false;
}
prototype = Object.getPrototypeOf(retainedPrototype);
}
return true;
}
function inspectBufferedEventGraph(value2, remainingBytes) {
let bytes2 = 0;
let scalarBytes = 0;
const visited = /* @__PURE__ */ new WeakSet();
const visitedSymbols = /* @__PURE__ */ new Set();
const roots = /* @__PURE__ */ new Set();
const nodes = /* @__PURE__ */ new Map();
let activeNode;
const availableBytes = () => remainingBytes - bytes2;
const charge = (amount) => {
if (!Number.isSafeInteger(amount) || amount < 0) {
bytes2 = remainingBytes + 1;
return false;
}
bytes2 += amount;
if (activeNode) {
activeNode.bytes += amount;
} else {
scalarBytes += amount;
}
return bytes2 <= remainingBytes;
};
const addIdentity = (identity) => {
if (activeNode) {
activeNode.edges.add(identity);
} else {
roots.add(identity);
}
};
const retainIdentity = (identity, inspect) => {
addIdentity(identity);
const node = { bytes: 0, edges: /* @__PURE__ */ new Set() };
nodes.set(identity, node);
const previous = activeNode;
activeNode = node;
try {
return inspect();
} finally {
activeNode = previous;
}
};
const visitSymbol = (current) => {
if (visitedSymbols.has(current)) {
addIdentity(current);
charge(8);
return;
}
visitedSymbols.add(current);
if (!retainIdentity(current, () => {
if (!symbolDescriptionGetter) {
return false;
}
const description = Reflect.apply(symbolDescriptionGetter, current, []);
return charge(8 + (description?.length ?? 0) * 2);
})) {
bytes2 = remainingBytes + 1;
}
};
const visit = (current, depth, isBlobInternalHandle = false) => {
if (bytes2 > remainingBytes) {
return;
}
if (typeof current === "string") {
charge(current.length * 2);
return;
}
if (typeof current === "symbol") {
visitSymbol(current);
return;
}
if (typeof current === "function") {
bytes2 = remainingBytes + 1;
return;
}
if (current === null || typeof current !== "object") {
charge(8);
return;
}
if (nativeProxyDetector?.(current)) {
bytes2 = remainingBytes + 1;
return;
}
if (depth >= MAX_BUFFERED_EVENT_DEPTH) {
bytes2 = remainingBytes + 1;
return;
}
if (visited.has(current)) {
addIdentity(current);
charge(8);
return;
}
visited.add(current);
if (!retainIdentity(current, () => {
if (!charge(16)) {
return false;
}
const retainedStorage = estimateRetainedBufferBytes(current, visit, depth);
if (!visitRetainedEventPrototypes(current, depth, isBlobInternalHandle, visited, availableBytes, charge, visit, retainIdentity)) {
return false;
}
if (retainedStorage !== void 0 && !charge(retainedStorage.bytes)) {
return false;
}
if (!visitHiddenEventValues(current, retainedStorage?.kind, (hiddenValue, overhead) => {
if (!charge(overhead)) {
return false;
}
visit(hiddenValue, depth + 1);
return bytes2 <= remainingBytes;
})) {
return false;
}
return visitInspectableEventProperties(current, retainedStorage?.kind, depth, availableBytes, charge, visit);
})) {
bytes2 = remainingBytes + 1;
}
};
try {
visit(value2, 0);
} catch {
return void 0;
}
return bytes2 <= remainingBytes ? { scalarBytes, roots, nodes } : void 0;
}
function areBufferedRetainedEdgesEqual(first, second) {
if (first.size !== second.size) {
return false;
}
for (const identity of first) {
if (!second.has(identity)) {
return false;
}
}
return true;
}
function getBufferedLedgerNodeBytes(node, owners) {
return node.bytes + BUFFERED_LEDGER_NODE_BYTES + node.edges.size * BUFFERED_LEDGER_EDGE_BYTES + owners * BUFFERED_LEDGER_OWNER_BYTES;
}
function getBufferedLedgerEntryBytes(entry2) {
return BUFFERED_LEDGER_ENTRY_BYTES + entry2.scalarBytes + entry2.roots.size * BUFFERED_LEDGER_EDGE_BYTES;
}
function collectBufferedLedgerIdentities(roots, candidate, records, work) {
const identities = /* @__PURE__ */ new Set();
const pending = [...roots];
while (pending.length) {
work.remaining -= 1;
if (work.remaining < 0) {
return void 0;
}
const identity = pending.pop();
if (identities.has(identity)) {
continue;
}
const node = candidate.get(identity) ?? records.get(identity);
if (!node) {
return void 0;
}
identities.add(identity);
for (const edge of node.edges) {
pending.push(edge);
}
}
return identities;
}
function getBufferedLedgerChange(identity, graph, records, changes, node) {
const existing = changes.get(identity);
if (existing) {
if (node) {
existing.node = node;
}
return existing;
}
const current = node ?? graph.nodes.get(identity) ?? records.get(identity);
if (!current) {
return void 0;
}
const update = { node: current, ownerDelta: 0 };
changes.set(identity, update);
return update;
}
function findBufferedLedgerAffectedOwners(entry2, graph, records, changes, work) {
const affected = /* @__PURE__ */ new Set([entry2]);
for (const [identity, node] of graph.nodes) {
work.remaining -= 1;
if (work.remaining < 0) {
return void 0;
}
const previous = records.get(identity);
if (!previous) {
continue;
}
const changedEdges = !areBufferedRetainedEdgesEqual(previous.edges, node.edges);
if (previous.bytes !== node.bytes || changedEdges) {
getBufferedLedgerChange(identity, graph, records, changes, node);
}
if (!changedEdges) {
continue;
}
for (const owner of previous.owners) {
work.remaining -= 1;
if (work.remaining < 0) {
return void 0;
}
affected.add(owner);
}
}
return affected;
}
function updateBufferedLedgerMembershipChanges(owner, next, graph, records, changes, work) {
for (const identity of owner.identities) {
work.remaining -= 1;
if (work.remaining < 0) {
return false;
}
if (!next.has(identity)) {
const update = getBufferedLedgerChange(identity, graph, records, changes);
if (!update) {
return false;
}
update.ownerDelta -= 1;
}
}
for (const identity of next) {
work.remaining -= 1;
if (work.remaining < 0) {
return false;
}
if (!owner.identities.has(identity)) {
const update = getBufferedLedgerChange(identity, graph, records, changes);
if (!update) {
return false;
}
update.ownerDelta += 1;
}
}
return true;
}
function collectBufferedLedgerMemberships(entry2, graph, affected, records, changes, work) {
const memberships = /* @__PURE__ */ new Map();
for (const owner of affected) {
const roots = owner === entry2 ? graph.roots : owner.roots;
const next = collectBufferedLedgerIdentities(roots, graph.nodes, records, work);
if (!next || !updateBufferedLedgerMembershipChanges(owner, next, graph, records, changes, work)) {
return void 0;
}
memberships.set(owner, next);
}
return memberships;
}
function projectBufferedLedgerBytes(currentBytes, entry2, graph, isNew, changes, records) {
let projected = currentBytes - (isNew ? 0 : getBufferedLedgerEntryBytes(entry2)) + getBufferedLedgerEntryBytes(graph);
for (const [identity, update] of changes) {
const previous = records.get(identity);
const owners = (previous?.owners.size ?? 0) + update.ownerDelta;
if (owners < 0) {
return void 0;
}
if (previous) {
projected -= getBufferedLedgerNodeBytes(previous, previous.owners.size);
}
if (owners) {
projected += getBufferedLedgerNodeBytes(update.node, owners);
}
}
return Number.isSafeInteger(projected) && projected >= 0 && projected <= MAX_BUFFERED_ITERATOR_BYTES ? projected : void 0;
}
function applyBufferedLedgerChanges(records, changes, memberships) {
for (const [identity, update] of changes) {
const previous = records.get(identity);
const owners = (previous?.owners.size ?? 0) + update.ownerDelta;
if (!owners) {
continue;
}
if (previous) {
previous.bytes = update.node.bytes;
previous.edges = update.node.edges;
} else {
records.set(identity, {
bytes: update.node.bytes,
edges: update.node.edges,
owners: /* @__PURE__ */ new Set()
});
}
}
for (const [owner, next] of memberships) {
for (const identity of owner.identities) {
if (!next.has(identity)) {
records.get(identity)?.owners.delete(owner);
}
}
for (const identity of next) {
if (!owner.identities.has(identity)) {
records.get(identity).owners.add(owner);
}
}
owner.identities = next;
}
for (const identity of changes.keys()) {
if (records.get(identity)?.owners.size === 0) {
records.delete(identity);
}
}
}
function createBufferedEventLedger() {
const records = /* @__PURE__ */ new Map();
let bytes2 = 0;
const reconcile = (entry2, graph, isNew) => {
const work = { remaining: MAX_BUFFERED_LEDGER_RECONCILIATION_WORK };
const changes = /* @__PURE__ */ new Map();
const affected = findBufferedLedgerAffectedOwners(entry2, graph, records, changes, work);
if (!affected) {
return false;
}
const memberships = collectBufferedLedgerMemberships(entry2, graph, affected, records, changes, work);
if (!memberships) {
return false;
}
const projectedBytes = projectBufferedLedgerBytes(bytes2, entry2, graph, isNew, changes, records);
if (projectedBytes === void 0) {
return false;
}
applyBufferedLedgerChanges(records, changes, memberships);
entry2.scalarBytes = graph.scalarBytes;
entry2.roots = graph.roots;
bytes2 = projectedBytes;
return true;
};
const release = (entry2) => {
bytes2 -= getBufferedLedgerEntryBytes(entry2);
for (const identity of entry2.identities) {
const record = records.get(identity);
if (!record?.owners.delete(entry2)) {
continue;
}
bytes2 -= BUFFERED_LEDGER_OWNER_BYTES;
if (record.owners.size === 0) {
bytes2 -= getBufferedLedgerNodeBytes(record, 0);
records.delete(identity);
}
}
entry2.identities.clear();
};
return {
retain(graph) {
const entry2 = { scalarBytes: 0, roots: /* @__PURE__ */ new Set(), identities: /* @__PURE__ */ new Set() };
return reconcile(entry2, graph, true) ? entry2 : void 0;
},
refresh(entry2, graph) {
return reconcile(entry2, graph, false);
},
release,
clear() {
records.clear();
bytes2 = 0;
}
};
}
var _EventStream_instances, _EventStream_connectedPromise, _EventStream_resolveConnectedPromise, _EventStream_rejectConnectedPromise, _EventStream_endPromise, _EventStream_resolveEndPromise, _EventStream_rejectEndPromise, _EventStream_listeners, _EventStream_abortListeners, _EventStream_emittedListenerRegistrations, _EventStream_pendingListenerCleanup, _EventStream_pendingBufferedEventChecks, _EventStream_listenerDispatchDepth, _EventStream_ended, _EventStream_errored, _EventStream_aborted, _EventStream_catchingPromiseCreated, _EventStream_terminalFailure, _EventStream_abortFromSignal, _EventStream_removeAbortListeners, _EventStream_onceForEmitted, _EventStream_removeEmittedListener, _EventStream_cleanupEmittedListeners, _EventStream_handleError, _EventStream_settleTerminalEvent, MAX_BUFFERED_ITERATOR_EVENTS, MAX_BUFFERED_ITERATOR_BYTES, MAX_INSPECTABLE_TYPED_ARRAY_ELEMENTS, MAX_BUFFERED_EVENT_DEPTH, bufferedJSONStringify, bufferedJSONParse, sdkOwnedBufferedEventArguments, typedArrayBufferGetter, typedArrayLengthGetter, dataViewBufferGetter, symbolDescriptionGetter, dateTimestampGetter, arrayBufferByteLengthGetter2, sharedArrayBufferByteLengthGetter, errorStackDescriptor, functionToString, objectToString, errorBrandDescriptor, nativeErrorBrand, nativeErrorConstructorSource, nativeDateConstructorSource, nativeFunctionConstructorSource, trustedIntrinsicPrototypes, trustedNativeConstructorSources, canonicalIntrinsicDescriptors, foreignErrorStackDescriptors, nativeProxyDetector, typedArrayConstructorDescriptor, blobInternalHandlePrototype, mapEntries, setValues, headersEntriesDescriptor, headersEntries, retainedStorageBrands, BUFFERED_LEDGER_ENTRY_BYTES, BUFFERED_LEDGER_NODE_BYTES, BUFFERED_LEDGER_EDGE_BYTES, BUFFERED_LEDGER_OWNER_BYTES, MAX_BUFFERED_LEDGER_RECONCILIATION_WORK, EventStream2;
var init_EventStream = __esm({
"node_modules/openai/lib/EventStream.mjs"() {
init_tslib();
init_error2();
MAX_BUFFERED_ITERATOR_EVENTS = 4096;
MAX_BUFFERED_ITERATOR_BYTES = 8 * 1024 * 1024;
MAX_INSPECTABLE_TYPED_ARRAY_ELEMENTS = 4096;
MAX_BUFFERED_EVENT_DEPTH = 256;
bufferedJSONStringify = JSON.stringify;
bufferedJSONParse = JSON.parse;
sdkOwnedBufferedEventArguments = /* @__PURE__ */ new WeakSet();
typedArrayBufferGetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), "buffer")?.get;
typedArrayLengthGetter = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), "length")?.get;
dataViewBufferGetter = Object.getOwnPropertyDescriptor(DataView.prototype, "buffer")?.get;
symbolDescriptionGetter = Object.getOwnPropertyDescriptor(Symbol.prototype, "description")?.get;
dateTimestampGetter = Date.prototype.getTime;
arrayBufferByteLengthGetter2 = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength")?.get;
sharedArrayBufferByteLengthGetter = typeof SharedArrayBuffer === "function" ? Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype, "byteLength")?.get : void 0;
errorStackDescriptor = Object.getOwnPropertyDescriptor(new Error("native stack descriptor"), "stack");
functionToString = Function.prototype.toString;
objectToString = Object.prototype.toString;
errorBrandDescriptor = Object.getOwnPropertyDescriptor(Error, "isError");
nativeErrorBrand = errorBrandDescriptor && "value" in errorBrandDescriptor && typeof errorBrandDescriptor.value === "function" ? errorBrandDescriptor.value : void 0;
nativeErrorConstructorSource = functionToString.call(Error);
nativeDateConstructorSource = functionToString.call(Date);
nativeFunctionConstructorSource = functionToString.call(Function);
trustedIntrinsicPrototypes = /* @__PURE__ */ new Set([
APIConnectionError.prototype,
APIConnectionTimeoutError.prototype,
APIError.prototype,
OpenAIError.prototype,
APIUserAbortError.prototype,
AuthenticationError.prototype,
BadRequestError.prototype,
ConflictError.prototype,
ContentFilterFinishReasonError.prototype,
InternalServerError.prototype,
InvalidWebhookSignatureError.prototype,
LengthFinishReasonError.prototype,
NotFoundError.prototype,
OAuthError.prototype,
PermissionDeniedError.prototype,
RateLimitError.prototype,
SubjectTokenProviderError.prototype,
UnprocessableEntityError.prototype
]);
trustedNativeConstructorSources = /* @__PURE__ */ new Set();
canonicalIntrinsicDescriptors = /* @__PURE__ */ new Map();
foreignErrorStackDescriptors = /* @__PURE__ */ new WeakMap();
nativeProxyDetector = captureNativeProxyDetector();
for (const constructor of [
Object,
Function,
Array,
Date,
Map,
Set,
ArrayBuffer,
DataView,
Error,
EvalError,
RangeError,
ReferenceError,
SyntaxError,
TypeError,
URIError,
Uint8Array,
Uint8ClampedArray,
Uint16Array,
Uint32Array,
Int8Array,
Int16Array,
Int32Array,
Float32Array,
Float64Array
]) {
rememberTrustedIntrinsic(constructor);
}
for (const name of [
"SharedArrayBuffer",
"AggregateError",
"Float16Array",
"BigInt64Array",
"BigUint64Array",
"Blob",
"File",
"Headers"
]) {
const descriptor = Object.getOwnPropertyDescriptor(globalThis, name);
if (descriptor && "value" in descriptor) {
rememberTrustedIntrinsic(descriptor.value);
}
}
typedArrayConstructorDescriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Uint8Array.prototype), "constructor");
if (typedArrayConstructorDescriptor && "value" in typedArrayConstructorDescriptor) {
rememberTrustedIntrinsic(typedArrayConstructorDescriptor.value);
}
if (typeof Buffer === "function") {
rememberTrustedIntrinsic(Buffer);
}
blobInternalHandlePrototype = (() => {
if (typeof Blob !== "function") {
return void 0;
}
try {
const blob = new Blob([]);
for (const key of Object.getOwnPropertySymbols(blob)) {
const descriptor = Object.getOwnPropertyDescriptor(blob, key);
if (descriptor && "value" in descriptor && typeof descriptor.value === "object" && descriptor.value) {
return Object.getPrototypeOf(descriptor.value);
}
}
} catch {
return void 0;
}
return void 0;
})();
mapEntries = Map.prototype.entries;
setValues = Set.prototype.values;
headersEntriesDescriptor = typeof Headers === "function" ? Object.getOwnPropertyDescriptor(Headers.prototype, "entries") : void 0;
headersEntries = headersEntriesDescriptor && "value" in headersEntriesDescriptor && typeof headersEntriesDescriptor.value === "function" ? headersEntriesDescriptor.value : void 0;
retainedStorageBrands = /* @__PURE__ */ new Set([
"ArrayBuffer",
"SharedArrayBuffer",
"Blob",
"File",
"Map",
"Date",
"Set",
"Headers"
]);
BUFFERED_LEDGER_ENTRY_BYTES = 32;
BUFFERED_LEDGER_NODE_BYTES = 32;
BUFFERED_LEDGER_EDGE_BYTES = 8;
BUFFERED_LEDGER_OWNER_BYTES = 16;
MAX_BUFFERED_LEDGER_RECONCILIATION_WORK = 128 * 1024;
EventStream2 = class {
/** Creates an unstarted stream with independent connection and completion lifecycle promises. */
constructor() {
_EventStream_instances.add(this);
this.controller = new AbortController();
_EventStream_connectedPromise.set(this, void 0);
_EventStream_resolveConnectedPromise.set(this, () => void 0);
_EventStream_rejectConnectedPromise.set(this, () => void 0);
_EventStream_endPromise.set(this, void 0);
_EventStream_resolveEndPromise.set(this, () => void 0);
_EventStream_rejectEndPromise.set(this, () => void 0);
_EventStream_listeners.set(this, /* @__PURE__ */ Object.create(null));
_EventStream_abortListeners.set(this, []);
_EventStream_emittedListenerRegistrations.set(this, /* @__PURE__ */ new WeakMap());
_EventStream_pendingListenerCleanup.set(this, /* @__PURE__ */ new Set());
_EventStream_pendingBufferedEventChecks.set(this, /* @__PURE__ */ new Set());
_EventStream_listenerDispatchDepth.set(this, 0);
_EventStream_ended.set(this, false);
_EventStream_errored.set(this, false);
_EventStream_aborted.set(this, false);
_EventStream_catchingPromiseCreated.set(this, false);
_EventStream_terminalFailure.set(this, void 0);
__classPrivateFieldSet(this, _EventStream_connectedPromise, new Promise((resolve2, reject2) => {
__classPrivateFieldSet(this, _EventStream_resolveConnectedPromise, resolve2, "f");
__classPrivateFieldSet(this, _EventStream_rejectConnectedPromise, reject2, "f");
}), "f");
__classPrivateFieldSet(this, _EventStream_endPromise, new Promise((resolve2, reject2) => {
__classPrivateFieldSet(this, _EventStream_resolveEndPromise, resolve2, "f");
__classPrivateFieldSet(this, _EventStream_rejectEndPromise, reject2, "f");
}), "f");
__classPrivateFieldGet(this, _EventStream_connectedPromise, "f").catch(() => void 0);
__classPrivateFieldGet(this, _EventStream_endPromise, "f").catch(() => void 0);
}
_run(executor) {
setTimeout(() => {
let failed = false;
Promise.resolve().then(executor).catch((error) => {
failed = true;
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_handleError).call(this, error);
}).then(() => {
if (failed) {
return;
}
try {
this._emitFinal();
} catch (error) {
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_handleError).call(this, error);
return;
}
this._emit("end");
});
}, 0);
}
_connected() {
if (this.ended) {
return;
}
__classPrivateFieldGet(this, _EventStream_resolveConnectedPromise, "f").call(this);
this._emit("connect");
}
/** Whether the stream has finished successfully, failed, or been aborted. */
get ended() {
return __classPrivateFieldGet(this, _EventStream_ended, "f");
}
/** Whether an error or user cancellation has been observed. */
get errored() {
return __classPrivateFieldGet(this, _EventStream_errored, "f");
}
/** Whether the stream ended because its request was cancelled. */
get aborted() {
return __classPrivateFieldGet(this, _EventStream_aborted, "f");
}
/**
* Cancels the underlying request; {@link done} and {@link events} observe cancellation.
* Promises returned by {@link emitted} for other events may remain pending.
*/
abort() {
this.controller.abort();
}
/** Creates a user-abort error retaining this runner's cancellation reason. */
_userAbortError() {
const error = new APIUserAbortError();
Object.defineProperty(error, "cause", {
value: this.controller.signal.reason,
writable: true,
configurable: true
});
return error;
}
_listenForAbort(signal) {
if (!signal || this.ended) {
return;
}
if (signal.aborted) {
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_abortFromSignal).call(this, signal);
return;
}
if (__classPrivateFieldGet(this, _EventStream_abortListeners, "f").some((registration) => registration.signal === signal)) {
return;
}
const listener = () => __classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_abortFromSignal).call(this, signal);
signal.addEventListener("abort", listener, { once: true });
__classPrivateFieldGet(this, _EventStream_abortListeners, "f").push({ signal, listener });
}
/**
* Adds the listener function to the end of the listeners array for the event.
* No checks are made to see if the listener has already been added. Multiple calls passing
* the same combination of event and listener will result in the listener being added, and
* called, multiple times.
* @returns This stream, so that listener registration calls can be chained.
*/
on(event, listener) {
var _a5;
const listeners = (_a5 = __classPrivateFieldGet(this, _EventStream_listeners, "f"))[event] || (_a5[event] = []);
listeners.push({ listener });
return this;
}
/**
* Removes the specified listener from the listener array for the event.
* off() will remove, at most, one instance of a listener from the listener array. If any single
* listener has been added multiple times to the listener array for the specified event, then
* off() must be called multiple times to remove each instance.
* @returns This stream, so that listener registration calls can be chained.
*/
off(event, listener) {
const listeners = __classPrivateFieldGet(this, _EventStream_listeners, "f")[event];
if (!listeners) {
return this;
}
const emittedRegistration = __classPrivateFieldGet(this, _EventStream_emittedListenerRegistrations, "f").get(listener);
if (emittedRegistration?.event === event && !emittedRegistration.registration.removed && !emittedRegistration.registration.detached) {
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_removeEmittedListener).call(this, event, emittedRegistration.registration);
return this;
}
const index = listeners.findIndex((l) => !l.removed && l.listener === listener);
if (index !== -1) {
listeners.splice(index, 1);
}
return this;
}
/**
* Adds a one-time listener function for the event. The next time the event is triggered,
* this listener is removed and then invoked.
* @returns This stream, so that listener registration calls can be chained.
*/
once(event, listener) {
var _a5;
const listeners = (_a5 = __classPrivateFieldGet(this, _EventStream_listeners, "f"))[event] || (_a5[event] = []);
listeners.push({ listener, once: true });
return this;
}
/**
* This is similar to `.once()`, but returns a Promise that resolves the next time
* the event is triggered, instead of calling a listener callback.
* Events without arguments resolve to `undefined`, single-argument events resolve
* to that argument, and events with multiple arguments resolve to an argument tuple.
*
* @returns A promise for the next event, or a rejection if an error occurs first.
* Requesting the `error` event resolves with the emitted error instead.
*
* Example:
*
* const message = await stream.emitted('message') // rejects if the stream errors
*/
emitted(event) {
return new Promise((resolve2, reject2) => {
__classPrivateFieldSet(this, _EventStream_catchingPromiseCreated, true, "f");
const onError = (error) => {
this.off(event, onEvent);
reject2(error);
};
const onEvent = (...values) => {
if (event !== "error") {
this.off("error", onError);
}
resolve2(values.length > 1 ? values : values[0]);
};
if (event !== "error") {
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_onceForEmitted).call(this, "error", onError);
}
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_onceForEmitted).call(this, event, onEvent);
});
}
/**
* Returns an async iterator that yields every time the event is triggered.
* The iterator ends when the stream ends and rejects if the stream errors
* or is aborted. If you request the 'error' or 'abort' event, the iterator
* yields that event instead of rejecting.
*
* Example:
*
* for await (const [message] of stream.events('message')) {
* await processMessage(message);
* }
*/
events(event) {
return this._createIterator((push) => {
const onEvent = (...args) => {
sdkOwnedBufferedEventArguments.add(args);
try {
push(args);
} finally {
sdkOwnedBufferedEventArguments.delete(args);
}
};
this.on(event, onEvent);
return () => this.off(event, onEvent);
}, {
// When iterating the 'error' or 'abort' event itself, yield it as a
// value instead of rejecting the iterator.
rejectOnError: event !== "error",
rejectOnAbort: event !== "abort"
});
}
/**
* Shared buffered async-iterator adapter over this stream's events.
*
* `attach` registers the producer listener(s) with the given `push` and
* returns a cleanup function that removes them. Termination is handled
* here: the iterator ends when the stream ends, listeners are removed on
* end/return, and a terminal error is retained until buffered values have
* drained so it is surfaced even when no reader was waiting when it fired.
* Detached consumers have bounded event and byte queues; exceeding either
* limit fails the stream and aborts its underlying request. Detached queues
* also reject accessor-backed payloads because getter closures cannot be
* safely sized without executing untrusted code.
*/
_createIterator(attach, { rejectOnError = true, rejectOnAbort = true, onReturn } = {}) {
const pushQueue = createEventQueue();
const bufferedEventSizes = createEventQueue();
const readQueue = createEventQueue();
const bufferedLedger = createBufferedEventLedger();
let ended = this.ended;
let failure;
let failureDelivered = false;
let detach = () => void 0;
const doneResult = () => ({ value: void 0, done: true });
const finishReaders = () => {
while (readQueue.length) {
readQueue.dequeue().resolve(doneResult());
}
};
const rejectReader = () => {
if (!failure || failureDelivered || !readQueue.length) {
return;
}
failureDelivered = true;
readQueue.dequeue().reject(failure);
};
const cleanup = () => {
detach();
this.off("end", onEnd);
if (rejectOnError) {
this.off("error", onFailure);
}
if (rejectOnAbort) {
this.off("abort", onFailure);
}
};
const deactivateBufferedEvent = (entry2) => {
entry2.active = false;
if (entry2.check) {
__classPrivateFieldGet(this, _EventStream_pendingBufferedEventChecks, "f").delete(entry2.check);
entry2.check = void 0;
}
};
const failBufferedEvents = (discardRetained = false) => {
if (discardRetained) {
while (bufferedEventSizes.length) {
deactivateBufferedEvent(bufferedEventSizes.dequeue());
}
pushQueue.clear();
bufferedLedger.clear();
}
const error = new OpenAIError(`Event stream iterator buffer limit exceeded (${MAX_BUFFERED_ITERATOR_EVENTS} events or ${MAX_BUFFERED_ITERATOR_BYTES} bytes); consume events as they arrive.`);
try {
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_handleError).call(this, error);
} finally {
this.controller.abort();
}
return error;
};
const revalidateBufferedEvent = (value2, entry2) => {
if (!entry2.active || __classPrivateFieldGet(this, _EventStream_ended, "f")) {
return;
}
const graph = inspectBufferedEventGraph(value2, MAX_BUFFERED_ITERATOR_BYTES);
if (!graph || !bufferedLedger.refresh(entry2.retention, graph)) {
failBufferedEvents(true);
}
};
const push = (value2) => {
if (ended) {
return;
}
const reader = readQueue.dequeue();
if (reader) {
reader.resolve({ value: value2, done: false });
} else {
if (pushQueue.length >= MAX_BUFFERED_ITERATOR_EVENTS) {
failBufferedEvents();
return;
}
const graph = inspectBufferedEventGraph(value2, MAX_BUFFERED_ITERATOR_BYTES);
const retention = graph && bufferedLedger.retain(graph);
if (!retention) {
failBufferedEvents();
return;
}
if (typeof value2 === "object" && value2 !== null && sdkOwnedBufferedEventArguments.has(value2)) {
const argumentsTuple = value2;
for (let index = 0; index < argumentsTuple.length; index += 1) {
const argument = argumentsTuple[index];
if (typeof argument === "string") {
argumentsTuple[index] = bufferedJSONParse(bufferedJSONStringify(argument));
}
}
}
const entry2 = { retention, active: true, check: void 0 };
pushQueue.enqueue(value2);
bufferedEventSizes.enqueue(entry2);
const check = () => {
entry2.check = void 0;
revalidateBufferedEvent(value2, entry2);
};
entry2.check = check;
__classPrivateFieldGet(this, _EventStream_pendingBufferedEventChecks, "f").add(check);
}
};
const onFailure = (error) => {
failure = error;
if (!pushQueue.length) {
rejectReader();
}
};
const adoptTerminalFailure = () => {
if (failure) {
return;
}
const terminal = __classPrivateFieldGet(this, _EventStream_terminalFailure, "f");
if (!terminal) {
return;
}
if (terminal.kind === "error" ? rejectOnError : rejectOnAbort) {
failure = terminal.error;
}
};
const onEnd = () => {
ended = true;
adoptTerminalFailure();
cleanup();
if (!pushQueue.length) {
rejectReader();
finishReaders();
}
};
if (!ended) {
detach = attach(push);
this.on("end", onEnd);
if (rejectOnError) {
this.on("error", onFailure);
}
if (rejectOnAbort) {
this.on("abort", onFailure);
}
}
return {
next: () => {
if (pushQueue.length) {
const value2 = pushQueue.dequeue();
const entry2 = bufferedEventSizes.dequeue();
deactivateBufferedEvent(entry2);
const graph = inspectBufferedEventGraph(value2, MAX_BUFFERED_ITERATOR_BYTES);
if (!graph || !bufferedLedger.refresh(entry2.retention, graph)) {
const error = failBufferedEvents(true);
failureDelivered = true;
return Promise.reject(error);
}
bufferedLedger.release(entry2.retention);
return Promise.resolve({ value: value2, done: false });
}
if (ended || this.ended) {
adoptTerminalFailure();
}
if (failure && !failureDelivered) {
failureDelivered = true;
return Promise.reject(failure);
}
if (ended) {
return Promise.resolve(doneResult());
}
return new Promise((resolve2, reject2) => {
readQueue.enqueue({ resolve: resolve2, reject: reject2 });
});
},
return: () => {
ended = true;
failureDelivered = true;
while (bufferedEventSizes.length) {
deactivateBufferedEvent(bufferedEventSizes.dequeue());
}
pushQueue.clear();
bufferedLedger.clear();
cleanup();
finishReaders();
if (onReturn) {
void this.done().catch(() => void 0);
onReturn();
}
return Promise.resolve(doneResult());
},
[Symbol.asyncIterator]() {
return this;
}
};
}
/** Resolves when the stream ends successfully or rejects when it fails or is aborted. */
async done() {
__classPrivateFieldSet(this, _EventStream_catchingPromiseCreated, true, "f");
await __classPrivateFieldGet(this, _EventStream_endPromise, "f");
}
/** Returns whether an event currently has one or more registered listeners. */
_hasListeners(event) {
return Boolean(__classPrivateFieldGet(this, _EventStream_listeners, "f")[event]?.some((listener) => !listener.removed));
}
/** Dispatches a stream event and performs the associated lifecycle transitions. */
_emit(event, ...args) {
if (__classPrivateFieldGet(this, _EventStream_ended, "f")) {
return;
}
if (event === "end") {
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_removeAbortListeners).call(this);
__classPrivateFieldSet(this, _EventStream_ended, true, "f");
__classPrivateFieldGet(this, _EventStream_resolveEndPromise, "f").call(this);
}
const listeners = __classPrivateFieldGet(this, _EventStream_listeners, "f")[event];
let dispatchError;
let dispatchThrew = false;
try {
if (listeners) {
__classPrivateFieldGet(this, _EventStream_listeners, "f")[event] = listeners.filter((listener) => {
if (listener.once) {
listener.detached = true;
}
return !listener.once && !listener.removed;
});
__classPrivateFieldSet(this, _EventStream_listenerDispatchDepth, __classPrivateFieldGet(this, _EventStream_listenerDispatchDepth, "f") + 1, "f");
try {
for (const registration of listeners) {
if (!registration.removed) {
const { listener } = registration;
listener(...args);
}
}
} finally {
__classPrivateFieldSet(this, _EventStream_listenerDispatchDepth, __classPrivateFieldGet(this, _EventStream_listenerDispatchDepth, "f") - 1, "f");
if (__classPrivateFieldGet(this, _EventStream_listenerDispatchDepth, "f") === 0) {
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_cleanupEmittedListeners).call(this);
for (const check of __classPrivateFieldGet(this, _EventStream_pendingBufferedEventChecks, "f")) {
__classPrivateFieldGet(this, _EventStream_pendingBufferedEventChecks, "f").delete(check);
if (!__classPrivateFieldGet(this, _EventStream_ended, "f")) {
check();
}
}
}
}
}
} catch (error) {
dispatchError = error;
dispatchThrew = true;
}
try {
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_settleTerminalEvent).call(this, event, args, Boolean(listeners?.length));
} catch (error) {
if (!dispatchThrew) {
dispatchError = error;
dispatchThrew = true;
}
}
if (dispatchThrew) {
throw dispatchError;
}
}
// oxlint-disable-next-line class-methods-use-this -- Subclasses override this instance hook.
_emitFinal() {
}
};
_EventStream_connectedPromise = /* @__PURE__ */ new WeakMap(), _EventStream_resolveConnectedPromise = /* @__PURE__ */ new WeakMap(), _EventStream_rejectConnectedPromise = /* @__PURE__ */ new WeakMap(), _EventStream_endPromise = /* @__PURE__ */ new WeakMap(), _EventStream_resolveEndPromise = /* @__PURE__ */ new WeakMap(), _EventStream_rejectEndPromise = /* @__PURE__ */ new WeakMap(), _EventStream_listeners = /* @__PURE__ */ new WeakMap(), _EventStream_abortListeners = /* @__PURE__ */ new WeakMap(), _EventStream_emittedListenerRegistrations = /* @__PURE__ */ new WeakMap(), _EventStream_pendingListenerCleanup = /* @__PURE__ */ new WeakMap(), _EventStream_pendingBufferedEventChecks = /* @__PURE__ */ new WeakMap(), _EventStream_listenerDispatchDepth = /* @__PURE__ */ new WeakMap(), _EventStream_ended = /* @__PURE__ */ new WeakMap(), _EventStream_errored = /* @__PURE__ */ new WeakMap(), _EventStream_aborted = /* @__PURE__ */ new WeakMap(), _EventStream_catchingPromiseCreated = /* @__PURE__ */ new WeakMap(), _EventStream_terminalFailure = /* @__PURE__ */ new WeakMap(), _EventStream_instances = /* @__PURE__ */ new WeakSet(), _EventStream_abortFromSignal = function _EventStream_abortFromSignal2(signal) {
try {
this.controller.abort(signal.reason);
} catch {
this.controller.abort();
}
}, _EventStream_removeAbortListeners = function _EventStream_removeAbortListeners2() {
for (const { signal, listener } of __classPrivateFieldGet(this, _EventStream_abortListeners, "f").splice(0)) {
signal.removeEventListener("abort", listener);
}
}, _EventStream_onceForEmitted = function _EventStream_onceForEmitted2(event, listener) {
const previousListeners = __classPrivateFieldGet(this, _EventStream_listeners, "f")[event];
const previousLength = previousListeners?.length ?? 0;
this.once(event, listener);
const listeners = __classPrivateFieldGet(this, _EventStream_listeners, "f")[event];
const [registration] = listeners?.slice(-1) ?? [];
if ((previousListeners === void 0 || listeners === previousListeners) && listeners?.length === previousLength + 1 && registration?.listener === listener && registration.once) {
__classPrivateFieldGet(this, _EventStream_emittedListenerRegistrations, "f").set(listener, { event, registration });
}
}, _EventStream_removeEmittedListener = function _EventStream_removeEmittedListener2(event, registration) {
if (registration.removed) {
return;
}
registration.removed = true;
__classPrivateFieldGet(this, _EventStream_emittedListenerRegistrations, "f").delete(registration.listener);
__classPrivateFieldGet(this, _EventStream_pendingListenerCleanup, "f").add(event);
if (__classPrivateFieldGet(this, _EventStream_listenerDispatchDepth, "f") === 0) {
__classPrivateFieldGet(this, _EventStream_instances, "m", _EventStream_cleanupEmittedListeners).call(this);
}
}, _EventStream_cleanupEmittedListeners = function _EventStream_cleanupEmittedListeners2() {
for (const event of __classPrivateFieldGet(this, _EventStream_pendingListenerCleanup, "f")) {
const eventType = event;
const listeners = __classPrivateFieldGet(this, _EventStream_listeners, "f")[eventType];
if (listeners) {
__classPrivateFieldGet(this, _EventStream_listeners, "f")[eventType] = listeners.filter((listener) => !listener.removed);
}
}
__classPrivateFieldGet(this, _EventStream_pendingListenerCleanup, "f").clear();
}, _EventStream_handleError = function _EventStream_handleError2(error) {
__classPrivateFieldSet(this, _EventStream_errored, true, "f");
if (error instanceof Error && error.name === "AbortError") {
error = this._userAbortError();
}
if (error instanceof APIUserAbortError) {
__classPrivateFieldSet(this, _EventStream_aborted, true, "f");
return this._emit("abort", error);
}
if (error instanceof OpenAIError) {
return this._emit("error", error);
}
if (error instanceof Error) {
const openAIError = new OpenAIError(error.message);
openAIError.cause = error;
return this._emit("error", openAIError);
}
return this._emit("error", new OpenAIError(String(error)));
}, _EventStream_settleTerminalEvent = function _EventStream_settleTerminalEvent2(event, args, hasListeners) {
if (event === "abort") {
const error = args[0];
__classPrivateFieldSet(this, _EventStream_terminalFailure, __classPrivateFieldGet(this, _EventStream_terminalFailure, "f") ?? { kind: "abort", error }, "f");
if (!__classPrivateFieldGet(this, _EventStream_catchingPromiseCreated, "f") && !hasListeners) {
Promise.reject(error);
}
__classPrivateFieldGet(this, _EventStream_rejectConnectedPromise, "f").call(this, error);
__classPrivateFieldGet(this, _EventStream_rejectEndPromise, "f").call(this, error);
this._emit("end");
return;
}
if (event === "error") {
const error = args[0];
__classPrivateFieldSet(this, _EventStream_terminalFailure, __classPrivateFieldGet(this, _EventStream_terminalFailure, "f") ?? { kind: "error", error }, "f");
if (!__classPrivateFieldGet(this, _EventStream_catchingPromiseCreated, "f") && !hasListeners) {
Promise.reject(error);
}
__classPrivateFieldGet(this, _EventStream_rejectConnectedPromise, "f").call(this, error);
__classPrivateFieldGet(this, _EventStream_rejectEndPromise, "f").call(this, error);
this._emit("end");
}
};
}
});
// node_modules/openai/lib/RunnableFunction.mjs
function isRunnableFunctionWithParse(fn) {
return typeof fn.parse === "function";
}
var init_RunnableFunction = __esm({
"node_modules/openai/lib/RunnableFunction.mjs"() {
}
});
// node_modules/openai/lib/AbstractChatCompletionRunner.mjs
function normalizeToolCallIds(chatCompletion) {
for (const choice of chatCompletion.choices) {
for (const toolCall of choice.message.tool_calls ?? []) {
if (!toolCall.id) {
toolCall.id = `call_${uuid4()}`;
}
}
}
}
function toRequestMessage(message) {
if (!isAssistantMessage(message)) {
return message;
}
const requestMessage = { role: "assistant" };
if (message.audio != null) {
requestMessage.audio = { id: message.audio.id };
}
if (message.content !== void 0) {
requestMessage.content = message.content;
}
if (message.function_call != null) {
requestMessage.function_call = message.function_call;
}
if (message.name !== void 0) {
requestMessage.name = message.name;
}
if (message.refusal != null) {
requestMessage.refusal = message.refusal;
}
if (message.tool_calls !== void 0) {
requestMessage.tool_calls = message.tool_calls.map((toolCall) => {
if (toolCall.type === "custom") {
return {
id: toolCall.id,
type: toolCall.type,
custom: {
input: toolCall.custom.input,
name: toolCall.custom.name
}
};
}
return {
id: toolCall.id,
type: toolCall.type,
function: {
arguments: toolCall.function.arguments,
name: toolCall.function.name
}
};
});
}
return requestMessage;
}
var _AbstractChatCompletionRunner_instances, _a2, _AbstractChatCompletionRunner_completionArrivedBeforeAbort, _AbstractChatCompletionRunner_afterCompletionInvoked, _AbstractChatCompletionRunner_getFinalContent, _AbstractChatCompletionRunner_getFinalMessage, _AbstractChatCompletionRunner_getFinalFunctionToolCall, _AbstractChatCompletionRunner_getFinalFunctionToolCallResult, _AbstractChatCompletionRunner_calculateTotalUsage, _AbstractChatCompletionRunner_throwIfAborted, _AbstractChatCompletionRunner_validateParams, _AbstractChatCompletionRunner_stringifyFunctionCallResult, DEFAULT_MAX_CHAT_COMPLETIONS, AbstractChatCompletionRunner;
var init_AbstractChatCompletionRunner = __esm({
"node_modules/openai/lib/AbstractChatCompletionRunner.mjs"() {
init_tslib();
init_error2();
init_uuid();
init_parser();
init_chatCompletionUtils();
init_EventStream();
init_RunnableFunction();
DEFAULT_MAX_CHAT_COMPLETIONS = 10;
AbstractChatCompletionRunner = class extends EventStream2 {
constructor() {
super(...arguments);
_AbstractChatCompletionRunner_instances.add(this);
this._chatCompletions = [];
_AbstractChatCompletionRunner_completionArrivedBeforeAbort.set(this, false);
_AbstractChatCompletionRunner_afterCompletionInvoked.set(this, false);
this.messages = [];
}
_addChatCompletion(chatCompletion) {
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_completionArrivedBeforeAbort, !this.controller.signal.aborted, "f");
normalizeToolCallIds(chatCompletion);
this._chatCompletions.push(chatCompletion);
this._emit("chatCompletion", chatCompletion);
const message = chatCompletion.choices[0]?.message;
if (message) {
this._addMessage(message);
}
return chatCompletion;
}
_addMessage(message, emit = true, normalizeContent = true) {
if (normalizeContent && !("content" in message)) {
message.content = null;
}
this.messages.push(message);
if (emit) {
this._emit("message", message);
if (isToolMessage(message) && message.content) {
this._emit("functionToolCallResult", message.content);
} else if (isAssistantMessage(message) && message.tool_calls) {
for (const tool_call of message.tool_calls) {
if (tool_call.type === "function") {
this._emit("functionToolCall", tool_call.function);
}
}
}
}
}
/**
* @returns a promise that resolves with the final ChatCompletion, or rejects
* if an error occurred or the stream ended prematurely without producing a ChatCompletion.
*/
async finalChatCompletion() {
await this.done();
const completion = this._chatCompletions[this._chatCompletions.length - 1];
if (!completion) {
throw new OpenAIError("stream ended without producing a ChatCompletion");
}
return completion;
}
/**
* @returns a promise that resolves with the content of the final ChatCompletionMessage, or rejects
* if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage.
*/
async finalContent() {
await this.done();
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalContent).call(this);
}
/**
* @returns a promise that resolves with the final assistant ChatCompletionMessage response,
* or rejects if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage.
*/
async finalMessage() {
await this.done();
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this);
}
/**
* Waits for completion and returns the last function-tool call, or `undefined`
* when no assistant message contains a function-tool call.
*/
async finalFunctionToolCall() {
await this.done();
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionToolCall).call(this);
}
/** Waits for completion and returns the last matching function-tool result, if any. */
async finalFunctionToolCallResult() {
await this.done();
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionToolCallResult).call(this);
}
/** Waits for completion and sums token usage across every chat completion in the run. */
async totalUsage() {
await this.done();
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_calculateTotalUsage).call(this);
}
/** Returns a copy of the chat completions received so far, in request order. */
allChatCompletions() {
return [...this._chatCompletions];
}
_emitFinal() {
if (__classPrivateFieldGet(this, _AbstractChatCompletionRunner_afterCompletionInvoked, "f")) {
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_throwIfAborted).call(this);
}
const completion = this._chatCompletions[this._chatCompletions.length - 1];
if (completion) {
this._emit("finalChatCompletion", completion);
}
const finalMessage = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this);
if (finalMessage) {
this._emit("finalMessage", finalMessage);
}
const finalContent = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalContent).call(this);
if (finalContent) {
this._emit("finalContent", finalContent);
}
const finalFunctionCall = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionToolCall).call(this);
if (finalFunctionCall) {
this._emit("finalFunctionToolCall", finalFunctionCall);
}
const finalFunctionCallResult = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionToolCallResult).call(this);
if (finalFunctionCallResult != null) {
this._emit("finalFunctionToolCallResult", finalFunctionCallResult);
}
if (this._chatCompletions.some((c) => c.usage)) {
this._emit("totalUsage", __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_calculateTotalUsage).call(this));
}
}
async _createChatCompletion(client, params, options) {
this._listenForAbort(options?.signal);
__classPrivateFieldGet(_a2, _a2, "m", _AbstractChatCompletionRunner_validateParams).call(_a2, params);
const chatCompletion = await client.chat.completions.create({ ...params, stream: false }, { ...options, signal: this.controller.signal });
this._connected();
return this._addChatCompletion(parseChatCompletion(chatCompletion, params));
}
async _runChatCompletion(client, params, options) {
for (const message of params.messages) {
this._addMessage(message, false, false);
}
return await this._createChatCompletion(client, params, options);
}
async _runTools(client, params, runner, options) {
const role = "tool";
const { tool_choice = "auto", stream: stream2, toolContext: inputToolContext, ...restParams } = params;
const toolContext = inputToolContext;
const singleFunctionToCall = (
// oxlint-disable-next-line anti-slop/no-runtime-typeof -- Chat history and tool-choice inputs can contain runtime variants that select different runner behavior.
typeof tool_choice !== "string" && tool_choice.type === "function" && tool_choice?.function?.name
);
const { maxChatCompletions = DEFAULT_MAX_CHAT_COMPLETIONS, afterCompletion } = options || {};
const runAfterCompletion = async (completion) => {
if (afterCompletion == null) {
return;
}
__classPrivateFieldSet(this, _AbstractChatCompletionRunner_afterCompletionInvoked, true, "f");
await afterCompletion(completion, runner);
__classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_throwIfAborted).call(this);
};
const inputTools = params.tools.map((tool) => {
if (isAutoParsableTool(tool)) {
if (!tool.$callback) {
throw new OpenAIError("Tool given to `.runTools()` that does not have an associated function");
}
return {
type: "function",
function: {
function: tool.$callback,
name: tool.function.name,
description: tool.function.description || "",
parameters: tool.function.parameters,
parse: tool.$parseRaw,
strict: true
}
};
}
return tool;
});
const functionsByName = /* @__PURE__ */ Object.create(null);
for (const f of inputTools) {
if (f.type === "function") {
functionsByName[f.function.name || f.function.function.name] = f.function;
}
}
const tools = "tools" in params ? inputTools.map((t) => t.type === "function" ? {
type: "function",
function: {
name: t.function.name || t.function.function.name,
// oxlint-disable-next-line anti-slop/no-unsafe-dictionary-type -- Tool parameter schemas use the published open JSON Schema dictionary contract, including arbitrary extensions.
parameters: t.function.parameters,
description: t.function.description,
strict: t.function.strict
}
} : (
// oxlint-disable-next-line anti-slop/no-chained-type-assertions -- Preserve the existing non-function tool pass-through; runnable and wire schema interfaces have incompatible index signatures.
t
)) : void 0;
for (const message of params.messages) {
this._addMessage(message, false, false);
}
let allowBufferedToolCall = false;
const runToolCall = async (toolCall) => {
const bufferedToolCall = allowBufferedToolCall;
allowBufferedToolCall = false;
if (toolCall.type !== "function") {
return { message: void 0, functionCalled: false };
}
const tool_call_id = toolCall.id;
const { name, arguments: args } = toolCall.function;
const fn = functionsByName[name];
if (!fn) {
const content2 = `Invalid tool_call: ${JSON.stringify(name)}. Available options are: ${Object.keys(functionsByName).map((name2) => JSON.stringify(name2)).join(", ")}. Please try again`;
return { message: { role, tool_call_id, content: content2 }, functionCalled: false };
}
if (singleFunctionToCall && singleFunctionToCall !== name) {
const content2 = `Invalid tool_call: ${JSON.stringify(name)}. ${JSON.stringify(singleFunctionToCall)} requested. Please try again`;
return { message: { role, tool_call_id, content: content2 }, functionCalled: false };
}
let rawContent;
if (isRunnableFunctionWithParse(fn)) {
let parsed;
try {
parsed = await fn.parse(args);
} catch (error) {
if (this.controller.signal.aborted) {
throw this._userAbortError();
}
const content2 = error instanceof Error ? error.message : String(error);
return { message: { role, tool_call_id, content: content2 }, functionCalled: false };
}
if (this.controller.signal.aborted) {
throw this._userAbortError();
}
try {
rawContent = await fn.function(parsed, runner, toolContext);
} catch (error) {
if (this.controller.signal.aborted && Object.is(error, this.controller.signal.reason)) {
throw this._userAbortError();
}
throw error;
}
} else {
if (this.controller.signal.aborted && !bufferedToolCall) {
throw this._userAbortError();
}
try {
rawContent = await fn.function(args, runner, toolContext);
} catch (error) {
if (this.controller.signal.aborted && Object.is(error, this.controller.signal.reason)) {
throw this._userAbortError();
}
throw error;
}
}
const content = __classPrivateFieldGet(_a2, _a2, "m", _AbstractChatCompletionRunner_stringifyFunctionCallResult).call(_a2, rawContent);
return { message: { role, tool_call_id, content }, functionCalled: true };
};
for (let i = 0; i < maxChatCompletions; ++i) {
const chatCompletion = await this._createChatCompletion(client, {
...restParams,
tool_choice,
tools,
messages: this.messages.map(toRequestMessage)
}, options);
allowBufferedToolCall = this.controller.signal.aborted && __classPrivateFieldGet(this, _AbstractChatCompletionRunner_completionArrivedBeforeAbort, "f");
const message = chatCompletion.choices[0]?.message;
if (!message) {
throw new OpenAIError(`missing message in ChatCompletion response`);
}
if (!message.tool_calls?.length) {
await runAfterCompletion(chatCompletion);
return;
}
if (singleFunctionToCall || params.parallel_tool_calls === false) {
for (const toolCall of message.tool_calls) {
const result = await runToolCall(toolCall);
if (result.message) {
this._addMessage(result.message);
}
if (this.controller.signal.aborted) {
throw this._userAbortError();
}
if (singleFunctionToCall && result.functionCalled) {
await runAfterCompletion(chatCompletion);
return;
}
}
} else {
const results = await Promise.allSettled(message.tool_calls.map(runToolCall));
if (!this.controller.signal.aborted) {
for (const result of results) {
if (result.status === "rejected") {
throw result.reason;
}
}
}
for (const result of results) {
if (result.status === "fulfilled" && result.value.message) {
this._addMessage(result.value.message);
}
}
if (this.controller.signal.aborted) {
throw this._userAbortError();
}
}
await runAfterCompletion(chatCompletion);
}
}
};
_a2 = AbstractChatCompletionRunner, _AbstractChatCompletionRunner_completionArrivedBeforeAbort = /* @__PURE__ */ new WeakMap(), _AbstractChatCompletionRunner_afterCompletionInvoked = /* @__PURE__ */ new WeakMap(), _AbstractChatCompletionRunner_instances = /* @__PURE__ */ new WeakSet(), _AbstractChatCompletionRunner_getFinalContent = function _AbstractChatCompletionRunner_getFinalContent2() {
return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this).content ?? null;
}, _AbstractChatCompletionRunner_getFinalMessage = function _AbstractChatCompletionRunner_getFinalMessage2() {
let i = this.messages.length;
while (i-- > 0) {
const message = this.messages[i];
if (isAssistantMessage(message)) {
const ret = {
...message,
content: message.content ?? null,
refusal: message.refusal ?? null
};
return ret;
}
}
throw new OpenAIError("stream ended without producing a ChatCompletionMessage with role=assistant");
}, _AbstractChatCompletionRunner_getFinalFunctionToolCall = function _AbstractChatCompletionRunner_getFinalFunctionToolCall2() {
for (let i = this.messages.length - 1; i >= 0; i--) {
const message = this.messages[i];
if (isAssistantMessage(message) && message?.tool_calls?.length) {
for (let j = message.tool_calls.length - 1; j >= 0; j--) {
const toolCall = message.tool_calls[j];
if (toolCall?.type === "function") {
return toolCall.function;
}
}
}
}
return void 0;
}, _AbstractChatCompletionRunner_getFinalFunctionToolCallResult = function _AbstractChatCompletionRunner_getFinalFunctionToolCallResult2() {
for (let i = this.messages.length - 1; i >= 0; i--) {
const message = this.messages[i];
if (isToolMessage(message) && message.content != null && // oxlint-disable-next-line anti-slop/no-runtime-typeof -- Chat history and tool-choice inputs can contain runtime variants that select different runner behavior.
typeof message.content === "string" && this.messages.some((x) => x.role === "assistant" && x.tool_calls?.some((y) => y.type === "function" && y.id === message.tool_call_id))) {
return message.content;
}
}
return void 0;
}, _AbstractChatCompletionRunner_calculateTotalUsage = function _AbstractChatCompletionRunner_calculateTotalUsage2() {
const total = {
completion_tokens: 0,
prompt_tokens: 0,
total_tokens: 0
};
for (const { usage } of this._chatCompletions) {
if (usage) {
total.completion_tokens += usage.completion_tokens;
total.prompt_tokens += usage.prompt_tokens;
total.total_tokens += usage.total_tokens;
}
}
return total;
}, _AbstractChatCompletionRunner_throwIfAborted = function _AbstractChatCompletionRunner_throwIfAborted2() {
if (this.controller.signal.aborted) {
throw this._userAbortError();
}
}, _AbstractChatCompletionRunner_validateParams = function _AbstractChatCompletionRunner_validateParams2(params) {
if (params.n != null && params.n > 1) {
throw new OpenAIError("ChatCompletion convenience helpers only support n=1 at this time. To use n>1, please use chat.completions.create() directly.");
}
}, _AbstractChatCompletionRunner_stringifyFunctionCallResult = function _AbstractChatCompletionRunner_stringifyFunctionCallResult2(rawContent) {
if (typeof rawContent === "string") {
return rawContent;
}
if (rawContent === void 0) {
return "undefined";
}
return JSON.stringify(rawContent);
};
}
});
// node_modules/openai/lib/ChatCompletionRunner.mjs
var ChatCompletionRunner;
var init_ChatCompletionRunner = __esm({
"node_modules/openai/lib/ChatCompletionRunner.mjs"() {
init_AbstractChatCompletionRunner();
init_chatCompletionUtils();
ChatCompletionRunner = class _ChatCompletionRunner extends AbstractChatCompletionRunner {
/** Starts a non-streaming tool loop and returns its event-driven conversation runner. */
static runTools(client, params, options) {
const runner = new _ChatCompletionRunner();
const opts = {
...options,
__metadata: { ...options?.__metadata, helperMethod: "runTools" }
};
runner._run(() => runner._runTools(client, params, runner, opts));
return runner;
}
/**
* Appends a conversation message and emits text content for assistant replies.
* @param normalizeContent Defaults to true; initial history passes false to preserve caller-owned messages.
*/
_addMessage(message, emit = true, normalizeContent = true) {
super._addMessage(message, emit, normalizeContent);
if (emit && isAssistantMessage(message) && message.content) {
this._emit("content", message.content);
}
}
};
}
});
// node_modules/openai/_vendor/partial-json-parser/parser.mjs
function parseJSON(jsonString, allowPartial = 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);
}
var STR, NUM, ARR, OBJ, NULL, BOOL, NAN, INFINITY, MINUS_INFINITY, INF, SPECIAL, ATOM, COLLECTION, ALL, Allow, PartialJSON, MalformedJSON, _parseJSON, partialParse;
var init_parser2 = __esm({
"node_modules/openai/_vendor/partial-json-parser/parser.mjs"() {
STR = 1;
NUM = 2;
ARR = 4;
OBJ = 8;
NULL = 16;
BOOL = 32;
NAN = 64;
INFINITY = 128;
MINUS_INFINITY = 256;
INF = INFINITY | MINUS_INFINITY;
SPECIAL = NULL | BOOL | INF | NAN;
ATOM = STR | NUM | SPECIAL;
COLLECTION = ARR | OBJ;
ALL = ATOM | COLLECTION;
Allow = {
STR,
NUM,
ARR,
OBJ,
NULL,
BOOL,
NAN,
INFINITY,
MINUS_INFINITY,
INF,
SPECIAL,
ATOM,
COLLECTION,
ALL
};
PartialJSON = class extends Error {
};
MalformedJSON = class extends Error {
};
_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" || Allow.NULL & allow && length - index < 4 && "null".startsWith(jsonString.substring(index))) {
index += 4;
return null;
}
if (jsonString.substring(index, index + 4) === "true" || Allow.BOOL & allow && length - index < 4 && "true".startsWith(jsonString.substring(index))) {
index += 4;
return true;
}
if (jsonString.substring(index, index + 5) === "false" || Allow.BOOL & allow && length - index < 5 && "false".startsWith(jsonString.substring(index))) {
index += 5;
return false;
}
if (jsonString.substring(index, index + 8) === "Infinity" || Allow.INFINITY & allow && length - index < 8 && "Infinity".startsWith(jsonString.substring(index))) {
index += 8;
return Infinity;
}
if (jsonString.substring(index, index + 9) === "-Infinity" || Allow.MINUS_INFINITY & allow && length - index > 1 && length - index < 9 && "-Infinity".startsWith(jsonString.substring(index))) {
index += 9;
return -Infinity;
}
if (jsonString.substring(index, index + 3) === "NaN" || Allow.NAN & allow && length - index < 3 && "NaN".startsWith(jsonString.substring(index))) {
index += 3;
return Number.NaN;
}
return parseNum();
};
const parseStr = () => {
const start = index;
let escape2 = false;
index++;
while (index < length && (jsonString[index] !== '"' || escape2 && jsonString[index - 1] === "\\")) {
escape2 = jsonString[index] === "\\" ? !escape2 : false;
index++;
}
if (jsonString.charAt(index) === '"') {
try {
return JSON.parse(jsonString.substring(start, ++index - Number(escape2)));
} catch (e) {
throwMalformedError(String(e));
}
} else if (Allow.STR & allow) {
try {
return JSON.parse(jsonString.substring(start, index - Number(escape2)) + '"');
} catch {
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("\\")) + '"');
}
}
markPartialJSON("Unterminated string literal");
};
const parseObj = () => {
index++;
skipBlank();
const obj2 = {};
try {
while (jsonString[index] !== "}") {
skipBlank();
if (index >= length && Allow.OBJ & allow) {
return obj2;
}
const key = parseStr();
skipBlank();
index++;
try {
const value2 = parseAny();
Object.defineProperty(obj2, key, { value: value2, writable: true, enumerable: true, configurable: true });
} catch (e) {
if (Allow.OBJ & allow) {
return obj2;
}
throw e;
}
skipBlank();
if (jsonString[index] === ",") {
index++;
}
}
} catch {
if (Allow.OBJ & allow) {
return obj2;
}
markPartialJSON("Expected '}' at end of object");
}
index++;
return obj2;
};
const parseArr = () => {
index++;
const arr2 = [];
try {
while (jsonString[index] !== "]") {
arr2.push(parseAny());
skipBlank();
if (jsonString[index] === ",") {
index++;
}
}
} catch {
if (Allow.ARR & allow) {
return arr2;
}
markPartialJSON("Expected ']' at end of array");
}
index++;
return arr2;
};
const parseNum = () => {
if (index === 0) {
if (jsonString === "-" && Allow.NUM & allow) {
markPartialJSON("Not sure what '-' is");
}
try {
return JSON.parse(jsonString);
} catch (e) {
if (Allow.NUM & allow) {
try {
if (jsonString[jsonString.length - 1] === ".") {
return JSON.parse(jsonString.substring(0, jsonString.lastIndexOf(".")));
}
return JSON.parse(jsonString.substring(0, jsonString.lastIndexOf("e")));
} catch {
}
}
throwMalformedError(String(e));
}
}
const start = index;
if (jsonString[index] === "-") {
index++;
}
while (jsonString[index] && !",]}".includes(jsonString[index])) {
index++;
}
if (index === length && !(Allow.NUM & allow)) {
markPartialJSON("Unterminated number literal");
}
const number2 = jsonString.substring(start, index);
try {
return JSON.parse(number2);
} catch {
if (number2 === "-" && Allow.NUM & allow) {
markPartialJSON("Not sure what '-' is");
}
try {
return JSON.parse(number2.substring(0, number2.lastIndexOf("e")));
} catch (e) {
throwMalformedError(String(e));
}
}
};
const skipBlank = () => {
while (index < length && " \n\r ".includes(jsonString[index])) {
index++;
}
};
return parseAny();
};
partialParse = (input) => parseJSON(input, Allow.ALL ^ Allow.NUM);
}
});
// node_modules/openai/streaming.mjs
var init_streaming2 = __esm({
"node_modules/openai/streaming.mjs"() {
init_streaming();
}
});
// node_modules/openai/lib/ChatCompletionStream.mjs
function parseStructuredStreamingJSON(content) {
try {
return partialParse(content);
} catch (error) {
if (error instanceof MalformedJSON || error instanceof SyntaxError) {
return parseResponseFormatContent({ type: "json_schema", $parseRaw: void 0 }, content);
}
throw error;
}
}
function makeChatCompletionReadableStreamMessageChunk(chunk, message, toolCallIds) {
const payload = {
type: "message",
message,
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...toolCallIds ? { tool_call_ids: toolCallIds } : {}
};
return {
id: chunk.id,
choices: [],
created: chunk.created,
model: chunk.model,
object: `${CHAT_COMPLETION_READABLE_STREAM_MESSAGE_PREFIX}${JSON.stringify(payload)}`
};
}
function isChatCompletionReadableStreamMessage(item) {
return "type" in item && item.type === "message" && "message" in item || "object" in item && typeof item.object === "string" && item.object.startsWith(CHAT_COMPLETION_READABLE_STREAM_MESSAGE_PREFIX);
}
function getChatCompletionReadableStreamMessage(item) {
if ("type" in item) {
return item;
}
return JSON.parse(item.object.slice(CHAT_COMPLETION_READABLE_STREAM_MESSAGE_PREFIX.length));
}
function createPartialJSONParseState() {
return {
bytes: 0,
depth: 0,
fragments: 0,
work: 0,
escaped: false,
has_non_whitespace: false,
in_string: false,
last_parsed_bytes: 0,
pending_high_surrogate: false
};
}
function recordPartialJSONFragment(state2, budget, fragment, validationWorkBudget) {
if (budget.fragments >= MAX_PARTIAL_JSON_FRAGMENTS) {
throw new OpenAIError("Chat completion stream exceeded its structured JSON fragment limit");
}
let bytes2 = 0;
let { depth, escaped, has_non_whitespace: hasNonWhitespace, in_string: inString } = state2;
let completed = false;
let firstCharacter = true;
for (const character of fragment) {
const previousBytes = bytes2;
const codePoint = character.codePointAt(0);
if (firstCharacter && state2.pending_high_surrogate && codePoint >= 56320 && codePoint <= 57343) {
bytes2 += 1;
} else if (codePoint <= 127) {
bytes2 += 1;
} else if (codePoint <= 2047) {
bytes2 += 2;
} else if (codePoint <= 65535) {
bytes2 += 3;
} else {
bytes2 += 4;
}
firstCharacter = false;
if (budget.bytes + bytes2 > MAX_PARTIAL_JSON_BYTES) {
throw new OpenAIError("Chat completion stream exceeded its structured JSON byte limit");
}
if (validationWorkBudget && validationWorkBudget.work + bytes2 > MAX_PARTIAL_JSON_PARSE_WORK) {
validationWorkBudget.work += previousBytes;
throw new OpenAIError("Chat completion stream exceeded its structured JSON parse-work limit");
}
if (character !== " " && character !== "\n" && character !== "\r" && character !== " ") {
hasNonWhitespace = true;
}
if (inString) {
if (escaped) {
escaped = false;
} else if (character === "\\") {
escaped = true;
} else if (character === '"') {
inString = false;
completed || (completed = depth === 0);
}
continue;
}
if (character === '"') {
inString = true;
} else if (character === "{" || character === "[") {
depth += 1;
if (depth > MAX_PARTIAL_JSON_DEPTH) {
throw new OpenAIError("Chat completion stream exceeded its structured JSON nesting depth limit");
}
} else if ((character === "}" || character === "]") && depth > 0) {
depth -= 1;
completed || (completed = depth === 0);
}
}
state2.bytes += bytes2;
state2.fragments += 1;
state2.depth = depth;
state2.escaped = escaped;
state2.has_non_whitespace = hasNonWhitespace;
state2.in_string = inString;
if (fragment.length > 0) {
const finalCodeUnit = fragment.codePointAt(fragment.length - 1) ?? 0;
state2.pending_high_surrogate = finalCodeUnit >= 55296 && finalCodeUnit <= 56319;
}
budget.bytes += bytes2;
budget.fragments += 1;
if (validationWorkBudget) {
validationWorkBudget.work += bytes2;
}
if (!hasNonWhitespace || bytes2 === 0) {
return false;
}
const minimumGrowth = Math.max(EAGER_PARTIAL_JSON_BYTES, Math.floor(state2.last_parsed_bytes / 2));
if (state2.bytes > EAGER_PARTIAL_JSON_BYTES && !completed && state2.bytes - state2.last_parsed_bytes < minimumGrowth) {
return false;
}
return true;
}
function reservePartialJSONParse(state2, budget) {
if (budget.work + state2.bytes > MAX_PARTIAL_JSON_PARSE_WORK) {
return false;
}
budget.work += state2.bytes;
state2.work += state2.bytes;
state2.last_parsed_bytes = state2.bytes;
return true;
}
function captureStructuredJSONSnapshot(snapshot, property) {
const descriptor = Object.getOwnPropertyDescriptor(snapshot, property);
if (!descriptor) {
let prototype = Object.getPrototypeOf(snapshot);
for (let depth = 0; prototype !== null; depth += 1) {
if (depth >= MAX_PARTIAL_JSON_DEPTH || Object.getOwnPropertyDescriptor(prototype, property)) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
prototype = Object.getPrototypeOf(prototype);
}
return void 0;
}
if (!("value" in descriptor) || typeof descriptor.value !== "string" && descriptor.value !== null && descriptor.value !== void 0) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
return descriptor.value;
}
function captureStructuredMessageSnapshot(choice) {
const descriptor = Object.getOwnPropertyDescriptor(choice, "message");
if (!descriptor || !("value" in descriptor) || typeof descriptor.value !== "object" || descriptor.value === null) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
return descriptor.value;
}
function captureSnapshotArray(snapshot, property, maximum, kind) {
const descriptor = Object.getOwnPropertyDescriptor(snapshot, property);
if (!descriptor) {
let prototype = Object.getPrototypeOf(snapshot);
for (let depth = 0; prototype !== null; depth += 1) {
if (depth >= MAX_PARTIAL_JSON_DEPTH || Object.getOwnPropertyDescriptor(prototype, property)) {
throw new OpenAIError(`Chat completion stream contains an unsafe snapshot ${kind} collection`);
}
prototype = Object.getPrototypeOf(prototype);
}
return void 0;
}
if (!("value" in descriptor) || !Array.isArray(descriptor.value)) {
throw new OpenAIError(`Chat completion stream contains an unsafe snapshot ${kind} collection`);
}
const length = Object.getOwnPropertyDescriptor(descriptor.value, "length");
if (!length || !("value" in length) || !Number.isSafeInteger(length.value) || length.value > maximum) {
throw new OpenAIError(`Chat completion stream exceeded its snapshot ${kind} limit`);
}
return descriptor.value;
}
function captureSnapshotArrayItem(array, index) {
const descriptor = Object.getOwnPropertyDescriptor(array, index);
if (!descriptor) {
return void 0;
}
if (!("value" in descriptor)) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
return descriptor.value;
}
function mapCapturedSnapshotArray(array, maximum, kind, map2) {
const descriptor = Object.getOwnPropertyDescriptor(array, "length");
const length = descriptor && "value" in descriptor ? descriptor.value : void 0;
if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || length > maximum) {
throw new OpenAIError(`Chat completion stream exceeded its snapshot ${kind} limit`);
}
const mapped = [];
mapped.length = length;
for (let index = 0; index < length; index += 1) {
const item = Object.getOwnPropertyDescriptor(array, index);
if (!item) {
continue;
}
if (!("value" in item)) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
mapped[index] = map2(item.value, index);
}
return mapped;
}
function validateStructuredJSONSnapshot(value2, budget, validationWorkBudget) {
const state2 = createPartialJSONParseState();
const parseBudget = budget ?? { bytes: 0, fragments: 0, work: 0 };
recordPartialJSONFragment(state2, parseBudget, value2, validationWorkBudget);
if (!reservePartialJSONParse(state2, parseBudget)) {
throw new OpenAIError("Chat completion stream exceeded its structured JSON parse-work limit");
}
return value2;
}
function ownFunctionToolIdentity(toolCall) {
const type = Object.getOwnPropertyDescriptor(toolCall, "type");
const fn = Object.getOwnPropertyDescriptor(toolCall, "function");
if (!type || !("value" in type) || type.value !== "function" || !fn || !("value" in fn)) {
return void 0;
}
if (typeof fn.value !== "object" || fn.value === null) {
return void 0;
}
const name = Object.getOwnPropertyDescriptor(fn.value, "name");
if (!name || !("value" in name) || typeof name.value !== "string" || name.value.length === 0) {
return void 0;
}
return { type: "function", name: name.value };
}
function assertBoundToolCallIdentity(toolCall, identity) {
const current = ownFunctionToolIdentity(toolCall);
if (!current || current.name !== identity.name || current.type !== identity.type) {
throw new OpenAIError("Chat completion stream contains a changed tool call identity");
}
}
function assignOwnProperties(target, source) {
if (Object.prototype.propertyIsEnumerable.call(source, "__proto__") && !hasOwn(target, "__proto__")) {
Object.defineProperty(target, "__proto__", {
value: void 0,
writable: true,
enumerable: true,
configurable: true
});
}
return Object.assign(target, source);
}
function cloneParserConfigObject(value2, stableFields = []) {
const descriptors = Object.getOwnPropertyDescriptors(value2);
for (const field of stableFields) {
const descriptor = descriptors[field];
if (!descriptor && !(field in value2)) {
continue;
}
descriptors[field] = {
// oxlint-disable-next-line anti-slop/no-reflect-get -- Generic config cloning must resolve inherited/accessor keys outside the declared config shape.
value: descriptor && "value" in descriptor ? descriptor.value : Reflect.get(value2, field, value2),
enumerable: descriptor?.enumerable ?? false,
configurable: descriptor?.configurable ?? true,
writable: descriptor && "writable" in descriptor ? descriptor.writable : false
};
}
return Object.create(Object.getPrototypeOf(value2), descriptors);
}
function snapshotChatCompletionParserParams(params) {
const snapshot = cloneParserConfigObject(params);
if (params.tools) {
const stableTools = [];
const lengthDescriptor = Object.getOwnPropertyDescriptor(params.tools, "length");
const length = lengthDescriptor && "value" in lengthDescriptor ? lengthDescriptor.value : void 0;
const toolCount = typeof length === "number" && Number.isSafeInteger(length) && length >= 0 ? Math.min(length, MAX_STREAM_TOOL_CALLS) : 0;
for (let index = 0; index < toolCount; index += 1) {
const item = Object.getOwnPropertyDescriptor(params.tools, String(index));
if (!item || !("value" in item)) {
stableTools.length = index + 1;
continue;
}
const tool = item.value;
const stableTool = cloneParserConfigObject(tool, [
"type",
"$brand",
"$parseRaw",
"$callback",
"function"
]);
const descriptors = Object.getOwnPropertyDescriptors(stableTool);
if (isChatCompletionFunctionTool(stableTool)) {
const descriptor = descriptors.function;
descriptors.function = {
...descriptor && "value" in descriptor ? descriptor : { configurable: true, enumerable: true, writable: true },
value: cloneParserConfigObject(stableTool.function, ["name", "strict"])
};
}
stableTools[index] = Object.create(Object.getPrototypeOf(tool), descriptors);
}
snapshot.tools = stableTools;
}
if (params.response_format) {
snapshot.response_format = cloneParserConfigObject(params.response_format, [
"type",
"$brand",
"$parseRaw"
]);
}
return snapshot;
}
function canonicalSerializedParserSchema(value2, budget) {
const ancestors = /* @__PURE__ */ new WeakSet();
const charge = (bytes2) => {
if (!Number.isSafeInteger(bytes2) || bytes2 < 0 || budget.bytes + bytes2 > MAX_SERIALIZED_PARSER_SCHEMA_BYTES) {
return false;
}
budget.bytes += bytes2;
return true;
};
const visit = (current, depth) => {
if (depth > MAX_SERIALIZED_PARSER_SCHEMA_DEPTH || budget.nodes >= MAX_SERIALIZED_PARSER_SCHEMA_NODES) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
budget.nodes += 1;
if (current === void 0 || typeof current === "function" || typeof current === "symbol") {
return OMITTED_SERIALIZED_PARSER_VALUE;
}
if (typeof current === "bigint") {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
if (current === null || typeof current === "boolean" || typeof current === "number") {
const serialized = stringifyParserSchemaValue(current);
return typeof serialized === "string" && charge(serialized.length) ? serialized : UNSAFE_SERIALIZED_PARSER_VALUE;
}
if (typeof current === "string") {
if (!charge(current.length * 6 + 2)) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
return stringifyParserSchemaValue(current);
}
if (typeof current !== "object" || ancestors.has(current)) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
const array = Array.isArray(current);
const prototype = Object.getPrototypeOf(current);
if (array && prototype !== Array.prototype || !array && prototype !== null && prototype !== Object.prototype) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
for (let owner = current; owner !== null; owner = Object.getPrototypeOf(owner)) {
const serializer = Object.getOwnPropertyDescriptor(owner, "toJSON");
if (!serializer) {
continue;
}
if (!("value" in serializer) || typeof serializer.value === "function") {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
break;
}
ancestors.add(current);
try {
if (!charge(2)) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
if (array) {
const lengthDescriptor = Object.getOwnPropertyDescriptor(current, "length");
const length = lengthDescriptor && "value" in lengthDescriptor ? lengthDescriptor.value : void 0;
if (typeof length !== "number" || !Number.isSafeInteger(length) || length < 0 || length > MAX_SERIALIZED_PARSER_SCHEMA_NODES - budget.nodes) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
const items = [];
for (let index = 0; index < length; index += 1) {
const key = String(index);
const descriptor = Object.getOwnPropertyDescriptor(current, key);
if (!descriptor) {
if (Object.getOwnPropertyDescriptor(Array.prototype, key) || Object.getOwnPropertyDescriptor(Object.prototype, key)) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
budget.nodes += 1;
if (!charge(4)) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
items.push("null");
continue;
}
if (!("value" in descriptor)) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
const item = visit(descriptor.value, depth + 1);
if (item === UNSAFE_SERIALIZED_PARSER_VALUE) {
return item;
}
items.push(item === OMITTED_SERIALIZED_PARSER_VALUE ? "null" : item);
}
return `[${items.join(",")}]`;
}
const keys = Reflect.ownKeys(current);
if (keys.length > MAX_SERIALIZED_PARSER_SCHEMA_NODES - budget.nodes) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
const entries2 = [];
for (const key of keys) {
if (typeof key !== "string") {
continue;
}
const descriptor = Object.getOwnPropertyDescriptor(current, key);
if (!descriptor) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
if (!descriptor.enumerable) {
continue;
}
if (!("value" in descriptor)) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
entries2.push([key, descriptor.value]);
}
entries2.sort(([left], [right]) => {
if (left === right) {
return 0;
}
return left < right ? -1 : 1;
});
const fields = [];
for (const [key, entry2] of entries2) {
const normalized = visit(entry2, depth + 1);
if (normalized === UNSAFE_SERIALIZED_PARSER_VALUE) {
return normalized;
}
if (normalized === OMITTED_SERIALIZED_PARSER_VALUE) {
continue;
}
if (!charge(key.length * 6 + 3)) {
return UNSAFE_SERIALIZED_PARSER_VALUE;
}
fields.push(`${stringifyParserSchemaValue(key)}:${normalized}`);
}
return `{${fields.join(",")}}`;
} finally {
ancestors.delete(current);
}
};
try {
const normalized = visit(value2, 0);
return typeof normalized === "string" ? normalized : void 0;
} catch {
return void 0;
}
}
function rememberSerializedParserSchema(signatures, source, holder, key) {
const parser = Object.getOwnPropertyDescriptor(source, "$parseRaw");
const schema = Object.getOwnPropertyDescriptor(holder, key);
if (!parser || !("value" in parser) || typeof parser.value !== "function" || !schema || !("value" in schema)) {
return;
}
const normalized = canonicalSerializedParserSchema(schema.value, { nodes: 0, bytes: 0 });
if (normalized !== void 0) {
signatures.set(source, normalized);
}
}
function hasMatchingSerializedParserSchema(signatures, source, holder, key, value2) {
const expected = source && signatures.get(source);
const descriptor = Object.getOwnPropertyDescriptor(holder, key);
return expected !== void 0 && descriptor !== void 0 && "value" in descriptor && canonicalSerializedParserSchema(value2, { nodes: 0, bytes: 0 }) === expected;
}
function serializedParserDescriptor(descriptor, value2) {
return descriptor && "value" in descriptor ? { ...descriptor, value: value2 } : { configurable: true, enumerable: true, writable: true, value: value2 };
}
function shadowSerializedParserMetadata(descriptors, source, fields) {
for (const field of fields) {
const descriptor = descriptors[field];
if (!descriptor && !(field in source)) {
continue;
}
descriptors[field] = descriptor && "value" in descriptor ? { ...descriptor, value: void 0 } : {
configurable: descriptor?.configurable ?? true,
enumerable: descriptor?.enumerable ?? false,
writable: false,
value: void 0
};
}
}
function snapshotSerializedParserTool(serialized) {
const source = serialized.source ?? {
type: serialized.type,
...serialized.type === "function" ? { function: {} } : {}
};
const descriptors = Object.getOwnPropertyDescriptors(source);
descriptors.type = serializedParserDescriptor(descriptors.type, serialized.type);
if (serialized.type !== "function" || !serialized.function) {
if (descriptors.function) {
descriptors.function = serializedParserDescriptor(descriptors.function, void 0);
}
shadowSerializedParserMetadata(descriptors, source, ["$brand", "$parseRaw", "$callback"]);
return Object.create(Object.getPrototypeOf(source), descriptors);
}
const descriptor = descriptors.function;
const original = descriptor && "value" in descriptor && typeof descriptor.value === "object" && descriptor.value !== null ? descriptor.value : {};
const functionDescriptors = Object.getOwnPropertyDescriptors(original);
functionDescriptors["name"] = serializedParserDescriptor(functionDescriptors["name"], serialized.function.name);
functionDescriptors["strict"] = serializedParserDescriptor(functionDescriptors["strict"], serialized.function.strict);
descriptors.function = serializedParserDescriptor(descriptor, Object.create(Object.getPrototypeOf(original), functionDescriptors));
if (!serialized.function.schemaMatches) {
shadowSerializedParserMetadata(descriptors, source, ["$brand", "$parseRaw", "$callback"]);
}
return Object.create(Object.getPrototypeOf(source), descriptors);
}
function snapshotSerializedResponseFormat(serialized) {
const source = serialized.source ?? { type: serialized.type };
const descriptors = Object.getOwnPropertyDescriptors(source);
descriptors.type = serializedParserDescriptor(descriptors.type, serialized.type);
if (serialized.type !== "json_schema" || !serialized.source || !serialized.schemaMatches) {
shadowSerializedParserMetadata(descriptors, source, ["$brand", "$parseRaw"]);
}
return Object.create(Object.getPrototypeOf(source), descriptors);
}
function ownSerializedParserObject(holder, key) {
const descriptor = Object.getOwnPropertyDescriptor(holder, key);
if (!descriptor || !("value" in descriptor)) {
return void 0;
}
const { value: value2 } = descriptor;
return typeof value2 === "object" && value2 !== null ? value2 : void 0;
}
function observeSerializedChatCompletionParserParams(body, initial, update) {
const originalToolOwners = /* @__PURE__ */ new WeakMap();
const originalSchemaSignatures = /* @__PURE__ */ new WeakMap();
if (body.tools) {
for (let index = 0; index < body.tools.length && index < MAX_STREAM_TOOL_CALLS; index += 1) {
const owner = ownSerializedParserObject(body.tools, String(index));
const source = initial.tools?.[index];
if (owner && source) {
originalToolOwners.set(owner, source);
const originalFunction = ownSerializedParserObject(source, "function");
if (originalFunction) {
rememberSerializedParserSchema(originalSchemaSignatures, source, originalFunction, "parameters");
}
}
}
}
if (initial.response_format) {
rememberSerializedParserSchema(originalSchemaSignatures, initial.response_format, initial.response_format, "json_schema");
}
let root2;
let tools;
let responseFormat;
let responseFrame;
let frames = [];
let toolFrames = /* @__PURE__ */ new WeakMap();
let actualToolOwners = /* @__PURE__ */ new Map();
let functionFrames = /* @__PURE__ */ new WeakMap();
return observeJSONRequestBody(body, {
value(holder, key, value2) {
if (!root2 && key === "" && typeof value2 === "object" && value2 !== null) {
root2 = value2;
tools = void 0;
responseFormat = void 0;
responseFrame = void 0;
frames = [];
toolFrames = /* @__PURE__ */ new WeakMap();
actualToolOwners = /* @__PURE__ */ new Map();
functionFrames = /* @__PURE__ */ new WeakMap();
return;
}
if (holder === root2 && key === "response_format") {
if (typeof value2 === "object" && value2 !== null) {
responseFormat = value2;
const owner = ownSerializedParserObject(holder, key);
responseFrame = {
source: owner === body.response_format ? initial.response_format : void 0,
schemaMatches: false
};
}
return;
}
if (holder === root2 && key === "tools") {
if (Array.isArray(value2)) {
tools = new Proxy(value2, {
get(target, property) {
const actual = Reflect.get(target, property, target);
if (typeof property === "string") {
const index = Number(property);
if (Number.isSafeInteger(index) && index >= 0 && index < MAX_STREAM_TOOL_CALLS && String(index) === property) {
actualToolOwners.set(index, typeof actual === "object" && actual !== null ? actual : void 0);
}
}
return actual;
}
});
return tools;
}
return;
}
if (holder === tools) {
const index = Number(key);
if (!Number.isSafeInteger(index) || index < 0 || index >= MAX_STREAM_TOOL_CALLS || typeof value2 !== "object" || value2 === null) {
return;
}
const owner = actualToolOwners.get(index);
const source = owner ? originalToolOwners.get(owner) : void 0;
const frame = { source };
frames[index] = frame;
toolFrames.set(value2, frame);
return;
}
const tool = toolFrames.get(holder);
if (tool) {
if (key === "type" && typeof value2 === "string") {
tool.type = value2;
} else if (key === "function" && typeof value2 === "object" && value2 !== null) {
const fn2 = { source: tool.source, schemaMatches: false };
tool.function = fn2;
functionFrames.set(value2, fn2);
}
return;
}
if (holder === responseFormat && responseFrame) {
if (key === "type" && typeof value2 === "string") {
responseFrame.type = value2;
} else if (key === "json_schema") {
responseFrame.schemaMatches = hasMatchingSerializedParserSchema(originalSchemaSignatures, responseFrame.source, holder, key, value2);
}
return;
}
const fn = functionFrames.get(holder);
if (fn) {
if (key === "name" && typeof value2 === "string") {
fn.name = value2;
} else if (key === "strict" && typeof value2 === "boolean") {
fn.strict = value2;
} else if (key === "parameters") {
fn.schemaMatches = hasMatchingSerializedParserSchema(originalSchemaSignatures, fn.source, holder, key, value2);
}
}
return void 0;
},
complete() {
if (!root2) {
return;
}
const snapshot = cloneParserConfigObject(initial);
if (tools) {
const serializedTools = [];
for (let index = 0; index < frames.length; index += 1) {
const frame = frames[index];
if (frame) {
serializedTools[index] = snapshotSerializedParserTool(frame);
}
}
snapshot.tools = serializedTools;
} else {
delete snapshot.tools;
}
if (responseFrame) {
snapshot.response_format = snapshotSerializedResponseFormat(responseFrame);
} else {
delete snapshot.response_format;
}
update(snapshot);
root2 = void 0;
tools = void 0;
responseFormat = void 0;
responseFrame = void 0;
frames = [];
toolFrames = /* @__PURE__ */ new WeakMap();
actualToolOwners = /* @__PURE__ */ new Map();
functionFrames = /* @__PURE__ */ new WeakMap();
}
});
}
function finalizeChatCompletion(snapshot, params, audioDoneChoiceIndexes, validatedMessages) {
const { id, choices, created, model: model3, system_fingerprint, ...rest } = snapshot;
const completion = {
...rest,
id,
choices: mapCapturedSnapshotArray(choices, MAX_STREAM_CHOICES, "choice", (choice) => {
const validated = validatedMessages.get(choice);
if (!validated) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
const stableChoice = new Proxy(choice, {
get(target, property, receiver) {
return property === "message" ? validated.message : Reflect.get(target, property, receiver);
}
});
const { message: sourceMessage, finish_reason, index, logprobs, ...choiceRest } = stableChoice;
const message = new Proxy(sourceMessage, {
get(target, property, receiver) {
if (property === "content") {
return validated.content;
}
if (property === "refusal") {
return validated.refusal;
}
if (property === "tool_calls") {
return validated.toolCallCollection;
}
return Reflect.get(target, property, receiver);
}
});
const { content = null, function_call, tool_calls, audio, ...messageRest } = message;
const finishReason = finish_reason ?? (audioDoneChoiceIndexes.has(index) && isCompleteAudio(audio) ? "stop" : null);
if (!finishReason) {
throw new OpenAIError(`missing finish_reason for choice ${index}`);
}
const audioResponse = audio ? { audio } : {};
const role = message.role;
if (!role) {
throw new OpenAIError(`missing role for choice ${index}`);
}
if (function_call) {
const { arguments: args, name } = function_call;
if (args == null) {
throw new OpenAIError(`missing function_call.arguments for choice ${index}`);
}
if (!name) {
throw new OpenAIError(`missing function_call.name for choice ${index}`);
}
return {
...choiceRest,
message: {
...audioResponse,
content,
function_call: { arguments: args, name },
role,
refusal: message.refusal ?? null
},
finish_reason: finishReason,
index,
logprobs
};
}
if (tool_calls) {
return {
...choiceRest,
index,
finish_reason: finishReason,
logprobs,
message: {
...messageRest,
...audioResponse,
role,
content,
refusal: message.refusal ?? null,
tool_calls: mapCapturedSnapshotArray(tool_calls, MAX_STREAM_TOOL_CALLS, "tool-call", (tool_call, i) => {
const captured = validated.toolCalls.get(i);
if (!captured) {
const identity = ownFunctionToolIdentity(tool_call);
if (identity && shouldParseToolCall(params, {
type: identity.type,
function: { name: identity.name }
})) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
}
if (captured && captured.tool !== tool_call) {
throw new OpenAIError("Chat completion stream contains a changed tool call identity");
}
const stableFunction = captured && new Proxy(captured.function, {
get(target, property, receiver) {
if (property === "arguments") {
return captured.arguments;
}
if (property === "name") {
return captured.name;
}
return Reflect.get(target, property, receiver);
}
});
const stableTool = captured && stableFunction ? new Proxy(tool_call, {
get(target, property, receiver) {
if (property === "type") {
return captured.type;
}
if (property === "function") {
return stableFunction;
}
return Reflect.get(target, property, receiver);
}
}) : tool_call;
if (stableTool.type == null) {
throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].type`);
}
if (stableTool.type === "custom") {
const { custom, type: type2, id: id3, ...toolRest2 } = stableTool;
const { input = "", name: name2, ...customRest } = custom || {};
if (name2 == null) {
throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].custom.name`);
}
return {
...toolRest2,
id: id3 || `call_${uuid4()}`,
type: type2,
custom: { ...customRest, name: name2, input }
};
}
const { function: fn, type, id: id2, ...toolRest } = stableTool;
const { arguments: args, name, ...fnRest } = fn || {};
if (name == null) {
throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].function.name`);
}
if (args == null) {
throw new OpenAIError(`missing choices[${index}].tool_calls[${i}].function.arguments`);
}
return {
...toolRest,
id: id2 || `call_${uuid4()}`,
type,
function: { ...fnRest, name, arguments: args }
};
})
}
};
}
return {
...choiceRest,
message: { ...messageRest, ...audioResponse, content, role, refusal: message.refusal ?? null },
finish_reason: finishReason,
index,
logprobs
};
}),
created,
model: model3,
object: "chat.completion",
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...system_fingerprint ? { system_fingerprint } : {}
};
return maybeParseChatCompletion(completion, params);
}
function isCompleteAudio(audio) {
return audio?.id != null && audio.data != null && audio.transcript != null && audio.expires_at != null;
}
function assertIsEmpty(obj2) {
void obj2;
}
function assertNever(_x) {
return _x;
}
var _ChatCompletionStream_instances, _ChatCompletionStream_params, _ChatCompletionStream_rejectsUnfinishedTurns, _ChatCompletionStream_audioDoneChoiceIndexes, _ChatCompletionStream_choiceEventStates, _ChatCompletionStream_currentChatCompletionSnapshot, _ChatCompletionStream_hasAutoParseableTool, _ChatCompletionStream_partialJSONParseBudget, _ChatCompletionStream_beginRequest, _ChatCompletionStream_getChoiceEventState, _ChatCompletionStream_addChunk, _ChatCompletionStream_emitToolCallDoneEvent, _ChatCompletionStream_emitContentDoneEvents, _ChatCompletionStream_validateStructuredSnapshots, _ChatCompletionStream_endRequest, _ChatCompletionStream_accumulateChatCompletion, CHAT_COMPLETION_READABLE_STREAM_MESSAGE_PREFIX, MAX_STREAM_CHOICES, MAX_STREAM_TOOL_CALLS, MAX_PARTIAL_JSON_BYTES, MAX_PARTIAL_JSON_FRAGMENTS, MAX_PARTIAL_JSON_DEPTH, MAX_PARTIAL_JSON_PARSE_WORK, EAGER_PARTIAL_JSON_BYTES, MAX_SERIALIZED_PARSER_SCHEMA_NODES, stringifyParserSchemaValue, MAX_SERIALIZED_PARSER_SCHEMA_BYTES, MAX_SERIALIZED_PARSER_SCHEMA_DEPTH, OMITTED_SERIALIZED_PARSER_VALUE, UNSAFE_SERIALIZED_PARSER_VALUE, ChatCompletionStream;
var init_ChatCompletionStream = __esm({
"node_modules/openai/lib/ChatCompletionStream.mjs"() {
init_tslib();
init_parser2();
init_error2();
init_request_options();
init_uuid();
init_values();
init_parser();
init_streaming2();
init_AbstractChatCompletionRunner();
CHAT_COMPLETION_READABLE_STREAM_MESSAGE_PREFIX = "chat.completion.chunk.message:";
MAX_STREAM_CHOICES = 128;
MAX_STREAM_TOOL_CALLS = 128;
MAX_PARTIAL_JSON_BYTES = 16 * 1024 * 1024;
MAX_PARTIAL_JSON_FRAGMENTS = 65536;
MAX_PARTIAL_JSON_DEPTH = 128;
MAX_PARTIAL_JSON_PARSE_WORK = 64 * 1024 * 1024;
EAGER_PARTIAL_JSON_BYTES = 1024;
MAX_SERIALIZED_PARSER_SCHEMA_NODES = 4096;
stringifyParserSchemaValue = JSON.stringify;
MAX_SERIALIZED_PARSER_SCHEMA_BYTES = 1024 * 1024;
MAX_SERIALIZED_PARSER_SCHEMA_DEPTH = 64;
OMITTED_SERIALIZED_PARSER_VALUE = /* @__PURE__ */ Symbol("omitted serialized parser value");
UNSAFE_SERIALIZED_PARSER_VALUE = /* @__PURE__ */ Symbol("unsafe serialized parser value");
ChatCompletionStream = class _ChatCompletionStream extends AbstractChatCompletionRunner {
/** Creates an unstarted stream, retaining request parameters for structured-output parsing. */
constructor(params) {
super();
_ChatCompletionStream_instances.add(this);
_ChatCompletionStream_params.set(this, void 0);
_ChatCompletionStream_rejectsUnfinishedTurns.set(this, false);
_ChatCompletionStream_audioDoneChoiceIndexes.set(this, void 0);
_ChatCompletionStream_choiceEventStates.set(this, void 0);
_ChatCompletionStream_currentChatCompletionSnapshot.set(this, void 0);
_ChatCompletionStream_hasAutoParseableTool.set(this, void 0);
_ChatCompletionStream_partialJSONParseBudget.set(this, void 0);
__classPrivateFieldSet(this, _ChatCompletionStream_params, params, "f");
__classPrivateFieldSet(this, _ChatCompletionStream_audioDoneChoiceIndexes, /* @__PURE__ */ new Set(), "f");
__classPrivateFieldSet(this, _ChatCompletionStream_choiceEventStates, [], "f");
__classPrivateFieldSet(this, _ChatCompletionStream_hasAutoParseableTool, false, "f");
const tools = params?.tools;
const lengthDescriptor = tools && Object.getOwnPropertyDescriptor(tools, "length");
const length = lengthDescriptor && "value" in lengthDescriptor ? lengthDescriptor.value : void 0;
if (tools && typeof length === "number" && Number.isSafeInteger(length) && length >= 0) {
for (let index = 0; index < Math.min(length, MAX_STREAM_TOOL_CALLS); index += 1) {
const descriptor = Object.getOwnPropertyDescriptor(tools, String(index));
if (!descriptor || !("value" in descriptor)) {
continue;
}
const tool = descriptor.value;
if (isChatCompletionFunctionTool(tool) && (isAutoParsableTool(tool) || tool.function.strict === true)) {
__classPrivateFieldSet(this, _ChatCompletionStream_hasAutoParseableTool, true, "f");
break;
}
}
}
__classPrivateFieldSet(this, _ChatCompletionStream_partialJSONParseBudget, { bytes: 0, fragments: 0, work: 0 }, "f");
}
/** The latest accumulated completion, or `undefined` before a chunk arrives or after finalization. */
get currentChatCompletionSnapshot() {
return __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f");
}
/**
* Intended for use on the frontend, consuming a stream produced with
* `.toReadableStream()` on the backend.
*
* Original input messages are not included in the serialized stream. Tool-result
* messages explicitly serialized by a streaming tool runner are replayed.
*/
static fromReadableStream(stream2) {
const runner = new _ChatCompletionStream(null);
runner._run(() => runner._fromReadableStream(stream2));
return runner;
}
/** Starts a streaming chat completion request and returns its event-driven helper. */
static createChatCompletion(client, params, options) {
const runner = new _ChatCompletionStream(params);
runner._run(() => runner._runChatCompletion(client, { ...params, stream: true }, { ...options, __metadata: { ...options?.__metadata, helperMethod: "stream" } }));
return runner;
}
/** Rejects unfinished turns before tool callbacks while preserving ordinary stream and replay behavior. */
_runTools(client, params, runner, options) {
__classPrivateFieldSet(this, _ChatCompletionStream_rejectsUnfinishedTurns, true, "f");
return super._runTools(client, params, runner, options);
}
async _createChatCompletion(client, params, options) {
this._listenForAbort(options?.signal);
const requestParams = { ...params, stream: true };
__classPrivateFieldSet(this, _ChatCompletionStream_params, requestParams, "f");
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_beginRequest).call(this);
const parserParams = snapshotChatCompletionParserParams(requestParams);
__classPrivateFieldSet(this, _ChatCompletionStream_params, parserParams, "f");
__classPrivateFieldSet(this, _ChatCompletionStream_hasAutoParseableTool, parserParams.tools?.some((tool) => isChatCompletionFunctionTool(tool) && (isAutoParsableTool(tool) || tool.function.strict === true)) ?? false, "f");
const stopObserving = requestParams.tools || requestParams.response_format ? observeSerializedChatCompletionParserParams(requestParams, parserParams, (serialized) => {
__classPrivateFieldSet(this, _ChatCompletionStream_params, serialized, "f");
__classPrivateFieldSet(this, _ChatCompletionStream_hasAutoParseableTool, serialized.tools?.some((tool) => isChatCompletionFunctionTool(tool) && (isAutoParsableTool(tool) || tool.function.strict === true)) ?? false, "f");
}) : void 0;
const stream2 = await client.chat.completions.create(requestParams, {
...options,
signal: this.controller.signal
}).finally(stopObserving);
this._connected();
for await (const chunk of stream2) {
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_addChunk).call(this, chunk);
}
if (stream2.controller.signal?.aborted) {
throw this._userAbortError();
}
return this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
}
async _fromReadableStream(readableStream, options) {
this._listenForAbort(options?.signal);
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_beginRequest).call(this);
this._connected();
const stream2 = Stream.fromReadableStream(readableStream, this.controller);
let chatId;
for await (const item of stream2) {
if ("error" in item && hasOwn(item, "error") && typeof item.error === "object" && item.error !== null) {
throw new APIError(void 0, item.error, void 0, void 0);
}
if (isChatCompletionReadableStreamMessage(item)) {
const message = getChatCompletionReadableStreamMessage(item);
if (__classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f")) {
const toolCalls = __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f").choices[0]?.message.tool_calls;
for (const [index, id] of message.tool_call_ids?.entries() ?? []) {
const toolCall = toolCalls?.[index];
if (toolCall && id) {
toolCall.id = id;
}
}
this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
chatId = void 0;
}
this._addMessage(message.message);
continue;
}
const chunk = item;
if (chatId && chunk.id && chatId !== chunk.id) {
this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
}
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_addChunk).call(this, chunk);
if (chunk.id) {
chatId = chunk.id;
}
}
if (stream2.controller.signal?.aborted) {
throw this._userAbortError();
}
if (__classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f")) {
return this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this));
}
const lastChatCompletion = this._chatCompletions[this._chatCompletions.length - 1];
if (lastChatCompletion) {
return lastChatCompletion;
}
throw new OpenAIError(`request ended without sending any chunks`);
}
/** Iterates over raw API chunks; stopping iteration early aborts the underlying request. */
[(_ChatCompletionStream_params = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_rejectsUnfinishedTurns = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_audioDoneChoiceIndexes = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_choiceEventStates = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_currentChatCompletionSnapshot = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_hasAutoParseableTool = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_partialJSONParseBudget = /* @__PURE__ */ new WeakMap(), _ChatCompletionStream_instances = /* @__PURE__ */ new WeakSet(), _ChatCompletionStream_beginRequest = function _ChatCompletionStream_beginRequest2() {
if (this.ended) {
return;
}
__classPrivateFieldSet(this, _ChatCompletionStream_audioDoneChoiceIndexes, /* @__PURE__ */ new Set(), "f");
__classPrivateFieldSet(this, _ChatCompletionStream_currentChatCompletionSnapshot, void 0, "f");
__classPrivateFieldSet(this, _ChatCompletionStream_partialJSONParseBudget, { bytes: 0, fragments: 0, work: 0 }, "f");
}, _ChatCompletionStream_getChoiceEventState = function _ChatCompletionStream_getChoiceEventState2(choice) {
let state2 = __classPrivateFieldGet(this, _ChatCompletionStream_choiceEventStates, "f")[choice.index];
if (state2) {
return state2;
}
state2 = {
content_done: false,
content_parse_state: void 0,
refusal_done: false,
logprobs_content_done: false,
logprobs_refusal_done: false,
done_tool_calls: /* @__PURE__ */ new Set(),
current_tool_call_index: null,
tool_call_parse_states: /* @__PURE__ */ new Map(),
tool_call_identities: /* @__PURE__ */ new Map()
};
__classPrivateFieldGet(this, _ChatCompletionStream_choiceEventStates, "f")[choice.index] = state2;
return state2;
}, _ChatCompletionStream_addChunk = function _ChatCompletionStream_addChunk2(chunk) {
if (this.ended) {
return;
}
const capturedChoiceFrames = /* @__PURE__ */ new WeakMap();
const completion = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_accumulateChatCompletion).call(this, chunk, capturedChoiceFrames);
this._emit("chunk", chunk, completion);
for (const choice of chunk.choices) {
const capturedChoice = capturedChoiceFrames.get(choice);
const choiceSnapshot = completion.choices[capturedChoice?.index ?? choice.index];
const capturedToolCalls = capturedChoice?.tool_calls ?? [];
const { delta } = choice;
const structuredResponse = isParseableResponseFormat(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.response_format);
const boundedSnapshot = structuredResponse || __classPrivateFieldGet(this, _ChatCompletionStream_hasAutoParseableTool, "f");
const messageSnapshot = boundedSnapshot ? captureStructuredMessageSnapshot(choiceSnapshot) : choiceSnapshot.message;
const refusal = boundedSnapshot ? captureStructuredJSONSnapshot(messageSnapshot, "refusal") : messageSnapshot.refusal;
const parseableContent = !refusal && structuredResponse;
const messageContent = parseableContent ? captureStructuredJSONSnapshot(messageSnapshot, "content") : messageSnapshot.content;
if (delta?.content != null && messageSnapshot.role === "assistant" && messageContent) {
this._emit("content", delta.content, messageContent);
this._emit("content.delta", {
delta: delta.content,
snapshot: messageContent,
parsed: messageSnapshot.parsed
});
}
if (delta?.refusal != null && messageSnapshot.role === "assistant" && refusal) {
this._emit("refusal.delta", {
delta: delta.refusal,
snapshot: refusal
});
}
if (choice.logprobs?.content != null && messageSnapshot.role === "assistant") {
this._emit("logprobs.content.delta", {
content: choice.logprobs?.content,
snapshot: choiceSnapshot.logprobs?.content ?? []
});
}
if (choice.logprobs?.refusal != null && messageSnapshot.role === "assistant") {
this._emit("logprobs.refusal.delta", {
refusal: choice.logprobs?.refusal,
snapshot: choiceSnapshot.logprobs?.refusal ?? []
});
}
const state2 = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choiceSnapshot);
if (choiceSnapshot.finish_reason) {
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitContentDoneEvents).call(this, choiceSnapshot);
if (state2.current_tool_call_index != null) {
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitToolCallDoneEvent).call(this, choiceSnapshot, state2.current_tool_call_index);
}
}
for (const toolCall of capturedToolCalls) {
if (state2.current_tool_call_index !== toolCall.index) {
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitContentDoneEvents).call(this, choiceSnapshot);
if (state2.current_tool_call_index != null) {
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_emitToolCallDoneEvent).call(this, choiceSnapshot, state2.current_tool_call_index);
}
}
state2.current_tool_call_index = toolCall.index;
}
for (const toolCallDelta of capturedToolCalls) {
const toolCallSnapshot = messageSnapshot.tool_calls?.[toolCallDelta.index];
if (!toolCallSnapshot?.type) {
continue;
}
if (toolCallSnapshot.type === "function") {
const boundIdentity = state2.tool_call_identities.get(toolCallDelta.index);
let argumentsSnapshot;
if (boundIdentity?.parseable) {
const capturedArguments = captureStructuredJSONSnapshot(toolCallSnapshot.function, "arguments");
if (typeof capturedArguments !== "string") {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
argumentsSnapshot = capturedArguments;
} else {
argumentsSnapshot = toolCallSnapshot.function.arguments;
}
this._emit("tool_calls.function.arguments.delta", {
name: toolCallSnapshot.function.name,
index: toolCallDelta.index,
arguments: argumentsSnapshot,
parsed_arguments: toolCallSnapshot.function.parsed_arguments,
arguments_delta: toolCallDelta.arguments_delta
});
} else if (toolCallSnapshot.type !== "custom") {
assertNever(toolCallSnapshot);
}
}
}
}, _ChatCompletionStream_emitToolCallDoneEvent = function _ChatCompletionStream_emitToolCallDoneEvent2(choiceSnapshot, toolCallIndex) {
const state2 = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choiceSnapshot);
if (state2.done_tool_calls.has(toolCallIndex)) {
return;
}
const messageSnapshot = __classPrivateFieldGet(this, _ChatCompletionStream_hasAutoParseableTool, "f") ? captureStructuredMessageSnapshot(choiceSnapshot) : choiceSnapshot.message;
const toolCallSnapshot = messageSnapshot.tool_calls?.[toolCallIndex];
if (!toolCallSnapshot) {
throw new Error("no tool call snapshot");
}
const boundIdentity = state2.tool_call_identities.get(toolCallIndex);
if (boundIdentity) {
assertBoundToolCallIdentity(toolCallSnapshot, boundIdentity);
}
if (!toolCallSnapshot.type) {
throw new Error("tool call snapshot missing `type`");
}
if (toolCallSnapshot.type === "function") {
const inputTool = __classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.tools?.find((tool) => isChatCompletionFunctionTool(tool) && tool.function.name === toolCallSnapshot.function.name);
let parsedArguments = null;
const parseable = isAutoParsableTool(inputTool) || inputTool?.function.strict === true;
let argumentsSnapshot;
if (parseable) {
if (__classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f")) {
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_validateStructuredSnapshots).call(this, __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f"));
}
const capturedArguments = captureStructuredJSONSnapshot(toolCallSnapshot.function, "arguments");
if (typeof capturedArguments !== "string") {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
argumentsSnapshot = capturedArguments;
} else {
argumentsSnapshot = toolCallSnapshot.function.arguments;
}
if (isAutoParsableTool(inputTool)) {
parsedArguments = inputTool.$parseRaw(validateStructuredJSONSnapshot(argumentsSnapshot));
} else if (inputTool?.function.strict) {
parsedArguments = parseResponseFormatContent({ type: "json_schema", $parseRaw: void 0 }, validateStructuredJSONSnapshot(argumentsSnapshot));
}
if (choiceSnapshot.finish_reason) {
state2.done_tool_calls.add(toolCallIndex);
}
this._emit("tool_calls.function.arguments.done", {
name: toolCallSnapshot.function.name,
index: toolCallIndex,
arguments: argumentsSnapshot,
parsed_arguments: parsedArguments
});
} else if (toolCallSnapshot.type !== "custom") {
assertNever(toolCallSnapshot);
}
}, _ChatCompletionStream_emitContentDoneEvents = function _ChatCompletionStream_emitContentDoneEvents2(choiceSnapshot) {
const state2 = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choiceSnapshot);
const structuredResponse = isParseableResponseFormat(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.response_format);
const boundedSnapshot = structuredResponse || __classPrivateFieldGet(this, _ChatCompletionStream_hasAutoParseableTool, "f");
const messageSnapshot = boundedSnapshot ? captureStructuredMessageSnapshot(choiceSnapshot) : choiceSnapshot.message;
const refusal = boundedSnapshot ? captureStructuredJSONSnapshot(messageSnapshot, "refusal") : messageSnapshot.refusal;
const parseableContent = !refusal && structuredResponse;
const content = parseableContent ? captureStructuredJSONSnapshot(messageSnapshot, "content") : messageSnapshot.content;
if (content != null && (content !== "" || !refusal && !messageSnapshot.tool_calls?.length && !messageSnapshot.function_call) && !state2.content_done) {
if (parseableContent && __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f")) {
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_validateStructuredSnapshots).call(this, __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f"));
}
state2.content_done = true;
this._emit("content.done", {
content,
parsed: refusal ? null : parseResponseFormatContent(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.response_format, parseableContent ? validateStructuredJSONSnapshot(content) : content)
});
}
if (refusal && !state2.refusal_done) {
state2.refusal_done = true;
this._emit("refusal.done", { refusal });
}
if (choiceSnapshot.logprobs?.content && !state2.logprobs_content_done) {
state2.logprobs_content_done = true;
this._emit("logprobs.content.done", { content: choiceSnapshot.logprobs.content });
}
if (choiceSnapshot.logprobs?.refusal && !state2.logprobs_refusal_done) {
state2.logprobs_refusal_done = true;
this._emit("logprobs.refusal.done", { refusal: choiceSnapshot.logprobs.refusal });
}
}, _ChatCompletionStream_validateStructuredSnapshots = function _ChatCompletionStream_validateStructuredSnapshots2(snapshot) {
const finalJSONBudget = { bytes: 0, fragments: 0, work: 0 };
const parseableContent = isParseableResponseFormat(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.response_format);
const validatedMessages = /* @__PURE__ */ new WeakMap();
const choices = captureSnapshotArray(snapshot, "choices", MAX_STREAM_CHOICES, "choice");
if (!choices) {
throw new OpenAIError("Chat completion stream contains an unsafe snapshot choice collection");
}
for (let choiceIndex = 0; choiceIndex < choices.length; choiceIndex += 1) {
const choice = captureSnapshotArrayItem(choices, choiceIndex);
if (!choice) {
continue;
}
const message = captureStructuredMessageSnapshot(choice);
const refusal = captureStructuredJSONSnapshot(message, "refusal");
const content = captureStructuredJSONSnapshot(message, "content");
const validatedTools = /* @__PURE__ */ new Map();
const toolCalls = captureSnapshotArray(message, "tool_calls", MAX_STREAM_TOOL_CALLS, "tool-call");
validatedMessages.set(choice, Object.freeze({
message,
content,
refusal,
toolCallCollection: toolCalls,
toolCalls: validatedTools
}));
const state2 = __classPrivateFieldGet(this, _ChatCompletionStream_choiceEventStates, "f")[choice.index];
if (parseableContent && !refusal && typeof content === "string") {
validateStructuredJSONSnapshot(content, finalJSONBudget, __classPrivateFieldGet(this, _ChatCompletionStream_partialJSONParseBudget, "f"));
}
for (const [index, identity] of state2?.tool_call_identities ?? []) {
const toolCall = toolCalls && captureSnapshotArrayItem(toolCalls, index);
if (!toolCall) {
throw new OpenAIError("Chat completion stream contains a changed tool call identity");
}
assertBoundToolCallIdentity(toolCall, identity);
}
if (!__classPrivateFieldGet(this, _ChatCompletionStream_hasAutoParseableTool, "f")) {
continue;
}
for (let toolCallIndex = 0; toolCallIndex < (toolCalls?.length ?? 0); toolCallIndex += 1) {
const toolCall = captureSnapshotArrayItem(toolCalls, toolCallIndex);
if (!toolCall) {
continue;
}
const identity = ownFunctionToolIdentity(toolCall);
if (!identity) {
const type = Object.getOwnPropertyDescriptor(toolCall, "type");
if (type && !("value" in type)) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
if (type?.value !== "function") {
continue;
}
const fn2 = Object.getOwnPropertyDescriptor(toolCall, "function");
if (fn2 && !("value" in fn2)) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
if (fn2 && typeof fn2.value === "object" && fn2.value !== null) {
const name = Object.getOwnPropertyDescriptor(fn2.value, "name");
if (name && !("value" in name)) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
}
continue;
}
if (!shouldParseToolCall(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f"), {
type: identity.type,
function: { name: identity.name }
})) {
continue;
}
const descriptor = Object.getOwnPropertyDescriptor(toolCall, "function");
if (!descriptor || !("value" in descriptor)) {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
const fn = descriptor.value;
const argumentsSnapshot = captureStructuredJSONSnapshot(fn, "arguments");
if (typeof argumentsSnapshot !== "string") {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
validateStructuredJSONSnapshot(argumentsSnapshot, finalJSONBudget, __classPrivateFieldGet(this, _ChatCompletionStream_partialJSONParseBudget, "f"));
validatedTools.set(toolCallIndex, Object.freeze({
tool: toolCall,
function: fn,
type: identity.type,
name: identity.name,
arguments: argumentsSnapshot
}));
}
}
return validatedMessages;
}, _ChatCompletionStream_endRequest = function _ChatCompletionStream_endRequest2() {
if (this.ended) {
throw new OpenAIError(`stream has ended, this shouldn't happen`);
}
const snapshot = __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f");
if (!snapshot) {
throw new OpenAIError(`request ended without sending any chunks`);
}
const validatedMessages = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_validateStructuredSnapshots).call(this, snapshot);
const audioDoneChoiceIndexes = __classPrivateFieldGet(this, _ChatCompletionStream_audioDoneChoiceIndexes, "f");
__classPrivateFieldSet(this, _ChatCompletionStream_audioDoneChoiceIndexes, /* @__PURE__ */ new Set(), "f");
__classPrivateFieldSet(this, _ChatCompletionStream_currentChatCompletionSnapshot, void 0, "f");
__classPrivateFieldSet(this, _ChatCompletionStream_choiceEventStates, [], "f");
return finalizeChatCompletion(snapshot, __classPrivateFieldGet(this, _ChatCompletionStream_params, "f"), audioDoneChoiceIndexes, validatedMessages);
}, _ChatCompletionStream_accumulateChatCompletion = function _ChatCompletionStream_accumulateChatCompletion2(chunk, capturedChoiceFrames) {
var _a5, _b, _c, _d, _e;
let snapshot = __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f");
const { choices, obfuscation: _obfuscation, ...rest } = chunk;
if (!snapshot) {
const newSnapshot = {
...rest,
choices: []
};
__classPrivateFieldSet(this, _ChatCompletionStream_currentChatCompletionSnapshot, newSnapshot, "f");
snapshot = newSnapshot;
} else if (chunk.id) {
assignOwnProperties(snapshot, rest);
}
const requestedChoiceCount = __classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.n;
const maxChoices = typeof requestedChoiceCount === "number" && Number.isSafeInteger(requestedChoiceCount) && requestedChoiceCount > 0 ? Math.min(requestedChoiceCount, MAX_STREAM_CHOICES) : MAX_STREAM_CHOICES;
for (const chunkChoice of chunk.choices) {
const { delta, finish_reason, index, logprobs = null, ...other } = chunkChoice;
const capturedToolCalls = [];
capturedChoiceFrames.set(chunkChoice, Object.freeze({ index, tool_calls: capturedToolCalls }));
if (!Number.isSafeInteger(index) || index < 0 || index >= maxChoices) {
throw new OpenAIError(`Chat completion stream contains an invalid choice index: ${index}`);
}
let choice = snapshot.choices[index];
if (!choice) {
const newChoice = { finish_reason, index, message: {}, logprobs: null, ...other };
snapshot.choices[index] = newChoice;
choice = newChoice;
}
if (isParseableResponseFormat(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.response_format) || __classPrivateFieldGet(this, _ChatCompletionStream_hasAutoParseableTool, "f")) {
captureStructuredJSONSnapshot(captureStructuredMessageSnapshot(choice), "refusal");
}
if (logprobs) {
if (choice.logprobs) {
const { content: content2, refusal: refusal2, ...rest3 } = logprobs;
assertIsEmpty(rest3);
assignOwnProperties(choice.logprobs, rest3);
if (content2) {
(_a5 = choice.logprobs).content ?? (_a5.content = []);
choice.logprobs.content.push(...content2);
}
if (refusal2) {
(_b = choice.logprobs).refusal ?? (_b.refusal = []);
choice.logprobs.refusal.push(...refusal2);
}
} else {
choice.logprobs = { ...logprobs };
if (logprobs.content) {
choice.logprobs.content = [...logprobs.content];
}
if (logprobs.refusal) {
choice.logprobs.refusal = [...logprobs.refusal];
}
}
}
if (finish_reason) {
choice.finish_reason = finish_reason;
if (__classPrivateFieldGet(this, _ChatCompletionStream_params, "f") && (__classPrivateFieldGet(this, _ChatCompletionStream_rejectsUnfinishedTurns, "f") || hasAutoParseableInput(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f")))) {
if (finish_reason === "length") {
throw new LengthFinishReasonError();
}
if (finish_reason === "content_filter") {
throw new ContentFilterFinishReasonError();
}
}
}
assignOwnProperties(choice, other);
if (!delta) {
Object.freeze(capturedToolCalls);
continue;
}
__classPrivateFieldGet(this, _ChatCompletionStream_audioDoneChoiceIndexes, "f").delete(index);
const { audio, content, refusal, function_call, role, ...capturedDeltaFields } = delta;
const { tool_calls: capturedToolCallDelta, ...rest2 } = capturedDeltaFields;
const tool_calls = hasOwn(capturedDeltaFields, "tool_calls") ? capturedToolCallDelta : delta.tool_calls;
assertIsEmpty(rest2);
assignOwnProperties(choice.message, rest2);
if (audio?.expires_at != null && audio.id == null && audio.data == null && audio.transcript == null && content == null && refusal == null && function_call == null && role == null && tool_calls == null && Object.keys(rest2).length === 0) {
__classPrivateFieldGet(this, _ChatCompletionStream_audioDoneChoiceIndexes, "f").add(index);
}
if (refusal) {
choice.message.refusal = (choice.message.refusal || "") + refusal;
}
if (role) {
choice.message.role = role;
}
if (audio) {
const audioSnapshot = (_c = choice.message).audio ?? (_c.audio = {});
if (audio.id != null) {
audioSnapshot.id = audio.id;
}
if (audio.data != null) {
audioSnapshot.data = (audioSnapshot.data ?? "") + audio.data;
}
if (audio.transcript != null) {
audioSnapshot.transcript = (audioSnapshot.transcript ?? "") + audio.transcript;
}
if (audio.expires_at != null) {
audioSnapshot.expires_at = audio.expires_at;
}
}
if (function_call) {
if (choice.message.function_call) {
if (function_call.name) {
choice.message.function_call.name = function_call.name;
}
if (function_call.arguments) {
(_d = choice.message.function_call).arguments ?? (_d.arguments = "");
choice.message.function_call.arguments += function_call.arguments;
}
} else {
choice.message.function_call = function_call;
}
}
if (content != null) {
if (!choice.message.refusal && isParseableResponseFormat(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.response_format)) {
const eventState = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choice);
const parseState = eventState.content_parse_state ?? (eventState.content_parse_state = createPartialJSONParseState());
const shouldParse = recordPartialJSONFragment(parseState, __classPrivateFieldGet(this, _ChatCompletionStream_partialJSONParseBudget, "f"), content);
choice.message.content = (captureStructuredJSONSnapshot(choice.message, "content") || "") + content;
if (!parseState.has_non_whitespace) {
choice.message.parsed = null;
} else if (shouldParse && reservePartialJSONParse(parseState, __classPrivateFieldGet(this, _ChatCompletionStream_partialJSONParseBudget, "f"))) {
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_validateStructuredSnapshots).call(this, snapshot);
choice.message.parsed = parseStructuredStreamingJSON(validateStructuredJSONSnapshot(choice.message.content));
} else if (content.length > 0) {
choice.message.parsed = null;
}
} else {
choice.message.content = (choice.message.content || "") + content;
}
}
if (tool_calls) {
const toolCallSnapshots = (_e = choice.message).tool_calls ?? (_e.tool_calls = []);
for (const toolCallDelta of tool_calls) {
const { index: index2, id, type, function: fn, custom, ...rest3 } = toolCallDelta;
if (!Number.isSafeInteger(index2) || index2 < 0 || index2 >= MAX_STREAM_TOOL_CALLS) {
throw new OpenAIError(`Chat completion stream contains an invalid tool call index: ${index2}`);
}
let argumentsDelta = "";
const tool_call = toolCallSnapshots[index2] ?? (toolCallSnapshots[index2] = {});
const functionName = fn?.name;
const eventState = __classPrivateFieldGet(this, _ChatCompletionStream_hasAutoParseableTool, "f") ? __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_getChoiceEventState).call(this, choice) : void 0;
let boundIdentity = eventState?.tool_call_identities.get(index2);
if (boundIdentity) {
assertBoundToolCallIdentity(tool_call, boundIdentity);
if (type !== void 0 && type !== boundIdentity.type || functionName !== void 0 && functionName !== boundIdentity.name) {
throw new OpenAIError("Chat completion stream contains a changed tool call identity");
}
}
assignOwnProperties(tool_call, rest3);
if (id) {
tool_call.id = id;
}
if (type) {
tool_call.type = type;
}
if (custom) {
const customSnapshot = tool_call.custom ?? (tool_call.custom = { name: custom.name ?? "", input: "" });
if (custom.name) {
customSnapshot.name = custom.name;
}
if (custom.input) {
customSnapshot.input += custom.input;
}
}
if (fn) {
const functionSnapshot = tool_call.function ?? (tool_call.function = { name: functionName ?? "", arguments: "" });
if (functionName) {
functionSnapshot.name = functionName;
}
if (eventState && !boundIdentity) {
const identity = ownFunctionToolIdentity(tool_call);
const configuredTool = identity && __classPrivateFieldGet(this, _ChatCompletionStream_params, "f")?.tools?.find((tool) => isChatCompletionFunctionTool(tool) && tool.function.name === identity.name);
if (identity) {
boundIdentity = {
...identity,
parseable: configuredTool !== void 0 && shouldParseToolCall(__classPrivateFieldGet(this, _ChatCompletionStream_params, "f"), {
type: identity.type,
function: { name: identity.name }
})
};
eventState.tool_call_identities.set(index2, boundIdentity);
if (!boundIdentity.parseable) {
const provisionalState = eventState.tool_call_parse_states.get(index2);
if (provisionalState) {
__classPrivateFieldGet(this, _ChatCompletionStream_partialJSONParseBudget, "f").bytes -= provisionalState.bytes;
__classPrivateFieldGet(this, _ChatCompletionStream_partialJSONParseBudget, "f").fragments -= provisionalState.fragments;
__classPrivateFieldGet(this, _ChatCompletionStream_partialJSONParseBudget, "f").work -= provisionalState.work;
eventState.tool_call_parse_states.delete(index2);
}
}
}
}
const argumentFragment = fn.arguments;
if (argumentFragment != null) {
argumentsDelta = argumentFragment;
if (eventState && boundIdentity?.parseable !== false) {
let parseState = eventState.tool_call_parse_states.get(index2);
if (!parseState) {
parseState = createPartialJSONParseState();
eventState.tool_call_parse_states.set(index2, parseState);
}
const shouldParse = recordPartialJSONFragment(parseState, __classPrivateFieldGet(this, _ChatCompletionStream_partialJSONParseBudget, "f"), argumentFragment);
const previousArguments = captureStructuredJSONSnapshot(functionSnapshot, "arguments");
if (typeof previousArguments !== "string") {
throw new OpenAIError("Chat completion stream contains an unsafe structured JSON snapshot");
}
functionSnapshot.arguments = previousArguments + argumentFragment;
if (shouldParse && boundIdentity?.parseable === true && reservePartialJSONParse(parseState, __classPrivateFieldGet(this, _ChatCompletionStream_partialJSONParseBudget, "f"))) {
__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_validateStructuredSnapshots).call(this, snapshot);
functionSnapshot.parsed_arguments = parseStructuredStreamingJSON(validateStructuredJSONSnapshot(functionSnapshot.arguments));
} else if (argumentFragment.length > 0 && hasOwn(functionSnapshot, "parsed_arguments")) {
functionSnapshot.parsed_arguments = void 0;
}
} else {
functionSnapshot.arguments += argumentFragment;
}
}
}
capturedToolCalls.push(Object.freeze({ index: index2, arguments_delta: argumentsDelta }));
}
}
Object.freeze(capturedToolCalls);
}
return snapshot;
}, Symbol.asyncIterator)]() {
return this._createIterator((push) => {
const onChunk = (chunk) => push(chunk);
this.on("chunk", onChunk);
return () => this.off("chunk", onChunk);
}, { onReturn: () => this.abort() });
}
/** Serializes raw completion chunks into a readable stream for transfer to another runtime. */
toReadableStream() {
const stream2 = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
return stream2.toReadableStream();
}
};
}
});
// node_modules/openai/lib/ChatCompletionStreamingRunner.mjs
var ChatCompletionStreamingRunner;
var init_ChatCompletionStreamingRunner = __esm({
"node_modules/openai/lib/ChatCompletionStreamingRunner.mjs"() {
init_ChatCompletionStream();
init_error2();
init_streaming2();
init_chatCompletionUtils();
ChatCompletionStreamingRunner = class _ChatCompletionStreamingRunner extends ChatCompletionStream {
/** Restores a serialized tool run, including intermediate completions and tool-result messages. */
static fromReadableStream(stream2) {
const runner = new _ChatCompletionStreamingRunner(null);
runner._run(() => runner._fromReadableStream(stream2));
return runner;
}
/** Serializes completion chunks and tool-result messages for replay in another runtime. */
toReadableStream() {
let lastChunk;
let toolCallIds;
const iterator = this._createIterator((push) => {
const onChunk = (chunk) => {
lastChunk = chunk;
push(chunk);
};
const onMessage = (message) => {
if (isAssistantMessage(message)) {
toolCallIds = message.tool_calls?.map((toolCall) => toolCall.id);
return;
}
if (isToolMessage(message)) {
if (!lastChunk) {
throw new OpenAIError("cannot serialize a tool message before receiving any chunks");
}
push(makeChatCompletionReadableStreamMessageChunk(lastChunk, message, toolCallIds));
toolCallIds = void 0;
}
};
this.on("chunk", onChunk);
this.on("message", onMessage);
return () => {
this.off("chunk", onChunk);
this.off("message", onMessage);
};
}, { onReturn: () => this.abort() });
const stream2 = new Stream(() => iterator, this.controller);
return stream2.toReadableStream();
}
/** Starts a streaming tool loop and returns its event-driven conversation runner. */
static runTools(client, params, options) {
const runner = new _ChatCompletionStreamingRunner(
// @ts-expect-error TODO these types are incompatible
params
);
const opts = {
...options,
__metadata: { ...options?.__metadata, helperMethod: "runTools" }
};
runner._run(() => runner._runTools(client, params, runner, opts));
return runner;
}
};
}
});
// node_modules/openai/resources/chat/completions/completions.mjs
var Completions;
var init_completions = __esm({
"node_modules/openai/resources/chat/completions/completions.mjs"() {
init_resource();
init_messages();
init_messages();
init_pagination();
init_path();
init_ChatCompletionRunner();
init_ChatCompletionStreamingRunner();
init_ChatCompletionStream();
init_parser();
init_ChatCompletionStreamingRunner();
init_RunnableFunction();
init_ChatCompletionStream();
init_ChatCompletionRunner();
Completions = class extends APIResource {
constructor() {
super(...arguments);
this.messages = new Messages(this._client);
}
create(body, options) {
return this._client.post("/chat/completions", {
body,
...options,
stream: body.stream ?? false,
__security: { bearerAuth: true }
});
}
/**
* Get a stored chat completion. Only Chat Completions that have been created with
* the `store` parameter set to `true` will be returned.
*
* @example
* ```ts
* const chatCompletion =
* await client.chat.completions.retrieve('completion_id');
* ```
*/
retrieve(completionID, options) {
return this._client.get(path`/chat/completions/${completionID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Modify a stored chat completion. Only Chat Completions that have been created
* with the `store` parameter set to `true` can be modified. Currently, the only
* supported modification is to update the `metadata` field.
*
* @example
* ```ts
* const chatCompletion = await client.chat.completions.update(
* 'completion_id',
* { metadata: { foo: 'string' } },
* );
* ```
*/
update(completionID, body, options) {
return this._client.post(path`/chat/completions/${completionID}`, {
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* List stored Chat Completions. Only Chat Completions that have been stored with
* the `store` parameter set to `true` will be returned.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const chatCompletion of client.chat.completions.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/chat/completions", CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Delete a stored chat completion. Only Chat Completions that have been created
* with the `store` parameter set to `true` can be deleted.
*
* @example
* ```ts
* const chatCompletionDeleted =
* await client.chat.completions.delete('completion_id');
* ```
*/
delete(completionID, options) {
return this._client.delete(path`/chat/completions/${completionID}`, {
...options,
__security: { bearerAuth: true }
});
}
parse(body, options) {
validateInputTools(body.tools);
return this._client.chat.completions.create(body, {
...options,
__metadata: { ...options?.__metadata, helperMethod: "chat.completions.parse" }
})._thenUnwrap((completion) => parseChatCompletion(completion, body));
}
runTools(body, options) {
if (body.stream) {
return ChatCompletionStreamingRunner.runTools(this._client, body, options);
}
return ChatCompletionRunner.runTools(this._client, body, options);
}
/**
* Creates a chat completion stream
*/
stream(body, options) {
return ChatCompletionStream.createChatCompletion(this._client, body, options);
}
};
Completions.Messages = Messages;
}
});
// node_modules/openai/resources/chat/chat.mjs
var Chat;
var init_chat = __esm({
"node_modules/openai/resources/chat/chat.mjs"() {
init_resource();
init_completions();
init_completions();
Chat = class extends APIResource {
constructor() {
super(...arguments);
this.completions = new Completions(this._client);
}
};
Chat.Completions = Completions;
}
});
// node_modules/openai/resources/chat/completions/index.mjs
var init_completions2 = __esm({
"node_modules/openai/resources/chat/completions/index.mjs"() {
init_completions();
init_completions();
init_messages();
}
});
// node_modules/openai/resources/chat/index.mjs
var init_chat2 = __esm({
"node_modules/openai/resources/chat/index.mjs"() {
init_chat();
init_completions2();
}
});
// node_modules/openai/resources/shared.mjs
var init_shared = __esm({
"node_modules/openai/resources/shared.mjs"() {
}
});
// node_modules/openai/resources/admin/organization/admin-api-keys.mjs
var AdminAPIKeys;
var init_admin_api_keys = __esm({
"node_modules/openai/resources/admin/organization/admin-api-keys.mjs"() {
init_resource();
init_pagination();
init_path();
AdminAPIKeys = class extends APIResource {
/**
* Create an organization admin API key
*
* @example
* ```ts
* const adminAPIKey =
* await client.admin.organization.adminAPIKeys.create({
* name: 'New Admin Key',
* });
* ```
*/
create(body, options) {
return this._client.post("/organization/admin_api_keys", {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieve a single organization API key
*
* @example
* ```ts
* const adminAPIKey =
* await client.admin.organization.adminAPIKeys.retrieve(
* 'key_id',
* );
* ```
*/
retrieve(keyID, options) {
return this._client.get(path`/organization/admin_api_keys/${keyID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* List organization API keys
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const adminAPIKey of client.admin.organization.adminAPIKeys.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/organization/admin_api_keys", CursorPage, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Delete an organization admin API key
*
* @example
* ```ts
* const adminAPIKey =
* await client.admin.organization.adminAPIKeys.delete(
* 'key_id',
* );
* ```
*/
delete(keyID, options) {
return this._client.delete(path`/organization/admin_api_keys/${keyID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/audit-logs.mjs
var AuditLogs;
var init_audit_logs = __esm({
"node_modules/openai/resources/admin/organization/audit-logs.mjs"() {
init_resource();
init_pagination();
AuditLogs = class extends APIResource {
/**
* List user actions and configuration changes within this organization.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const auditLogListResponse of client.admin.organization.auditLogs.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/organization/audit_logs", ConversationCursorPage, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/certificates.mjs
var Certificates;
var init_certificates = __esm({
"node_modules/openai/resources/admin/organization/certificates.mjs"() {
init_resource();
init_pagination();
init_path();
Certificates = class extends APIResource {
/**
* Upload a certificate to the organization. This does **not** automatically
* activate the certificate.
*
* Organizations can upload up to 50 certificates.
*
* @example
* ```ts
* const certificate =
* await client.admin.organization.certificates.create({
* certificate: 'certificate',
* });
* ```
*/
create(body, options) {
return this._client.post("/organization/certificates", {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get a certificate that has been uploaded to the organization.
*
* You can get a certificate regardless of whether it is active or not.
*
* @example
* ```ts
* const certificate =
* await client.admin.organization.certificates.retrieve(
* 'certificate_id',
* );
* ```
*/
retrieve(certificateID, query = {}, options) {
return this._client.get(path`/organization/certificates/${certificateID}`, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Modify a certificate. Note that only the name can be modified.
*
* @example
* ```ts
* const certificate =
* await client.admin.organization.certificates.update(
* 'certificate_id',
* );
* ```
*/
update(certificateID, body, options) {
return this._client.post(path`/organization/certificates/${certificateID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* List uploaded certificates for this organization.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const certificateListResponse of client.admin.organization.certificates.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/organization/certificates", ConversationCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Delete a certificate from the organization.
*
* The certificate must be inactive for the organization and all projects.
*
* @example
* ```ts
* const certificate =
* await client.admin.organization.certificates.delete(
* 'certificate_id',
* );
* ```
*/
delete(certificateID, options) {
return this._client.delete(path`/organization/certificates/${certificateID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Activate certificates at the organization level.
*
* You can atomically and idempotently activate up to 10 certificates at a time.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const certificateActivateResponse of client.admin.organization.certificates.activate(
* { certificate_ids: ['cert_abc'] },
* )) {
* // ...
* }
* ```
*/
activate(body, options) {
return this._client.getAPIList("/organization/certificates/activate", Page, {
body,
method: "post",
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Deactivate certificates at the organization level.
*
* You can atomically and idempotently deactivate up to 10 certificates at a time.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const certificateDeactivateResponse of client.admin.organization.certificates.deactivate(
* { certificate_ids: ['cert_abc'] },
* )) {
* // ...
* }
* ```
*/
deactivate(body, options) {
return this._client.getAPIList("/organization/certificates/deactivate", Page, { body, method: "post", ...options, __security: { adminAPIKeyAuth: true } });
}
};
}
});
// node_modules/openai/resources/admin/organization/data-retention.mjs
var DataRetention;
var init_data_retention = __esm({
"node_modules/openai/resources/admin/organization/data-retention.mjs"() {
init_resource();
DataRetention = class extends APIResource {
/**
* Retrieves organization data retention controls.
*
* @example
* ```ts
* const organizationDataRetention =
* await client.admin.organization.dataRetention.retrieve();
* ```
*/
retrieve(options) {
return this._client.get("/organization/data_retention", {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates organization data retention controls.
*
* @example
* ```ts
* const organizationDataRetention =
* await client.admin.organization.dataRetention.update({
* retention_type: 'zero_data_retention',
* });
* ```
*/
update(body, options) {
return this._client.post("/organization/data_retention", {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/invites.mjs
var Invites;
var init_invites = __esm({
"node_modules/openai/resources/admin/organization/invites.mjs"() {
init_resource();
init_pagination();
init_path();
Invites = class extends APIResource {
/**
* Create an invite for a user to the organization. The invite must be accepted by
* the user before they have access to the organization.
*
* @example
* ```ts
* const invite =
* await client.admin.organization.invites.create({
* email: 'email',
* role: 'reader',
* });
* ```
*/
create(body, options) {
return this._client.post("/organization/invites", {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves an invite.
*
* @example
* ```ts
* const invite =
* await client.admin.organization.invites.retrieve(
* 'invite_id',
* );
* ```
*/
retrieve(inviteID, options) {
return this._client.get(path`/organization/invites/${inviteID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Returns a list of invites in the organization.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const invite of client.admin.organization.invites.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/organization/invites", ConversationCursorPage, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Delete an invite. If the invite has already been accepted, it cannot be deleted.
*
* @example
* ```ts
* const invite =
* await client.admin.organization.invites.delete(
* 'invite_id',
* );
* ```
*/
delete(inviteID, options) {
return this._client.delete(path`/organization/invites/${inviteID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/roles.mjs
var Roles;
var init_roles = __esm({
"node_modules/openai/resources/admin/organization/roles.mjs"() {
init_resource();
init_pagination();
init_path();
Roles = class extends APIResource {
/**
* Creates a custom role for the organization.
*
* @example
* ```ts
* const role = await client.admin.organization.roles.create({
* permissions: ['string'],
* role_name: 'role_name',
* });
* ```
*/
create(body, options) {
return this._client.post("/organization/roles", {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves an organization role.
*
* @example
* ```ts
* const role = await client.admin.organization.roles.retrieve(
* 'role_id',
* );
* ```
*/
retrieve(roleID, options) {
return this._client.get(path`/organization/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates an existing organization role.
*
* @example
* ```ts
* const role = await client.admin.organization.roles.update(
* 'role_id',
* );
* ```
*/
update(roleID, body, options) {
return this._client.post(path`/organization/roles/${roleID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists the roles configured for the organization.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const role of client.admin.organization.roles.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/organization/roles", NextCursorPage, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Deletes a custom role from the organization.
*
* @example
* ```ts
* const role = await client.admin.organization.roles.delete(
* 'role_id',
* );
* ```
*/
delete(roleID, options) {
return this._client.delete(path`/organization/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/spend-alerts.mjs
var SpendAlerts;
var init_spend_alerts = __esm({
"node_modules/openai/resources/admin/organization/spend-alerts.mjs"() {
init_resource();
init_pagination();
init_path();
SpendAlerts = class extends APIResource {
/**
* Creates an organization spend alert.
*
* @example
* ```ts
* const organizationSpendAlert =
* await client.admin.organization.spendAlerts.create({
* currency: 'USD',
* interval: 'month',
* notification_channel: {
* recipients: ['string'],
* type: 'email',
* },
* threshold_amount: 0,
* });
* ```
*/
create(body, options) {
return this._client.post("/organization/spend_alerts", {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves an organization spend alert.
*
* @example
* ```ts
* const organizationSpendAlert =
* await client.admin.organization.spendAlerts.retrieve(
* 'alert_id',
* );
* ```
*/
retrieve(alertID, options) {
return this._client.get(path`/organization/spend_alerts/${alertID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates an organization spend alert.
*
* @example
* ```ts
* const organizationSpendAlert =
* await client.admin.organization.spendAlerts.update(
* 'alert_id',
* {
* currency: 'USD',
* interval: 'month',
* notification_channel: {
* recipients: ['string'],
* type: 'email',
* },
* threshold_amount: 0,
* },
* );
* ```
*/
update(alertID, body, options) {
return this._client.post(path`/organization/spend_alerts/${alertID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists organization spend alerts.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const organizationSpendAlert of client.admin.organization.spendAlerts.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/organization/spend_alerts", ConversationCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Deletes an organization spend alert.
*
* @example
* ```ts
* const organizationSpendAlertDeleted =
* await client.admin.organization.spendAlerts.delete(
* 'alert_id',
* );
* ```
*/
delete(alertID, options) {
return this._client.delete(path`/organization/spend_alerts/${alertID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/spend-limit.mjs
var SpendLimit;
var init_spend_limit = __esm({
"node_modules/openai/resources/admin/organization/spend-limit.mjs"() {
init_resource();
SpendLimit = class extends APIResource {
/**
* Get the organization's hard spend limit.
*
* @example
* ```ts
* const organizationSpendLimit =
* await client.admin.organization.spendLimit.retrieve();
* ```
*/
retrieve(options) {
return this._client.get("/organization/spend_limit", {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Create or replace the organization's hard spend limit.
*
* @example
* ```ts
* const organizationSpendLimit =
* await client.admin.organization.spendLimit.update({
* currency: 'USD',
* interval: 'month',
* threshold_amount: 1,
* });
* ```
*/
update(body, options) {
return this._client.post("/organization/spend_limit", {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Delete the organization's hard spend limit.
*
* @example
* ```ts
* const organizationSpendLimitDeleted =
* await client.admin.organization.spendLimit.delete();
* ```
*/
delete(options) {
return this._client.delete("/organization/spend_limit", {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/usage.mjs
var Usage;
var init_usage = __esm({
"node_modules/openai/resources/admin/organization/usage.mjs"() {
init_resource();
Usage = class extends APIResource {
/**
* Get audio speeches usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.audioSpeeches({
* start_time: 0,
* });
* ```
*/
audioSpeeches(query, options) {
return this._client.get("/organization/usage/audio_speeches", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get audio transcriptions usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.audioTranscriptions(
* { start_time: 0 },
* );
* ```
*/
audioTranscriptions(query, options) {
return this._client.get("/organization/usage/audio_transcriptions", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get code interpreter sessions usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.codeInterpreterSessions(
* { start_time: 0 },
* );
* ```
*/
codeInterpreterSessions(query, options) {
return this._client.get("/organization/usage/code_interpreter_sessions", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get completions usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.completions({
* start_time: 0,
* });
* ```
*/
completions(query, options) {
return this._client.get("/organization/usage/completions", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get costs details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.costs({
* start_time: 0,
* });
* ```
*/
costs(query, options) {
return this._client.get("/organization/costs", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get embeddings usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.embeddings({
* start_time: 0,
* });
* ```
*/
embeddings(query, options) {
return this._client.get("/organization/usage/embeddings", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get file search calls usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.fileSearchCalls({
* start_time: 0,
* });
* ```
*/
fileSearchCalls(query, options) {
return this._client.get("/organization/usage/file_search_calls", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get images usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.images({
* start_time: 0,
* });
* ```
*/
images(query, options) {
return this._client.get("/organization/usage/images", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get moderations usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.moderations({
* start_time: 0,
* });
* ```
*/
moderations(query, options) {
return this._client.get("/organization/usage/moderations", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get vector stores usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.vectorStores({
* start_time: 0,
* });
* ```
*/
vectorStores(query, options) {
return this._client.get("/organization/usage/vector_stores", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Get web search calls usage details for the organization.
*
* @example
* ```ts
* const response =
* await client.admin.organization.usage.webSearchCalls({
* start_time: 0,
* });
* ```
*/
webSearchCalls(query, options) {
return this._client.get("/organization/usage/web_search_calls", {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/groups/roles.mjs
var Roles2;
var init_roles2 = __esm({
"node_modules/openai/resources/admin/organization/groups/roles.mjs"() {
init_resource();
init_pagination();
init_path();
Roles2 = class extends APIResource {
/**
* Assigns an organization role to a group within the organization.
*
* @example
* ```ts
* const role =
* await client.admin.organization.groups.roles.create(
* 'group_id',
* { role_id: 'role_id' },
* );
* ```
*/
create(groupID, body, options) {
return this._client.post(path`/organization/groups/${groupID}/roles`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves an organization role assigned to a group.
*
* @example
* ```ts
* const role =
* await client.admin.organization.groups.roles.retrieve(
* 'role_id',
* { group_id: 'group_id' },
* );
* ```
*/
retrieve(roleID, params, options) {
const { group_id } = params;
return this._client.get(path`/organization/groups/${group_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists the organization roles assigned to a group within the organization.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const roleListResponse of client.admin.organization.groups.roles.list(
* 'group_id',
* )) {
* // ...
* }
* ```
*/
list(groupID, query = {}, options) {
return this._client.getAPIList(path`/organization/groups/${groupID}/roles`, NextCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Unassigns an organization role from a group within the organization.
*
* @example
* ```ts
* const role =
* await client.admin.organization.groups.roles.delete(
* 'role_id',
* { group_id: 'group_id' },
* );
* ```
*/
delete(roleID, params, options) {
const { group_id } = params;
return this._client.delete(path`/organization/groups/${group_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/groups/users.mjs
var Users;
var init_users = __esm({
"node_modules/openai/resources/admin/organization/groups/users.mjs"() {
init_resource();
init_pagination();
init_path();
Users = class extends APIResource {
/**
* Adds a user to a group.
*
* @example
* ```ts
* const user =
* await client.admin.organization.groups.users.create(
* 'group_id',
* { user_id: 'user_id' },
* );
* ```
*/
create(groupID, body, options) {
return this._client.post(path`/organization/groups/${groupID}/users`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a user in a group.
*
* @example
* ```ts
* const user =
* await client.admin.organization.groups.users.retrieve(
* 'user_id',
* { group_id: 'group_id' },
* );
* ```
*/
retrieve(userID, params, options) {
const { group_id } = params;
return this._client.get(path`/organization/groups/${group_id}/users/${userID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists the users assigned to a group.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const organizationGroupUser of client.admin.organization.groups.users.list(
* 'group_id',
* )) {
* // ...
* }
* ```
*/
list(groupID, query = {}, options) {
return this._client.getAPIList(path`/organization/groups/${groupID}/users`, NextCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Removes a user from a group.
*
* @example
* ```ts
* const user =
* await client.admin.organization.groups.users.delete(
* 'user_id',
* { group_id: 'group_id' },
* );
* ```
*/
delete(userID, params, options) {
const { group_id } = params;
return this._client.delete(path`/organization/groups/${group_id}/users/${userID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/groups/groups.mjs
var Groups;
var init_groups = __esm({
"node_modules/openai/resources/admin/organization/groups/groups.mjs"() {
init_resource();
init_roles2();
init_roles2();
init_users();
init_users();
init_pagination();
init_path();
Groups = class extends APIResource {
constructor() {
super(...arguments);
this.users = new Users(this._client);
this.roles = new Roles2(this._client);
}
/**
* Creates a new group in the organization.
*
* @example
* ```ts
* const group = await client.admin.organization.groups.create(
* { name: 'x' },
* );
* ```
*/
create(body, options) {
return this._client.post("/organization/groups", {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a group.
*
* @example
* ```ts
* const group =
* await client.admin.organization.groups.retrieve(
* 'group_id',
* );
* ```
*/
retrieve(groupID, options) {
return this._client.get(path`/organization/groups/${groupID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates a group's information.
*
* @example
* ```ts
* const group = await client.admin.organization.groups.update(
* 'group_id',
* { name: 'x' },
* );
* ```
*/
update(groupID, body, options) {
return this._client.post(path`/organization/groups/${groupID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists all groups in the organization.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const group of client.admin.organization.groups.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/organization/groups", NextCursorPage, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Deletes a group from the organization.
*
* @example
* ```ts
* const group = await client.admin.organization.groups.delete(
* 'group_id',
* );
* ```
*/
delete(groupID, options) {
return this._client.delete(path`/organization/groups/${groupID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
Groups.Users = Users;
Groups.Roles = Roles2;
}
});
// node_modules/openai/resources/admin/organization/projects/api-keys.mjs
var APIKeys;
var init_api_keys = __esm({
"node_modules/openai/resources/admin/organization/projects/api-keys.mjs"() {
init_resource();
init_pagination();
init_path();
APIKeys = class extends APIResource {
/**
* Retrieves an API key in the project.
*
* @example
* ```ts
* const projectAPIKey =
* await client.admin.organization.projects.apiKeys.retrieve(
* 'api_key_id',
* { project_id: 'project_id' },
* );
* ```
*/
retrieve(apiKeyID, params, options) {
const { project_id } = params;
return this._client.get(path`/organization/projects/${project_id}/api_keys/${apiKeyID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Returns a list of API keys in the project.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const projectAPIKey of client.admin.organization.projects.apiKeys.list(
* 'project_id',
* )) {
* // ...
* }
* ```
*/
list(projectID, query = {}, options) {
return this._client.getAPIList(path`/organization/projects/${projectID}/api_keys`, ConversationCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Deletes an API key from the project.
*
* Returns confirmation of the key deletion, or an error if the key belonged to a
* service account.
*
* @example
* ```ts
* const apiKey =
* await client.admin.organization.projects.apiKeys.delete(
* 'api_key_id',
* { project_id: 'project_id' },
* );
* ```
*/
delete(apiKeyID, params, options) {
const { project_id } = params;
return this._client.delete(path`/organization/projects/${project_id}/api_keys/${apiKeyID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/certificates.mjs
var Certificates2;
var init_certificates2 = __esm({
"node_modules/openai/resources/admin/organization/projects/certificates.mjs"() {
init_resource();
init_pagination();
init_path();
Certificates2 = class extends APIResource {
/**
* List certificates for this project.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const certificateListResponse of client.admin.organization.projects.certificates.list(
* 'project_id',
* )) {
* // ...
* }
* ```
*/
list(projectID, query = {}, options) {
return this._client.getAPIList(path`/organization/projects/${projectID}/certificates`, ConversationCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Activate certificates at the project level.
*
* You can atomically and idempotently activate up to 10 certificates at a time.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const certificateActivateResponse of client.admin.organization.projects.certificates.activate(
* 'project_id',
* { certificate_ids: ['cert_abc'] },
* )) {
* // ...
* }
* ```
*/
activate(projectID, body, options) {
return this._client.getAPIList(path`/organization/projects/${projectID}/certificates/activate`, Page, { body, method: "post", ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Deactivate certificates at the project level. You can atomically and
* idempotently deactivate up to 10 certificates at a time.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const certificateDeactivateResponse of client.admin.organization.projects.certificates.deactivate(
* 'project_id',
* { certificate_ids: ['cert_abc'] },
* )) {
* // ...
* }
* ```
*/
deactivate(projectID, body, options) {
return this._client.getAPIList(path`/organization/projects/${projectID}/certificates/deactivate`, Page, { body, method: "post", ...options, __security: { adminAPIKeyAuth: true } });
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/data-retention.mjs
var DataRetention2;
var init_data_retention2 = __esm({
"node_modules/openai/resources/admin/organization/projects/data-retention.mjs"() {
init_resource();
init_path();
DataRetention2 = class extends APIResource {
/**
* Retrieves project data retention controls.
*
* @example
* ```ts
* const projectDataRetention =
* await client.admin.organization.projects.dataRetention.retrieve(
* 'project_id',
* );
* ```
*/
retrieve(projectID, options) {
return this._client.get(path`/organization/projects/${projectID}/data_retention`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates project data retention controls.
*
* @example
* ```ts
* const projectDataRetention =
* await client.admin.organization.projects.dataRetention.update(
* 'project_id',
* { retention_type: 'organization_default' },
* );
* ```
*/
update(projectID, body, options) {
return this._client.post(path`/organization/projects/${projectID}/data_retention`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/hosted-tool-permissions.mjs
var HostedToolPermissions;
var init_hosted_tool_permissions = __esm({
"node_modules/openai/resources/admin/organization/projects/hosted-tool-permissions.mjs"() {
init_resource();
init_path();
HostedToolPermissions = class extends APIResource {
/**
* Returns hosted tool permissions for a project.
*
* @example
* ```ts
* const projectHostedToolPermissions =
* await client.admin.organization.projects.hostedToolPermissions.retrieve(
* 'project_id',
* );
* ```
*/
retrieve(projectID, options) {
return this._client.get(path`/organization/projects/${projectID}/hosted_tool_permissions`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates hosted tool permissions for a project.
*
* @example
* ```ts
* const projectHostedToolPermissions =
* await client.admin.organization.projects.hostedToolPermissions.update(
* 'project_id',
* );
* ```
*/
update(projectID, body, options) {
return this._client.post(path`/organization/projects/${projectID}/hosted_tool_permissions`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/model-permissions.mjs
var ModelPermissions;
var init_model_permissions = __esm({
"node_modules/openai/resources/admin/organization/projects/model-permissions.mjs"() {
init_resource();
init_path();
ModelPermissions = class extends APIResource {
/**
* Returns model permissions for a project.
*
* @example
* ```ts
* const projectModelPermissions =
* await client.admin.organization.projects.modelPermissions.retrieve(
* 'project_id',
* );
* ```
*/
retrieve(projectID, options) {
return this._client.get(path`/organization/projects/${projectID}/model_permissions`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates model permissions for a project.
*
* @example
* ```ts
* const projectModelPermissions =
* await client.admin.organization.projects.modelPermissions.update(
* 'project_id',
* { mode: 'allow_list', model_ids: ['string'] },
* );
* ```
*/
update(projectID, body, options) {
return this._client.post(path`/organization/projects/${projectID}/model_permissions`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Deletes model permissions for a project.
*
* @example
* ```ts
* const projectModelPermissionsDeleted =
* await client.admin.organization.projects.modelPermissions.delete(
* 'project_id',
* );
* ```
*/
delete(projectID, options) {
return this._client.delete(path`/organization/projects/${projectID}/model_permissions`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/rate-limits.mjs
var RateLimits;
var init_rate_limits = __esm({
"node_modules/openai/resources/admin/organization/projects/rate-limits.mjs"() {
init_resource();
init_pagination();
init_path();
RateLimits = class extends APIResource {
/**
* Returns the rate limits per model for a project.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const projectRateLimit of client.admin.organization.projects.rateLimits.listRateLimits(
* 'project_id',
* )) {
* // ...
* }
* ```
*/
listRateLimits(projectID, query = {}, options) {
return this._client.getAPIList(path`/organization/projects/${projectID}/rate_limits`, ConversationCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Updates a project rate limit.
*
* @example
* ```ts
* const projectRateLimit =
* await client.admin.organization.projects.rateLimits.updateRateLimit(
* 'rate_limit_id',
* { project_id: 'project_id' },
* );
* ```
*/
updateRateLimit(rateLimitID, params, options) {
const { project_id, ...body } = params;
return this._client.post(path`/organization/projects/${project_id}/rate_limits/${rateLimitID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/roles.mjs
var Roles3;
var init_roles3 = __esm({
"node_modules/openai/resources/admin/organization/projects/roles.mjs"() {
init_resource();
init_pagination();
init_path();
Roles3 = class extends APIResource {
/**
* Creates a custom role for a project.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.roles.create(
* 'project_id',
* { permissions: ['string'], role_name: 'role_name' },
* );
* ```
*/
create(projectID, body, options) {
return this._client.post(path`/projects/${projectID}/roles`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a project role.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.roles.retrieve(
* 'role_id',
* { project_id: 'project_id' },
* );
* ```
*/
retrieve(roleID, params, options) {
const { project_id } = params;
return this._client.get(path`/projects/${project_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates an existing project role.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.roles.update(
* 'role_id',
* { project_id: 'project_id' },
* );
* ```
*/
update(roleID, params, options) {
const { project_id, ...body } = params;
return this._client.post(path`/projects/${project_id}/roles/${roleID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists the roles configured for a project.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const role of client.admin.organization.projects.roles.list(
* 'project_id',
* )) {
* // ...
* }
* ```
*/
list(projectID, query = {}, options) {
return this._client.getAPIList(path`/projects/${projectID}/roles`, NextCursorPage, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Deletes a custom role from a project.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.roles.delete(
* 'role_id',
* { project_id: 'project_id' },
* );
* ```
*/
delete(roleID, params, options) {
const { project_id } = params;
return this._client.delete(path`/projects/${project_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/spend-alerts.mjs
var SpendAlerts2;
var init_spend_alerts2 = __esm({
"node_modules/openai/resources/admin/organization/projects/spend-alerts.mjs"() {
init_resource();
init_pagination();
init_path();
SpendAlerts2 = class extends APIResource {
/**
* Creates a project spend alert.
*
* @example
* ```ts
* const projectSpendAlert =
* await client.admin.organization.projects.spendAlerts.create(
* 'project_id',
* {
* currency: 'USD',
* interval: 'month',
* notification_channel: {
* recipients: ['string'],
* type: 'email',
* },
* threshold_amount: 0,
* },
* );
* ```
*/
create(projectID, body, options) {
return this._client.post(path`/organization/projects/${projectID}/spend_alerts`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a project spend alert.
*
* @example
* ```ts
* const projectSpendAlert =
* await client.admin.organization.projects.spendAlerts.retrieve(
* 'alert_id',
* { project_id: 'project_id' },
* );
* ```
*/
retrieve(alertID, params, options) {
const { project_id } = params;
return this._client.get(path`/organization/projects/${project_id}/spend_alerts/${alertID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates a project spend alert.
*
* @example
* ```ts
* const projectSpendAlert =
* await client.admin.organization.projects.spendAlerts.update(
* 'alert_id',
* {
* project_id: 'project_id',
* currency: 'USD',
* interval: 'month',
* notification_channel: {
* recipients: ['string'],
* type: 'email',
* },
* threshold_amount: 0,
* },
* );
* ```
*/
update(alertID, params, options) {
const { project_id, ...body } = params;
return this._client.post(path`/organization/projects/${project_id}/spend_alerts/${alertID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists project spend alerts.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const projectSpendAlert of client.admin.organization.projects.spendAlerts.list(
* 'project_id',
* )) {
* // ...
* }
* ```
*/
list(projectID, query = {}, options) {
return this._client.getAPIList(path`/organization/projects/${projectID}/spend_alerts`, ConversationCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Deletes a project spend alert.
*
* @example
* ```ts
* const projectSpendAlertDeleted =
* await client.admin.organization.projects.spendAlerts.delete(
* 'alert_id',
* { project_id: 'project_id' },
* );
* ```
*/
delete(alertID, params, options) {
const { project_id } = params;
return this._client.delete(path`/organization/projects/${project_id}/spend_alerts/${alertID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/spend-limit.mjs
var SpendLimit2;
var init_spend_limit2 = __esm({
"node_modules/openai/resources/admin/organization/projects/spend-limit.mjs"() {
init_resource();
init_path();
SpendLimit2 = class extends APIResource {
/**
* Get a project's hard spend limit.
*
* @example
* ```ts
* const projectSpendLimit =
* await client.admin.organization.projects.spendLimit.retrieve(
* 'proj_123',
* );
* ```
*/
retrieve(projectID, options) {
return this._client.get(path`/organization/projects/${projectID}/spend_limit`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Create or replace a project's hard spend limit.
*
* @example
* ```ts
* const projectSpendLimit =
* await client.admin.organization.projects.spendLimit.update(
* 'proj_123',
* {
* currency: 'USD',
* interval: 'month',
* threshold_amount: 1,
* },
* );
* ```
*/
update(projectID, body, options) {
return this._client.post(path`/organization/projects/${projectID}/spend_limit`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Delete a project's hard spend limit.
*
* @example
* ```ts
* const projectSpendLimitDeleted =
* await client.admin.organization.projects.spendLimit.delete(
* 'proj_123',
* );
* ```
*/
delete(projectID, options) {
return this._client.delete(path`/organization/projects/${projectID}/spend_limit`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/groups/roles.mjs
var Roles4;
var init_roles4 = __esm({
"node_modules/openai/resources/admin/organization/projects/groups/roles.mjs"() {
init_resource();
init_pagination();
init_path();
Roles4 = class extends APIResource {
/**
* Assigns a project role to a group within a project.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.groups.roles.create(
* 'group_id',
* { project_id: 'project_id', role_id: 'role_id' },
* );
* ```
*/
create(groupID, params, options) {
const { project_id, ...body } = params;
return this._client.post(path`/projects/${project_id}/groups/${groupID}/roles`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a project role assigned to a group.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.groups.roles.retrieve(
* 'role_id',
* { project_id: 'project_id', group_id: 'group_id' },
* );
* ```
*/
retrieve(roleID, params, options) {
const { project_id, group_id } = params;
return this._client.get(path`/projects/${project_id}/groups/${group_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists the project roles assigned to a group within a project.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const roleListResponse of client.admin.organization.projects.groups.roles.list(
* 'group_id',
* { project_id: 'project_id' },
* )) {
* // ...
* }
* ```
*/
list(groupID, params, options) {
const { project_id, ...query } = params;
return this._client.getAPIList(path`/projects/${project_id}/groups/${groupID}/roles`, NextCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Unassigns a project role from a group within a project.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.groups.roles.delete(
* 'role_id',
* { project_id: 'project_id', group_id: 'group_id' },
* );
* ```
*/
delete(roleID, params, options) {
const { project_id, group_id } = params;
return this._client.delete(path`/projects/${project_id}/groups/${group_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/groups/groups.mjs
var Groups2;
var init_groups2 = __esm({
"node_modules/openai/resources/admin/organization/projects/groups/groups.mjs"() {
init_resource();
init_roles4();
init_roles4();
init_pagination();
init_path();
Groups2 = class extends APIResource {
constructor() {
super(...arguments);
this.roles = new Roles4(this._client);
}
/**
* Grants a group access to a project.
*
* @example
* ```ts
* const projectGroup =
* await client.admin.organization.projects.groups.create(
* 'project_id',
* { group_id: 'group_id', role: 'role' },
* );
* ```
*/
create(projectID, body, options) {
return this._client.post(path`/organization/projects/${projectID}/groups`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a project's group.
*
* @example
* ```ts
* const projectGroup =
* await client.admin.organization.projects.groups.retrieve(
* 'group_id',
* { project_id: 'project_id' },
* );
* ```
*/
retrieve(groupID, params, options) {
const { project_id, ...query } = params;
return this._client.get(path`/organization/projects/${project_id}/groups/${groupID}`, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists the groups that have access to a project.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const projectGroup of client.admin.organization.projects.groups.list(
* 'project_id',
* )) {
* // ...
* }
* ```
*/
list(projectID, query = {}, options) {
return this._client.getAPIList(path`/organization/projects/${projectID}/groups`, NextCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Revokes a group's access to a project.
*
* @example
* ```ts
* const group =
* await client.admin.organization.projects.groups.delete(
* 'group_id',
* { project_id: 'project_id' },
* );
* ```
*/
delete(groupID, params, options) {
const { project_id } = params;
return this._client.delete(path`/organization/projects/${project_id}/groups/${groupID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
Groups2.Roles = Roles4;
}
});
// node_modules/openai/resources/admin/organization/projects/service-accounts/api-keys.mjs
var APIKeys2;
var init_api_keys2 = __esm({
"node_modules/openai/resources/admin/organization/projects/service-accounts/api-keys.mjs"() {
init_resource();
init_path();
APIKeys2 = class extends APIResource {
/**
* Creates an API key for a service account in the project.
*
* @example
* ```ts
* const apiKey =
* await client.admin.organization.projects.serviceAccounts.apiKeys.create(
* 'service_account_id',
* { project_id: 'project_id' },
* );
* ```
*/
create(serviceAccountID, params, options) {
const { project_id, ...body } = params;
return this._client.post(path`/organization/projects/${project_id}/service_accounts/${serviceAccountID}/api_keys`, { body, ...options, __security: { adminAPIKeyAuth: true } });
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/service-accounts/service-accounts.mjs
var ServiceAccounts;
var init_service_accounts = __esm({
"node_modules/openai/resources/admin/organization/projects/service-accounts/service-accounts.mjs"() {
init_resource();
init_api_keys2();
init_api_keys2();
init_pagination();
init_path();
ServiceAccounts = class extends APIResource {
constructor() {
super(...arguments);
this.apiKeys = new APIKeys2(this._client);
}
/**
* Creates a new service account in the project. By default, this also returns an
* unredacted API key for the service account.
*
* @example
* ```ts
* const serviceAccount =
* await client.admin.organization.projects.serviceAccounts.create(
* 'project_id',
* { name: 'name' },
* );
* ```
*/
create(projectID, body, options) {
return this._client.post(path`/organization/projects/${projectID}/service_accounts`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a service account in the project.
*
* @example
* ```ts
* const projectServiceAccount =
* await client.admin.organization.projects.serviceAccounts.retrieve(
* 'service_account_id',
* { project_id: 'project_id' },
* );
* ```
*/
retrieve(serviceAccountID, params, options) {
const { project_id } = params;
return this._client.get(path`/organization/projects/${project_id}/service_accounts/${serviceAccountID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Updates a service account in the project.
*
* @example
* ```ts
* const projectServiceAccount =
* await client.admin.organization.projects.serviceAccounts.update(
* 'service_account_id',
* { project_id: 'project_id' },
* );
* ```
*/
update(serviceAccountID, params, options) {
const { project_id, ...body } = params;
return this._client.post(path`/organization/projects/${project_id}/service_accounts/${serviceAccountID}`, { body, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Returns a list of service accounts in the project.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const projectServiceAccount of client.admin.organization.projects.serviceAccounts.list(
* 'project_id',
* )) {
* // ...
* }
* ```
*/
list(projectID, query = {}, options) {
return this._client.getAPIList(path`/organization/projects/${projectID}/service_accounts`, ConversationCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Deletes a service account from the project.
*
* Returns confirmation of service account deletion, or an error if the project is
* archived (archived projects have no service accounts).
*
* @example
* ```ts
* const serviceAccount =
* await client.admin.organization.projects.serviceAccounts.delete(
* 'service_account_id',
* { project_id: 'project_id' },
* );
* ```
*/
delete(serviceAccountID, params, options) {
const { project_id } = params;
return this._client.delete(path`/organization/projects/${project_id}/service_accounts/${serviceAccountID}`, { ...options, __security: { adminAPIKeyAuth: true } });
}
};
ServiceAccounts.APIKeys = APIKeys2;
}
});
// node_modules/openai/resources/admin/organization/projects/users/roles.mjs
var Roles5;
var init_roles5 = __esm({
"node_modules/openai/resources/admin/organization/projects/users/roles.mjs"() {
init_resource();
init_pagination();
init_path();
Roles5 = class extends APIResource {
/**
* Assigns a project role to a user within a project.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.users.roles.create(
* 'user_id',
* { project_id: 'project_id', role_id: 'role_id' },
* );
* ```
*/
create(userID, params, options) {
const { project_id, ...body } = params;
return this._client.post(path`/projects/${project_id}/users/${userID}/roles`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a project role assigned to a user.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.users.roles.retrieve(
* 'role_id',
* { project_id: 'project_id', user_id: 'user_id' },
* );
* ```
*/
retrieve(roleID, params, options) {
const { project_id, user_id } = params;
return this._client.get(path`/projects/${project_id}/users/${user_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists the project roles assigned to a user within a project.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const roleListResponse of client.admin.organization.projects.users.roles.list(
* 'user_id',
* { project_id: 'project_id' },
* )) {
* // ...
* }
* ```
*/
list(userID, params, options) {
const { project_id, ...query } = params;
return this._client.getAPIList(path`/projects/${project_id}/users/${userID}/roles`, NextCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Unassigns a project role from a user within a project.
*
* @example
* ```ts
* const role =
* await client.admin.organization.projects.users.roles.delete(
* 'role_id',
* { project_id: 'project_id', user_id: 'user_id' },
* );
* ```
*/
delete(roleID, params, options) {
const { project_id, user_id } = params;
return this._client.delete(path`/projects/${project_id}/users/${user_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/projects/users/users.mjs
var Users2;
var init_users2 = __esm({
"node_modules/openai/resources/admin/organization/projects/users/users.mjs"() {
init_resource();
init_roles5();
init_roles5();
init_pagination();
init_path();
Users2 = class extends APIResource {
constructor() {
super(...arguments);
this.roles = new Roles5(this._client);
}
/**
* Adds a user to the project. Users must already be members of the organization to
* be added to a project.
*
* @example
* ```ts
* const projectUser =
* await client.admin.organization.projects.users.create(
* 'project_id',
* { role: 'role' },
* );
* ```
*/
create(projectID, body, options) {
return this._client.post(path`/organization/projects/${projectID}/users`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a user in the project.
*
* @example
* ```ts
* const projectUser =
* await client.admin.organization.projects.users.retrieve(
* 'user_id',
* { project_id: 'project_id' },
* );
* ```
*/
retrieve(userID, params, options) {
const { project_id } = params;
return this._client.get(path`/organization/projects/${project_id}/users/${userID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Modifies a user's role in the project.
*
* @example
* ```ts
* const projectUser =
* await client.admin.organization.projects.users.update(
* 'user_id',
* { project_id: 'project_id' },
* );
* ```
*/
update(userID, params, options) {
const { project_id, ...body } = params;
return this._client.post(path`/organization/projects/${project_id}/users/${userID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Returns a list of users in the project.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const projectUser of client.admin.organization.projects.users.list(
* 'project_id',
* )) {
* // ...
* }
* ```
*/
list(projectID, query = {}, options) {
return this._client.getAPIList(path`/organization/projects/${projectID}/users`, ConversationCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Deletes a user from the project.
*
* Returns confirmation of project user deletion, or an error if the project is
* archived (archived projects have no users).
*
* @example
* ```ts
* const user =
* await client.admin.organization.projects.users.delete(
* 'user_id',
* { project_id: 'project_id' },
* );
* ```
*/
delete(userID, params, options) {
const { project_id } = params;
return this._client.delete(path`/organization/projects/${project_id}/users/${userID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
Users2.Roles = Roles5;
}
});
// node_modules/openai/resources/admin/organization/projects/projects.mjs
var Projects;
var init_projects = __esm({
"node_modules/openai/resources/admin/organization/projects/projects.mjs"() {
init_resource();
init_api_keys();
init_api_keys();
init_certificates2();
init_certificates2();
init_data_retention2();
init_data_retention2();
init_hosted_tool_permissions();
init_hosted_tool_permissions();
init_model_permissions();
init_model_permissions();
init_rate_limits();
init_rate_limits();
init_roles3();
init_roles3();
init_spend_alerts2();
init_spend_alerts2();
init_spend_limit2();
init_spend_limit2();
init_groups2();
init_groups2();
init_service_accounts();
init_service_accounts();
init_users2();
init_users2();
init_pagination();
init_path();
Projects = class extends APIResource {
constructor() {
super(...arguments);
this.users = new Users2(this._client);
this.serviceAccounts = new ServiceAccounts(this._client);
this.apiKeys = new APIKeys(this._client);
this.rateLimits = new RateLimits(this._client);
this.modelPermissions = new ModelPermissions(this._client);
this.hostedToolPermissions = new HostedToolPermissions(this._client);
this.groups = new Groups2(this._client);
this.roles = new Roles3(this._client);
this.dataRetention = new DataRetention2(this._client);
this.spendLimit = new SpendLimit2(this._client);
this.spendAlerts = new SpendAlerts2(this._client);
this.certificates = new Certificates2(this._client);
}
/**
* Create a new project in the organization. Projects can be created and archived,
* but cannot be deleted.
*
* @example
* ```ts
* const project =
* await client.admin.organization.projects.create({
* name: 'name',
* });
* ```
*/
create(body, options) {
return this._client.post("/organization/projects", {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves a project.
*
* @example
* ```ts
* const project =
* await client.admin.organization.projects.retrieve(
* 'project_id',
* );
* ```
*/
retrieve(projectID, options) {
return this._client.get(path`/organization/projects/${projectID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Modifies a project in the organization.
*
* @example
* ```ts
* const project =
* await client.admin.organization.projects.update(
* 'project_id',
* );
* ```
*/
update(projectID, body, options) {
return this._client.post(path`/organization/projects/${projectID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Returns a list of projects.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const project of client.admin.organization.projects.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/organization/projects", ConversationCursorPage, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Archives a project in the organization. Archived projects cannot be used or
* updated.
*
* @example
* ```ts
* const project =
* await client.admin.organization.projects.archive(
* 'project_id',
* );
* ```
*/
archive(projectID, options) {
return this._client.post(path`/organization/projects/${projectID}/archive`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
Projects.Users = Users2;
Projects.ServiceAccounts = ServiceAccounts;
Projects.APIKeys = APIKeys;
Projects.RateLimits = RateLimits;
Projects.ModelPermissions = ModelPermissions;
Projects.HostedToolPermissions = HostedToolPermissions;
Projects.Groups = Groups2;
Projects.Roles = Roles3;
Projects.DataRetention = DataRetention2;
Projects.SpendLimit = SpendLimit2;
Projects.SpendAlerts = SpendAlerts2;
Projects.Certificates = Certificates2;
}
});
// node_modules/openai/resources/admin/organization/users/roles.mjs
var Roles6;
var init_roles6 = __esm({
"node_modules/openai/resources/admin/organization/users/roles.mjs"() {
init_resource();
init_pagination();
init_path();
Roles6 = class extends APIResource {
/**
* Assigns an organization role to a user within the organization.
*
* @example
* ```ts
* const role =
* await client.admin.organization.users.roles.create(
* 'user_id',
* { role_id: 'role_id' },
* );
* ```
*/
create(userID, body, options) {
return this._client.post(path`/organization/users/${userID}/roles`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Retrieves an organization role assigned to a user.
*
* @example
* ```ts
* const role =
* await client.admin.organization.users.roles.retrieve(
* 'role_id',
* { user_id: 'user_id' },
* );
* ```
*/
retrieve(roleID, params, options) {
const { user_id } = params;
return this._client.get(path`/organization/users/${user_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists the organization roles assigned to a user within the organization.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const roleListResponse of client.admin.organization.users.roles.list(
* 'user_id',
* )) {
* // ...
* }
* ```
*/
list(userID, query = {}, options) {
return this._client.getAPIList(path`/organization/users/${userID}/roles`, NextCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* Unassigns an organization role from a user within the organization.
*
* @example
* ```ts
* const role =
* await client.admin.organization.users.roles.delete(
* 'role_id',
* { user_id: 'user_id' },
* );
* ```
*/
delete(roleID, params, options) {
const { user_id } = params;
return this._client.delete(path`/organization/users/${user_id}/roles/${roleID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
}
});
// node_modules/openai/resources/admin/organization/users/users.mjs
var Users3;
var init_users3 = __esm({
"node_modules/openai/resources/admin/organization/users/users.mjs"() {
init_resource();
init_roles6();
init_roles6();
init_pagination();
init_path();
Users3 = class extends APIResource {
constructor() {
super(...arguments);
this.roles = new Roles6(this._client);
}
/**
* Retrieves a user by their identifier.
*
* @example
* ```ts
* const organizationUser =
* await client.admin.organization.users.retrieve('user_id');
* ```
*/
retrieve(userID, options) {
return this._client.get(path`/organization/users/${userID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Modifies a user's role in the organization.
*
* @example
* ```ts
* const organizationUser =
* await client.admin.organization.users.update('user_id');
* ```
*/
update(userID, body, options) {
return this._client.post(path`/organization/users/${userID}`, {
body,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Lists all of the users in the organization.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const organizationUser of client.admin.organization.users.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/organization/users", ConversationCursorPage, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* Deletes a user from the organization.
*
* @example
* ```ts
* const user = await client.admin.organization.users.delete(
* 'user_id',
* );
* ```
*/
delete(userID, options) {
return this._client.delete(path`/organization/users/${userID}`, {
...options,
__security: { adminAPIKeyAuth: true }
});
}
};
Users3.Roles = Roles6;
}
});
// node_modules/openai/resources/admin/organization/organization.mjs
var Organization;
var init_organization = __esm({
"node_modules/openai/resources/admin/organization/organization.mjs"() {
init_resource();
init_admin_api_keys();
init_admin_api_keys();
init_audit_logs();
init_audit_logs();
init_certificates();
init_certificates();
init_data_retention();
init_data_retention();
init_invites();
init_invites();
init_roles();
init_roles();
init_spend_alerts();
init_spend_alerts();
init_spend_limit();
init_spend_limit();
init_usage();
init_usage();
init_groups();
init_groups();
init_projects();
init_projects();
init_users3();
init_users3();
Organization = class extends APIResource {
constructor() {
super(...arguments);
this.auditLogs = new AuditLogs(this._client);
this.adminAPIKeys = new AdminAPIKeys(this._client);
this.usage = new Usage(this._client);
this.invites = new Invites(this._client);
this.users = new Users3(this._client);
this.groups = new Groups(this._client);
this.roles = new Roles(this._client);
this.dataRetention = new DataRetention(this._client);
this.spendLimit = new SpendLimit(this._client);
this.spendAlerts = new SpendAlerts(this._client);
this.certificates = new Certificates(this._client);
this.projects = new Projects(this._client);
}
};
Organization.AuditLogs = AuditLogs;
Organization.AdminAPIKeys = AdminAPIKeys;
Organization.Usage = Usage;
Organization.Invites = Invites;
Organization.Users = Users3;
Organization.Groups = Groups;
Organization.Roles = Roles;
Organization.DataRetention = DataRetention;
Organization.SpendLimit = SpendLimit;
Organization.SpendAlerts = SpendAlerts;
Organization.Certificates = Certificates;
Organization.Projects = Projects;
}
});
// node_modules/openai/resources/admin/admin.mjs
var Admin;
var init_admin = __esm({
"node_modules/openai/resources/admin/admin.mjs"() {
init_resource();
init_organization();
init_organization();
Admin = class extends APIResource {
constructor() {
super(...arguments);
this.organization = new Organization(this._client);
}
};
Admin.Organization = Organization;
}
});
// node_modules/openai/resources/audio/speech.mjs
var Speech;
var init_speech = __esm({
"node_modules/openai/resources/audio/speech.mjs"() {
init_resource();
init_headers2();
Speech = class extends APIResource {
/**
* Generates audio from the input text.
*
* Returns the audio file content, or a stream of audio events.
*
* @example
* ```ts
* const speech = await client.audio.speech.create({
* input: 'input',
* model: 'tts-1',
* voice: 'alloy',
* });
*
* const content = await speech.blob();
* console.log(content);
* ```
*/
create(body, options) {
return this._client.post("/audio/speech", {
body,
...options,
headers: buildHeaders([{ Accept: "application/octet-stream" }, options?.headers]),
__security: { bearerAuth: true },
__binaryResponse: true
});
}
};
}
});
// node_modules/openai/resources/audio/transcriptions.mjs
var Transcriptions;
var init_transcriptions = __esm({
"node_modules/openai/resources/audio/transcriptions.mjs"() {
init_resource();
init_uploads();
Transcriptions = class extends APIResource {
create(body, options) {
return this._client.post("/audio/transcriptions", multipartFormRequestOptions({
body,
...options,
stream: body.stream ?? false,
__metadata: { model: body.model },
__security: { bearerAuth: true }
}, this._client));
}
};
}
});
// node_modules/openai/resources/audio/translations.mjs
var Translations;
var init_translations = __esm({
"node_modules/openai/resources/audio/translations.mjs"() {
init_resource();
init_uploads();
Translations = class extends APIResource {
create(body, options) {
return this._client.post("/audio/translations", multipartFormRequestOptions({ body, ...options, __metadata: { model: body.model }, __security: { bearerAuth: true } }, this._client));
}
};
}
});
// node_modules/openai/resources/audio/audio.mjs
var Audio;
var init_audio = __esm({
"node_modules/openai/resources/audio/audio.mjs"() {
init_resource();
init_speech();
init_speech();
init_transcriptions();
init_transcriptions();
init_translations();
init_translations();
Audio = class extends APIResource {
constructor() {
super(...arguments);
this.transcriptions = new Transcriptions(this._client);
this.translations = new Translations(this._client);
this.speech = new Speech(this._client);
}
};
Audio.Transcriptions = Transcriptions;
Audio.Translations = Translations;
Audio.Speech = Speech;
}
});
// node_modules/openai/resources/batches.mjs
var Batches;
var init_batches = __esm({
"node_modules/openai/resources/batches.mjs"() {
init_resource();
init_pagination();
init_path();
Batches = class extends APIResource {
/**
* Creates and executes a batch from an uploaded file of requests
*/
create(body, options) {
return this._client.post("/batches", { body, ...options, __security: { bearerAuth: true } });
}
/**
* Retrieves a batch.
*/
retrieve(batchID, options) {
return this._client.get(path`/batches/${batchID}`, { ...options, __security: { bearerAuth: true } });
}
/**
* List your organization's batches.
*/
list(query = {}, options) {
return this._client.getAPIList("/batches", CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Cancels an in-progress batch. The batch will be in status `cancelling` for up to
* 10 minutes, before changing to `cancelled`, where it will have partial results
* (if any) available in the output file.
*/
cancel(batchID, options) {
return this._client.post(path`/batches/${batchID}/cancel`, {
...options,
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/assistants.mjs
var Assistants;
var init_assistants = __esm({
"node_modules/openai/resources/beta/assistants.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Assistants = class extends APIResource {
/**
* Create an assistant with a model and instructions.
*
* @deprecated
*/
create(body, options) {
return this._client.post("/assistants", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieves an assistant.
*
* @deprecated
*/
retrieve(assistantID, options) {
return this._client.get(path`/assistants/${assistantID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Modifies an assistant.
*
* @deprecated
*/
update(assistantID, body, options) {
return this._client.post(path`/assistants/${assistantID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Returns a list of assistants.
*
* @deprecated
*/
list(query = {}, options) {
return this._client.getAPIList("/assistants", CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Delete an assistant.
*
* @deprecated
*/
delete(assistantID, options) {
return this._client.delete(path`/assistants/${assistantID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/realtime/sessions.mjs
var Sessions;
var init_sessions = __esm({
"node_modules/openai/resources/beta/realtime/sessions.mjs"() {
init_resource();
init_headers2();
Sessions = class extends APIResource {
/**
* Create an ephemeral API token for use in client-side applications with the
* Realtime API. Can be configured with the same session parameters as the
* `session.update` client event.
*
* It responds with a session object, plus a `client_secret` key which contains a
* usable ephemeral API token that can be used to authenticate browser clients for
* the Realtime API.
*
* @example
* ```ts
* const session =
* await client.beta.realtime.sessions.create();
* ```
*/
create(body, options) {
return this._client.post("/realtime/sessions", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/realtime/transcription-sessions.mjs
var TranscriptionSessions;
var init_transcription_sessions = __esm({
"node_modules/openai/resources/beta/realtime/transcription-sessions.mjs"() {
init_resource();
init_headers2();
TranscriptionSessions = class extends APIResource {
/**
* Create an ephemeral API token for use in client-side applications with the
* Realtime API specifically for realtime transcriptions. Can be configured with
* the same session parameters as the `transcription_session.update` client event.
*
* It responds with a session object, plus a `client_secret` key which contains a
* usable ephemeral API token that can be used to authenticate browser clients for
* the Realtime API.
*
* @example
* ```ts
* const transcriptionSession =
* await client.beta.realtime.transcriptionSessions.create();
* ```
*/
create(body, options) {
return this._client.post("/realtime/transcription_sessions", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/realtime/realtime.mjs
var Realtime;
var init_realtime = __esm({
"node_modules/openai/resources/beta/realtime/realtime.mjs"() {
init_resource();
init_sessions();
init_sessions();
init_transcription_sessions();
init_transcription_sessions();
Realtime = class extends APIResource {
constructor() {
super(...arguments);
this.sessions = new Sessions(this._client);
this.transcriptionSessions = new TranscriptionSessions(this._client);
}
};
Realtime.Sessions = Sessions;
Realtime.TranscriptionSessions = TranscriptionSessions;
}
});
// node_modules/openai/resources/beta/agents/environments/files.mjs
var Files;
var init_files = __esm({
"node_modules/openai/resources/beta/agents/environments/files.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Files = class extends APIResource {
/**
* Copies inline bytes or a Files API file into a connected execution environment.
* See
* [environment files](https://developers.openai.com/api/docs/guides/agents-api/environments/files).
*
* @example
* ```ts
* const environmentFile =
* await client.beta.agents.environments.files.create(
* 'environment_id',
* {
* type: 'inline',
* path: '/workspace/example.txt',
* data: 'SGVsbG8K',
* },
* );
* ```
*/
create(environmentID, body, options) {
return this._client.post(path`/agents/environments/${environmentID}/files`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists live files on a connected execution environment with optional directory
* filtering and opaque cursor pagination. See
* [environment files](https://developers.openai.com/api/docs/guides/agents-api/environments/files).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const environmentFile of client.beta.agents.environments.files.list(
* 'environment_id',
* )) {
* // ...
* }
* ```
*/
list(environmentID, query = {}, options) {
return this._client.getAPIList(path`/agents/environments/${environmentID}/files`, TokenPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/agents/environments/templates.mjs
var Templates;
var init_templates = __esm({
"node_modules/openai/resources/beta/agents/environments/templates.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Templates = class extends APIResource {
/**
* Creates reusable environment configuration without returning confidential setup
* commands or environment values. See
* [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup).
*
* @example
* ```ts
* const environmentTemplate =
* await client.beta.agents.environments.templates.create();
* ```
*/
create(body = {}, options) {
return this._client.post("/agents/environments/templates", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieves reusable environment configuration without returning confidential
* values. See
* [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup).
*
* @example
* ```ts
* const environmentTemplate =
* await client.beta.agents.environments.templates.retrieve(
* 'environment_template_id',
* );
* ```
*/
retrieve(environmentTemplateID, options) {
return this._client.get(path`/agents/environments/templates/${environmentTemplateID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Updates reusable environment configuration without returning confidential
* values. See
* [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup).
*
* @example
* ```ts
* const environmentTemplate =
* await client.beta.agents.environments.templates.update(
* 'environment_template_id',
* );
* ```
*/
update(environmentTemplateID, body = {}, options) {
return this._client.post(path`/agents/environments/templates/${environmentTemplateID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists reusable environment templates without returning confidential values. See
* [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const environmentTemplate of client.beta.agents.environments.templates.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/agents/environments/templates", CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Deletes reusable environment configuration and all confidential template inputs.
* See
* [reusing a hosted setup](https://developers.openai.com/api/docs/guides/agents-api/tools#reuse-a-hosted-plugin-setup).
*
* @example
* ```ts
* const environmentTemplateDeleted =
* await client.beta.agents.environments.templates.delete(
* 'environment_template_id',
* );
* ```
*/
delete(environmentTemplateID, options) {
return this._client.delete(path`/agents/environments/templates/${environmentTemplateID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/agents/environments/environments.mjs
var Environments;
var init_environments = __esm({
"node_modules/openai/resources/beta/agents/environments/environments.mjs"() {
init_resource();
init_files();
init_files();
init_templates();
init_templates();
init_headers2();
init_path();
Environments = class extends APIResource {
constructor() {
super(...arguments);
this.files = new Files(this._client);
this.templates = new Templates(this._client);
}
/**
* Retrieves an execution environment's connection status and safe installed
* metadata. See
* [environment lifecycle](https://developers.openai.com/api/docs/guides/agents-api/environments/lifecycle).
*
* @example
* ```ts
* const environmentInfo =
* await client.beta.agents.environments.retrieve(
* 'environment_id',
* );
* ```
*/
retrieve(environmentID, options) {
return this._client.get(path`/agents/environments/${environmentID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
Environments.Files = Files;
Environments.Templates = Templates;
}
});
// node_modules/openai/lib/agents/turn-state.mjs
var _TurnState_turnID, _TurnState_turnEnded, _TurnState_eventIDs, _TurnState_calls, TurnState;
var init_turn_state = __esm({
"node_modules/openai/lib/agents/turn-state.mjs"() {
init_tslib();
TurnState = class {
constructor() {
_TurnState_turnID.set(this, void 0);
_TurnState_turnEnded.set(this, false);
_TurnState_eventIDs.set(this, /* @__PURE__ */ new Set());
_TurnState_calls.set(this, /* @__PURE__ */ new Set());
}
/** Records a delivery unless its event ID is in the bounded recent window. */
accept(event) {
if (__classPrivateFieldGet(this, _TurnState_eventIDs, "f").has(event.event_id)) {
return false;
}
if (__classPrivateFieldGet(this, _TurnState_eventIDs, "f").size === 1024) {
const oldest = __classPrivateFieldGet(this, _TurnState_eventIDs, "f").values().next();
if (!oldest.done) {
__classPrivateFieldGet(this, _TurnState_eventIDs, "f").delete(oldest.value);
}
}
__classPrivateFieldGet(this, _TurnState_eventIDs, "f").add(event.event_id);
if (event.type === "agent.session.turn.created" && event.turn.subagent_id === null && __classPrivateFieldGet(this, _TurnState_turnID, "f") === void 0) {
__classPrivateFieldSet(this, _TurnState_turnID, event.turn_id, "f");
}
if ((event.type === "agent.session.turn.completed" || event.type === "agent.session.turn.failed" || event.type === "agent.session.turn.cancelled") && __classPrivateFieldGet(this, _TurnState_turnID, "f") !== void 0 && event.turn_id === __classPrivateFieldGet(this, _TurnState_turnID, "f")) {
__classPrivateFieldSet(this, _TurnState_turnEnded, true, "f");
}
return true;
}
/** Checks session termination after updating the selected turn state. */
terminal(event) {
return event.type === "agent.session.failed" || event.type === "agent.session.idle" && __classPrivateFieldGet(this, _TurnState_turnEnded, "f");
}
/** Returns each tool call once for the full invocation, including subagent turns. */
call(event) {
if (event.type !== "agent.session.turn.item.added" || event.item.type !== "function_call") {
return;
}
const call = event.item;
const key = JSON.stringify([call.turn_id, call.call_id]);
if (__classPrivateFieldGet(this, _TurnState_calls, "f").has(key)) {
return;
}
__classPrivateFieldGet(this, _TurnState_calls, "f").add(key);
return call;
}
};
_TurnState_turnID = /* @__PURE__ */ new WeakMap(), _TurnState_turnEnded = /* @__PURE__ */ new WeakMap(), _TurnState_eventIDs = /* @__PURE__ */ new WeakMap(), _TurnState_calls = /* @__PURE__ */ new WeakMap();
}
});
// node_modules/openai/lib/agents/agent-session-stream.mjs
function isInputContent(value2) {
if (!isObj(value2)) {
return false;
}
const content = value2;
let field;
if (content["type"] === "input_text") {
field = "text";
} else if (content["type"] === "input_image") {
field = "image_url";
} else {
return false;
}
return hasOwn(content, "type") && hasOwn(content, field) && typeof content[field] === "string";
}
function normalizedOutput(value2) {
if (value2 === null) {
return null;
}
if (typeof value2 === "string" || Array.isArray(value2) && value2.every(isInputContent)) {
return value2;
}
throw new OpenAIError("Tool output must be text, content, a JSON object, or null");
}
function toolResult(call, value2) {
const output = isObj(value2) ? JSON.stringify(value2) : value2;
const serialized = JSON.stringify(output);
if (serialized === void 0) {
throw new OpenAIError("Tool output must be JSON serializable");
}
return {
type: "agent.session.input.tool_result",
turn_id: call.turn_id,
call_id: call.call_id,
success: true,
output: normalizedOutput(typeof output === "string" ? output : JSON.parse(serialized))
};
}
async function cancelBody(response) {
try {
await response?.body?.cancel();
} catch {
}
}
var _AgentSessionStream_instances, _AgentSessionStream_consumed, _AgentSessionStream_stream, _AgentSessionStream_response, _AgentSessionStream_reading, _AgentSessionStream_sessions, _AgentSessionStream_sessionID, _AgentSessionStream_input, _AgentSessionStream_handlers, _AgentSessionStream_inputKey, _AgentSessionStream_options, _AgentSessionStream_iterate, _AgentSessionStream_result, _AgentSessionStream_checkAbort, _AgentSessionStream_abortError, _AgentSessionStream_wait, _AgentSessionStream_submit, AgentSessionStream;
var init_agent_session_stream = __esm({
"node_modules/openai/lib/agents/agent-session-stream.mjs"() {
init_tslib();
init_turn_state();
init_error();
init_headers2();
init_uuid();
init_values();
AgentSessionStream = class {
/** Creates an unstarted helper. Prefer client.beta.agents.sessions.stream(). */
constructor(sessions, sessionID, params, options) {
_AgentSessionStream_instances.add(this);
this.controller = new AbortController();
_AgentSessionStream_consumed.set(this, false);
_AgentSessionStream_stream.set(this, void 0);
_AgentSessionStream_response.set(this, void 0);
_AgentSessionStream_reading.set(this, false);
_AgentSessionStream_sessions.set(this, void 0);
_AgentSessionStream_sessionID.set(this, void 0);
_AgentSessionStream_input.set(this, void 0);
_AgentSessionStream_handlers.set(this, void 0);
_AgentSessionStream_inputKey.set(this, void 0);
_AgentSessionStream_options.set(this, void 0);
const input = typeof params.input === "string" ? [{ role: "user", content: [{ type: "input_text", text: params.input }] }] : params.input;
if (params.input.length === 0) {
throw new OpenAIError("input must not be empty");
}
__classPrivateFieldSet(this, _AgentSessionStream_sessions, sessions, "f");
__classPrivateFieldSet(this, _AgentSessionStream_sessionID, sessionID, "f");
__classPrivateFieldSet(this, _AgentSessionStream_input, { type: "agent.session.input.message", input }, "f");
__classPrivateFieldSet(this, _AgentSessionStream_handlers, new Map(Object.entries(params.toolHandlers ?? {})), "f");
const headers = buildHeaders([options?.headers]);
__classPrivateFieldSet(this, _AgentSessionStream_inputKey, headers.nulls.has("idempotency-key") ? void 0 : headers.values.get("idempotency-key") ?? params.idempotencyKey ?? options?.idempotencyKey ?? uuid4(), "f");
headers.values.delete("idempotency-key");
headers.nulls.delete("idempotency-key");
const { idempotencyKey: _key, ...rest } = options ?? {};
__classPrivateFieldSet(this, _AgentSessionStream_options, { ...rest, headers }, "f");
}
/** Closes local requests without cancelling the turn; an optional reason becomes the abort error's cause. */
abort(reason) {
this.controller.abort(reason);
__classPrivateFieldGet(this, _AgentSessionStream_stream, "f")?.controller.abort(this.controller.signal.reason);
if (!__classPrivateFieldGet(this, _AgentSessionStream_reading, "f")) {
void cancelBody(__classPrivateFieldGet(this, _AgentSessionStream_response, "f"));
}
}
/** Starts iteration once; use for await to ensure early exits close the connection. */
[(_AgentSessionStream_consumed = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_stream = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_response = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_reading = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_sessions = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_sessionID = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_input = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_handlers = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_inputKey = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_options = /* @__PURE__ */ new WeakMap(), _AgentSessionStream_instances = /* @__PURE__ */ new WeakSet(), Symbol.asyncIterator)]() {
if (__classPrivateFieldGet(this, _AgentSessionStream_consumed, "f")) {
throw new OpenAIError("An AgentSessionStream can only be consumed once");
}
__classPrivateFieldSet(this, _AgentSessionStream_consumed, true, "f");
return __classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_iterate).call(this);
}
};
_AgentSessionStream_iterate = async function* _AgentSessionStream_iterate2() {
const externalSignal = __classPrivateFieldGet(this, _AgentSessionStream_options, "f").signal;
const abort = () => this.abort(externalSignal?.aborted ? externalSignal.reason : this.controller.signal.reason);
externalSignal?.addEventListener("abort", abort, { once: true });
this.controller.signal.addEventListener("abort", abort, { once: true });
const options = { ...__classPrivateFieldGet(this, _AgentSessionStream_options, "f"), signal: this.controller.signal };
const state2 = new TurnState();
try {
if (externalSignal?.aborted) {
this.abort(externalSignal.reason);
}
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
const session = await __classPrivateFieldGet(this, _AgentSessionStream_sessions, "f").retrieve(__classPrivateFieldGet(this, _AgentSessionStream_sessionID, "f"), options);
if (session.status !== "idle") {
throw new OpenAIError("sessions.stream requires an idle session; use sessions.events.stream for active sessions");
}
const subscription = await __classPrivateFieldGet(this, _AgentSessionStream_sessions, "f").events.stream(__classPrivateFieldGet(this, _AgentSessionStream_sessionID, "f"), options).withResponse();
__classPrivateFieldSet(this, _AgentSessionStream_stream, subscription.data, "f");
__classPrivateFieldSet(this, _AgentSessionStream_response, subscription.response, "f");
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
await __classPrivateFieldGet(this, _AgentSessionStream_sessions, "f").events.create(__classPrivateFieldGet(this, _AgentSessionStream_sessionID, "f"), {
events: [__classPrivateFieldGet(this, _AgentSessionStream_input, "f")],
// Spread creates an own data property without invoking inherited setters or changing the object prototype.
...__classPrivateFieldGet(this, _AgentSessionStream_inputKey, "f") === void 0 ? {} : { "Idempotency-Key": __classPrivateFieldGet(this, _AgentSessionStream_inputKey, "f") }
}, {
...options,
headers: buildHeaders([options.headers, { "Idempotency-Key": __classPrivateFieldGet(this, _AgentSessionStream_inputKey, "f") ?? null }])
});
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
__classPrivateFieldSet(this, _AgentSessionStream_reading, true, "f");
for await (const event of __classPrivateFieldGet(this, _AgentSessionStream_stream, "f")) {
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
if (!state2.accept(event)) {
continue;
}
const terminal = state2.terminal(event);
const pendingCall = state2.call(event);
const handler = pendingCall && __classPrivateFieldGet(this, _AgentSessionStream_handlers, "f").get(pendingCall.name);
const call = pendingCall && handler ? structuredClone(pendingCall) : void 0;
if (terminal) {
__classPrivateFieldGet(this, _AgentSessionStream_stream, "f").controller.abort();
}
yield event;
if (terminal) {
return;
}
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
if (!call || !handler) {
continue;
}
const result = await __classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_result).call(this, call, handler);
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
await __classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_submit).call(this, result, options);
}
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
throw new OpenAIError("Session event stream ended before the turn reached idle or failed");
} finally {
externalSignal?.removeEventListener("abort", abort);
this.controller.signal.removeEventListener("abort", abort);
this.abort();
}
}, _AgentSessionStream_result = async function _AgentSessionStream_result2(call, handler) {
try {
const args = typeof call.arguments === "string" ? JSON.parse(call.arguments) : call.arguments;
if (!isObj(args)) {
throw new OpenAIError("Function arguments must be a JSON object");
}
return toolResult(call, await __classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_wait).call(this, () => handler(args)));
} catch {
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
return {
type: "agent.session.input.tool_result",
turn_id: call.turn_id,
call_id: call.call_id,
success: false,
error: "Tool handler failed."
};
}
}, _AgentSessionStream_checkAbort = function _AgentSessionStream_checkAbort2() {
if (this.controller.signal.aborted) {
throw __classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_abortError).call(this);
}
}, _AgentSessionStream_abortError = function _AgentSessionStream_abortError2() {
const error = new APIUserAbortError();
Object.defineProperty(error, "cause", {
value: this.controller.signal.reason,
writable: true,
configurable: true
});
return error;
}, _AgentSessionStream_wait = async function _AgentSessionStream_wait2(action) {
let onAbort;
const aborted = new Promise((_resolve, reject2) => {
onAbort = () => reject2(__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_abortError).call(this));
this.controller.signal.addEventListener("abort", onAbort, { once: true });
});
try {
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
const invoke = async () => await action();
return await Promise.race([invoke(), aborted]);
} finally {
if (onAbort) {
this.controller.signal.removeEventListener("abort", onAbort);
}
}
}, _AgentSessionStream_submit = async function _AgentSessionStream_submit2(result, options, key = uuid4(), attempt = 0) {
__classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_checkAbort).call(this);
try {
await __classPrivateFieldGet(this, _AgentSessionStream_sessions, "f").events.create(__classPrivateFieldGet(this, _AgentSessionStream_sessionID, "f"), { events: [result], "Idempotency-Key": key }, options);
} catch (error) {
const delay = [100, 300, 600][attempt];
if (delay === void 0 || !(error instanceof BadRequestError) || error.code !== "invalid_request_error" || !error.error || !("message" in error.error) || error.error.message !== `Unknown pending tool call: ${result.call_id}`) {
throw error;
}
let timer;
try {
await __classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_wait).call(this, () => (
// oxlint-disable-next-line promise/avoid-new -- Own the registration timer so cancellation clears it promptly.
new Promise((resolve2) => {
timer = setTimeout(resolve2, delay);
})
));
} finally {
if (timer !== void 0) {
clearTimeout(timer);
}
}
await __classPrivateFieldGet(this, _AgentSessionStream_instances, "m", _AgentSessionStream_submit2).call(this, result, options, key, attempt + 1);
}
};
}
});
// node_modules/openai/resources/beta/agents/sessions/artifacts.mjs
var Artifacts;
var init_artifacts = __esm({
"node_modules/openai/resources/beta/agents/sessions/artifacts.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Artifacts = class extends APIResource {
/**
* Retrieves immutable metadata for one durable session artifact. See
* [session artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files#openai-hosted-artifacts).
*
* @example
* ```ts
* const sessionArtifact =
* await client.beta.agents.sessions.artifacts.retrieve(
* 'artifact_id',
* { session_id: 'session_id' },
* );
* ```
*/
retrieve(artifactID, params, options) {
const { session_id } = params;
return this._client.get(path`/agents/sessions/${session_id}/artifacts/${artifactID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists immutable artifacts published by completed hosted session turns. See
* [session artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files#openai-hosted-artifacts).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const sessionArtifact of client.beta.agents.sessions.artifacts.list(
* 'session_id',
* )) {
* // ...
* }
* ```
*/
list(sessionID, query = {}, options) {
return this._client.getAPIList(path`/agents/sessions/${sessionID}/artifacts`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Deletes an immutable session artifact without deleting its live environment file
* or original Files API object. See
* [session artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files#openai-hosted-artifacts).
*
* @example
* ```ts
* const sessionArtifactDeleted =
* await client.beta.agents.sessions.artifacts.delete(
* 'artifact_id',
* { session_id: 'session_id' },
* );
* ```
*/
delete(artifactID, params, options) {
const { session_id } = params;
return this._client.delete(path`/agents/sessions/${session_id}/artifacts/${artifactID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Downloads immutable session artifact bytes after the execution environment
* expires. See
* [session artifacts](https://developers.openai.com/api/docs/guides/agents-api/environments/files#openai-hosted-artifacts).
*
* @example
* ```ts
* const response =
* await client.beta.agents.sessions.artifacts.content(
* 'artifact_id',
* { session_id: 'session_id' },
* );
*
* const content = await response.blob();
* console.log(content);
* ```
*/
content(artifactID, params, options) {
const { session_id } = params;
return this._client.get(path`/agents/sessions/${session_id}/artifacts/${artifactID}/content`, {
...options,
headers: buildHeaders([
{ "OpenAI-Beta": "agents=v1", Accept: "application/octet-stream" },
options?.headers
]),
__security: { bearerAuth: true },
__binaryResponse: true
});
}
};
}
});
// node_modules/openai/resources/beta/agents/sessions/events.mjs
var Events;
var init_events = __esm({
"node_modules/openai/resources/beta/agents/sessions/events.mjs"() {
init_resource();
init_headers2();
init_path();
Events = class extends APIResource {
/**
* Submits message, cancellation, or tool-result events to a managed agent session.
* Cancellation can recover a still-open turn whose backend execution has ended by
* marking it cancelled and abandoning unpublished outputs. Saved results,
* published files, and existing terminal outcomes are preserved. HTTP 202 confirms
* acceptance, not durable completion. See
* [session events](https://developers.openai.com/api/docs/guides/agents-api/sessions/events).
*
* @example
* ```ts
* await client.beta.agents.sessions.events.create(
* 'session_id',
* {
* events: [
* {
* input: [
* {
* content: [{ text: 'text', type: 'input_text' }],
* role: 'user',
* },
* ],
* type: 'agent.session.input.message',
* },
* ],
* },
* );
* ```
*/
create(sessionID, params, options) {
const { "Idempotency-Key": idempotencyKey, ...body } = params;
return this._client.post(path`/agents/sessions/${sessionID}/events`, {
body,
...options,
headers: buildHeaders([
{
"OpenAI-Beta": "agents=v1",
Accept: "*/*",
...idempotencyKey != null ? { "Idempotency-Key": idempotencyKey } : void 0
},
options?.headers
]),
__security: { bearerAuth: true }
});
}
/**
* Streams live events for an agent session. See
* [session events](https://developers.openai.com/api/docs/guides/agents-api/sessions/events).
*
* @example
* ```ts
* const agentSessionEvent =
* await client.beta.agents.sessions.events.stream(
* 'session_id',
* );
* ```
*/
stream(sessionID, options) {
return this._client.get(path`/agents/sessions/${sessionID}/events`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1", Accept: "text/event-stream" }, options?.headers]),
stream: true,
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/agents/sessions/items.mjs
var Items;
var init_items = __esm({
"node_modules/openai/resources/beta/agents/sessions/items.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Items = class extends APIResource {
/**
* Lists items produced by the session's root agent, including its interactions
* with subagents. Each subagent has its own item history. See
* [inspecting agent output](https://developers.openai.com/api/docs/guides/agents-api/observability).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const agentSessionItem of client.beta.agents.sessions.items.list(
* 'session_id',
* )) {
* // ...
* }
* ```
*/
list(sessionID, query = {}, options) {
return this._client.getAPIList(path`/agents/sessions/${sessionID}/items`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/agents/sessions/turns.mjs
var Turns;
var init_turns = __esm({
"node_modules/openai/resources/beta/agents/sessions/turns.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Turns = class extends APIResource {
/**
* Retrieves a turn's current status, timestamps, usage, and error. Returns 404 if
* the turn does not belong to the session. See
* [session turns](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage#inspect-session-turns).
*
* @example
* ```ts
* const turn =
* await client.beta.agents.sessions.turns.retrieve(
* 'turn_id',
* { session_id: 'session_id' },
* );
* ```
*/
retrieve(turnID, params, options) {
const { session_id } = params;
return this._client.get(path`/agents/sessions/${session_id}/turns/${turnID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists turns by creation time and turn ID. The after cursor is exclusive in the
* selected order. See
* [session turns](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage#inspect-session-turns).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const turn of client.beta.agents.sessions.turns.list(
* 'session_id',
* )) {
* // ...
* }
* ```
*/
list(sessionID, query = {}, options) {
return this._client.getAPIList(path`/agents/sessions/${sessionID}/turns`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/agents/sessions/subagents/items.mjs
var Items2;
var init_items2 = __esm({
"node_modules/openai/resources/beta/agents/sessions/subagents/items.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Items2 = class extends APIResource {
/**
* Lists this subagent's own items across all of its turns. See
* [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const agentSessionItem of client.beta.agents.sessions.subagents.items.list(
* 'subagent_id',
* { session_id: 'session_id' },
* )) {
* // ...
* }
* ```
*/
list(subagentID, params, options) {
const { session_id, ...query } = params;
return this._client.getAPIList(path`/agents/sessions/${session_id}/subagents/${subagentID}/items`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/agents/sessions/subagents/turns/items.mjs
var Items3;
var init_items3 = __esm({
"node_modules/openai/resources/beta/agents/sessions/subagents/turns/items.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Items3 = class extends APIResource {
/**
* Lists items belonging to one turn of this subagent. See
* [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const agentSessionItem of client.beta.agents.sessions.subagents.turns.items.list(
* 'turn_id',
* { session_id: 'session_id', subagent_id: 'subagent_id' },
* )) {
* // ...
* }
* ```
*/
list(turnID, params, options) {
const { session_id, subagent_id, ...query } = params;
return this._client.getAPIList(path`/agents/sessions/${session_id}/subagents/${subagent_id}/turns/${turnID}/items`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/agents/sessions/subagents/turns/turns.mjs
var Turns2;
var init_turns2 = __esm({
"node_modules/openai/resources/beta/agents/sessions/subagents/turns/turns.mjs"() {
init_resource();
init_items3();
init_items3();
init_pagination();
init_headers2();
init_path();
Turns2 = class extends APIResource {
constructor() {
super(...arguments);
this.items = new Items3(this._client);
}
/**
* Retrieves a turn belonging to this subagent. See
* [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent).
*
* @example
* ```ts
* const turn =
* await client.beta.agents.sessions.subagents.turns.retrieve(
* 'turn_id',
* {
* session_id: 'session_id',
* subagent_id: 'subagent_id',
* },
* );
* ```
*/
retrieve(turnID, params, options) {
const { session_id, subagent_id } = params;
return this._client.get(path`/agents/sessions/${session_id}/subagents/${subagent_id}/turns/${turnID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists all turns of this subagent, including turns after a resume. See
* [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const turn of client.beta.agents.sessions.subagents.turns.list(
* 'subagent_id',
* { session_id: 'session_id' },
* )) {
* // ...
* }
* ```
*/
list(subagentID, params, options) {
const { session_id, ...query } = params;
return this._client.getAPIList(path`/agents/sessions/${session_id}/subagents/${subagentID}/turns`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
Turns2.Items = Items3;
}
});
// node_modules/openai/resources/beta/agents/sessions/subagents/subagents.mjs
var Subagents;
var init_subagents = __esm({
"node_modules/openai/resources/beta/agents/sessions/subagents/subagents.mjs"() {
init_resource();
init_items2();
init_items2();
init_turns2();
init_turns2();
init_pagination();
init_headers2();
init_path();
Subagents = class extends APIResource {
constructor() {
super(...arguments);
this.items = new Items2(this._client);
this.turns = new Turns2(this._client);
}
/**
* Retrieves a subagent belonging to this session. See
* [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent).
*
* @example
* ```ts
* const subagent =
* await client.beta.agents.sessions.subagents.retrieve(
* 'subagent_id',
* { session_id: 'session_id' },
* );
* ```
*/
retrieve(subagentID, params, options) {
const { session_id } = params;
return this._client.get(path`/agents/sessions/${session_id}/subagents/${subagentID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists subagents in a session, including nested and closed subagents. See
* [subagent workflows](https://developers.openai.com/api/docs/guides/agents-api/multi-agent).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const subagent of client.beta.agents.sessions.subagents.list(
* 'session_id',
* )) {
* // ...
* }
* ```
*/
list(sessionID, query = {}, options) {
return this._client.getAPIList(path`/agents/sessions/${sessionID}/subagents`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
Subagents.Items = Items2;
Subagents.Turns = Turns2;
}
});
// node_modules/openai/resources/beta/agents/sessions/sessions.mjs
var Sessions2;
var init_sessions2 = __esm({
"node_modules/openai/resources/beta/agents/sessions/sessions.mjs"() {
init_agent_session_stream();
init_resource();
init_artifacts();
init_artifacts();
init_events();
init_events();
init_items();
init_items();
init_turns();
init_turns();
init_subagents();
init_subagents();
init_pagination();
init_headers2();
init_path();
Sessions2 = class extends APIResource {
constructor() {
super(...arguments);
this.subagents = new Subagents(this._client);
this.artifacts = new Artifacts(this._client);
this.items = new Items(this._client);
this.events = new Events(this._client);
this.turns = new Turns(this._client);
}
/** Stream one turn on an idle session with a single input writer. See AgentSessionStream for lifecycle and tool handling. */
stream(sessionID, params, options) {
return new AgentSessionStream(this, sessionID, params, options);
}
create(body, options) {
return this._client.post("/agents/sessions", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
stream: body.stream ?? false,
__security: { bearerAuth: true }
});
}
/**
* Retrieves the current state of a managed agent session. See
* [managing sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage).
*
* @example
* ```ts
* const agentSession =
* await client.beta.agents.sessions.retrieve('session_id');
* ```
*/
retrieve(sessionID, options) {
return this._client.get(path`/agents/sessions/${sessionID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Updates session metadata, model, reasoning effort, or service tier. Model
* settings apply to subsequent turns. Omitted fields are unchanged. See
* [managing sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage).
*
* @example
* ```ts
* const agentSession =
* await client.beta.agents.sessions.update('session_id');
* ```
*/
update(sessionID, body = {}, options) {
return this._client.post(path`/agents/sessions/${sessionID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists managed agent sessions using ID-based pagination and the requested sort
* order. See
* [managing sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const agentSession of client.beta.agents.sessions.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/agents/sessions", CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Removes a managed agent session from the public API and returns a deletion
* confirmation. If backend execution has ended, deletion can cancel a still-open
* public turn and abandon unpublished outputs. Running execution must be cancelled
* first. Physical cleanup may continue asynchronously. See
* [managing sessions](https://developers.openai.com/api/docs/guides/agents-api/sessions/manage).
*
* @example
* ```ts
* const agentSessionDeleted =
* await client.beta.agents.sessions.delete('session_id');
* ```
*/
delete(sessionID, options) {
return this._client.delete(path`/agents/sessions/${sessionID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
Sessions2.Subagents = Subagents;
Sessions2.Artifacts = Artifacts;
Sessions2.Items = Items;
Sessions2.Events = Events;
Sessions2.Turns = Turns;
}
});
// node_modules/openai/resources/beta/agents/vaults/credentials.mjs
var Credentials;
var init_credentials = __esm({
"node_modules/openai/resources/beta/agents/vaults/credentials.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Credentials = class extends APIResource {
/**
* Creates a vault credential. Secret values are write-only and are never returned.
* See
* [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults).
*
* @example
* ```ts
* const credential =
* await client.beta.agents.vaults.credentials.create(
* 'vault_id',
* {
* auth: {
* access_token: 'access_token',
* mcp_server_url: 'mcp_server_url',
* type: 'mcp_oauth',
* },
* name: 'x',
* },
* );
* ```
*/
create(vaultID, body, options) {
return this._client.post(path`/vaults/${vaultID}/credentials`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieves vault credential metadata without returning secret values. See
* [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults).
*
* @example
* ```ts
* const credential =
* await client.beta.agents.vaults.credentials.retrieve(
* 'credential_id',
* { vault_id: 'vault_id' },
* );
* ```
*/
retrieve(credentialID, params, options) {
const { vault_id } = params;
return this._client.get(path`/vaults/${vault_id}/credentials/${credentialID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Rotates a vault credential's write-only secret and returns only credential
* metadata. See
* [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults).
*
* @example
* ```ts
* const credential =
* await client.beta.agents.vaults.credentials.update(
* 'credential_id',
* {
* vault_id: 'vault_id',
* auth: { type: 'mcp_oauth' },
* },
* );
* ```
*/
update(credentialID, params, options) {
const { vault_id, ...body } = params;
return this._client.post(path`/vaults/${vault_id}/credentials/${credentialID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists a vault's credentials using ID-based pagination without returning secret
* values. See
* [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const credential of client.beta.agents.vaults.credentials.list(
* 'vault_id',
* )) {
* // ...
* }
* ```
*/
list(vaultID, query = {}, options) {
return this._client.getAPIList(path`/vaults/${vaultID}/credentials`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Deletes a vault credential. See
* [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults).
*
* @example
* ```ts
* const credentialDeleted =
* await client.beta.agents.vaults.credentials.delete(
* 'credential_id',
* { vault_id: 'vault_id' },
* );
* ```
*/
delete(credentialID, params, options) {
const { vault_id } = params;
return this._client.delete(path`/vaults/${vault_id}/credentials/${credentialID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/agents/vaults/vaults.mjs
var Vaults;
var init_vaults = __esm({
"node_modules/openai/resources/beta/agents/vaults/vaults.mjs"() {
init_resource();
init_credentials();
init_credentials();
init_pagination();
init_headers2();
init_path();
Vaults = class extends APIResource {
constructor() {
super(...arguments);
this.credentials = new Credentials(this._client);
}
/**
* Creates a vault for the current project. See
* [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults).
*
* @example
* ```ts
* const vault = await client.beta.agents.vaults.create();
* ```
*/
create(body = {}, options) {
return this._client.post("/vaults", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieves a vault by its ID. See
* [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults).
*
* @example
* ```ts
* const vault = await client.beta.agents.vaults.retrieve(
* 'vault_id',
* );
* ```
*/
retrieve(vaultID, options) {
return this._client.get(path`/vaults/${vaultID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists vaults using ID-based pagination. See
* [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const vault of client.beta.agents.vaults.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/vaults", CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Deletes a vault and all its credentials. See
* [vaults](https://developers.openai.com/api/docs/guides/agents-api/tools/vaults).
*
* @example
* ```ts
* const vaultDeleted = await client.beta.agents.vaults.delete(
* 'vault_id',
* );
* ```
*/
delete(vaultID, options) {
return this._client.delete(path`/vaults/${vaultID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
Vaults.Credentials = Credentials;
}
});
// node_modules/openai/resources/beta/agents/agents.mjs
var Agents;
var init_agents = __esm({
"node_modules/openai/resources/beta/agents/agents.mjs"() {
init_resource();
init_environments();
init_environments();
init_sessions2();
init_sessions2();
init_vaults();
init_vaults();
init_pagination();
init_headers2();
init_path();
Agents = class extends APIResource {
constructor() {
super(...arguments);
this.environments = new Environments(this._client);
this.vaults = new Vaults(this._client);
this.sessions = new Sessions2(this._client);
}
/**
* Creates a reusable agent without storing credentials. See
* [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration).
*
* @example
* ```ts
* const agent = await client.beta.agents.create({
* model: 'model',
* });
* ```
*/
create(body, options) {
return this._client.post("/agents", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieves a reusable agent by ID. See
* [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration).
*
* @example
* ```ts
* const agent = await client.beta.agents.retrieve('agent_id');
* ```
*/
retrieve(agentID, options) {
return this._client.get(path`/agents/${agentID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Updates a reusable agent. See
* [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration).
*
* @example
* ```ts
* const agent = await client.beta.agents.update('agent_id');
* ```
*/
update(agentID, body = {}, options) {
return this._client.post(path`/agents/${agentID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Lists reusable agents in the current project. See
* [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration).
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const agent of client.beta.agents.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/agents", CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Deletes a reusable agent. See
* [agent configuration](https://developers.openai.com/api/docs/guides/agents-api/configuration).
*
* @example
* ```ts
* const agentDeleted = await client.beta.agents.delete(
* 'agent_id',
* );
* ```
*/
delete(agentID, options) {
return this._client.delete(path`/agents/${agentID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "agents=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
Agents.Environments = Environments;
Agents.Vaults = Vaults;
Agents.Sessions = Sessions2;
}
});
// node_modules/openai/resources/beta/chatkit/sessions.mjs
var Sessions3;
var init_sessions3 = __esm({
"node_modules/openai/resources/beta/chatkit/sessions.mjs"() {
init_resource();
init_headers2();
init_path();
Sessions3 = class extends APIResource {
/**
* Create a ChatKit session.
*
* @example
* ```ts
* const chatSession =
* await client.beta.chatkit.sessions.create({
* user: 'x',
* workflow: { id: 'id' },
* });
* ```
*/
create(body, options) {
return this._client.post("/chatkit/sessions", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "chatkit_beta=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Cancel an active ChatKit session and return its most recent metadata.
*
* Cancelling prevents new requests from using the issued client secret.
*
* @example
* ```ts
* const chatSession =
* await client.beta.chatkit.sessions.cancel('cksess_123');
* ```
*/
cancel(sessionID, options) {
return this._client.post(path`/chatkit/sessions/${sessionID}/cancel`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "chatkit_beta=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/chatkit/threads.mjs
var Threads;
var init_threads = __esm({
"node_modules/openai/resources/beta/chatkit/threads.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Threads = class extends APIResource {
/**
* Retrieve a ChatKit thread by its identifier.
*
* @example
* ```ts
* const chatkitThread =
* await client.beta.chatkit.threads.retrieve('cthr_123');
* ```
*/
retrieve(threadID, options) {
return this._client.get(path`/chatkit/threads/${threadID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "chatkit_beta=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* List ChatKit threads with optional pagination and user filters.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const chatkitThread of client.beta.chatkit.threads.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/chatkit/threads", ConversationCursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "chatkit_beta=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Delete a ChatKit thread along with its items and stored attachments.
*
* @example
* ```ts
* const thread = await client.beta.chatkit.threads.delete(
* 'cthr_123',
* );
* ```
*/
delete(threadID, options) {
return this._client.delete(path`/chatkit/threads/${threadID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "chatkit_beta=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* List items that belong to a ChatKit thread.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const thread of client.beta.chatkit.threads.listItems(
* 'cthr_123',
* )) {
* // ...
* }
* ```
*/
listItems(threadID, query = {}, options) {
return this._client.getAPIList(path`/chatkit/threads/${threadID}/items`, ConversationCursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "chatkit_beta=v1" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/chatkit/chatkit.mjs
var ChatKit;
var init_chatkit = __esm({
"node_modules/openai/resources/beta/chatkit/chatkit.mjs"() {
init_resource();
init_sessions3();
init_sessions3();
init_threads();
init_threads();
ChatKit = class extends APIResource {
constructor() {
super(...arguments);
this.sessions = new Sessions3(this._client);
this.threads = new Threads(this._client);
}
};
ChatKit.Sessions = Sessions3;
ChatKit.Threads = Threads;
}
});
// node_modules/openai/resources/beta/responses/input-items.mjs
var InputItems;
var init_input_items = __esm({
"node_modules/openai/resources/beta/responses/input-items.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
InputItems = class extends APIResource {
/**
* Returns a list of input items for a given response.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const betaResponseItem of client.beta.responses.inputItems.list(
* 'response_id',
* )) {
* // ...
* }
* ```
*/
list(responseID, params = {}, options) {
const { betas, ...query } = params ?? {};
return this._client.getAPIList(path`/responses/${responseID}/input_items?beta=true`, CursorPage, {
query,
...options,
headers: buildHeaders([
{ ...betas?.toString() != null ? { "openai-beta": betas?.toString() } : void 0 },
options?.headers
]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/responses/input-tokens.mjs
var InputTokens;
var init_input_tokens = __esm({
"node_modules/openai/resources/beta/responses/input-tokens.mjs"() {
init_resource();
init_headers2();
InputTokens = class extends APIResource {
/**
* Returns input token counts of the request.
*
* Returns an object with `object` set to `response.input_tokens` and an
* `input_tokens` count.
*
* @example
* ```ts
* const response =
* await client.beta.responses.inputTokens.count();
* ```
*/
count(params = {}, options) {
const { betas, ...body } = params ?? {};
return this._client.post("/responses/input_tokens?beta=true", {
body,
...options,
headers: buildHeaders([
{ ...betas?.toString() != null ? { "openai-beta": betas?.toString() } : void 0 },
options?.headers
]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/responses/responses.mjs
var Responses;
var init_responses = __esm({
"node_modules/openai/resources/beta/responses/responses.mjs"() {
init_resource();
init_input_items();
init_input_items();
init_input_tokens();
init_input_tokens();
init_headers2();
init_path();
Responses = class extends APIResource {
constructor() {
super(...arguments);
this.inputItems = new InputItems(this._client);
this.inputTokens = new InputTokens(this._client);
}
create(params, options) {
const { betas, ...body } = params;
return this._client.post("/responses?beta=true", {
body,
...options,
headers: buildHeaders([
{ ...betas?.toString() != null ? { "openai-beta": betas?.toString() } : void 0 },
options?.headers
]),
stream: params.stream ?? false,
__security: { bearerAuth: true }
});
}
retrieve(responseID, params = {}, options) {
const { betas, ...query } = params ?? {};
return this._client.get(path`/responses/${responseID}?beta=true`, {
query,
...options,
headers: buildHeaders([
{ ...betas?.toString() != null ? { "openai-beta": betas?.toString() } : void 0 },
options?.headers
]),
stream: params?.stream ?? false,
__security: { bearerAuth: true }
});
}
/**
* Deletes a model response with the given ID.
*
* @example
* ```ts
* await client.beta.responses.delete(
* 'resp_677efb5139a88190b512bc3fef8e535d',
* );
* ```
*/
delete(responseID, params = {}, options) {
const { betas } = params ?? {};
return this._client.delete(path`/responses/${responseID}?beta=true`, {
...options,
headers: buildHeaders([
{ Accept: "*/*", ...betas?.toString() != null ? { "openai-beta": betas?.toString() } : void 0 },
options?.headers
]),
__security: { bearerAuth: true }
});
}
/**
* Cancels a model response with the given ID. Only responses created with the
* `background` parameter set to `true` can be cancelled.
* [Learn more](https://developers.openai.com/api/docs/guides/background).
*
* @example
* ```ts
* const betaResponse = await client.beta.responses.cancel(
* 'resp_677efb5139a88190b512bc3fef8e535d',
* );
* ```
*/
cancel(responseID, params = {}, options) {
const { betas } = params ?? {};
return this._client.post(path`/responses/${responseID}/cancel?beta=true`, {
...options,
headers: buildHeaders([
{ ...betas?.toString() != null ? { "openai-beta": betas?.toString() } : void 0 },
options?.headers
]),
__security: { bearerAuth: true }
});
}
/**
* Compact a conversation. Returns a compacted response object.
*
* Learn when and how to compact long-running conversations in the
* [conversation state guide](https://developers.openai.com/api/docs/guides/conversation-state#managing-the-context-window).
* For ZDR-compatible compaction details, see
* [Compaction (advanced)](https://developers.openai.com/api/docs/guides/conversation-state#compaction-advanced).
*
* @example
* ```ts
* const betaCompactedResponse =
* await client.beta.responses.compact({
* model: 'gpt-6-astra',
* });
* ```
*/
compact(params, options) {
const { betas, ...body } = params;
return this._client.post("/responses/compact?beta=true", {
body,
...options,
headers: buildHeaders([
{ ...betas?.toString() != null ? { "openai-beta": betas?.toString() } : void 0 },
options?.headers
]),
__security: { bearerAuth: true }
});
}
};
Responses.InputItems = InputItems;
Responses.InputTokens = InputTokens;
}
});
// node_modules/openai/resources/beta/threads/messages.mjs
var Messages2;
var init_messages2 = __esm({
"node_modules/openai/resources/beta/threads/messages.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Messages2 = class extends APIResource {
/**
* Create a message.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
create(threadID, body, options) {
return this._client.post(path`/threads/${threadID}/messages`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieve a message.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
retrieve(messageID, params, options) {
const { thread_id } = params;
return this._client.get(path`/threads/${thread_id}/messages/${messageID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Modifies a message.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
update(messageID, params, options) {
const { thread_id, ...body } = params;
return this._client.post(path`/threads/${thread_id}/messages/${messageID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Returns a list of messages for a given thread.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
list(threadID, query = {}, options) {
return this._client.getAPIList(path`/threads/${threadID}/messages`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Deletes a message.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
delete(messageID, params, options) {
const { thread_id } = params;
return this._client.delete(path`/threads/${thread_id}/messages/${messageID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/beta/threads/runs/steps.mjs
var Steps;
var init_steps = __esm({
"node_modules/openai/resources/beta/threads/runs/steps.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_path();
Steps = class extends APIResource {
/**
* Retrieves a run step.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
retrieve(stepID, params, options) {
const { thread_id, run_id, ...query } = params;
return this._client.get(path`/threads/${thread_id}/runs/${run_id}/steps/${stepID}`, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Returns a list of run steps belonging to a run.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
list(runID, params, options) {
const { thread_id, ...query } = params;
return this._client.getAPIList(path`/threads/${thread_id}/runs/${runID}/steps`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/internal/utils/base64.mjs
var fromBase64, toFloat32Array;
var init_base64 = __esm({
"node_modules/openai/internal/utils/base64.mjs"() {
init_error();
init_bytes();
fromBase64 = (str2) => {
if (typeof globalThis.Buffer !== "undefined") {
const buf = globalThis.Buffer.from(str2, "base64");
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
}
if (typeof atob !== "undefined") {
const bstr = atob(str2);
const buf = new Uint8Array(bstr.length);
for (let i = 0; i < bstr.length; i++) {
buf[i] = bstr.charCodeAt(i);
}
return buf;
}
throw new OpenAIError("Cannot decode base64 string; Expected `Buffer` or `atob` to be defined");
};
toFloat32Array = (base64Str) => {
if (typeof Buffer !== "undefined") {
const buf = Buffer.from(base64Str, "base64");
if (buf.length % Float32Array.BYTES_PER_ELEMENT !== 0) {
throw new RangeError("Invalid base64-encoded float32 array: byte length must be a multiple of 4");
}
return Array.from(new Float32Array(buf.buffer, buf.byteOffset, buf.length / Float32Array.BYTES_PER_ELEMENT));
} else {
const binaryStr = atob(base64Str);
const len = binaryStr.length;
const bytes2 = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes2[i] = binaryStr.charCodeAt(i);
}
return Array.from(new Float32Array(bytes2.buffer));
}
};
}
});
// node_modules/openai/internal/utils/env.mjs
var readEnv;
var init_env = __esm({
"node_modules/openai/internal/utils/env.mjs"() {
readEnv = (env) => {
try {
if (typeof globalThis.process !== "undefined") {
return globalThis.process.env?.[env]?.trim() || void 0;
}
if (typeof globalThis.Deno !== "undefined") {
return globalThis.Deno.env?.get?.(env)?.trim() || void 0;
}
} catch {
return void 0;
}
return void 0;
};
}
});
// node_modules/openai/internal/utils.mjs
var init_utils2 = __esm({
"node_modules/openai/internal/utils.mjs"() {
init_values();
init_base64();
init_env();
init_log();
init_uuid();
init_sleep();
init_query();
}
});
// node_modules/openai/internal/assistant-stream-delta.mjs
function getAssistantStreamDiagnosticProperty(property) {
switch (property) {
case "value":
case "arguments":
case "input":
case "text":
case "content":
case "annotations":
case "metadata":
case "name":
case "role":
case "status":
case "tool_calls":
case "step_details": {
return property;
}
default: {
return "unknown";
}
}
}
function createAssistantStreamDeltaProjection(cacheArrays) {
return { arrays: /* @__PURE__ */ new Map(), cacheArrays, records: /* @__PURE__ */ new WeakMap() };
}
function commitAssistantStreamArrayProjection(projection) {
for (const [array, projected] of projection.arrays) {
if (projected.cacheable && !externallyMutableAssistantStreamValues.has(array)) {
assistantStreamArrayStates.set(array, {
length: projected.length,
ownEntryCount: projected.ownEntryCount
});
} else {
assistantStreamArrayStates.delete(array);
}
}
}
function isPrimitiveAssistantStreamValue(value2) {
return typeof value2 === "string" || typeof value2 === "number";
}
function isPrimitiveAssistantStreamArrayDelta(accumulator, delta) {
return delta.every(isPrimitiveAssistantStreamValue) && accumulator.every(isPrimitiveAssistantStreamValue);
}
function countOwnAssistantStreamArrayEntries(accumulator) {
let count = 0;
for (const key of Object.keys(accumulator)) {
const index = Number(key);
if (Number.isSafeInteger(index) && index >= 0 && index < accumulator.length && String(index) === key) {
count += 1;
}
}
return count;
}
function getAssistantStreamArrayOwnEntryCount(accumulator, enforceSparseHoleBudget, cachedState) {
if (!enforceSparseHoleBudget) {
return 0;
}
if (cachedState?.length === accumulator.length) {
return cachedState.ownEntryCount;
}
return countOwnAssistantStreamArrayEntries(accumulator);
}
function getAssistantStreamDeltaIndex(deltaEntry, kind, baselineLength) {
const { index } = deltaEntry;
if (kind === "array" && (index === null || index === void 0)) {
throw new Error("Expected array delta entry to have an `index` property");
}
if (kind === "array" && typeof index !== "number") {
throw new TypeError("Expected array delta entry `index` property to be a number but got an invalid value");
}
if (!Number.isSafeInteger(index) || index < 0 || index >= baselineLength + MAX_ASSISTANT_STREAM_ARRAY_GROWTH || index >= MAX_EXTERNALLY_MUTABLE_ASSISTANT_STREAM_ARRAY_LENGTH) {
const safeIndex = typeof index === "number" ? index : "unknown";
throw new OpenAIError(`Assistant stream delta contains an invalid ${kind} index: ${safeIndex}`);
}
return index;
}
function assertValidAssistantStreamArrayDelta(accumulator, delta, kind, projection, validateRecord) {
let projectedArray = projection.arrays.get(accumulator);
if (!projectedArray) {
const enforceSparseHoleBudget = projection.cacheArrays && !externallyMutableAssistantStreamValues.has(accumulator);
const cachedState = enforceSparseHoleBudget ? assistantStreamArrayStates.get(accumulator) : void 0;
projectedArray = {
baselineLength: accumulator.length,
cacheable: enforceSparseHoleBudget,
enforceSparseHoleBudget,
entries: /* @__PURE__ */ new Map(),
length: accumulator.length,
ownEntryCount: getAssistantStreamArrayOwnEntryCount(accumulator, enforceSparseHoleBudget, cachedState)
};
projection.arrays.set(accumulator, projectedArray);
}
for (const deltaEntry of delta) {
if (!isObj(deltaEntry)) {
throw new Error("Expected array delta entry to be an object but got an invalid value");
}
const validatedIndex = getAssistantStreamDeltaIndex(deltaEntry, kind, projectedArray.baselineLength);
let accumulatedEntry;
if (projectedArray.entries.has(validatedIndex)) {
accumulatedEntry = projectedArray.entries.get(validatedIndex);
} else if (hasOwn(accumulator, validatedIndex)) {
accumulatedEntry = accumulator[validatedIndex];
if (accumulatedEntry === null || accumulatedEntry === void 0) {
projectedArray.entries.set(validatedIndex, deltaEntry);
}
} else {
projectedArray.entries.set(validatedIndex, deltaEntry);
projectedArray.ownEntryCount += 1;
}
const projectedLength = Math.max(projectedArray.length, validatedIndex + 1);
if (projectedArray.enforceSparseHoleBudget && projectedLength - projectedArray.ownEntryCount > MAX_ASSISTANT_STREAM_ARRAY_GROWTH) {
throw new OpenAIError(`Assistant stream delta contains an invalid ${kind} index: ${validatedIndex}`);
}
if (isObj(accumulatedEntry)) {
validateRecord(accumulatedEntry, deltaEntry, projection);
}
projectedArray.length = projectedLength;
}
}
function assertValidAssistantStreamDeltaIndices(accumulator, delta, projection) {
let projectedValues = projection.records.get(accumulator);
for (const [key, deltaValue] of Object.entries(delta)) {
if (key === "index" || key === "type") {
continue;
}
let accumulatedValue;
if (projectedValues?.has(key)) {
accumulatedValue = projectedValues.get(key);
} else if (hasOwn(accumulator, key)) {
accumulatedValue = accumulator[key];
}
if (accumulatedValue === null || accumulatedValue === void 0) {
if (!projectedValues) {
projectedValues = /* @__PURE__ */ new Map();
projection.records.set(accumulator, projectedValues);
}
projectedValues.set(key, deltaValue);
continue;
}
if (isObj(accumulatedValue) && isObj(deltaValue)) {
assertValidAssistantStreamDeltaIndices(accumulatedValue, deltaValue, projection);
} else if (Array.isArray(accumulatedValue) && Array.isArray(deltaValue) && !isPrimitiveAssistantStreamArrayDelta(accumulatedValue, deltaValue)) {
assertValidAssistantStreamArrayDelta(accumulatedValue, deltaValue, "array", projection, assertValidAssistantStreamDeltaIndices);
}
}
}
function isAssistantStreamValueExternallyMutable(value2) {
return (isObj(value2) || Array.isArray(value2)) && externallyMutableAssistantStreamValues.has(value2);
}
function markAssistantStreamValueExternallyMutable(value2) {
if (!isObj(value2) && !Array.isArray(value2) || externallyMutableAssistantStreamValues.has(value2)) {
return;
}
externallyMutableAssistantStreamValues.add(value2);
if (Array.isArray(value2)) {
assistantStreamArrayStates.delete(value2);
}
for (const key of Reflect.ownKeys(value2)) {
const descriptor = Object.getOwnPropertyDescriptor(value2, key);
if (descriptor && "value" in descriptor) {
markAssistantStreamValueExternallyMutable(descriptor.value);
}
}
}
function defineAssistantStreamArrayEntry(accumulator, index, value2) {
if (externallyMutableAssistantStreamValues.has(accumulator)) {
markAssistantStreamValueExternallyMutable(value2);
}
Object.defineProperty(accumulator, index, {
configurable: true,
enumerable: true,
value: value2,
writable: true
});
}
function getRequiredAssistantStreamArrayIndex(deltaEntry) {
const { index } = deltaEntry;
if (index === null || index === void 0) {
throw new Error("Expected array delta entry to have an `index` property");
}
if (typeof index !== "number") {
throw new TypeError("Expected array delta entry `index` property to be a number but got an invalid value");
}
return index;
}
function applyAssistantStreamArrayDelta(accumulator, delta, applyRecord) {
if (isPrimitiveAssistantStreamArrayDelta(accumulator, delta)) {
accumulator.push(...delta);
assistantStreamArrayStates.delete(accumulator);
return;
}
for (const deltaEntry of delta) {
if (!isObj(deltaEntry)) {
throw new Error("Expected array delta entry to be an object but got an invalid value");
}
const index = getRequiredAssistantStreamArrayIndex(deltaEntry);
if (hasOwn(accumulator, index)) {
const accumulatedEntry = accumulator[index];
if (accumulatedEntry === null || accumulatedEntry === void 0) {
if (externallyMutableAssistantStreamValues.has(accumulator)) {
markAssistantStreamValueExternallyMutable(deltaEntry);
}
accumulator[index] = deltaEntry;
} else {
accumulator[index] = applyRecord(accumulatedEntry, deltaEntry);
}
} else {
defineAssistantStreamArrayEntry(accumulator, index, deltaEntry);
}
}
}
function applyAssistantStreamDelta(accumulator, delta) {
const externallyMutable = externallyMutableAssistantStreamValues.has(accumulator);
for (const [key, deltaValue] of Object.entries(delta)) {
if (key === "__proto__" || key === "constructor" || key === "prototype") {
throw new OpenAIError(`Assistant stream delta contains an unsafe property: ${key}`);
}
if (!hasOwn(accumulator, key)) {
if (externallyMutable) {
markAssistantStreamValueExternallyMutable(deltaValue);
}
accumulator[key] = deltaValue;
continue;
}
let accumulatedValue = accumulator[key];
if (accumulatedValue === null || accumulatedValue === void 0) {
if (externallyMutable) {
markAssistantStreamValueExternallyMutable(deltaValue);
}
accumulator[key] = deltaValue;
continue;
}
if (key === "index" || key === "type") {
accumulator[key] = deltaValue;
continue;
}
if (typeof accumulatedValue === "string" && typeof deltaValue === "string") {
accumulatedValue += deltaValue;
} else if (typeof accumulatedValue === "number" && typeof deltaValue === "number") {
accumulatedValue += deltaValue;
} else if (isObj(accumulatedValue) && isObj(deltaValue)) {
accumulatedValue = applyAssistantStreamDelta(accumulatedValue, deltaValue);
} else if (Array.isArray(accumulatedValue) && Array.isArray(deltaValue)) {
applyAssistantStreamArrayDelta(accumulatedValue, deltaValue, applyAssistantStreamDelta);
continue;
} else {
throw new TypeError(`Unhandled record type: ${getAssistantStreamDiagnosticProperty(key)}`);
}
accumulator[key] = accumulatedValue;
}
return accumulator;
}
function assertSafeAssistantStreamDelta(value2) {
if (!isObj(value2) && !Array.isArray(value2)) {
return;
}
for (const [key, nestedValue] of Object.entries(value2)) {
if (key === "__proto__" || key === "constructor" || key === "prototype") {
throw new OpenAIError(`Assistant stream delta contains an unsafe property: ${key}`);
}
assertSafeAssistantStreamDelta(nestedValue);
}
}
function accumulateAssistantStreamDelta(accumulator, delta, cacheArrays = false) {
assertSafeAssistantStreamDelta(delta);
const accumulatorRecord = accumulator;
const deltaRecord = delta;
const projection = createAssistantStreamDeltaProjection(cacheArrays && !isAssistantStreamValueExternallyMutable(accumulator));
assertValidAssistantStreamDeltaIndices(accumulatorRecord, deltaRecord, projection);
applyAssistantStreamDelta(accumulatorRecord, deltaRecord);
commitAssistantStreamArrayProjection(projection);
return accumulator;
}
function createAssistantStreamArrayDeltaCommit(accumulator, delta, kind, cacheArrays = true) {
assertSafeAssistantStreamDelta(delta);
const projection = createAssistantStreamDeltaProjection(cacheArrays && !isAssistantStreamValueExternallyMutable(accumulator));
assertValidAssistantStreamArrayDelta(accumulator, delta, kind, projection, assertValidAssistantStreamDeltaIndices);
return () => commitAssistantStreamArrayProjection(projection);
}
var MAX_ASSISTANT_STREAM_ARRAY_GROWTH, MAX_EXTERNALLY_MUTABLE_ASSISTANT_STREAM_ARRAY_LENGTH, assistantStreamArrayStates, externallyMutableAssistantStreamValues;
var init_assistant_stream_delta = __esm({
"node_modules/openai/internal/assistant-stream-delta.mjs"() {
init_error2();
init_utils2();
MAX_ASSISTANT_STREAM_ARRAY_GROWTH = 1024;
MAX_EXTERNALLY_MUTABLE_ASSISTANT_STREAM_ARRAY_LENGTH = 65536;
assistantStreamArrayStates = /* @__PURE__ */ new WeakMap();
externallyMutableAssistantStreamValues = /* @__PURE__ */ new WeakSet();
}
});
// node_modules/openai/lib/AssistantStream.mjs
function stabilizeAssistantStreamEvent(event) {
const eventDescriptor = Object.getOwnPropertyDescriptor(event, "event");
const dataDescriptor = Object.getOwnPropertyDescriptor(event, "data");
const eventType = Reflect.get(event, "event", event);
const data = Reflect.get(event, "data", event);
let stableData = data;
if (eventType === "thread.message.created" || eventType === "thread.message.in_progress" || eventType === "thread.message.delta" || eventType === "thread.message.completed" || eventType === "thread.message.incomplete" || eventType === "thread.run.step.created" || eventType === "thread.run.step.in_progress" || eventType === "thread.run.step.delta" || eventType === "thread.run.step.completed" || eventType === "thread.run.step.failed" || eventType === "thread.run.step.cancelled" || eventType === "thread.run.step.expired") {
const messageID = Object.getOwnPropertyDescriptor(data, "id");
if (messageID && "value" in messageID && // SAFETY: The own id descriptor was found above; keep its live read unknown while comparing it with the captured descriptor value.
data.id !== messageID.value) {
const canonicalID = messageID.value;
stableData = new Proxy(data, {
get(target, property) {
return property === "id" ? canonicalID : Reflect.get(target, property, target);
}
});
}
}
const stableEvent = Object.freeze({ event: eventType, data: stableData });
const ordinaryEvent = eventDescriptor !== void 0 && "value" in eventDescriptor && eventDescriptor.value === eventType && dataDescriptor !== void 0 && "value" in dataDescriptor && dataDescriptor.value === data && stableData === data;
return {
event: stableEvent,
exposedEvent: ordinaryEvent ? event : { event: eventType, data: stableData }
};
}
function assertNever2(_x) {
return _x;
}
var _AssistantStream_instances, _AssistantStream_runStepSnapshots, _AssistantStream_runStepIDOwners, _AssistantStream_activeRunStepID, _AssistantStream_messageSnapshots, _AssistantStream_messageIDOwners, _AssistantStream_messageSnapshot, _AssistantStream_activeMessageID, _AssistantStream_finalRun, _AssistantStream_currentContentIndex, _AssistantStream_currentContent, _AssistantStream_currentToolCallIndex, _AssistantStream_currentToolCall, _AssistantStream_currentEvent, _AssistantStream_currentRunSnapshot, _AssistantStream_currentRunStepSnapshot, _AssistantStream_addEvent, _AssistantStream_endRequest, _AssistantStream_validateRunStepEvent, _AssistantStream_reserveRunStepAlias, _AssistantStream_validateMessageEvent, _AssistantStream_reserveMessageAlias, _AssistantStream_handleMessage, _AssistantStream_handleRunStep, _AssistantStream_emitExposed, _AssistantStream_handleEvent, _AssistantStream_accumulateRunStep, _AssistantStream_accumulateMessage, _AssistantStream_accumulateContent, _AssistantStream_handleRun, AssistantStream;
var init_AssistantStream = __esm({
"node_modules/openai/lib/AssistantStream.mjs"() {
init_tslib();
init_streaming2();
init_error2();
init_EventStream();
init_utils2();
init_assistant_stream_delta();
AssistantStream = class _AssistantStream extends EventStream2 {
constructor() {
super(...arguments);
_AssistantStream_instances.add(this);
_AssistantStream_runStepSnapshots.set(this, /* @__PURE__ */ Object.create(null));
_AssistantStream_runStepIDOwners.set(this, /* @__PURE__ */ new Map());
_AssistantStream_activeRunStepID.set(this, void 0);
_AssistantStream_messageSnapshots.set(this, /* @__PURE__ */ Object.create(null));
_AssistantStream_messageIDOwners.set(this, /* @__PURE__ */ new Map());
_AssistantStream_messageSnapshot.set(this, void 0);
_AssistantStream_activeMessageID.set(this, void 0);
_AssistantStream_finalRun.set(this, void 0);
_AssistantStream_currentContentIndex.set(this, void 0);
_AssistantStream_currentContent.set(this, void 0);
_AssistantStream_currentToolCallIndex.set(this, void 0);
_AssistantStream_currentToolCall.set(this, void 0);
_AssistantStream_currentEvent.set(this, void 0);
_AssistantStream_currentRunSnapshot.set(this, void 0);
_AssistantStream_currentRunStepSnapshot.set(this, void 0);
}
/** Iterates over cloned raw assistant events; stopping early aborts the underlying request. */
[(_AssistantStream_runStepSnapshots = /* @__PURE__ */ new WeakMap(), _AssistantStream_runStepIDOwners = /* @__PURE__ */ new WeakMap(), _AssistantStream_activeRunStepID = /* @__PURE__ */ new WeakMap(), _AssistantStream_messageSnapshots = /* @__PURE__ */ new WeakMap(), _AssistantStream_messageIDOwners = /* @__PURE__ */ new WeakMap(), _AssistantStream_messageSnapshot = /* @__PURE__ */ new WeakMap(), _AssistantStream_activeMessageID = /* @__PURE__ */ new WeakMap(), _AssistantStream_finalRun = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentContentIndex = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentContent = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentToolCallIndex = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentToolCall = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentEvent = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentRunSnapshot = /* @__PURE__ */ new WeakMap(), _AssistantStream_currentRunStepSnapshot = /* @__PURE__ */ new WeakMap(), _AssistantStream_instances = /* @__PURE__ */ new WeakSet(), Symbol.asyncIterator)]() {
return this._createIterator((push) => {
const onEvent = (event) => push(structuredClone(event));
this.on("event", onEvent);
return () => this.off("event", onEvent);
}, { onReturn: () => this.abort() });
}
/** Restores an assistant stream from events serialized by `toReadableStream()`. */
static fromReadableStream(stream2) {
const runner = new _AssistantStream();
runner._run(() => runner._fromReadableStream(stream2));
return runner;
}
async _fromReadableStream(readableStream, options) {
this._listenForAbort(options?.signal);
this._connected();
const stream2 = Stream.fromReadableStream(readableStream, this.controller);
for await (const event of stream2) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event);
}
if (stream2.controller.signal?.aborted) {
throw this._userAbortError();
}
return this._addRun(__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this));
}
/** Serializes assistant events into a readable stream for transfer to another runtime. */
toReadableStream() {
const stream2 = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
return stream2.toReadableStream();
}
/** Submits tool outputs and starts streaming the continuation of an existing assistant run. */
static createToolAssistantStream(runId, runs, params, options) {
const runner = new _AssistantStream();
runner._run(() => runner._runToolAssistantStream(runId, runs, params, {
...options,
__metadata: { ...options?.__metadata, helperMethod: "stream" }
}));
return runner;
}
async _createToolAssistantStream(run2, runId, params, options) {
this._listenForAbort(options?.signal);
const body = { ...params, stream: true };
const stream2 = await run2.submitToolOutputs(runId, body, {
...options,
signal: this.controller.signal
});
this._connected();
for await (const event of stream2) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event);
}
if (stream2.controller.signal?.aborted) {
throw this._userAbortError();
}
return this._addRun(__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this));
}
/** Creates an assistant thread and starts streaming its newly created run. */
static createThreadAssistantStream(params, thread, options) {
const runner = new _AssistantStream();
runner._run(() => runner._threadAssistantStream(params, thread, {
...options,
__metadata: { ...options?.__metadata, helperMethod: "stream" }
}));
return runner;
}
/** Creates a run on an existing assistant thread and starts streaming its events. */
static createAssistantStream(threadId, runs, params, options) {
const runner = new _AssistantStream();
runner._run(() => runner._runAssistantStream(threadId, runs, params, {
...options,
__metadata: { ...options?.__metadata, helperMethod: "stream" }
}));
return runner;
}
/** Returns the most recent raw event, or `undefined` before any event arrives. */
currentEvent() {
markAssistantStreamValueExternallyMutable(__classPrivateFieldGet(this, _AssistantStream_currentEvent, "f"));
return __classPrivateFieldGet(this, _AssistantStream_currentEvent, "f");
}
/** Returns the latest run snapshot, or `undefined` before a run event arrives. */
currentRun() {
markAssistantStreamValueExternallyMutable(__classPrivateFieldGet(this, _AssistantStream_currentRunSnapshot, "f"));
return __classPrivateFieldGet(this, _AssistantStream_currentRunSnapshot, "f");
}
/** Returns the message currently being accumulated, or `undefined` before message creation. */
currentMessageSnapshot() {
markAssistantStreamValueExternallyMutable(__classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f"));
return __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f");
}
/** Returns the run step currently being accumulated, or `undefined` before a step begins. */
currentRunStepSnapshot() {
markAssistantStreamValueExternallyMutable(__classPrivateFieldGet(this, _AssistantStream_currentRunStepSnapshot, "f"));
return __classPrivateFieldGet(this, _AssistantStream_currentRunStepSnapshot, "f");
}
/** Waits for successful completion and returns the final snapshot of every observed run step. */
async finalRunSteps() {
await this.done();
return Object.values(__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f"));
}
/**
* Waits for successful completion and returns the final snapshot of every observed message.
* Terminal message events replace accumulated snapshots without mutating earlier snapshots.
*/
async finalMessages() {
await this.done();
return Object.values(__classPrivateFieldGet(this, _AssistantStream_messageSnapshots, "f"));
}
/** Waits for completion and returns the final run, or rejects if no terminal run was received. */
async finalRun() {
await this.done();
if (!__classPrivateFieldGet(this, _AssistantStream_finalRun, "f")) {
throw new Error("Final run was not received.");
}
return __classPrivateFieldGet(this, _AssistantStream_finalRun, "f");
}
async _createThreadAssistantStream(thread, params, options) {
this._listenForAbort(options?.signal);
const body = { ...params, stream: true };
const stream2 = await thread.createAndRun(body, { ...options, signal: this.controller.signal });
this._connected();
for await (const event of stream2) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event);
}
if (stream2.controller.signal?.aborted) {
throw this._userAbortError();
}
return this._addRun(__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this));
}
async _createAssistantStream(run2, threadId, params, options) {
this._listenForAbort(options?.signal);
const body = { ...params, stream: true };
const stream2 = await run2.create(threadId, body, { ...options, signal: this.controller.signal });
this._connected();
for await (const event of stream2) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event);
}
if (stream2.controller.signal?.aborted) {
throw this._userAbortError();
}
return this._addRun(__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this));
}
/**
* Applies an assistant delta to its mutable snapshot, concatenating text and
* merging nested objects and indexed array entries.
*/
static accumulateDelta(acc, delta) {
return accumulateAssistantStreamDelta(acc, delta);
}
_addRun(run2) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "run", run2);
return run2;
}
async _threadAssistantStream(params, thread, options) {
return await this._createThreadAssistantStream(thread, params, options);
}
async _runAssistantStream(threadId, runs, params, options) {
return await this._createAssistantStream(runs, threadId, params, options);
}
async _runToolAssistantStream(runId, runs, params, options) {
return await this._createToolAssistantStream(runs, runId, params, options);
}
};
_AssistantStream_addEvent = function _AssistantStream_addEvent2(event) {
if (this.ended) {
return;
}
const { event: stableEvent, exposedEvent } = stabilizeAssistantStreamEvent(event);
let messageID;
let messageData;
let runStepID;
let runStepData;
switch (stableEvent.event) {
case "thread.message.created":
case "thread.message.in_progress":
case "thread.message.delta":
case "thread.message.completed":
case "thread.message.incomplete": {
messageID = __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_validateMessageEvent).call(this, stableEvent);
messageData = stableEvent.data;
break;
}
case "thread.run.step.created":
case "thread.run.step.in_progress":
case "thread.run.step.delta":
case "thread.run.step.completed":
case "thread.run.step.failed":
case "thread.run.step.cancelled":
case "thread.run.step.expired": {
runStepID = __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_validateRunStepEvent).call(this, stableEvent);
runStepData = stableEvent.data;
break;
}
}
__classPrivateFieldSet(this, _AssistantStream_currentEvent, exposedEvent, "f");
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_handleEvent).call(this, exposedEvent);
if (messageID !== void 0 && messageData !== void 0) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_reserveMessageAlias).call(this, messageData, messageID);
}
if (runStepID !== void 0 && runStepData !== void 0) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_reserveRunStepAlias).call(this, runStepData, runStepID);
}
if (runStepID === void 0 && __classPrivateFieldGet(this, _AssistantStream_activeRunStepID, "f") !== void 0 && __classPrivateFieldGet(this, _AssistantStream_currentRunStepSnapshot, "f")) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_reserveRunStepAlias).call(this, __classPrivateFieldGet(this, _AssistantStream_currentRunStepSnapshot, "f"), __classPrivateFieldGet(this, _AssistantStream_activeRunStepID, "f"));
}
switch (stableEvent.event) {
case "thread.created": {
break;
}
case "thread.run.created":
case "thread.run.queued":
case "thread.run.in_progress":
case "thread.run.requires_action":
case "thread.run.completed":
case "thread.run.incomplete":
case "thread.run.failed":
case "thread.run.cancelling":
case "thread.run.cancelled":
case "thread.run.expired": {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_handleRun).call(this, stableEvent);
break;
}
case "thread.run.step.created":
case "thread.run.step.in_progress":
case "thread.run.step.delta":
case "thread.run.step.completed":
case "thread.run.step.failed":
case "thread.run.step.cancelled":
case "thread.run.step.expired": {
if (runStepID === void 0) {
throw new OpenAIError("Received assistant run-step event without a canonical run-step ID");
}
const activeRunStep = __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[runStepID];
if (activeRunStep) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_reserveRunStepAlias).call(this, activeRunStep, runStepID);
}
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_handleRunStep).call(this, stableEvent, runStepID);
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_reserveRunStepAlias).call(this, stableEvent.data, runStepID);
const retainedRunStep = __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[runStepID];
if (retainedRunStep) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_reserveRunStepAlias).call(this, retainedRunStep, runStepID);
}
break;
}
case "thread.message.created":
case "thread.message.in_progress":
case "thread.message.delta":
case "thread.message.completed":
case "thread.message.incomplete": {
if (messageID !== void 0 && __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_reserveMessageAlias).call(this, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f"), messageID);
}
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_handleMessage).call(this, stableEvent);
if (messageID !== void 0) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_reserveMessageAlias).call(this, stableEvent.data, messageID);
const retainedMessage = __classPrivateFieldGet(this, _AssistantStream_messageSnapshots, "f")[messageID];
if (retainedMessage) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_reserveMessageAlias).call(this, retainedMessage, messageID);
}
}
break;
}
case "error": {
throw new APIError(void 0, stableEvent.data, void 0, void 0);
}
default: {
assertNever2(stableEvent);
}
}
}, _AssistantStream_endRequest = function _AssistantStream_endRequest2() {
if (this.ended) {
throw new OpenAIError(`stream has ended, this shouldn't happen`);
}
if (!__classPrivateFieldGet(this, _AssistantStream_finalRun, "f")) {
throw new Error("Final run has not been received");
}
return __classPrivateFieldGet(this, _AssistantStream_finalRun, "f");
}, _AssistantStream_validateRunStepEvent = function _AssistantStream_validateRunStepEvent2(event) {
const descriptor = Object.getOwnPropertyDescriptor(event.data, "id");
const runStepID = descriptor && "value" in descriptor ? descriptor.value : void 0;
if (typeof runStepID !== "string" || runStepID.length === 0) {
throw new OpenAIError("Received assistant run-step event with an invalid run-step ID");
}
if (event.event === "thread.run.step.delta") {
const delta = event.data.delta;
if (delta && hasOwn(delta, "id")) {
throw new OpenAIError("Run-step deltas must not contain an id field");
}
}
if (event.event === "thread.run.step.created") {
if (__classPrivateFieldGet(this, _AssistantStream_activeRunStepID, "f") !== void 0) {
throw new OpenAIError(`Received run-step creation for "${runStepID}" before the active run step "${__classPrivateFieldGet(this, _AssistantStream_activeRunStepID, "f")}" reached a terminal state`);
}
if (hasOwn(__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f"), runStepID) || __classPrivateFieldGet(this, _AssistantStream_runStepIDOwners, "f").has(runStepID)) {
throw new OpenAIError(`Received run-step creation for run step "${runStepID}", which has already been created`);
}
__classPrivateFieldSet(this, _AssistantStream_activeRunStepID, runStepID, "f");
__classPrivateFieldGet(this, _AssistantStream_runStepIDOwners, "f").set(runStepID, runStepID);
return runStepID;
}
if (__classPrivateFieldGet(this, _AssistantStream_activeRunStepID, "f") !== void 0) {
if (runStepID !== __classPrivateFieldGet(this, _AssistantStream_activeRunStepID, "f")) {
throw new OpenAIError(`Received ${event.event} for run step "${runStepID}", which does not match the active run step "${__classPrivateFieldGet(this, _AssistantStream_activeRunStepID, "f")}"`);
}
return runStepID;
}
if (event.event === "thread.run.step.delta") {
if (!hasOwn(__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f"), runStepID)) {
throw new OpenAIError("Received a RunStepDelta before creation of a snapshot");
}
throw new OpenAIError(`Received run-step delta for "${runStepID}" with no active run step`);
}
if (hasOwn(__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f"), runStepID) || __classPrivateFieldGet(this, _AssistantStream_runStepIDOwners, "f").has(runStepID)) {
throw new OpenAIError(`Received run-step event for run step "${runStepID}", which has already been created`);
}
__classPrivateFieldGet(this, _AssistantStream_runStepIDOwners, "f").set(runStepID, runStepID);
if (event.event === "thread.run.step.in_progress") {
__classPrivateFieldSet(this, _AssistantStream_activeRunStepID, runStepID, "f");
}
return runStepID;
}, _AssistantStream_reserveRunStepAlias = function _AssistantStream_reserveRunStepAlias2(data, canonicalID) {
const descriptor = Object.getOwnPropertyDescriptor(data, "id");
const runStepID = descriptor && "value" in descriptor ? descriptor.value : void 0;
if (typeof runStepID !== "string" || runStepID.length === 0) {
throw new OpenAIError("Received assistant run-step event with an invalid run-step ID");
}
const owner = __classPrivateFieldGet(this, _AssistantStream_runStepIDOwners, "f").get(runStepID);
if (owner !== void 0 && owner !== canonicalID) {
throw new OpenAIError(`Received run-step creation for run step "${runStepID}", which has already been created`);
}
__classPrivateFieldGet(this, _AssistantStream_runStepIDOwners, "f").set(runStepID, canonicalID);
}, _AssistantStream_validateMessageEvent = function _AssistantStream_validateMessageEvent2(event) {
const descriptor = Object.getOwnPropertyDescriptor(event.data, "id");
const messageID = descriptor && "value" in descriptor ? descriptor.value : void 0;
if (typeof messageID !== "string" || messageID.length === 0) {
throw new OpenAIError("Received assistant message event with an invalid message ID");
}
if (event.event === "thread.message.created") {
if (__classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")) {
throw new OpenAIError(`Received message creation for "${messageID}" before the active message "${__classPrivateFieldGet(this, _AssistantStream_activeMessageID, "f")}" reached a terminal state`);
}
if (hasOwn(__classPrivateFieldGet(this, _AssistantStream_messageSnapshots, "f"), messageID) || __classPrivateFieldGet(this, _AssistantStream_messageIDOwners, "f").has(messageID)) {
throw new OpenAIError(`Received message creation for message "${messageID}", which has already been created`);
}
__classPrivateFieldSet(this, _AssistantStream_activeMessageID, messageID, "f");
__classPrivateFieldGet(this, _AssistantStream_messageIDOwners, "f").set(messageID, messageID);
return messageID;
}
if (!__classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")) {
if (event.event === "thread.message.delta") {
throw new OpenAIError("Received a delta with no existing snapshot (there should be one from message creation)");
}
throw new OpenAIError("Received thread message event with no existing snapshot");
}
if (messageID !== __classPrivateFieldGet(this, _AssistantStream_activeMessageID, "f")) {
throw new OpenAIError(`Received ${event.event} for message "${messageID}", which does not match the active message "${__classPrivateFieldGet(this, _AssistantStream_activeMessageID, "f")}"`);
}
return messageID;
}, _AssistantStream_reserveMessageAlias = function _AssistantStream_reserveMessageAlias2(data, canonicalID) {
const descriptor = Object.getOwnPropertyDescriptor(data, "id");
const messageID = descriptor && "value" in descriptor ? descriptor.value : void 0;
if (typeof messageID !== "string" || messageID.length === 0) {
throw new OpenAIError("Received assistant message event with an invalid message ID");
}
const owner = __classPrivateFieldGet(this, _AssistantStream_messageIDOwners, "f").get(messageID);
if (owner !== void 0 && owner !== canonicalID) {
throw new OpenAIError(`Received message creation for message "${messageID}", which has already been created`);
}
__classPrivateFieldGet(this, _AssistantStream_messageIDOwners, "f").set(messageID, canonicalID);
}, _AssistantStream_handleMessage = function _AssistantStream_handleMessage2(event) {
const [accumulatedMessage, newContent] = __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_accumulateMessage).call(this, event, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f"));
__classPrivateFieldSet(this, _AssistantStream_messageSnapshot, accumulatedMessage, "f");
if (!__classPrivateFieldGet(this, _AssistantStream_activeMessageID, "f")) {
throw new OpenAIError("Received thread message event with no active message ID");
}
__classPrivateFieldGet(this, _AssistantStream_messageSnapshots, "f")[__classPrivateFieldGet(this, _AssistantStream_activeMessageID, "f")] = accumulatedMessage;
for (const content of newContent) {
const snapshotContent = accumulatedMessage.content[content.index];
if (snapshotContent?.type === "text") {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "textCreated", snapshotContent.text);
}
}
switch (event.event) {
case "thread.message.created": {
__classPrivateFieldSet(this, _AssistantStream_currentContentIndex, void 0, "f");
__classPrivateFieldSet(this, _AssistantStream_currentContent, void 0, "f");
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "messageCreated", event.data);
break;
}
case "thread.message.in_progress": {
break;
}
case "thread.message.delta": {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "messageDelta", event.data.delta, accumulatedMessage);
if (event.data.delta.content) {
for (const content of event.data.delta.content) {
if (content.type === "text" && content.text) {
const textDelta = content.text;
const snapshot = accumulatedMessage.content[content.index];
if (snapshot && snapshot.type === "text") {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "textDelta", textDelta, snapshot.text);
} else {
throw new Error("The snapshot associated with this text delta is not text or missing");
}
}
if (content.index !== __classPrivateFieldGet(this, _AssistantStream_currentContentIndex, "f")) {
if (__classPrivateFieldGet(this, _AssistantStream_currentContent, "f")) {
switch (__classPrivateFieldGet(this, _AssistantStream_currentContent, "f").type) {
case "text": {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "textDone", __classPrivateFieldGet(this, _AssistantStream_currentContent, "f").text, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f"));
break;
}
case "image_file": {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "imageFileDone", __classPrivateFieldGet(this, _AssistantStream_currentContent, "f").image_file, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f"));
break;
}
}
}
__classPrivateFieldSet(this, _AssistantStream_currentContentIndex, content.index, "f");
}
__classPrivateFieldSet(this, _AssistantStream_currentContent, accumulatedMessage.content[content.index], "f");
}
}
break;
}
case "thread.message.completed":
case "thread.message.incomplete": {
if (__classPrivateFieldGet(this, _AssistantStream_currentContentIndex, "f") !== void 0) {
const currentContent = event.data.content[__classPrivateFieldGet(this, _AssistantStream_currentContentIndex, "f")];
if (currentContent) {
switch (currentContent.type) {
case "image_file": {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "imageFileDone", currentContent.image_file, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f"));
break;
}
case "text": {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "textDone", currentContent.text, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f"));
break;
}
}
}
}
if (__classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "messageDone", event.data);
}
__classPrivateFieldSet(this, _AssistantStream_currentContentIndex, void 0, "f");
__classPrivateFieldSet(this, _AssistantStream_currentContent, void 0, "f");
__classPrivateFieldSet(this, _AssistantStream_messageSnapshot, void 0, "f");
__classPrivateFieldSet(this, _AssistantStream_activeMessageID, void 0, "f");
}
}
}, _AssistantStream_handleRunStep = function _AssistantStream_handleRunStep2(event, runStepID) {
const accumulatedRunStep = __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_accumulateRunStep).call(this, event, runStepID);
__classPrivateFieldSet(this, _AssistantStream_currentRunStepSnapshot, accumulatedRunStep, "f");
switch (event.event) {
case "thread.run.step.created": {
__classPrivateFieldSet(this, _AssistantStream_currentToolCallIndex, void 0, "f");
__classPrivateFieldSet(this, _AssistantStream_currentToolCall, void 0, "f");
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "runStepCreated", event.data);
break;
}
case "thread.run.step.delta": {
const delta = event.data.delta;
if (delta.step_details && delta.step_details.type === "tool_calls" && delta.step_details.tool_calls && accumulatedRunStep.step_details.type === "tool_calls") {
for (const toolCall of delta.step_details.tool_calls) {
if (toolCall.index === __classPrivateFieldGet(this, _AssistantStream_currentToolCallIndex, "f")) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "toolCallDelta", toolCall, accumulatedRunStep.step_details.tool_calls[toolCall.index]);
} else {
if (__classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "toolCallDone", __classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f"));
}
__classPrivateFieldSet(this, _AssistantStream_currentToolCallIndex, toolCall.index, "f");
__classPrivateFieldSet(this, _AssistantStream_currentToolCall, accumulatedRunStep.step_details.tool_calls[toolCall.index], "f");
if (__classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "toolCallCreated", __classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f"));
}
}
}
}
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "runStepDelta", event.data.delta, accumulatedRunStep);
break;
}
case "thread.run.step.completed":
case "thread.run.step.failed":
case "thread.run.step.cancelled":
case "thread.run.step.expired": {
__classPrivateFieldSet(this, _AssistantStream_currentRunStepSnapshot, void 0, "f");
__classPrivateFieldSet(this, _AssistantStream_activeRunStepID, void 0, "f");
const details = event.data.step_details;
if (details.type === "tool_calls" && __classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "toolCallDone", __classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f"));
}
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "runStepDone", event.data, accumulatedRunStep);
__classPrivateFieldSet(this, _AssistantStream_currentToolCallIndex, void 0, "f");
__classPrivateFieldSet(this, _AssistantStream_currentToolCall, void 0, "f");
break;
}
case "thread.run.step.in_progress": {
break;
}
}
}, _AssistantStream_emitExposed = function _AssistantStream_emitExposed2(event, ...args) {
if (this._hasListeners(event)) {
for (const value2 of args) {
markAssistantStreamValueExternallyMutable(value2);
}
}
this._emit(event, ...args);
}, _AssistantStream_handleEvent = function _AssistantStream_handleEvent2(event) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "event", event);
}, _AssistantStream_accumulateRunStep = function _AssistantStream_accumulateRunStep2(event, runStepID) {
switch (event.event) {
case "thread.run.step.created": {
__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[runStepID] = event.data;
return event.data;
}
case "thread.run.step.delta": {
const snapshot = __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[runStepID];
if (!snapshot) {
throw new Error("Received a RunStepDelta before creation of a snapshot");
}
const delta = event.data.delta;
if (delta) {
if (hasOwn(delta, "id")) {
throw new OpenAIError("Run-step deltas must not contain an id field");
}
const accumulated = accumulateAssistantStreamDelta(snapshot, delta, true);
__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[runStepID] = accumulated;
}
return __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[runStepID];
}
case "thread.run.step.completed":
case "thread.run.step.failed":
case "thread.run.step.cancelled":
case "thread.run.step.expired":
case "thread.run.step.in_progress": {
__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[runStepID] = event.data;
break;
}
}
if (__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[runStepID]) {
return __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[runStepID];
}
throw new Error("No snapshot available");
}, _AssistantStream_accumulateMessage = function _AssistantStream_accumulateMessage2(event, snapshot) {
const newContent = [];
switch (event.event) {
case "thread.message.created": {
return [event.data, newContent];
}
case "thread.message.delta": {
if (!snapshot) {
throw new Error("Received a delta with no existing snapshot (there should be one from message creation)");
}
const data = event.data;
if (data.delta.content) {
assertSafeAssistantStreamDelta(data.delta);
const cacheArrays = !isAssistantStreamValueExternallyMutable(snapshot);
const commitProjection = createAssistantStreamArrayDeltaCommit(snapshot.content, data.delta.content, "content", cacheArrays);
for (const contentElement of data.delta.content) {
if (hasOwn(snapshot.content, contentElement.index)) {
const currentContent = snapshot.content[contentElement.index];
snapshot.content[contentElement.index] = __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_accumulateContent).call(this, contentElement, currentContent, cacheArrays);
} else {
defineAssistantStreamArrayEntry(snapshot.content, contentElement.index, contentElement);
newContent.push(contentElement);
}
}
commitProjection();
}
return [snapshot, newContent];
}
case "thread.message.in_progress":
case "thread.message.completed":
case "thread.message.incomplete": {
if (snapshot) {
return [event.event === "thread.message.in_progress" ? snapshot : event.data, newContent];
}
throw new Error("Received thread message event with no existing snapshot");
}
}
throw new Error("Tried to accumulate a non-message event");
}, _AssistantStream_accumulateContent = function _AssistantStream_accumulateContent2(contentElement, currentContent, cacheArrays) {
return accumulateAssistantStreamDelta(currentContent, contentElement, cacheArrays);
}, _AssistantStream_handleRun = function _AssistantStream_handleRun2(event) {
__classPrivateFieldSet(this, _AssistantStream_currentRunSnapshot, event.data, "f");
switch (event.event) {
case "thread.run.created": {
break;
}
case "thread.run.queued": {
break;
}
case "thread.run.in_progress": {
break;
}
case "thread.run.requires_action":
case "thread.run.cancelled":
case "thread.run.failed":
case "thread.run.completed":
case "thread.run.expired":
case "thread.run.incomplete": {
__classPrivateFieldSet(this, _AssistantStream_finalRun, event.data, "f");
if (__classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")) {
__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_emitExposed).call(this, "toolCallDone", __classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f"));
}
__classPrivateFieldSet(this, _AssistantStream_currentToolCallIndex, void 0, "f");
__classPrivateFieldSet(this, _AssistantStream_currentToolCall, void 0, "f");
break;
}
case "thread.run.cancelling": {
break;
}
}
};
}
});
// node_modules/openai/lib/polling.mjs
function sleepUntilAborted(milliseconds, signal) {
return new Promise((resolve2, reject2) => {
let timer;
let registered;
let settled = false;
const removeAbortListener = (listener) => {
try {
signal.removeEventListener("abort", listener);
} catch {
}
};
const cleanup = () => {
if (timer !== void 0) {
clearTimeout(timer);
timer = void 0;
}
if (registered) {
const listener = registered;
registered = void 0;
removeAbortListener(listener);
}
};
const abort = () => {
if (settled) {
return;
}
settled = true;
cleanup();
try {
const error = new APIUserAbortError();
Object.defineProperty(error, "cause", {
value: signal.reason,
writable: true,
configurable: true
});
reject2(error);
} catch (error) {
reject2(error);
}
};
if (signal.aborted) {
abort();
return;
}
timer = setTimeout(() => {
if (settled) {
return;
}
settled = true;
cleanup();
resolve2();
}, milliseconds);
registered = abort;
try {
signal.addEventListener("abort", abort, { once: true });
if (settled) {
removeAbortListener(abort);
} else if (signal.aborted) {
abort();
}
} catch (error) {
if (settled) {
removeAbortListener(abort);
} else {
settled = true;
cleanup();
reject2(error);
}
}
});
}
async function pollWithResponse(retrieve, intermediateStatuses, terminalStatuses, options) {
const headers = buildHeaders([
options?.headers,
{
"X-Stainless-Poll-Helper": "true",
"X-Stainless-Custom-Poll-Interval": options?.pollIntervalMs?.toString() ?? void 0
}
]);
while (true) {
const { data, response } = await retrieve(headers).withResponse();
const { status } = data;
if (intermediateStatuses.includes(status)) {
let sleepInterval = 5e3;
const pollIntervalMs = options?.pollIntervalMs;
if (pollIntervalMs || pollIntervalMs === 0) {
sleepInterval = pollIntervalMs;
} else {
const headerInterval = response.headers.get("openai-poll-after-ms");
if (headerInterval) {
const headerIntervalMs = Number.parseInt(headerInterval);
if (!Number.isNaN(headerIntervalMs)) {
sleepInterval = headerIntervalMs;
}
}
}
const signal = options && Object.prototype.propertyIsEnumerable.call(options, "signal") ? options.signal : void 0;
await (signal ? sleepUntilAborted(sleepInterval, signal) : sleep(sleepInterval));
} else if (terminalStatuses.includes(status)) {
return data;
}
}
}
var init_polling = __esm({
"node_modules/openai/lib/polling.mjs"() {
init_error();
init_headers2();
init_sleep();
}
});
// node_modules/openai/lib/assistant-run-polling.mjs
function pollAssistantRun(resource, runID, params, options) {
return pollWithResponse((headers) => resource.retrieve(runID, params, {
...options,
headers: { ...options?.headers, ...headers }
}), ["queued", "in_progress", "cancelling"], ["requires_action", "incomplete", "cancelled", "completed", "failed", "expired"], options);
}
var init_assistant_run_polling = __esm({
"node_modules/openai/lib/assistant-run-polling.mjs"() {
init_polling();
}
});
// node_modules/openai/resources/beta/threads/runs/runs.mjs
var Runs;
var init_runs = __esm({
"node_modules/openai/resources/beta/threads/runs/runs.mjs"() {
init_resource();
init_steps();
init_steps();
init_pagination();
init_headers2();
init_AssistantStream();
init_assistant_run_polling();
init_path();
Runs = class extends APIResource {
constructor() {
super(...arguments);
this.steps = new Steps(this._client);
}
create(threadID, params, options) {
const { include, ...body } = params;
return this._client.post(path`/threads/${threadID}/runs`, {
query: { include },
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
stream: params.stream ?? false,
__synthesizeEventData: true,
__security: { bearerAuth: true }
});
}
/**
* Retrieves a run.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
retrieve(runID, params, options) {
const { thread_id } = params;
return this._client.get(path`/threads/${thread_id}/runs/${runID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Modifies a run.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
update(runID, params, options) {
const { thread_id, ...body } = params;
return this._client.post(path`/threads/${thread_id}/runs/${runID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Returns a list of runs belonging to a thread.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
list(threadID, query = {}, options) {
return this._client.getAPIList(path`/threads/${threadID}/runs`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Cancels a run that is `in_progress`.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
cancel(runID, params, options) {
const { thread_id } = params;
return this._client.post(path`/threads/${thread_id}/runs/${runID}/cancel`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* A helper to create a run an poll for a terminal state. More information on Run
* lifecycles can be found here:
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
*/
async createAndPoll(threadId, body, options) {
const run2 = await this.create(threadId, body, options);
return await this.poll(run2.id, { thread_id: threadId }, options);
}
/**
* Create a Run stream
*
* @deprecated use `stream` instead
*/
createAndStream(threadId, body, options) {
return AssistantStream.createAssistantStream(threadId, this._client.beta.threads.runs, body, options);
}
/**
* A helper to poll a run status until it reaches a terminal state. More
* information on Run lifecycles can be found here:
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
*/
async poll(runId, params, options) {
return await pollAssistantRun(this, runId, params, options);
}
/**
* Create a Run stream
*/
stream(threadId, body, options) {
return AssistantStream.createAssistantStream(threadId, this._client.beta.threads.runs, body, options);
}
submitToolOutputs(runID, params, options) {
const { thread_id, ...body } = params;
return this._client.post(path`/threads/${thread_id}/runs/${runID}/submit_tool_outputs`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
stream: params.stream ?? false,
__synthesizeEventData: true,
__security: { bearerAuth: true }
});
}
/**
* A helper to submit a tool output to a run and poll for a terminal run state.
* More information on Run lifecycles can be found here:
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
*/
async submitToolOutputsAndPoll(runId, params, options) {
const run2 = await this.submitToolOutputs(runId, params, options);
return await this.poll(run2.id, params, options);
}
/**
* Submit the tool outputs from a previous run and stream the run to a terminal
* state. More information on Run lifecycles can be found here:
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
*/
submitToolOutputsStream(runId, params, options) {
return AssistantStream.createToolAssistantStream(runId, this._client.beta.threads.runs, params, options);
}
};
Runs.Steps = Steps;
}
});
// node_modules/openai/resources/beta/threads/threads.mjs
var Threads2;
var init_threads2 = __esm({
"node_modules/openai/resources/beta/threads/threads.mjs"() {
init_resource();
init_messages2();
init_messages2();
init_runs();
init_runs();
init_headers2();
init_AssistantStream();
init_path();
Threads2 = class extends APIResource {
constructor() {
super(...arguments);
this.runs = new Runs(this._client);
this.messages = new Messages2(this._client);
}
/**
* Create a thread.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
create(body = {}, options) {
return this._client.post("/threads", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieves a thread.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
retrieve(threadID, options) {
return this._client.get(path`/threads/${threadID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Modifies a thread.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
update(threadID, body, options) {
return this._client.post(path`/threads/${threadID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Delete a thread.
*
* @deprecated The Assistants API is deprecated in favor of the Responses API
*/
delete(threadID, options) {
return this._client.delete(path`/threads/${threadID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
createAndRun(body, options) {
return this._client.post("/threads/runs", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
stream: body.stream ?? false,
__synthesizeEventData: true,
__security: { bearerAuth: true }
});
}
/**
* A helper to create a thread, start a run and then poll for a terminal state.
* More information on Run lifecycles can be found here:
* https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps
*/
async createAndRunPoll(body, options) {
const run2 = await this.createAndRun(body, options);
return await this.runs.poll(run2.id, { thread_id: run2.thread_id }, options);
}
/**
* Create a thread and stream the run back
*/
createAndRunStream(body, options) {
return AssistantStream.createThreadAssistantStream(body, this._client.beta.threads, options);
}
};
Threads2.Runs = Runs;
Threads2.Messages = Messages2;
}
});
// node_modules/openai/resources/beta/beta.mjs
var Beta;
var init_beta = __esm({
"node_modules/openai/resources/beta/beta.mjs"() {
init_resource();
init_assistants();
init_assistants();
init_realtime();
init_realtime();
init_agents();
init_agents();
init_chatkit();
init_chatkit();
init_responses();
init_responses();
init_threads2();
init_threads2();
Beta = class extends APIResource {
constructor() {
super(...arguments);
this.realtime = new Realtime(this._client);
this.agents = new Agents(this._client);
this.responses = new Responses(this._client);
this.chatkit = new ChatKit(this._client);
this.assistants = new Assistants(this._client);
this.threads = new Threads2(this._client);
}
};
Beta.Realtime = Realtime;
Beta.Agents = Agents;
Beta.Responses = Responses;
Beta.ChatKit = ChatKit;
Beta.Assistants = Assistants;
Beta.Threads = Threads2;
}
});
// node_modules/openai/resources/completions.mjs
var Completions2;
var init_completions3 = __esm({
"node_modules/openai/resources/completions.mjs"() {
init_resource();
Completions2 = class extends APIResource {
create(body, options) {
return this._client.post("/completions", {
body,
...options,
stream: body.stream ?? false,
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/containers/files/content.mjs
var Content;
var init_content = __esm({
"node_modules/openai/resources/containers/files/content.mjs"() {
init_resource();
init_headers2();
init_path();
Content = class extends APIResource {
/**
* Retrieve Container File Content
*/
retrieve(fileID, params, options) {
const { container_id } = params;
return this._client.get(path`/containers/${container_id}/files/${fileID}/content`, {
...options,
headers: buildHeaders([{ Accept: "application/binary" }, options?.headers]),
__security: { bearerAuth: true },
__binaryResponse: true
});
}
};
}
});
// node_modules/openai/resources/containers/files/files.mjs
var Files2;
var init_files2 = __esm({
"node_modules/openai/resources/containers/files/files.mjs"() {
init_resource();
init_content();
init_content();
init_pagination();
init_headers2();
init_uploads();
init_path();
Files2 = class extends APIResource {
constructor() {
super(...arguments);
this.content = new Content(this._client);
}
/**
* Create a Container File
*
* You can send either a multipart/form-data request with the raw file content, or
* a JSON request with a file ID.
*/
create(containerID, body, options) {
return this._client.post(path`/containers/${containerID}/files`, maybeMultipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
/**
* Retrieve Container File
*/
retrieve(fileID, params, options) {
const { container_id } = params;
return this._client.get(path`/containers/${container_id}/files/${fileID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* List Container files
*/
list(containerID, query = {}, options) {
return this._client.getAPIList(path`/containers/${containerID}/files`, CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Delete Container File
*/
delete(fileID, params, options) {
const { container_id } = params;
return this._client.delete(path`/containers/${container_id}/files/${fileID}`, {
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
Files2.Content = Content;
}
});
// node_modules/openai/resources/containers/containers.mjs
var Containers;
var init_containers = __esm({
"node_modules/openai/resources/containers/containers.mjs"() {
init_resource();
init_files2();
init_files2();
init_pagination();
init_headers2();
init_path();
Containers = class extends APIResource {
constructor() {
super(...arguments);
this.files = new Files2(this._client);
}
/**
* Create Container
*/
create(body, options) {
return this._client.post("/containers", { body, ...options, __security: { bearerAuth: true } });
}
/**
* Retrieve Container
*/
retrieve(containerID, options) {
return this._client.get(path`/containers/${containerID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* List Containers
*/
list(query = {}, options) {
return this._client.getAPIList("/containers", CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Delete Container
*/
delete(containerID, options) {
return this._client.delete(path`/containers/${containerID}`, {
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
Containers.Files = Files2;
}
});
// node_modules/openai/resources/content-provenance-checks.mjs
var ContentProvenanceChecks;
var init_content_provenance_checks = __esm({
"node_modules/openai/resources/content-provenance-checks.mjs"() {
init_resource();
init_uploads();
ContentProvenanceChecks = class extends APIResource {
/**
* Check whether an image or audio file contains known OpenAI provenance signals.
* [Learn more about content provenance](https://developers.openai.com/api/docs/guides/content-provenance).
*
* If `not_detected`, it means the tool did not find supported signals in the
* uploaded file. The content could still have been generated by OpenAI if the
* metadata was stripped or has evidence of tampering, the watermark was degraded,
* it comes from a legacy generation model, or it was created before provenance
* signals were available. Content could also still be AI-generated by another
* company's model, which the tool currently does not detect.
*/
create(body, options) {
return this._client.post("/content_provenance_checks", multipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
};
}
});
// node_modules/openai/resources/conversations/items.mjs
var Items4;
var init_items4 = __esm({
"node_modules/openai/resources/conversations/items.mjs"() {
init_resource();
init_pagination();
init_path();
Items4 = class extends APIResource {
/**
* Create items in a conversation with the given ID.
*/
create(conversationID, params, options) {
const { include, ...body } = params;
return this._client.post(path`/conversations/${conversationID}/items`, {
query: { include },
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* Get a single item from a conversation with the given IDs.
*/
retrieve(itemID, params, options) {
const { conversation_id, ...query } = params;
return this._client.get(path`/conversations/${conversation_id}/items/${itemID}`, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* List all items for a conversation with the given ID.
*/
list(conversationID, query = {}, options) {
return this._client.getAPIList(path`/conversations/${conversationID}/items`, ConversationCursorPage, { query, ...options, __security: { bearerAuth: true } });
}
/**
* Delete an item from a conversation with the given IDs.
*/
delete(itemID, params, options) {
const { conversation_id } = params;
return this._client.delete(path`/conversations/${conversation_id}/items/${itemID}`, {
...options,
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/conversations/conversations.mjs
var Conversations;
var init_conversations = __esm({
"node_modules/openai/resources/conversations/conversations.mjs"() {
init_resource();
init_items4();
init_items4();
init_path();
Conversations = class extends APIResource {
constructor() {
super(...arguments);
this.items = new Items4(this._client);
}
/**
* Create a conversation.
*/
create(body = {}, options) {
return this._client.post("/conversations", { body, ...options, __security: { bearerAuth: true } });
}
/**
* Get a conversation
*/
retrieve(conversationID, options) {
return this._client.get(path`/conversations/${conversationID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Update a conversation
*/
update(conversationID, body, options) {
return this._client.post(path`/conversations/${conversationID}`, {
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* Delete a conversation. Items in the conversation will not be deleted.
*/
delete(conversationID, options) {
return this._client.delete(path`/conversations/${conversationID}`, {
...options,
__security: { bearerAuth: true }
});
}
};
Conversations.Items = Items4;
}
});
// node_modules/openai/lib/embeddings.mjs
function createEmbedding(client, body, options) {
const hasUserProvidedEncodingFormat = !!body.encoding_format;
const encodingFormat = hasUserProvidedEncodingFormat ? body.encoding_format : "base64";
if (hasUserProvidedEncodingFormat) {
loggerFor(client).debug("embeddings/user defined encoding_format:", body.encoding_format);
}
const optimizedBody = { ...body, encoding_format: encodingFormat };
const requestOptions = {
body: optimizedBody,
...options,
__security: { bearerAuth: true }
};
const response = client.post("/embeddings", requestOptions);
if (hasUserProvidedEncodingFormat) {
return response;
}
loggerFor(client).debug("embeddings/decoding base64 embeddings from base64");
return response._thenUnwrap((data) => {
const embeddings = data?.data;
if (embeddings !== void 0) {
if (!Array.isArray(embeddings)) {
throw new TypeError("Expected embeddings response data to be an array");
}
const { length } = embeddings;
for (let index = 0; index < length; index += 1) {
if (index in embeddings) {
const embeddingBase64Obj = embeddings[index];
const { embedding } = embeddingBase64Obj;
if (Array.isArray(embedding)) {
continue;
}
embeddingBase64Obj.embedding = toFloat32Array(embedding);
}
}
}
return data;
});
}
var init_embeddings = __esm({
"node_modules/openai/lib/embeddings.mjs"() {
init_utils2();
}
});
// node_modules/openai/resources/embeddings.mjs
var Embeddings;
var init_embeddings2 = __esm({
"node_modules/openai/resources/embeddings.mjs"() {
init_resource();
init_embeddings();
Embeddings = class extends APIResource {
create(body, options) {
return createEmbedding(this._client, body, options);
}
};
}
});
// node_modules/openai/resources/evals/runs/output-items.mjs
var OutputItems;
var init_output_items = __esm({
"node_modules/openai/resources/evals/runs/output-items.mjs"() {
init_resource();
init_pagination();
init_path();
OutputItems = class extends APIResource {
/**
* Get an evaluation run output item by ID.
*/
retrieve(outputItemID, params, options) {
const { eval_id, run_id } = params;
return this._client.get(path`/evals/${eval_id}/runs/${run_id}/output_items/${outputItemID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Get a list of output items for an evaluation run.
*/
list(runID, params, options) {
const { eval_id, ...query } = params;
return this._client.getAPIList(path`/evals/${eval_id}/runs/${runID}/output_items`, CursorPage, { query, ...options, __security: { bearerAuth: true } });
}
};
}
});
// node_modules/openai/resources/evals/runs/runs.mjs
var Runs2;
var init_runs2 = __esm({
"node_modules/openai/resources/evals/runs/runs.mjs"() {
init_resource();
init_output_items();
init_output_items();
init_pagination();
init_path();
Runs2 = class extends APIResource {
constructor() {
super(...arguments);
this.outputItems = new OutputItems(this._client);
}
/**
* Kicks off a new run for a given evaluation, specifying the data source, and what
* model configuration to use to test. The datasource will be validated against the
* schema specified in the config of the evaluation.
*/
create(evalID, body, options) {
return this._client.post(path`/evals/${evalID}/runs`, {
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* Get an evaluation run by ID.
*/
retrieve(runID, params, options) {
const { eval_id } = params;
return this._client.get(path`/evals/${eval_id}/runs/${runID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Get a list of runs for an evaluation.
*/
list(evalID, query = {}, options) {
return this._client.getAPIList(path`/evals/${evalID}/runs`, CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Delete an eval run.
*/
delete(runID, params, options) {
const { eval_id } = params;
return this._client.delete(path`/evals/${eval_id}/runs/${runID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Cancel an ongoing evaluation run.
*/
cancel(runID, params, options) {
const { eval_id } = params;
return this._client.post(path`/evals/${eval_id}/runs/${runID}`, {
...options,
__security: { bearerAuth: true }
});
}
};
Runs2.OutputItems = OutputItems;
}
});
// node_modules/openai/resources/evals/evals.mjs
var Evals;
var init_evals = __esm({
"node_modules/openai/resources/evals/evals.mjs"() {
init_resource();
init_runs2();
init_runs2();
init_pagination();
init_path();
Evals = class extends APIResource {
constructor() {
super(...arguments);
this.runs = new Runs2(this._client);
}
/**
* Create the structure of an evaluation that can be used to test a model's
* performance. An evaluation is a set of testing criteria and the config for a
* data source, which dictates the schema of the data used in the evaluation. After
* creating an evaluation, you can run it on different models and model parameters.
* We support several types of graders and datasources. For more information, see
* the [Evals guide](https://developers.openai.com/api/docs/guides/evals).
*/
create(body, options) {
return this._client.post("/evals", { body, ...options, __security: { bearerAuth: true } });
}
/**
* Get an evaluation by ID.
*/
retrieve(evalID, options) {
return this._client.get(path`/evals/${evalID}`, { ...options, __security: { bearerAuth: true } });
}
/**
* Update certain properties of an evaluation.
*/
update(evalID, body, options) {
return this._client.post(path`/evals/${evalID}`, { body, ...options, __security: { bearerAuth: true } });
}
/**
* List evaluations for a project.
*/
list(query = {}, options) {
return this._client.getAPIList("/evals", CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Delete an evaluation.
*/
delete(evalID, options) {
return this._client.delete(path`/evals/${evalID}`, { ...options, __security: { bearerAuth: true } });
}
};
Evals.Runs = Runs2;
}
});
// node_modules/openai/lib/file-processing.mjs
async function waitForFileProcessing(resource, id, pollInterval, maxWait) {
const terminalStates = /* @__PURE__ */ new Set(["processed", "error", "deleted"]);
const start = performance.now();
let file = await resource.retrieve(id);
while (!file.status || !terminalStates.has(file.status)) {
await sleep(pollInterval);
file = await resource.retrieve(id);
if (performance.now() - start > maxWait) {
throw new APIConnectionTimeoutError({
message: `Giving up on waiting for file ${id} to finish processing after ${maxWait} milliseconds.`
});
}
}
return file;
}
var init_file_processing = __esm({
"node_modules/openai/lib/file-processing.mjs"() {
init_error2();
init_sleep();
}
});
// node_modules/openai/resources/files.mjs
var Files3;
var init_files3 = __esm({
"node_modules/openai/resources/files.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_uploads();
init_file_processing();
init_path();
Files3 = class extends APIResource {
/**
* Upload a file that can be used across various endpoints. Individual files can be
* up to 512 MB, and each project can store up to 2.5 TB of files in total. There
* is no organization-wide storage limit. Uploads to this endpoint are rate-limited
* to 1,000 requests per minute per authenticated user.
*
* - The Assistants API supports files up to 2 million tokens and of specific file
* types. See the
* [Assistants Tools guide](https://developers.openai.com/api/docs/guides/tools)
* for details.
* - The Fine-tuning API only supports `.jsonl` files. The input also has certain
* required formats for fine-tuning
* [chat](https://developers.openai.com/api/docs/guides/supervised-fine-tuning#formatting-your-data)
* or
* [completions](https://developers.openai.com/api/docs/guides/supervised-fine-tuning#formatting-your-data)
* models.
* - The Batch API only supports `.jsonl` files up to 200 MB in size. The input
* also has a specific required
* [format](https://developers.openai.com/api/docs/guides/batch#1-prepare-your-batch-file).
* - For Retrieval or `file_search` ingestion, upload files here first. If you need
* to attach multiple uploaded files to the same vector store, use
* [`/vector_stores/{vector_store_id}/file_batches`](https://developers.openai.com/api/reference/resources/vector_stores/subresources/file_batches/methods/create)
* instead of attaching them one by one. Vector store attachment has separate
* limits from file upload, including 2,000 attached files per minute per
* organization.
*
* Please [contact us](https://help.openai.com/) if you need to increase these
* storage limits.
*/
create(body, options) {
return this._client.post("/files", multipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
/**
* Returns information about a specific file.
*/
retrieve(fileID, options) {
return this._client.get(path`/files/${fileID}`, { ...options, __security: { bearerAuth: true } });
}
/**
* Returns a list of files.
*/
list(query = {}, options) {
return this._client.getAPIList("/files", CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Delete a file and remove it from all vector stores.
*/
delete(fileID, options) {
return this._client.delete(path`/files/${fileID}`, { ...options, __security: { bearerAuth: true } });
}
/**
* Returns a response containing the contents of the specified file.
*/
content(fileID, options) {
return this._client.get(path`/files/${fileID}/content`, {
...options,
headers: buildHeaders([{ Accept: "application/binary" }, options?.headers]),
__security: { bearerAuth: true },
__binaryResponse: true
});
}
/**
* Waits for the given file to be processed, default timeout is 30 mins.
*/
async waitForProcessing(id, { pollInterval = 5e3, maxWait = 30 * 60 * 1e3 } = {}) {
return await waitForFileProcessing(this, id, pollInterval, maxWait);
}
};
}
});
// node_modules/openai/resources/fine-tuning/methods.mjs
var Methods;
var init_methods = __esm({
"node_modules/openai/resources/fine-tuning/methods.mjs"() {
init_resource();
Methods = class extends APIResource {
};
}
});
// node_modules/openai/resources/fine-tuning/alpha/graders.mjs
var Graders;
var init_graders = __esm({
"node_modules/openai/resources/fine-tuning/alpha/graders.mjs"() {
init_resource();
Graders = class extends APIResource {
/**
* Run a grader.
*
* @example
* ```ts
* const response = await client.fineTuning.alpha.graders.run({
* grader: {
* input: 'input',
* name: 'name',
* operation: 'eq',
* reference: 'reference',
* type: 'string_check',
* },
* model_sample: 'model_sample',
* });
* ```
*/
run(body, options) {
return this._client.post("/fine_tuning/alpha/graders/run", {
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* Validate a grader.
*
* @example
* ```ts
* const response =
* await client.fineTuning.alpha.graders.validate({
* grader: {
* input: 'input',
* name: 'name',
* operation: 'eq',
* reference: 'reference',
* type: 'string_check',
* },
* });
* ```
*/
validate(body, options) {
return this._client.post("/fine_tuning/alpha/graders/validate", {
body,
...options,
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/fine-tuning/alpha/alpha.mjs
var Alpha;
var init_alpha = __esm({
"node_modules/openai/resources/fine-tuning/alpha/alpha.mjs"() {
init_resource();
init_graders();
init_graders();
Alpha = class extends APIResource {
constructor() {
super(...arguments);
this.graders = new Graders(this._client);
}
};
Alpha.Graders = Graders;
}
});
// node_modules/openai/resources/fine-tuning/checkpoints/permissions.mjs
var Permissions;
var init_permissions = __esm({
"node_modules/openai/resources/fine-tuning/checkpoints/permissions.mjs"() {
init_resource();
init_pagination();
init_path();
Permissions = class extends APIResource {
/**
* **NOTE:** Calling this endpoint requires an
* [admin API key](https://developers.openai.com/api/reference/resources/admin/subresources/organization/subresources/admin_api_keys).
*
* This enables organization owners to share fine-tuned models with other projects
* in their organization.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const permissionCreateResponse of client.fineTuning.checkpoints.permissions.create(
* 'ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd',
* { project_ids: ['string'] },
* )) {
* // ...
* }
* ```
*/
create(fineTunedModelCheckpoint, body, options) {
return this._client.getAPIList(path`/fine_tuning/checkpoints/${fineTunedModelCheckpoint}/permissions`, Page, { body, method: "post", ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* **NOTE:** This endpoint requires an
* [admin API key](https://developers.openai.com/api/reference/resources/admin/subresources/organization/subresources/admin_api_keys).
*
* Organization owners can use this endpoint to view all permissions for a
* fine-tuned model checkpoint.
*
* @deprecated Retrieve is deprecated. Please swap to the paginated list method instead.
*/
retrieve(fineTunedModelCheckpoint, query = {}, options) {
return this._client.get(path`/fine_tuning/checkpoints/${fineTunedModelCheckpoint}/permissions`, {
query,
...options,
__security: { adminAPIKeyAuth: true }
});
}
/**
* **NOTE:** This endpoint requires an
* [admin API key](https://developers.openai.com/api/reference/resources/admin/subresources/organization/subresources/admin_api_keys).
*
* Organization owners can use this endpoint to view all permissions for a
* fine-tuned model checkpoint.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const permissionListResponse of client.fineTuning.checkpoints.permissions.list(
* 'ft-AF1WoRqd3aJAHsqc9NY7iL8F',
* )) {
* // ...
* }
* ```
*/
list(fineTunedModelCheckpoint, query = {}, options) {
return this._client.getAPIList(path`/fine_tuning/checkpoints/${fineTunedModelCheckpoint}/permissions`, ConversationCursorPage, { query, ...options, __security: { adminAPIKeyAuth: true } });
}
/**
* **NOTE:** This endpoint requires an
* [admin API key](https://developers.openai.com/api/reference/resources/admin/subresources/organization/subresources/admin_api_keys).
*
* Organization owners can use this endpoint to delete a permission for a
* fine-tuned model checkpoint.
*
* @example
* ```ts
* const permission =
* await client.fineTuning.checkpoints.permissions.delete(
* 'cp_zc4Q7MP6XxulcVzj4MZdwsAB',
* {
* fine_tuned_model_checkpoint:
* 'ft:gpt-4o-mini-2024-07-18:org:weather:B7R9VjQd',
* },
* );
* ```
*/
delete(permissionID, params, options) {
const { fine_tuned_model_checkpoint } = params;
return this._client.delete(path`/fine_tuning/checkpoints/${fine_tuned_model_checkpoint}/permissions/${permissionID}`, { ...options, __security: { adminAPIKeyAuth: true } });
}
};
}
});
// node_modules/openai/resources/fine-tuning/checkpoints/checkpoints.mjs
var Checkpoints;
var init_checkpoints = __esm({
"node_modules/openai/resources/fine-tuning/checkpoints/checkpoints.mjs"() {
init_resource();
init_permissions();
init_permissions();
Checkpoints = class extends APIResource {
constructor() {
super(...arguments);
this.permissions = new Permissions(this._client);
}
};
Checkpoints.Permissions = Permissions;
}
});
// node_modules/openai/resources/fine-tuning/jobs/checkpoints.mjs
var Checkpoints2;
var init_checkpoints2 = __esm({
"node_modules/openai/resources/fine-tuning/jobs/checkpoints.mjs"() {
init_resource();
init_pagination();
init_path();
Checkpoints2 = class extends APIResource {
/**
* List checkpoints for a fine-tuning job.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const fineTuningJobCheckpoint of client.fineTuning.jobs.checkpoints.list(
* 'ft-AF1WoRqd3aJAHsqc9NY7iL8F',
* )) {
* // ...
* }
* ```
*/
list(fineTuningJobID, query = {}, options) {
return this._client.getAPIList(path`/fine_tuning/jobs/${fineTuningJobID}/checkpoints`, CursorPage, { query, ...options, __security: { bearerAuth: true } });
}
};
}
});
// node_modules/openai/resources/fine-tuning/jobs/jobs.mjs
var Jobs;
var init_jobs = __esm({
"node_modules/openai/resources/fine-tuning/jobs/jobs.mjs"() {
init_resource();
init_checkpoints2();
init_checkpoints2();
init_pagination();
init_path();
Jobs = class extends APIResource {
constructor() {
super(...arguments);
this.checkpoints = new Checkpoints2(this._client);
}
/**
* Creates a fine-tuning job which begins the process of creating a new model from
* a given dataset.
*
* Response includes details of the enqueued job including job status and the name
* of the fine-tuned models once complete.
*
* [Learn more about fine-tuning](https://developers.openai.com/api/docs/guides/model-optimization)
*
* @example
* ```ts
* const fineTuningJob = await client.fineTuning.jobs.create({
* model: 'gpt-4o-mini',
* training_file: 'file-abc123',
* });
* ```
*/
create(body, options) {
return this._client.post("/fine_tuning/jobs", { body, ...options, __security: { bearerAuth: true } });
}
/**
* Get info about a fine-tuning job.
*
* [Learn more about fine-tuning](https://developers.openai.com/api/docs/guides/model-optimization)
*
* @example
* ```ts
* const fineTuningJob = await client.fineTuning.jobs.retrieve(
* 'ft-AF1WoRqd3aJAHsqc9NY7iL8F',
* );
* ```
*/
retrieve(fineTuningJobID, options) {
return this._client.get(path`/fine_tuning/jobs/${fineTuningJobID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* List your organization's fine-tuning jobs
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const fineTuningJob of client.fineTuning.jobs.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/fine_tuning/jobs", CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Immediately cancel a fine-tune job.
*
* @example
* ```ts
* const fineTuningJob = await client.fineTuning.jobs.cancel(
* 'ft-AF1WoRqd3aJAHsqc9NY7iL8F',
* );
* ```
*/
cancel(fineTuningJobID, options) {
return this._client.post(path`/fine_tuning/jobs/${fineTuningJobID}/cancel`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Get status updates for a fine-tuning job.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const fineTuningJobEvent of client.fineTuning.jobs.listEvents(
* 'ft-AF1WoRqd3aJAHsqc9NY7iL8F',
* )) {
* // ...
* }
* ```
*/
listEvents(fineTuningJobID, query = {}, options) {
return this._client.getAPIList(path`/fine_tuning/jobs/${fineTuningJobID}/events`, CursorPage, { query, ...options, __security: { bearerAuth: true } });
}
/**
* Pause a fine-tune job.
*
* @example
* ```ts
* const fineTuningJob = await client.fineTuning.jobs.pause(
* 'ft-AF1WoRqd3aJAHsqc9NY7iL8F',
* );
* ```
*/
pause(fineTuningJobID, options) {
return this._client.post(path`/fine_tuning/jobs/${fineTuningJobID}/pause`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Resume a fine-tune job.
*
* @example
* ```ts
* const fineTuningJob = await client.fineTuning.jobs.resume(
* 'ft-AF1WoRqd3aJAHsqc9NY7iL8F',
* );
* ```
*/
resume(fineTuningJobID, options) {
return this._client.post(path`/fine_tuning/jobs/${fineTuningJobID}/resume`, {
...options,
__security: { bearerAuth: true }
});
}
};
Jobs.Checkpoints = Checkpoints2;
}
});
// node_modules/openai/resources/fine-tuning/fine-tuning.mjs
var FineTuning;
var init_fine_tuning = __esm({
"node_modules/openai/resources/fine-tuning/fine-tuning.mjs"() {
init_resource();
init_methods();
init_methods();
init_alpha();
init_alpha();
init_checkpoints();
init_checkpoints();
init_jobs();
init_jobs();
FineTuning = class extends APIResource {
constructor() {
super(...arguments);
this.methods = new Methods(this._client);
this.jobs = new Jobs(this._client);
this.checkpoints = new Checkpoints(this._client);
this.alpha = new Alpha(this._client);
}
};
FineTuning.Methods = Methods;
FineTuning.Jobs = Jobs;
FineTuning.Checkpoints = Checkpoints;
FineTuning.Alpha = Alpha;
}
});
// node_modules/openai/resources/graders/grader-models.mjs
var GraderModels;
var init_grader_models = __esm({
"node_modules/openai/resources/graders/grader-models.mjs"() {
init_resource();
GraderModels = class extends APIResource {
};
}
});
// node_modules/openai/resources/graders/graders.mjs
var Graders2;
var init_graders2 = __esm({
"node_modules/openai/resources/graders/graders.mjs"() {
init_resource();
init_grader_models();
init_grader_models();
Graders2 = class extends APIResource {
constructor() {
super(...arguments);
this.graderModels = new GraderModels(this._client);
}
};
Graders2.GraderModels = GraderModels;
}
});
// node_modules/openai/resources/images.mjs
var Images;
var init_images = __esm({
"node_modules/openai/resources/images.mjs"() {
init_resource();
init_uploads();
Images = class extends APIResource {
/**
* Creates a variation of a given image. This endpoint only supports `dall-e-2`.
*
* @example
* ```ts
* const imagesResponse = await client.images.createVariation({
* image: fs.createReadStream('otter.png'),
* });
* ```
*/
createVariation(body, options) {
return this._client.post("/images/variations", multipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
edit(body, options) {
return this._client.post("/images/edits", multipartFormRequestOptions({
body,
...options,
stream: body.stream ?? false,
__metadata: { ...options?.__metadata, ...body.model == null ? {} : { model: body.model } },
__security: { bearerAuth: true }
}, this._client));
}
generate(body, options) {
return this._client.post("/images/generations", {
body,
...options,
stream: body.stream ?? false,
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/live/sessions.mjs
var Sessions4;
var init_sessions4 = __esm({
"node_modules/openai/resources/live/sessions.mjs"() {
init_resource();
init_headers2();
init_path();
Sessions4 = class extends APIResource {
/**
* Accept an incoming SIP call. Supply session with type live, the model, and
* startup configuration. Before accepting calls, follow the
* [Live prompting guide](https://developers.openai.com/api/docs/guides/live-prompting)
* to write frontend conversation instructions and a separate backend prompt. SIP
* media format is negotiated; omit audio.format.
*
* @example
* ```ts
* await client.live.sessions.accept('session_id', {
* session: { model: 'gpt-live-1', type: 'live' },
* });
* ```
*/
accept(sessionID, body, options) {
return this._client.post(path`/live/sessions/${sessionID}/accept`, {
body,
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Get Live session content
*
* @example
* ```ts
* const response =
* await client.live.sessions.downloadRecording('live_SQ');
*
* const content = await response.blob();
* console.log(content);
* ```
*/
downloadRecording(sessionID, options) {
return this._client.get(path`/live/sessions/${sessionID}/content`, {
...options,
headers: buildHeaders([{ Accept: "application/binary" }, options?.headers]),
__security: { bearerAuth: true },
__binaryResponse: true
});
}
/**
* Fork a stored Live session onto a new WebRTC connection.
*
* @example
* ```ts
* const response = await client.live.sessions.fork(
* 'session_id',
* { transport: { sdp: 'x', type: 'webrtc' } },
* );
* ```
*/
fork(sessionID, body, options) {
return this._client.post(path`/live/sessions/${sessionID}/fork`, {
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* End a SIP call identified by session_id.
*
* @example
* ```ts
* await client.live.sessions.hangup('session_id');
* ```
*/
hangup(sessionID, options) {
return this._client.post(path`/live/sessions/${sessionID}/hangup`, {
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Transfer a SIP call to another destination. Supply a nonblank target_uri for the
* SIP Refer-To header.
*
* @example
* ```ts
* await client.live.sessions.refer('session_id', {
* target_uri: 'tel:+14155550123',
* });
* ```
*/
refer(sessionID, body, options) {
return this._client.post(path`/live/sessions/${sessionID}/refer`, {
body,
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Reject an incoming SIP call. Send a required SIP rejection status_code between
* 300 and 699.
*
* @example
* ```ts
* await client.live.sessions.reject('session_id', {
* status_code: 486,
* });
* ```
*/
reject(sessionID, body, options) {
return this._client.post(path`/live/sessions/${sessionID}/reject`, {
body,
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/live/forks/forks.mjs
var Forks;
var init_forks = __esm({
"node_modules/openai/resources/live/forks/forks.mjs"() {
init_resource();
Forks = class extends APIResource {
};
}
});
// node_modules/openai/resources/live/sideband/sideband.mjs
var Sideband;
var init_sideband = __esm({
"node_modules/openai/resources/live/sideband/sideband.mjs"() {
init_resource();
Sideband = class extends APIResource {
};
}
});
// node_modules/openai/resources/live/live.mjs
var Live;
var init_live = __esm({
"node_modules/openai/resources/live/live.mjs"() {
init_resource();
init_sessions4();
init_sessions4();
init_forks();
init_forks();
init_sideband();
init_sideband();
Live = class extends APIResource {
constructor() {
super(...arguments);
this.sideband = new Sideband(this._client);
this.forks = new Forks(this._client);
this.sessions = new Sessions4(this._client);
}
/**
* Create a Live WebRTC session. Start with the
* [Live prompting guide](https://developers.openai.com/api/docs/guides/live-prompting).
*
* @example
* ```ts
* const live = await client.live.create({
* session: { model: 'gpt-live-1' },
* transport: { sdp: 'x', type: 'webrtc' },
* });
* ```
*/
create(body, options) {
return this._client.post("/live/sessions", { body, ...options, __security: { bearerAuth: true } });
}
};
Live.Sideband = Sideband;
Live.Forks = Forks;
Live.Sessions = Sessions4;
}
});
// node_modules/openai/resources/models.mjs
var Models;
var init_models2 = __esm({
"node_modules/openai/resources/models.mjs"() {
init_resource();
init_pagination();
init_path();
Models = class extends APIResource {
/**
* Retrieves a model instance, providing basic information about the model such as
* the owner and permissioning.
*/
retrieve(model3, options) {
return this._client.get(path`/models/${model3}`, { ...options, __security: { bearerAuth: true } });
}
/**
* Lists the currently available models, and provides basic information about each
* one such as the owner and availability.
*/
list(options) {
return this._client.getAPIList("/models", Page, { ...options, __security: { bearerAuth: true } });
}
/**
* Delete a fine-tuned model. You must have the Owner role in your organization to
* delete a model.
*/
delete(model3, options) {
return this._client.delete(path`/models/${model3}`, { ...options, __security: { bearerAuth: true } });
}
};
}
});
// node_modules/openai/resources/moderations.mjs
var Moderations;
var init_moderations = __esm({
"node_modules/openai/resources/moderations.mjs"() {
init_resource();
Moderations = class extends APIResource {
/**
* Classifies if text and/or image inputs are potentially harmful. Learn more in
* the
* [moderation guide](https://developers.openai.com/api/docs/guides/moderation).
*/
create(body, options) {
return this._client.post("/moderations", { body, ...options, __security: { bearerAuth: true } });
}
};
}
});
// node_modules/openai/internal/multipart-encoding.mjs
async function encodedMultipartFormRequestOptions(options, client, encodings, rawBodyField = null) {
if (options.body === null || typeof options.body !== "object" || Array.isArray(options.body)) {
throw new TypeError("Multipart request body must be an object");
}
const body = Object.fromEntries(Object.entries(options.body).filter(([, value2]) => value2 !== void 0));
if (rawBodyField !== null && Object.keys(body).length === 1 && Object.prototype.hasOwnProperty.call(body, rawBodyField)) {
const value2 = body[rawBodyField];
if (typeof value2 !== "string")
throw new TypeError("Raw multipart alternative must be a string");
return {
...options,
body: value2,
headers: buildHeaders([options.headers, { "content-type": encodings[rawBodyField].content_type }])
};
}
const encoded = [];
for (const [name, encoding] of Object.entries(encodings)) {
if (!Object.prototype.hasOwnProperty.call(body, name))
continue;
const value2 = body[name];
const data = encoding.json ? JSON.stringify(value2) : value2;
if (typeof data !== "string")
throw new TypeError(`Multipart field ${name} must encode as a string`);
encoded.push([name, makeFile([data], "", { type: encoding.content_type })]);
delete body[name];
}
const multipart = await multipartFormRequestOptions({ ...options, body }, client);
const form = multipart.body;
if (!(form instanceof FormData)) {
await form.cancel();
throw new TypeError("Unexpected streaming upload in typed multipart request body");
}
for (const [name, part] of encoded)
form.append(name, part, "");
return {
...options,
body: form,
headers: buildHeaders([options.headers, { "content-type": null }])
};
}
var init_multipart_encoding = __esm({
"node_modules/openai/internal/multipart-encoding.mjs"() {
init_uploads();
init_headers2();
}
});
// node_modules/openai/resources/realtime/calls.mjs
var Calls;
var init_calls = __esm({
"node_modules/openai/resources/realtime/calls.mjs"() {
init_resource();
init_headers2();
init_path();
init_multipart_encoding();
Calls = class extends APIResource {
/**
* Create a new Realtime API call over WebRTC and receive the SDP answer needed to
* complete the peer connection.
*
* @example
* ```ts
* await client.realtime.calls.create({
* sdp: 'sdp',
* });
* ```
*/
create(body, options) {
return this._client.post("/realtime/calls", encodedMultipartFormRequestOptions({
body,
...options,
headers: buildHeaders([{ Accept: "application/sdp" }, options?.headers]),
__security: { bearerAuth: true },
__binaryResponse: true
}, this._client, {
sdp: { content_type: "application/sdp", json: false },
session: { content_type: "application/json", json: true }
}, "sdp"));
}
/**
* Accept an incoming SIP call and configure the realtime session that will handle
* it.
*
* @example
* ```ts
* await client.realtime.calls.accept('call_id', {
* type: 'realtime',
* });
* ```
*/
accept(callID, body, options) {
return this._client.post(path`/realtime/calls/${callID}/accept`, {
body,
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* End an active Realtime API call, whether it was initiated over SIP or WebRTC.
*
* @example
* ```ts
* await client.realtime.calls.hangup('call_id');
* ```
*/
hangup(callID, options) {
return this._client.post(path`/realtime/calls/${callID}/hangup`, {
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Transfer an active SIP call to a new destination using the SIP REFER verb.
*
* @example
* ```ts
* await client.realtime.calls.refer('call_id', {
* target_uri: 'tel:+14155550123',
* });
* ```
*/
refer(callID, body, options) {
return this._client.post(path`/realtime/calls/${callID}/refer`, {
body,
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Decline an incoming SIP call by returning a SIP status code to the caller.
*
* @example
* ```ts
* await client.realtime.calls.reject('call_id');
* ```
*/
reject(callID, body = {}, options) {
return this._client.post(path`/realtime/calls/${callID}/reject`, {
body,
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/realtime/client-secrets.mjs
var ClientSecrets;
var init_client_secrets = __esm({
"node_modules/openai/resources/realtime/client-secrets.mjs"() {
init_resource();
ClientSecrets = class extends APIResource {
/**
* Create a Realtime client secret with an associated session configuration.
*
* Client secrets are short-lived tokens that can be passed to a client app, such
* as a web frontend or mobile client, which grants access to the Realtime API
* without leaking your main API key. You can configure a custom TTL for each
* client secret.
*
* You can also attach session configuration options to the client secret, which
* will be applied to any sessions created using that client secret, but these can
* also be overridden by the client connection.
*
* [Learn more about authentication with client secrets over WebRTC](https://developers.openai.com/api/docs/guides/realtime-webrtc).
*
* Returns the created client secret and the effective session object. The client
* secret is a string that looks like `ek_1234`.
*
* @example
* ```ts
* const clientSecret =
* await client.realtime.clientSecrets.create();
* ```
*/
create(body, options) {
return this._client.post("/realtime/client_secrets", {
body,
...options,
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/realtime/realtime.mjs
var Realtime2;
var init_realtime2 = __esm({
"node_modules/openai/resources/realtime/realtime.mjs"() {
init_resource();
init_calls();
init_calls();
init_client_secrets();
init_client_secrets();
Realtime2 = class extends APIResource {
constructor() {
super(...arguments);
this.clientSecrets = new ClientSecrets(this._client);
this.calls = new Calls(this._client);
}
};
Realtime2.ClientSecrets = ClientSecrets;
Realtime2.Calls = Calls;
}
});
// node_modules/openai/lib/ResponsesParser.mjs
function maybeParseResponse(response, params) {
if (!params || !hasAutoParseableInput2(params)) {
const parsed = {
...response,
output_parsed: null,
output: response.output.map((item) => {
if (item.type === "function_call") {
return {
...item,
parsed_arguments: null
};
}
if (item.type === "message") {
return {
...item,
content: item.content.map((content) => ({
...content,
parsed: null
}))
};
}
return item;
})
};
if (needsOutputText(response, parsed)) {
addOutputText(parsed);
}
return parsed;
}
return parseResponse(response, params);
}
function parseResponse(response, params) {
const shouldParse = !response.status || response.status === "completed";
const output = response.output.map((item) => {
if (item.type === "function_call") {
return shouldParse ? parseToolCall2(params, item) : { ...item, parsed_arguments: null };
}
if (item.type === "message") {
const content = item.content.map((content2) => {
if (content2.type === "output_text") {
return {
...content2,
parsed: shouldParse ? parseTextFormat(params, content2.text) : null
};
}
return content2;
});
return {
...item,
content
};
}
return item;
});
const parsed = { ...response, output };
if (needsOutputText(response, parsed)) {
addOutputText(parsed);
}
Object.defineProperty(parsed, "output_parsed", {
enumerable: true,
get() {
for (const output2 of parsed.output) {
if (output2.type !== "message") {
continue;
}
for (const content of output2.content) {
if (content.type === "output_text" && content.parsed !== null) {
return content.parsed;
}
}
}
return null;
}
});
return parsed;
}
function parseTextFormat(params, content) {
return parseResponseFormatContent(params.text?.format, content);
}
function hasAutoParseableInput2(params) {
if (isParseableResponseFormat(params.text?.format)) {
return true;
}
return Array.isArray(params.tools) && params.tools.some((tool) => isAutoParsableTool2(tool) || tool.type === "function" && tool.strict === true || tool.type === "namespace" && tool.tools.some((nested) => nested.type === "function" && (isAutoParsableTool2(nested) || nested.strict === true)));
}
function isAutoParsableTool2(tool) {
return tool?.["$brand"] === "auto-parseable-tool";
}
function getInputToolByName(input_tools, name, namespace) {
for (const tool of input_tools) {
if (namespace == null) {
if (tool.type === "function" && tool.name === name) {
return tool;
}
} else if (tool.type === "namespace" && tool.name === namespace) {
return tool.tools.find((nested) => nested.type === "function" && nested.name === name);
}
}
return void 0;
}
function parseToolCall2(params, toolCall) {
const inputTool = getInputToolByName(params.tools ?? [], toolCall.name, toolCall.namespace);
let parsedArguments = null;
if (isAutoParsableTool2(inputTool)) {
parsedArguments = inputTool.$parseRaw(toolCall.arguments);
} else if (inputTool?.strict) {
parsedArguments = parseResponseFormatContent({ type: "json_schema", $parseRaw: void 0 }, toolCall.arguments);
}
return {
...toolCall,
parsed_arguments: parsedArguments
};
}
function needsOutputText(response, target) {
return !Object.getOwnPropertyDescriptor(response, "output_text") || target.output_text == null;
}
function addOutputText(rsp) {
const texts = [];
for (const output of rsp.output) {
if (output.type !== "message") {
continue;
}
for (const content of output.content) {
if (content.type === "output_text") {
texts.push(content.text);
}
}
}
rsp.output_text = texts.join("");
}
var init_ResponsesParser = __esm({
"node_modules/openai/lib/ResponsesParser.mjs"() {
init_error2();
init_parser();
}
});
// node_modules/openai/internal/responses/output-text-index.mjs
var OutputTextIndex;
var init_output_text_index = __esm({
"node_modules/openai/internal/responses/output-text-index.mjs"() {
OutputTextIndex = class {
constructor() {
this.capacity = 1;
this.values = [0, 0];
this.size = 0;
}
get length() {
return this.size;
}
append(value2) {
if (this.size === this.capacity) {
this.grow();
}
const index = this.size;
this.size += 1;
this.update(index, value2);
}
update(index, value2) {
if (!Number.isSafeInteger(index) || index < 0 || index >= this.size) {
throw new RangeError(`missing output at index ${index}`);
}
let node = this.capacity + index;
const difference = value2 - (this.values[node] ?? 0);
if (difference === 0) {
return;
}
while (node >= 1) {
this.values[node] = (this.values[node] ?? 0) + difference;
node = Math.floor(node / 2);
}
}
prefixSum(end) {
if (!Number.isSafeInteger(end) || end < 0 || end > this.size) {
throw new RangeError(`missing output at index ${end}`);
}
let start = this.capacity;
let stop2 = this.capacity + end;
let sum = 0;
while (start < stop2) {
if (start % 2 === 1) {
sum += this.values[start] ?? 0;
start += 1;
}
if (stop2 % 2 === 1) {
stop2 -= 1;
sum += this.values[stop2] ?? 0;
}
start = Math.floor(start / 2);
stop2 = Math.floor(stop2 / 2);
}
return sum;
}
grow() {
const previousCapacity = this.capacity;
this.capacity *= 2;
const values = Array.from({ length: this.capacity * 2 }, () => 0);
for (let index = 0; index < this.size; index += 1) {
values[this.capacity + index] = this.values[previousCapacity + index] ?? 0;
}
for (let index = this.capacity - 1; index > 0; index -= 1) {
values[index] = (values[index * 2] ?? 0) + (values[index * 2 + 1] ?? 0);
}
this.values = values;
}
};
}
});
// node_modules/openai/internal/responses/canonical-output-text.mjs
function createCanonicalResponseContext() {
return {
canonicalSnapshot: void 0,
outputTextLengths: /* @__PURE__ */ new WeakMap(),
outputTextIndex: new OutputTextIndex()
};
}
function getOutputText(context, output) {
if (output.type !== "message") {
return "";
}
let text2 = "";
for (const content of output.content) {
if (content.type === "output_text") {
text2 += content.text;
}
}
context.outputTextLengths.set(output, text2.length);
return text2;
}
function ensureCanonicalOutputText(context, snapshot) {
if (context.canonicalSnapshot === snapshot) {
return;
}
const outputTextIndex = new OutputTextIndex();
let text2 = "";
for (const output of snapshot.output) {
const outputText = getOutputText(context, output);
text2 += outputText;
outputTextIndex.append(outputText.length);
}
snapshot.output_text = text2;
context.outputTextIndex = outputTextIndex;
context.canonicalSnapshot = snapshot;
}
function cloneResponse(context, response) {
context.canonicalSnapshot = void 0;
context.outputTextLengths = /* @__PURE__ */ new WeakMap();
context.outputTextIndex = new OutputTextIndex();
const snapshot = structuredClone(response);
if (!Object.getOwnPropertyDescriptor(snapshot, "output_text") || snapshot.output_text === null || snapshot.output_text === void 0) {
ensureCanonicalOutputText(context, snapshot);
} else if (snapshot.output.length === 0 && snapshot.output_text === "") {
context.canonicalSnapshot = snapshot;
}
return snapshot;
}
function updateCachedOutputTextLength(context, output, outputIndex, previousText, nextText) {
const length = context.outputTextLengths.get(output);
if (length !== void 0) {
const nextLength = length - previousText.length + nextText.length;
context.outputTextLengths.set(output, nextLength);
context.outputTextIndex.update(outputIndex, nextLength);
}
}
function replaceOutputTextSuffix(snapshot, previousText, nextText) {
if (previousText.length === 0) {
snapshot.output_text += nextText;
return;
}
snapshot.output_text = snapshot.output_text.slice(0, snapshot.output_text.length - previousText.length) + nextText;
}
function getPrecedingContentTextLength(context, output, contentIndex, nextText) {
if (contentIndex === void 0 || output?.type !== "message") {
return 0;
}
if (contentIndex < output.content.length - contentIndex - 1) {
let precedingContentLength = 0;
for (let index = 0; index < contentIndex; index += 1) {
const precedingContent = output.content[index];
if (precedingContent?.type === "output_text") {
precedingContentLength += precedingContent.text.length;
}
}
return precedingContentLength;
}
let followingContentLength = 0;
for (let index = contentIndex + 1; index < output.content.length; index += 1) {
const followingContent = output.content[index];
if (followingContent?.type === "output_text") {
followingContentLength += followingContent.text.length;
}
}
const outputTextLength = context.outputTextLengths.get(output) ?? getOutputText(context, output).length;
return outputTextLength - followingContentLength - nextText.length;
}
function updateOutputText(context, snapshot, outputIndex, previousText, nextText, contentIndex) {
if (previousText === nextText) {
return;
}
const output = snapshot.output[outputIndex];
if (outputIndex === snapshot.output.length - 1 && (contentIndex === void 0 || output?.type === "message" && contentIndex === output.content.length - 1)) {
replaceOutputTextSuffix(snapshot, previousText, nextText);
return;
}
const precedingContentLength = getPrecedingContentTextLength(context, output, contentIndex, nextText);
const offset = context.outputTextIndex.prefixSum(outputIndex) + precedingContentLength;
if (offset + previousText.length === snapshot.output_text.length) {
replaceOutputTextSuffix(snapshot, previousText, nextText);
return;
}
snapshot.output_text = snapshot.output_text.slice(0, offset) + nextText + snapshot.output_text.slice(offset + previousText.length);
}
var init_canonical_output_text = __esm({
"node_modules/openai/internal/responses/canonical-output-text.mjs"() {
init_output_text_index();
}
});
// node_modules/openai/internal/responses/response-accumulator.mjs
function validateArrayIndex(collection, index, kind, allowAppend = false) {
if (!Array.isArray(collection) || !Number.isSafeInteger(index) || index < 0 || index > collection.length || (index === collection.length ? !allowAppend || index in collection : !hasOwn(collection, index))) {
throw new OpenAIError(`missing ${kind} at index ${index}`);
}
}
function validateArrayAppend(collection, index, kind) {
if (index !== collection.length) {
throw new OpenAIError(`missing ${kind} at index ${index}`);
}
validateArrayIndex(collection, index, kind, true);
}
function getOutput(snapshot, outputIndex) {
validateArrayIndex(snapshot.output, outputIndex, "output");
const output = snapshot.output[outputIndex];
if (!output) {
throw new OpenAIError(`missing output at index ${outputIndex}`);
}
return output;
}
function hasRoutedOutputCallIdentity(output) {
return output.type === "function_call" || output.type === "custom_tool_call" || output.type === "shell_call" || output.type === "shell_call_output";
}
function getOutputItemIdentityKeys(output, eventType) {
if (!hasOwn(output, "type") || typeof output.type !== "string") {
throw new OpenAIError(`expected an own output item type for ${eventType}`);
}
const optionalPlatformID = output.type === "function_call" || output.type === "custom_tool_call";
const identities = [];
if (hasOwn(output, "id")) {
if (typeof output.id !== "string" || output.id.length === 0) {
throw new OpenAIError(`expected a non-empty output item id for ${eventType}`);
}
identities.push(`id:${output.id}`);
} else if (!optionalPlatformID) {
throw new OpenAIError(`expected a non-empty output item id for ${eventType}`);
}
if (hasRoutedOutputCallIdentity(output)) {
if (!hasOwn(output, "call_id") || typeof output.call_id !== "string" || output.call_id.length === 0) {
throw new OpenAIError(`expected a non-empty output item call_id for ${eventType}`);
}
identities.push(`call:${output.type}:${output.call_id}`);
}
return identities;
}
function assertOutputItemIdentitiesAvailable(identities, keys) {
for (const key of keys) {
if (identities.has(key)) {
throw new OpenAIError(`duplicate output item identity '${key}'`);
}
}
}
function addOutputItemIdentities(identities, keys) {
assertOutputItemIdentitiesAvailable(identities, keys);
for (const key of keys) {
identities.add(key);
}
}
function createResponseOutputIdentityIndex(snapshot) {
const identityIndex = {
snapshot,
output: snapshot.output,
length: snapshot.output.length,
identities: /* @__PURE__ */ new Set()
};
for (let index = 0; index < snapshot.output.length; index += 1) {
const output = getOutput(snapshot, index);
addOutputItemIdentities(identityIndex.identities, getOutputItemIdentityKeys(output, "response snapshot"));
}
return identityIndex;
}
function getResponseOutputIdentityIndex(context, snapshot) {
const cached = responseOutputIdentityIndexes.get(context);
if (cached && cached.snapshot === snapshot && cached.output === snapshot.output && cached.length === snapshot.output.length) {
return cached;
}
const identityIndex = createResponseOutputIdentityIndex(snapshot);
responseOutputIdentityIndexes.set(context, identityIndex);
return identityIndex;
}
function cloneValidatedResponse(context, response) {
const nextContext = createCanonicalResponseContext();
const snapshot = cloneResponse(nextContext, response);
const identityIndex = createResponseOutputIdentityIndex(snapshot);
context.canonicalSnapshot = nextContext.canonicalSnapshot;
context.outputTextLengths = nextContext.outputTextLengths;
context.outputTextIndex = nextContext.outputTextIndex;
responseOutputIdentityIndexes.set(context, identityIndex);
return snapshot;
}
function getExpectedOutputItemType(event) {
if (event.type === "response.content_part.added" || event.type === "response.content_part.done") {
return event.part.type === "reasoning_text" ? "reasoning" : "message";
}
return expectedOutputItemTypes[event.type];
}
function validateCompletedOutputItemIdentity(event, snapshot) {
const output = getOutput(snapshot, event.output_index);
const replacement = event.item;
getOutputItemIdentityKeys(output, event.type);
getOutputItemIdentityKeys(replacement, event.type);
if (!hasOwn(replacement, "type") || output.type !== replacement.type) {
throw new OpenAIError(`expected output item type '${output.type}', got '${replacement.type}'`);
}
const outputID = hasOwn(output, "id") ? output.id : void 0;
const replacementID = hasOwn(replacement, "id") ? replacement.id : void 0;
if (outputID !== replacementID) {
throw new OpenAIError(`expected output item id '${outputID}', got '${replacementID}'`);
}
if (hasRoutedOutputCallIdentity(output) && hasRoutedOutputCallIdentity(replacement) && output.call_id !== replacement.call_id) {
throw new OpenAIError(`expected output item call_id '${output.call_id}', got '${replacement.call_id}'`);
}
}
function validateOutputItemIdentity(event, snapshot, rejectInvalidShellTargets) {
if (event.type === "response.output_item.done") {
validateCompletedOutputItemIdentity(event, snapshot);
return;
}
if (rejectInvalidShellTargets && (event.type === "response.shell_call_command.added" || event.type === "response.shell_call_command.delta" || event.type === "response.shell_call_command.done")) {
const output2 = getOutput(snapshot, event.output_index);
if (!hasOwn(output2, "type") || output2.type !== "shell_call") {
throw new OpenAIError(`expected output item type 'shell_call', got '${output2.type}'`);
}
return;
}
if (event.type !== "response.content_part.added" && event.type !== "response.content_part.done" && !hasOwn(expectedOutputItemTypes, event.type)) {
return;
}
const itemEvent = event;
if (!hasOwn(event, "item_id") || typeof itemEvent.item_id !== "string" || itemEvent.item_id.length === 0) {
throw new OpenAIError(`expected a non-empty item_id for ${event.type}`);
}
const output = getOutput(snapshot, itemEvent.output_index);
const outputID = hasOwn(output, "id") ? output.id : void 0;
if (outputID !== itemEvent.item_id) {
throw new OpenAIError(`expected item_id '${outputID}', got '${itemEvent.item_id}'`);
}
const expectedType = getExpectedOutputItemType(itemEvent);
if (output.type !== expectedType) {
throw new OpenAIError(`expected output item type '${expectedType}', got '${output.type}'`);
}
}
function getContent(content, contentIndex) {
validateArrayIndex(content, contentIndex, "content");
const part = content[contentIndex];
if (!part) {
throw new OpenAIError(`missing content at index ${contentIndex}`);
}
return part;
}
function getShellOutputContent(snapshot, output, commandIndex) {
const shellCall = snapshot.output.find((item) => item.type === "shell_call" && item.call_id === output.call_id);
if (shellCall) {
validateArrayIndex(shellCall.action.commands, commandIndex, "command");
} else {
validateArrayIndex(output.output, commandIndex, "content", true);
}
while (output.output.length <= commandIndex) {
output.output.push({
stdout: "",
stderr: "",
outcome: { type: "exit", exit_code: 0 }
});
}
return getContent(output.output, commandIndex);
}
function createSupportedResponseEventTypes(eventTypes) {
return new Set(eventTypes);
}
function assertNever3(_value) {
throw new OpenAIError("Unhandled response stream event: unknown");
}
function sanitizeResponseEvent(event) {
let descriptor;
try {
descriptor = Object.getOwnPropertyDescriptor(event, "type");
} catch {
return assertNever3(event);
}
const type = descriptor?.value;
if (
// oxlint-disable-next-line anti-slop/no-runtime-typeof -- Validate untrusted streamed item identifiers and discriminators before mutating the response snapshot.
typeof type !== "string" || !supportedResponseEventTypes.has(type)
) {
return assertNever3(event);
}
const stableValues = /* @__PURE__ */ new Map([["type", type]]);
const itemScoped = type === "response.output_item.added" || type === "response.output_item.done" || type === "response.content_part.added" || type === "response.content_part.done" || type === "response.shell_call_command.added" || type === "response.shell_call_command.delta" || type === "response.shell_call_command.done" || hasOwn(expectedOutputItemTypes, type);
if (itemScoped) {
try {
for (const field of responseEventRoutingFields) {
const routingDescriptor = Object.getOwnPropertyDescriptor(event, field);
stableValues.set(field, routingDescriptor ? event[field] : void 0);
}
if (type === "response.output_item.done") {
stableValues.set("item", structuredClone(event.item));
} else if (type === "response.content_part.added" || type === "response.content_part.done") {
stableValues.set("part", structuredClone(event.part));
}
} catch {
return assertNever3(event);
}
}
return new Proxy(event, {
get(target, property) {
return stableValues.has(property) ? stableValues.get(property) : Reflect.get(target, property, target);
}
});
}
function accumulateOutputItemEvent(event, snapshot, context) {
switch (event.type) {
case "response.output_item.added": {
validateArrayAppend(snapshot.output, event.output_index, "output");
const identityIndex = getResponseOutputIdentityIndex(context, snapshot);
const output = structuredClone(event.item);
const identities = getOutputItemIdentityKeys(output, event.type);
assertOutputItemIdentitiesAvailable(identityIndex.identities, identities);
if (output.type === "message") {
ensureCanonicalOutputText(context, snapshot);
}
snapshot.output.push(output);
addOutputItemIdentities(identityIndex.identities, identities);
identityIndex.length = snapshot.output.length;
const text2 = getOutputText(context, output);
if (context.canonicalSnapshot === snapshot) {
context.outputTextIndex.append(text2.length);
}
if (text2) {
snapshot.output_text += text2;
}
return true;
}
case "response.output_item.done": {
const output = getOutput(snapshot, event.output_index);
const previousText = getOutputText(context, output);
const replacement = event.item;
if (output.type === "message" || replacement.type === "message") {
ensureCanonicalOutputText(context, snapshot);
}
snapshot.output[event.output_index] = replacement;
const nextText = getOutputText(context, replacement);
if (context.canonicalSnapshot === snapshot) {
context.outputTextIndex.update(event.output_index, nextText.length);
}
updateOutputText(context, snapshot, event.output_index, previousText, nextText);
return true;
}
default: {
return false;
}
}
}
function accumulateContentPartAddedEvent(event, snapshot, context) {
switch (event.type) {
case "response.content_part.added": {
const output = getOutput(snapshot, event.output_index);
const { type } = output;
const { part } = event;
if (type === "message" && part.type !== "reasoning_text") {
validateArrayAppend(output.content, event.content_index, "content");
const content = part;
if (content.type === "output_text") {
ensureCanonicalOutputText(context, snapshot);
}
output.content.push(content);
if (content.type === "output_text") {
updateCachedOutputTextLength(context, output, event.output_index, "", content.text);
updateOutputText(context, snapshot, event.output_index, "", content.text, event.content_index);
}
} else if (type === "reasoning" && part.type === "reasoning_text") {
const content = output.content ?? [];
validateArrayAppend(content, event.content_index, "content");
if (!output.content) {
output.content = content;
}
content.push(part);
}
return true;
}
default: {
return false;
}
}
}
function accumulateContentPartDoneEvent(event, snapshot, context) {
switch (event.type) {
case "response.content_part.done": {
const output = getOutput(snapshot, event.output_index);
const { part } = event;
if (output.type === "message" && part.type !== "reasoning_text") {
const content = getContent(output.content, event.content_index);
const previousText = content.type === "output_text" ? content.text : "";
const replacement = part;
if (content.type === "output_text" || replacement.type === "output_text") {
ensureCanonicalOutputText(context, snapshot);
}
output.content[event.content_index] = replacement;
const nextText = replacement.type === "output_text" ? replacement.text : "";
updateCachedOutputTextLength(context, output, event.output_index, previousText, nextText);
updateOutputText(context, snapshot, event.output_index, previousText, nextText, event.content_index);
} else if (output.type === "reasoning" && part.type === "reasoning_text") {
const { content } = output;
if (!content) {
throw new OpenAIError(`missing content at index ${event.content_index}`);
}
getContent(content, event.content_index);
content[event.content_index] = part;
}
return true;
}
default: {
return false;
}
}
}
function accumulateOutputTextEvent(event, snapshot, context) {
switch (event.type) {
case "response.output_text.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "message") {
const content = getContent(output.content, event.content_index);
if (content.type !== "output_text") {
throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
const previousText = content.text;
ensureCanonicalOutputText(context, snapshot);
content.text = previousText + event.delta;
updateCachedOutputTextLength(context, output, event.output_index, previousText, content.text);
if (event.output_index === snapshot.output.length - 1 && event.content_index === output.content.length - 1) {
snapshot.output_text += event.delta;
} else {
updateOutputText(context, snapshot, event.output_index, previousText, content.text, event.content_index);
}
}
return true;
}
case "response.output_text.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "message") {
const content = getContent(output.content, event.content_index);
if (content.type !== "output_text") {
throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
const previousText = content.text;
ensureCanonicalOutputText(context, snapshot);
content.text = event.text;
updateCachedOutputTextLength(context, output, event.output_index, previousText, event.text);
updateOutputText(context, snapshot, event.output_index, previousText, event.text, event.content_index);
}
return true;
}
case "response.output_text.annotation.added": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "message") {
const content = getContent(output.content, event.content_index);
if (content.type !== "output_text") {
throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
validateArrayIndex(content.annotations, event.annotation_index, "annotation", true);
content.annotations[event.annotation_index] = structuredClone(event.annotation);
}
return true;
}
default: {
return false;
}
}
}
function accumulateRefusalAndArgumentsEvent(event, snapshot) {
switch (event.type) {
case "response.refusal.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "message") {
const content = getContent(output.content, event.content_index);
if (content.type !== "refusal") {
throw new OpenAIError(`expected content to be 'refusal', got ${content.type}`);
}
content.refusal += event.delta;
}
return true;
}
case "response.refusal.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "message") {
const content = getContent(output.content, event.content_index);
if (content.type !== "refusal") {
throw new OpenAIError(`expected content to be 'refusal', got ${content.type}`);
}
content.refusal = event.refusal;
}
return true;
}
case "response.function_call_arguments.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "function_call") {
output.arguments += event.delta;
}
return true;
}
case "response.function_call_arguments.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "function_call") {
output.arguments = event.arguments;
}
return true;
}
case "response.custom_tool_call_input.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "custom_tool_call") {
output.input += event.delta;
}
return true;
}
case "response.custom_tool_call_input.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "custom_tool_call") {
output.input = event.input;
}
return true;
}
case "response.mcp_call_arguments.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "mcp_call") {
output.arguments += event.delta;
}
return true;
}
case "response.mcp_call_arguments.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "mcp_call") {
output.arguments = event.arguments;
}
return true;
}
default: {
return false;
}
}
}
function accumulateShellEvent(event, snapshot) {
switch (event.type) {
case "response.shell_call_command.added":
case "response.shell_call_command.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "shell_call") {
const allowAppend = event.type === "response.shell_call_command.added";
validateArrayIndex(output.action.commands, event.command_index, "command", allowAppend);
output.action.commands[event.command_index] = event.command;
}
return true;
}
case "response.shell_call_command.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "shell_call") {
validateArrayIndex(output.action.commands, event.command_index, "command");
output.action.commands[event.command_index] += event.delta;
}
return true;
}
case "response.shell_call_output_content.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "shell_call_output") {
const content = getShellOutputContent(snapshot, output, event.command_index);
content.stdout += event.delta.stdout ?? "";
content.stderr += event.delta.stderr ?? "";
}
return true;
}
case "response.shell_call_output_content.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "shell_call_output") {
const content = getContent(event.output, 0);
getShellOutputContent(snapshot, output, event.command_index);
output.output[event.command_index] = structuredClone(content);
}
return true;
}
default: {
return false;
}
}
}
function accumulateReasoningEvent(event, snapshot) {
switch (event.type) {
case "response.reasoning_text.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "reasoning") {
if (!output.content) {
throw new OpenAIError(`missing content at index ${event.content_index}`);
}
const content = getContent(output.content, event.content_index);
if (content.type !== "reasoning_text") {
throw new OpenAIError(`expected content to be 'reasoning_text', got ${content.type}`);
}
content.text += event.delta;
}
return true;
}
case "response.reasoning_text.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "reasoning") {
if (!output.content) {
throw new OpenAIError(`missing content at index ${event.content_index}`);
}
const content = getContent(output.content, event.content_index);
if (content.type !== "reasoning_text") {
throw new OpenAIError(`expected content to be 'reasoning_text', got ${content.type}`);
}
content.text = event.text;
}
return true;
}
case "response.reasoning_summary_part.added": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "reasoning") {
validateArrayAppend(output.summary, event.summary_index, "content");
output.summary.push(structuredClone(event.part));
}
return true;
}
case "response.reasoning_summary_part.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "reasoning") {
getContent(output.summary, event.summary_index);
output.summary[event.summary_index] = structuredClone(event.part);
}
return true;
}
case "response.reasoning_summary_text.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "reasoning") {
const part = getContent(output.summary, event.summary_index);
part.text += event.delta;
}
return true;
}
case "response.reasoning_summary_text.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "reasoning") {
const part = getContent(output.summary, event.summary_index);
part.text = event.text;
}
return true;
}
default: {
return false;
}
}
}
function accumulateCodeInterpreterEvent(event, snapshot) {
switch (event.type) {
case "response.code_interpreter_call_code.delta": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "code_interpreter_call") {
output.code = (output.code ?? "") + event.delta;
}
return true;
}
case "response.code_interpreter_call_code.done": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "code_interpreter_call") {
output.code = event.code;
}
return true;
}
case "response.code_interpreter_call.in_progress": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "code_interpreter_call") {
output.status = "in_progress";
}
return true;
}
case "response.code_interpreter_call.interpreting": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "code_interpreter_call") {
output.status = "interpreting";
}
return true;
}
case "response.code_interpreter_call.completed": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "code_interpreter_call") {
output.status = "completed";
}
return true;
}
default: {
return false;
}
}
}
function accumulateSearchStatusEvent(event, snapshot) {
switch (event.type) {
case "response.file_search_call.in_progress": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "file_search_call") {
output.status = "in_progress";
}
return true;
}
case "response.file_search_call.searching": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "file_search_call") {
output.status = "searching";
}
return true;
}
case "response.file_search_call.completed": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "file_search_call") {
output.status = "completed";
}
return true;
}
case "response.web_search_call.in_progress": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "web_search_call") {
output.status = "in_progress";
}
return true;
}
case "response.web_search_call.searching": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "web_search_call") {
output.status = "searching";
}
return true;
}
case "response.web_search_call.completed": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "web_search_call") {
output.status = "completed";
}
return true;
}
default: {
return false;
}
}
}
function accumulateImageAndMcpStatusEvent(event, snapshot) {
switch (event.type) {
case "response.image_generation_call.in_progress": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "image_generation_call") {
output.status = "in_progress";
}
return true;
}
case "response.image_generation_call.generating": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "image_generation_call") {
output.status = "generating";
}
return true;
}
case "response.image_generation_call.completed": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "image_generation_call") {
output.status = "completed";
}
return true;
}
case "response.mcp_call.in_progress": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "mcp_call") {
output.status = "in_progress";
}
return true;
}
case "response.mcp_call.completed": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "mcp_call") {
output.status = "completed";
}
return true;
}
case "response.mcp_call.failed": {
const output = getOutput(snapshot, event.output_index);
if (output.type === "mcp_call") {
output.status = "failed";
}
return true;
}
default: {
return false;
}
}
}
function isResponseLifecycleEvent(event) {
switch (event.type) {
case "response.created":
case "response.queued":
case "response.in_progress":
case "response.completed":
case "response.failed":
case "response.incomplete": {
return true;
}
default: {
return false;
}
}
}
function isIgnoredResponseEvent(event) {
switch (event.type) {
case "response.audio.delta":
case "response.audio.done":
case "response.audio.transcript.delta":
case "response.audio.transcript.done":
case "response.compaction.compacting":
case "response.image_generation_call.partial_image":
case "response.mcp_list_tools.in_progress":
case "response.mcp_list_tools.completed":
case "response.mcp_list_tools.failed":
case "keepalive":
case "error": {
return true;
}
default: {
return false;
}
}
}
function createResponseContext() {
return createCanonicalResponseContext();
}
function accumulateResponseWithContext(event, snapshot, context, rejectInvalidShellTargets = false, onSanitizedEvent) {
const dispatchEvent = sanitizeResponseEvent(event);
if (onSanitizedEvent && dispatchEvent.type !== "keepalive") {
onSanitizedEvent(dispatchEvent);
}
if (!snapshot) {
if (dispatchEvent.type !== "response.created") {
throw new OpenAIError(`When snapshot hasn't been set yet, expected 'response.created' event, got ${dispatchEvent.type}`);
}
return cloneValidatedResponse(context, dispatchEvent.response);
}
validateOutputItemIdentity(dispatchEvent, snapshot, rejectInvalidShellTargets);
if (accumulateOutputItemEvent(dispatchEvent, snapshot, context)) {
return snapshot;
}
if (accumulateContentPartAddedEvent(dispatchEvent, snapshot, context)) {
return snapshot;
}
if (accumulateContentPartDoneEvent(dispatchEvent, snapshot, context)) {
return snapshot;
}
if (accumulateOutputTextEvent(dispatchEvent, snapshot, context)) {
return snapshot;
}
if (accumulateRefusalAndArgumentsEvent(dispatchEvent, snapshot)) {
return snapshot;
}
if (accumulateShellEvent(dispatchEvent, snapshot)) {
return snapshot;
}
if (accumulateReasoningEvent(dispatchEvent, snapshot)) {
return snapshot;
}
if (accumulateCodeInterpreterEvent(dispatchEvent, snapshot)) {
return snapshot;
}
if (accumulateSearchStatusEvent(dispatchEvent, snapshot)) {
return snapshot;
}
if (accumulateImageAndMcpStatusEvent(dispatchEvent, snapshot)) {
return snapshot;
}
if (isResponseLifecycleEvent(dispatchEvent)) {
return cloneValidatedResponse(context, dispatchEvent.response);
}
if (isIgnoredResponseEvent(dispatchEvent)) {
return snapshot;
}
return assertNever3(dispatchEvent);
}
var responseOutputIdentityIndexes, expectedOutputItemTypes, supportedResponseEventTypes, responseEventRoutingFields;
var init_response_accumulator = __esm({
"node_modules/openai/internal/responses/response-accumulator.mjs"() {
init_error2();
init_utils2();
init_canonical_output_text();
responseOutputIdentityIndexes = /* @__PURE__ */ new WeakMap();
expectedOutputItemTypes = {
"response.output_text.delta": "message",
"response.output_text.done": "message",
"response.output_text.annotation.added": "message",
"response.refusal.delta": "message",
"response.refusal.done": "message",
"response.function_call_arguments.delta": "function_call",
"response.function_call_arguments.done": "function_call",
"response.custom_tool_call_input.delta": "custom_tool_call",
"response.custom_tool_call_input.done": "custom_tool_call",
"response.mcp_call_arguments.delta": "mcp_call",
"response.mcp_call_arguments.done": "mcp_call",
"response.mcp_call.in_progress": "mcp_call",
"response.mcp_call.completed": "mcp_call",
"response.mcp_call.failed": "mcp_call",
"response.shell_call_output_content.delta": "shell_call_output",
"response.shell_call_output_content.done": "shell_call_output",
"response.reasoning_text.delta": "reasoning",
"response.reasoning_text.done": "reasoning",
"response.reasoning_summary_part.added": "reasoning",
"response.reasoning_summary_part.done": "reasoning",
"response.reasoning_summary_text.delta": "reasoning",
"response.reasoning_summary_text.done": "reasoning",
"response.code_interpreter_call_code.delta": "code_interpreter_call",
"response.code_interpreter_call_code.done": "code_interpreter_call",
"response.code_interpreter_call.in_progress": "code_interpreter_call",
"response.code_interpreter_call.interpreting": "code_interpreter_call",
"response.code_interpreter_call.completed": "code_interpreter_call",
"response.file_search_call.in_progress": "file_search_call",
"response.file_search_call.searching": "file_search_call",
"response.file_search_call.completed": "file_search_call",
"response.web_search_call.in_progress": "web_search_call",
"response.web_search_call.searching": "web_search_call",
"response.web_search_call.completed": "web_search_call",
"response.image_generation_call.in_progress": "image_generation_call",
"response.image_generation_call.generating": "image_generation_call",
"response.image_generation_call.completed": "image_generation_call",
"response.image_generation_call.partial_image": "image_generation_call",
"response.mcp_list_tools.in_progress": "mcp_list_tools",
"response.mcp_list_tools.completed": "mcp_list_tools",
"response.mcp_list_tools.failed": "mcp_list_tools",
"response.compaction.compacting": "compaction"
};
supportedResponseEventTypes = createSupportedResponseEventTypes([
"response.output_item.added",
"response.output_item.done",
"response.content_part.added",
"response.content_part.done",
"response.output_text.delta",
"response.output_text.done",
"response.output_text.annotation.added",
"response.refusal.delta",
"response.refusal.done",
"response.function_call_arguments.delta",
"response.function_call_arguments.done",
"response.custom_tool_call_input.delta",
"response.custom_tool_call_input.done",
"response.mcp_call_arguments.delta",
"response.mcp_call_arguments.done",
"response.shell_call_command.added",
"response.shell_call_command.done",
"response.shell_call_command.delta",
"response.shell_call_output_content.delta",
"response.shell_call_output_content.done",
"response.reasoning_text.delta",
"response.reasoning_text.done",
"response.reasoning_summary_part.added",
"response.reasoning_summary_part.done",
"response.reasoning_summary_text.delta",
"response.reasoning_summary_text.done",
"response.code_interpreter_call_code.delta",
"response.code_interpreter_call_code.done",
"response.code_interpreter_call.in_progress",
"response.code_interpreter_call.interpreting",
"response.code_interpreter_call.completed",
"response.file_search_call.in_progress",
"response.file_search_call.searching",
"response.file_search_call.completed",
"response.web_search_call.in_progress",
"response.web_search_call.searching",
"response.web_search_call.completed",
"response.image_generation_call.in_progress",
"response.image_generation_call.generating",
"response.image_generation_call.completed",
"response.mcp_call.in_progress",
"response.mcp_call.completed",
"response.mcp_call.failed",
"response.created",
"response.queued",
"response.in_progress",
"response.completed",
"response.failed",
"response.incomplete",
"response.audio.delta",
"response.audio.done",
"response.audio.transcript.delta",
"response.audio.transcript.done",
"response.compaction.compacting",
"response.image_generation_call.partial_image",
"response.mcp_list_tools.in_progress",
"response.mcp_list_tools.completed",
"response.mcp_list_tools.failed",
"keepalive",
"error"
]);
responseEventRoutingFields = [
"item_id",
"output_index",
"content_index",
"annotation_index",
"command_index",
"summary_index"
];
}
});
// node_modules/openai/lib/responses/ResponseStream.mjs
function finalizeResponse(snapshot, params) {
return maybeParseResponse(snapshot, params);
}
var _ResponseStream_instances, _ResponseStream_params, _ResponseStream_currentResponseSnapshot, _ResponseStream_finalResponse, _ResponseStream_accumulatorContext, _ResponseStream_beginRequest, _ResponseStream_addEvent, _ResponseStream_endRequest, ResponseStream;
var init_ResponseStream = __esm({
"node_modules/openai/lib/responses/ResponseStream.mjs"() {
init_tslib();
init_error2();
init_EventStream();
init_response_accumulator();
init_ResponsesParser();
init_streaming2();
ResponseStream = class _ResponseStream extends EventStream2 {
/** Creates an unstarted stream, retaining request parameters for structured-output parsing. */
constructor(params) {
super();
_ResponseStream_instances.add(this);
_ResponseStream_params.set(this, void 0);
_ResponseStream_currentResponseSnapshot.set(this, void 0);
_ResponseStream_finalResponse.set(this, void 0);
_ResponseStream_accumulatorContext.set(this, createResponseContext());
__classPrivateFieldSet(this, _ResponseStream_params, params, "f");
}
/** Starts a new response stream or replays an existing response by its identifier. */
static createResponse(client, params, options) {
const runner = new _ResponseStream(params);
runner._run(() => runner._createOrRetrieveResponse(client, params, {
...options,
__metadata: { ...options?.__metadata, helperMethod: "stream" }
}));
return runner;
}
/** Consumes serialized response events from a readable stream in another runtime. */
static fromReadableStream(stream2) {
const runner = new _ResponseStream(null);
runner._run(() => runner._fromReadableStream(stream2));
return runner;
}
async _createOrRetrieveResponse(client, params, options) {
this._listenForAbort(options?.signal);
__classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_beginRequest).call(this);
let stream2;
let starting_after = null;
if ("response_id" in params) {
stream2 = await client.responses.retrieve(params.response_id, { stream: true }, { ...options, signal: this.controller.signal, stream: true });
starting_after = params.starting_after ?? null;
} else {
stream2 = await client.responses.create({ ...params, stream: true }, { ...options, signal: this.controller.signal });
}
this._connected();
for await (const event of stream2) {
__classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_addEvent).call(this, event, starting_after);
}
if (stream2.controller.signal?.aborted) {
throw this._userAbortError();
}
return __classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_endRequest).call(this);
}
async _fromReadableStream(readableStream, options) {
this._listenForAbort(options?.signal);
__classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_beginRequest).call(this);
this._connected();
const stream2 = Stream.fromReadableStream(readableStream, this.controller);
for await (const event of stream2) {
__classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_addEvent).call(this, event, null);
}
if (stream2.controller.signal?.aborted) {
throw this._userAbortError();
}
return __classPrivateFieldGet(this, _ResponseStream_instances, "m", _ResponseStream_endRequest).call(this);
}
/** Iterates over response events; stopping iteration early aborts the underlying request. */
[(_ResponseStream_params = /* @__PURE__ */ new WeakMap(), _ResponseStream_currentResponseSnapshot = /* @__PURE__ */ new WeakMap(), _ResponseStream_finalResponse = /* @__PURE__ */ new WeakMap(), _ResponseStream_accumulatorContext = /* @__PURE__ */ new WeakMap(), _ResponseStream_instances = /* @__PURE__ */ new WeakSet(), _ResponseStream_beginRequest = function _ResponseStream_beginRequest2() {
if (this.ended) {
return;
}
__classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, void 0, "f");
__classPrivateFieldSet(this, _ResponseStream_accumulatorContext, createResponseContext(), "f");
}, _ResponseStream_addEvent = function _ResponseStream_addEvent2(event, starting_after) {
if (this.ended) {
return;
}
const maybeEmit = (name, event2) => {
if (starting_after == null || event2.sequence_number > starting_after) {
this._emit(name, event2);
}
};
if (event.type === "error") {
const error = (
// oxlint-disable-next-line anti-slop/no-runtime-typeof -- An error event can contain malformed server data; validate its container before extracting error details.
"error" in event && typeof event.error === "object" && event.error !== null ? event.error : event
);
throw new APIError(void 0, error, event.message, void 0);
}
let dispatchEvent = event;
const response = accumulateResponseWithContext(event, __classPrivateFieldGet(this, _ResponseStream_currentResponseSnapshot, "f"), __classPrivateFieldGet(this, _ResponseStream_accumulatorContext, "f"), true, (sanitizedEvent) => {
dispatchEvent = sanitizedEvent;
});
__classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, response, "f");
maybeEmit("event", event);
switch (dispatchEvent.type) {
case "response.output_text.delta": {
const output = response.output[dispatchEvent.output_index];
if (!output) {
throw new OpenAIError(`missing output at index ${dispatchEvent.output_index}`);
}
if (output.type === "message") {
const content = output.content[dispatchEvent.content_index];
if (!content) {
throw new OpenAIError(`missing content at index ${dispatchEvent.content_index}`);
}
if (content.type !== "output_text") {
throw new OpenAIError(`expected content to be 'output_text', got ${content.type}`);
}
maybeEmit("response.output_text.delta", {
...dispatchEvent,
type: dispatchEvent.type,
item_id: dispatchEvent.item_id,
output_index: dispatchEvent.output_index,
content_index: dispatchEvent.content_index,
snapshot: content.text
});
}
break;
}
case "response.function_call_arguments.delta": {
const output = response.output[dispatchEvent.output_index];
if (!output) {
throw new OpenAIError(`missing output at index ${dispatchEvent.output_index}`);
}
if (output.type === "function_call") {
maybeEmit("response.function_call_arguments.delta", {
...dispatchEvent,
type: dispatchEvent.type,
item_id: dispatchEvent.item_id,
output_index: dispatchEvent.output_index,
snapshot: output.arguments
});
}
break;
}
default: {
maybeEmit(dispatchEvent.type, event);
break;
}
}
}, _ResponseStream_endRequest = function _ResponseStream_endRequest2() {
if (this.ended) {
throw new OpenAIError(`stream has ended, this shouldn't happen`);
}
const snapshot = __classPrivateFieldGet(this, _ResponseStream_currentResponseSnapshot, "f");
if (!snapshot) {
throw new OpenAIError(`request ended without sending any events`);
}
__classPrivateFieldSet(this, _ResponseStream_currentResponseSnapshot, void 0, "f");
__classPrivateFieldSet(this, _ResponseStream_accumulatorContext, createResponseContext(), "f");
const parsedResponse = finalizeResponse(snapshot, __classPrivateFieldGet(this, _ResponseStream_params, "f"));
__classPrivateFieldSet(this, _ResponseStream_finalResponse, parsedResponse, "f");
return parsedResponse;
}, Symbol.asyncIterator)]() {
return this._createIterator((push) => {
const onEvent = (event) => push(event);
this.on("event", onEvent);
return () => this.off("event", onEvent);
}, { onReturn: () => this.abort() });
}
/**
* Waits for the stream to end and returns its latest accumulated response.
*
* A clean end after at least one response event resolves even when the response is
* incomplete. Network errors, cancellation, and streams without a response reject.
*/
async finalResponse() {
await this.done();
const response = __classPrivateFieldGet(this, _ResponseStream_finalResponse, "f");
if (!response) {
throw new OpenAIError("stream ended without producing a Response");
}
return response;
}
};
}
});
// node_modules/openai/resources/responses/input-items.mjs
var InputItems2;
var init_input_items2 = __esm({
"node_modules/openai/resources/responses/input-items.mjs"() {
init_resource();
init_pagination();
init_path();
InputItems2 = class extends APIResource {
/**
* Returns a list of input items for a given response.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const responseItem of client.responses.inputItems.list(
* 'response_id',
* )) {
* // ...
* }
* ```
*/
list(responseID, query = {}, options) {
return this._client.getAPIList(path`/responses/${responseID}/input_items`, CursorPage, { query, ...options, __security: { bearerAuth: true } });
}
};
}
});
// node_modules/openai/resources/responses/input-tokens.mjs
var InputTokens2;
var init_input_tokens2 = __esm({
"node_modules/openai/resources/responses/input-tokens.mjs"() {
init_resource();
InputTokens2 = class extends APIResource {
/**
* Returns input token counts of the request.
*
* Returns an object with `object` set to `response.input_tokens` and an
* `input_tokens` count.
*
* @example
* ```ts
* const response = await client.responses.inputTokens.count();
* ```
*/
count(body = {}, options) {
return this._client.post("/responses/input_tokens", {
body,
...options,
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/responses/responses.mjs
var Responses2;
var init_responses2 = __esm({
"node_modules/openai/resources/responses/responses.mjs"() {
init_ResponsesParser();
init_ResponseStream();
init_resource();
init_input_items2();
init_input_items2();
init_input_tokens2();
init_input_tokens2();
init_headers2();
init_path();
Responses2 = class extends APIResource {
constructor() {
super(...arguments);
this.inputItems = new InputItems2(this._client);
this.inputTokens = new InputTokens2(this._client);
}
create(body, options) {
return this._client.post("/responses", {
body,
...options,
stream: body.stream ?? false,
__security: { bearerAuth: true }
})._thenUnwrap((rsp) => {
if ("object" in rsp && rsp.object === "response") {
addOutputText(rsp);
}
return rsp;
});
}
retrieve(responseID, query = {}, options) {
return this._client.get(path`/responses/${responseID}`, {
query,
...options,
stream: query?.stream ?? false,
__security: { bearerAuth: true }
})._thenUnwrap((rsp) => {
if ("object" in rsp && rsp.object === "response") {
addOutputText(rsp);
}
return rsp;
});
}
/**
* Deletes a model response with the given ID.
*
* @example
* ```ts
* await client.responses.delete(
* 'resp_677efb5139a88190b512bc3fef8e535d',
* );
* ```
*/
delete(responseID, options) {
return this._client.delete(path`/responses/${responseID}`, {
...options,
headers: buildHeaders([{ Accept: "*/*" }, options?.headers]),
__security: { bearerAuth: true }
});
}
parse(body, options) {
return this._client.responses.create(body, options)._thenUnwrap((response) => parseResponse(response, body));
}
/**
* Creates a model response stream
*/
stream(body, options) {
return ResponseStream.createResponse(this._client, body, options);
}
/**
* Cancels a model response with the given ID. Only responses created with the
* `background` parameter set to `true` can be cancelled.
* [Learn more](https://developers.openai.com/api/docs/guides/background).
*
* @example
* ```ts
* const response = await client.responses.cancel(
* 'resp_677efb5139a88190b512bc3fef8e535d',
* );
* ```
*/
cancel(responseID, options) {
return this._client.post(path`/responses/${responseID}/cancel`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Compact a conversation. Returns a compacted response object.
*
* Learn when and how to compact long-running conversations in the
* [conversation state guide](https://developers.openai.com/api/docs/guides/conversation-state#managing-the-context-window).
* For ZDR-compatible compaction details, see
* [Compaction (advanced)](https://developers.openai.com/api/docs/guides/conversation-state#compaction-advanced).
*
* @example
* ```ts
* const compactedResponse = await client.responses.compact({
* model: 'gpt-6-astra',
* });
* ```
*/
compact(body, options) {
return this._client.post("/responses/compact", { body, ...options, __security: { bearerAuth: true } });
}
};
Responses2.InputItems = InputItems2;
Responses2.InputTokens = InputTokens2;
}
});
// node_modules/openai/resources/safety/alerts.mjs
var Alerts;
var init_alerts = __esm({
"node_modules/openai/resources/safety/alerts.mjs"() {
init_resource();
init_path();
Alerts = class extends APIResource {
/**
* Get a safety alert belonging to the authenticated API project.
*/
retrieve(id, options) {
return this._client.get(path`/safety/alerts/${id}`, { ...options, __security: { bearerAuth: true } });
}
};
}
});
// node_modules/openai/resources/safety/safety.mjs
var Safety;
var init_safety = __esm({
"node_modules/openai/resources/safety/safety.mjs"() {
init_resource();
init_alerts();
init_alerts();
Safety = class extends APIResource {
constructor() {
super(...arguments);
this.alerts = new Alerts(this._client);
}
};
Safety.Alerts = Alerts;
}
});
// node_modules/openai/resources/skills/content.mjs
var Content2;
var init_content2 = __esm({
"node_modules/openai/resources/skills/content.mjs"() {
init_resource();
init_headers2();
init_path();
Content2 = class extends APIResource {
/**
* Download a skill zip bundle by its ID.
*/
retrieve(skillID, options) {
return this._client.get(path`/skills/${skillID}/content`, {
...options,
headers: buildHeaders([{ Accept: "application/binary" }, options?.headers]),
__security: { bearerAuth: true },
__binaryResponse: true
});
}
};
}
});
// node_modules/openai/resources/skills/versions/content.mjs
var Content3;
var init_content3 = __esm({
"node_modules/openai/resources/skills/versions/content.mjs"() {
init_resource();
init_headers2();
init_path();
Content3 = class extends APIResource {
/**
* Download a skill version zip bundle.
*/
retrieve(version, params, options) {
const { skill_id } = params;
return this._client.get(path`/skills/${skill_id}/versions/${version}/content`, {
...options,
headers: buildHeaders([{ Accept: "application/binary" }, options?.headers]),
__security: { bearerAuth: true },
__binaryResponse: true
});
}
};
}
});
// node_modules/openai/resources/skills/versions/versions.mjs
var Versions;
var init_versions = __esm({
"node_modules/openai/resources/skills/versions/versions.mjs"() {
init_resource();
init_content3();
init_content3();
init_pagination();
init_uploads();
init_path();
Versions = class extends APIResource {
constructor() {
super(...arguments);
this.content = new Content3(this._client);
}
/**
* Create a new immutable skill version.
*/
create(skillID, body = {}, options) {
return this._client.post(path`/skills/${skillID}/versions`, maybeMultipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client, {
stripFilenames: false
}));
}
/**
* Get a specific skill version.
*/
retrieve(version, params, options) {
const { skill_id } = params;
return this._client.get(path`/skills/${skill_id}/versions/${version}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* List skill versions for a skill.
*/
list(skillID, query = {}, options) {
return this._client.getAPIList(path`/skills/${skillID}/versions`, CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Delete a skill version.
*/
delete(version, params, options) {
const { skill_id } = params;
return this._client.delete(path`/skills/${skill_id}/versions/${version}`, {
...options,
__security: { bearerAuth: true }
});
}
};
Versions.Content = Content3;
}
});
// node_modules/openai/resources/skills/skills.mjs
var Skills;
var init_skills = __esm({
"node_modules/openai/resources/skills/skills.mjs"() {
init_resource();
init_content2();
init_content2();
init_versions();
init_versions();
init_pagination();
init_uploads();
init_path();
Skills = class extends APIResource {
constructor() {
super(...arguments);
this.content = new Content2(this._client);
this.versions = new Versions(this._client);
}
/**
* Create a new skill.
*/
create(body = {}, options) {
return this._client.post("/skills", maybeMultipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client, {
stripFilenames: false
}));
}
/**
* Get a skill by its ID.
*/
retrieve(skillID, options) {
return this._client.get(path`/skills/${skillID}`, { ...options, __security: { bearerAuth: true } });
}
/**
* Update the default version pointer for a skill.
*/
update(skillID, body, options) {
return this._client.post(path`/skills/${skillID}`, {
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* List all skills for the current project.
*/
list(query = {}, options) {
return this._client.getAPIList("/skills", CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Delete a skill by its ID.
*/
delete(skillID, options) {
return this._client.delete(path`/skills/${skillID}`, { ...options, __security: { bearerAuth: true } });
}
};
Skills.Content = Content2;
Skills.Versions = Versions;
}
});
// node_modules/openai/resources/uploads/parts.mjs
var Parts;
var init_parts = __esm({
"node_modules/openai/resources/uploads/parts.mjs"() {
init_resource();
init_uploads();
init_path();
Parts = class extends APIResource {
/**
* Adds a
* [Part](https://developers.openai.com/api/reference/resources/uploads/subresources/parts)
* to an [Upload](https://developers.openai.com/api/reference/resources/uploads)
* object. A Part represents a chunk of bytes from the file you are trying to
* upload.
*
* Each Part can be at most 64 MB, and you can add Parts until you hit the Upload
* maximum of 8 GB.
*
* It is possible to add multiple Parts in parallel. You can decide the intended
* order of the Parts when you
* [complete the Upload](https://developers.openai.com/api/reference/resources/uploads/methods/complete).
*/
create(uploadID, body, options) {
return this._client.post(path`/uploads/${uploadID}/parts`, multipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
};
}
});
// node_modules/openai/resources/uploads/uploads.mjs
var Uploads;
var init_uploads3 = __esm({
"node_modules/openai/resources/uploads/uploads.mjs"() {
init_resource();
init_parts();
init_parts();
init_path();
Uploads = class extends APIResource {
constructor() {
super(...arguments);
this.parts = new Parts(this._client);
}
/**
* Creates an intermediate
* [Upload](https://developers.openai.com/api/reference/resources/uploads) object
* that you can add
* [Parts](https://developers.openai.com/api/reference/resources/uploads/subresources/parts)
* to. Currently, an Upload can accept at most 8 GB in total and expires after an
* hour after you create it.
*
* Once you complete the Upload, we will create a
* [File](https://developers.openai.com/api/reference/resources/files) object that
* contains all the parts you uploaded. This File is usable in the rest of our
* platform as a regular File object.
*
* For certain `purpose` values, the correct `mime_type` must be specified. Please
* refer to documentation for the
* [supported MIME types for your use case](https://developers.openai.com/api/docs/guides/tools-file-search#supported-files).
*
* For guidance on the proper filename extensions for each purpose, please follow
* the documentation on
* [creating a File](https://developers.openai.com/api/reference/resources/files/methods/create).
*
* Returns the Upload object with status `pending`.
*/
create(body, options) {
return this._client.post("/uploads", { body, ...options, __security: { bearerAuth: true } });
}
/**
* Cancels the Upload. No Parts may be added after an Upload is cancelled.
*
* Returns the Upload object with status `cancelled`.
*/
cancel(uploadID, options) {
return this._client.post(path`/uploads/${uploadID}/cancel`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Completes the
* [Upload](https://developers.openai.com/api/reference/resources/uploads).
*
* Within the returned Upload object, there is a nested
* [File](https://developers.openai.com/api/reference/resources/files) object that
* is ready to use in the rest of the platform.
*
* You can specify the order of the Parts by passing in an ordered list of the Part
* IDs.
*
* The number of bytes uploaded upon completion must match the number of bytes
* initially specified when creating the Upload object. No Parts may be added after
* an Upload is completed. Returns the Upload object with status `completed`,
* including an additional `file` property containing the created usable File
* object.
*/
complete(uploadID, body, options) {
return this._client.post(path`/uploads/${uploadID}/complete`, {
body,
...options,
__security: { bearerAuth: true }
});
}
};
Uploads.Parts = Parts;
}
});
// node_modules/openai/lib/vector-store-polling.mjs
function pollVectorStoreFile(resource, vectorStoreID, fileID, options) {
return pollWithResponse((headers) => resource.retrieve(fileID, { vector_store_id: vectorStoreID }, { ...options, headers }), ["in_progress"], ["failed", "cancelled", "completed"], options);
}
function pollVectorStoreFileBatch(resource, vectorStoreID, batchID, options) {
return pollWithResponse((headers) => resource.retrieve(batchID, { vector_store_id: vectorStoreID }, { ...options, headers }), ["in_progress"], ["failed", "cancelled", "completed"], options);
}
var init_vector_store_polling = __esm({
"node_modules/openai/lib/vector-store-polling.mjs"() {
init_polling();
}
});
// node_modules/openai/lib/Util.mjs
var allSettledWithThrow;
var init_Util = __esm({
"node_modules/openai/lib/Util.mjs"() {
allSettledWithThrow = async (promises) => {
const results = await Promise.allSettled(promises);
const rejected = results.filter((result) => result.status === "rejected");
if (rejected.length) {
throw Object.defineProperty(new Error(`${rejected.length} promise(s) failed`), "rejections", {
configurable: true,
value: rejected.map(({ reason }) => reason),
writable: true
});
}
const values = [];
for (const result of results) {
if (result.status === "fulfilled") {
values.push(result.value);
}
}
return values;
};
}
});
// node_modules/openai/lib/vector-store-upload.mjs
async function uploadAndPollVectorStoreFileBatch(resource, client, vectorStoreId, files, fileIds, options) {
if (files === null || files === void 0 || files.length === 0) {
throw new Error("No `files` provided to process. If you've already uploaded files you should use `.createAndPoll()` instead");
}
const configuredConcurrency = options?.maxConcurrency ?? 5;
const concurrencyLimit = Math.min(configuredConcurrency, files.length);
if (concurrencyLimit === 0) {
throw new RangeError("maxConcurrency must be greater than 0");
}
const fileIterator = files.values();
const allFileIds = [...fileIds];
async function processFiles(iterator) {
for (const item of iterator) {
const fileObj = await client.files.create({ file: item, purpose: "assistants" }, options);
allFileIds.push(fileObj.id);
}
}
const workers = [];
workers.length = concurrencyLimit;
for (let index = 0; index < workers.length; index += 1) {
workers[index] = processFiles(fileIterator);
}
await allSettledWithThrow(workers);
return await resource.createAndPoll(vectorStoreId, { file_ids: allFileIds }, options);
}
var init_vector_store_upload = __esm({
"node_modules/openai/lib/vector-store-upload.mjs"() {
init_Util();
}
});
// node_modules/openai/resources/vector-stores/file-batches.mjs
var FileBatches;
var init_file_batches = __esm({
"node_modules/openai/resources/vector-stores/file-batches.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_vector_store_polling();
init_vector_store_upload();
init_path();
FileBatches = class extends APIResource {
/**
* Create a vector store file batch.
*/
create(vectorStoreID, body, options) {
return this._client.post(path`/vector_stores/${vectorStoreID}/file_batches`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieves a vector store file batch.
*/
retrieve(batchID, params, options) {
const { vector_store_id } = params;
return this._client.get(path`/vector_stores/${vector_store_id}/file_batches/${batchID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Cancel a vector store file batch. This attempts to cancel the processing of
* files in this batch as soon as possible.
*/
cancel(batchID, params, options) {
const { vector_store_id } = params;
return this._client.post(path`/vector_stores/${vector_store_id}/file_batches/${batchID}/cancel`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Create a vector store batch and poll until all files have been processed.
*/
async createAndPoll(vectorStoreId, body, options) {
const batch = await this.create(vectorStoreId, body, options);
return await this.poll(vectorStoreId, batch.id, options);
}
/**
* Returns a list of vector store files in a batch.
*/
listFiles(batchID, params, options) {
const { vector_store_id, ...query } = params;
return this._client.getAPIList(path`/vector_stores/${vector_store_id}/file_batches/${batchID}/files`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Wait for the given file batch to be processed.
*
* Note: this will return even if one of the files failed to process, you need to
* check batch.file_counts.failed_count to handle this case.
*/
async poll(vectorStoreID, batchID, options) {
return await pollVectorStoreFileBatch(this, vectorStoreID, batchID, options);
}
/**
* Uploads the given files concurrently and then creates a vector store file batch.
*
* The concurrency limit is configurable using the `maxConcurrency` parameter.
*/
async uploadAndPoll(vectorStoreId, { files, fileIds = [] }, options) {
return await uploadAndPollVectorStoreFileBatch(this, this._client, vectorStoreId, files, fileIds, options);
}
};
}
});
// node_modules/openai/resources/vector-stores/files.mjs
var Files4;
var init_files4 = __esm({
"node_modules/openai/resources/vector-stores/files.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_vector_store_polling();
init_path();
Files4 = class extends APIResource {
/**
* Create a vector store file by attaching a
* [File](https://developers.openai.com/api/reference/resources/files) to a
* [vector store](https://developers.openai.com/api/reference/resources/vector_stores).
*/
create(vectorStoreID, body, options) {
return this._client.post(path`/vector_stores/${vectorStoreID}/files`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieves a vector store file.
*/
retrieve(fileID, params, options) {
const { vector_store_id } = params;
return this._client.get(path`/vector_stores/${vector_store_id}/files/${fileID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Update attributes on a vector store file.
*/
update(fileID, params, options) {
const { vector_store_id, ...body } = params;
return this._client.post(path`/vector_stores/${vector_store_id}/files/${fileID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Returns a list of vector store files.
*/
list(vectorStoreID, query = {}, options) {
return this._client.getAPIList(path`/vector_stores/${vectorStoreID}/files`, CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Delete a vector store file. This will remove the file from the vector store but
* the file itself will not be deleted. To delete the file, use the
* [delete file](https://developers.openai.com/api/reference/resources/files/methods/delete)
* endpoint.
*/
delete(fileID, params, options) {
const { vector_store_id } = params;
return this._client.delete(path`/vector_stores/${vector_store_id}/files/${fileID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Attach a file to the given vector store and wait for it to be processed.
*/
async createAndPoll(vectorStoreId, body, options) {
const file = await this.create(vectorStoreId, body, options);
return await this.poll(vectorStoreId, file.id, options);
}
/**
* Wait for the vector store file to finish processing.
*
* Note: this will return even if the file failed to process, you need to check
* file.last_error and file.status to handle these cases
*/
async poll(vectorStoreID, fileID, options) {
return await pollVectorStoreFile(this, vectorStoreID, fileID, options);
}
/**
* Upload a file to the `files` API and then attach it to the given vector store.
*
* Note the file will be asynchronously processed (you can use the alternative
* polling helper method to wait for processing to complete).
*/
async upload(vectorStoreId, file, options) {
const fileInfo = await this._client.files.create({ file, purpose: "assistants" }, options);
return this.create(vectorStoreId, { file_id: fileInfo.id }, options);
}
/**
* Add a file to a vector store and poll until processing is complete.
*/
async uploadAndPoll(vectorStoreId, file, options) {
const fileInfo = await this.upload(vectorStoreId, file, options);
return await this.poll(vectorStoreId, fileInfo.id, options);
}
/**
* Retrieve the parsed contents of a vector store file.
*/
content(fileID, params, options) {
const { vector_store_id } = params;
return this._client.getAPIList(path`/vector_stores/${vector_store_id}/files/${fileID}/content`, Page, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
}
});
// node_modules/openai/resources/vector-stores/vector-stores.mjs
var VectorStores;
var init_vector_stores = __esm({
"node_modules/openai/resources/vector-stores/vector-stores.mjs"() {
init_resource();
init_file_batches();
init_file_batches();
init_files4();
init_files4();
init_pagination();
init_headers2();
init_path();
VectorStores = class extends APIResource {
constructor() {
super(...arguments);
this.files = new Files4(this._client);
this.fileBatches = new FileBatches(this._client);
}
/**
* Create a vector store.
*/
create(body, options) {
return this._client.post("/vector_stores", {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Retrieves a vector store.
*/
retrieve(vectorStoreID, options) {
return this._client.get(path`/vector_stores/${vectorStoreID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Modifies a vector store.
*/
update(vectorStoreID, body, options) {
return this._client.post(path`/vector_stores/${vectorStoreID}`, {
body,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Returns a list of vector stores.
*/
list(query = {}, options) {
return this._client.getAPIList("/vector_stores", CursorPage, {
query,
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Delete a vector store.
*/
delete(vectorStoreID, options) {
return this._client.delete(path`/vector_stores/${vectorStoreID}`, {
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
/**
* Search a vector store for relevant chunks based on a query and file attributes
* filter.
*/
search(vectorStoreID, body, options) {
return this._client.getAPIList(path`/vector_stores/${vectorStoreID}/search`, Page, {
body,
method: "post",
...options,
headers: buildHeaders([{ "OpenAI-Beta": "assistants=v2" }, options?.headers]),
__security: { bearerAuth: true }
});
}
};
VectorStores.Files = Files4;
VectorStores.FileBatches = FileBatches;
}
});
// node_modules/openai/resources/videos.mjs
var Videos;
var init_videos = __esm({
"node_modules/openai/resources/videos.mjs"() {
init_resource();
init_pagination();
init_headers2();
init_uploads();
init_path();
Videos = class extends APIResource {
/**
* Create a new video generation job from a prompt and optional reference assets.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
create(body, options) {
return this._client.post("/videos", multipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
/**
* Fetch the latest metadata for a generated video.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
retrieve(videoID, options) {
return this._client.get(path`/videos/${videoID}`, { ...options, __security: { bearerAuth: true } });
}
/**
* List recently generated videos for the current project.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
list(query = {}, options) {
return this._client.getAPIList("/videos", ConversationCursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Permanently delete a completed or failed video and its stored assets.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
delete(videoID, options) {
return this._client.delete(path`/videos/${videoID}`, { ...options, __security: { bearerAuth: true } });
}
/**
* Create a character from an uploaded video.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
createCharacter(body, options) {
return this._client.post("/videos/characters", multipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
/**
* Download the generated video bytes or a derived preview asset.
*
* Streams the rendered video content for the specified video job.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
downloadContent(videoID, query = {}, options) {
return this._client.get(path`/videos/${videoID}/content`, {
query,
...options,
headers: buildHeaders([{ Accept: "application/binary" }, options?.headers]),
__security: { bearerAuth: true },
__binaryResponse: true
});
}
/**
* Create a new video generation job by editing a source video or existing
* generated video.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
edit(body, options) {
return this._client.post("/videos/edits", multipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
/**
* Create an extension of a completed video.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
extend(body, options) {
return this._client.post("/videos/extensions", multipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
/**
* Fetch a character.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
getCharacter(characterID, options) {
return this._client.get(path`/videos/characters/${characterID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Create a remix of a completed video using a refreshed prompt.
*
* @deprecated The Sora API is scheduled to permanently shut down on September 24, 2026.
*/
remix(videoID, body, options) {
return this._client.post(path`/videos/${videoID}/remix`, maybeMultipartFormRequestOptions({ body, ...options, __security: { bearerAuth: true } }, this._client));
}
};
}
});
// node_modules/openai/lib/webhook-signature.mjs
function webhookSignatureRequiresSigning(signatureHeader) {
return signatureHeader.split(" ", MAX_DIRECT_WEBHOOK_VERIFICATIONS + 1).length > MAX_DIRECT_WEBHOOK_VERIFICATIONS;
}
function* signatureCandidates(signatureHeader) {
let start = 0;
while (start <= signatureHeader.length) {
const separator = signatureHeader.indexOf(" ", start);
const candidate = signatureHeader.slice(start, separator === -1 ? void 0 : separator);
yield candidate.startsWith("v1,") ? candidate.slice(3) : candidate;
if (separator === -1) {
break;
}
start = separator + 1;
}
}
function decodeSignature(signature) {
try {
const signatureBytes = fromBase64(signature);
return signatureBytes.byteLength === SHA256_SIGNATURE_LENGTH ? signatureBytes : void 0;
} catch {
return void 0;
}
}
function firstValidLengthSignature(signatureHeader) {
for (const signature of signatureCandidates(signatureHeader)) {
const signatureBytes = decodeSignature(signature);
if (signatureBytes) {
return signatureBytes;
}
}
return void 0;
}
function selectMatchingSignature(signatureHeader, expectedSignature, firstSignature) {
let matchingSignature = firstSignature;
for (const signature of signatureCandidates(signatureHeader)) {
const signatureBytes = decodeSignature(signature);
if (!signatureBytes) {
continue;
}
let difference = 0;
for (const [index, byte] of signatureBytes.entries()) {
difference |= byte ^ (expectedSignature[index] ?? 0);
}
if (difference === 0) {
matchingSignature = signatureBytes;
}
}
return matchingSignature;
}
async function verifyWebhookSignature(payload, signatureHeader, timestamp, webhookId, secret, tolerance) {
const timestampSeconds = Number.parseInt(timestamp, 10);
if (Number.isNaN(timestampSeconds)) {
throw new InvalidWebhookSignatureError("Invalid webhook timestamp format");
}
const nowSeconds = Math.floor(Date.now() / 1e3);
if (nowSeconds - timestampSeconds > tolerance) {
throw new InvalidWebhookSignatureError("Webhook timestamp is too old");
}
if (timestampSeconds > nowSeconds + tolerance) {
throw new InvalidWebhookSignatureError("Webhook timestamp is too new");
}
const useBoundedVerification = webhookSignatureRequiresSigning(signatureHeader);
const firstSignature = useBoundedVerification ? firstValidLengthSignature(signatureHeader) : void 0;
if (useBoundedVerification && !firstSignature) {
throw new InvalidWebhookSignatureError("The given webhook signature does not match the expected signature");
}
const decodedSecret = Uint8Array.from(secret.startsWith("whsec_") ? fromBase64(secret.slice("whsec_".length)) : encodeUTF8(secret));
const signedPayload = webhookId ? `${webhookId}.${timestamp}.${payload}` : `${timestamp}.${payload}`;
const signedPayloadBytes = Uint8Array.from(encodeUTF8(signedPayload));
const key = await crypto.subtle.importKey("raw", decodedSecret, { name: "HMAC", hash: "SHA-256" }, false, useBoundedVerification ? ["sign", "verify"] : ["verify"]);
if (useBoundedVerification && firstSignature) {
const expectedSignature = new Uint8Array(await crypto.subtle.sign("HMAC", key, signedPayloadBytes));
const signatureToVerify = selectMatchingSignature(signatureHeader, expectedSignature, firstSignature);
try {
if (await crypto.subtle.verify("HMAC", key, Uint8Array.from(signatureToVerify), signedPayloadBytes)) {
return;
}
} catch {
}
throw new InvalidWebhookSignatureError("The given webhook signature does not match the expected signature");
}
for (const signature of signatureCandidates(signatureHeader)) {
try {
const signatureBytes = Uint8Array.from(fromBase64(signature));
const isValid = await crypto.subtle.verify("HMAC", key, signatureBytes, signedPayloadBytes);
if (isValid) {
return;
}
} catch {
}
}
throw new InvalidWebhookSignatureError("The given webhook signature does not match the expected signature");
}
var MAX_DIRECT_WEBHOOK_VERIFICATIONS, SHA256_SIGNATURE_LENGTH;
var init_webhook_signature = __esm({
"node_modules/openai/lib/webhook-signature.mjs"() {
init_error2();
init_base64();
init_bytes();
MAX_DIRECT_WEBHOOK_VERIFICATIONS = 32;
SHA256_SIGNATURE_LENGTH = 32;
}
});
// node_modules/openai/resources/webhooks/event-types.mjs
var EventTypes;
var init_event_types = __esm({
"node_modules/openai/resources/webhooks/event-types.mjs"() {
init_resource();
EventTypes = class extends APIResource {
/**
* Returns webhook event types visible to the authenticated project.
*
* @example
* ```ts
* const webhookEventTypeList =
* await client.webhooks.eventTypes.list();
* ```
*/
list(options) {
return this._client.get("/webhook_event_types", { ...options, __security: { bearerAuth: true } });
}
};
}
});
// node_modules/openai/resources/webhooks/webhooks.mjs
var _Webhooks_instances, _Webhooks_validateSecret, _Webhooks_getRequiredHeader, Webhooks;
var init_webhooks = __esm({
"node_modules/openai/resources/webhooks/webhooks.mjs"() {
init_tslib();
init_resource();
init_headers2();
init_webhook_signature();
init_event_types();
init_event_types();
init_pagination();
init_path();
Webhooks = class extends APIResource {
constructor() {
super(...arguments);
_Webhooks_instances.add(this);
this.eventTypes = new EventTypes(this._client);
}
/**
* Creates a webhook endpoint for the authenticated project.
*
* @example
* ```ts
* const webhookEndpointWithSecret =
* await client.webhooks.create({
* event_types: ['batch.completed'],
* name: 'x',
* url: 'https://',
* });
* ```
*/
create(body, options) {
return this._client.post("/webhook_endpoints", { body, ...options, __security: { bearerAuth: true } });
}
/**
* Retrieves a webhook endpoint for the authenticated project.
*
* @example
* ```ts
* const webhookEndpoint = await client.webhooks.retrieve(
* 'whe_123',
* );
* ```
*/
retrieve(webhookEndpointID, options) {
return this._client.get(path`/webhook_endpoints/${webhookEndpointID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Updates a webhook endpoint for the authenticated project.
*
* @example
* ```ts
* const webhookEndpoint = await client.webhooks.update('whe_123');
* ```
*/
update(webhookEndpointID, body = {}, options) {
return this._client.post(path`/webhook_endpoints/${webhookEndpointID}`, {
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* Returns webhook endpoints for the authenticated project in newest-first order.
*
* @example
* ```ts
* // Automatically fetches more pages as needed.
* for await (const webhookEndpoint of client.webhooks.list()) {
* // ...
* }
* ```
*/
list(query = {}, options) {
return this._client.getAPIList("/webhook_endpoints", CursorPage, {
query,
...options,
__security: { bearerAuth: true }
});
}
/**
* Deletes a webhook endpoint for the authenticated project.
*
* @example
* ```ts
* const deletedWebhookEndpoint = await client.webhooks.delete(
* 'whe_123',
* );
* ```
*/
delete(webhookEndpointID, options) {
return this._client.delete(path`/webhook_endpoints/${webhookEndpointID}`, {
...options,
__security: { bearerAuth: true }
});
}
/**
* Rotates the signing secret for a webhook endpoint in the authenticated project.
*
* @example
* ```ts
* const webhookEndpointWithSecret =
* await client.webhooks.rotateSecret('whe_123');
* ```
*/
rotateSecret(webhookEndpointID, body = {}, options) {
return this._client.post(path`/webhook_endpoints/${webhookEndpointID}/rotate_secret`, {
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* Sends a sample event to a webhook endpoint for the authenticated project.
*
* @example
* ```ts
* const webhookEndpointTestResult =
* await client.webhooks.test('whe_123', {
* event_type: 'batch.completed',
* });
* ```
*/
test(webhookEndpointID, body, options) {
return this._client.post(path`/webhook_endpoints/${webhookEndpointID}/test`, {
body,
...options,
__security: { bearerAuth: true }
});
}
/**
* Validates that the given payload was sent by OpenAI and parses the payload.
*/
async unwrap(payload, headers, secret = this._client.webhookSecret, tolerance = 300) {
await this.verifySignature(payload, headers, secret, tolerance);
return JSON.parse(payload);
}
/**
* Validates whether or not the webhook payload was sent by OpenAI.
*
* An error will be raised if the webhook payload was not sent by OpenAI.
*
* @param payload - The webhook payload
* @param headers - The webhook headers
* @param secret - The webhook secret (optional, will use client secret if not provided)
* @param tolerance - Maximum age of the webhook in seconds (default: 300 = 5 minutes)
*/
async verifySignature(payload, headers, secret = this._client.webhookSecret, tolerance = 300) {
if (typeof crypto === "undefined" || typeof crypto.subtle?.importKey !== "function" || typeof crypto.subtle.verify !== "function") {
throw new Error("Webhook signature verification is only supported when the `crypto` global is defined");
}
__classPrivateFieldGet(this, _Webhooks_instances, "m", _Webhooks_validateSecret).call(this, secret);
const headersObj = buildHeaders([headers]).values;
const signatureHeader = __classPrivateFieldGet(this, _Webhooks_instances, "m", _Webhooks_getRequiredHeader).call(this, headersObj, "webhook-signature");
const timestamp = __classPrivateFieldGet(this, _Webhooks_instances, "m", _Webhooks_getRequiredHeader).call(this, headersObj, "webhook-timestamp");
const webhookId = __classPrivateFieldGet(this, _Webhooks_instances, "m", _Webhooks_getRequiredHeader).call(this, headersObj, "webhook-id");
if (webhookSignatureRequiresSigning(signatureHeader) && typeof crypto.subtle.sign !== "function") {
throw new Error("Webhook signature verification is only supported when the `crypto` global is defined");
}
return await verifyWebhookSignature(payload, signatureHeader, timestamp, webhookId, secret, tolerance);
}
};
_Webhooks_instances = /* @__PURE__ */ new WeakSet(), _Webhooks_validateSecret = function _Webhooks_validateSecret2(secret) {
if (typeof secret !== "string" || secret.length === 0) {
throw new Error(`The webhook secret must either be set using the env var, OPENAI_WEBHOOK_SECRET, on the client class, OpenAI({ webhookSecret: '123' }), or passed to this function`);
}
}, _Webhooks_getRequiredHeader = function _Webhooks_getRequiredHeader2(headers, name) {
if (!headers) {
throw new Error(`Headers are required`);
}
const value2 = headers.get(name);
if (value2 === null || value2 === void 0) {
throw new Error(`Missing required header: ${name}`);
}
return value2;
};
Webhooks.EventTypes = EventTypes;
}
});
// node_modules/openai/resources/index.mjs
var init_resources = __esm({
"node_modules/openai/resources/index.mjs"() {
init_chat2();
init_shared();
init_admin();
init_audio();
init_batches();
init_beta();
init_completions3();
init_containers();
init_content_provenance_checks();
init_conversations();
init_embeddings2();
init_evals();
init_files3();
init_fine_tuning();
init_graders2();
init_images();
init_live();
init_models2();
init_moderations();
init_realtime2();
init_responses2();
init_safety();
init_skills();
init_uploads3();
init_vector_stores();
init_videos();
init_webhooks();
}
});
// node_modules/openai/internal/realtime-credentials.mjs
async function resolveRealtimeAPIKey(client) {
let apiKey;
const isProvider = await client._callApiKey((resolved) => {
apiKey = resolved;
});
return { apiKey: apiKey === void 0 ? client.apiKey : apiKey, isProvider };
}
var init_realtime_credentials = __esm({
"node_modules/openai/internal/realtime-credentials.mjs"() {
}
});
// node_modules/openai/internal/provider.mjs
function configureProvider(provider3) {
const definition = providerDefinitions.get(provider3);
if (!definition) {
throw new Error("Invalid provider. Providers must be created with createProvider().");
}
return definition.configure();
}
var providerDefinitionsKey, providerGlobal, existingProviderDefinitions, providerDefinitions;
var init_provider = __esm({
"node_modules/openai/internal/provider.mjs"() {
providerDefinitionsKey = /* @__PURE__ */ Symbol.for("openai.node.providerDefinitions.v1");
providerGlobal = globalThis;
existingProviderDefinitions = providerGlobal[providerDefinitionsKey];
providerDefinitions = existingProviderDefinitions ?? /* @__PURE__ */ new WeakMap();
if (!existingProviderDefinitions) {
Object.defineProperty(providerGlobal, providerDefinitionsKey, { value: providerDefinitions });
}
}
});
// node_modules/openai/client.mjs
function isRunningInBrowserOrBrowserWorker() {
if (isRunningInBrowser())
return true;
const scope = globalThis;
return typeof scope.WorkerGlobalScope === "function" && scope instanceof scope.WorkerGlobalScope && typeof scope.WorkerNavigator === "function" && scope.navigator instanceof scope.WorkerNavigator && typeof scope.navigator?.userAgent === "string" && scope.navigator.userAgent !== "Cloudflare-Workers" && scope.process?.versions?.node === void 0 && scope.Deno === void 0 && scope.Bun === void 0 && scope.EdgeRuntime === void 0 && scope.WebSocketPair === void 0;
}
function createRequestController(callerSignal, originalSignal) {
const controller = new AbortController();
if (!callerSignal)
return controller;
const nativeAbortSignal = globalThis.AbortSignal;
if (typeof nativeAbortSignal?.any !== "function" || !(callerSignal instanceof nativeAbortSignal)) {
return controller;
}
try {
const signals = [controller.signal, callerSignal];
if (originalSignal && originalSignal !== callerSignal) {
signals.push(originalSignal);
}
const composed = nativeAbortSignal.any(signals);
Object.defineProperty(controller, "signal", { value: composed, configurable: true });
composedCallerSignals.set(controller, callerSignal);
} catch {
}
return controller;
}
function getConnectionErrorMessage(error) {
if (isUndiciDispatcherVersionMismatchError(error)) {
return `Connection error. This may be caused by passing an undici dispatcher, such as ProxyAgent, that is incompatible with the fetch implementation. If you are using undici's ProxyAgent, pass the fetch implementation from the same undici package: import { fetch, ProxyAgent } from 'undici'; new OpenAI({ fetch, fetchOptions: { dispatcher: new ProxyAgent(...) } });`;
}
return void 0;
}
function isUndiciDispatcherVersionMismatchError(error) {
let current = error;
for (let i = 0; i < 8 && current && typeof current === "object"; i++) {
const err = current;
if (err.code === "UND_ERR_INVALID_ARG" && typeof err.message === "string" && err.message.includes("invalid onRequestStart method")) {
return true;
}
current = err.cause;
}
return false;
}
var _OpenAI_instances, _a3, _OpenAI_encoder, _OpenAI_x509Authentication, _OpenAI_x509Credential, _OpenAI_x509Fetch, _OpenAI_explicitDataResidency, _OpenAI_responseAttempts, _OpenAI_baseURLOverridden, WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER, inheritedDataResidencySelection, OpenAI, composedCallerSignals;
var init_client = __esm({
"node_modules/openai/client.mjs"() {
init_tslib();
init_uuid();
init_values();
init_sleep();
init_abort2();
init_errors();
init_parse();
init_detect_platform();
init_shims();
init_request_options();
init_query();
init_version2();
init_data_residency();
init_error();
init_pagination();
init_workload_identity_auth();
init_x509_api_origin();
init_x509_workload_identity_auth();
init_x509_credential_options();
init_x509_transport_state();
init_error();
init_uploads2();
init_resources();
init_api_promise();
init_realtime_credentials();
init_batches();
init_completions3();
init_content_provenance_checks();
init_embeddings2();
init_files3();
init_images();
init_models2();
init_moderations();
init_videos();
init_admin();
init_audio();
init_beta();
init_chat();
init_containers();
init_conversations();
init_evals();
init_fine_tuning();
init_graders2();
init_live();
init_realtime2();
init_responses2();
init_safety();
init_skills();
init_uploads3();
init_vector_stores();
init_webhooks();
init_detect_platform();
init_headers2();
init_provider();
init_env();
init_log();
init_values();
WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER = "workload-identity-auth";
inheritedDataResidencySelection = /* @__PURE__ */ Symbol("inheritedDataResidencySelection");
OpenAI = class {
/**
* API Client for interfacing with the OpenAI API.
*
* @param {string | null | undefined} [opts.apiKey=process.env['OPENAI_API_KEY'] ?? null]
* @param {string | null | undefined} [opts.adminAPIKey=process.env['OPENAI_ADMIN_KEY'] ?? null]
* @param {string | null | undefined} [opts.organization=process.env['OPENAI_ORG_ID'] ?? null]
* @param {string | null | undefined} [opts.project=process.env['OPENAI_PROJECT_ID'] ?? null]
* @param {string | null | undefined} [opts.webhookSecret=process.env['OPENAI_WEBHOOK_SECRET'] ?? null]
* @param {string} [opts.baseURL=process.env['OPENAI_BASE_URL'] ?? https://api.openai.com/v1] - Override the default base URL for the API.
* @param {Provider} [opts.provider] - Configure a third-party API provider. Mutually exclusive with top-level authentication and base URL options.
* @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
* @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.
* @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
* @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
* @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.
* @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
*/
constructor(clientOptions = {}) {
_OpenAI_instances.add(this);
_OpenAI_encoder.set(this, void 0);
_OpenAI_x509Authentication.set(this, void 0);
_OpenAI_x509Credential.set(this, void 0);
_OpenAI_x509Fetch.set(this, void 0);
_OpenAI_explicitDataResidency.set(this, false);
_OpenAI_responseAttempts.set(this, /* @__PURE__ */ new WeakMap());
this.completions = new Completions2(this);
this.chat = new Chat(this);
this.embeddings = new Embeddings(this);
this.files = new Files3(this);
this.images = new Images(this);
this.contentProvenanceChecks = new ContentProvenanceChecks(this);
this.audio = new Audio(this);
this.moderations = new Moderations(this);
this.models = new Models(this);
this.fineTuning = new FineTuning(this);
this.graders = new Graders2(this);
this.vectorStores = new VectorStores(this);
this.safety = new Safety(this);
this.webhooks = new Webhooks(this);
this.beta = new Beta(this);
this.batches = new Batches(this);
this.uploads = new Uploads(this);
this.admin = new Admin(this);
this.responses = new Responses2(this);
this.live = new Live(this);
this.realtime = new Realtime2(this);
this.conversations = new Conversations(this);
this.evals = new Evals(this);
this.containers = new Containers(this);
this.skills = new Skills(this);
this.videos = new Videos(this);
const { credential, options: normalizedOptions } = normalizeX509CredentialOptions(clientOptions);
clientOptions = normalizedOptions;
const residencyBaseURL = resolveDataResidency(clientOptions);
const provider3 = clientOptions.provider;
const { baseURL = provider3 ? null : readEnv("OPENAI_BASE_URL"), dataResidency: _dataResidency, [inheritedDataResidencySelection]: inheritedResidencySelection = false, apiKey = provider3 ? null : readEnv("OPENAI_API_KEY") ?? null, adminAPIKey = provider3 ? null : readEnv("OPENAI_ADMIN_KEY") ?? null, organization = provider3 ? null : readEnv("OPENAI_ORG_ID") ?? null, project = provider3 ? null : readEnv("OPENAI_PROJECT_ID") ?? null, webhookSecret = readEnv("OPENAI_WEBHOOK_SECRET") ?? null, workloadIdentity, x509Transport, credential: _credential, ...opts } = clientOptions;
if (provider3) {
const conflictingOptions = ["apiKey", "adminAPIKey", "workloadIdentity", "x509Transport", "baseURL", "dataResidency"].filter((key) => (key === "workloadIdentity" ? workloadIdentity : clientOptions[key]) != null);
if (conflictingOptions.length) {
throw new OpenAIError(`The \`provider\` option cannot be used with ${conflictingOptions.map((key) => `\`${key}\``).join(", ")}. Configure authentication and the base URL through the provider instead.`);
}
}
const identity = isX509WorkloadIdentity(workloadIdentity) ? { x509: workloadIdentity, legacy: void 0 } : { x509: void 0, legacy: workloadIdentity };
const x509Identity = identity.x509;
const usesX509Identity = x509Identity !== void 0;
const providerRuntime = provider3 ? configureProvider(provider3) : void 0;
const options = {
apiKey,
adminAPIKey,
organization,
project,
webhookSecret,
workloadIdentity,
x509Transport,
provider: provider3,
...opts,
baseURL: providerRuntime?.baseURL ?? residencyBaseURL ?? (baseURL || (usesX509Identity ? X509_API_BASE_URL : `https://api.openai.com/v1`))
};
if (x509Transport && !usesX509Identity) {
throw new OpenAIError("An X.509 transport requires an X.509 workload identity.");
}
if (usesX509Identity) {
if (residencyBaseURL !== void 0 || inheritedResidencySelection) {
throw new OpenAIError("X.509 workload identity does not support data residency selection.");
}
if (clientOptions.fetch !== void 0) {
throw new OpenAIError("X.509 workload identity does not support a custom fetch implementation.");
}
assertX509APIOrigin(options.baseURL);
assertX509RequestOptions(options.fetchOptions);
if (this.fetchWithAuth !== _a3.prototype.fetchWithAuth || this.fetchWithTimeout !== _a3.prototype.fetchWithTimeout) {
throw new OpenAIError("X.509 workload identity does not support overridden fetch dispatch hooks.");
}
}
if (apiKey && workloadIdentity) {
throw new OpenAIError("The `apiKey` and `workloadIdentity` options are mutually exclusive");
}
if (!providerRuntime && !apiKey && !adminAPIKey && !workloadIdentity) {
throw new OpenAIError("Missing credentials. Please pass an `apiKey`, `workloadIdentity`, `adminAPIKey`, or set the `OPENAI_API_KEY` or `OPENAI_ADMIN_KEY` environment variable.");
}
if (!options.dangerouslyAllowBrowser && isRunningInBrowserOrBrowserWorker()) {
throw new OpenAIError("It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew OpenAI({ apiKey, dangerouslyAllowBrowser: true });\n\nhttps://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety\n");
}
this.baseURL = options.baseURL;
__classPrivateFieldSet(this, _OpenAI_explicitDataResidency, residencyBaseURL !== void 0 || inheritedResidencySelection, "f");
this.timeout = options.timeout ?? _a3.DEFAULT_TIMEOUT;
this.logger = options.logger ?? console;
const defaultLogLevel = "warn";
this.logLevel = defaultLogLevel;
this.logLevel = parseLogLevel(options.logLevel, "ClientOptions.logLevel", this) ?? parseLogLevel(readEnv("OPENAI_LOG"), "process.env['OPENAI_LOG']", this) ?? defaultLogLevel;
this.fetchOptions = options.fetchOptions;
this.maxRetries = options.maxRetries ?? 2;
this.fetch = options.fetch ?? getDefaultFetch();
__classPrivateFieldSet(this, _OpenAI_encoder, FallbackEncoder, "f");
const customHeadersEnv = provider3 || credential ? void 0 : readEnv("OPENAI_CUSTOM_HEADERS");
if (customHeadersEnv) {
const parsed = {};
for (const line of customHeadersEnv.split("\n")) {
const colon = line.indexOf(":");
if (colon >= 0) {
parsed[line.substring(0, colon).trim()] = line.substring(colon + 1).trim();
}
}
options.defaultHeaders = buildHeaders([parsed, options.defaultHeaders]);
}
this._options = options;
this._provider = providerRuntime;
if (x509Identity) {
const authentication = new X509WorkloadIdentityAuth(x509Identity, x509Transport, organization, project);
this._workloadIdentityAuth = authentication;
__classPrivateFieldSet(this, _OpenAI_x509Authentication, authentication, "f");
__classPrivateFieldSet(this, _OpenAI_x509Credential, credential, "f");
__classPrivateFieldSet(this, _OpenAI_x509Fetch, authentication.fetch(), "f");
this.fetch = __classPrivateFieldGet(this, _OpenAI_x509Fetch, "f");
markApprovedX509Client2(this);
} else if (identity.legacy) {
this._workloadIdentityAuth = new WorkloadIdentityAuth(identity.legacy, this.fetch);
}
this.apiKey = typeof apiKey === "string" ? apiKey : null;
this.adminAPIKey = adminAPIKey;
this.organization = organization;
this.project = project;
this.webhookSecret = webhookSecret;
}
/**
* Create a new client instance re-using the same options given to the current client with optional overriding.
*/
withOptions(options) {
const residencyBaseURL = resolveDataResidency(options);
const x509Authentication = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f");
const inheritedOptions = {
...this._options,
baseURL: this.baseURL,
maxRetries: this.maxRetries,
timeout: this.timeout,
logger: this.logger,
logLevel: this.logLevel,
fetch: __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f") ? void 0 : this.fetch,
fetchOptions: this.fetchOptions,
apiKey: this._options.apiKey,
adminAPIKey: this.adminAPIKey,
workloadIdentity: x509Authentication?.identitySnapshot() ?? this._options.workloadIdentity,
x509Transport: this._options.x509Transport,
organization: this.organization,
project: this.project,
webhookSecret: this.webhookSecret
};
const { credential, provider: provider3 } = prepareX509ClientClone(inheritedOptions, options, __classPrivateFieldGet(this, _OpenAI_x509Credential, "f"), x509Authentication !== void 0);
if (residencyBaseURL !== void 0) {
delete inheritedOptions.baseURL;
}
const clientOptions = {
...inheritedOptions,
...options,
credential,
provider: provider3,
[inheritedDataResidencySelection]: __classPrivateFieldGet(this, _OpenAI_explicitDataResidency, "f") && residencyBaseURL === void 0 && !hasOwn(options, "baseURL") && options.credential === void 0 && !provider3
};
const client = new this.constructor(clientOptions);
if (provider3 && new URL(client.baseURL).origin !== new URL(this.baseURL).origin) {
Object.assign(client._options, {
defaultHeaders: options.defaultHeaders,
defaultQuery: options.defaultQuery,
fetchOptions: options.fetchOptions,
fetch: options.fetch
});
client.fetchOptions = options.fetchOptions;
client.fetch = options.fetch ?? getDefaultFetch();
client.organization = options.organization ?? null;
client.project = options.project ?? null;
}
if (__classPrivateFieldGet(this, _OpenAI_x509Authentication, "f") && __classPrivateFieldGet(client, _OpenAI_x509Authentication, "f") && this.baseURL === client.baseURL && __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f").matches(__classPrivateFieldGet(client, _OpenAI_x509Authentication, "f"))) {
client._workloadIdentityAuth = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f");
__classPrivateFieldSet(client, _OpenAI_x509Authentication, __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f"), "f");
__classPrivateFieldSet(client, _OpenAI_x509Fetch, __classPrivateFieldGet(this, _OpenAI_x509Fetch, "f"), "f");
}
return client;
}
defaultQuery() {
return this._options.defaultQuery;
}
/** @internal Client request headers for each new WebSocket handshake. */
_buildWebSocketHeaders(authHeaders) {
return Object.fromEntries(buildHeaders([
{
"User-Agent": this.getUserAgent(),
"OpenAI-Organization": this.organization,
"OpenAI-Project": this.project
},
authHeaders,
this._options.defaultHeaders
]).values);
}
validateHeaders({ values, nulls }, schemes = {
bearerAuth: true,
adminAPIKeyAuth: true
}) {
if (values.get("authorization") || values.get("api-key")) {
return;
}
if (nulls.has("authorization") || nulls.has("api-key")) {
return;
}
if (this._workloadIdentityAuth && schemes.bearerAuth) {
return;
}
throw new Error('Could not resolve authentication method. Expected either apiKey or adminAPIKey to be set. Or for one of the "Authorization" or "api-key" headers to be explicitly omitted');
}
async authHeaders(opts, schemes = {
bearerAuth: true,
adminAPIKeyAuth: true
}) {
const authentication = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f") ?? this._workloadIdentityAuth;
if (authentication instanceof X509WorkloadIdentityAuth && schemes.adminAPIKeyAuth && this.adminAPIKey !== null) {
return await this.adminAPIKeyAuth(opts);
}
return buildHeaders([
schemes.bearerAuth ? await this.bearerAuth(opts) : null,
schemes.adminAPIKeyAuth ? await this.adminAPIKeyAuth(opts) : null
]);
}
async bearerAuth(opts) {
const authentication = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f") ?? this._workloadIdentityAuth;
if (authentication) {
if (authentication instanceof X509WorkloadIdentityAuth) {
if (authentication === this._workloadIdentityAuth && (this.fetchWithAuth !== _a3.prototype.fetchWithAuth || this.fetchWithTimeout !== _a3.prototype.fetchWithTimeout)) {
throw new OpenAIError("X.509 workload identity does not support overridden fetch dispatch hooks.");
}
const snapshots = authentication.headerSnapshots();
if (!X509WorkloadIdentityAuth.shouldAuthenticate(opts, snapshots.defaultHeaders, snapshots.requestHeaders)) {
return void 0;
}
}
const token = authentication instanceof X509WorkloadIdentityAuth ? await authentication.getToken(opts, {
apiURL: authentication.requestAPIURL(),
...authentication.headerSnapshots(),
...authentication.requestSnapshot(),
signal: authentication.effectiveSignal(),
...authentication.tenantSnapshot()
}) : await authentication.getToken();
return buildHeaders([{ Authorization: `Bearer ${token}` }]);
}
const { apiKey } = await resolveRealtimeAPIKey(this);
if (apiKey == null) {
return void 0;
}
return buildHeaders([{ Authorization: `Bearer ${apiKey}` }]);
}
async adminAPIKeyAuth(opts) {
if (this.adminAPIKey == null) {
return void 0;
}
return buildHeaders([{ Authorization: `Bearer ${this.adminAPIKey}` }]);
}
stringifyQuery(query) {
return stringifyQuery(query);
}
getUserAgent() {
return `${this.constructor.name}/JS ${VERSION}`;
}
defaultIdempotencyKey() {
return `stainless-node-retry-${uuid4()}`;
}
makeStatusError(status, error, message, headers) {
const normalizedError = error && typeof error === "object" && error.error == null ? { error } : error;
return APIError.generate(status, normalizedError, message, headers);
}
_hasApiKeyProvider() {
return typeof this._options.apiKey === "function";
}
/**
* Resolves a function-based API key and retains the resolved value on this client.
* Returns whether a provider was invoked. Internal callers can capture this
* invocation's key before another request updates the shared `apiKey` property.
* Overrides should forward `capture` or invoke it with their own resolved key
* to preserve invocation-local credentials in concurrent requests and Realtime factories.
* @internal
*/
async _callApiKey(capture) {
if (this._provider) {
capture?.(this.apiKey);
return false;
}
const apiKey = this._options.apiKey;
if (typeof apiKey !== "function") {
capture?.(this.apiKey);
return false;
}
let token;
try {
token = await apiKey();
} catch (err) {
if (err instanceof OpenAIError)
throw err;
throw new OpenAIError(
`Failed to get token from 'apiKey' function: ${err.message}`,
// @ts-ignore
{ cause: err }
);
}
if (typeof token !== "string" || !token) {
throw new OpenAIError(`Expected 'apiKey' function argument to return a string but it returned ${token}`);
}
this.apiKey = token;
capture?.(this.apiKey);
return true;
}
buildURL(path3, query, defaultBaseURL) {
const baseURL = !__classPrivateFieldGet(this, _OpenAI_instances, "m", _OpenAI_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
const url = isAbsoluteURL(path3) ? new URL(path3) : new URL(baseURL + (baseURL.endsWith("/") && path3.startsWith("/") ? path3.slice(1) : path3));
const defaultQuery = this.defaultQuery();
const pathQuery = Object.fromEntries(url.searchParams);
if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
query = { ...pathQuery, ...defaultQuery, ...query };
}
if (typeof query === "object" && query && !Array.isArray(query)) {
url.search = this.stringifyQuery(query);
}
return url.toString();
}
/**
* Used as a callback for mutating the given `FinalRequestOptions` object.
* Function-based credentials are resolved later, when building authentication
* headers, including for direct `buildRequest()` calls. Overriding this hook
* does not bypass that resolution.
*/
async prepareOptions(options) {
}
/**
* Used as a callback for mutating the given `RequestInit` object.
*
* This is useful for cases where you want to add certain headers based off of
* the request properties, e.g. `method` or `url`.
*/
async prepareRequest(request2, { url, options }) {
}
get(path3, opts) {
return this.methodRequest("get", path3, opts);
}
post(path3, opts) {
return this.methodRequest("post", path3, opts);
}
patch(path3, opts) {
return this.methodRequest("patch", path3, opts);
}
put(path3, opts) {
return this.methodRequest("put", path3, opts);
}
delete(path3, opts) {
return this.methodRequest("delete", path3, opts);
}
methodRequest(method, path3, opts) {
return this.request(Promise.resolve(opts).then((opts2) => {
return { method, path: path3, ...opts2 };
}));
}
request(options, remainingRetries = null) {
const authentication = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f") ?? this._workloadIdentityAuth;
const request2 = authentication instanceof X509WorkloadIdentityAuth ? Promise.resolve(options).then((resolved) => authentication.runRequest(() => this.makeRequest(resolved, remainingRetries, void 0), this)) : this.makeRequest(options, remainingRetries, void 0);
return this.responsePromise(request2);
}
responsePromise(request2, parse = (client, props) => this.parseResponseWithTimeout(client, props)) {
const promise = new APIPromise(this, request2, (client, props) => {
const resume = __classPrivateFieldGet(this, _OpenAI_responseAttempts, "f").get(props.controller)?.continueRequest;
return resume ? resume(() => parse(client, props)) : parse(client, props);
});
promise.withResponse = async () => {
const data = await promise;
const { response } = await request2;
return { data, response, request_id: response.headers.get("x-request-id") };
};
promise._thenUnwrap = (transform) => this.responsePromise(request2, async (client, props) => addRequestID(transform(await parse(client, props), props), props.response));
return promise;
}
async parseResponseWithTimeout(client, props) {
if (props.options.stream || props.options.__binaryResponse || props.response.status === 204 || props.response.headers.get("content-length") === "0") {
return defaultParseResponse(client, props);
}
while (true) {
const attempt = __classPrivateFieldGet(this, _OpenAI_responseAttempts, "f").get(props.controller);
const timeout = attempt?.timeout ?? props.options.timeout ?? this.timeout;
const x509Authentication = attempt?.authentication;
const callerSignal = x509Authentication ? props.controller.signal : props.options.signal;
const abortError2 = () => x509Authentication && callerSignal ? this._makeUserAbortError(callerSignal) : new APIUserAbortError();
let remaining;
try {
remaining = x509Authentication?.remainingTimeout(props.options, timeout) ?? Math.max(0, props.startTime + timeout - Date.now());
} catch (error) {
const cancellation = callerSignal?.aborted ? abortError2() : void 0;
props.controller.abort();
void CancelReadableStream(props.response.body).catch(() => void 0);
throw cancellation ?? error;
}
let timer;
let abortListener;
let timedOut = false;
try {
if (callerSignal?.aborted && attempt?.helperMethod !== "runTools") {
throw abortError2();
}
const timeoutPromise = new Promise((_, reject2) => {
timer = setTimeout(() => {
timedOut = true;
props.controller.abort();
reject2(new APIConnectionTimeoutError());
}, remaining);
if (callerSignal) {
abortListener = () => {
if (!timedOut)
reject2(abortError2());
};
callerSignal.addEventListener("abort", abortListener, { once: true });
}
});
return await Promise.race([defaultParseResponse(client, props), timeoutPromise]);
} catch (error) {
if (callerSignal?.aborted && !timedOut) {
throw abortError2();
}
if (!timedOut) {
if (x509Authentication && error instanceof SyntaxError) {
throw new SyntaxError("X.509 workload identity API response contains invalid JSON.");
}
if (x509Authentication && !(error instanceof OpenAIError)) {
throw new APIConnectionError({
message: "X.509 workload identity API response body could not be read."
});
}
throw error;
}
const retriesRemaining = attempt?.retriesRemaining ?? 0;
if (!retriesRemaining || attempt?.hasStreamingBody || props.options.__metadata?.["hasStreamingBody"] || globalThis.ReadableStream && props.options.body instanceof globalThis.ReadableStream || typeof props.options.body === "object" && props.options.body !== null && (Symbol.asyncIterator in props.options.body || Symbol.iterator in props.options.body && "next" in props.options.body && typeof props.options.body.next === "function")) {
throw new APIConnectionTimeoutError();
}
if (timer !== void 0)
clearTimeout(timer);
if (abortListener)
callerSignal?.removeEventListener("abort", abortListener);
abortListener = void 0;
const next = await this.retryRequest(props.options, retriesRemaining, props.retryOfRequestLogID ?? props.requestLogID, void 0, props.requestSignal);
Object.assign(props, next);
} finally {
if (timer !== void 0)
clearTimeout(timer);
if (abortListener)
callerSignal?.removeEventListener("abort", abortListener);
}
}
}
/** Keeps terminal X.509 error-body consumption inside the original logical request deadline. */
async readX509ResponseError(response, options, timeout, controller, authentication) {
const deadline = new AbortController();
const callerSignal = controller.signal;
let timedOut = false;
const cancel = () => deadline.abort(callerSignal.reason);
callerSignal.addEventListener("abort", cancel, { once: true });
if (callerSignal.aborted) {
cancel();
}
try {
const remaining = authentication.remainingTimeout(options, timeout);
const expiration = authentication.waitForRetry(remaining, deadline.signal).then(() => {
throw new APIConnectionTimeoutError();
});
const body = await Promise.race([
response.text().catch(() => "X.509 workload identity API response body could not be read."),
expiration
]);
if (callerSignal.aborted) {
throw this._makeUserAbortError(callerSignal);
}
return body;
} catch (error) {
if (error instanceof APIConnectionTimeoutError) {
timedOut = !callerSignal.aborted;
controller.abort();
void CancelReadableStream(response.body).catch(() => void 0);
}
if (callerSignal.aborted && !timedOut) {
throw this._makeUserAbortError(callerSignal);
}
throw error;
} finally {
callerSignal.removeEventListener("abort", cancel);
deadline.abort();
}
}
async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) {
const options = await optionsInput;
const maxRetries = options.maxRetries ?? this.maxRetries;
if (retriesRemaining == null) {
retriesRemaining = maxRetries;
}
const x509Authentication = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f");
x509Authentication?.beginRequestPreparation();
await this.prepareOptions(options);
x509Authentication?.beginRequestPlanning();
let built;
try {
const candidate = await this.buildRequest(options, {
retryCount: maxRetries - retriesRemaining
});
built = { req: candidate.req, url: candidate.url, timeout: candidate.timeout };
if (x509Authentication) {
validatePositiveInteger("timeout", built.timeout);
x509Authentication.authorizePlannedRequest(built.url, built.req, built.timeout);
if (X509WorkloadIdentityAuth.isStreamingRequestBody(built.req.body)) {
options.__metadata = { ...options.__metadata, hasStreamingBody: true };
}
await this.prepareRequest(built.req, { url: built.url, options });
await this._provider?.prepareRequest?.(built.req, { url: built.url, options });
x509Authentication.beginRequestPlanning();
x509Authentication.authorizePlannedRequest(built.url, built.req, built.timeout, true);
if (X509WorkloadIdentityAuth.isStreamingRequestBody(built.req.body)) {
options.__metadata = { ...options.__metadata, hasStreamingBody: true };
}
const callerSignal2 = x509Authentication.requestSnapshot().signal;
if (callerSignal2?.aborted || built.req.signal?.aborted) {
throw this._makeUserAbortError(callerSignal2?.aborted ? callerSignal2 : built.req.signal);
}
x509Authentication.setEffectiveSignal(built.req.signal || callerSignal2 ? createRequestController(built.req.signal ?? callerSignal2, callerSignal2).signal : void 0);
x509Authentication.beginRequestNetwork();
const security2 = options.__security ?? { bearerAuth: true };
const authenticationHeaders = await this.authHeaders(options, security2);
const suppliedHeaders = x509Authentication.headerSnapshots();
const supplied = buildHeaders([suppliedHeaders.defaultHeaders, suppliedHeaders.requestHeaders]);
for (const [name, value2] of authenticationHeaders?.values ?? []) {
if (!supplied.nulls.has(name) && !built.req.headers.has(name)) {
built.req.headers.set(name, value2);
}
}
this.validateHeaders(buildHeaders([supplied, built.req.headers]), security2);
}
} catch (error) {
x509Authentication?.retireRequestBody();
if (x509Authentication && retriesRemaining && !options.__metadata?.["hasStreamingBody"] && X509WorkloadIdentityAuth.isRetryableFailure(error)) {
return await this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? "x509-token-exchange", X509WorkloadIdentityAuth.retryHeaders(error));
}
throw error;
}
const { req, url } = built;
const timeout = x509Authentication ? Math.min(built.timeout, x509Authentication.requestSnapshot().timeout) : built.timeout;
x509Authentication?.bindRequest(options, req, this.adminAPIKey);
let hasStreamingBody = options.__metadata?.["hasStreamingBody"] === true;
if (!x509Authentication) {
await this.prepareRequest(req, { url, options });
await this._provider?.prepareRequest?.(req, { url, options });
}
x509Authentication?.adoptRequestHeaders(req);
if (x509Authentication && X509WorkloadIdentityAuth.isStreamingRequestBody(req.body)) {
hasStreamingBody = true;
}
const requestLogID = "log_" + (Math.random() * (1 << 24) | 0).toString(16).padStart(6, "0");
const retryLogStr = retryOfRequestLogID === void 0 ? "" : `, retryOf: ${retryOfRequestLogID}`;
const startTime = x509Authentication?.requestStartedAt(options) ?? Date.now();
if (this.logLevel === "debug") {
const body = typeof req.body === "string" ? { type: "string", length: req.body.length } : req.body;
loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({
retryOfRequestLogID,
method: options.method,
url,
options: x509Authentication ? { body, ...x509Authentication.requestSnapshot() } : { ...options, body },
headers: req.headers
}));
}
const callerSignal = x509Authentication ? x509Authentication.requestSnapshot().signal : options.signal;
if (callerSignal?.aborted || req.signal?.aborted) {
throw this._makeUserAbortError(callerSignal?.aborted ? callerSignal : req.signal);
}
const security = options.__security ?? { bearerAuth: true };
const controller = x509Authentication || this.fetchWithTimeout === _a3.prototype.fetchWithTimeout ? createRequestController(req.signal ?? (x509Authentication ? callerSignal : void 0), x509Authentication ? callerSignal : void 0) : new AbortController();
const remainingTimeout = x509Authentication?.remainingTimeout(options, timeout) ?? timeout;
const fetchWithAuth = x509Authentication ? _a3.prototype.fetchWithAuth : this.fetchWithAuth;
x509Authentication?.releaseRequestBody(req.body);
const response = await fetchWithAuth.call(this, url, req, remainingTimeout, controller, security).catch(castToError);
const headersTime = Date.now();
if (response instanceof globalThis.Error) {
const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
if (callerSignal?.aborted || req.signal?.aborted) {
throw this._makeUserAbortError(callerSignal?.aborted ? callerSignal : req.signal);
}
const isTimeout = isAbortError(response) || /timed? ?out/i.test(String(response) + ("cause" in response ? String(response.cause) : ""));
if (retriesRemaining && !hasStreamingBody && (!x509Authentication || isTransientX509ConnectionError2(response))) {
loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? "timed out" : "failed"} - ${retryMessage}`);
loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? "timed out" : "failed"} (${retryMessage})`, formatRequestDetails({
retryOfRequestLogID,
url,
durationMs: headersTime - startTime,
message: x509Authentication ? "X.509 workload identity API connection failed." : response.message
}));
return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID, void 0, req.signal);
}
const terminalMessage = hasStreamingBody ? "error; streaming body cannot be retried" : "error; no more retries left";
loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? "timed out" : "failed"} - ${terminalMessage}`);
loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? "timed out" : "failed"} (${terminalMessage})`, formatRequestDetails({
retryOfRequestLogID,
url,
durationMs: headersTime - startTime,
message: x509Authentication ? "X.509 workload identity API connection failed." : response.message
}));
if (response instanceof OAuthError || response instanceof SubjectTokenProviderError) {
throw response;
}
if (isTimeout) {
const transportCause = "cause" in response ? response.cause : void 0;
const isHeadersTimeout = typeof transportCause === "object" && transportCause !== null && "code" in transportCause && transportCause.code === "UND_ERR_HEADERS_TIMEOUT";
const timeoutError2 = isHeadersTimeout ? new APIConnectionTimeoutError({
message: "Request timed out. Node.js fetch timed out waiting for response headers; configure a matching undici fetch and fetchOptions.dispatcher with an Agent whose headersTimeout is at least the SDK timeout."
}) : new APIConnectionTimeoutError();
if (x509Authentication) {
throw new APIConnectionTimeoutError();
}
throw Object.assign(timeoutError2, { cause: response });
}
if (x509Authentication) {
throw new APIConnectionError({ message: "X.509 workload identity API connection failed." });
}
throw new APIConnectionError({
message: getConnectionErrorMessage(response),
cause: response
});
}
const specialHeaders = [...response.headers.entries()].filter(([name]) => name === "x-request-id").map(([name, value2]) => ", " + name + ": " + JSON.stringify(value2)).join("");
const responseInfo = `[${requestLogID}${retryLogStr}${specialHeaders}] ${req.method} ${redactURL(url)} ${response.ok ? "succeeded" : "failed"} with status ${response.status} in ${headersTime - startTime}ms`;
if (!response.ok) {
const rejectedX509Credential = response.status === 401 && x509Authentication && security.bearerAuth && x509Authentication.usedWorkloadToken(options);
if (rejectedX509Credential) {
x509Authentication.invalidateToken();
}
if (response.status === 401 && (x509Authentication || this._workloadIdentityAuth) && security.bearerAuth && (!x509Authentication || x509Authentication.usedWorkloadToken(options)) && (!x509Authentication || retriesRemaining > 0) && !hasStreamingBody && !options.__metadata?.["workloadIdentityTokenRefreshed"]) {
if (x509Authentication) {
void CancelReadableStream(response.body).catch(() => void 0);
} else {
await CancelReadableStream(response.body);
this._workloadIdentityAuth?.invalidateToken();
}
const replayOptions = {
...options,
__metadata: {
...options.__metadata,
workloadIdentityTokenRefreshed: true
}
};
return this.makeRequest(replayOptions, x509Authentication ? retriesRemaining - 1 : retriesRemaining, retryOfRequestLogID ?? requestLogID);
}
const shouldRetry = rejectedX509Credential && options.__metadata?.["workloadIdentityTokenRefreshed"] ? false : await this.shouldRetry(response);
if (retriesRemaining && shouldRetry && !hasStreamingBody) {
const retryMessage2 = `retrying, ${retriesRemaining} attempts remaining`;
if (x509Authentication) {
void CancelReadableStream(response.body).catch(() => void 0);
} else {
await CancelReadableStream(response.body);
}
loggerFor(this).info(`${responseInfo} - ${retryMessage2}`);
loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage2})`, formatRequestDetails({
retryOfRequestLogID,
url: response.url,
status: response.status,
headers: response.headers,
durationMs: headersTime - startTime
}));
return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID, response.headers, req.signal);
}
const retryMessage = shouldRetry ? hasStreamingBody ? `error; streaming body cannot be retried` : `error; no more retries left` : `error; not retryable`;
loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
const errText = x509Authentication ? await this.readX509ResponseError(response, options, timeout, controller, x509Authentication) : await response.text().catch((err2) => castToError(err2).message);
const errJSON = safeJSON(errText);
const errMessage = errJSON ? void 0 : errText;
loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
retryOfRequestLogID,
url: response.url,
status: response.status,
headers: response.headers,
message: errMessage,
durationMs: Date.now() - startTime
}));
const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
throw err;
}
loggerFor(this).info(responseInfo);
loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({
retryOfRequestLogID,
url: response.url,
status: response.status,
headers: response.headers,
durationMs: headersTime - startTime
}));
const continueRequest = x509Authentication?.continuation();
x509Authentication?.releaseRequestCredentials();
__classPrivateFieldGet(this, _OpenAI_responseAttempts, "f").set(controller, {
timeout,
retriesRemaining,
hasStreamingBody,
...x509Authentication ? { authentication: x509Authentication } : {},
helperMethod: options.__metadata?.["helperMethod"],
...continueRequest ? { continueRequest } : {}
});
return {
response,
options,
controller,
requestSignal: req.signal,
requestLogID,
retryOfRequestLogID,
startTime
};
}
getAPIList(path3, Page2, opts) {
return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path3, ...opts2 })) : { method: "get", path: path3, ...opts });
}
requestAPIList(Page2, options) {
const authentication = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f") ?? this._workloadIdentityAuth;
const request2 = authentication instanceof X509WorkloadIdentityAuth ? Promise.resolve(options).then((resolved) => authentication.runRequest(() => this.makeRequest(resolved, null, void 0), this)) : this.makeRequest(options, null, void 0);
const page2 = new PagePromise(this, request2, Page2);
const guarded = this.responsePromise(request2, async (client, props) => {
const body = await this.parseResponseWithTimeout(client, props);
return new Page2(client, props.response, body, props.options);
});
page2.then = guarded.then.bind(guarded);
page2.catch = guarded.catch.bind(guarded);
page2.finally = guarded.finally.bind(guarded);
page2.withResponse = guarded.withResponse.bind(guarded);
page2._thenUnwrap = guarded._thenUnwrap.bind(guarded);
return page2;
}
async fetchWithAuth(url, init, timeout, controller, schemes = {
bearerAuth: true,
adminAPIKeyAuth: true
}) {
if (this._workloadIdentityAuth && !__classPrivateFieldGet(this, _OpenAI_x509Fetch, "f") && schemes.bearerAuth) {
const headers = init.headers;
const authHeader = headers.get("Authorization");
if (authHeader === `Bearer ${WORKLOAD_IDENTITY_API_KEY_PLACEHOLDER}`) {
const token = await this._workloadIdentityAuth.getToken();
headers.set("Authorization", `Bearer ${token}`);
}
}
const fetchWithTimeout = __classPrivateFieldGet(this, _OpenAI_x509Fetch, "f") ? _a3.prototype.fetchWithTimeout : this.fetchWithTimeout;
const response = await fetchWithTimeout.call(this, url, init, timeout, controller);
return response;
}
async fetchWithTimeout(url, init, ms, controller) {
const { signal, method, ...options } = init || {};
const abort = this._makeAbort(controller);
const composed = !!signal && composedCallerSignals.get(controller) === signal;
const cleanup = signal && !composed ? addRequestAbortListener(signal, abort, controller.signal) : void 0;
const timeout = setTimeout(abort, ms);
const isReadableBody = globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream || typeof options.body === "object" && options.body !== null && Symbol.asyncIterator in options.body;
const fetchOptions = {
signal: controller.signal,
...isReadableBody ? { duplex: "half" } : {},
method: "GET",
...options
};
if (method) {
fetchOptions.method = method.toUpperCase();
}
try {
const response = await (__classPrivateFieldGet(this, _OpenAI_x509Fetch, "f") ?? this.fetch).call(void 0, url, fetchOptions);
if (cleanup) {
retainRequestAbortCallback(response.body ?? response, abort, controller.signal);
}
return response;
} catch (err) {
cleanup?.();
throw err;
} finally {
clearTimeout(timeout);
}
}
async shouldRetry(response) {
const shouldRetryHeader = response.headers.get("x-should-retry");
if (shouldRetryHeader === "true")
return true;
if (shouldRetryHeader === "false")
return false;
if (response.status === 408)
return true;
if (response.status === 409)
return true;
if (response.status === 429)
return true;
if (response.status >= 500)
return true;
return false;
}
async retryRequest(options, retriesRemaining, requestLogID, responseHeaders, requestSignal = options.signal) {
let timeoutMillis;
const retryAfterMillisHeader = responseHeaders?.get("retry-after-ms");
if (retryAfterMillisHeader) {
const timeoutMs = parseFloat(retryAfterMillisHeader);
if (!Number.isNaN(timeoutMs)) {
timeoutMillis = timeoutMs;
}
}
const retryAfterHeader = responseHeaders?.get("retry-after");
if (retryAfterHeader && timeoutMillis === void 0) {
const timeoutSeconds = parseFloat(retryAfterHeader);
if (!Number.isNaN(timeoutSeconds)) {
timeoutMillis = timeoutSeconds * 1e3;
} else {
timeoutMillis = Date.parse(retryAfterHeader) - Date.now();
}
}
if (timeoutMillis === void 0 || !Number.isFinite(timeoutMillis) || timeoutMillis < 0 || timeoutMillis > 60 * 1e3) {
const maxRetries = options.maxRetries ?? this.maxRetries;
timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
}
const x509Authentication = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f");
if (x509Authentication) {
const remaining = x509Authentication.remainingTimeout(options, x509Authentication.requestSnapshot().timeout);
if (timeoutMillis >= remaining) {
throw new APIConnectionTimeoutError();
}
}
if (x509Authentication) {
await x509Authentication.waitForRetry(timeoutMillis, x509Authentication.effectiveSignal());
} else {
const retrySignals = requestSignal === options.signal ? [requestSignal] : [requestSignal, options.signal];
try {
await sleep(timeoutMillis, ...retrySignals);
} catch (error) {
const abortedSignal = retrySignals.find((signal) => signal?.aborted);
if (abortedSignal) {
throw this._makeUserAbortError(abortedSignal);
}
throw error;
}
}
return this.makeRequest(options, retriesRemaining - 1, requestLogID);
}
calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) {
const initialRetryDelay = 0.5;
const maxRetryDelay = 8;
const numRetries = maxRetries - retriesRemaining;
const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);
const jitter = 1 - Math.random() * 0.25;
return sleepSeconds * jitter * 1e3;
}
/**
* Builds a request, resolving callback credentials when constructing authentication
* headers, after any subclass request-option rewrites. Calling this method directly
* also resolves credentials. Complete replacement builders own authentication and
* can call `this.authHeaders()` to resolve headers with request-local credentials.
*/
async buildRequest(inputOptions, { retryCount = 0 } = {}) {
if (__classPrivateFieldGet(this, _OpenAI_x509Authentication, "f") && !__classPrivateFieldGet(this, _OpenAI_x509Authentication, "f").inRequest(this)) {
const authentication = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f");
return await authentication.runRequest(async () => {
const built = await _a3.prototype.buildRequest.call(this, inputOptions, { retryCount });
authentication.releaseRequestBody(built.req.body);
return built;
}, this);
}
const options = { ...inputOptions };
const x509Authentication = __classPrivateFieldGet(this, _OpenAI_x509Authentication, "f");
const x509Tenant = x509Authentication?.snapshotTenant(this.organization, this.project);
const x509Headers = x509Authentication?.snapshotHeaders(this._options.defaultHeaders, options.headers);
if (x509Headers) {
options.headers = x509Headers.requestHeaders;
}
const x509ClientFetchOptions = x509Authentication ? snapshotX509RequestOptions(this.fetchOptions) : void 0;
const x509RequestFetchOptions = x509Authentication ? snapshotX509RequestOptions(options.fetchOptions) : void 0;
const { method, path: path3, query, defaultBaseURL } = options;
const url = this.buildURL(path3, query, defaultBaseURL);
x509Authentication?.snapshotAPIURL(url);
const explicitTimeout = "timeout" in options;
if (explicitTimeout)
validatePositiveInteger("timeout", options.timeout);
options.timeout = options.timeout ?? this.timeout;
if (x509Authentication && x509RequestFetchOptions) {
x509Authentication.snapshotRequest(options.signal, options.timeout, x509RequestFetchOptions);
}
if (x509Authentication) {
const snapshot = x509Authentication.requestSnapshot();
options.timeout = snapshot.timeout;
if (snapshot.signal === void 0) {
delete options.signal;
} else {
options.signal = snapshot.signal;
}
}
const authenticationHeaders = this._provider || x509Authentication ? void 0 : await this.authHeaders(inputOptions, inputOptions.__security ?? { bearerAuth: true });
const { bodyHeaders, body, isStreamingBody } = this.buildBody({ options });
if (isStreamingBody) {
inputOptions.__metadata = {
...inputOptions.__metadata,
hasStreamingBody: true
};
x509Authentication?.ownRequestBody(body, options.body);
}
const reqHeaders = await this.buildHeaders({
options: inputOptions,
method,
bodyHeaders,
authenticationHeaders,
retryCount,
x509Headers,
x509Timeout: explicitTimeout ? options.timeout : void 0,
x509Tenant
});
const req = {
method,
headers: reqHeaders,
...options.signal && { signal: options.signal },
...globalThis.ReadableStream && body instanceof globalThis.ReadableStream && { duplex: "half" },
...body && { body },
...(x509Authentication ? x509ClientFetchOptions : this.fetchOptions) ?? {},
...(x509Authentication ? x509RequestFetchOptions : options.fetchOptions) ?? {}
};
return { req, url, timeout: options.timeout };
}
async buildHeaders({ options, method, bodyHeaders, authenticationHeaders, retryCount, x509Headers, x509Timeout, x509Tenant }) {
let idempotencyHeaders = {};
if (this.idempotencyHeader && method !== "get") {
if (!options.idempotencyKey)
options.idempotencyKey = this.defaultIdempotencyKey();
idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;
}
const helperMethod = options.__metadata?.["helperMethod"];
const timeout = x509Headers ? x509Timeout : options.timeout;
const headers = buildHeaders([
idempotencyHeaders,
{
Accept: "application/json",
...!isRunningInBrowserOrBrowserWorker() ? { "User-Agent": this.getUserAgent() } : void 0,
"X-Stainless-Retry-Count": String(retryCount),
...timeout ? { "X-Stainless-Timeout": String(Math.trunc(timeout / 1e3)) } : {},
...getPlatformHeaders(),
...typeof helperMethod === "string" ? { "X-Stainless-Helper-Method": helperMethod } : {},
"OpenAI-Organization": x509Tenant ? x509Tenant.organization : this.organization,
"OpenAI-Project": x509Tenant ? x509Tenant.project : this.project
},
// X.509 owns streaming uploads before authentication so it can retire them on failure.
__classPrivateFieldGet(this, _OpenAI_x509Authentication, "f") && !__classPrivateFieldGet(this, _OpenAI_x509Authentication, "f").isPlanningRequest() ? await this.authHeaders(options, options.__security ?? { bearerAuth: true }) : authenticationHeaders,
x509Headers?.defaultHeaders ?? this._options.defaultHeaders,
bodyHeaders,
x509Headers?.requestHeaders ?? options.headers
]);
if (!this._provider && !__classPrivateFieldGet(this, _OpenAI_x509Authentication, "f")?.isPlanningRequest()) {
this.validateHeaders(headers, options.__security ?? { bearerAuth: true });
}
return headers.values;
}
_makeAbort(controller) {
return () => controller.abort();
}
_makeUserAbortError(signal) {
const error = new APIUserAbortError();
Object.defineProperty(error, "cause", { value: signal.reason, writable: true, configurable: true });
return error;
}
buildBody({ options }) {
const { body, headers: rawHeaders } = options;
if (!body) {
if (body === void 0 && "body" in options) {
return { ...__classPrivateFieldGet(this, _OpenAI_encoder, "f").call(this, { body, headers: buildHeaders([rawHeaders]) }), isStreamingBody: false };
}
return { bodyHeaders: void 0, body: void 0, isStreamingBody: false };
}
const headers = buildHeaders([rawHeaders]);
const isReadableStream2 = typeof globalThis.ReadableStream !== "undefined" && body instanceof globalThis.ReadableStream;
const isRetryableBody = !isReadableStream2 && (typeof body === "string" || body instanceof ArrayBuffer || ArrayBuffer.isView(body) || typeof globalThis.Blob !== "undefined" && body instanceof globalThis.Blob || body instanceof URLSearchParams || body instanceof FormData);
if (
// Pass raw type verbatim
ArrayBuffer.isView(body) || body instanceof ArrayBuffer || body instanceof DataView || typeof body === "string" && // Preserve legacy string encoding behavior for now
headers.values.has("content-type") || // `Blob` is superset of `File`
globalThis.Blob && body instanceof globalThis.Blob || // `FormData` -> `multipart/form-data`
body instanceof FormData || // `URLSearchParams` -> `application/x-www-form-urlencoded`
body instanceof URLSearchParams || // Send chunked stream (each chunk has own `length`)
isReadableStream2
) {
return { bodyHeaders: void 0, body, isStreamingBody: !isRetryableBody };
} else if (typeof body === "object" && (Symbol.asyncIterator in body || Symbol.iterator in body && "next" in body && typeof body.next === "function")) {
return {
bodyHeaders: void 0,
body: ReadableStreamFrom(body),
isStreamingBody: true
};
} else if (typeof body === "object" && headers.values.get("content-type") === "application/x-www-form-urlencoded") {
return {
bodyHeaders: { "content-type": "application/x-www-form-urlencoded" },
body: this.stringifyQuery(body),
isStreamingBody: false
};
} else {
return { ...__classPrivateFieldGet(this, _OpenAI_encoder, "f").call(this, { body, headers }), isStreamingBody: false };
}
}
};
_a3 = OpenAI, _OpenAI_encoder = /* @__PURE__ */ new WeakMap(), _OpenAI_x509Authentication = /* @__PURE__ */ new WeakMap(), _OpenAI_x509Credential = /* @__PURE__ */ new WeakMap(), _OpenAI_x509Fetch = /* @__PURE__ */ new WeakMap(), _OpenAI_explicitDataResidency = /* @__PURE__ */ new WeakMap(), _OpenAI_responseAttempts = /* @__PURE__ */ new WeakMap(), _OpenAI_instances = /* @__PURE__ */ new WeakSet(), _OpenAI_baseURLOverridden = function _OpenAI_baseURLOverridden2() {
return __classPrivateFieldGet(this, _OpenAI_explicitDataResidency, "f") || this._provider !== void 0 || this.baseURL !== "https://api.openai.com/v1";
};
OpenAI.OpenAI = _a3;
OpenAI.DEFAULT_TIMEOUT = 6e5;
OpenAI.OpenAIError = OpenAIError;
OpenAI.APIError = APIError;
OpenAI.APIConnectionError = APIConnectionError;
OpenAI.APIConnectionTimeoutError = APIConnectionTimeoutError;
OpenAI.APIUserAbortError = APIUserAbortError;
OpenAI.NotFoundError = NotFoundError;
OpenAI.ConflictError = ConflictError;
OpenAI.RateLimitError = RateLimitError;
OpenAI.BadRequestError = BadRequestError;
OpenAI.AuthenticationError = AuthenticationError;
OpenAI.InternalServerError = InternalServerError;
OpenAI.PermissionDeniedError = PermissionDeniedError;
OpenAI.UnprocessableEntityError = UnprocessableEntityError;
OpenAI.InvalidWebhookSignatureError = InvalidWebhookSignatureError;
OpenAI.toFile = toFile;
OpenAI.toStreamingFile = toStreamingFile;
OpenAI.Completions = Completions2;
OpenAI.Chat = Chat;
OpenAI.Embeddings = Embeddings;
OpenAI.Files = Files3;
OpenAI.Images = Images;
OpenAI.ContentProvenanceChecks = ContentProvenanceChecks;
OpenAI.Audio = Audio;
OpenAI.Moderations = Moderations;
OpenAI.Models = Models;
OpenAI.FineTuning = FineTuning;
OpenAI.Graders = Graders2;
OpenAI.VectorStores = VectorStores;
OpenAI.Safety = Safety;
OpenAI.Webhooks = Webhooks;
OpenAI.Beta = Beta;
OpenAI.Batches = Batches;
OpenAI.Uploads = Uploads;
OpenAI.Admin = Admin;
OpenAI.Responses = Responses2;
OpenAI.Live = Live;
OpenAI.Realtime = Realtime2;
OpenAI.Conversations = Conversations;
OpenAI.Evals = Evals;
OpenAI.Containers = Containers;
OpenAI.Skills = Skills;
OpenAI.Videos = Videos;
OpenAI.ConversationCursorPage = ConversationCursorPage;
OpenAI.CursorPage = CursorPage;
OpenAI.NextCursorPage = NextCursorPage;
OpenAI.Page = Page;
OpenAI.TokenPage = TokenPage;
composedCallerSignals = /* @__PURE__ */ new WeakMap();
}
});
// node_modules/openai/azure.mjs
var init_azure = __esm({
"node_modules/openai/azure.mjs"() {
init_headers2();
init_error2();
init_utils2();
init_path();
init_client();
init_data_residency();
}
});
// node_modules/openai/internal/bedrock.mjs
var brand_privateBedrockClient;
var init_bedrock = __esm({
"node_modules/openai/internal/bedrock.mjs"() {
init_error2();
init_utils2();
brand_privateBedrockClient = /* @__PURE__ */ Symbol.for("openai.privateBedrockClient");
}
});
// node_modules/openai/bedrock.mjs
var _a4;
var init_bedrock2 = __esm({
"node_modules/openai/bedrock.mjs"() {
init_error2();
init_client();
init_realtime_credentials();
init_data_residency();
init_bedrock();
init_headers2();
init_utils2();
init_ResponsesParser();
init_resources();
_a4 = brand_privateBedrockClient;
}
});
// node_modules/openai/index.mjs
var init_openai = __esm({
"node_modules/openai/index.mjs"() {
init_client();
init_uploads2();
init_api_promise();
init_client();
init_pagination();
init_error();
init_azure();
init_bedrock2();
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/provider-env.js
function getBunSandboxEnvValue(name) {
if (typeof process === "undefined" || !process.versions?.bun || Object.keys(process.env).length > 0) {
return void 0;
}
if (procEnvCache === null) {
procEnvCache = /* @__PURE__ */ new Map();
try {
const { readFileSync } = __require("node:fs");
const data = readFileSync("/proc/self/environ", "utf-8");
for (const entry2 of data.split("\0")) {
const idx = entry2.indexOf("=");
if (idx > 0) {
procEnvCache.set(entry2.slice(0, idx), entry2.slice(idx + 1));
}
}
} catch {
}
}
return procEnvCache.get(name);
}
function getProviderEnvValue(name, env) {
return env?.[name] || (typeof process !== "undefined" ? process.env[name] : void 0) || getBunSandboxEnvValue(name) || void 0;
}
var procEnvCache;
var init_provider_env = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/provider-env.js"() {
procEnvCache = null;
}
});
// node_modules/@earendil-works/pi-ai/dist/api/constrained-sampling.js
function isJsonSchemaObject(value2) {
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
}
function isStructuredSchema(schema) {
if (!isJsonSchemaObject(schema))
return false;
const types = typeof schema.type === "string" ? [schema.type] : Array.isArray(schema.type) ? schema.type : [];
return types.includes("object") || types.includes("array") || schema.properties !== void 0 || schema.items !== void 0;
}
function schemaAllowsNull(schema) {
if (!isJsonSchemaObject(schema))
return false;
if (schema.type === "null" || Array.isArray(schema.type) && schema.type.includes("null"))
return true;
if (schema.const === null || Array.isArray(schema.enum) && schema.enum.includes(null))
return true;
return Array.isArray(schema.anyOf) && schema.anyOf.some((variant) => schemaAllowsNull(variant));
}
function makeJsonSchemaNodeStrict(schema, isUnsupportedKeyword) {
if (!isJsonSchemaObject(schema)) {
throw new UnsupportedStrictJsonSchemaError("boolean schemas are unsupported");
}
for (const key of UNSUPPORTED_STRICT_SCHEMA_KEYS) {
if (schema[key] !== void 0) {
throw new UnsupportedStrictJsonSchemaError(`${key} schemas are unsupported`);
}
}
if (isUnsupportedKeyword) {
for (const [key, value2] of Object.entries(schema)) {
if (isUnsupportedKeyword(key, value2)) {
throw new UnsupportedStrictJsonSchemaError(`${key}: ${JSON.stringify(value2)} is unsupported`);
}
}
}
if (schema.anyOf !== void 0) {
if (!Array.isArray(schema.anyOf) || schema.anyOf.length === 0) {
throw new UnsupportedStrictJsonSchemaError("anyOf must contain at least one schema");
}
for (const variant of schema.anyOf) {
if (isStructuredSchema(variant)) {
throw new UnsupportedStrictJsonSchemaError("object and array unions are unsupported");
}
makeJsonSchemaNodeStrict(variant, isUnsupportedKeyword);
}
}
if (schema.items !== void 0) {
if (Array.isArray(schema.items)) {
throw new UnsupportedStrictJsonSchemaError("tuple schemas are unsupported");
}
makeJsonSchemaNodeStrict(schema.items, isUnsupportedKeyword);
}
const isObjectSchema = schema.type === "object";
if (schema.properties !== void 0 && !isObjectSchema) {
throw new UnsupportedStrictJsonSchemaError("properties require type object");
}
if (!isObjectSchema)
return;
if (schema.additionalProperties !== void 0 && schema.additionalProperties !== false) {
throw new UnsupportedStrictJsonSchemaError("schema-valued or true additionalProperties is unsupported");
}
if (schema.properties !== void 0 && !isJsonSchemaObject(schema.properties)) {
throw new UnsupportedStrictJsonSchemaError("object properties must be a schema map");
}
if (schema.required !== void 0 && (!Array.isArray(schema.required) || schema.required.some((key) => typeof key !== "string"))) {
throw new UnsupportedStrictJsonSchemaError("object required must be a string array");
}
const properties = schema.properties ?? {};
const propertyNames = Object.keys(properties);
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
if ([...required].some((key) => !propertyNames.includes(key))) {
throw new UnsupportedStrictJsonSchemaError("required contains an unknown property");
}
for (const [key, property] of Object.entries(properties)) {
makeJsonSchemaNodeStrict(property, isUnsupportedKeyword);
if (!required.has(key) && !schemaAllowsNull(property)) {
properties[key] = { anyOf: [property, { type: "null" }] };
}
}
schema.required = propertyNames;
schema.additionalProperties = false;
}
function makeStrictJsonSchema(schema, isUnsupportedKeyword) {
const cloned = structuredClone(schema);
if (!isJsonSchemaObject(cloned)) {
throw new UnsupportedStrictJsonSchemaError("root schema must have type object");
}
makeJsonSchemaNodeStrict(cloned, isUnsupportedKeyword);
if (cloned.type !== "object") {
throw new UnsupportedStrictJsonSchemaError("root schema must have type object");
}
return cloned;
}
function getJsonSchemaToolParameters(tool, strict) {
return strict === true ? makeStrictJsonSchema(tool.parameters) : tool.parameters;
}
function getGrammarToolInput(toolName, arguments_, inputProperty) {
const input = arguments_[inputProperty];
if (typeof input !== "string") {
throw new Error(`Grammar tool call "${toolName}" requires argument "${inputProperty}" to be a string.`);
}
return input;
}
function appendGrammarToolInputJsonDelta(buffer, inputProperty, inputDelta) {
if (buffer.closed) {
throw new Error(`grammar tool input for property "${inputProperty}" changed after it was closed`);
}
if (inputDelta.length === 0)
return void 0;
buffer.input += inputDelta;
return grammarToolInputJsonStart(buffer, inputProperty) + JSON.stringify(inputDelta).slice(1, -1);
}
function closeGrammarToolInputJson(buffer, inputProperty, finalInput) {
if (buffer.closed) {
if (finalInput === void 0 || finalInput === buffer.input)
return void 0;
throw new Error(`grammar tool input for property "${inputProperty}" changed after it was closed`);
}
if (finalInput !== void 0 && !finalInput.startsWith(buffer.input)) {
throw new Error(`grammar tool input for property "${inputProperty}" changed non-monotonically`);
}
const rest = finalInput === void 0 ? "" : finalInput.slice(buffer.input.length);
if (finalInput !== void 0)
buffer.input = finalInput;
buffer.closed = true;
return `${grammarToolInputJsonStart(buffer, inputProperty)}${JSON.stringify(rest).slice(1, -1)}"}`;
}
function grammarToolInputJsonStart(buffer, inputProperty) {
if (buffer.started)
return "";
buffer.started = true;
return `{${JSON.stringify(inputProperty)}:"`;
}
function inferGrammarInputProperty(tool) {
const schema = tool.parameters;
if (schema.type !== "object") {
throw new Error("grammar constrained sampling requires an object parameter schema");
}
if (!Array.isArray(schema.required) || schema.required.length !== 1 || typeof schema.required[0] !== "string") {
throw new Error("grammar constrained sampling requires exactly one required string property");
}
const inputProperty = schema.required[0];
if (!schema.properties?.[inputProperty]) {
throw new Error(`grammar constrained sampling requires a properties entry for ${inputProperty}`);
}
if (schema.properties[inputProperty]?.type !== "string") {
throw new Error(`grammar constrained sampling property ${inputProperty} must have type string`);
}
return inputProperty;
}
function resolveJsonSchemaStrictSampling(tool, supportsStrictMode, isUnsupportedKeyword) {
const config = tool.constrainedSampling;
if (!config || config.type !== "json_schema")
return void 0;
if (supportsStrictMode) {
try {
makeStrictJsonSchema(tool.parameters, isUnsupportedKeyword);
return true;
} catch (error) {
if (!(error instanceof UnsupportedStrictJsonSchemaError))
throw error;
if (config.strict !== "require")
return void 0;
throw new Error(`Tool "${tool.name}" requires JSON-schema constrained sampling, but ${error.message}.`);
}
}
if (config.strict === "require") {
throw new Error(`Tool "${tool.name}" requires JSON-schema constrained sampling, but strict tools are unsupported.`);
}
return void 0;
}
function resolveGrammarConstrainedSampling(tool, supportsOpenAIGrammarTools) {
const config = tool.constrainedSampling;
if (!config || config.type !== "grammar") {
return void 0;
}
if (!supportsOpenAIGrammarTools) {
return void 0;
}
const larkDefinition = config.variants.openai_lark;
const regexDefinition = config.variants.openai_regex;
const hasLarkDefinition = typeof larkDefinition === "string" && larkDefinition.trim().length > 0;
const hasRegexDefinition = typeof regexDefinition === "string" && regexDefinition.trim().length > 0;
if (!hasLarkDefinition && !hasRegexDefinition) {
throw new Error(`Tool "${tool.name}" cannot use grammar constrained sampling: no supported grammar variant was provided.`);
}
try {
return {
format: hasLarkDefinition ? "lark" : "regex",
definition: hasLarkDefinition ? larkDefinition : regexDefinition,
inputProperty: inferGrammarInputProperty(tool)
};
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`Tool "${tool.name}" cannot use grammar constrained sampling: ${message}.`);
}
}
function createGrammarToolInputProperties(tools, supportsOpenAIGrammarTools) {
const properties = /* @__PURE__ */ new Map();
for (const tool of tools ?? []) {
const grammar = resolveGrammarConstrainedSampling(tool, supportsOpenAIGrammarTools);
if (grammar) {
properties.set(tool.name, grammar.inputProperty);
}
}
return properties;
}
var UnsupportedStrictJsonSchemaError, UNSUPPORTED_STRICT_SCHEMA_KEYS;
var init_constrained_sampling = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/constrained-sampling.js"() {
UnsupportedStrictJsonSchemaError = class extends Error {
};
UNSUPPORTED_STRICT_SCHEMA_KEYS = [
"$ref",
"$defs",
"definitions",
"allOf",
"oneOf",
"patternProperties",
"dependentSchemas",
"dependencies",
"unevaluatedProperties",
"propertyNames",
"contains",
"prefixItems",
"not",
"if",
"then",
"else"
];
}
});
// node_modules/@earendil-works/pi-ai/dist/api/github-copilot-headers.js
function inferCopilotInitiator(messages) {
const last = messages[messages.length - 1];
return last && last.role !== "user" ? "agent" : "user";
}
function hasCopilotVisionInput(messages) {
return messages.some((msg) => {
if (msg.role === "user" && Array.isArray(msg.content)) {
return msg.content.some((c) => c.type === "image");
}
if (msg.role === "toolResult" && Array.isArray(msg.content)) {
return msg.content.some((c) => c.type === "image");
}
return false;
});
}
function buildCopilotDynamicHeaders(params) {
const headers = {
"X-Initiator": inferCopilotInitiator(params.messages),
"Openai-Intent": "conversation-edits"
};
if (params.hasImages) {
headers["Copilot-Vision-Request"] = "true";
}
return headers;
}
var init_github_copilot_headers = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/github-copilot-headers.js"() {
}
});
// node_modules/@earendil-works/pi-ai/dist/api/openai-prompt-cache.js
function clampOpenAIPromptCacheKey(key) {
if (key === void 0)
return void 0;
const chars = Array.from(key);
if (chars.length <= OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH)
return key;
return chars.slice(0, OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH).join("");
}
var OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH;
var init_openai_prompt_cache = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/openai-prompt-cache.js"() {
OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH = 64;
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/hash.js
function shortHash(str2) {
let h1 = 3735928559;
let h2 = 1103547991;
for (let i = 0; i < str2.length; i++) {
const ch = str2.charCodeAt(i);
h1 = Math.imul(h1 ^ ch, 2654435761);
h2 = Math.imul(h2 ^ ch, 1597334677);
}
h1 = Math.imul(h1 ^ h1 >>> 16, 2246822507) ^ Math.imul(h2 ^ h2 >>> 13, 3266489909);
h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507) ^ Math.imul(h1 ^ h1 >>> 13, 3266489909);
return (h2 >>> 0).toString(36) + (h1 >>> 0).toString(36);
}
var init_hash = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/hash.js"() {
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/sanitize-unicode.js
function sanitizeSurrogates(text2) {
return text2.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
}
var init_sanitize_unicode = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/sanitize-unicode.js"() {
}
});
// node_modules/partial-json/dist/options.js
var require_options = __commonJS({
"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;
}
});
// node_modules/partial-json/dist/index.js
var require_dist = __commonJS({
"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 PartialJSON2 = class extends Error {
};
exports.PartialJSON = PartialJSON2;
var MalformedJSON2 = class extends Error {
};
exports.MalformedJSON = MalformedJSON2;
function parseJSON2(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 _parseJSON2(jsonString.trim(), allowPartial);
}
exports.parseJSON = parseJSON2;
var _parseJSON2 = (jsonString, allow) => {
const length = jsonString.length;
let index = 0;
const markPartialJSON = (msg) => {
throw new PartialJSON2(`${msg} at position ${index}`);
};
const throwMalformedError = (msg) => {
throw new MalformedJSON2(`${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 escape2 = false;
index++;
while (index < length && (jsonString[index] !== '"' || escape2 && jsonString[index - 1] === "\\")) {
escape2 = jsonString[index] === "\\" ? !escape2 : false;
index++;
}
if (jsonString.charAt(index) == '"') {
try {
return JSON.parse(jsonString.substring(start, ++index - Number(escape2)));
} catch (e) {
throwMalformedError(String(e));
}
} else if (options_1.Allow.STR & allow) {
try {
return JSON.parse(jsonString.substring(start, index - Number(escape2)) + '"');
} catch (e) {
return JSON.parse(jsonString.substring(start, jsonString.lastIndexOf("\\")) + '"');
}
}
markPartialJSON("Unterminated string literal");
};
const parseObj = () => {
index++;
skipBlank();
const obj2 = {};
try {
while (jsonString[index] !== "}") {
skipBlank();
if (index >= length && options_1.Allow.OBJ & allow)
return obj2;
const key = parseStr();
skipBlank();
index++;
try {
const value2 = parseAny();
obj2[key] = value2;
} catch (e) {
if (options_1.Allow.OBJ & allow)
return obj2;
else
throw e;
}
skipBlank();
if (jsonString[index] === ",")
index++;
}
} catch (e) {
if (options_1.Allow.OBJ & allow)
return obj2;
else
markPartialJSON("Expected '}' at end of object");
}
index++;
return obj2;
};
const parseArr = () => {
index++;
const arr2 = [];
try {
while (jsonString[index] !== "]") {
arr2.push(parseAny());
skipBlank();
if (jsonString[index] === ",") {
index++;
}
}
} catch (e) {
if (options_1.Allow.ARR & allow) {
return arr2;
}
markPartialJSON("Expected ']' at end of array");
}
index++;
return arr2;
};
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 = parseJSON2;
exports.parse = parse;
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/json-parse.js
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}`
};
}
}
var import_partial_json, VALID_JSON_ESCAPES;
var init_json_parse = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/json-parse.js"() {
import_partial_json = __toESM(require_dist(), 1);
VALID_JSON_ESCAPES = /* @__PURE__ */ new Set(['"', "\\", "/", "b", "f", "n", "r", "t"]);
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/streaming-json.js
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, value2] of LITERALS)
if (token === literal)
return value2;
return NUMBER.test(token) ? Number(token) : void 0;
}
function pendingScalarValue(token) {
for (const [literal, value2] of LITERALS)
if (literal.startsWith(token))
return value2;
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, value2) {
if (slot.kind === "element")
container[slot.index] = value2;
else if (slot.kind === "member")
setMember(container, slot.key, value2);
}
function setMember(members, key, value2) {
if (key === "__proto__") {
Object.defineProperty(members, key, { value: value2, writable: true, enumerable: true, configurable: true });
} else {
members[key] = value2;
}
}
var MAX_REPORTED_DEPTH, ROOT_SLOT, CREDIT_PER_APPEND, CREDIT_PER_CHARACTER, MAX_PENDING_SCALAR_LENGTH, NUMBER, NUMBER_WITHOUT_EXPONENT_DIGITS, LITERALS, QUOTE, BACKSLASH, StreamingJsonParser, ToolCallArgumentsStream, SIMPLE_ESCAPES;
var init_streaming_json = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/streaming-json.js"() {
init_json_parse();
MAX_REPORTED_DEPTH = 32;
ROOT_SLOT = { kind: "root" };
CREDIT_PER_APPEND = 256;
CREDIT_PER_CHARACTER = 8;
MAX_PENDING_SCALAR_LENGTH = 64;
NUMBER = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
NUMBER_WITHOUT_EXPONENT_DIGITS = /^(-?(?:0|[1-9]\d*)(?:\.\d+)?)[eE][+-]?$/;
LITERALS = [
["true", true],
["false", false],
["null", null]
];
QUOTE = 34;
BACKSLASH = 92;
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(text2) {
this.#credit += CREDIT_PER_APPEND + CREDIT_PER_CHARACTER * text2.length;
this.#changes = [];
if (this.#string !== void 0)
this.#string.change = void 0;
let index = 0;
while (index < text2.length && !this.#done) {
const open = this.#string;
if (open !== void 0)
index = this.#readString(open, text2, index);
else if (this.#scalar !== "")
index = this.#readScalar(text2, index);
else
this.#structural(text2[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, text2, start) {
let runStart = start;
for (let index = start; index < text2.length; index++) {
const code = text2.charCodeAt(index);
if (open.escape !== "") {
if (this.#continueEscape(open, text2[index])) {
runStart = index + 1;
continue;
}
runStart = index;
}
if (code === QUOTE) {
if (index > runStart)
this.#appendString(open, text2.slice(runStart, index));
this.#endString(open);
return index + 1;
}
if (code === BACKSLASH) {
if (index > runStart)
this.#appendString(open, text2.slice(runStart, index));
open.escape = "\\";
runStart = index + 1;
}
}
if (text2.length > runStart)
this.#appendString(open, text2.slice(runStart));
return text2.length;
}
/** Read number or literal characters from `start` up to the next delimiter; returns the delimiter's index. */
#readScalar(text2, start) {
let end = start;
while (end < text2.length && !isDelimiter(text2[end]))
end++;
if (end > start) {
this.#scalar += text2.slice(start, end);
if (this.#scalarSlot !== void 0)
this.#dirty = true;
}
if (end < text2.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 path3 = this.#reportedPath(slot);
this.#string = { target: "value", slot, text: "", escape: "", path: path3, change: void 0 };
this.#place(slot, "");
if (path3 !== void 0)
this.#string.change = this.#report({ kind: "set", path: path3, 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, text2) {
open.text += text2;
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 + text2;
else
change.text += text2;
return;
}
open.change = this.#report({ kind: "append", path: open.path, text: text2 });
}
#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 value2 = scalarValue(token);
if (value2 !== void 0) {
this.#place(slot, value2);
const path3 = this.#reportedPath(slot);
if (path3 !== void 0)
this.#report({ kind: "set", path: path3, value: value2 });
}
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 value2 = pendingScalarValue(token);
return value2 === void 0 ? void 0 : { slot, value: value2 };
}
#openContainer(container) {
const slot = this.#valueSlot();
const path3 = this.#reportedPath(slot);
this.#place(slot, container);
this.#stack.push({
container,
slot,
path: path3,
reportsInside: path3 !== void 0 && path3.length < MAX_REPORTED_DEPTH,
size: 0,
key: void 0,
phase: Array.isArray(container) ? "value" : "key"
});
this.#pathCost += 1;
this.#dirty = true;
if (path3 !== void 0)
this.#report({ kind: "set", path: path3, 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, value2) {
if (slot === void 0)
return;
this.#dirty = true;
if (slot.kind === "root") {
this.#root = value2;
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] = value2;
return;
}
const members = frame.container;
if (!Object.hasOwn(members, slot.key)) {
frame.size++;
this.#pathCost++;
}
setMember(members, slot.key, value2);
}
/** 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 copy2 = Array.isArray(frame.container) ? frame.container.slice() : { ...frame.container };
if (depth === this.#stack.length - 1 && pending !== void 0)
setSlot(copy2, pending.slot, pending.value);
if (child !== void 0 && childSlot !== void 0)
setSlot(copy2, childSlot, child);
child = copy2;
childSlot = frame.slot;
}
return childSlot?.kind === "root" ? child : this.#root;
}
};
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(text2) {
if (text2.startsWith(this.#text)) {
const delta = text2.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(text2) };
}
/** 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;
}
};
SIMPLE_ESCAPES = {
'"': '"',
"\\": "\\",
"/": "/",
b: "\b",
f: "\f",
n: "\n",
r: "\r",
t: " "
};
}
});
// node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js
function replaceImagesWithPlaceholder(content, placeholder) {
const result = [];
let previousWasPlaceholder = false;
for (const block of content) {
if (block.type === "image") {
if (!previousWasPlaceholder) {
result.push({ type: "text", text: placeholder });
}
previousWasPlaceholder = true;
continue;
}
result.push(block);
previousWasPlaceholder = block.text === placeholder;
}
return result;
}
function downgradeUnsupportedImages(messages, model3) {
if (model3.input.includes("image")) {
return messages;
}
return messages.map((msg) => {
if (msg.role === "user" && Array.isArray(msg.content)) {
return {
...msg,
content: replaceImagesWithPlaceholder(msg.content, NON_VISION_USER_IMAGE_PLACEHOLDER)
};
}
if (msg.role === "toolResult") {
return {
...msg,
content: replaceImagesWithPlaceholder(msg.content, NON_VISION_TOOL_IMAGE_PLACEHOLDER)
};
}
return msg;
});
}
function transformMessages(messages, model3, normalizeToolCallId) {
const toolCallIdMap = /* @__PURE__ */ new Map();
const normalizedMessages = messages.map((msg) => msg.content == null ? { ...msg, content: [] } : msg);
const imageAwareMessages = downgradeUnsupportedImages(normalizedMessages, model3);
const transformed = imageAwareMessages.map((msg) => {
if (msg.role === "system" || msg.role === "user") {
return msg;
}
if (msg.role === "toolResult") {
const normalizedId = toolCallIdMap.get(msg.toolCallId);
if (normalizedId && normalizedId !== msg.toolCallId) {
return { ...msg, toolCallId: normalizedId };
}
return msg;
}
if (msg.role === "assistant") {
const assistantMsg = msg;
const isSameModel = assistantMsg.provider === model3.provider && assistantMsg.api === model3.api && assistantMsg.model === model3.id;
const transformedContent = assistantMsg.content.flatMap((block) => {
if (block.type === "thinking") {
if (!isSameModel)
return [];
if (block.redacted || block.thinkingSignature)
return block;
if (!block.thinking || block.thinking.trim() === "")
return [];
return block;
}
if (block.type === "text") {
if (isSameModel)
return block;
return {
type: "text",
text: block.text
};
}
if (block.type === "toolCall") {
const toolCall = block;
let normalizedToolCall = toolCall;
if (!isSameModel && toolCall.thoughtSignature) {
normalizedToolCall = { ...toolCall };
delete normalizedToolCall.thoughtSignature;
}
if (!isSameModel && normalizeToolCallId) {
const normalizedId = normalizeToolCallId(toolCall.id, model3, assistantMsg);
if (normalizedId !== toolCall.id) {
toolCallIdMap.set(toolCall.id, normalizedId);
normalizedToolCall = { ...normalizedToolCall, id: normalizedId };
}
}
return normalizedToolCall;
}
return block;
});
return {
...assistantMsg,
content: transformedContent
};
}
return msg;
});
const result = [];
let pendingToolCalls = [];
let existingToolResultIds = /* @__PURE__ */ new Set();
const heldSystemMessages = [];
const closePendingToolCalls = () => {
if (pendingToolCalls.length > 0) {
for (const tc of pendingToolCalls) {
if (!existingToolResultIds.has(tc.id)) {
result.push({
role: "toolResult",
toolCallId: tc.id,
toolName: tc.name,
content: [{ type: "text", text: "No result provided" }],
isError: true,
timestamp: Date.now()
});
}
}
pendingToolCalls = [];
existingToolResultIds = /* @__PURE__ */ new Set();
}
result.push(...heldSystemMessages);
heldSystemMessages.length = 0;
};
for (let i = 0; i < transformed.length; i++) {
const msg = transformed[i];
if (msg.role === "assistant") {
closePendingToolCalls();
const assistantMsg = msg;
if (assistantMsg.stopReason === "error" || assistantMsg.stopReason === "aborted") {
continue;
}
const toolCalls = assistantMsg.content.filter((b) => b.type === "toolCall");
if (toolCalls.length > 0) {
pendingToolCalls = toolCalls;
existingToolResultIds = /* @__PURE__ */ new Set();
}
result.push(msg);
} else if (msg.role === "toolResult") {
existingToolResultIds.add(msg.toolCallId);
result.push(msg);
} else if (msg.role === "system") {
if (pendingToolCalls.length > 0) {
heldSystemMessages.push(msg);
} else {
result.push(msg);
}
} else if (msg.role === "user") {
closePendingToolCalls();
result.push(msg);
} else {
result.push(msg);
}
}
closePendingToolCalls();
return result;
}
var NON_VISION_USER_IMAGE_PLACEHOLDER, NON_VISION_TOOL_IMAGE_PLACEHOLDER;
var init_transform_messages = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js"() {
NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
NON_VISION_TOOL_IMAGE_PLACEHOLDER = "(tool image omitted: model does not support images)";
}
});
// node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js
function encodeTextSignatureV1(id, phase) {
const payload = { v: 1, id };
if (phase)
payload.phase = phase;
return JSON.stringify(payload);
}
function parseTextSignature(signature) {
if (!signature)
return void 0;
if (signature.startsWith("{")) {
try {
const parsed = JSON.parse(signature);
if (parsed.v === 1 && typeof parsed.id === "string") {
if (parsed.phase === "commentary" || parsed.phase === "final_answer") {
return { id: parsed.id, phase: parsed.phase };
}
return { id: parsed.id };
}
} catch {
}
}
return { id: signature };
}
function convertToolResultOutput(model3, content) {
const textResult = content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
const images = content.filter((c) => c.type === "image");
const hasText = textResult.trim().length > 0;
if (images.length === 0 || !model3.input.includes("image")) {
return sanitizeSurrogates(hasText ? textResult : images.length > 0 ? "(see attached image)" : "(no tool output)");
}
const output = [];
if (hasText) {
output.push({ type: "input_text", text: sanitizeSurrogates(textResult) });
}
for (const image of images) {
output.push({
type: "input_image",
detail: "auto",
image_url: `data:${image.mimeType};base64,${image.data}`
});
}
return output;
}
function getResponsesToolSupport(options) {
if (options.supportsMidConvoSystemMessages && options.supportsAdditionalTools)
return "changes";
return options.supportsToolSearch ? "additions" : "none";
}
function renderIncrementalToolsNotice(unavailable) {
const notice = "This is an incremental tools update. Previously declared tools remain available unless explicitly marked unavailable. A tool declared again here is available again, and its latest definition replaces the earlier one.";
return unavailable.size > 0 ? `${notice}
Still unavailable: ${[...unavailable].join(", ")}.` : notice;
}
function renderToolRemovalNotice(names2) {
return `The following tools are no longer available. Do not call them:
${names2.map((name) => `- ${name}`).join("\n")}`;
}
function convertResponsesMessages(model3, context, allowedToolCallProviders, options) {
const normalizedContext = resolveTranscript(context, options?.supportsMidConvoSystemMessages);
const messages = [];
const normalizeIdPart = (part) => {
const sanitized = part.replace(/[^a-zA-Z0-9_-]/g, "_");
const normalized = sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized;
return normalized.replace(/_+$/, "");
};
const buildForeignResponsesItemId = (itemId) => {
const normalized = `fc_${shortHash(itemId)}`;
return normalized.length > 64 ? normalized.slice(0, 64) : normalized;
};
const normalizeToolCallId = (id, _targetModel, source) => {
if (!allowedToolCallProviders.has(model3.provider))
return normalizeIdPart(id);
if (!id.includes("|"))
return normalizeIdPart(id);
const [callId, itemId] = id.split("|");
const normalizedCallId = normalizeIdPart(callId);
const isForeignToolCall = source.provider !== model3.provider || source.api !== model3.api;
let normalizedItemId = isForeignToolCall ? buildForeignResponsesItemId(itemId) : normalizeIdPart(itemId);
if (!normalizedItemId.startsWith("fc_")) {
normalizedItemId = normalizeIdPart(`fc_${normalizedItemId}`);
}
return `${normalizedCallId}|${normalizedItemId}`;
};
const transformedMessages = transformMessages(normalizedContext.messages, model3, normalizeToolCallId);
const toolSupport = getResponsesToolSupport(options ?? {});
const transcriptTools = resolveTranscriptTools(normalizedContext.messages, toolSupport);
let declaredAdditionalTools = false;
const unavailableTools = /* @__PURE__ */ new Set();
const appendSystemToolAdditions = (message, seed) => {
const tools = message.toolsAdded ?? [];
for (const tool of tools)
unavailableTools.delete(tool.name);
if (tools.length === 0)
return;
if (toolSupport === "changes") {
if (declaredAdditionalTools) {
messages.push({ role: instructionRole, content: renderIncrementalToolsNotice(unavailableTools) });
}
declaredAdditionalTools = true;
messages.push({
type: "additional_tools",
role: "developer",
tools: convertResponsesTools(tools, options?.toolOptions)
});
return;
}
if (toolSupport !== "additions")
return;
const names2 = tools.map((tool) => tool.name);
const callId = `pi_tool_load_${shortHash(`${seed}:${names2.join(",")}`)}`;
messages.push({
type: "tool_search_call",
call_id: callId,
execution: "client",
status: "completed",
arguments: { query: names2.join(" "), limit: names2.length }
});
messages.push({
type: "tool_search_output",
call_id: callId,
execution: "client",
status: "completed",
tools: convertResponsesTools(tools, { ...options?.toolOptions, toolSearchResult: true })
});
};
const includeInitialSystemMessage = options?.includeSystemPrompt ?? true;
const pushConfigurationUpdate = (effort) => {
messages.push({
type: "configuration_update",
reasoning: { effort }
});
};
const compat = model3.compat;
const instructionRole = model3.reasoning && compat?.supportsDeveloperRole !== false ? "developer" : "system";
let msgIndex = 0;
let sourceIndex = 0;
let systemIndex = 0;
for (const msg of transformedMessages) {
const isLeadingSystemMessage = sourceIndex++ === 0 && msg.role === "system";
if (msg.role === "system") {
const anchorsToolChanges = systemIndex++ >= transcriptTools.foldedSystemMessages;
if (anchorsToolChanges)
appendSystemToolAdditions(msg, `system:${msgIndex}`);
if (!isLeadingSystemMessage || includeInitialSystemMessage) {
const parts = [isLeadingSystemMessage ? getSystemMessageText(msg) : renderSystemMessageUpdate(msg)];
if (anchorsToolChanges) {
const added = new Set((msg.toolsAdded ?? []).map((tool) => tool.name));
const removed = (msg.toolsRemoved ?? []).map((tool) => tool.name).filter((name) => !added.has(name));
if (removed.length > 0)
parts.push(renderToolRemovalNotice(removed));
for (const name of removed)
unavailableTools.add(name);
}
const text2 = parts.filter((part) => part.length > 0).join("\n\n");
if (text2.length > 0) {
messages.push({ role: instructionRole, content: sanitizeSurrogates(text2) });
}
}
} else if (msg.role === "user") {
if (typeof msg.content === "string") {
messages.push({
role: "user",
content: [{ type: "input_text", text: sanitizeSurrogates(msg.content) }]
});
} else {
const content = msg.content.map((item) => {
if (item.type === "text") {
return {
type: "input_text",
text: sanitizeSurrogates(item.text)
};
}
return {
type: "input_image",
detail: "auto",
image_url: `data:${item.mimeType};base64,${item.data}`
};
});
if (content.length === 0)
continue;
messages.push({
role: "user",
content
});
}
} else if (msg.role === "assistant") {
const output = [];
const assistantMsg = msg;
const isSameProviderAndApi = assistantMsg.provider === model3.provider && assistantMsg.api === model3.api;
const isSameModel = isSameProviderAndApi && assistantMsg.model === model3.id;
const isDifferentModel = isSameProviderAndApi && assistantMsg.model !== model3.id;
let textBlockIndex = 0;
for (const block of msg.content) {
if (block.type === "thinking") {
if (block.thinkingSignature) {
const reasoningItem = JSON.parse(block.thinkingSignature);
output.push(reasoningItem);
}
} else if (block.type === "text") {
const textBlock = block;
const parsedSignature = parseTextSignature(textBlock.textSignature);
const fallbackMessageId = textBlockIndex === 0 ? `msg_pi_${msgIndex}` : `msg_pi_${msgIndex}_${textBlockIndex}`;
textBlockIndex++;
let msgId = parsedSignature?.id;
if (!msgId) {
msgId = fallbackMessageId;
} else if (msgId.length > 64) {
msgId = `msg_${shortHash(msgId)}`;
}
output.push({
type: "message",
role: "assistant",
content: [{ type: "output_text", text: sanitizeSurrogates(textBlock.text), annotations: [] }],
status: "completed",
id: msgId,
phase: parsedSignature?.phase
});
} else if (block.type === "toolCall") {
const toolCall = block;
const [callId, itemIdRaw] = toolCall.id.split("|");
const customInputProperty = options?.grammarToolInputProperties?.get(toolCall.name);
let itemId = itemIdRaw;
const itemIdPrefix = customInputProperty === void 0 ? "fc_" : "ctc_";
if (isDifferentModel || !itemId?.startsWith(itemIdPrefix)) {
itemId = void 0;
}
if (customInputProperty !== void 0) {
output.push({
type: "custom_tool_call",
id: itemId,
call_id: callId,
name: toolCall.name,
input: sanitizeSurrogates(getGrammarToolInput(toolCall.name, toolCall.arguments, customInputProperty)),
...isSameModel && toolCall.namespace !== void 0 ? { namespace: toolCall.namespace } : {}
});
} else {
output.push({
type: "function_call",
id: itemId,
call_id: callId,
name: toolCall.name,
arguments: JSON.stringify(toolCall.arguments),
...isSameModel && toolCall.namespace !== void 0 ? { namespace: toolCall.namespace } : {}
});
}
}
}
if (output.length === 0)
continue;
if (options?.configurationUpdateEffort !== void 0 && isSameModel && msg.providerThinkingLevel !== void 0) {
pushConfigurationUpdate(msg.providerThinkingLevel);
}
messages.push(...output);
} else if (msg.role === "toolResult") {
const [callId] = msg.toolCallId.split("|");
const output = convertToolResultOutput(model3, msg.content);
if (options?.grammarToolInputProperties?.has(msg.toolName)) {
messages.push({
type: "custom_tool_call_output",
call_id: callId,
output
});
} else {
messages.push({
type: "function_call_output",
call_id: callId,
output
});
}
}
if (!isLeadingSystemMessage)
msgIndex++;
}
if (options?.configurationUpdateEffort !== void 0)
pushConfigurationUpdate(options.configurationUpdateEffort);
return messages;
}
function convertResponsesTools(tools, options) {
const defaultStrict = options?.strict === void 0 ? false : options.strict;
const supportsStrictMode = options?.supportsStrictMode ?? true;
const supportsOpenAIGrammarTools = options?.supportsOpenAIGrammarTools ?? false;
return tools.map((tool) => {
const grammar = resolveGrammarConstrainedSampling(tool, supportsOpenAIGrammarTools);
if (grammar) {
return {
type: "custom",
name: tool.name,
description: tool.description,
format: {
type: "grammar",
syntax: grammar.format,
definition: grammar.definition
},
...options?.toolSearchResult ? { defer_loading: true } : {}
};
}
const constrainedStrict = resolveJsonSchemaStrictSampling(tool, supportsStrictMode);
const strict = constrainedStrict ?? defaultStrict;
const functionTool = {
type: "function",
name: tool.name,
description: tool.description,
parameters: getJsonSchemaToolParameters(tool, strict === true),
...options?.toolSearchResult ? { defer_loading: true } : {}
};
if (supportsStrictMode) {
functionTool.strict = strict;
}
return functionTool;
});
}
async function processResponsesStream(openaiStream, output, stream2, model3, options) {
let sawTerminalResponseEvent = false;
const outputSlots = /* @__PURE__ */ new Map();
const unfinishedToolCalls = /* @__PURE__ */ new Set();
const reasoningBlocksById = /* @__PURE__ */ new Map();
const applyMessagePhaseStopReason = (item) => {
if (item.type === "message" && item.phase === "final_answer") {
output.stopReason = "stop";
}
};
const getSlot = (outputIndex, type) => {
const slot = outputSlots.get(outputIndex);
return slot?.type === type ? slot : void 0;
};
const pushToolCallDelta = (slot, delta) => {
if (delta === void 0)
return;
stream2.push({
type: "toolcall_delta",
contentIndex: slot.contentIndex,
delta,
partial: output
});
};
const createSlot = (outputIndex, item) => {
if (item.type === "reasoning") {
const block = { type: "thinking", thinking: "" };
output.content.push(block);
const slot = {
type: "thinking",
block,
contentIndex: output.content.length - 1
};
outputSlots.set(outputIndex, slot);
stream2.push({ type: "thinking_start", contentIndex: slot.contentIndex, partial: output });
return slot;
}
if (item.type === "message") {
applyMessagePhaseStopReason(item);
const block = { type: "text", text: "" };
output.content.push(block);
const slot = { type: "text", block, contentIndex: output.content.length - 1 };
outputSlots.set(outputIndex, slot);
stream2.push({ type: "text_start", contentIndex: slot.contentIndex, partial: output });
return slot;
}
if (item.type === "function_call") {
const args = new ToolCallArgumentsStream();
const block = {
type: "toolCall",
id: `${item.call_id}|${item.id}`,
name: item.name,
arguments: item.arguments ? args.append(item.arguments) : {},
...item.namespace !== void 0 ? { namespace: item.namespace } : {}
};
output.content.push(block);
unfinishedToolCalls.add(block);
const slot = {
type: "toolCall",
block,
contentIndex: output.content.length - 1,
input: { kind: "json", arguments: args }
};
outputSlots.set(outputIndex, slot);
stream2.push({ type: "toolcall_start", contentIndex: slot.contentIndex, partial: output });
return slot;
}
if (item.type === "custom_tool_call") {
const inputProperty = options?.grammarToolInputProperties?.get(item.name) ?? "input";
const input = item.input || "";
const block = {
type: "toolCall",
id: `${item.call_id}|${item.id}`,
name: item.name,
arguments: { [inputProperty]: input },
...item.namespace !== void 0 ? { namespace: item.namespace } : {}
};
output.content.push(block);
unfinishedToolCalls.add(block);
const slot = {
type: "toolCall",
block,
contentIndex: output.content.length - 1,
input: customInput(inputProperty, input)
};
outputSlots.set(outputIndex, slot);
stream2.push({ type: "toolcall_start", contentIndex: slot.contentIndex, partial: output });
return slot;
}
return void 0;
};
const getOrCreateSlot = (outputIndex, item) => {
return outputSlots.get(outputIndex) ?? createSlot(outputIndex, item);
};
const backfillReasoningSignatures = (responseOutput) => {
for (const item of responseOutput) {
if (item.type !== "reasoning" || !item.encrypted_content)
continue;
const block = reasoningBlocksById.get(item.id);
if (!block?.thinkingSignature)
continue;
const storedItem = JSON.parse(block.thinkingSignature);
if (storedItem.encrypted_content)
continue;
block.thinkingSignature = JSON.stringify({
...storedItem,
encrypted_content: item.encrypted_content
});
}
};
const finalizeResponse2 = (response) => {
sawTerminalResponseEvent = true;
backfillReasoningSignatures(response.output ?? []);
if (response?.id) {
output.responseId = response.id;
}
if (response?.usage) {
const inputDetails = response.usage.input_tokens_details;
const cachedTokens = inputDetails?.cached_tokens || 0;
const cacheWriteTokens = inputDetails?.cache_write_tokens || 0;
output.usage = {
// OpenAI includes cached and cache-write tokens in input_tokens, so subtract both.
input: Math.max(0, (response.usage.input_tokens || 0) - cachedTokens - cacheWriteTokens),
output: response.usage.output_tokens || 0,
cacheRead: cachedTokens,
cacheWrite: cacheWriteTokens,
reasoning: response.usage.output_tokens_details?.reasoning_tokens || 0,
totalTokens: response.usage.total_tokens || 0,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
};
}
calculateCost(model3, output.usage);
if (options?.applyServiceTierPricing) {
const serviceTier = options.resolveServiceTier ? options.resolveServiceTier(response?.service_tier, options.serviceTier) : response?.service_tier ?? options.serviceTier;
options.applyServiceTierPricing(output.usage, serviceTier);
}
const status = response?.status;
const incompleteDetails = response?.incomplete_details;
const incompleteReason = typeof incompleteDetails?.reason === "string" ? incompleteDetails.reason : void 0;
output.rawStopReason = incompleteReason ? `${status}.${incompleteReason}` : status;
const mappedStop = mapStopReason(status, incompleteReason);
output.stopReason = mappedStop.stopReason;
if (mappedStop.errorMessage === void 0)
delete output.errorMessage;
else
output.errorMessage = mappedStop.errorMessage;
if (output.content.some((b) => b.type === "toolCall") && output.stopReason === "stop") {
output.stopReason = "toolUse";
}
};
for await (const event of openaiStream) {
await options?.onProviderStreamEvent?.(event, model3);
if (event.type === "response.created") {
output.responseId = event.response.id;
} else if (event.type === "response.output_item.added") {
createSlot(event.output_index, event.item);
} else if (event.type === "response.reasoning_summary_text.delta") {
const slot = getSlot(event.output_index, "thinking");
if (!slot)
continue;
slot.block.thinking += event.delta;
stream2.push({
type: "thinking_delta",
contentIndex: slot.contentIndex,
delta: event.delta,
partial: output
});
} else if (event.type === "response.reasoning_summary_part.done") {
const slot = getSlot(event.output_index, "thinking");
if (!slot)
continue;
slot.block.thinking += "\n\n";
stream2.push({
type: "thinking_delta",
contentIndex: slot.contentIndex,
delta: "\n\n",
partial: output
});
} else if (event.type === "response.reasoning_text.delta") {
const slot = getSlot(event.output_index, "thinking");
if (!slot)
continue;
slot.block.thinking += event.delta;
stream2.push({
type: "thinking_delta",
contentIndex: slot.contentIndex,
delta: event.delta,
partial: output
});
} else if (event.type === "response.output_text.delta") {
const slot = getSlot(event.output_index, "text");
if (!slot)
continue;
slot.block.text += event.delta;
stream2.push({
type: "text_delta",
contentIndex: slot.contentIndex,
delta: event.delta,
partial: output
});
} else if (event.type === "response.refusal.delta") {
const slot = getSlot(event.output_index, "text");
if (!slot)
continue;
slot.block.text += event.delta;
stream2.push({
type: "text_delta",
contentIndex: slot.contentIndex,
delta: event.delta,
partial: output
});
} else if (event.type === "response.function_call_arguments.delta") {
const slot = getSlot(event.output_index, "toolCall");
if (slot?.input.kind !== "json")
continue;
slot.block.arguments = slot.input.arguments.append(event.delta);
pushToolCallDelta(slot, event.delta);
} else if (event.type === "response.function_call_arguments.done") {
const slot = getSlot(event.output_index, "toolCall");
if (slot?.input.kind !== "json")
continue;
const replaced = slot.input.arguments.replace(event.arguments);
slot.block.arguments = replaced.arguments;
if (replaced.delta)
pushToolCallDelta(slot, replaced.delta);
} else if (event.type === "response.custom_tool_call_input.delta") {
const slot = getSlot(event.output_index, "toolCall");
if (slot?.input.kind !== "custom")
continue;
pushToolCallDelta(slot, appendCustomInput(slot.block, slot.input, event.delta));
} else if (event.type === "response.custom_tool_call_input.done") {
const slot = getSlot(event.output_index, "toolCall");
if (slot?.input.kind !== "custom")
continue;
pushToolCallDelta(slot, closeCustomInput(slot.block, slot.input, event.input));
} else if (event.type === "response.output_item.done") {
const item = event.item;
applyMessagePhaseStopReason(item);
const slot = getOrCreateSlot(event.output_index, item);
if (item.type === "reasoning" && slot?.type === "thinking") {
const summaryText2 = item.summary?.map((s) => s.text).join("\n\n") || "";
const contentText3 = item.content?.map((c) => c.text).join("\n\n") || "";
slot.block.thinking = summaryText2 || contentText3 || slot.block.thinking;
slot.block.thinkingSignature = JSON.stringify(item);
reasoningBlocksById.set(item.id, slot.block);
stream2.push({
type: "thinking_end",
contentIndex: slot.contentIndex,
content: slot.block.thinking,
partial: output
});
outputSlots.delete(event.output_index);
} else if (item.type === "message" && slot?.type === "text") {
slot.block.text = item.content?.map((c) => c.type === "output_text" ? c.text : c.refusal).join("") || "";
slot.block.textSignature = encodeTextSignatureV1(item.id, item.phase ?? void 0);
stream2.push({
type: "text_end",
contentIndex: slot.contentIndex,
content: slot.block.text,
partial: output
});
outputSlots.delete(event.output_index);
} else if (item.type === "function_call" && slot?.type === "toolCall" && slot.input.kind === "json") {
if (item.arguments)
slot.input.arguments.replace(item.arguments);
Object.assign(slot.block, slot.input.arguments.finish());
if (item.namespace !== void 0)
slot.block.namespace = item.namespace;
unfinishedToolCalls.delete(slot.block);
stream2.push({
type: "toolcall_end",
contentIndex: slot.contentIndex,
toolCall: slot.block,
partial: output
});
outputSlots.delete(event.output_index);
} else if (item.type === "custom_tool_call" && slot?.type === "toolCall" && slot.input.kind === "custom") {
pushToolCallDelta(slot, closeCustomInput(slot.block, slot.input, item.input));
if (item.namespace !== void 0)
slot.block.namespace = item.namespace;
unfinishedToolCalls.delete(slot.block);
stream2.push({
type: "toolcall_end",
contentIndex: slot.contentIndex,
toolCall: slot.block,
partial: output
});
outputSlots.delete(event.output_index);
}
} else if (event.type === "response.completed" || event.type === "response.incomplete") {
finalizeResponse2(event.response);
} else if (event.type === "error") {
throw new Error(`Error Code ${event.code}: ${event.message}` || "Unknown error");
} else if (event.type === "response.failed") {
sawTerminalResponseEvent = true;
output.rawStopReason = event.response?.status;
const error = event.response?.error;
const details = event.response?.incomplete_details;
const msg = error ? `${error.code || "unknown"}: ${error.message || "no message"}` : details?.reason ? `incomplete: ${details.reason}` : "Unknown error (no error details in response)";
throw new Error(msg);
}
}
if (!sawTerminalResponseEvent) {
throw new Error("OpenAI Responses stream ended before a terminal response event");
}
if (output.stopReason === "toolUse") {
for (const toolCall of unfinishedToolCalls) {
throw new Error(`OpenAI Responses stream completed with an unfinished tool call: ${toolCall.name} (${toolCall.id})`);
}
}
}
function customInput(property, initialInput) {
const buffer = { input: "", started: false, closed: false };
return {
kind: "custom",
property,
buffer,
unsent: appendGrammarToolInputJsonDelta(buffer, property, initialInput) ?? ""
};
}
function appendCustomInput(block, input, delta) {
return sendCustomInput(block, input, appendGrammarToolInputJsonDelta(input.buffer, input.property, delta));
}
function closeCustomInput(block, input, finalInput) {
return sendCustomInput(block, input, closeGrammarToolInputJson(input.buffer, input.property, finalInput));
}
function sendCustomInput(block, input, jsonDelta) {
block.arguments = { [input.property]: input.buffer.input };
if (input.unsent === "")
return jsonDelta;
const sent = input.unsent + (jsonDelta ?? "");
input.unsent = "";
return sent;
}
function mapStopReason(status, incompleteReason) {
if (!status)
return { stopReason: "stop" };
switch (status) {
case "completed":
return { stopReason: "stop" };
case "incomplete":
if (incompleteReason === "max_output_tokens") {
return { stopReason: "length" };
}
return {
stopReason: "error",
errorMessage: incompleteReason ? `Response incomplete: ${incompleteReason}` : "Response incomplete without a provider reason"
};
case "failed":
case "cancelled":
return { stopReason: "error" };
// These two are wonky ...
case "in_progress":
case "queued":
return { stopReason: "stop" };
default: {
const _exhaustive = status;
throw new Error(`Unhandled stop reason: ${_exhaustive}`);
}
}
}
var init_openai_responses_shared = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js"() {
init_models();
init_hash();
init_sanitize_unicode();
init_streaming_json();
init_text();
init_transcript();
init_constrained_sampling();
init_transform_messages();
}
});
// node_modules/@earendil-works/pi-ai/dist/utils/estimate.js
function calculateContextTokens(usage) {
return usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
}
function safeJsonStringify2(value2) {
try {
return JSON.stringify(value2) ?? "undefined";
} catch {
return "[unserializable]";
}
}
function estimateTextAndImageContentChars(content) {
if (typeof content === "string")
return content.length;
let chars = 0;
for (const block of content)
chars += block.type === "text" ? block.text.length : ESTIMATED_IMAGE_CHARS;
return chars;
}
function estimateTextTokens(text2) {
return Math.ceil(text2.length / CHARS_PER_TOKEN);
}
function estimateTextAndImageContentTokens(content) {
return Math.ceil(estimateTextAndImageContentChars(content) / CHARS_PER_TOKEN);
}
function estimateMessageTokens(message) {
let chars = 0;
if (message.role === "system") {
return estimateTextTokens(getSystemMessageText(message)) + estimateToolsTokens(message.toolsAdded) + estimateToolsTokens(message.toolsRemoved);
}
if (message.role === "user")
return estimateTextAndImageContentTokens(message.content);
if (message.role === "toolResult")
return estimateTextAndImageContentTokens(message.content);
for (const block of message.content) {
if (block.type === "text") {
chars += block.text.length;
} else if (block.type === "thinking") {
chars += block.thinking.length;
} else {
chars += block.name.length + safeJsonStringify2(block.arguments).length;
}
}
return Math.ceil(chars / CHARS_PER_TOKEN);
}
function getLastAssistantUsageInfo(messages) {
let latestPrefixTimestamp = Number.NEGATIVE_INFINITY;
let usageInfo;
for (let i = 0; i < messages.length; i++) {
const message = messages[i];
if (message.role === "assistant") {
const assistant = message;
const usageAppliesToPrefix = assistant.timestamp >= latestPrefixTimestamp;
if (usageAppliesToPrefix && assistant.stopReason !== "aborted" && assistant.stopReason !== "error" && calculateContextTokens(assistant.usage) > 0) {
usageInfo = { usage: assistant.usage, index: i };
}
}
latestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);
}
return usageInfo;
}
function estimateContextTokens(context) {
const messages = "messages" in context ? context.messages : context;
const usageInfo = getLastAssistantUsageInfo(messages);
if (usageInfo) {
const usageTokens = calculateContextTokens(usageInfo.usage);
let trailingTokens = 0;
for (let i = usageInfo.index + 1; i < messages.length; i++) {
trailingTokens += estimateMessageTokens(messages[i]);
}
return { tokens: usageTokens + trailingTokens, usageTokens, trailingTokens, lastUsageIndex: usageInfo.index };
}
let tokens = 0;
for (const message of messages)
tokens += estimateMessageTokens(message);
return { tokens, usageTokens: 0, trailingTokens: tokens, lastUsageIndex: null };
}
function estimateToolsTokens(tools) {
if (!tools || tools.length === 0)
return 0;
return estimateTextTokens(safeJsonStringify2(tools));
}
var CHARS_PER_TOKEN, ESTIMATED_IMAGE_CHARS;
var init_estimate = __esm({
"node_modules/@earendil-works/pi-ai/dist/utils/estimate.js"() {
init_text();
CHARS_PER_TOKEN = 3.5;
ESTIMATED_IMAGE_CHARS = 4800;
}
});
// node_modules/@earendil-works/pi-ai/dist/api/simple-options.js
function clampMaxTokensToContext(model3, context, maxTokens) {
if (model3.contextWindow <= 0)
return Math.max(MIN_MAX_TOKENS, maxTokens);
const available = model3.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;
return Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));
}
function resolveSamplingParams(model3, thinkingLevel, requestParams) {
const effectiveThinkingLevel = clampThinkingLevel(model3, thinkingLevel);
const thinkingLevelParams = model3.samplingParamsByThinkingLevel?.[effectiveThinkingLevel];
return model3.samplingParams || thinkingLevelParams || requestParams ? { ...model3.samplingParams, ...thinkingLevelParams, ...requestParams } : void 0;
}
function buildBaseOptions(model3, context, options, apiKey) {
const samplingParams = resolveSamplingParams(model3, options?.reasoning ?? "off", options?.samplingParams);
return {
temperature: options?.temperature,
samplingParams,
maxTokens: clampMaxTokensToContext(model3, context, options?.maxTokens ?? model3.maxTokens),
signal: options?.signal,
telemetry: options?.telemetry,
apiKey: apiKey || options?.apiKey,
fetch: options?.fetch,
transport: options?.transport,
cacheRetention: options?.cacheRetention,
sessionId: options?.sessionId,
headers: options?.headers,
identity: options?.identity,
onPayload: options?.onPayload,
onResponse: options?.onResponse,
onProviderStreamEvent: options?.onProviderStreamEvent,
timeoutMs: options?.timeoutMs,
websocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,
maxRetries: options?.maxRetries,
maxRetryDelayMs: options?.maxRetryDelayMs,
metadata: options?.metadata,
env: options?.env
};
}
var CONTEXT_SAFETY_TOKENS, MIN_MAX_TOKENS;
var init_simple_options = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/simple-options.js"() {
init_models();
init_estimate();
CONTEXT_SAFETY_TOKENS = 4096;
MIN_MAX_TOKENS = 1;
}
});
// node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js
var openai_responses_exports = {};
__export(openai_responses_exports, {
stream: () => stream,
streamSimple: () => streamSimple
});
function isChatGPTSignIn(model3, apiKey) {
return model3.provider === "openai" && model3.baseUrl === "https://api.openai.com/v1" && apiKey !== void 0 && !apiKey.startsWith("sk-");
}
function hasHeader(headers, name) {
if (!headers)
return false;
const expected = name.toLowerCase();
for (const [key, value2] of Object.entries(headers)) {
if (key.toLowerCase() === expected && value2 !== null && value2.trim().length > 0)
return true;
}
return false;
}
function getClientApiKey(provider3, apiKey, headers) {
if (apiKey)
return apiKey;
if (hasHeader(headers, "authorization") || hasHeader(headers, "cf-aig-authorization"))
return "unused";
throw new Error(`No API key for provider: ${provider3}`);
}
function detectSessionAffinityFormat(model3) {
return model3.provider === "openrouter" || model3.baseUrl.includes("openrouter.ai") ? "openrouter" : "openai";
}
function resolveCacheRetention(cacheRetention, env) {
if (cacheRetention) {
return cacheRetention;
}
if (getProviderEnvValue("PI_CACHE_RETENTION", env) === "long") {
return "long";
}
return "short";
}
function getCompat(model3) {
return {
supportsDeveloperRole: model3.compat?.supportsDeveloperRole ?? true,
supportsMidConvoSystemMessages: model3.compat?.supportsMidConvoSystemMessages ?? false,
sessionAffinityFormat: model3.compat?.sessionAffinityFormat ?? detectSessionAffinityFormat(model3),
supportsLongCacheRetention: model3.compat?.supportsLongCacheRetention ?? true,
supportsStrictMode: model3.compat?.supportsStrictMode ?? false,
supportsOpenAIGrammarTools: model3.compat?.supportsOpenAIGrammarTools ?? false,
supportsAdditionalTools: model3.compat?.supportsAdditionalTools ?? false,
supportsToolSearch: model3.compat?.supportsToolSearch ?? false,
supportsExplicitPromptCacheMode: model3.compat?.supportsExplicitPromptCacheMode ?? false,
supportsMaxOutputTokens: model3.compat?.supportsMaxOutputTokens ?? true,
supportsMidConvoEffort: model3.compat?.supportsMidConvoEffort ?? false
};
}
function getConfigurationUpdateEffort(model3, options, compat) {
if (!compat.supportsMidConvoEffort || !options?.reasoningEffort || // Sign in with ChatGPT rejects configuration_update items.
isChatGPTSignIn(model3, options.apiKey)) {
return void 0;
}
return model3.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
}
function getPromptCacheRetention(compat, cacheRetention) {
return cacheRetention === "long" && compat.supportsLongCacheRetention && !compat.supportsExplicitPromptCacheMode ? "24h" : void 0;
}
function getPromptCacheOptions(compat, cacheRetention) {
if (!compat.supportsExplicitPromptCacheMode)
return void 0;
if (cacheRetention === "none")
return { mode: "explicit" };
if (cacheRetention === "long" && compat.supportsLongCacheRetention)
return { ttl: "30m" };
return void 0;
}
function createClient(model3, context, apiKey, optionsHeaders, identity, fetch2, sessionId) {
const compat = getCompat(model3);
const headers = { ...getIdentityHeaders(model3, identity), ...model3.headers };
if (model3.provider === "github-copilot") {
const hasImages = hasCopilotVisionInput(context.messages);
const copilotHeaders = buildCopilotDynamicHeaders({
messages: context.messages,
hasImages
});
Object.assign(headers, copilotHeaders);
}
if (sessionId) {
if (compat.sessionAffinityFormat === "openrouter") {
headers["x-session-id"] = sessionId;
} else {
if (compat.sessionAffinityFormat === "openai") {
headers.session_id = sessionId;
}
headers["x-client-request-id"] = sessionId;
}
}
if (optionsHeaders) {
Object.assign(headers, optionsHeaders);
}
return new OpenAI({
apiKey,
baseURL: model3.baseUrl,
dangerouslyAllowBrowser: true,
fetch: fetch2,
defaultHeaders: headers
});
}
function buildParams(model3, context, options, compat, grammarToolInputProperties, configurationUpdateEffort) {
const transcriptTools = resolveTranscriptTools(context.messages, getResponsesToolSupport(compat));
const messages = convertResponsesMessages(model3, context, OPENAI_TOOL_CALL_PROVIDERS, {
grammarToolInputProperties,
supportsMidConvoSystemMessages: compat.supportsMidConvoSystemMessages,
supportsAdditionalTools: compat.supportsAdditionalTools,
supportsToolSearch: compat.supportsToolSearch,
toolOptions: {
supportsStrictMode: compat.supportsStrictMode,
supportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools
},
configurationUpdateEffort
});
const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
const omitUnsupportedFields = isChatGPTSignIn(model3, options?.apiKey);
const params = {
model: model3.id,
input: messages,
stream: true,
prompt_cache_key: cacheRetention === "none" ? void 0 : clampOpenAIPromptCacheKey(options?.sessionId),
prompt_cache_retention: omitUnsupportedFields ? void 0 : getPromptCacheRetention(compat, cacheRetention),
prompt_cache_options: omitUnsupportedFields ? void 0 : getPromptCacheOptions(compat, cacheRetention),
store: false
};
if (options?.maxTokens && compat.supportsMaxOutputTokens && !omitUnsupportedFields) {
params.max_output_tokens = Math.max(options.maxTokens, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS);
}
if (options?.temperature !== void 0 && !omitUnsupportedFields) {
params.temperature = options?.temperature;
}
if (options?.serviceTier !== void 0) {
params.service_tier = options.serviceTier;
}
if (transcriptTools.requestTools.length > 0) {
params.tools = convertResponsesTools(transcriptTools.requestTools, {
supportsStrictMode: compat.supportsStrictMode,
supportsOpenAIGrammarTools: compat.supportsOpenAIGrammarTools
});
}
if (options?.toolChoice !== void 0) {
params.tool_choice = options.toolChoice;
}
const reasoningEffort = options?.reasoningEffort ?? (options?.reasoningSummary ? "medium" : void 0);
if (model3.reasoning) {
if (reasoningEffort) {
const requestedEffort = options?.reasoningEffort ? model3.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort : reasoningEffort;
const effort = configurationUpdateEffort === void 0 ? requestedEffort : CONFIGURATION_UPDATE_REQUEST_EFFORT;
params.reasoning = {
effort,
summary: options?.reasoningSummary || "auto"
};
params.include = ["reasoning.encrypted_content"];
} else if (model3.provider !== "github-copilot" && model3.thinkingLevelMap?.off !== null) {
params.reasoning = {
effort: model3.thinkingLevelMap?.off ?? "none"
};
}
if (model3.provider === "xai")
params.include = ["reasoning.encrypted_content"];
}
const samplingParams = resolveSamplingParams(model3, reasoningEffort ?? "off", options?.samplingParams);
if (samplingParams) {
Object.assign(params, samplingParams);
}
return params;
}
function getServiceTierCostMultiplier(model3, serviceTier) {
switch (serviceTier) {
case "flex":
return 0.5;
case "priority":
case "fast":
return model3.id === "gpt-5.5" ? 2.5 : 2;
default:
return 1;
}
}
function applyServiceTierPricing(usage, serviceTier, model3) {
const multiplier = getServiceTierCostMultiplier(model3, serviceTier);
if (multiplier === 1)
return;
usage.cost.input *= multiplier;
usage.cost.output *= multiplier;
usage.cost.cacheRead *= multiplier;
usage.cost.cacheWrite *= multiplier;
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
}
var OPENAI_TOOL_CALL_PROVIDERS, OPENAI_RESPONSES_MIN_OUTPUT_TOKENS, CHATGPT_USAGE_URL, CHATGPT_WORKSPACE_LIMIT_HINT, CONFIGURATION_UPDATE_REQUEST_EFFORT, stream, streamSimple;
var init_openai_responses = __esm({
"node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js"() {
init_openai();
init_models();
init_error_body();
init_event_stream();
init_headers();
init_identity();
init_provider_env();
init_provider_retry();
init_transcript();
init_constrained_sampling();
init_github_copilot_headers();
init_openai_prompt_cache();
init_openai_responses_shared();
init_simple_options();
OPENAI_TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openai-codex", "opencode"]);
OPENAI_RESPONSES_MIN_OUTPUT_TOKENS = 16;
CHATGPT_USAGE_URL = "https://chatgpt.com/settings/usage";
CHATGPT_WORKSPACE_LIMIT_HINT = "You've reached your ChatGPT workspace's usage limit. Ask your workspace admin to increase it at admin.openai.com \u2192 Workspace \u2192 Usage limits.";
CONFIGURATION_UPDATE_REQUEST_EFFORT = "medium";
stream = (model3, context, options) => {
const stream2 = new AssistantMessageEventStream();
const normalizedContext = resolveTranscript(context, getCompat(model3).supportsMidConvoSystemMessages);
(async () => {
const compat = getCompat(model3);
const configurationUpdateEffort = getConfigurationUpdateEffort(model3, options, compat);
const output = {
role: "assistant",
content: [],
api: model3.api,
provider: model3.provider,
model: model3.id,
...configurationUpdateEffort === void 0 ? {} : { providerThinkingLevel: configurationUpdateEffort },
usage: {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0,
totalTokens: 0,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
},
stopReason: "pending",
timestamp: Date.now()
};
try {
const apiKey = getClientApiKey(model3.provider, options?.apiKey, options?.headers);
const cacheRetention = resolveCacheRetention(options?.cacheRetention, options?.env);
const cacheSessionId = cacheRetention === "none" ? void 0 : options?.sessionId;
const grammarToolInputProperties = createGrammarToolInputProperties(getDeclaredTools(normalizedContext.messages), compat.supportsOpenAIGrammarTools);
const client = createClient(model3, normalizedContext, apiKey, options?.headers, options?.identity, options?.fetch, cacheSessionId);
let params = buildParams(model3, normalizedContext, options, compat, grammarToolInputProperties, configurationUpdateEffort);
const nextParams = await options?.onPayload?.(params, model3);
if (nextParams !== void 0) {
params = nextParams;
}
const requestOptions = {
...options?.signal ? { signal: options.signal } : {},
...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
maxRetries: 0
};
const { data: openaiStream, response } = await retryProviderRequest(() => client.responses.create(params, requestOptions).withResponse(), {
maxRetries: options?.maxRetries,
maxRetryDelayMs: options?.maxRetryDelayMs,
signal: options?.signal
});
await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model3);
stream2.push({ type: "start", partial: output });
await processResponsesStream(openaiStream, output, stream2, model3, {
onProviderStreamEvent: options?.onProviderStreamEvent,
serviceTier: options?.serviceTier,
grammarToolInputProperties,
applyServiceTierPricing: (usage, serviceTier) => applyServiceTierPricing(usage, serviceTier, model3)
});
if (options?.signal?.aborted) {
throw new Error("Request was aborted");
}
if (output.stopReason === "pending") {
throw new Error("OpenAI Responses stream ended without a stop reason");
}
if (output.stopReason === "aborted" || output.stopReason === "error") {
throw new Error(output.errorMessage || "An unknown error occurred");
}
stream2.push({ type: "done", reason: output.stopReason, message: output });
stream2.end();
} catch (error) {
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
const errorMessage3 = formatProviderError(normalizeProviderError(error), `${model3.provider === "openai" ? "OpenAI" : model3.provider} API error`);
if (errorMessage3.includes("subscription_sharing_usage_limit_exceeded")) {
output.errorMessage = `${errorMessage3}
Check your ChatGPT usage: ${CHATGPT_USAGE_URL}`;
} else if (errorMessage3.includes("subscription_sharing_workplace_individual_usage_limit_exceeded")) {
output.errorMessage = `${errorMessage3}
${CHATGPT_WORKSPACE_LIMIT_HINT}`;
} else {
output.errorMessage = errorMessage3;
}
stream2.push({ type: "error", reason: output.stopReason, error: output });
stream2.end();
}
})();
return stream2;
};
streamSimple = (model3, context, options) => {
getClientApiKey(model3.provider, options?.apiKey, options?.headers);
const base = {
...buildBaseOptions(model3, context, options, options?.apiKey),
toolChoice: options?.toolChoice
};
const clampedReasoning = options?.reasoning ? clampThinkingLevel(model3, options.reasoning) : void 0;
const reasoningEffort = clampedReasoning === "off" ? void 0 : clampedReasoning;
return stream(model3, context, {
...base,
reasoningEffort
});
};
}
});
// node_modules/@earendil-works/chord/dist/context/index.js
init_dist();
var ABORT_SIGNAL_CONTEXT_KEY = Object.freeze({
token: /* @__PURE__ */ Symbol("chord.abortSignal")
});
var TELEMETRY_CONTEXT_KEY = Object.freeze({
token: /* @__PURE__ */ Symbol("chord.telemetry")
});
var BaseContext = class {
get abortSignal() {
return this.value(ABORT_SIGNAL_CONTEXT_KEY);
}
get telemetry() {
return this.value(TELEMETRY_CONTEXT_KEY) ?? NOOP_TELEMETRY_CONTEXT;
}
};
var EmptyContext = class extends BaseContext {
#name;
constructor(name) {
super();
this.#name = name;
}
value(_key) {
return void 0;
}
toString() {
return this.#name;
}
};
var ContextValue = class extends BaseContext {
#parent;
#key;
#value;
constructor(parent, key, value2) {
super();
this.#parent = parent;
this.#key = key;
this.#value = value2;
}
value(key) {
if (key.token === this.#key.token)
return this.#value;
return this.#parent.value(key);
}
toString() {
return `${this.#parent}.WithValue(${this.#key.token.description ?? "anonymous"})`;
}
};
var BACKGROUND_CONTEXT = new EmptyContext("[Context BACKGROUND_CONTEXT]");
var TODO_CONTEXT = new EmptyContext("[Context TODO_CONTEXT]");
function withContextValue(key, value2, parent) {
return new ContextValue(parent, key, value2);
}
function withTelemetry(telemetry, context) {
return withContextValue(TELEMETRY_CONTEXT_KEY, telemetry, context);
}
function withAbortSignal(signal, context) {
const parentSignal = context.abortSignal;
const combined = parentSignal === void 0 ? signal : AbortSignal.any([parentSignal, signal]);
return withContextValue(ABORT_SIGNAL_CONTEXT_KEY, combined, context);
}
function withoutAbortSignal(context) {
return withContextValue(ABORT_SIGNAL_CONTEXT_KEY, void 0, context);
}
function awaitWithContext(promise, context) {
const signal = context.abortSignal;
if (signal === void 0)
return promise;
if (signal.aborted)
return Promise.reject(abortError(signal));
return new Promise((resolve2, reject2) => {
const onAbort = () => reject2(abortError(signal));
signal.addEventListener("abort", onAbort, { once: true });
void promise.then((value2) => {
signal.removeEventListener("abort", onAbort);
resolve2(value2);
}, (error) => {
signal.removeEventListener("abort", onAbort);
reject2(error);
});
});
}
function abortError(signal) {
const reason = signal.reason;
return reason instanceof Error ? reason : new DOMException("The operation was aborted", "AbortError");
}
// main.ts
init_models();
// node_modules/@earendil-works/pi-ai/dist/api/openai-decisions.lazy.js
var openAIDecisionsApi = () => ({
classify: async (model3, context, options) => (await Promise.resolve().then(() => (init_openai_decisions(), openai_decisions_exports))).classify(model3, context, options)
});
// node_modules/@earendil-works/pi-ai/dist/api/openai-responses.lazy.js
init_lazy();
var openAIResponsesApi = () => lazyApi(() => Promise.resolve().then(() => (init_openai_responses(), openai_responses_exports)));
// node_modules/@earendil-works/pi-ai/dist/auth/helpers.js
function envApiKeyAuth(name, envVars) {
return {
name,
login: async (interaction) => {
interaction.signal.throwIfAborted();
const key = await interaction.prompt({ type: "secret", message: `Enter ${name}` });
interaction.signal.throwIfAborted();
return { type: "api_key", key };
},
resolve: async ({ ctx, credential, signal }) => {
signal.throwIfAborted();
if (credential?.key) {
return { auth: { apiKey: credential.key }, env: credential.env, source: "stored credential" };
}
for (const envVar of envVars) {
const value2 = await ctx.env(envVar);
signal.throwIfAborted();
if (value2)
return { auth: { apiKey: value2 }, source: envVar };
}
return void 0;
}
};
}
function lazyOAuth(input) {
let promise;
const loaded = () => {
promise ??= input.load();
return promise;
};
return {
name: input.name,
isSubscription: input.isSubscription,
loginLabel: input.loginLabel,
login: async (interaction, options) => (await loaded()).login(interaction, options),
refresh: async (credential, signal) => (await loaded()).refresh(credential, signal),
toAuth: async (credential) => (await loaded()).toAuth(credential)
};
}
// node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js
var __rewriteRelativeImportExtension2 = function(path3, preserveJsx) {
if (typeof path3 === "string" && /^\.\.?\//.test(path3)) {
return path3.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
});
}
return path3;
};
var importOAuthModule = (specifier) => {
const runtimeSpecifier = import.meta.url.endsWith(".js") ? specifier.replace(/\.ts$/, ".js") : specifier;
return import(__rewriteRelativeImportExtension2(runtimeSpecifier));
};
var bundledLoaders;
var loadOpenAIChatGPTOAuth = async () => {
if (bundledLoaders)
return bundledLoaders.openaiChatGPT();
return (await importOAuthModule("./openai-chatgpt.ts")).openaiChatGPTOAuth;
};
// node_modules/@earendil-works/pi-ai/dist/providers/openai.js
init_models();
// node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json
var openai_default = { "openai-decisions": { "classifier:gpt-6-luna": { type: "classifier", id: "gpt-6-luna", name: "GPT-6 Luna", api: "openai-decisions", provider: "openai", baseUrl: "https://api.openai.com/v1", input: ["text", "image"], cost: { input: 0.1, output: 0, cacheRead: 0, cacheWrite: 0, tiers: [{ inputTokensAbove: 272e3, input: 0.2, output: 0, cacheRead: 0, cacheWrite: 0 }] }, contextWindow: 922e3 } }, "openai-responses": { "chat:chat-latest": { id: "chat-latest", name: "Chat Latest", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-4": { id: "gpt-4", name: "GPT-4", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text"], cost: { input: 30, output: 60, cacheRead: 0, cacheWrite: 0 }, contextWindow: 8192, maxTokens: 8192, compat: { supportsStrictMode: true }, type: "chat" }, "chat:gpt-4-turbo": { id: "gpt-4-turbo", name: "GPT-4 Turbo", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text", "image"], cost: { input: 10, output: 30, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-4.1": { id: "gpt-4.1", name: "GPT-4.1", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text", "image"], cost: { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-4.1-mini": { id: "gpt-4.1-mini", name: "GPT-4.1 mini", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text", "image"], cost: { input: 0.4, output: 1.6, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-4.1-nano": { id: "gpt-4.1-nano", name: "GPT-4.1 nano", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text", "image"], cost: { input: 0.1, output: 0.4, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 1047576, maxTokens: 32768, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-4o": { id: "gpt-4o", name: "GPT-4o", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-4o-2024-05-13": { id: "gpt-4o-2024-05-13", name: "GPT-4o (2024-05-13)", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text", "image"], cost: { input: 5, output: 15, cacheRead: 0, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 4096, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-4o-2024-08-06": { id: "gpt-4o-2024-08-06", name: "GPT-4o (2024-08-06)", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-4o-2024-11-20": { id: "gpt-4o-2024-11-20", name: "GPT-4o (2024-11-20)", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text", "image"], cost: { input: 2.5, output: 10, cacheRead: 1.25, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-4o-mini": { id: "gpt-4o-mini", name: "GPT-4o mini", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: false, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5": { id: "gpt-5", name: "GPT-5", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5-chat-latest": { id: "gpt-5-chat-latest", name: "GPT-5 Chat Latest", api: "openai-responses", baseUrl: "https://api.openai.com/v1", provider: "openai", reasoning: false, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 16384, thinkingLevelMap: { off: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5-mini": { id: "gpt-5-mini", name: "GPT-5 Mini", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.25, output: 2, cacheRead: 0.025, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5-nano": { id: "gpt-5-nano", name: "GPT-5 Nano", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.05, output: 0.4, cacheRead: 5e-3, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5-pro": { id: "gpt-5-pro", name: "GPT-5 Pro", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 120, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: null, medium: null, high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.1": { id: "gpt-5.1", name: "GPT-5.1", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.2": { id: "gpt-5.2", name: "GPT-5.2", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.2-pro": { id: "gpt-5.2-pro", name: "GPT-5.2 Pro", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 21, output: 168, cacheRead: 0, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: null, medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.3-codex": { id: "gpt-5.3-codex", name: "GPT-5.3 Codex", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.3-codex-spark": { id: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 }, contextWindow: 128e3, maxTokens: 32e3, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.4": { id: "gpt-5.4", name: "GPT-5.4", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0, tiers: [{ inputTokensAbove: 272e3, input: 5, output: 22.5, cacheRead: 0.5, cacheWrite: 0 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsMidConvoSystemMessages: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.4-mini": { id: "gpt-5.4-mini", name: "GPT-5.4 mini", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.75, output: 4.5, cacheRead: 0.075, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsMidConvoSystemMessages: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.4-nano": { id: "gpt-5.4-nano", name: "GPT-5.4 nano", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.25, cacheRead: 0.02, cacheWrite: 0 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.4-pro": { id: "gpt-5.4-pro", name: "GPT-5.4 Pro", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 30, output: 180, cacheRead: 0, cacheWrite: 0, tiers: [{ inputTokensAbove: 272e3, input: 60, output: 270, cacheRead: 0, cacheWrite: 0 }] }, contextWindow: 105e4, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: null, medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsMidConvoSystemMessages: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.5": { id: "gpt-5.5", name: "GPT-5.5", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 0, tiers: [{ inputTokensAbove: 272e3, input: 10, output: 45, cacheRead: 1, cacheWrite: 0 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsMidConvoSystemMessages: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.5-pro": { id: "gpt-5.5-pro", name: "GPT-5.5 Pro", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 30, output: 180, cacheRead: 0, cacheWrite: 0, tiers: [{ inputTokensAbove: 272e3, input: 60, output: 270, cacheRead: 0, cacheWrite: 0 }] }, contextWindow: 105e4, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: null, medium: "medium", high: "high", xhigh: "xhigh", max: null }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.6-cyber": { id: "gpt-5.6-cyber", name: "GPT-5.6 Cyber", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 12.5, output: 75, cacheRead: 1.25, cacheWrite: 15.625 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsExplicitPromptCacheMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.6-luna": { id: "gpt-5.6-luna", name: "GPT-5.6 Luna", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25, tiers: [{ inputTokensAbove: 272e3, input: 0.4, output: 1.8, cacheRead: 0.04, cacheWrite: 0.5 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsAdditionalTools: true, supportsToolSearch: true, supportsMidConvoSystemMessages: true, supportsExplicitPromptCacheMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.6-sol": { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 4, output: 20, cacheRead: 0.4, cacheWrite: 5, tiers: [{ inputTokensAbove: 272e3, input: 8, output: 30, cacheRead: 0.8, cacheWrite: 10 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsAdditionalTools: true, supportsToolSearch: true, supportsMidConvoSystemMessages: true, supportsExplicitPromptCacheMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-5.6-terra": { id: "gpt-5.6-terra", name: "GPT-5.6 Terra", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.5, tiers: [{ inputTokensAbove: 272e3, input: 4, output: 18, cacheRead: 0.4, cacheWrite: 5 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsAdditionalTools: true, supportsToolSearch: true, supportsMidConvoSystemMessages: true, supportsExplicitPromptCacheMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-6-astra": { id: "gpt-6-astra", name: "GPT-6 Astra", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5, tiers: [{ inputTokensAbove: 272e3, input: 20, output: 75, cacheRead: 2, cacheWrite: 25 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsAdditionalTools: true, supportsToolSearch: true, supportsMidConvoSystemMessages: true, supportsExplicitPromptCacheMode: true, supportsMidConvoEffort: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-6-luna": { id: "gpt-6-luna", name: "GPT-6 Luna", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.5, cacheRead: 0.01, cacheWrite: 0.125, tiers: [{ inputTokensAbove: 272e3, input: 0.2, output: 0.75, cacheRead: 0.02, cacheWrite: 0.25 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsAdditionalTools: true, supportsToolSearch: true, supportsMidConvoSystemMessages: true, supportsExplicitPromptCacheMode: true, supportsMidConvoEffort: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-6-sol": { id: "gpt-6-sol", name: "GPT-6 Sol", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5, tiers: [{ inputTokensAbove: 272e3, input: 4, output: 15, cacheRead: 0.4, cacheWrite: 5 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsAdditionalTools: true, supportsToolSearch: true, supportsMidConvoSystemMessages: true, supportsExplicitPromptCacheMode: true, supportsMidConvoEffort: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-6.1-sol": { id: "gpt-6.1-sol", name: "GPT-6.1 Sol", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.1, cacheWrite: 2.5, tiers: [{ inputTokensAbove: 272e3, input: 4, output: 15, cacheRead: 0.2, cacheWrite: 5 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsAdditionalTools: true, supportsToolSearch: true, supportsMidConvoSystemMessages: true, supportsExplicitPromptCacheMode: true, supportsMidConvoEffort: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-6.1-terra": { id: "gpt-6.1-terra", name: "GPT-6.1 Terra", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 5, cacheRead: 0.05, cacheWrite: 1.25, tiers: [{ inputTokensAbove: 272e3, input: 2, output: 7.5, cacheRead: 0.1, cacheWrite: 2.5 }] }, contextWindow: 272e3, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsOpenAIGrammarTools: true, supportsAdditionalTools: true, supportsToolSearch: true, supportsMidConvoSystemMessages: true, supportsExplicitPromptCacheMode: true, supportsMidConvoEffort: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-daybreak-blue-latest": { id: "gpt-daybreak-blue-latest", name: "Daybreak Blue", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 4, output: 20, cacheRead: 0.4, cacheWrite: 5, tiers: [{ inputTokensAbove: 272e3, input: 8, output: 30, cacheRead: 0.8, cacheWrite: 10 }] }, contextWindow: 105e4, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsExplicitPromptCacheMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-daybreak-red-latest": { id: "gpt-daybreak-red-latest", name: "Daybreak Red", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 12.5, output: 75, cacheRead: 1.25, cacheWrite: 15.625 }, contextWindow: 4e5, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, compat: { supportsStrictMode: true, supportsExplicitPromptCacheMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:o1": { id: "o1", name: "o1", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 15, output: 60, cacheRead: 7.5, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:o1-pro": { id: "o1-pro", name: "o1-pro", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 150, output: 600, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:o3": { id: "o3", name: "o3", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:o3-mini": { id: "o3-mini", name: "o3-mini", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text"], cost: { input: 1.1, output: 4.4, cacheRead: 0.55, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true }, type: "chat" }, "chat:o3-pro": { id: "o3-pro", name: "o3-pro", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 20, output: 80, cacheRead: 0, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:o4-mini": { id: "o4-mini", name: "o4-mini", api: "openai-responses", provider: "openai", baseUrl: "https://api.openai.com/v1", reasoning: true, input: ["text", "image"], cost: { input: 1.1, output: 4.4, cacheRead: 0.275, cacheWrite: 0 }, contextWindow: 2e5, maxTokens: 1e5, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, compat: { supportsStrictMode: true }, inputLimits: { maxRequestBytes: 536870912, images: { maxPerRequest: 1500, resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" } } };
// node_modules/@earendil-works/pi-ai/dist/model-catalog.js
function flattenModelCatalog(groups, type) {
return Object.fromEntries(Object.values(groups).flatMap((models2) => Object.values(models2)).filter((model3) => model3.type === type).map((model3) => [model3.id, model3]));
}
function flattenChatModelCatalog(_provider, groups) {
return flattenModelCatalog(groups, "chat");
}
function flattenImageModelCatalog(_provider, groups) {
return flattenModelCatalog(groups, "image");
}
function flattenClassifierModelCatalog(_provider, groups) {
return flattenModelCatalog(groups, "classifier");
}
// node_modules/@earendil-works/pi-ai/dist/providers/openai.models.js
var OPENAI_MODELS = flattenChatModelCatalog("openai", openai_default);
var OPENAI_IMAGE_MODELS = flattenImageModelCatalog("openai", openai_default);
var OPENAI_CLASSIFIER_MODELS = flattenClassifierModelCatalog("openai", openai_default);
// node_modules/@earendil-works/pi-ai/dist/providers/openai.js
function openaiProvider() {
return createProvider({
id: "openai",
name: "OpenAI",
baseUrl: "https://api.openai.com/v1",
auth: {
apiKey: envApiKeyAuth("OpenAI API key", ["OPENAI_API_KEY"]),
oauth: lazyOAuth({
name: "OpenAI (ChatGPT subscription)",
isSubscription: true,
loginLabel: "Sign in with ChatGPT",
load: loadOpenAIChatGPTOAuth
})
},
models: [
...Object.values(OPENAI_MODELS),
...Object.values(OPENAI_CLASSIFIER_MODELS)
],
// Sign in with ChatGPT tokens only reach the Responses API; the Decisions API rejects them.
filterAllModels: (models2, credential) => credential?.type === "oauth" ? models2.filter((model3) => !isModelType(model3, "classifier")) : models2,
api: openAIResponsesApi(),
classifiers: {
"openai-decisions": openAIDecisionsApi()
}
});
}
// node_modules/@earendil-works/pi-schema/dist/builders.js
function str(options = {}) {
return { type: "string", ...options };
}
function num(options = {}) {
return { type: "number", ...options };
}
function bool(options = {}) {
return { type: "boolean", ...options };
}
function lit(value2, options = {}) {
return { const: value2, ...options };
}
function union(schemas, options = {}) {
return { anyOf: schemas, ...options };
}
function arr(items, options = {}) {
return { type: "array", items, ...options };
}
var Optional = class {
schema;
constructor(schema) {
this.schema = schema;
}
};
function opt(schema) {
return new Optional(schema);
}
function obj(properties, options = {}) {
const { open, ...annotations } = options;
const props = {};
const required = [];
for (const [name, property] of Object.entries(properties)) {
if (property instanceof Optional)
props[name] = property.schema;
else {
props[name] = property;
required.push(name);
}
}
return {
type: "object",
properties: props,
...required.length > 0 ? { required } : {},
...open === true ? {} : { additionalProperties: false },
...annotations
};
}
// node_modules/@earendil-works/pi-schema/dist/resolver.js
var DEFAULT_BASE = "https://json-schema.invalid/root.json";
var Resolver = class {
draft;
rootBase;
/** Schema object to the base URI it was indexed under. */
baseOf = /* @__PURE__ */ new Map();
/** URI (with a `#name` fragment) of every `$dynamicAnchor`, to its schema. */
dynamicAnchors = /* @__PURE__ */ new Map();
root;
options;
registry = /* @__PURE__ */ new Map();
rejectUnresolved;
/** The references that named nothing and resolved to `false` (with `unresolvedRefs: "reject"`). */
unresolved = /* @__PURE__ */ new Set();
resources = /* @__PURE__ */ new Map();
anchors = /* @__PURE__ */ new Map();
indexed = false;
constructor(root2, options) {
this.draft = options.draft === "7" ? "7" : "2020-12";
this.root = root2;
this.options = options;
this.rejectUnresolved = options.unresolvedRefs === "reject";
this.rootBase = isSchemaObject(root2) ? this.baseFor(root2, DEFAULT_BASE) : DEFAULT_BASE;
}
/**
* The base URI of `node`, whose parent has `base`: its `$id` changes it, unless draft 7 makes the `$id` inert. Once
* the schema is indexed, the indexed base (a resolved reference target already has its own).
*/
baseFor(node, base) {
const indexed = this.baseOf.get(node);
if (indexed !== void 0)
return indexed;
const id = node.$id;
if (typeof id !== "string")
return base;
if (this.draft === "7" && (typeof node.$ref === "string" || id.startsWith("#")))
return base;
return documentOf(resolveUri(id, base));
}
/** Indexes the root schema and the registered documents' URIs (once). */
ensureIndexed() {
if (this.indexed)
return;
this.indexed = true;
for (const [uri, schema] of Object.entries(this.options.schemas ?? {})) {
this.registry.set(documentOf(resolveUri(uri, DEFAULT_BASE)), schema);
}
this.resources.set(DEFAULT_BASE, this.root);
this.index(this.root, DEFAULT_BASE);
}
/**
* The schema a reference names, with the base URI it compiles under. Throws if it names nothing, or, with
* `unresolvedRefs: "reject"`, resolves to `false`, the schema no value passes.
*/
resolve(ref, base) {
this.ensureIndexed();
if (!this.rejectUnresolved)
return this.find(ref, base);
try {
return this.find(ref, base);
} catch {
this.unresolved.add(resolveUri(ref, base));
return { node: false, base };
}
}
/** Whether `ref`, from `base`, named nothing and resolved to `false`. */
isUnresolved(ref, base) {
return this.unresolved.has(resolveUri(ref, base));
}
find(ref, base) {
const uri = resolveUri(ref, base);
const doc = documentOf(uri);
const fragment = uri.length > doc.length ? decodeURIComponent(uri.slice(doc.length + 1)) : "";
const root2 = this.resources.has(doc) ? this.resources.get(doc) : this.load(doc);
if (root2 === void 0)
throw new Error(`Unresolved $ref ${ref} (no schema registered for ${doc})`);
if (fragment === "")
return { node: root2, base: doc };
if (fragment.startsWith("/"))
return this.pointer(root2, doc, fragment);
const target = this.anchors.get(`${doc}#${fragment}`);
if (target === void 0)
throw new Error(`Unresolved $ref ${ref} (no anchor ${fragment} in ${doc})`);
return { node: target, base: this.baseOf.get(target) ?? doc };
}
/** Whether `node` is the root of the schema resource at `base`. */
isResource(node, base) {
this.ensureIndexed();
return this.resources.get(base) === node;
}
// Walks only keywords that hold subschemas: an `$id` inside `enum`, `const` or an unknown keyword names nothing.
index(node, base) {
if (!isSchemaObject(node) || this.baseOf.has(node))
return;
let b = base;
const refOnly = this.draft === "7" && typeof node.$ref === "string";
if (!refOnly && typeof node.$id === "string") {
if (this.draft === "7" && node.$id.startsWith("#"))
this.anchors.set(documentOf(b) + node.$id, node);
else {
const uri = resolveUri(node.$id, b);
b = documentOf(uri);
this.resources.set(b, node);
if (uri.length > b.length + 1)
this.anchors.set(uri, node);
}
}
this.baseOf.set(node, b);
if (refOnly)
return;
if (this.draft !== "7") {
if (typeof node.$anchor === "string")
this.anchors.set(`${b}#${node.$anchor}`, node);
if (typeof node.$dynamicAnchor === "string") {
this.anchors.set(`${b}#${node.$dynamicAnchor}`, node);
this.dynamicAnchors.set(`${b}#${node.$dynamicAnchor}`, node);
}
}
for (const key of SCHEMA_KEYWORDS)
this.index(node[key], b);
for (const key of MAP_KEYWORDS) {
const map2 = node[key];
if (isSchemaObject(map2))
for (const k of Object.keys(map2))
this.index(map2[k], b);
}
for (const key of ARRAY_KEYWORDS) {
const list = node[key];
if (Array.isArray(list))
for (const s of list)
this.index(s, b);
}
}
load(doc) {
const schema = this.registry.get(doc);
if (schema === void 0)
return void 0;
this.resources.set(doc, schema);
this.index(schema, doc);
return schema;
}
pointer(root2, base, fragment) {
let node = root2;
let b = base;
for (const raw of fragment.split("/").slice(1)) {
const key = raw.replace(/~1/g, "/").replace(/~0/g, "~");
node = typeof node === "object" && node !== null && Object.hasOwn(node, key) ? node[key] : void 0;
if (node === void 0)
throw new Error(`Unresolved $ref #${fragment} in ${base}`);
if (typeof node === "object" && node !== null)
b = this.baseOf.get(node) ?? b;
}
return { node, base: b };
}
};
var SCHEMA_KEYWORDS = [
"additionalProperties",
"propertyNames",
"contains",
"not",
"if",
"then",
"else",
"unevaluatedProperties",
"unevaluatedItems",
"additionalItems",
"contentSchema",
"items"
];
var MAP_KEYWORDS = ["properties", "patternProperties", "$defs", "definitions", "dependentSchemas", "dependencies"];
var ARRAY_KEYWORDS = ["allOf", "anyOf", "oneOf", "prefixItems", "items"];
function isSchemaObject(value2) {
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
}
function resolveUri(ref, base) {
try {
return new URL(ref, base).href;
} catch {
return ref.startsWith("#") ? documentOf(base) + ref : ref;
}
}
function documentOf(uri) {
const hash = uri.indexOf("#");
return hash < 0 ? uri : uri.slice(0, hash);
}
// node_modules/@earendil-works/pi-schema/dist/shared.js
function sharedRegex(source) {
const hit = regexes.get(source)?.deref();
if (hit !== void 0)
return hit;
let re;
try {
re = new RegExp(source, "u");
} catch {
re = new RegExp(source);
}
regexes.set(source, new WeakRef(re));
regexCleanup.register(re, source);
return re;
}
var regexes = /* @__PURE__ */ new Map();
var regexCleanup = new FinalizationRegistry((source) => {
if (regexes.get(source)?.deref() === void 0)
regexes.delete(source);
});
// node_modules/@earendil-works/pi-schema/dist/coerce.js
var Coercer = class {
c;
schema;
/**
* The (schema node, value) pairs pass 2 is converting through a re-entry point, as a stack. Conversion can enter
* a node again with the same value only through a `$ref` or by wrapping a single value into an array (also for
* schemas that cycle through shared JS objects): a recursive schema that meets a value no branch accepts would
* convert it without end. A pair already on the stack (primitives by value, objects by reference) leaves the value
* unchanged. Only those two points push, so schemas without references or wraps pay nothing.
*/
entered = [];
/** How often a re-entry was cut short in this coerce() call; results computed across one are not memoized. */
cuts = 0;
/**
* Results of `$ref` targets by (node, value) within one coerce() call: a recursive union whose branches all
* convert the same children (and all fail) would convert them once per branch, exponentially in the depth.
*/
memo = void 0;
constructor(compiler2, schema) {
this.c = compiler2;
this.schema = schema;
}
/** `value` coerced: a copy along the changed paths only, or `value` itself when nothing changes. */
coerce(value2) {
const base = this.c.r.rootBase;
const withoutNulls = this.dropOptionalNulls(value2, this.schema, base);
return this.coerceTypes(this.convertOnly(withoutNulls), this.schema, base);
}
/** Pass 2 alone, as TypeBox's `Value.Convert` (the TypeBox conformance tests run it). */
convertOnly(value2) {
try {
return this.convert(this.schema, this.c.r.rootBase, value2);
} finally {
this.memo = void 0;
this.cuts = 0;
}
}
/** `node` converted for `value` at a re-entry point: unchanged when that pair is already being converted. */
reenter(node, base, value2, memoize) {
const entered = this.entered;
for (let i = 0; i < entered.length; i += 2) {
if (entered[i] === node && Object.is(entered[i + 1], value2)) {
this.cuts++;
return value2;
}
}
const memo = memoize ? this.memo?.get(node) : void 0;
if (memo?.has(value2))
return memo.get(value2);
const cuts = this.cuts;
entered.push(node, value2);
let result;
try {
result = this.convert(node, base, value2);
} finally {
entered.length -= 2;
}
if (memoize && this.cuts === cuts) {
this.memo ??= /* @__PURE__ */ new Map();
let values = this.memo.get(node);
if (values === void 0) {
values = /* @__PURE__ */ new Map();
this.memo.set(node, values);
}
values.set(value2, result);
}
return result;
}
/** Whether `value` passes the schema `node`; undefined when `node` cannot be compiled. */
passes(node, base, value2) {
try {
return this.c.check(node, this.baseOf(node, base))(value2);
} catch {
return void 0;
}
}
baseOf(node, base) {
return isSchemaObject(node) ? this.c.r.baseOf.get(node) ?? base : base;
}
// ---------------------------------------------------------------------------------------------------------------
// Pass 1: optional nulls
// ---------------------------------------------------------------------------------------------------------------
dropOptionalNulls(value2, schema, base) {
if (!isSchemaObject(schema))
return value2;
const b = this.baseOf(schema, base);
if (Array.isArray(value2)) {
return mapItems(value2, (item, i) => {
const itemSchema = itemSchemaAt(schema, i);
return itemSchema === void 0 ? item : this.dropOptionalNulls(item, itemSchema, b);
});
}
if (!isPlainObject(value2))
return value2;
const properties = isSchemaObject(schema.properties) ? schema.properties : {};
const patterns = isSchemaObject(schema.patternProperties) ? Object.entries(schema.patternProperties).map(([pattern, item]) => [sharedRegex(pattern), item]) : [];
const additional = isSchemaObject(schema.additionalProperties) ? schema.additionalProperties : void 0;
if (patterns.length === 0 && additional === void 0 && !isSchemaObject(schema.properties))
return value2;
const required = new Set(Array.isArray(schema.required) ? schema.required : []);
let out;
const set = (key, next) => {
if (next === (out ?? value2)[key])
return;
out ??= { ...value2 };
out[key] = next;
};
for (const [key, property] of Object.entries(properties)) {
if (!Object.hasOwn(value2, key))
continue;
const isRef = isSchemaObject(property) && typeof property.$ref === "string";
if (value2[key] === null && !required.has(key) && !isRef && this.passes(property, b, null) === false) {
out ??= { ...value2 };
delete out[key];
continue;
}
set(key, this.dropOptionalNulls(value2[key], property, b));
}
if (patterns.length > 0 || additional !== void 0) {
for (const key of Object.keys(value2)) {
let matched = Object.hasOwn(properties, key);
for (const [pattern, item] of patterns) {
if (!pattern.test(key))
continue;
matched = true;
set(key, this.dropOptionalNulls((out ?? value2)[key], item, b));
}
if (!matched && additional !== void 0)
set(key, this.dropOptionalNulls(value2[key], additional, b));
}
}
return out ?? value2;
}
// ---------------------------------------------------------------------------------------------------------------
// Pass 2: TypeBox's conversion rules
// ---------------------------------------------------------------------------------------------------------------
convert(node, base, value2) {
if (!isSchemaObject(node))
return value2;
const b = this.baseOf(node, base);
if (typeof node.$ref === "string") {
let target;
try {
target = this.c.r.resolve(node.$ref, b);
} catch {
return value2;
}
return isSchemaObject(target.node) ? this.reenter(target.node, target.base, value2, true) : value2;
}
return this.convertNode(node, b, value2);
}
/** One schema node's conversion: its first keyword among `const`, `enum`, the unions, `allOf` and `type`. */
convertNode(node, b, value2) {
if (Object.hasOwn(node, "const"))
return convertLiteral(node.const, value2);
if (Array.isArray(node.enum))
return this.convertEnum(node, node.enum, b, value2);
if (Array.isArray(node.anyOf))
return this.convertUnion(node, node.anyOf, b, value2);
if (Array.isArray(node.oneOf))
return this.convertUnion(node, node.oneOf, b, value2);
if (Array.isArray(node.allOf)) {
let next = value2;
for (const member of node.allOf)
next = this.convert(member, b, next);
return this.convertMembers(node, b, next);
}
switch (node.type) {
case "string":
return orValue(tryString(value2), value2);
case "number":
return orValue(tryNumber(value2), value2);
case "integer": {
const result = tryNumber(value2);
return result === void 0 ? value2 : Math.trunc(result.value);
}
case "boolean":
return orValue(tryBoolean(value2), value2);
case "null":
return orValue(tryNull(value2), value2);
case "array":
return this.convertArray(node, b, value2);
case "object":
return this.convertObject(node, b, value2);
case void 0:
if (node.properties !== void 0 || node.patternProperties !== void 0) {
return this.convertObject(node, b, value2);
}
if (node.items !== void 0 || node.prefixItems !== void 0)
return this.convertArray(node, b, value2);
return value2;
default:
return value2;
}
}
/** An enum is a union of its values: a member stays, else the first value the input converts to. */
convertEnum(node, values, base, value2) {
if (values.some((member) => member === value2))
return value2;
for (const member of values) {
const candidate = convertLiteral(member, value2);
if (candidate !== value2 && this.passes(node, base, candidate) === true)
return candidate;
}
return value2;
}
/**
* A value one branch accepts stays; else the first branch's conversion that the whole union accepts. Branches are
* converted in order and only until one is accepted, so a later recursive branch is not entered needlessly. A node
* that also declares members (plain JSON Schema; TypeBox's never do) converts them into each candidate before it is
* checked, so a branch is not discarded for a sibling property that is converted after it.
*/
convertUnion(node, branches, base, value2) {
if (branches.some((branch) => this.passes(branch, base, value2) === true))
return this.convertMembers(node, base, value2);
for (const branch of branches) {
const candidate = this.convertMembers(node, base, this.convert(branch, base, value2));
if (this.passes(node, base, candidate) === true)
return candidate;
}
return this.convertMembers(node, base, value2);
}
/** The object members of a union or intersection node, when it declares any. */
convertMembers(node, base, value2) {
const declares = node.properties !== void 0 || node.patternProperties !== void 0 || node.additionalProperties !== void 0;
return declares ? this.convertObject(node, base, value2) : value2;
}
convertArray(node, base, value2) {
const prefix = Array.isArray(node.items) ? node.items : Array.isArray(node.prefixItems) ? node.prefixItems : void 0;
if (prefix !== void 0) {
if (!Array.isArray(value2))
return value2;
const rest = Array.isArray(node.items) ? void 0 : node.items;
return mapItems(value2, (item2, i) => {
const schema = i < prefix.length ? prefix[i] : rest;
return schema === void 0 ? item2 : this.convert(schema, base, item2);
});
}
if (Array.isArray(value2)) {
return node.items === void 0 ? value2 : mapItems(value2, (item2) => this.convert(node.items, base, item2));
}
const item = node.items;
return [isSchemaObject(item) ? this.reenter(item, base, value2, false) : value2];
}
convertObject(node, base, value2) {
if (!isPlainObject(value2))
return value2;
const properties = isSchemaObject(node.properties) ? node.properties : {};
const patterns = isSchemaObject(node.patternProperties) ? Object.entries(node.patternProperties).map(([pattern, schema]) => [sharedRegex(pattern), schema]) : [];
const additional = isSchemaObject(node.additionalProperties) ? node.additionalProperties : void 0;
let out;
for (const key of Object.keys(value2)) {
if (value2[key] === void 0)
continue;
let next = value2[key];
let matched = Object.hasOwn(properties, key);
if (matched)
next = this.convert(properties[key], base, next);
for (const [pattern, schema] of patterns) {
if (!pattern.test(key))
continue;
matched = true;
next = this.convert(schema, base, next);
}
if (!matched && additional !== void 0)
next = this.convert(additional, base, next);
if (next !== value2[key]) {
out ??= { ...value2 };
out[key] = next;
}
}
return out ?? value2;
}
// ---------------------------------------------------------------------------------------------------------------
// Pass 3: primitive coercion by type
// ---------------------------------------------------------------------------------------------------------------
coerceTypes(value2, schema, base) {
if (!isSchemaObject(schema))
return value2;
const b = this.baseOf(schema, base);
let next = value2;
if (Array.isArray(schema.allOf))
for (const member of schema.allOf)
next = this.coerceTypes(next, member, b);
if (Array.isArray(schema.anyOf))
next = this.coerceUnion(next, schema.anyOf, b);
if (Array.isArray(schema.oneOf))
next = this.coerceUnion(next, schema.oneOf, b);
const types = typesOf(schema);
const matchesUnionMember = types.length > 1 && types.some((type) => matchesType(next, type));
if (types.length > 0 && !matchesUnionMember) {
for (const type of types) {
const candidate = coercePrimitive(next, type);
if (candidate !== next) {
next = candidate;
break;
}
}
}
if (types.includes("object") && isPlainObject(next))
next = this.coerceProperties(next, schema, b);
if (types.includes("array") && Array.isArray(next))
next = this.coerceItems(next, schema, b);
return next;
}
coerceUnion(value2, branches, base) {
for (const branch of branches)
if (this.passes(branch, base, value2) === true)
return value2;
for (const branch of branches) {
const coerced = this.coerceTypes(value2, branch, base);
if (this.passes(branch, base, coerced) === true)
return coerced;
}
return value2;
}
coerceProperties(value2, schema, base) {
const properties = isSchemaObject(schema.properties) ? schema.properties : {};
const patterns = isSchemaObject(schema.patternProperties) ? Object.entries(schema.patternProperties).map(([pattern, item]) => [sharedRegex(pattern), item]) : [];
const additional = isSchemaObject(schema.additionalProperties) ? schema.additionalProperties : void 0;
let out;
const set = (key, next) => {
if (next === (out ?? value2)[key])
return;
out ??= { ...value2 };
out[key] = next;
};
for (const [key, property] of Object.entries(properties)) {
if (key in value2)
set(key, this.coerceTypes(value2[key], property, base));
}
for (const key of Object.keys(value2)) {
let matched = Object.hasOwn(properties, key);
for (const [pattern, item] of patterns) {
if (!pattern.test(key))
continue;
matched = true;
set(key, this.coerceTypes((out ?? value2)[key], item, base));
}
if (!matched && additional !== void 0)
set(key, this.coerceTypes(value2[key], additional, base));
}
return out ?? value2;
}
coerceItems(value2, schema, base) {
return mapItems(value2, (item, i) => {
const itemSchema = itemSchemaAt(schema, i);
return isSchemaObject(itemSchema) ? this.coerceTypes(item, itemSchema, base) : item;
});
}
};
function itemSchemaAt(schema, index) {
if (Array.isArray(schema.items))
return schema.items[index];
if (Array.isArray(schema.prefixItems) && index < schema.prefixItems.length)
return schema.prefixItems[index];
return schema.items;
}
function mapItems(items, map2) {
let out;
for (let i = 0; i < items.length; i++) {
const next = map2(items[i], i);
if (next === items[i])
continue;
out ??= items.slice();
out[i] = next;
}
return out ?? items;
}
function orValue(result, value2) {
return result === void 0 ? value2 : result.value;
}
function convertLiteral(literal, value2) {
if (literal === value2)
return value2;
const result = typeof literal === "string" ? tryString(value2) : typeof literal === "number" ? tryNumber(value2) : typeof literal === "boolean" ? tryBoolean(value2) : void 0;
return result !== void 0 && result.value === literal ? result.value : value2;
}
function tryString(value2) {
if (typeof value2 === "bigint" || typeof value2 === "boolean" || isFiniteNumber(value2))
return { value: String(value2) };
if (value2 === null)
return { value: "null" };
if (typeof value2 === "string")
return { value: value2 };
if (value2 === void 0)
return { value: "" };
return void 0;
}
var MAX_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
var MIN_BIGINT = BigInt(Number.MIN_SAFE_INTEGER);
function tryNumber(value2) {
if (typeof value2 === "bigint")
return value2 <= MAX_BIGINT && value2 >= MIN_BIGINT ? { value: Number(value2) } : void 0;
if (typeof value2 === "boolean")
return { value: value2 ? 1 : 0 };
if (isFiniteNumber(value2))
return { value: value2 };
if (value2 === null || value2 === void 0)
return { value: 0 };
if (typeof value2 !== "string")
return void 0;
const coerced = +value2;
if (Number.isFinite(coerced))
return { value: coerced };
const lowercase = value2.toLowerCase();
if (lowercase === "false")
return { value: 0 };
if (lowercase === "true")
return { value: 1 };
const big = bigIntOfString(value2);
return big !== void 0 && big <= MAX_BIGINT && big >= MIN_BIGINT ? { value: Number(big) } : void 0;
}
function bigIntOfString(value2) {
if (/^-?(0|[1-9]\d*)n$/.test(value2))
return BigInt(value2.slice(0, -1));
if (/^-?(0|[1-9]\d*)\.\d+$/.test(value2))
return BigInt(value2.split(".")[0]);
if (/^-?(0|[1-9]\d*)$/.test(value2))
return BigInt(value2);
return void 0;
}
function tryBoolean(value2) {
if (typeof value2 === "bigint")
return value2 === 0n ? { value: false } : value2 === 1n ? { value: true } : void 0;
if (typeof value2 === "boolean")
return { value: value2 };
if (isFiniteNumber(value2))
return value2 === 0 ? { value: false } : value2 === 1 ? { value: true } : void 0;
if (value2 === null || value2 === void 0)
return { value: false };
if (typeof value2 !== "string")
return void 0;
const lowercase = value2.toLowerCase();
if (lowercase === "false" || value2 === "0")
return { value: false };
if (lowercase === "true" || value2 === "1")
return { value: true };
return void 0;
}
function tryNull(value2) {
if (typeof value2 === "bigint")
return value2 === 0n ? { value: null } : void 0;
if (typeof value2 === "boolean")
return value2 === false ? { value: null } : void 0;
if (isFiniteNumber(value2))
return value2 === 0 ? { value: null } : void 0;
if (value2 === null || value2 === void 0)
return { value: null };
if (typeof value2 !== "string")
return void 0;
const lowercase = value2.toLowerCase();
return lowercase === "undefined" || lowercase === "null" || value2 === "" || value2 === "0" ? { value: null } : void 0;
}
function isFiniteNumber(value2) {
return typeof value2 === "number" && Number.isFinite(value2);
}
function typesOf(schema) {
if (typeof schema.type === "string")
return [schema.type];
if (Array.isArray(schema.type))
return schema.type.filter((type) => typeof type === "string");
return [];
}
function matchesType(value2, type) {
switch (type) {
case "number":
return typeof value2 === "number";
case "integer":
return typeof value2 === "number" && Number.isInteger(value2);
case "boolean":
return typeof value2 === "boolean";
case "string":
return typeof value2 === "string";
case "null":
return value2 === null;
case "array":
return Array.isArray(value2);
case "object":
return isPlainObject(value2);
default:
return false;
}
}
function coercePrimitive(value2, type) {
switch (type) {
case "number":
case "integer": {
if (value2 === null)
return 0;
if (typeof value2 === "string" && value2.trim() !== "") {
const parsed = Number(value2);
if (type === "number" ? Number.isFinite(parsed) : Number.isInteger(parsed))
return parsed;
}
if (typeof value2 === "boolean")
return value2 ? 1 : 0;
return value2;
}
case "boolean":
if (value2 === null)
return false;
if (value2 === "true" || value2 === 1)
return true;
if (value2 === "false" || value2 === 0)
return false;
return value2;
case "string":
if (value2 === null)
return "";
if (typeof value2 === "number" || typeof value2 === "boolean")
return String(value2);
return value2;
case "null":
return value2 === "" || value2 === 0 || value2 === false ? null : value2;
default:
return value2;
}
}
function isPlainObject(value2) {
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
}
// node_modules/@earendil-works/pi-schema/dist/checks.js
var ALWAYS = () => true;
var NEVER = () => false;
var IS_STRING = (v) => typeof v === "string";
var IS_NUMBER = (v) => typeof v === "number";
var IS_INTEGER = (v) => Number.isInteger(v);
var IS_BOOLEAN = (v) => typeof v === "boolean";
var IS_NULL = (v) => v === null;
var IS_ARRAY = (v) => Array.isArray(v);
var IS_BYTES = (v) => v instanceof Uint8Array;
var IS_OBJECT = (v) => isObject(v);
function isObject(v) {
return typeof v === "object" && v !== null && !Array.isArray(v) && !(v instanceof Uint8Array);
}
var TYPE_CHECKS = /* @__PURE__ */ new Map([
["string", IS_STRING],
["number", IS_NUMBER],
["integer", IS_INTEGER],
["boolean", IS_BOOLEAN],
["null", IS_NULL],
["array", IS_ARRAY],
["object", IS_OBJECT],
["bytes", IS_BYTES]
]);
var LEAF_CODES = /* @__PURE__ */ new Map([
[IS_STRING, 1],
[IS_NUMBER, 2],
[IS_INTEGER, 3],
[IS_BOOLEAN, 4],
[IS_NULL, 5],
[ALWAYS, 6]
]);
function leafOk(code, x) {
switch (code) {
case 1:
return typeof x === "string";
case 2:
return typeof x === "number";
case 3:
return Number.isInteger(x);
case 4:
return typeof x === "boolean";
case 5:
return x === null;
default:
return true;
}
}
var GUARD_NONE = 0;
var GUARD_STRICT = 1;
var GUARD_LOOSE = 2;
var CODE = 7;
var REQUIRED = 8;
var INHERITED = 16;
function and(parts) {
switch (parts.length) {
case 0:
return ALWAYS;
case 1:
return parts[0];
case 2: {
const [a, b] = parts;
return (v) => a(v) && b(v);
}
case 3: {
const [a, b, c] = parts;
return (v) => a(v) && b(v) && c(v);
}
default:
return (v) => {
for (let i = 0; i < parts.length; i++)
if (!parts[i](v))
return false;
return true;
};
}
}
function indirect(slot) {
return (v) => slot.check(v);
}
function scopedCheck(scope, uri, check) {
return (v) => {
scope.push(uri);
const ok2 = check(v);
scope.pop();
return ok2;
};
}
function typeCheck(types) {
const checks = types.map((t) => (typeof t === "string" ? TYPE_CHECKS.get(t) : void 0) ?? NEVER);
if (checks.length === 1)
return checks[0];
return (v) => {
for (let i = 0; i < checks.length; i++)
if (checks[i](v))
return true;
return false;
};
}
function bytesCheck(min, max) {
return (v) => v instanceof Uint8Array && v.length >= min && v.length <= max;
}
function codePoints(s) {
let n = 0;
for (let i = 0; i < s.length; i++, n++) {
const c = s.charCodeAt(i);
if (c >= 55296 && c <= 56319 && i + 1 < s.length) {
const next = s.charCodeAt(i + 1);
if (next >= 56320 && next <= 57343)
i++;
}
}
return n;
}
function lengthOk(s, min, max) {
const units = s.length;
if (units < min)
return false;
if (units < 2 * min && codePoints(s) < min)
return false;
return units <= max || codePoints(s) <= max;
}
function stringCheck(strict, min, max, re, format) {
if (re !== void 0 && min === 0 && max === Number.POSITIVE_INFINITY && format === void 0) {
return strict ? (v) => typeof v === "string" && re.test(v) : (v) => typeof v !== "string" || re.test(v);
}
if (re === void 0 && format === void 0) {
return strict ? (v) => typeof v === "string" && lengthOk(v, min, max) : (v) => typeof v !== "string" || lengthOk(v, min, max);
}
return (v) => {
if (typeof v !== "string")
return !strict;
return lengthOk(v, min, max) && (re === void 0 || re.test(v)) && (format === void 0 || format(v));
};
}
function numberCheck(mode, min, max, xmin, xmax, multipleOf) {
return (v) => {
if (typeof v !== "number")
return mode === 0;
if (mode === 2 && !Number.isInteger(v))
return false;
return v >= min && v <= max && v > xmin && v < xmax && (multipleOf === void 0 || isMultiple(v, multipleOf));
};
}
function isMultiple(v, d) {
const q = v / d;
if (Number.isInteger(q))
return true;
if (!Number.isFinite(q))
return v % d === 0;
const [vc, ve] = decimal(v);
const [dc, de] = decimal(d);
return ve >= de ? vc * 10n ** BigInt(ve - de) % dc === 0n : vc % (dc * 10n ** BigInt(de - ve)) === 0n;
}
function decimal(x) {
const [mantissa, exponent = "0"] = Math.abs(x).toString().split("e");
const point = mantissa.indexOf(".");
const fraction = point < 0 ? 0 : mantissa.length - point - 1;
return [BigInt(mantissa.replace(".", "")), Number(exponent) - fraction];
}
function guardObject(inner, strict) {
return strict ? (v) => isObject(v) && inner(v) : (v) => !isObject(v) || inner(v);
}
function guardArray(inner, strict) {
return strict ? (v) => Array.isArray(v) && inner(v) : (v) => !Array.isArray(v) || inner(v);
}
function declaredObject(entries2, requiredCount, closed, guard) {
const n = entries2.length;
return (v) => {
if (guard !== GUARD_NONE && !isObject(v))
return guard === GUARD_LOOSE;
const o = v;
let required = 0;
for (const k in o) {
let i = 0;
while (i < n && entries2[i] !== k)
i += 3;
if (i === n) {
if (closed)
return false;
continue;
}
const x = o[k];
if (x === void 0)
continue;
const f = entries2[i + 2];
const c = f & CODE;
if (c !== 0 ? !leafOk(c, x) : !entries2[i + 1](x))
return false;
if (f & REQUIRED)
required++;
}
return required === requiredCount;
};
}
function openObject(entries2, keys, extraRequired, patterns, additional, guard) {
const known = patterns.length > 0 || additional !== void 0 ? new Set(keys) : void 0;
return (v) => {
if (guard !== GUARD_NONE && !isObject(v))
return guard === GUARD_LOOSE;
const o = v;
for (let i = 0; i < entries2.length; i += 3) {
const k = entries2[i];
const x = o[k];
const f = entries2[i + 2];
if (x === void 0 || f & INHERITED && !Object.hasOwn(o, k)) {
if (f & REQUIRED)
return false;
continue;
}
const c = f & CODE;
if (c !== 0 ? !leafOk(c, x) : !entries2[i + 1](x))
return false;
}
for (let i = 0; i < extraRequired.length; i++)
if (!Object.hasOwn(o, extraRequired[i]))
return false;
if (known === void 0)
return true;
for (const k of Object.keys(o)) {
let matched = known.has(k);
for (let i = 0; i < patterns.length; i++) {
if (patterns[i][0].test(k)) {
matched = true;
if (!patterns[i][1](o[k]))
return false;
}
}
if (!matched && additional !== void 0 && !additional(o[k]))
return false;
}
return true;
};
}
function propertyNamesCheck(check) {
return (v) => {
for (const k in v)
if (!check(k))
return false;
return true;
};
}
function propertyCountCheck(min, max) {
return (v) => {
let n = 0;
for (const _ in v)
n++;
return n >= min && n <= max;
};
}
function dependentRequiredCheck(entries2) {
return (v) => {
const o = v;
for (const [k, list] of entries2)
if (Object.hasOwn(o, k)) {
for (const r of list)
if (!Object.hasOwn(o, r))
return false;
}
return true;
};
}
function dependentSchemasCheck(entries2) {
return (v) => {
for (const [k, check] of entries2)
if (Object.hasOwn(v, k) && !check(v))
return false;
return true;
};
}
function listCheck(guard, min, max, prefix, rest) {
const n = prefix.length;
const code = rest === void 0 ? 0 : LEAF_CODES.get(rest) ?? 0;
return (v) => {
if (!Array.isArray(v))
return guard === GUARD_LOOSE;
const length = v.length;
if (length < min || length > max)
return false;
const m = length < n ? length : n;
for (let i = 0; i < m; i++)
if (!prefix[i](v[i]))
return false;
if (rest === void 0)
return true;
if (code !== 0) {
for (let i = n; i < length; i++)
if (!leafOk(code, v[i]))
return false;
return true;
}
for (let i = n; i < length; i++)
if (!rest(v[i]))
return false;
return true;
};
}
function itemsCheck(prefix, rest) {
return listCheck(GUARD_NONE, 0, Number.POSITIVE_INFINITY, prefix, rest);
}
function lengthCheck(min, max) {
return (v) => v.length >= min && v.length <= max;
}
function containsCheck(check, min, max) {
return (v) => {
const list = v;
let n = 0;
for (let i = 0; i < list.length; i++)
if (check(list[i]) && ++n > max)
return false;
return n >= min;
};
}
function uniqueCheck(v) {
const list = v;
for (let i = 1; i < list.length; i++)
for (let j = 0; j < i; j++)
if (deepEqual(list[i], list[j]))
return false;
return true;
}
function enumCheck(values) {
const primitives = values.filter((x) => typeof x !== "object" || x === null);
if (primitives.length === values.length && primitives.length <= 8) {
return (v) => {
for (let i = 0; i < primitives.length; i++)
if (primitives[i] === v)
return true;
return false;
};
}
const set = new Set(primitives);
const objects = values.filter((x) => typeof x === "object" && x !== null);
return (v) => set.has(v) || typeof v === "object" && objects.some((o) => deepEqual(v, o));
}
function constCheck(value2) {
if (typeof value2 !== "object" || value2 === null)
return (v) => v === value2;
return (v) => deepEqual(v, value2);
}
function anyCheck(checks) {
return (v) => {
for (let i = 0; i < checks.length; i++)
if (checks[i](v))
return true;
return false;
};
}
function oneCheck(checks) {
return (v) => {
let n = 0;
for (let i = 0; i < checks.length; i++)
if (checks[i](v) && ++n > 1)
return false;
return n === 1;
};
}
function notCheck(check) {
return (v) => !check(v);
}
function ifCheck(cond, then, otherwise) {
return (v) => cond(v) ? then(v) : otherwise(v);
}
function taggedCheck(key, tags, checks) {
return (v) => {
if (!isObject(v))
return false;
const tag = v[key];
for (let i = 0; i < tags.length; i++)
if (tags[i] === tag)
return checks[i](v);
return false;
};
}
function deepEqual(a, b) {
if (a === b)
return true;
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null)
return false;
const array = Array.isArray(a);
if (array !== Array.isArray(b))
return false;
if (array) {
const x2 = a;
const y2 = b;
if (x2.length !== y2.length)
return false;
for (let i = 0; i < x2.length; i++)
if (!deepEqual(x2[i], y2[i]))
return false;
return true;
}
const x = a;
const y = b;
const keys = Object.keys(x);
if (keys.length !== Object.keys(y).length)
return false;
for (const k of keys)
if (!Object.hasOwn(y, k) || !deepEqual(x[k], y[k]))
return false;
return true;
}
// node_modules/@earendil-works/pi-schema/dist/annotations.js
function newAnnotations() {
return { props: null, allProps: false, items: 0, allItems: false, indexes: null };
}
function merge(a, b) {
if (b.props !== null)
for (const k of b.props)
addProp(a, k);
a.allProps ||= b.allProps;
if (b.items > a.items)
a.items = b.items;
a.allItems ||= b.allItems;
if (b.indexes !== null)
for (const i of b.indexes)
addIndex(a, i);
}
function addProp(a, key) {
if (a.props === null)
a.props = /* @__PURE__ */ new Set();
a.props.add(key);
}
function addIndex(a, index) {
if (a.indexes === null)
a.indexes = /* @__PURE__ */ new Set();
a.indexes.add(index);
}
var ANNOTATING_TRUE = () => true;
var ANNOTATING_FALSE = () => false;
function indirectAnnotating(slot) {
return (v, a) => slot.check(v, a);
}
function ignoreAnnotations(check) {
return (v) => check(v);
}
function withFreshAnnotations(check) {
return (v) => check(v, newAnnotations());
}
function scopedAnnotating(scope, uri, check) {
return (v, a) => {
scope.push(uri);
const ok2 = check(v, a);
scope.pop();
return ok2;
};
}
function isolateAnnotations(check) {
return (v, a) => {
const b = newAnnotations();
if (!check(v, b))
return false;
merge(a, b);
return true;
};
}
function annotateAll(plain, parts) {
return (v, a) => {
if (!plain(v))
return false;
for (let i = 0; i < parts.length; i++)
if (!parts[i](v, a))
return false;
return true;
};
}
function annotateObject(props, patterns, additional) {
const declared = new Set(props.map(([k]) => k));
return (v, a) => {
if (!isObject(v))
return true;
const seen = [];
for (const [k, check] of props) {
if (!Object.hasOwn(v, k))
continue;
if (!check(v[k]))
return false;
seen.push(k);
}
for (const k of Object.keys(v)) {
let matched = declared.has(k);
for (const [re, check] of patterns) {
if (re.test(k)) {
if (!check(v[k]))
return false;
matched = true;
seen.push(k);
}
}
if (!matched && additional !== void 0) {
if (!additional(v[k]))
return false;
seen.push(k);
}
}
for (const k of seen)
addProp(a, k);
return true;
};
}
function annotateArray(prefix, rest, contains, minContains, maxContains) {
return (v, a) => {
if (!Array.isArray(v))
return true;
const m = Math.min(v.length, prefix.length);
for (let i = 0; i < m; i++)
if (!prefix[i](v[i]))
return false;
if (rest !== void 0) {
for (let i = prefix.length; i < v.length; i++)
if (!rest(v[i]))
return false;
a.allItems = true;
}
if (m > a.items)
a.items = m;
if (contains !== void 0) {
let n = 0;
for (let i = 0; i < v.length; i++) {
if (contains(v[i])) {
n++;
addIndex(a, i);
}
}
if (n < minContains || n > maxContains)
return false;
}
return true;
};
}
function annotateAny(branches, exactlyOne) {
return (v, a) => {
let n = 0;
for (const branch of branches) {
const b = newAnnotations();
if (branch(v, b)) {
n++;
merge(a, b);
}
}
return exactlyOne ? n === 1 : n > 0;
};
}
function annotateIf(cond, then, otherwise) {
return (v, a) => {
const b = newAnnotations();
if (cond(v, b)) {
merge(a, b);
return then === void 0 || then(v, a);
}
return otherwise === void 0 || otherwise(v, a);
};
}
function annotateDependent(key, check) {
return (v, a) => !isObject(v) || !Object.hasOwn(v, key) || check(v, a);
}
function unevaluatedProperties(check) {
return (v, a) => {
if (!isObject(v) || a.allProps)
return true;
for (const k of Object.keys(v))
if (!(a.props?.has(k) ?? false) && !check(v[k]))
return false;
a.allProps = true;
return true;
};
}
function unevaluatedItems(check) {
return (v, a) => {
if (!Array.isArray(v) || a.allItems)
return true;
for (let i = a.items; i < v.length; i++)
if (!(a.indexes?.has(i) ?? false) && !check(v[i]))
return false;
a.allItems = true;
return true;
};
}
// node_modules/@earendil-works/pi-schema/dist/compiler.js
var RESTART = /* @__PURE__ */ Symbol("restart");
var Compiler = class {
r;
draft;
formats;
/** Whether checks track the dynamic scope (the schema has a bookended `$dynamicRef`). */
dynamic;
schema;
scope;
cache = /* @__PURE__ */ new Map();
annotatingCache = /* @__PURE__ */ new Map();
constructor(schema, options, dynamic) {
this.schema = schema;
this.r = new Resolver(schema, options);
this.draft = this.r.draft;
this.formats = options.formats;
this.dynamic = dynamic;
this.scope = [];
}
/** The check of the root schema. */
root() {
return this.check(this.schema, this.r.rootBase);
}
/** The check of a schema (cached by schema object; a recursive reference goes through an indirection). */
check(node, base) {
if (node === true)
return ALWAYS;
if (node === false)
return NEVER;
if (!isSchemaObject(node))
throw new Error(`A schema must be an object or a boolean, got ${JSON.stringify(node)}`);
const cached = this.cache.get(node);
if (cached !== void 0)
return cached;
const bare = this.bareType(node);
if (bare !== void 0)
return bare;
const slot = { check: void 0 };
this.cache.set(node, indirect(slot));
const check = this.build(node, this.r.baseFor(node, base));
slot.check = check;
this.cache.set(node, check);
return check;
}
build(node, base) {
if (this.draft === "7" && typeof node.$ref === "string")
return this.ref(node.$ref, base);
if (this.draft !== "7" && (node.unevaluatedProperties !== void 0 || node.unevaluatedItems !== void 0)) {
return withFreshAnnotations(this.annotating(node, base));
}
const check = this.plain(node, base);
return this.dynamic && this.r.isResource(node, base) ? scopedCheck(this.scope, base, check) : check;
}
/**
* The module-level check of a schema that is only a `type` (with annotations), `ALWAYS` for one with no assertion
* at all; undefined for every other schema. These are the most common subschemas and cost nothing to share.
*/
bareType(node) {
let type;
for (const k in node) {
if (k === "type")
type = node.type;
else if (!NEUTRAL_KEYWORDS.has(k))
return void 0;
}
if (type === void 0)
return ALWAYS;
return typeof type === "string" ? TYPE_CHECKS.get(type) : void 0;
}
/** Every keyword of `node`, not tracking annotations. */
plain(node, base) {
const parts = [];
const types = node.type === void 0 ? void 0 : Array.isArray(node.type) ? node.type : [node.type];
const single = types?.length === 1 ? types[0] : void 0;
let typeInGroup = false;
if (single === "bytes") {
parts.push(bytesCheck(number(node.minLength) ?? 0, number(node.maxLength) ?? Number.POSITIVE_INFINITY));
typeInGroup = true;
} else {
const string = this.stringGroup(node, single === "string");
if (string !== void 0)
parts.push(string);
const numeric = single === "number" || single === "integer";
const number2 = this.numberGroup(node, single === "number" ? 1 : single === "integer" ? 2 : 0);
if (number2 !== void 0)
parts.push(number2);
const object = this.objectGroup(node, base, single === "object");
if (object !== void 0)
parts.push(object);
const array = this.arrayGroup(node, base, single === "array");
if (array !== void 0)
parts.push(array);
typeInGroup = single === "string" && string !== void 0 || numeric && number2 !== void 0 || single === "object" && object !== void 0 || single === "array" && array !== void 0;
}
if (types !== void 0 && !typeInGroup)
parts.unshift(typeCheck(types));
this.inPlace(node, base, parts);
return and(parts);
}
// The keywords that apply to the value itself, whatever its type.
inPlace(node, base, parts) {
if (Array.isArray(node.enum))
parts.push(enumCheck(node.enum));
if (Object.hasOwn(node, "const"))
parts.push(constCheck(node.const));
if (Array.isArray(node.allOf))
parts.push(and(node.allOf.map((s) => this.check(s, base))));
if (Array.isArray(node.anyOf))
parts.push(this.union(node.anyOf, base, false));
if (Array.isArray(node.oneOf))
parts.push(this.union(node.oneOf, base, true));
if (node.not !== void 0)
parts.push(notCheck(this.check(node.not, base)));
if (node.if !== void 0 && (node.then !== void 0 || node.else !== void 0)) {
const then = node.then === void 0 ? ALWAYS : this.check(node.then, base);
const otherwise = node.else === void 0 ? ALWAYS : this.check(node.else, base);
parts.push(ifCheck(this.check(node.if, base), then, otherwise));
}
if (typeof node.$ref === "string")
parts.push(this.ref(node.$ref, base));
if (this.draft !== "7" && typeof node.$dynamicRef === "string") {
parts.push(this.dynamicRef(node.$dynamicRef, base));
}
}
union(branches, base, exactlyOne) {
const checks = () => branches.map((s) => this.check(s, base));
return constUnion(branches, exactlyOne) ?? this.tagged(branches, base) ?? (exactlyOne ? oneCheck(checks()) : anyCheck(checks()));
}
ref(ref, base) {
const target = this.r.resolve(ref, base);
const check = this.check(target.node, target.base);
return this.dynamic && target.base !== base ? scopedCheck(this.scope, target.base, check) : check;
}
dynamicRef(ref, base) {
const resolved = this.bookended(ref, base);
if (resolved === void 0)
return this.ref(ref, base);
const { initial, name } = resolved;
const fallback = this.check(initial.node, initial.base);
const lookup = this.dynamicLookup(name, (node, b) => this.check(node, b));
const scope = this.scope;
return (v) => {
for (let i = 0; i < scope.length; i++) {
const check = lookup(scope[i]);
if (check !== null)
return check(v);
}
return fallback(v);
};
}
/** The initial target and anchor name of a `$dynamicRef` that resolves dynamically, or undefined for a plain ref. */
bookended(ref, base) {
const initial = this.r.resolve(ref, base);
const uri = resolveUri(ref, base);
const name = uri.slice(documentOf(uri).length + 1);
const anchored = isSchemaObject(initial.node) && initial.node.$dynamicAnchor === name;
if (name === "" || name.startsWith("/") || !anchored)
return void 0;
if (!this.dynamic)
throw RESTART;
return { initial, name };
}
// Resolved at run time against the dynamic scope, so a schema with a bookended $dynamicRef keeps its compiler.
dynamicLookup(name, compile2) {
const found = /* @__PURE__ */ new Map();
return (uri) => {
const key = `${uri}#${name}`;
let check = found.get(key);
if (check === void 0) {
const target = this.r.dynamicAnchors.get(key);
check = target === void 0 ? null : compile2(target, this.r.baseOf.get(target) ?? uri);
found.set(key, check);
}
return check;
};
}
/** anyOf/oneOf whose branches are all objects with a distinct required const on one key: the tag picks the branch. */
tagged(branches, base) {
if (branches.length < 2)
return void 0;
const resolved = [];
for (const branch of branches) {
if (!isSchemaObject(branch))
return void 0;
const ref = typeof branch.$ref === "string" && Object.keys(branch).length === 1 ? branch.$ref : void 0;
const node = ref === void 0 ? branch : this.r.resolve(ref, this.r.baseFor(branch, base)).node;
if (!isSchemaObject(node))
return void 0;
resolved.push(node);
}
const first = resolved[0].properties;
if (!isSchemaObject(first))
return void 0;
for (const key of Object.keys(first)) {
const tags = resolved.map((s) => tagOf(s, key));
if (tags.some((t) => t === void 0) || new Set(tags).size !== tags.length)
continue;
return taggedCheck(key, tags, branches.map((s) => this.check(s, base)));
}
return void 0;
}
stringGroup(node, strict) {
const min = number(node.minLength) ?? 0;
const max = number(node.maxLength) ?? Number.POSITIVE_INFINITY;
const re = typeof node.pattern === "string" ? sharedRegex(node.pattern) : void 0;
const format = this.formats !== void 0 && typeof node.format === "string" && Object.hasOwn(this.formats, node.format) ? this.formats[node.format] : void 0;
if (min === 0 && max === Number.POSITIVE_INFINITY && re === void 0 && format === void 0)
return void 0;
return stringCheck(strict, min, max, re, format);
}
numberGroup(node, mode) {
const min = number(node.minimum);
const max = number(node.maximum);
const xmin = number(node.exclusiveMinimum);
const xmax = number(node.exclusiveMaximum);
const multipleOf = number(node.multipleOf);
if ([min, max, xmin, xmax, multipleOf].every((x) => x === void 0))
return void 0;
const inf = Number.POSITIVE_INFINITY;
return numberCheck(mode, min ?? -inf, max ?? inf, xmin ?? -inf, xmax ?? inf, multipleOf);
}
objectGroup(node, base, strict) {
const onlyCore = OBJECT_EXTRAS.every((k) => node[k] === void 0);
const core = this.objectCore(node, base, onlyCore ? strict ? GUARD_STRICT : GUARD_LOOSE : GUARD_NONE);
if (core !== void 0 && onlyCore)
return core;
const parts = core === void 0 ? [] : [core];
if (node.propertyNames !== void 0)
parts.push(propertyNamesCheck(this.check(node.propertyNames, base)));
const minProperties = number(node.minProperties);
const maxProperties = number(node.maxProperties);
if (minProperties !== void 0 || maxProperties !== void 0) {
parts.push(propertyCountCheck(minProperties ?? 0, maxProperties ?? Number.POSITIVE_INFINITY));
}
const dependentRequired = [];
const dependentSchemas = [];
if (this.draft !== "7") {
for (const [k, list] of entries(node.dependentRequired))
if (Array.isArray(list))
dependentRequired.push([k, list]);
for (const [k, s] of entries(node.dependentSchemas))
dependentSchemas.push([k, this.check(s, base)]);
}
for (const [k, d] of entries(node.dependencies)) {
if (Array.isArray(d))
dependentRequired.push([k, d]);
else
dependentSchemas.push([k, this.check(d, base)]);
}
if (dependentRequired.length > 0)
parts.push(dependentRequiredCheck(dependentRequired));
if (dependentSchemas.length > 0)
parts.push(dependentSchemasCheck(dependentSchemas));
if (parts.length === 0)
return strict ? IS_OBJECT : void 0;
return guardObject(and(parts), strict);
}
objectCore(node, base, guard) {
const properties = isSchemaObject(node.properties) ? node.properties : {};
const required = Array.isArray(node.required) ? node.required.filter((k) => typeof k === "string") : [];
const patterns = isSchemaObject(node.patternProperties) ? node.patternProperties : {};
const additional = node.additionalProperties;
const keys = Object.keys(properties);
const patternKeys = Object.keys(patterns);
if (keys.length + required.length + patternKeys.length === 0 && (additional === void 0 || additional === true)) {
return void 0;
}
const entries2 = [];
for (const k of keys) {
const check = this.check(properties[k], base);
const flags = (LEAF_CODES.get(check) ?? 0) | (required.includes(k) ? REQUIRED : 0) | (k in Object.prototype ? INHERITED : 0);
entries2.push(k, check, flags);
}
const extraRequired = required.filter((k) => !Object.hasOwn(properties, k));
const pats = patternKeys.map((p) => [sharedRegex(p), this.check(patterns[p], base)]);
const extra = additional === void 0 || additional === true ? void 0 : this.check(additional, base);
if (pats.length === 0 && extraRequired.length === 0 && (extra === void 0 || additional === false)) {
const requiredCount = keys.filter((k) => required.includes(k)).length;
return declaredObject(entries2, requiredCount, additional === false, guard);
}
return openObject(entries2, keys, extraRequired, pats, extra, guard);
}
arrayGroup(node, base, strict) {
let prefix = [];
let rest;
if (Array.isArray(node.items)) {
prefix = node.items;
rest = node.additionalItems;
} else {
if (this.draft !== "7" && Array.isArray(node.prefixItems))
prefix = node.prefixItems;
rest = node.items;
}
const prefixChecks = prefix.map((s) => this.check(s, base));
const restCheck = rest === void 0 || rest === true ? void 0 : this.check(rest, base);
const minItems = number(node.minItems);
const maxItems = number(node.maxItems);
if (node.contains === void 0 && node.uniqueItems !== true && (prefixChecks.length > 0 || restCheck !== void 0)) {
const guard = strict ? GUARD_STRICT : GUARD_LOOSE;
return listCheck(guard, minItems ?? 0, maxItems ?? Number.POSITIVE_INFINITY, prefixChecks, restCheck);
}
const parts = [];
if (prefixChecks.length > 0 || restCheck !== void 0)
parts.push(itemsCheck(prefixChecks, restCheck));
if (minItems !== void 0 || maxItems !== void 0) {
parts.push(lengthCheck(minItems ?? 0, maxItems ?? Number.POSITIVE_INFINITY));
}
if (node.contains !== void 0) {
const min = this.draft === "7" ? 1 : number(node.minContains) ?? 1;
const max = this.draft === "7" ? Number.POSITIVE_INFINITY : number(node.maxContains) ?? Number.POSITIVE_INFINITY;
parts.push(containsCheck(this.check(node.contains, base), min, max));
}
if (node.uniqueItems === true)
parts.push(uniqueCheck);
if (parts.length === 0)
return strict ? IS_ARRAY : void 0;
return guardArray(and(parts), strict);
}
/** The annotating check of a schema evaluated in place (only below `unevaluatedProperties`/`unevaluatedItems`). */
annotating(node, base) {
if (node === true)
return ANNOTATING_TRUE;
if (node === false)
return ANNOTATING_FALSE;
if (!isSchemaObject(node))
throw new Error(`A schema must be an object or a boolean, got ${JSON.stringify(node)}`);
const cached = this.annotatingCache.get(node);
if (cached !== void 0)
return cached;
const slot = { check: void 0 };
this.annotatingCache.set(node, indirectAnnotating(slot));
const check = this.buildAnnotating(node, this.r.baseFor(node, base));
slot.check = check;
this.annotatingCache.set(node, check);
return check;
}
buildAnnotating(node, base) {
const rest = {};
let annotates = false;
for (const k of Object.keys(node)) {
if (ANNOTATING.has(k))
annotates = true;
else
rest[k] = node[k];
}
const plain = this.plain(rest, base);
const parts = [];
if (annotates)
this.annotatingParts(node, base, parts);
const all = parts.length === 0 ? ignoreAnnotations(plain) : annotateAll(plain, parts);
const own = node.unevaluatedProperties !== void 0 || node.unevaluatedItems !== void 0 ? isolateAnnotations(all) : all;
return this.dynamic && this.r.isResource(node, base) ? scopedAnnotating(this.scope, base, own) : own;
}
annotatingParts(node, base, parts) {
if (node.properties !== void 0 || node.patternProperties !== void 0 || node.additionalProperties !== void 0) {
const props = entries(node.properties).map(([k, s]) => [k, this.check(s, base)]);
const pats = entries(node.patternProperties).map(([p, s]) => [sharedRegex(p), this.check(s, base)]);
const extra = node.additionalProperties === void 0 ? void 0 : this.check(node.additionalProperties, base);
parts.push(annotateObject(props, pats, extra));
}
if (node.prefixItems !== void 0 || node.items !== void 0 || node.contains !== void 0) {
const prefix = Array.isArray(node.prefixItems) ? node.prefixItems : Array.isArray(node.items) ? node.items : [];
const rest = Array.isArray(node.items) ? node.additionalItems : node.items;
parts.push(annotateArray(prefix.map((s) => this.check(s, base)), rest === void 0 ? void 0 : this.check(rest, base), node.contains === void 0 ? void 0 : this.check(node.contains, base), number(node.minContains) ?? 1, number(node.maxContains) ?? Number.POSITIVE_INFINITY));
}
if (Array.isArray(node.allOf))
for (const s of node.allOf)
parts.push(this.annotating(s, base));
if (Array.isArray(node.anyOf))
parts.push(annotateAny(node.anyOf.map((s) => this.annotating(s, base)), false));
if (Array.isArray(node.oneOf))
parts.push(annotateAny(node.oneOf.map((s) => this.annotating(s, base)), true));
if (node.if !== void 0) {
const then = node.then === void 0 ? void 0 : this.annotating(node.then, base);
const otherwise = node.else === void 0 ? void 0 : this.annotating(node.else, base);
parts.push(annotateIf(this.annotating(node.if, base), then, otherwise));
}
if (typeof node.$ref === "string")
parts.push(this.annotatingRef(node.$ref, base));
if (typeof node.$dynamicRef === "string")
parts.push(this.annotatingDynamicRef(node.$dynamicRef, base));
for (const [k, s] of entries(node.dependentSchemas))
parts.push(annotateDependent(k, this.annotating(s, base)));
if (node.unevaluatedProperties !== void 0) {
parts.push(unevaluatedProperties(this.check(node.unevaluatedProperties, base)));
}
if (node.unevaluatedItems !== void 0)
parts.push(unevaluatedItems(this.check(node.unevaluatedItems, base)));
}
annotatingRef(ref, base) {
const target = this.r.resolve(ref, base);
const check = this.annotating(target.node, target.base);
return this.dynamic && target.base !== base ? scopedAnnotating(this.scope, target.base, check) : check;
}
annotatingDynamicRef(ref, base) {
const resolved = this.bookended(ref, base);
if (resolved === void 0)
return this.annotatingRef(ref, base);
const { initial, name } = resolved;
const fallback = this.annotating(initial.node, initial.base);
const lookup = this.dynamicLookup(name, (node, b) => this.annotating(node, b));
const scope = this.scope;
return (v, a) => {
for (let i = 0; i < scope.length; i++) {
const check = lookup(scope[i]);
if (check !== null)
return check(v, a);
}
return fallback(v, a);
};
}
};
var NEUTRAL_KEYWORDS = /* @__PURE__ */ new Set([
"$schema",
"$comment",
"title",
"description",
"default",
"examples",
"deprecated",
"readOnly",
"writeOnly",
"$defs",
"definitions",
"contentEncoding",
"contentMediaType",
"minContains",
"maxContains",
"$vocabulary"
]);
var OBJECT_EXTRAS = [
"propertyNames",
"minProperties",
"maxProperties",
"dependentRequired",
"dependentSchemas",
"dependencies"
];
var ANNOTATING = /* @__PURE__ */ new Set([
"properties",
"patternProperties",
"additionalProperties",
"prefixItems",
"items",
"additionalItems",
"contains",
"minContains",
"maxContains",
"allOf",
"anyOf",
"oneOf",
"if",
"then",
"else",
"$ref",
"$dynamicRef",
"dependentSchemas",
"unevaluatedProperties",
"unevaluatedItems"
]);
function constUnion(branches, exactlyOne) {
const values = [];
for (const branch of branches) {
if (!isSchemaObject(branch) || !Object.hasOwn(branch, "const"))
return void 0;
for (const k of Object.keys(branch))
if (k !== "const" && !NEUTRAL_KEYWORDS.has(k))
return void 0;
if (typeof branch.const === "object" && branch.const !== null)
return void 0;
if (exactlyOne && values.includes(branch.const))
return void 0;
values.push(branch.const);
}
return enumCheck(values);
}
function tagOf(branch, key) {
const properties = branch.properties;
if (branch.type !== "object" || !Array.isArray(branch.required) || !branch.required.includes(key))
return void 0;
const tag = isSchemaObject(properties) ? properties[key] : void 0;
if (!isSchemaObject(tag) || !Object.hasOwn(tag, "const"))
return void 0;
return typeof tag.const === "object" && tag.const !== null ? void 0 : tag.const;
}
function number(value2) {
return typeof value2 === "number" ? value2 : void 0;
}
function entries(value2) {
return isSchemaObject(value2) ? Object.entries(value2) : [];
}
// node_modules/@earendil-works/pi-schema/dist/explain.js
var Explainer = class {
c;
schema;
/**
* The errors of `$ref` targets for object values, within one errors() call: a recursive union explains each branch
* to pick the one to blame, and every branch would explain the same children again, exponentially in the depth.
*/
memo = void 0;
constructor(compiler2, schema) {
this.c = compiler2;
this.schema = schema;
compiler2.root();
}
/** The errors of `value`, at least one (`value` failed the check). */
errors(value2) {
const out = [];
try {
this.walk(this.schema, this.c.r.rootBase, value2, "", out);
} finally {
this.memo = void 0;
}
if (out.length === 0)
out.push({ path: "", keyword: "schema", message: "invalid" });
return out;
}
ok(node, base, v) {
return this.c.check(node, base)(v);
}
// For $dynamicRef schemas this check runs outside the original dynamic scope, so their errors are approximate.
walk(node, base, v, path3, out) {
if (node === true)
return;
if (node === false) {
out.push({ path: path3, keyword: "false", message: "no value is allowed here" });
return;
}
if (!isSchemaObject(node))
return;
const b = this.c.r.baseFor(node, base);
if (this.ok(node, b, v))
return;
const start = out.length;
const push = (keyword, message, at = path3) => {
out.push({ path: at, keyword, message });
};
if (this.c.draft === "7" && typeof node.$ref === "string") {
this.walkRef(node.$ref, b, v, path3, out);
return;
}
if (node.type !== void 0) {
const types = Array.isArray(node.type) ? node.type : [node.type];
const checks = types.map((t) => (typeof t === "string" ? TYPE_CHECKS.get(t) : void 0) ?? NEVER);
if (!checks.some((check) => check(v))) {
push("type", `expected ${types.join(" or ")}, got ${typeName(v)}`);
return;
}
}
if (Array.isArray(node.enum) && !enumCheck(node.enum)(v))
push("enum", `expected one of ${listValues(node.enum)}`);
if (Object.hasOwn(node, "const") && !constCheck(node.const)(v))
push("const", `expected ${JSON.stringify(node.const)}`);
if (typeof v === "string" && node.type !== "bytes")
this.walkString(node, v, push);
if (v instanceof Uint8Array && node.type === "bytes")
this.walkBytes(node, v, push);
if (typeof v === "number")
this.walkNumber(node, v, push);
if (isObject(v))
this.walkObject(node, b, v, path3, out, push);
if (Array.isArray(v))
this.walkArray(node, b, v, path3, out, push);
if (Array.isArray(node.allOf))
for (const s of node.allOf)
this.walk(s, b, v, path3, out);
if (Array.isArray(node.anyOf))
this.walkUnion(node.anyOf, b, v, path3, out, false);
if (Array.isArray(node.oneOf))
this.walkUnion(node.oneOf, b, v, path3, out, true);
if (node.not !== void 0 && this.ok(node.not, b, v))
push("not", "must not match the schema in not");
if (node.if !== void 0) {
const branch = this.ok(node.if, b, v) ? node.then : node.else;
if (branch !== void 0)
this.walk(branch, b, v, path3, out);
}
if (typeof node.$ref === "string")
this.walkRef(node.$ref, b, v, path3, out);
if (out.length === start && (node.unevaluatedProperties !== void 0 || node.unevaluatedItems !== void 0)) {
this.walkUnevaluated(node, b, v, path3, out);
}
if (out.length === start && typeof node.$dynamicRef === "string") {
push("$dynamicRef", "does not match the dynamically referenced schema");
}
}
walkRef(ref, base, v, path3, out) {
const target = this.c.r.resolve(ref, base);
if (target.node === false && this.c.r.isUnresolved(ref, base)) {
out.push({ path: path3, keyword: "$ref", message: `unresolved reference ${ref}` });
return;
}
if (!isSchemaObject(target.node) || typeof v !== "object" || v === null) {
this.walk(target.node, target.base, v, path3, out);
return;
}
this.memo ??= /* @__PURE__ */ new Map();
let values = this.memo.get(target.node);
const known = values?.get(v);
if (known !== void 0 && known.path === path3) {
out.push(...known.errors);
return;
}
const errors = [];
this.walk(target.node, target.base, v, path3, errors);
if (values === void 0) {
values = /* @__PURE__ */ new Map();
this.memo.set(target.node, values);
}
values.set(v, { path: path3, errors });
out.push(...errors);
}
walkString(node, v, push) {
const n = codePoints(v);
if (typeof node.minLength === "number" && n < node.minLength) {
push("minLength", `expected at least ${node.minLength} characters`);
}
if (typeof node.maxLength === "number" && n > node.maxLength) {
push("maxLength", `expected at most ${node.maxLength} characters`);
}
if (typeof node.pattern === "string" && !sharedRegex(node.pattern).test(v)) {
push("pattern", `expected to match ${node.pattern}`);
}
const formats2 = this.c.formats;
const format = formats2 !== void 0 && typeof node.format === "string" && Object.hasOwn(formats2, node.format) ? formats2[node.format] : void 0;
if (format !== void 0 && !format(v))
push("format", `expected format ${node.format}`);
}
walkBytes(node, v, push) {
if (typeof node.minLength === "number" && v.length < node.minLength) {
push("minLength", `expected at least ${node.minLength} bytes`);
}
if (typeof node.maxLength === "number" && v.length > node.maxLength) {
push("maxLength", `expected at most ${node.maxLength} bytes`);
}
}
walkNumber(node, v, push) {
if (typeof node.minimum === "number" && v < node.minimum)
push("minimum", `expected >= ${node.minimum}`);
if (typeof node.maximum === "number" && v > node.maximum)
push("maximum", `expected <= ${node.maximum}`);
if (typeof node.exclusiveMinimum === "number" && v <= node.exclusiveMinimum) {
push("exclusiveMinimum", `expected > ${node.exclusiveMinimum}`);
}
if (typeof node.exclusiveMaximum === "number" && v >= node.exclusiveMaximum) {
push("exclusiveMaximum", `expected < ${node.exclusiveMaximum}`);
}
if (typeof node.multipleOf === "number" && !isMultiple(v, node.multipleOf)) {
push("multipleOf", `expected a multiple of ${node.multipleOf}`);
}
}
walkObject(node, b, v, path3, out, push) {
const properties = isSchemaObject(node.properties) ? node.properties : {};
const required = Array.isArray(node.required) ? node.required : [];
for (const k of required) {
if (typeof k === "string" && (!Object.hasOwn(v, k) || v[k] === void 0))
push("required", "missing", pointer(path3, k));
}
for (const k of Object.keys(properties)) {
if (Object.hasOwn(v, k) && v[k] !== void 0)
this.walk(properties[k], b, v[k], pointer(path3, k), out);
}
const patterns = isSchemaObject(node.patternProperties) ? Object.entries(node.patternProperties) : [];
for (const k of Object.keys(v)) {
let matched = Object.hasOwn(properties, k);
for (const [p, s] of patterns) {
if (sharedRegex(p).test(k)) {
matched = true;
this.walk(s, b, v[k], pointer(path3, k), out);
}
}
if (!matched && node.additionalProperties !== void 0) {
if (node.additionalProperties === false)
push("additionalProperties", "unknown field", pointer(path3, k));
else
this.walk(node.additionalProperties, b, v[k], pointer(path3, k), out);
}
if (node.propertyNames !== void 0 && !this.ok(node.propertyNames, b, k)) {
push("propertyNames", "invalid property name", pointer(path3, k));
}
}
const count = Object.keys(v).length;
if (typeof node.minProperties === "number" && count < node.minProperties) {
push("minProperties", `expected at least ${node.minProperties} properties`);
}
if (typeof node.maxProperties === "number" && count > node.maxProperties) {
push("maxProperties", `expected at most ${node.maxProperties} properties`);
}
const dependencies = {
...this.c.draft === "7" || !isSchemaObject(node.dependentRequired) ? {} : node.dependentRequired,
...isSchemaObject(node.dependencies) ? node.dependencies : {}
};
for (const [k, d] of Object.entries(dependencies)) {
if (!Object.hasOwn(v, k))
continue;
if (!Array.isArray(d))
this.walk(d, b, v, path3, out);
else
for (const r of d)
if (!Object.hasOwn(v, r))
push("dependentRequired", `required when ${k} is present`, pointer(path3, r));
}
if (this.c.draft !== "7" && isSchemaObject(node.dependentSchemas)) {
for (const [k, s] of Object.entries(node.dependentSchemas))
if (Object.hasOwn(v, k))
this.walk(s, b, v, path3, out);
}
}
walkArray(node, b, v, path3, out, push) {
let prefix = [];
let rest;
if (Array.isArray(node.items)) {
prefix = node.items;
rest = node.additionalItems;
} else {
if (this.c.draft !== "7" && Array.isArray(node.prefixItems))
prefix = node.prefixItems;
rest = node.items;
}
for (let i = 0; i < v.length; i++) {
const s = i < prefix.length ? prefix[i] : rest;
if (s !== void 0)
this.walk(s, b, v[i], `${path3}/${i}`, out);
}
if (typeof node.minItems === "number" && v.length < node.minItems) {
push("minItems", `expected at least ${node.minItems} items`);
}
if (typeof node.maxItems === "number" && v.length > node.maxItems) {
push("maxItems", `expected at most ${node.maxItems} items`);
}
if (node.uniqueItems === true && !uniqueCheck(v))
push("uniqueItems", "expected unique items");
if (node.contains !== void 0) {
const draft7 = this.c.draft === "7";
const min = draft7 || typeof node.minContains !== "number" ? 1 : node.minContains;
const max = draft7 || typeof node.maxContains !== "number" ? Number.POSITIVE_INFINITY : node.maxContains;
if (!containsCheck(this.c.check(node.contains, b), min, max)(v)) {
push("contains", containsMessage(min, max));
}
}
}
walkUnion(branches, b, v, path3, out, exactlyOne) {
const matches = branches.filter((s) => this.ok(s, b, v)).length;
if (matches === 1 || !exactlyOne && matches > 0)
return;
const keyword = exactlyOne ? "oneOf" : "anyOf";
if (matches > 1) {
out.push({ path: path3, keyword, message: "matches more than one alternative" });
return;
}
const tag = this.tagOf(branches, b);
if (tag !== void 0 && isObject(v)) {
const i = tag.values.indexOf(v[tag.key]);
if (i < 0)
out.push({
path: pointer(path3, tag.key),
keyword,
message: `expected one of ${listValues(tag.values)}`
});
else
this.walk(branches[i], b, v, path3, out);
return;
}
let best;
for (const s of branches) {
const errors = [];
this.walk(s, b, v, path3, errors);
if (errors.length === 0)
continue;
const declared = isObject(v) ? this.declaredKeys(s, b, v) : 0;
const better = best === void 0 || declared > best.declared || declared === best.declared && errors[0].path.length > best.errors[0].path.length;
if (better)
best = { errors, declared };
}
out.push(...best?.errors ?? [{ path: path3, keyword, message: "matches no alternative" }]);
}
/** How many of the keys of `v` the branch `s` (through a `$ref`) declares in `properties`. */
declaredKeys(s, b, v) {
const node = isSchemaObject(s) && typeof s.$ref === "string" ? this.c.r.resolve(s.$ref, b).node : s;
const properties = isSchemaObject(node) && isSchemaObject(node.properties) ? node.properties : {};
return Object.keys(v).filter((k) => Object.hasOwn(properties, k)).length;
}
tagOf(branches, b) {
const resolved = branches.map((s) => isSchemaObject(s) && typeof s.$ref === "string" ? this.c.r.resolve(s.$ref, b).node : s);
const first = resolved[0];
if (!isSchemaObject(first) || !isSchemaObject(first.properties))
return void 0;
for (const key of Object.keys(first.properties)) {
const values = resolved.map((s) => {
const tag = isSchemaObject(s) && isSchemaObject(s.properties) ? s.properties[key] : void 0;
return isSchemaObject(tag) ? tag.const : void 0;
});
const primitive = values.every((x) => x !== void 0 && (typeof x !== "object" || x === null));
if (primitive && new Set(values).size === values.length)
return { key, values };
}
return void 0;
}
walkUnevaluated(node, b, v, path3, out) {
const { unevaluatedProperties: unevaluatedProperties2, unevaluatedItems: unevaluatedItems2, ...rest } = node;
const a = newAnnotations();
this.c.annotating(rest, b)(v, a);
if (isObject(v) && unevaluatedProperties2 !== void 0 && !a.allProps) {
for (const k of Object.keys(v)) {
if (a.props?.has(k))
continue;
if (unevaluatedProperties2 === false) {
out.push({ path: pointer(path3, k), keyword: "unevaluatedProperties", message: "unknown field" });
} else
this.walk(unevaluatedProperties2, b, v[k], pointer(path3, k), out);
}
}
if (Array.isArray(v) && unevaluatedItems2 !== void 0 && !a.allItems) {
for (let i = a.items; i < v.length; i++) {
if (a.indexes?.has(i))
continue;
if (unevaluatedItems2 === false) {
out.push({ path: `${path3}/${i}`, keyword: "unevaluatedItems", message: "unexpected item" });
} else
this.walk(unevaluatedItems2, b, v[i], `${path3}/${i}`, out);
}
}
}
};
var LISTED_VALUES = 20;
function listValues(values) {
if (values.length <= LISTED_VALUES)
return JSON.stringify(values);
const listed = JSON.stringify(values.slice(0, LISTED_VALUES));
return `${listed.slice(0, -1)}, ... and ${values.length - LISTED_VALUES} more]`;
}
function containsMessage(min, max) {
if (max === Number.POSITIVE_INFINITY)
return `expected at least ${min} matching ${min === 1 ? "item" : "items"}`;
if (min === 0)
return `expected at most ${max} matching ${max === 1 ? "item" : "items"}`;
return `expected between ${min} and ${max} matching items`;
}
function pointer(path3, key) {
return `${path3}/${String(key).replace(/~/g, "~0").replace(/\//g, "~1")}`;
}
function typeName(v) {
if (v === null)
return "null";
if (Array.isArray(v))
return "array";
if (v instanceof Uint8Array)
return "bytes";
if (typeof v === "number" && Number.isInteger(v))
return "integer";
return typeof v;
}
// node_modules/@earendil-works/pi-schema/dist/validator.js
function compile(schema, options = NO_OPTIONS) {
const check = compileCheck(schema, options);
return options.coerce === true ? new CoercingValidator(schema, options, check) : new Validator(schema, options, check);
}
var NO_OPTIONS = Object.freeze({});
var Validator = class {
/** Whether `value` is valid. A plain function: it may be passed around without its validator. */
check;
schema;
options;
explainer = void 0;
constructor(schema, options, check) {
this.check = check;
this.schema = schema;
this.options = options;
}
/**
* Why `value` is invalid: one error per failing keyword, `[]` when it is valid. Built on the first failure and
* kept, so a validator whose values always pass never pays for it.
*/
errors(value2) {
if (this.check(value2))
return [];
this.explainer ??= new Explainer(compiler(this.schema, this.options), this.schema);
return this.explainer.errors(value2);
}
};
var CoercingValidator = class extends Validator {
coercer = void 0;
/**
* `value` coerced towards the schema: numeric strings to numbers, `"true"` to `true`, a single value to a one-item
* array, an optional `null` dropped, the first union branch the value converts to (the README lists every rule).
* Only the changed paths are copied; `value` comes back itself when nothing changes, and is never modified. Values
* that cannot be coerced stay as they are. The rules are built on the first call.
*/
coerce(value2) {
this.coercer ??= new Coercer(compiler(this.schema, this.options), this.schema);
return this.coercer.coerce(value2);
}
/** Coerces `value`, then checks it: the coerced value when it is valid, else its errors. */
parse(value2) {
const coerced = this.coerce(value2);
return this.check(coerced) ? { ok: true, value: coerced } : { ok: false, errors: this.errors(coerced) };
}
};
function compileCheck(schema, options) {
return compiler(schema, options).root();
}
function compiler(schema, options) {
const plain = new Compiler(schema, options, false);
try {
plain.root();
return plain;
} catch (error) {
if (error !== RESTART)
throw error;
return new Compiler(schema, options, true);
}
}
// node_modules/@earendil-works/chord/dist/json.js
var DATA_DESCRIPTOR = {
value: void 0,
writable: true,
enumerable: true,
configurable: true
};
function copyJson(value2, options) {
return copy(value2, void 0, options?.omitUndefinedProperties === true);
}
function copy(value2, ancestors, omitUndefinedProperties) {
if (value2 === null || typeof value2 === "string" || typeof value2 === "boolean")
return value2;
if (typeof value2 === "number") {
if (Number.isFinite(value2))
return value2;
throw new TypeError("Value contains a non-finite number and is not strict JSON");
}
if (typeof value2 !== "object")
throw new TypeError(`Value contains a non-JSON ${typeof value2}; expected strict JSON`);
const active = ancestors ?? /* @__PURE__ */ new Set();
if (active.has(value2))
throw new TypeError("Value contains cycles and is not strict JSON");
active.add(value2);
try {
if (Array.isArray(value2)) {
if (Object.getPrototypeOf(value2) !== Array.prototype || Reflect.ownKeys(value2).length !== value2.length + 1) {
throw new TypeError("Value must contain strict JSON dense plain arrays");
}
const result2 = new Array(value2.length);
for (let index = 0; index < value2.length; index++) {
const descriptor = Object.getOwnPropertyDescriptor(value2, index);
if (descriptor === void 0 || !descriptor.enumerable || !("value" in descriptor)) {
throw new TypeError("Value must contain strict JSON enumerable indexed data properties");
}
defineData(result2, String(index), copy(descriptor.value, active, omitUndefinedProperties));
}
return result2;
}
const prototype = Object.getPrototypeOf(value2);
if (prototype !== Object.prototype && prototype !== null) {
throw new TypeError("Value must contain strict JSON plain objects or arrays");
}
const result = Object.create(prototype);
for (const key of Reflect.ownKeys(value2)) {
if (typeof key === "symbol")
throw new TypeError("Value contains a symbol key and is not strict JSON");
const descriptor = Object.getOwnPropertyDescriptor(value2, key);
if (!descriptor.enumerable || !("value" in descriptor)) {
throw new TypeError("Value must contain strict JSON enumerable data properties");
}
if (descriptor.value === void 0 && omitUndefinedProperties)
continue;
defineData(result, key, copy(descriptor.value, active, omitUndefinedProperties));
}
return result;
} finally {
active.delete(value2);
}
}
function defineData(target, key, value2) {
DATA_DESCRIPTOR.value = value2;
Object.defineProperty(target, key, DATA_DESCRIPTOR);
DATA_DESCRIPTOR.value = void 0;
}
// node_modules/@earendil-works/chord/dist/delta/apply-immutable-trusted.js
var DATA_DESCRIPTOR2 = {
value: void 0,
writable: true,
enumerable: true,
configurable: true
};
function applyImmutableTrusted(target, operations) {
let root2 = target;
const owned = /* @__PURE__ */ new WeakSet();
for (const operation of operations) {
if (operation[0] === "r") {
root2 = operation[1];
continue;
}
if (operation[0] === "p" || operation[0] === "m") {
const copied2 = copyPath(root2, operation[1], operation[1].length, owned);
root2 = copied2.root;
if (!Array.isArray(copied2.target))
throw new TypeError("Trusted array operation target is not an array");
if (operation[0] === "p")
spliceTrusted(copied2.target, operation[2], operation[3], operation[4]);
else
permuteTrusted(copied2.target, operation[2]);
continue;
}
const path3 = operation[1];
const copied = copyPath(root2, path3, path3.length - 1, owned);
root2 = copied.root;
const key = path3[path3.length - 1];
switch (operation[0]) {
case "s":
defineData2(copied.target, key, operation[2]);
break;
case "d":
if (Array.isArray(copied.target)) {
if (typeof key !== "number")
throw new TypeError("Trusted array deletion key is not numeric");
spliceTrusted(copied.target, key, 1, []);
} else
Reflect.deleteProperty(copied.target, key);
break;
case "a": {
const current = read(copied.target, key);
if (typeof current !== "string")
throw new TypeError("Trusted append target is not a string");
defineData2(copied.target, key, `${current}${operation[2]}`);
break;
}
case "t": {
const current = read(copied.target, key);
if (typeof current !== "string")
throw new TypeError("Trusted truncate target is not a string");
defineData2(copied.target, key, current.slice(operation[2]));
break;
}
}
}
return root2;
}
function copyPath(root2, path3, length, owned) {
if (!isContainer(root2))
throw new TypeError("Trusted operation root is not a container");
let copiedRoot = root2;
if (!owned.has(root2)) {
copiedRoot = shallowCopy(root2);
owned.add(copiedRoot);
}
let destination = copiedRoot;
for (let index = 0; index < length; index++) {
const segment = path3[index];
const child = read(destination, segment);
if (!isContainer(child))
throw new TypeError("Trusted operation path is not a container");
if (owned.has(child)) {
destination = child;
continue;
}
const copy2 = shallowCopy(child);
defineData2(destination, segment, copy2);
owned.add(copy2);
destination = copy2;
}
return { root: copiedRoot, target: destination };
}
function shallowCopy(value2) {
if (Array.isArray(value2))
return Array.from(value2);
return Object.getPrototypeOf(value2) === null ? Object.assign(/* @__PURE__ */ Object.create(null), value2) : { ...value2 };
}
function read(target, key) {
return target[key];
}
function defineData2(target, key, value2) {
DATA_DESCRIPTOR2.value = value2;
Object.defineProperty(target, key, DATA_DESCRIPTOR2);
DATA_DESCRIPTOR2.value = void 0;
}
function spliceTrusted(target, start, remove, items) {
const oldLength = target.length;
const delta = items.length - remove;
if (delta > 0) {
target.length = oldLength + delta;
target.copyWithin(start + items.length, start + remove, oldLength);
} else if (delta < 0) {
target.copyWithin(start + items.length, start + remove, oldLength);
target.length = oldLength + delta;
}
for (let index = 0; index < items.length; index++)
defineData2(target, start + index, items[index]);
}
function permuteTrusted(target, permutation) {
if (target.length !== permutation.length)
throw new TypeError("Trusted permutation length mismatch");
const previous = target.slice();
for (let index = 0; index < permutation.length; index++)
target[index] = previous[permutation[index]];
}
function isContainer(value2) {
return value2 !== null && typeof value2 === "object";
}
// node_modules/@earendil-works/chord/dist/delta/tracker.js
var NODE = /* @__PURE__ */ Symbol("chord.delta.overlay.node");
var PREPARED = /* @__PURE__ */ new WeakMap();
var RELEASED = {};
var ARRAY_MUTATORS = /* @__PURE__ */ new Set([
"push",
"pop",
"shift",
"unshift",
"splice",
"reverse",
"sort",
"fill",
"copyWithin"
]);
var MAX_DELTA_OPERATIONS = 4096;
var MAX_SIMPLE_OBJECT_NODES = 128;
var DATA_DESCRIPTOR3 = {
value: void 0,
writable: true,
enumerable: true,
configurable: true
};
var PreparedImpl = class {
#context;
value;
base;
ops;
constructor(context, value2, operations) {
this.#context = context;
this.value = value2;
this.base = context.baseValue;
this.ops = operations;
PREPARED.set(this, context);
}
get baseRevision() {
return this.#context.baseRevision;
}
abort() {
abortContext(this.#context);
}
};
var ChangeImpl = class {
#context;
#preparedStatus;
#settled = false;
constructor(context) {
this.#context = context;
}
get state() {
const state2 = this.#context?.root?.proxy;
if (state2 === void 0)
throw new TypeError("Cannot use a settled overlay");
return state2;
}
prepare() {
if (this.#settled)
throw new Error("Change has already been settled");
const context = this.#context;
assertWritable(context);
context.status.value = "prepared";
try {
if (!context.replacement)
context.ops = context.dirty.length === 0 ? [] : emitOperations(context);
const prepared = materializePrepared(context);
this.#preparedStatus = context.status;
this.#settled = true;
return prepared;
} catch (error) {
context.status.value = "aborted";
clearContext(context);
this.#settled = true;
throw error;
} finally {
this.#context = void 0;
}
}
abort() {
if (this.#settled) {
if (this.#preparedStatus?.value === "prepared")
this.#preparedStatus.value = "aborted";
this.#preparedStatus = void 0;
return;
}
this.#settled = true;
abortContext(this.#context);
this.#context = void 0;
}
};
var TrackerImpl = class {
#owner = {};
#open;
#competitors;
#selfRef;
#value;
#revision = 0;
#pruneBudget = 256;
constructor(initial) {
this.#value = initial;
this.#selfRef = new WeakRef(this);
}
get value() {
return this.#value;
}
get revision() {
return this.#revision;
}
beginChange() {
const context = createContext(this.#selfRef, this.#owner, this.#revision, this.#value, false, this.#value);
if (this.#open !== void 0)
this.#demote(this.#open);
this.#open = context;
return new ChangeImpl(context);
}
prepareReplace(value2) {
const context = createContext(this.#selfRef, this.#owner, this.#revision, value2, true, this.#value);
context.status.value = "prepared";
try {
return materializePrepared(context);
} catch (error) {
context.status.value = "aborted";
clearContext(context);
throw error;
}
}
adopt(prepared) {
const context = PREPARED.get(prepared);
if (context?.owner !== this.#owner)
throw new Error("Prepared change belongs to a different tracker");
if (context.status.value === "consumed")
throw new Error("Prepared change has already been used");
if (context.status.value === "aborted")
throw new Error("Prepared change has been aborted");
if (context.status.value === "stale")
throw new Error("Prepared change is stale");
if (context.status.value !== "prepared")
throw new Error("Prepared change is not ready");
if (context.baseRevision !== this.#revision) {
context.status.value = "stale";
clearContext(context);
throw new Error("Prepared change is stale");
}
if (this.#value !== prepared.base) {
context.status.value = "stale";
throw new Error("Prepared change is stale");
}
this.#value = prepared.value;
context.status.value = "consumed";
this.#revision += 1;
this.#invalidate(context);
}
releaseContext(context) {
if (this.#open === context)
this.#open = void 0;
else if (context.registryRef !== void 0)
this.#competitors?.delete(context.registryRef);
context.registryRef = void 0;
}
#demote(context) {
const reference = new WeakRef(context);
context.registryRef = reference;
this.#competitors ??= /* @__PURE__ */ new Set();
this.#competitors.add(reference);
this.#pruneBudget -= 1;
if (this.#pruneBudget === 0) {
for (const entry2 of this.#competitors) {
if (entry2.deref() === void 0)
this.#competitors.delete(entry2);
}
this.#pruneBudget = Math.max(256, this.#competitors.size);
}
}
#invalidate(winner) {
const open = this.#open;
const competitors = this.#competitors;
this.#open = void 0;
this.#competitors = void 0;
this.#pruneBudget = 256;
if (open !== void 0)
staleCompetitor(open, winner);
if (competitors === void 0)
return;
for (const reference of competitors) {
const context = reference.deref();
if (context !== void 0)
staleCompetitor(context, winner);
}
}
replacementBase(context) {
return context.baseRevision === this.#revision ? this.#value : void 0;
}
};
function staleCompetitor(context, winner) {
if (context === winner)
return;
if (context.status.value === "open" || context.status.value === "prepared")
context.status.value = "stale";
context.registryRef = void 0;
releaseOverlayReferences(context);
}
function track(initial) {
return new TrackerImpl(initial);
}
function appendText(draft, key, text2) {
const node = draft[NODE];
if (node === void 0)
throw new TypeError("appendText() needs a draft");
assertWritable(node.context);
const name = String(key);
const current = Array.isArray(nodeBase(node)) || !objectHas(node, name) ? void 0 : objectValue(node, name);
if (typeof current !== "string")
throw new TypeError(`appendText() needs a string at ${JSON.stringify(name)}`);
if (text2.length === 0)
return;
const owned = ownedSlice2(text2, 0);
const appended = node.appends?.get(name) ?? (hasObjectWrite(node, name) ? void 0 : "");
setObjectWrite(node, name, current + owned);
markDirty(node);
if (appended !== void 0) {
node.appends ??= /* @__PURE__ */ new Map();
node.appends.set(name, appended + owned);
}
}
function materializePrepared(context) {
const operations = ensureOperations(context);
const base = context.baseValue;
const value2 = operations.length === 0 ? base : context.simpleObjectMaterialization ? cloneNode(context.root) : materializeOperations(base, operations);
const prepared = new PreparedImpl(context, value2, operations);
if (context.nodes.length > 4096)
releaseOverlayReferences(context);
else
clearContext(context);
return prepared;
}
function materializeOperations(base, operations) {
for (const operation of operations) {
if (operation[0] === "p" || operation[0] === "m")
return applyImmutable(base, operations);
}
return applyImmutableTrusted(base, operations);
}
function createContext(tracker, owner, baseRevision, root2, replacement, base) {
const context = {
owner,
tracker,
baseRevision,
status: { value: "open" },
root: void 0,
bases: [],
stored: void 0,
dirty: [],
nodes: [],
rawNodes: void 0,
ops: void 0,
replacement,
replacementNoop: false,
baseValue: base,
overlayReleased: false,
simpleObjectMaterialization: false,
registryRef: void 0
};
context.root = createNode(context, root2, void 0);
return context;
}
var sharedObjectHandler = {
deleteProperty(target, property) {
return deleteProperty(nodeForTarget(target), property);
},
defineProperty(target) {
assertWritable(nodeForTarget(target).context);
throw new TypeError("Defining overlay properties is not supported");
},
get(target, property) {
if (property === "then") {
const node2 = target[NODE];
if (node2 === void 0 || isSettledContext(node2.context))
return void 0;
}
const node = nodeForTarget(target);
if (property === NODE)
return node;
return getProperty(node, property);
},
getOwnPropertyDescriptor(target, property) {
return getDescriptor(nodeForTarget(target), property);
},
getPrototypeOf(target) {
const node = nodeForTarget(target);
assertReadable(node.context);
return Object.getPrototypeOf(nodeBase(node));
},
has(target, property) {
return hasProperty(nodeForTarget(target), property);
},
isExtensible(target) {
assertReadable(nodeForTarget(target).context);
return true;
},
ownKeys(target) {
return ownKeys(nodeForTarget(target));
},
preventExtensions(target) {
assertWritable(nodeForTarget(target).context);
throw new TypeError("Overlays cannot be made non-extensible");
},
set(target, property, value2) {
return setProperty(nodeForTarget(target), property, value2);
},
setPrototypeOf(target) {
assertWritable(nodeForTarget(target).context);
throw new TypeError("Changing an overlay prototype is not supported");
}
};
var sharedArrayHandler = sharedObjectHandler;
function createNode(context, base, parent, parentKind = 0, parentKey = "", parentSource = void 0, parentPlacement = false) {
const existing = context.rawNodes?.get(base);
if (existing !== void 0)
return existing;
const target = Array.isArray(base) ? [] : {};
const baseIndex = context.bases.length;
const parentIndex = parent?.baseIndex ?? -1;
context.bases.push(base);
const node = {
context,
baseIndex,
parentIndex,
parentKind,
parentKey,
parentPlacement,
target,
proxy: target
};
if (parentSource !== void 0)
node.parentSource = parentSource;
target[NODE] = node;
node.proxy = new Proxy(target, Array.isArray(base) ? sharedArrayHandler : sharedObjectHandler);
if (parent !== void 0) {
context.rawNodes ??= /* @__PURE__ */ new WeakMap();
context.rawNodes.set(base, node);
}
context.nodes.push(node);
return node;
}
function nodeBase(node) {
return node.context.bases[node.baseIndex];
}
function nodeParent(node) {
return node.parentIndex < 0 ? void 0 : node.context.nodes[node.parentIndex];
}
function storeValue(context, value2) {
if (!isContainer2(value2))
return value2;
context.stored ??= [];
const index = context.stored.length;
context.stored.push(value2);
return { index };
}
function storedValue(context, reference) {
return typeof reference === "object" && reference !== null ? context.stored[reference.index] : reference;
}
function replaceStoredValue(context, reference, value2) {
if (isContainer2(value2)) {
if (typeof reference === "object" && reference !== null) {
context.stored[reference.index] = value2;
return reference;
}
return storeValue(context, value2);
}
if (typeof reference === "object" && reference !== null)
context.stored[reference.index] = RELEASED;
return value2;
}
function releaseStoredValue(context, reference) {
if (typeof reference === "object" && reference !== null)
context.stored[reference.index] = RELEASED;
}
function nodeForTarget(target) {
const node = target[NODE];
if (node === void 0)
throw new TypeError("Cannot use a settled overlay");
return node;
}
function isSettledContext(context) {
return context.overlayReleased || context.status.value === "consumed" || context.status.value === "aborted" || context.status.value === "stale";
}
function assertReadable(context) {
if (isSettledContext(context))
throw new TypeError("Cannot use a settled overlay");
}
function assertWritable(context) {
assertReadable(context);
if (context.status.value !== "open")
throw new TypeError("Prepared overlays are read-only");
}
function getProperty(node, property) {
assertReadable(node.context);
if (Array.isArray(nodeBase(node))) {
const overlay = arrayOverlay(node);
if (property === "length")
return arrayLength(overlay);
if (ARRAY_MUTATORS.has(property))
return arrayMutators[property];
const index = arrayIndex(property);
if (index !== void 0)
return getArrayIndex(node, index);
return Reflect.get(Array.prototype, property, node.proxy);
}
if (typeof property === "symbol")
return Reflect.get(nodeBase(node), property, node.proxy);
const key = String(property);
if (!objectHas(node, key)) {
if (isObjectDeleted(node, key) || Object.hasOwn(nodeBase(node), key))
return void 0;
return Reflect.get(nodeBase(node), property, node.proxy);
}
const value2 = objectValue(node, key);
if (!isContainer2(value2))
return value2;
return createNode(node.context, value2, node, 0, key, void 0, hasObjectWrite(node, key)).proxy;
}
function getArrayIndex(node, index) {
const overlay = arrayOverlay(node);
if (index >= arrayLength(overlay))
return void 0;
const piece = locatePiece(overlay, index);
const sourceIndex = piece.start + piece.step * overlay.locatedOffset;
const value2 = entryValueAt(node, piece, sourceIndex);
if (!isContainer2(value2))
return value2;
return createNode(node.context, value2, node, piece.kind === "base" ? 1 : 2, sourceIndex, piece.kind === "insert" ? piece.source : void 0, piece.kind === "insert" || hasEntryOverrideAt(overlay, piece, sourceIndex)).proxy;
}
function setProperty(node, property, supplied) {
assertWritable(node.context);
if (typeof property === "symbol")
throw new TypeError("Symbol writes are not supported");
if (Array.isArray(nodeBase(node))) {
if (property === "length") {
setArrayLength(node, toArrayLength(supplied));
return true;
}
const index = arrayIndex(property);
if (index === void 0)
throw new TypeError("Only array indices and length can be written");
if (index > arrayLength(arrayOverlay(node)))
throw new TypeError("Overlay arrays cannot contain holes");
setArrayIndex(node, index, clonePlacement(supplied));
return true;
}
const key = String(property);
if (supplied === void 0)
return deleteProperty(node, key);
const stored = clonePlacement(supplied);
const current = objectValue(node, key);
const wasDeleted = isObjectDeleted(node, key);
if (!wasDeleted && !isContainer2(stored) && current === stored)
return true;
node.appends?.delete(key);
setObjectWrite(node, key, stored);
if (wasDeleted && Object.hasOwn(nodeBase(node), key)) {
if (node.readded === void 0)
node.readded = /* @__PURE__ */ new Set();
node.readded.add(key);
}
deleteObjectDeletion(node, key);
markDirty(node);
return true;
}
function deleteProperty(node, property) {
assertWritable(node.context);
if (typeof property === "symbol")
throw new TypeError("Symbol writes are not supported");
if (Array.isArray(nodeBase(node)))
throw new TypeError("Overlay arrays cannot contain holes");
const key = String(property);
if (!objectHas(node, key))
return true;
node.appends?.delete(key);
deleteObjectWrite(node, key);
node.readded?.delete(key);
setObjectDeletion(node, key);
markDirty(node);
return true;
}
function hasProperty(node, property) {
assertReadable(node.context);
if (Array.isArray(nodeBase(node))) {
if (property === "length")
return true;
const index = arrayIndex(property);
if (index !== void 0)
return index < arrayLength(arrayOverlay(node));
return property in Array.prototype;
}
return typeof property === "symbol" ? property in nodeBase(node) : objectHas(node, String(property));
}
function ownKeys(node) {
assertReadable(node.context);
if (Array.isArray(nodeBase(node))) {
const length = arrayLength(arrayOverlay(node));
const keys2 = new Array(length + 1);
for (let index = 0; index < length; index++)
keys2[index] = String(index);
keys2[length] = "length";
return keys2;
}
let existingKeysOnly = node.deleteKey === void 0 && node.deletes === void 0 && node.readded === void 0 && (node.writeKey === void 0 || Object.hasOwn(nodeBase(node), node.writeKey));
if (existingKeysOnly && node.writes !== void 0) {
for (const key of node.writes.keys()) {
if (!Object.hasOwn(nodeBase(node), key)) {
existingKeysOnly = false;
break;
}
}
}
if (existingKeysOnly)
return Object.keys(nodeBase(node));
const keys = Object.keys(nodeBase(node)).filter((key) => !isObjectDeleted(node, key) && !node.readded?.has(key));
const seen = new Set(keys);
if (node.writeKey !== void 0 && !seen.has(node.writeKey)) {
keys.push(node.writeKey);
seen.add(node.writeKey);
}
if (node.writes !== void 0) {
for (const key of node.writes.keys()) {
if (seen.has(key))
continue;
keys.push(key);
seen.add(key);
}
}
const indices = [];
const strings = [];
for (const key of keys) {
const index = arrayIndex(key);
if (index === void 0)
strings.push(key);
else
indices.push(index);
}
indices.sort((left, right) => left - right);
return [...indices.map(String), ...strings];
}
function getDescriptor(node, property) {
assertReadable(node.context);
if (Array.isArray(nodeBase(node))) {
if (property === "length") {
const length = arrayLength(arrayOverlay(node));
node.target.length = length;
return Reflect.getOwnPropertyDescriptor(node.target, "length");
}
const index = arrayIndex(property);
if (index === void 0 || index >= arrayLength(arrayOverlay(node)))
return void 0;
} else {
if (typeof property === "symbol" || !objectHas(node, String(property)))
return void 0;
}
return {
configurable: true,
enumerable: true,
writable: node.context.status.value === "open",
value: getProperty(node, property)
};
}
function hasObjectWrite(node, key) {
return node.writeKey === key || (node.writes?.has(key) ?? false);
}
function setObjectWrite(node, key, value2) {
if (node.writes !== void 0) {
const reference = node.writes.get(key);
node.writes.set(key, reference === void 0 ? storeValue(node.context, value2) : replaceStoredValue(node.context, reference, value2));
return;
}
if (node.writeKey === void 0 || node.writeKey === key) {
node.writeKey = key;
node.writeValue = node.writeValue === void 0 ? storeValue(node.context, value2) : replaceStoredValue(node.context, node.writeValue, value2);
return;
}
node.writes = /* @__PURE__ */ new Map();
node.writes.set(node.writeKey, node.writeValue);
node.writes.set(key, storeValue(node.context, value2));
node.writeKey = void 0;
node.writeValue = void 0;
}
function deleteObjectWrite(node, key) {
if (node.writeKey === key) {
node.writeKey = void 0;
releaseStoredValue(node.context, node.writeValue);
node.writeValue = void 0;
} else {
const reference = node.writes?.get(key);
if (reference !== void 0)
releaseStoredValue(node.context, reference);
node.writes?.delete(key);
}
}
function isObjectDeleted(node, key) {
return node.deleteKey === key || (node.deletes?.has(key) ?? false);
}
function setObjectDeletion(node, key) {
if (node.deletes !== void 0) {
node.deletes.add(key);
return;
}
if (node.deleteKey === void 0 || node.deleteKey === key) {
node.deleteKey = key;
return;
}
node.deletes = /* @__PURE__ */ new Set();
node.deletes.add(node.deleteKey);
node.deletes.add(key);
node.deleteKey = void 0;
}
function deleteObjectDeletion(node, key) {
if (node.deleteKey === key)
node.deleteKey = void 0;
else
node.deletes?.delete(key);
}
function objectHas(node, key) {
if (isObjectDeleted(node, key))
return false;
return hasObjectWrite(node, key) || Object.hasOwn(nodeBase(node), key);
}
function objectValue(node, key) {
if (node.writeKey === key)
return storedValue(node.context, node.writeValue);
const reference = node.writes?.get(key);
if (reference !== void 0)
return storedValue(node.context, reference);
return nodeBase(node)[key];
}
function markDirty(node) {
if (node.dirty)
return;
node.dirty = true;
node.context.dirty.push(node);
for (let parent = nodeParent(node); parent !== void 0; parent = nodeParent(parent))
parent.subtreeDirty = true;
}
function arrayOverlay(node) {
if (node.array !== void 0)
return node.array;
const base = nodeBase(node);
const overlay = {
root: void 0,
pieces: void 0,
baseOverrides: void 0,
insertOverrides: void 0,
structural: false,
generation: 0,
plan: void 0,
seed: 2654435769,
locatedOffset: 0,
baseLocations: void 0,
insertLocations: void 0
};
if (base.length > 0)
overlay.root = createPieceNode(overlay, { kind: "base", start: 0, length: base.length, step: 1 });
node.array = overlay;
return overlay;
}
function baseOverridesForWrite(overlay) {
if (overlay.baseOverrides === void 0)
overlay.baseOverrides = /* @__PURE__ */ new Map();
return overlay.baseOverrides;
}
function insertOverridesForWrite(overlay) {
if (overlay.insertOverrides === void 0)
overlay.insertOverrides = /* @__PURE__ */ new Map();
return overlay.insertOverrides;
}
function nextPiecePriority(overlay) {
let value2 = overlay.seed;
value2 ^= value2 << 13;
value2 ^= value2 >>> 17;
value2 ^= value2 << 5;
overlay.seed = value2 >>> 0;
return overlay.seed;
}
function treeElements(node) {
return node?.elements ?? 0;
}
function updatePieceNode(node) {
node.elements = treeElements(node.left) + node.piece.length + treeElements(node.right);
}
function createPieceNode(overlay, piece) {
return { piece, left: void 0, right: void 0, priority: nextPiecePriority(overlay), elements: piece.length };
}
function mergePieceTrees(left, right) {
if (left === void 0)
return right;
if (right === void 0)
return left;
if (left.priority >= right.priority) {
left.right = mergePieceTrees(left.right, right);
updatePieceNode(left);
return left;
}
right.left = mergePieceTrees(left, right.left);
updatePieceNode(right);
return right;
}
function splitPieceTree(overlay, root2, index) {
if (root2 === void 0)
return [void 0, void 0];
const leftLength = treeElements(root2.left);
if (index < leftLength) {
const [left, right] = splitPieceTree(overlay, root2.left, index);
root2.left = right;
updatePieceNode(root2);
return [left, root2];
}
const pieceEnd = leftLength + root2.piece.length;
if (index > pieceEnd) {
const [left, right] = splitPieceTree(overlay, root2.right, index - pieceEnd);
root2.right = left;
updatePieceNode(root2);
return [root2, right];
}
if (index === leftLength) {
const left = root2.left;
root2.left = void 0;
updatePieceNode(root2);
return [left, root2];
}
if (index === pieceEnd) {
const right = root2.right;
root2.right = void 0;
updatePieceNode(root2);
return [root2, right];
}
const offset = index - leftLength;
const first = { ...root2.piece, length: offset };
const second = {
...root2.piece,
start: root2.piece.start + root2.piece.step * offset,
length: root2.piece.length - offset
};
return [
mergePieceTrees(root2.left, createPieceNode(overlay, first)),
mergePieceTrees(createPieceNode(overlay, second), root2.right)
];
}
function leftmostPieceNode(node) {
while (node.left !== void 0)
node = node.left;
return node;
}
function rightmostPieceNode(node) {
while (node.right !== void 0)
node = node.right;
return node;
}
function mergeablePieces(left, right) {
if (left.kind !== right.kind)
return false;
if (left.kind === "insert" && left.source !== right.source)
return false;
if (left.length === 1 && right.length === 1)
return Math.abs(right.start - left.start) === 1;
return left.step === right.step && left.start + left.step * left.length === right.start;
}
function joinNormalized(overlay, left, right) {
if (left === void 0)
return right;
if (right === void 0)
return left;
const leftPiece = rightmostPieceNode(left).piece;
const rightPiece = leftmostPieceNode(right).piece;
if (!mergeablePieces(leftPiece, rightPiece))
return mergePieceTrees(left, right);
const [leftRest] = splitPieceTree(overlay, left, treeElements(left) - leftPiece.length);
const [, rightRest] = splitPieceTree(overlay, right, rightPiece.length);
const step = leftPiece.length === 1 ? rightPiece.start - leftPiece.start : leftPiece.step;
const combined = leftPiece.kind === "base" ? { kind: "base", start: leftPiece.start, length: leftPiece.length + rightPiece.length, step } : {
kind: "insert",
source: leftPiece.source,
start: leftPiece.start,
length: leftPiece.length + rightPiece.length,
step
};
return joinNormalized(overlay, joinNormalized(overlay, leftRest, createPieceNode(overlay, combined)), rightRest);
}
function flattenPieceTree(node, output) {
if (node === void 0)
return;
flattenPieceTree(node.left, output);
output.push(node.piece);
flattenPieceTree(node.right, output);
}
function piecesOf(overlay) {
if (overlay.pieces === void 0) {
overlay.pieces = [];
flattenPieceTree(overlay.root, overlay.pieces);
}
return overlay.pieces;
}
function treeFromPieces(overlay, pieces) {
mergePieces(pieces);
let root2;
for (const piece of pieces)
root2 = mergePieceTrees(root2, createPieceNode(overlay, piece));
return root2;
}
function replaceAllPieces(overlay, pieces) {
overlay.root = treeFromPieces(overlay, pieces);
overlay.pieces = void 0;
overlay.baseLocations = void 0;
overlay.insertLocations = void 0;
}
function arrayLength(overlay) {
return treeElements(overlay.root);
}
function locatePiece(overlay, index) {
let node = overlay.root;
while (node !== void 0) {
const leftLength = treeElements(node.left);
if (index < leftLength)
node = node.left;
else if (index >= leftLength + node.piece.length) {
index -= leftLength + node.piece.length;
node = node.right;
} else {
overlay.locatedOffset = index - leftLength;
return node.piece;
}
}
throw new RangeError("Array overlay index is out of range");
}
function arrayIndex(property) {
if (typeof property !== "string" || property.length === 0 || property.length > 10)
return void 0;
if (property === "0")
return 0;
const first = property.charCodeAt(0);
if (first < 49 || first > 57)
return void 0;
let index = first - 48;
for (let offset = 1; offset < property.length; offset++) {
const digit = property.charCodeAt(offset) - 48;
if (digit < 0 || digit > 9)
return void 0;
index = index * 10 + digit;
if (index >= 4294967295)
return void 0;
}
return index;
}
function entryValueAt(node, piece, sourceIndex) {
const overlay = arrayOverlay(node);
if (piece.kind === "base") {
const valueIndex = overlay.baseOverrides?.get(sourceIndex);
return valueIndex === void 0 ? nodeBase(node)[sourceIndex] : storedValue(node.context, valueIndex);
}
const overrides = overlay.insertOverrides?.get(piece.source);
const reference = overrides?.has(sourceIndex) ? overrides.get(sourceIndex) : piece.source.refs[sourceIndex];
return storedValue(node.context, reference);
}
function hasEntryOverrideAt(overlay, piece, sourceIndex) {
return piece.kind === "base" ? overlay.baseOverrides?.has(sourceIndex) ?? false : overlay.insertOverrides?.get(piece.source)?.has(sourceIndex) ?? false;
}
function extendRightmostPiece(node, amount) {
if (node.right !== void 0)
extendRightmostPiece(node.right, amount);
else
node.piece.length += amount;
updatePieceNode(node);
}
function invalidatePieceCaches(overlay) {
overlay.pieces = void 0;
overlay.baseLocations = void 0;
overlay.insertLocations = void 0;
overlay.plan = void 0;
}
function replacePieceRange(node, index, remove, inserted) {
if (remove === 0 && inserted.length === 0)
return;
const overlay = arrayOverlay(node);
if (remove === 0 && index === arrayLength(overlay) && inserted.length === 1 && overlay.root !== void 0) {
const addition = inserted[0];
const tail = rightmostPieceNode(overlay.root).piece;
if (addition.kind === "insert" && tail.kind === "insert" && tail.step === 1 && tail.start + tail.length === tail.source.refs.length) {
for (let offset = 0; offset < addition.length; offset++) {
tail.source.refs.push(addition.source.refs[addition.start + offset]);
}
extendRightmostPiece(overlay.root, addition.length);
invalidatePieceCaches(overlay);
overlay.structural = true;
overlay.generation += 1;
markDirty(node);
return;
}
}
const [left, rest] = splitPieceTree(overlay, overlay.root, index);
const [, right] = splitPieceTree(overlay, rest, remove);
const middle = treeFromPieces(overlay, inserted);
overlay.root = joinNormalized(overlay, joinNormalized(overlay, left, middle), right);
invalidatePieceCaches(overlay);
overlay.structural = true;
overlay.generation += 1;
markDirty(node);
}
function mergePieces(pieces) {
for (let index = 1; index < pieces.length; ) {
const left = pieces[index - 1];
const right = pieces[index];
const sameSource = left.kind === right.kind && (left.kind === "base" || left.source === right.source);
if (sameSource && left.length === 1 && right.length === 1 && Math.abs(right.start - left.start) === 1) {
left.step = right.start - left.start;
left.length = 2;
pieces.splice(index, 1);
} else if (sameSource && left.step === right.step && left.start + left.step * left.length === right.start) {
left.length += right.length;
pieces.splice(index, 1);
} else
index += 1;
}
}
function insertPiece(node, items, start = 0) {
if (items.length === start)
return [];
const refs = [];
for (let index = start; index < items.length; index++)
refs.push(storeValue(node.context, items[index]));
return [{ kind: "insert", source: { refs }, start: 0, length: refs.length, step: 1 }];
}
function insertPlacementPiece(node, values, start = 0) {
if (values.length === start)
return [];
const storedLength = node.context.stored?.length ?? 0;
try {
for (let index = start; index < values.length; index++)
values[index] = storeValue(node.context, clonePlacement(values[index]));
} catch (error) {
if (node.context.stored !== void 0)
node.context.stored.length = storedLength;
throw error;
}
return [
{
kind: "insert",
source: { refs: values },
start,
length: values.length - start,
step: 1
}
];
}
function setArrayIndex(node, index, stored) {
const overlay = arrayOverlay(node);
const length = arrayLength(overlay);
if (index === length) {
replacePieceRange(node, length, 0, insertPiece(node, [stored]));
return;
}
const piece = locatePiece(overlay, index);
const sourceIndex = piece.start + piece.step * overlay.locatedOffset;
const current = entryValueAt(node, piece, sourceIndex);
if (!isContainer2(stored) && current === stored)
return;
if (piece.kind === "base") {
const existingIndex = overlay.baseOverrides?.get(sourceIndex);
if (!isContainer2(stored) && stored === nodeBase(node)[sourceIndex]) {
if (existingIndex !== void 0)
releaseStoredValue(node.context, existingIndex);
overlay.baseOverrides?.delete(sourceIndex);
} else if (existingIndex === void 0) {
baseOverridesForWrite(overlay).set(sourceIndex, storeValue(node.context, stored));
} else
overlay.baseOverrides.set(sourceIndex, replaceStoredValue(node.context, existingIndex, stored));
} else {
let overrides = overlay.insertOverrides?.get(piece.source);
const existingIndex = overrides?.get(sourceIndex);
if (!isContainer2(stored) && stored === storedValue(node.context, piece.source.refs[sourceIndex])) {
if (existingIndex !== void 0)
releaseStoredValue(node.context, existingIndex);
overrides?.delete(sourceIndex);
if (overrides?.size === 0)
overlay.insertOverrides?.delete(piece.source);
} else {
if (overrides === void 0) {
overrides = /* @__PURE__ */ new Map();
insertOverridesForWrite(overlay).set(piece.source, overrides);
}
if (existingIndex === void 0)
overrides.set(sourceIndex, storeValue(node.context, stored));
else
overrides.set(sourceIndex, replaceStoredValue(node.context, existingIndex, stored));
}
}
markDirty(node);
}
function setArrayLength(node, next) {
const current = arrayLength(arrayOverlay(node));
if (next === current)
return;
if (next < current)
replacePieceRange(node, next, current - next, []);
else
replacePieceRange(node, current, 0, insertPiece(node, Array.from({ length: next - current }, () => null)));
}
function toArrayLength(value2) {
const number2 = Number(value2);
if (!Number.isInteger(number2) || number2 < 0 || number2 >= 4294967296)
throw new RangeError("Invalid array length");
return number2;
}
function toIntegerOrInfinity(value2) {
const number2 = Number(value2);
if (Number.isNaN(number2) || number2 === 0)
return 0;
return Number.isFinite(number2) ? Math.trunc(number2) : number2;
}
function clampIndex(value2, length) {
if (value2 === Number.NEGATIVE_INFINITY)
return 0;
if (value2 < 0)
return Math.max(length + value2, 0);
return Math.min(value2, length);
}
function mutatorNode(receiver) {
if (!isContainer2(receiver))
return void 0;
const node = Reflect.get(receiver, NODE);
if (node === void 0)
return void 0;
if (!Array.isArray(nodeBase(node)))
throw new TypeError("Array mutator called on incompatible receiver");
assertWritable(node.context);
return node;
}
var arrayMutators = {
push(...items) {
const node = mutatorNode(this);
if (node === void 0)
return Reflect.apply(Array.prototype.push, this, items);
const length = arrayLength(arrayOverlay(node));
replacePieceRange(node, length, 0, insertPlacementPiece(node, items));
return length + items.length;
},
pop() {
const node = mutatorNode(this);
if (node === void 0)
return Reflect.apply(Array.prototype.pop, this, []);
const length = arrayLength(arrayOverlay(node));
if (length === 0)
return void 0;
const value2 = getArrayIndex(node, length - 1);
replacePieceRange(node, length - 1, 1, []);
return value2;
},
shift() {
const node = mutatorNode(this);
if (node === void 0)
return Reflect.apply(Array.prototype.shift, this, []);
const length = arrayLength(arrayOverlay(node));
if (length === 0)
return void 0;
const value2 = getArrayIndex(node, 0);
replacePieceRange(node, 0, 1, []);
return value2;
},
unshift(...items) {
const node = mutatorNode(this);
if (node === void 0)
return Reflect.apply(Array.prototype.unshift, this, items);
replacePieceRange(node, 0, 0, insertPlacementPiece(node, items));
return arrayLength(arrayOverlay(node));
},
splice(...args) {
const node = mutatorNode(this);
if (node === void 0)
return Reflect.apply(Array.prototype.splice, this, args);
const length = arrayLength(arrayOverlay(node));
const start = args.length === 0 ? 0 : clampIndex(toIntegerOrInfinity(args[0]), length);
const remove = args.length === 0 ? 0 : args.length === 1 ? length - start : Math.min(Math.max(toIntegerOrInfinity(args[1]), 0), length - start);
const removed = Array.from({ length: remove }, (_, offset) => getArrayIndex(node, start + offset));
const itemStart = Math.min(2, args.length);
const itemCount = Math.max(args.length - 2, 0);
replacePieceRange(node, start, remove, insertPlacementPiece(node, args, itemStart));
setArrayLength(node, length - remove + itemCount);
return removed;
},
reverse() {
const node = mutatorNode(this);
if (node === void 0)
return Reflect.apply(Array.prototype.reverse, this, []);
const overlay = arrayOverlay(node);
if (arrayLength(overlay) < 2)
return node.proxy;
const pieces = [...piecesOf(overlay)].reverse();
for (const piece of pieces) {
piece.start += piece.step * (piece.length - 1);
piece.step = piece.step === 1 ? -1 : 1;
}
replaceAllPieces(overlay, pieces);
overlay.structural = true;
overlay.generation += 1;
overlay.plan = void 0;
markDirty(node);
return node.proxy;
},
sort(comparator) {
const node = mutatorNode(this);
if (node === void 0)
return Reflect.apply(Array.prototype.sort, this, [comparator]);
if (comparator !== void 0 && typeof comparator !== "function")
throw new TypeError("Comparator must be a function");
const overlay = arrayOverlay(node);
const insertedSources = [];
const insertedIndices = [];
const insertedValues = [];
const baseValues = new Array(nodeBase(node).length);
const order = [];
for (const piece of piecesOf(overlay)) {
for (let offset = 0; offset < piece.length; offset++) {
const sourceIndex = piece.start + piece.step * offset;
if (piece.kind === "base") {
order.push(sourceIndex);
baseValues[sourceIndex] = publicSortValue(node, sourceIndex, insertedSources, insertedIndices);
} else {
insertedSources.push(piece.source);
insertedIndices.push(sourceIndex);
const token = -insertedSources.length;
order.push(token);
insertedValues.push(publicSortValue(node, token, insertedSources, insertedIndices));
}
}
}
const baseSnapshot = /* @__PURE__ */ new Map();
for (const [index, valueIndex] of overlay.baseOverrides ?? [])
baseSnapshot.set(index, storedValue(node.context, valueIndex));
const insertSnapshots = /* @__PURE__ */ new Map();
for (const [source, overrides] of overlay.insertOverrides ?? []) {
const snapshot = /* @__PURE__ */ new Map();
for (const [index, valueIndex] of overrides)
snapshot.set(index, storedValue(node.context, valueIndex));
insertSnapshots.set(source, snapshot);
}
const generation = overlay.generation;
order.sort((left, right) => {
const leftValue = left < 0 ? insertedValues[-left - 1] : baseValues[left];
const rightValue = right < 0 ? insertedValues[-right - 1] : baseValues[right];
if (typeof comparator === "function")
return Number(comparator(leftValue, rightValue));
const a = String(leftValue);
const b = String(rightValue);
return a < b ? -1 : a > b ? 1 : 0;
});
if (baseSnapshot.size > 0 || insertSnapshots.size > 0 || (overlay.baseOverrides?.size ?? 0) > 0 || (overlay.insertOverrides?.size ?? 0) > 0) {
for (const token of order) {
restoreSortOverride(node, token, insertedSources, insertedIndices, baseSnapshot, insertSnapshots);
}
}
const comparatorWasStructural = overlay.generation !== generation;
const currentLength = arrayLength(overlay);
const samePrefix = currentLength >= order.length && order.every((token, index) => sameSortTokenAt(overlay, index, token, insertedSources, insertedIndices));
if (!samePrefix) {
replacePieceRange(node, 0, Math.min(order.length, currentLength), piecesFromSortOrder(order, insertedSources, insertedIndices));
}
if (comparatorWasStructural)
deduplicateArrayEntries(node);
return node.proxy;
},
fill(supplied, startArg, endArg) {
const node = mutatorNode(this);
if (node === void 0)
return Reflect.apply(Array.prototype.fill, this, [supplied, startArg, endArg]);
const length = arrayLength(arrayOverlay(node));
const start = startArg === void 0 ? 0 : clampIndex(toIntegerOrInfinity(startArg), length);
const end = endArg === void 0 ? length : clampIndex(toIntegerOrInfinity(endArg), length);
if (end <= start)
return node.proxy;
const items = Array.from({ length: end - start }, () => clonePlacement(supplied));
replacePieceRange(node, start, end - start, insertPiece(node, items));
return node.proxy;
},
copyWithin(targetArg, startArg, endArg) {
const node = mutatorNode(this);
if (node === void 0)
return Reflect.apply(Array.prototype.copyWithin, this, [targetArg, startArg, endArg]);
const length = arrayLength(arrayOverlay(node));
const target = clampIndex(toIntegerOrInfinity(targetArg), length);
const start = clampIndex(toIntegerOrInfinity(startArg), length);
const end = endArg === void 0 ? length : clampIndex(toIntegerOrInfinity(endArg), length);
const count = Math.min(Math.max(end - start, 0), length - target);
const values = Array.from({ length: count }, (_, offset) => clonePlacement(getArrayIndex(node, start + offset)));
replacePieceRange(node, target, count, insertPiece(node, values));
return node.proxy;
}
};
function sortTokenSource(token, sources) {
return token < 0 ? sources[-token - 1] : void 0;
}
function sortTokenIndex(token, indices) {
return token < 0 ? indices[-token - 1] : token;
}
function publicSortValue(node, token, sources, indices) {
const overlay = arrayOverlay(node);
const source = sortTokenSource(token, sources);
const sourceIndex = sortTokenIndex(token, indices);
const overrideIndex = source === void 0 ? overlay.baseOverrides?.get(sourceIndex) : overlay.insertOverrides?.get(source)?.get(sourceIndex);
const value2 = overrideIndex !== void 0 ? storedValue(node.context, overrideIndex) : source === void 0 ? nodeBase(node)[sourceIndex] : storedValue(node.context, source.refs[sourceIndex]);
if (!isContainer2(value2))
return value2;
return createNode(node.context, value2, node, source === void 0 ? 1 : 2, sourceIndex, source, source !== void 0 || (overlay.baseOverrides?.has(sourceIndex) ?? false)).proxy;
}
function restoreSortOverride(node, token, sources, indices, baseSnapshot, insertSnapshots) {
const overlay = arrayOverlay(node);
const source = sortTokenSource(token, sources);
const sourceIndex = sortTokenIndex(token, indices);
if (source === void 0) {
const existingIndex2 = overlay.baseOverrides?.get(sourceIndex);
const snapshotValue2 = baseSnapshot.get(sourceIndex);
if (snapshotValue2 !== void 0) {
if (existingIndex2 === void 0)
baseOverridesForWrite(overlay).set(sourceIndex, storeValue(node.context, snapshotValue2));
else
overlay.baseOverrides.set(sourceIndex, replaceStoredValue(node.context, existingIndex2, snapshotValue2));
} else {
if (existingIndex2 !== void 0)
releaseStoredValue(node.context, existingIndex2);
overlay.baseOverrides?.delete(sourceIndex);
}
return;
}
let overrides = overlay.insertOverrides?.get(source);
const existingIndex = overrides?.get(sourceIndex);
const snapshotValue = insertSnapshots.get(source)?.get(sourceIndex);
if (snapshotValue !== void 0) {
if (overrides === void 0) {
overrides = /* @__PURE__ */ new Map();
insertOverridesForWrite(overlay).set(source, overrides);
}
if (existingIndex === void 0)
overrides.set(sourceIndex, storeValue(node.context, snapshotValue));
else
overrides.set(sourceIndex, replaceStoredValue(node.context, existingIndex, snapshotValue));
} else {
if (existingIndex !== void 0)
releaseStoredValue(node.context, existingIndex);
overrides?.delete(sourceIndex);
if (overrides?.size === 0)
overlay.insertOverrides?.delete(source);
}
}
function sameSortTokenAt(overlay, logicalIndex, token, sources, indices) {
const piece = locatePiece(overlay, logicalIndex);
const sourceIndex = piece.start + piece.step * overlay.locatedOffset;
const tokenSource = sortTokenSource(token, sources);
return sourceIndex === sortTokenIndex(token, indices) && (piece.kind === "base" && tokenSource === void 0 || piece.kind === "insert" && piece.source === tokenSource);
}
function deduplicateArrayEntries(node) {
const overlay = arrayOverlay(node);
const seenBase = /* @__PURE__ */ new Set();
const seenInsert = /* @__PURE__ */ new Map();
const next = [];
let duplicated = false;
for (const piece of piecesOf(overlay)) {
for (let offset = 0; offset < piece.length; offset++) {
const sourceIndex = piece.start + piece.step * offset;
let seen;
if (piece.kind === "base") {
seen = seenBase.has(sourceIndex);
seenBase.add(sourceIndex);
} else {
let indices = seenInsert.get(piece.source);
if (indices === void 0) {
indices = /* @__PURE__ */ new Set();
seenInsert.set(piece.source, indices);
}
seen = indices.has(sourceIndex);
indices.add(sourceIndex);
}
if (seen) {
duplicated = true;
appendMergedPiece(next, insertPiece(node, [clonePlacementStored(entryValueAt(node, piece, sourceIndex), node.context)])[0]);
} else
appendMergedPiece(next, singletonPiece(piece, sourceIndex));
}
}
if (!duplicated)
return;
replaceAllPieces(overlay, next);
overlay.structural = true;
overlay.generation += 1;
overlay.plan = void 0;
markDirty(node);
}
function piecesFromSortOrder(order, sources, indices) {
const pieces = [];
for (const token of order) {
const source = token < 0 ? sources[-token - 1] : void 0;
const sourceIndex = token < 0 ? indices[-token - 1] : token;
const previous = pieces.at(-1);
const sameSource = previous !== void 0 && (source === void 0 && previous.kind === "base" || source !== void 0 && previous.kind === "insert" && previous.source === source);
if (previous !== void 0 && sameSource) {
if (previous.length === 1) {
const step = sourceIndex - previous.start;
if (step === 1 || step === -1) {
previous.step = step;
previous.length = 2;
continue;
}
} else if (previous.start + previous.step * previous.length === sourceIndex) {
previous.length += 1;
continue;
}
}
pieces.push(source === void 0 ? { kind: "base", start: sourceIndex, length: 1, step: 1 } : { kind: "insert", source, start: sourceIndex, length: 1, step: 1 });
}
return pieces;
}
function appendMergedPiece(pieces, piece) {
const previous = pieces.at(-1);
const sameSource = previous !== void 0 && previous.kind === piece.kind && (previous.kind === "base" || previous.source === piece.source);
if (previous !== void 0 && sameSource && previous.length === 1 && piece.length === 1) {
const step = piece.start - previous.start;
if (step === 1 || step === -1) {
previous.step = step;
previous.length = 2;
return;
}
}
if (previous !== void 0 && sameSource && previous.step === piece.step && previous.start + previous.step * previous.length === piece.start) {
previous.length += piece.length;
} else
pieces.push(piece);
}
function singletonPiece(piece, sourceIndex) {
return piece.kind === "base" ? { kind: "base", start: sourceIndex, length: 1, step: 1 } : { kind: "insert", source: piece.source, start: sourceIndex, length: 1, step: 1 };
}
function clonePlacement(value2) {
const proxyNode = isContainer2(value2) ? Reflect.get(value2, NODE) : void 0;
return proxyNode === void 0 ? copyJson(value2) : clonePlacementNode(proxyNode);
}
function cloneNode(node) {
assertReadable(node.context);
if (Array.isArray(nodeBase(node))) {
const overlay = arrayOverlay(node);
const result2 = [];
for (const piece of piecesOf(overlay)) {
for (let offset = 0; offset < piece.length; offset++) {
const sourceIndex = piece.start + piece.step * offset;
result2.push(cloneStored(entryValueAt(node, piece, sourceIndex), node.context));
}
}
return result2;
}
const result = Object.create(Object.getPrototypeOf(nodeBase(node)));
for (const key of ownKeys(node))
defineData3(result, key, cloneStored(objectValue(node, key), node.context));
return result;
}
function cloneStored(value2, context) {
if (!isContainer2(value2))
return value2;
const node = context.rawNodes?.get(value2);
return node === void 0 || !node.dirty && !node.subtreeDirty ? value2 : cloneNode(node);
}
function clonePlacementNode(node) {
assertReadable(node.context);
if (Array.isArray(nodeBase(node))) {
const overlay = arrayOverlay(node);
const result2 = [];
for (const piece of piecesOf(overlay)) {
for (let offset = 0; offset < piece.length; offset++) {
const sourceIndex = piece.start + piece.step * offset;
result2.push(clonePlacementStored(entryValueAt(node, piece, sourceIndex), node.context));
}
}
return result2;
}
const result = Object.create(Object.getPrototypeOf(nodeBase(node)));
for (const key of ownKeys(node))
defineData3(result, key, clonePlacementStored(objectValue(node, key), node.context));
return result;
}
function clonePlacementStored(value2, context) {
if (!isContainer2(value2))
return copyJson(value2);
const node = context.rawNodes?.get(value2);
return node === void 0 ? copyJson(value2) : clonePlacementNode(node);
}
function defineData3(target, key, value2) {
DATA_DESCRIPTOR3.value = value2;
Object.defineProperty(target, key, DATA_DESCRIPTOR3);
DATA_DESCRIPTOR3.value = void 0;
}
function emitOperations(context) {
const simple = emitSimpleObjectOperations(context);
if (simple !== void 0)
return simple;
const operations = [];
const forcedFolds = /* @__PURE__ */ new Map();
const emissionPaths = /* @__PURE__ */ new Map();
const denseIndices = /* @__PURE__ */ new Map();
for (const node of context.dirty) {
recordDenseArrayPosition(node, denseIndices);
if (Array.isArray(nodeBase(node))) {
const overlay = arrayOverlay(node);
if (!overlay.structural && (overlay.baseOverrides?.size ?? 0) > 0) {
let candidates = denseIndices.get(node);
if (candidates === void 0) {
candidates = { indices: [], bits: void 0, length: nodeBase(node).length };
denseIndices.set(node, candidates);
}
for (const index of overlay.baseOverrides.keys())
addDenseCandidate(candidates, index);
}
}
}
const denseRegions = /* @__PURE__ */ new Map();
for (const [array, candidates] of denseIndices) {
const path3 = resolvePath(array);
if (path3 === void 0 || path3.some((segment) => typeof segment === "string" && RESERVED_SEGMENTS.has(segment))) {
continue;
}
const regions = buildDenseRegions(candidates);
if (regions.length > 0)
denseRegions.set(array, regions);
}
for (const node of context.dirty) {
const path3 = resolvePath(node);
if (path3 === void 0)
continue;
if (hasCoveringDenseRegion(node, path3, denseRegions))
continue;
emissionPaths.set(node, path3);
if (!Array.isArray(nodeBase(node)) && hasReservedMutation(node))
forcedFolds.set(node, path3);
const reservedAt = path3.findIndex((segment) => typeof segment === "string" && RESERVED_SEGMENTS.has(segment));
if (reservedAt >= 0) {
let ancestor = node;
for (let depth = path3.length; depth > reservedAt; depth--)
ancestor = nodeParent(ancestor);
forcedFolds.set(ancestor, path3.slice(0, reservedAt));
}
}
for (const [node, path3] of forcedFolds)
emissionPaths.set(node, path3);
for (const node of denseRegions.keys()) {
const path3 = resolvePath(node);
if (path3 !== void 0 && !hasCoveringDenseRegion(node, path3, denseRegions))
emissionPaths.set(node, path3);
}
let maxDepth = 0;
for (const path3 of emissionPaths.values())
maxDepth = Math.max(maxDepth, path3.length);
const buckets = Array.from({ length: maxDepth + 1 }, () => []);
for (const [node, path3] of emissionPaths)
buckets[path3.length].push(node);
const folded = /* @__PURE__ */ new Set();
for (const bucket of buckets) {
for (const node of bucket) {
const path3 = emissionPaths.get(node);
if (hasPlacementAncestor(node) || hasFoldedAncestor(node, folded))
continue;
if (forcedFolds.has(node)) {
emitSet(operations, path3, cloneNode(node));
folded.add(node);
continue;
}
if (Array.isArray(nodeBase(node)))
emitArrayOperations(node, path3, operations, denseRegions.get(node));
else
emitObjectOperations(node, path3, operations);
if (operations.length > MAX_DELTA_OPERATIONS) {
locatedDenseArray = void 0;
return [["r", cloneNode(context.root)]];
}
}
}
locatedDenseArray = void 0;
return operations;
}
function emitSimpleObjectOperations(context) {
const nodes = [];
for (const node of context.dirty) {
if (Array.isArray(nodeBase(node)) || hasReservedMutation(node) || hasPlacementAncestor(node))
return void 0;
for (let parent = nodeParent(node); parent !== void 0; parent = nodeParent(parent)) {
if (Array.isArray(nodeBase(parent)))
return void 0;
}
const path3 = resolvePath(node);
if (path3 === void 0)
continue;
for (const segment of path3) {
if (typeof segment === "string" && RESERVED_SEGMENTS.has(segment))
return void 0;
}
nodes.push(node);
if (nodes.length > MAX_SIMPLE_OBJECT_NODES)
return void 0;
}
for (let index = 1; index < nodes.length; index++) {
const node = nodes[index];
const depth = node.preparedPath.length;
let at = index;
while (at > 0 && nodes[at - 1].preparedPath.length > depth) {
nodes[at] = nodes[at - 1];
at -= 1;
}
nodes[at] = node;
}
const operations = [];
let canMaterializeDirectly = true;
for (const node of nodes) {
if (emitObjectOperations(node, node.preparedPath, operations))
canMaterializeDirectly = false;
if (operations.length > MAX_DELTA_OPERATIONS)
return [["r", cloneNode(context.root)]];
}
context.simpleObjectMaterialization = canMaterializeDirectly;
return operations;
}
var locatedDenseArray;
var locatedDenseIndex = 0;
function locateDenseArrayPosition(node) {
let child = node;
for (let parent = nodeParent(child); parent !== void 0; parent = nodeParent(child)) {
if (Array.isArray(nodeBase(parent))) {
const overlay = arrayOverlay(parent);
if (child.parentKind !== 1 || overlay.structural)
return false;
const sourceIndex = child.parentKey;
const valueIndex = overlay.baseOverrides?.get(sourceIndex);
const current = valueIndex === void 0 ? nodeBase(parent)[sourceIndex] : storedValue(parent.context, valueIndex);
if (current !== nodeBase(child))
return false;
locatedDenseArray = parent;
locatedDenseIndex = sourceIndex;
return true;
}
child = parent;
}
return false;
}
function hasCoveringDenseRegion(node, path3, denseRegions) {
for (let parent = nodeParent(node); parent !== void 0; parent = nodeParent(parent)) {
const regions = denseRegions.get(parent);
if (regions === void 0)
continue;
const parentPath = resolvePath(parent);
if (parentPath === void 0 || path3.length <= parentPath.length)
continue;
let matches = true;
for (let index2 = 0; index2 < parentPath.length; index2++) {
if (path3[index2] !== parentPath[index2]) {
matches = false;
break;
}
}
if (!matches)
continue;
const index = path3[parentPath.length];
if (typeof index === "number" && regionContaining(regions, index))
return true;
}
return false;
}
function addDenseCandidate(candidates, index) {
if (candidates.bits !== void 0) {
candidates.bits[index] = 1;
return;
}
candidates.indices.push(index);
if (candidates.indices.length < 256)
return;
candidates.bits = new Uint8Array(candidates.length);
for (const existing of candidates.indices)
candidates.bits[existing] = 1;
candidates.indices.length = 0;
}
function recordDenseArrayPosition(node, groups) {
if (!locateDenseArrayPosition(node))
return;
let candidates = groups.get(locatedDenseArray);
if (candidates === void 0) {
candidates = { indices: [], bits: void 0, length: nodeBase(locatedDenseArray).length };
groups.set(locatedDenseArray, candidates);
}
addDenseCandidate(candidates, locatedDenseIndex);
}
function buildDenseRegions(candidates) {
if (candidates.bits === void 0)
return [];
const regions = [];
const bits = candidates.bits;
for (let at = 0; at < bits.length; ) {
while (at < bits.length && bits[at] === 0)
at += 1;
if (at === bits.length)
break;
const start = at;
let end = at;
let count = 0;
let gap = 0;
while (at < bits.length) {
if (bits[at] !== 0) {
count += 1;
end = at;
gap = 0;
} else if (++gap > 1)
break;
at += 1;
}
const length = end - start + 1;
if (count >= 256 && count * 2 >= length)
regions.push({ start, length });
}
return regions;
}
function regionContaining(regions, index) {
for (const region of regions)
if (index >= region.start && index < region.start + region.length)
return true;
return false;
}
function hasReservedMutation(node) {
if (node.writeKey !== void 0 && RESERVED_SEGMENTS.has(node.writeKey))
return true;
if (node.deleteKey !== void 0 && RESERVED_SEGMENTS.has(node.deleteKey))
return true;
if (node.writes !== void 0) {
for (const key of node.writes.keys())
if (RESERVED_SEGMENTS.has(key))
return true;
}
if (node.deletes !== void 0) {
for (const key of node.deletes)
if (RESERVED_SEGMENTS.has(key))
return true;
}
return false;
}
function hasFoldedAncestor(node, folded) {
for (let parent = nodeParent(node); parent !== void 0; parent = nodeParent(parent))
if (folded.has(parent))
return true;
return false;
}
function hasPlacementAncestor(node) {
for (let current = node; current !== void 0; current = nodeParent(current)) {
if (nodeParent(current) !== void 0 && current.parentPlacement)
return true;
}
return false;
}
function emitObjectWrite(node, path3, operations, key, value2) {
const nextPath = [...path3, key];
const appended = node.appends?.get(key);
if (appended !== void 0) {
operations.push(["a", nextPath, appended]);
return false;
}
const before = node.readded?.has(key) || !Object.hasOwn(nodeBase(node), key) ? void 0 : nodeBase(node)[key];
const after = cloneStored(value2, node.context);
const emitted2 = emitChangedValue(operations, nextPath, before, after);
return isContainer2(before) && isContainer2(after) && !emitted2;
}
function emitObjectOperations(node, path3, operations) {
if (node.readded !== void 0) {
for (const key of node.readded) {
if (Object.hasOwn(nodeBase(node), key))
operations.push(["d", [...path3, key]]);
}
}
let normalizedContainerWrite = false;
if (node.writeKey !== void 0)
normalizedContainerWrite = emitObjectWrite(node, path3, operations, node.writeKey, objectValue(node, node.writeKey));
if (node.writes !== void 0) {
for (const [key, valueIndex] of node.writes) {
if (operations.length > MAX_DELTA_OPERATIONS)
return normalizedContainerWrite;
if (emitObjectWrite(node, path3, operations, key, storedValue(node.context, valueIndex)))
normalizedContainerWrite = true;
}
}
if (node.deleteKey !== void 0 && Object.hasOwn(nodeBase(node), node.deleteKey)) {
operations.push(["d", [...path3, node.deleteKey]]);
}
if (node.deletes !== void 0) {
for (const key of node.deletes) {
if (operations.length > MAX_DELTA_OPERATIONS)
return normalizedContainerWrite;
if (Object.hasOwn(nodeBase(node), key))
operations.push(["d", [...path3, key]]);
}
}
return normalizedContainerWrite;
}
function buildArrayPlan(node) {
const overlay = arrayOverlay(node);
if (overlay.plan !== void 0)
return overlay.plan;
const base = nodeBase(node);
const pieces = piecesOf(overlay);
overlay.plan = orderedArrayPlan(base.length, pieces) ?? elementArrayPlan(base.length, pieces);
return overlay.plan;
}
function orderedArrayPlan(baseLength, pieces) {
const ranges = [];
for (const piece of pieces) {
if (piece.kind !== "base" || piece.length === 0)
continue;
if (piece.step !== 1 && piece.length > 1)
return void 0;
if (ranges.length > 0 && piece.start <= ranges[ranges.length - 1])
return void 0;
ranges.push(piece.start, piece.start + piece.length - 1);
}
const removeRuns = [];
let end = baseLength;
for (let index = ranges.length - 2; index >= -2; index -= 2) {
const start = index >= 0 ? ranges[index + 1] + 1 : 0;
if (end > start)
removeRuns.push(start, end - start);
if (index >= 0)
end = ranges[index];
}
return { removeRuns, permutation: void 0, insertRuns: insertRunsOf(pieces) };
}
function elementArrayPlan(baseLength, pieces) {
const retained = new Uint8Array(baseLength);
const targetBase = [];
for (const piece of pieces) {
if (piece.kind !== "base")
continue;
for (let offset = 0; offset < piece.length; offset++) {
const index = piece.start + piece.step * offset;
retained[index] = 1;
targetBase.push(index);
}
}
const removeRuns = [];
for (let end = baseLength; end > 0; ) {
if (retained[end - 1] !== 0) {
end -= 1;
continue;
}
let start = end - 1;
while (start > 0 && retained[start - 1] === 0)
start -= 1;
removeRuns.push(start, end - start);
end = start;
}
const retainedBase = [];
for (let index = 0; index < retained.length; index++)
if (retained[index] !== 0)
retainedBase.push(index);
let permutation;
if (targetBase.some((value2, index) => value2 !== retainedBase[index])) {
const positions = new Map(retainedBase.map((value2, index) => [value2, index]));
permutation = targetBase.map((value2) => positions.get(value2));
}
return { removeRuns, permutation, insertRuns: insertRunsOf(pieces) };
}
function insertRunsOf(pieces) {
const insertRuns = [];
let logicalIndex = 0;
for (let pieceIndex = 0; pieceIndex < pieces.length; ) {
const piece = pieces[pieceIndex];
if (piece.kind === "base") {
logicalIndex += piece.length;
pieceIndex += 1;
continue;
}
const startPiece = pieceIndex;
while (pieceIndex < pieces.length && pieces[pieceIndex].kind === "insert") {
logicalIndex += pieces[pieceIndex].length;
pieceIndex += 1;
}
insertRuns.push(logicalIndex - rangeLength(pieces, startPiece, pieceIndex), startPiece, pieceIndex);
}
return insertRuns;
}
function rangeLength(pieces, start, end) {
let length = 0;
for (let index = start; index < end; index++)
length += pieces[index].length;
return length;
}
function emitArrayOperations(node, path3, operations, denseRegions) {
const overlay = arrayOverlay(node);
const base = nodeBase(node);
if (denseRegions !== void 0) {
for (const region of denseRegions) {
if (operations.length > MAX_DELTA_OPERATIONS)
return;
operations.push(["p", path3, region.start, region.length, cloneArrayRegion(node, region)]);
}
}
if (overlay.structural) {
const plan = buildArrayPlan(node);
for (let index = 0; index < plan.removeRuns.length; index += 2) {
if (operations.length > MAX_DELTA_OPERATIONS)
return;
operations.push(["p", path3, plan.removeRuns[index], plan.removeRuns[index + 1], []]);
}
if (plan.permutation !== void 0)
operations.push(["m", path3, plan.permutation]);
const pieces = piecesOf(overlay);
for (let run2 = 0; run2 < plan.insertRuns.length; run2 += 3) {
if (operations.length > MAX_DELTA_OPERATIONS)
return;
const logicalIndex = plan.insertRuns[run2];
const items = [];
for (let pieceIndex = plan.insertRuns[run2 + 1]; pieceIndex < plan.insertRuns[run2 + 2]; pieceIndex++) {
const piece = pieces[pieceIndex];
for (let offset = 0; offset < piece.length; offset++) {
const sourceIndex = piece.start + piece.step * offset;
items.push(cloneStored(entryValueAt(node, piece, sourceIndex), node.context));
}
}
operations.push(["p", path3, logicalIndex, 0, items]);
}
}
for (const [baseIndex, valueIndex] of overlay.baseOverrides ?? []) {
if (operations.length > MAX_DELTA_OPERATIONS)
return;
const index = findEntryIndex(overlay, 1, baseIndex, void 0);
if (index === void 0 || denseRegions !== void 0 && regionContaining(denseRegions, index))
continue;
emitChangedValue(operations, [...path3, index], base[baseIndex], cloneStored(storedValue(node.context, valueIndex), node.context));
}
}
function cloneArrayRegion(node, region) {
const overlay = arrayOverlay(node);
const result = [];
for (let index = region.start; index < region.start + region.length; index++) {
const piece = locatePiece(overlay, index);
const sourceIndex = piece.start + piece.step * overlay.locatedOffset;
result.push(cloneStored(entryValueAt(node, piece, sourceIndex), node.context));
}
return result;
}
function emitChangedValue(operations, path3, before, after) {
if (!isContainer2(after) && before === after)
return false;
if (isContainer2(before) && isContainer2(after) && equalTrustedJson(before, after))
return false;
if (typeof before === "string" && typeof after === "string") {
if (after.length > before.length && after.slice(0, before.length) === before) {
operations.push(["a", path3, ownedSlice2(after, before.length)]);
return true;
}
const shared = overlap(before, after, 65536);
if (shared > 0) {
operations.push(["t", path3, before.length - shared]);
if (after.length > shared)
operations.push(["a", path3, ownedSlice2(after, shared)]);
return true;
}
}
operations.push(["s", path3, after]);
return true;
}
function emitSet(operations, path3, value2) {
if (path3.length === 0)
operations.push(["r", value2]);
else
operations.push(["s", path3, value2]);
}
function resolvePath(node) {
if (node.preparedPath !== void 0)
return node.preparedPath;
const parent = nodeParent(node);
if (parent === void 0) {
node.preparedPath = [];
return node.preparedPath;
}
const parentPath = resolvePath(parent);
if (parentPath === void 0)
return void 0;
if (node.parentKind === 0) {
const key = node.parentKey;
if (!objectHas(parent, key) || objectValue(parent, key) !== nodeBase(node))
return void 0;
node.preparedPath = [...parentPath, key];
return node.preparedPath;
}
const overlay = arrayOverlay(parent);
const index = findEntryIndex(overlay, node.parentKind, node.parentKey, node.parentSource);
if (index === void 0)
return void 0;
const piece = locatePiece(overlay, index);
if (entryValueAt(parent, piece, node.parentKey) !== nodeBase(node))
return void 0;
node.preparedPath = [...parentPath, index];
return node.preparedPath;
}
function ensurePieceLocations(overlay) {
if (overlay.baseLocations !== void 0)
return;
overlay.baseLocations = [];
overlay.insertLocations = /* @__PURE__ */ new Map();
let logicalStart = 0;
for (const piece of piecesOf(overlay)) {
const last = piece.start + piece.step * (piece.length - 1);
const location = {
piece,
logicalStart,
minimum: Math.min(piece.start, last),
maximum: Math.max(piece.start, last)
};
if (piece.kind === "base")
overlay.baseLocations.push(location);
else {
let locations = overlay.insertLocations.get(piece.source);
if (locations === void 0) {
locations = [];
overlay.insertLocations.set(piece.source, locations);
}
locations.push(location);
}
logicalStart += piece.length;
}
const byMinimum = (left, right) => left.minimum - right.minimum;
overlay.baseLocations.sort(byMinimum);
for (const locations of overlay.insertLocations.values())
locations.sort(byMinimum);
}
function findEntryIndex(overlay, kind, sourceIndex, source) {
if (kind === 1 && !overlay.structural)
return sourceIndex;
ensurePieceLocations(overlay);
const locations = kind === 1 ? overlay.baseLocations : overlay.insertLocations.get(source);
if (locations === void 0)
return void 0;
let low = 0;
let high = locations.length;
while (low < high) {
const middle = low + high >>> 1;
if (locations[middle].minimum <= sourceIndex)
low = middle + 1;
else
high = middle;
}
const location = locations[low - 1];
if (location === void 0 || sourceIndex > location.maximum)
return void 0;
const offset = (sourceIndex - location.piece.start) / location.piece.step;
return offset >= 0 && offset < location.piece.length ? location.logicalStart + offset : void 0;
}
function ensureOperations(context) {
if (context.ops !== void 0)
return context.ops;
assertReadable(context);
if (context.replacement) {
const base = context.tracker.deref()?.replacementBase(context);
context.replacementNoop = base !== void 0 && equalTrustedJson(base, nodeBase(context.root));
context.ops = context.replacementNoop ? [] : [["r", nodeBase(context.root)]];
} else
context.ops = emitOperations(context);
return context.ops;
}
function equalTrustedJson(left, right) {
if (left === right)
return true;
if (!isContainer2(left) || !isContainer2(right) || Array.isArray(left) !== Array.isArray(right))
return false;
if (Array.isArray(left)) {
const other2 = right;
if (left.length !== other2.length)
return false;
for (let index = 0; index < left.length; index++)
if (!equalTrustedJson(left[index], other2[index]))
return false;
return true;
}
const other = right;
const keys = Object.keys(left);
if (keys.length !== Object.keys(other).length)
return false;
for (const key of keys)
if (!Object.hasOwn(other, key) || !equalTrustedJson(left[key], other[key]))
return false;
return true;
}
function abortContext(context) {
if (context.status.value === "aborted" || context.status.value === "consumed" || context.status.value === "stale")
return;
context.status.value = "aborted";
clearContext(context);
}
function releaseOverlayReferences(context) {
context.tracker.deref()?.releaseContext(context);
if (locatedDenseArray?.context === context)
locatedDenseArray = void 0;
context.overlayReleased = true;
context.dirty.length = 0;
context.nodes.length = 0;
context.rawNodes = void 0;
context.ops = void 0;
context.root = void 0;
context.bases = void 0;
context.stored = void 0;
context.baseValue = void 0;
}
function clearContext(context) {
context.tracker.deref()?.releaseContext(context);
if (locatedDenseArray?.context === context)
locatedDenseArray = void 0;
for (const node of context.nodes) {
if (Array.isArray(node.target))
node.target.length = 0;
Reflect.deleteProperty(node.target, NODE);
node.writes?.clear();
node.deletes?.clear();
node.readded?.clear();
if (node.array?.pieces !== void 0)
node.array.pieces.length = 0;
if (node.array !== void 0) {
node.array.root = void 0;
node.array.baseLocations = void 0;
node.array.insertLocations = void 0;
}
node.array?.baseOverrides?.clear();
node.array?.insertOverrides?.clear();
node.parentSource = void 0;
node.target = RELEASED;
node.proxy = RELEASED;
node.writeKey = void 0;
node.writeValue = void 0;
node.writes = void 0;
node.deleteKey = void 0;
node.deletes = void 0;
node.readded = void 0;
node.array = void 0;
node.subtreeDirty = void 0;
node.preparedPath = void 0;
}
context.dirty.length = 0;
context.nodes.length = 0;
context.rawNodes = void 0;
context.ops = void 0;
context.root = void 0;
context.bases = void 0;
context.stored = void 0;
context.baseValue = void 0;
context.overlayReleased = true;
}
function isContainer2(value2) {
return value2 !== null && typeof value2 === "object";
}
// node_modules/@earendil-works/chord/dist/delta/pending.js
var MAX_PENDING_OPS = 1e4;
var EMPTY2 = { kind: "empty" };
var REPLACE = { kind: "replace" };
var NO_OPS = { kind: "ops", ops: [] };
var REPLACE_TAKE = { kind: "replace" };
var PendingOps = class {
#state = EMPTY2;
/** Queue the ops of one commit. */
push(ops2) {
if (ops2.length === 0)
return;
const state2 = this.#state;
if (ops2[0][0] === "r") {
this.#state = { kind: "batch", ops: ops2 };
return;
}
switch (state2.kind) {
case "empty":
this.#state = { kind: "batch", ops: ops2 };
return;
case "batch": {
const folding = { kind: "folding", ops: [], leaves: /* @__PURE__ */ new Map() };
this.#state = folding;
if (this.#fold(state2.ops, folding))
this.#fold(ops2, folding);
return;
}
case "folding":
this.#fold(ops2, state2);
return;
case "replace":
return;
}
}
/**
* Pending ops after folding; 1 once overflowed (the replacement the owner sends). One batch is counted as received,
* so a single commit larger than `MAX_PENDING_OPS` counts in full until a second one arrives and overflows.
*/
get size() {
const state2 = this.#state;
if (state2.kind === "empty")
return 0;
return state2.kind === "replace" ? 1 : state2.ops.length;
}
/** Hand over everything pending and start empty. */
take() {
const state2 = this.#state;
this.#state = EMPTY2;
switch (state2.kind) {
case "empty":
return NO_OPS;
case "batch":
case "folding":
return { kind: "ops", ops: state2.ops };
case "replace":
return REPLACE_TAKE;
}
}
/** Fold `ops` into `folding`; false once the queue overflowed into `replace`. */
#fold(ops2, folding) {
for (const op2 of ops2) {
switch (op2[0]) {
case "r":
folding.ops.length = 0;
folding.leaves.clear();
break;
case "a":
if (mergeLeaf(op2, folding))
continue;
break;
case "s":
if (isPrimitive(op2[2])) {
if (mergeLeaf(op2, folding))
continue;
} else if (folding.leaves.size > 0)
folding.leaves.clear();
break;
default:
if (folding.leaves.size > 0)
folding.leaves.clear();
}
folding.ops.push(op2);
if (folding.ops.length > MAX_PENDING_OPS) {
this.#state = REPLACE;
return false;
}
}
return true;
}
};
var isPrimitive = (value2) => value2 === null || typeof value2 !== "object";
function mergeLeaf(op2, folding) {
const key = pathKey(op2[1]);
const at = folding.leaves.get(key);
if (at !== void 0) {
const merged = merge2(folding.ops[at], op2);
if (merged !== void 0) {
folding.ops[at] = merged;
return true;
}
}
folding.leaves.set(key, folding.ops.length);
return false;
}
function pathKey(path3) {
return JSON.stringify(path3);
}
function merge2(previous, next) {
if (next[0] === "s")
return next;
if (previous[0] === "a")
return ["a", previous[1], previous[2] + next[2]];
if (typeof previous[2] === "string")
return ["s", previous[1], previous[2] + next[2]];
return void 0;
}
// node_modules/@earendil-works/chord/dist/delta/index.js
var isObj2 = (value2) => value2 !== null && typeof value2 === "object";
function overlap(a, b, scan, probe = 64, maxCandidates = 8) {
if (a.length === 0 || b.length === 0 || scan === 0)
return 0;
const tail = a.length > scan ? a.slice(a.length - scan) : a;
for (const h of [Math.min(probe, b.length), 1]) {
const head = b.slice(0, h);
let tried = 0;
for (let k = tail.indexOf(head); k !== -1; k = tail.indexOf(head, k + 1)) {
if (++tried > maxCandidates)
break;
const n = tail.length - k;
if (n <= b.length && tail.slice(k) === b.slice(0, n))
return n;
}
if (h === 1)
break;
}
return 0;
}
function ownedSlice2(text2, start, end = text2.length) {
return `${text2.slice(start, end)} `.slice(0, -1);
}
var RESERVED_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
var UnsafePathError = class extends Error {
// Not a parameter property: Node's --experimental-strip-types rejects those,
// and these files are meant to run under it directly.
segment;
constructor(segment) {
super(`unsafe path segment: ${String(segment)}`);
this.segment = segment;
this.name = "UnsafePathError";
}
};
function assertValidOp(op2) {
if (!Array.isArray(op2) || op2.length === 0)
throw new TypeError("op is not a tuple");
switch (op2[0]) {
case "r":
if (op2.length !== 2)
throw new TypeError("r arity");
return;
case "s":
if (op2.length !== 3)
throw new TypeError("s arity");
assertPathArg(op2[1], true);
return;
case "d":
if (op2.length !== 2)
throw new TypeError("d arity");
assertPathArg(op2[1], true);
return;
case "a":
if (op2.length !== 3 || typeof op2[2] !== "string")
throw new TypeError("a shape");
assertPathArg(op2[1], true);
return;
case "t":
if (op2.length !== 3 || !Number.isInteger(op2[2]) || op2[2] < 0)
throw new TypeError("t shape");
assertPathArg(op2[1], true);
return;
case "p": {
if (op2.length !== 5)
throw new TypeError("p arity");
assertPathArg(op2[1]);
if (!Number.isInteger(op2[2]) || op2[2] < 0)
throw new TypeError("p index");
if (!Number.isInteger(op2[3]) || op2[3] < 0)
throw new TypeError("p remove");
if (!Array.isArray(op2[4]))
throw new TypeError("p items");
return;
}
case "m":
if (op2.length !== 3)
throw new TypeError("m arity");
assertPathArg(op2[1]);
assertPermutation(op2[2]);
return;
// Silently skipping an unknown verb is how a newer producer's op vanishes.
default:
throw new TypeError(`unknown op verb: ${String(op2[0])}`);
}
}
function assertPathArg(p, nonEmpty = false) {
if (!Array.isArray(p))
throw new TypeError("path is not an array");
if (nonEmpty && p.length === 0)
throw new TypeError("path is empty");
assertSafePath(p);
}
function assertPermutation(value2) {
if (!Array.isArray(value2))
throw new TypeError("m permutation is not an array");
const seen = new Uint8Array(value2.length);
for (const index of value2) {
if (!Number.isInteger(index) || index < 0 || index >= value2.length || seen[index] !== 0) {
throw new TypeError("m permutation is not a bijection");
}
seen[index] = 1;
}
}
function assertSafePath(path3) {
for (const seg of path3) {
if (typeof seg === "string") {
if (RESERVED_SEGMENTS.has(seg))
throw new UnsafePathError(seg);
} else if (!Number.isInteger(seg) || seg < 0) {
throw new UnsafePathError(seg);
}
}
}
function assertIndexInRange(parent, index) {
if (index > parent.length)
throw new UnsafePathError(index);
}
var PathError = class extends Error {
path;
constructor(path3) {
super(`unresolvable path: ${JSON.stringify(path3)}`);
this.path = path3;
this.name = "PathError";
}
};
function apply(target, ops2) {
return applyOps(target, ops2);
}
function applyOps(target, ops2) {
let root2 = target;
for (const op2 of ops2) {
assertValidOp(op2);
if (op2[0] === "r") {
root2 = op2[1];
continue;
}
const path3 = op2[1];
assertSafePath(path3);
if (op2[0] === "p") {
const target_ = path3.length === 0 ? root2 : resolve(root2, path3);
if (!Array.isArray(target_))
throw new PathError(path3);
target_.splice(op2[2], op2[3]);
const chunkSize = 1e4;
for (let offset = 0; offset < op2[4].length; offset += chunkSize) {
target_.splice(op2[2] + offset, 0, ...op2[4].slice(offset, offset + chunkSize));
}
continue;
}
if (op2[0] === "m") {
const target_ = path3.length === 0 ? root2 : resolve(root2, path3);
if (!Array.isArray(target_) || target_.length !== op2[2].length)
throw new PathError(path3);
const previous = target_.slice();
for (let index = 0; index < op2[2].length; index++)
target_[index] = previous[op2[2][index]];
continue;
}
const parent = resolve(root2, path3.slice(0, -1));
const key = path3[path3.length - 1];
if (Array.isArray(parent)) {
if (typeof key !== "number")
throw new UnsafePathError(key);
assertIndexInRange(parent, key);
}
const write = (value2) => {
Object.defineProperty(parent, key, { value: value2, writable: true, enumerable: true, configurable: true });
};
const read2 = () => Object.hasOwn(parent, key) ? parent[key] : void 0;
switch (op2[0]) {
case "s":
write(op2[2]);
break;
case "d":
if (Array.isArray(parent)) {
if (typeof key !== "number" || key >= parent.length)
throw new PathError(path3);
parent.splice(key, 1);
} else
delete parent[key];
break;
case "a": {
const current = read2();
if (typeof current !== "string")
throw new PathError(path3);
write(`${current}${op2[2]}`);
break;
}
case "t": {
const current = read2();
if (typeof current !== "string")
throw new PathError(path3);
write(current.slice(op2[2]));
break;
}
}
}
return root2;
}
function applyImmutable(target, ops2) {
return applyImmutableBatches(target, [ops2]);
}
function applyImmutableBatches(target, batches) {
let root2 = target;
const owned = /* @__PURE__ */ new WeakSet();
for (const ops2 of batches) {
for (const op2 of ops2) {
assertValidOp(op2);
if (op2[0] === "r") {
root2 = op2[1];
continue;
}
if (op2[0] === "p") {
const appended = appendCopy(root2, op2, owned);
if (appended !== void 0) {
root2 = appended;
continue;
}
}
root2 = copyContainers(root2, op2[0] === "p" || op2[0] === "m" ? op2[1] : op2[1].slice(0, -1), owned);
root2 = applyOps(root2, [op2]);
}
}
return root2;
}
function appendCopy(root2, op2, owned) {
const [, path3, index, deleteCount, items] = op2;
if (deleteCount !== 0)
return void 0;
let target = root2;
for (const segment of path3) {
const valid = typeof segment === "string" ? !RESERVED_SEGMENTS.has(segment) && isObj2(target) && !Array.isArray(target) : Number.isInteger(segment) && segment >= 0 && Array.isArray(target);
if (!valid || !Object.hasOwn(target, segment))
return void 0;
target = target[segment];
}
if (!Array.isArray(target) || owned.has(target) || index !== target.length)
return void 0;
const appended = target.concat(items);
owned.add(appended);
if (path3.length === 0)
return appended;
const parentPath = path3.slice(0, -1);
const copiedRoot = copyContainers(root2, parentPath, owned);
Object.defineProperty(resolve(copiedRoot, parentPath), path3[path3.length - 1], {
value: appended,
writable: true,
enumerable: true,
configurable: true
});
return copiedRoot;
}
function copyContainers(root2, path3, owned) {
const copy2 = (value2) => {
if (Array.isArray(value2))
return value2.slice();
if (!isObj2(value2))
throw new PathError(path3);
return Object.getPrototypeOf(value2) === null ? Object.assign(/* @__PURE__ */ Object.create(null), value2) : { ...value2 };
};
if (!isObj2(root2))
throw new PathError(path3);
let copiedRoot;
if (owned.has(root2))
copiedRoot = root2;
else {
copiedRoot = copy2(root2);
owned.add(copiedRoot);
}
let destination = copiedRoot;
for (const segment of path3) {
if (!Object.hasOwn(destination, segment))
throw new PathError(path3);
if (Array.isArray(destination) && typeof segment !== "number")
throw new UnsafePathError(segment);
const child = destination[segment];
if (!isObj2(child))
throw new PathError(path3);
if (owned.has(child)) {
destination = child;
continue;
}
const copiedChild = copy2(child);
Object.defineProperty(destination, segment, {
value: copiedChild,
writable: true,
enumerable: true,
configurable: true
});
owned.add(copiedChild);
destination = copiedChild;
}
return copiedRoot;
}
function resolveValue(root2, path3) {
let node = root2;
for (const seg of path3) {
if (!isObj2(node))
throw new PathError(path3);
if (Array.isArray(node) && typeof seg !== "number")
throw new UnsafePathError(seg);
if (!Object.hasOwn(node, seg))
throw new PathError(path3);
node = node[seg];
}
return node;
}
function resolve(root2, path3) {
const node = resolveValue(root2, path3);
if (!isObj2(node))
throw new PathError(path3);
return node;
}
// node_modules/@earendil-works/chord/dist/watch.js
var STOPPED = { kind: "stopped" };
var ABORTED = { kind: "aborted" };
var ENDED = { kind: "ended" };
var WatchLifecycle = class {
#detach;
#report;
#closed = Promise.withResolvers();
#value;
#listener;
#started = false;
#scheduled = false;
#running = false;
/** Set by `endAfterDelivery()`: the source sends nothing more; the watch ends `ended` once it delivered the rest. */
#ending = false;
/** Set once, by `#terminate()`. */
#end;
#abortSignal;
#abortListener;
constructor(value2, detach, report2) {
this.#value = value2;
this.#detach = detach;
this.#report = report2;
}
get value() {
return this.#value;
}
get closed() {
return this.#closed.promise;
}
start(listener) {
if (this.#started)
throw new Error("Watch is already started");
if (this.#end !== void 0)
throw new Error("Watch is stopped");
this.#started = true;
this.#listener = listener;
this.#schedule();
}
stop() {
this.#terminate(STOPPED);
return this.#closed.promise;
}
/** End the watch `aborted` when `signal` aborts; installed once. */
observeAbort(signal) {
if (this.#abortSignal !== void 0)
throw new Error("Watch abort is already installed");
if (this.#end !== void 0)
return;
this.#abortSignal = signal;
this.#abortListener = () => this.abort();
signal.addEventListener("abort", this.#abortListener, { once: true });
if (signal.aborted)
this.abort();
}
/** End the watch `aborted`: its acquisition context was aborted. */
abort() {
this.#terminate(ABORTED);
}
/**
* End the watch with `end` at once, dropping what is pending: the source closed (`ended`), or failed for good
* (`failed`). A failure the source may recover from is a `failed` call instead (`fail()`).
*/
end(end) {
this.#terminate(end);
}
/**
* The source sends nothing more after its last frames, such as a retirement: take no more frames, deliver what is
* pending, then end `ended`, after the running call returns, if one runs. Until then the watch stays attached, so
* `end()`, `stop()`, an abort, and a throwing listener still end it first; a watch never started keeps what is
* pending until one of them or `start()`.
*/
endAfterDelivery() {
if (this.#end !== void 0 || this.#ending)
return;
this.#ending = true;
if (!this.#running && this.pendingContext === void 0)
this.#terminate(ENDED);
}
/** Whether the watch still takes frames: it has not ended, and its source has not ended. */
get open() {
return this.#end === void 0 && !this.#ending;
}
/** Something became pending: deliver it once started, never inline. */
pending() {
if (this.#started)
this.#schedule();
}
#schedule() {
if (this.#scheduled || this.#running || this.#end !== void 0)
return;
this.#scheduled = true;
queueMicrotask(() => {
this.#scheduled = false;
void this.#drain();
});
}
/**
* Deliver until nothing is pending; what arrives during a call is taken after it returns. A watch whose source ended
* ends once it delivered the rest and its last call returned.
*/
async #drain() {
if (this.#running || this.#end !== void 0 || !this.#started)
return;
this.#running = true;
try {
while (this.#end === void 0) {
const listener = this.#listener;
if (listener === void 0)
break;
const frameContext = this.pendingContext;
if (frameContext === void 0) {
if (this.#ending)
this.#terminate(ENDED);
break;
}
const call = this.next();
if (call.kind === "value")
this.#value = call.value;
try {
await listener(call, withoutAbortSignal(frameContext));
} catch (error) {
if (this.#end === void 0) {
this.#report?.(error);
this.#terminate({ kind: "listener_error", error: toError(error) });
}
break;
}
}
} finally {
this.#running = false;
}
}
/**
* End the watch, once: detach, drop what is pending and every reference into the source, and settle `closed`. A
* callback already running keeps running.
*/
#terminate(end) {
if (this.#end !== void 0)
return;
this.#end = end;
const detach = this.#detach;
this.#detach = void 0;
this.#report = void 0;
this.#listener = void 0;
this.release();
if (this.#abortListener !== void 0)
this.#abortSignal?.removeEventListener("abort", this.#abortListener);
this.#abortSignal = void 0;
this.#abortListener = void 0;
detach?.();
this.#closed.resolve(end);
}
};
function toError(error) {
if (error instanceof Error)
return error;
try {
return new Error(String(error));
} catch {
return new Error(Object.prototype.toString.call(error));
}
}
var Watch = class extends WatchLifecycle {
#ops = new PendingOps();
/**
* The source's call while it is the only frame pending: the call passes it on, with no allocation. A second frame
* drops it, so its ops stay only as long as `PendingOps` keeps them (folded, or dropped by an overflow).
*/
#lone;
/** The newest frame's value and context, while a call is pending; the context also marks that one is. */
#newestValue;
#newestContext;
/** A pending frame was a retirement. */
#retired = false;
/** The newest frame was a failure: the next call is this. */
#failure;
/** A failure came after the last value call: the next value call replaces the root, and ops are not kept. */
#replace = false;
/**
* Queue the frame `call`. A value's ops turn the previous value into it, and `retired` says the document the watch
* follows was retired, which the next value call reports however many frames it folds; a failure is `fail()`.
*/
advance(call, context) {
if (call.kind === "failed") {
this.#fail(call, context);
return;
}
if (!this.open)
return;
if (this.#replace) {
this.#failure = void 0;
} else {
this.#lone = this.#newestContext === void 0 ? call : void 0;
this.#ops.push(call.ops);
}
this.#newestValue = call.value;
this.#newestContext = context;
if (call.retired)
this.#retired = true;
this.pending();
}
/**
* Queue a failure the source may recover from: the pending frames are dropped (`value` keeps the last delivered
* value), the listener gets `{ kind: "failed", error }`, and the next value arrives as `[["r", value]]`.
*/
fail(error, context) {
this.#fail({ kind: "failed", error }, context);
}
#fail(call, context) {
if (!this.open)
return;
this.#ops.take();
this.#lone = void 0;
this.#newestValue = void 0;
this.#failure = call;
this.#newestContext = context;
this.#replace = true;
this.pending();
}
get pendingContext() {
return this.#newestContext;
}
next() {
if (this.#replace)
return this.#nextAfterFailure();
const lone = this.#lone;
const value2 = this.#newestValue;
const batch = this.#ops.take();
const retired = this.#retired;
this.#lone = void 0;
this.#newestValue = void 0;
this.#newestContext = void 0;
this.#retired = false;
if (lone !== void 0)
return lone;
const ops2 = batch.kind === "ops" ? batch.ops : [["r", value2]];
return { kind: "value", value: value2, ops: ops2, retired };
}
/** The pending failure, or the value after one as a root replacement (no ops were kept since the failure). */
#nextAfterFailure() {
const failure = this.#failure;
this.#newestContext = void 0;
if (failure !== void 0) {
this.#failure = void 0;
return failure;
}
const value2 = this.#newestValue;
const retired = this.#retired;
this.#newestValue = void 0;
this.#retired = false;
this.#replace = false;
return { kind: "value", value: value2, ops: [["r", value2]], retired };
}
release() {
this.#ops.take();
this.#lone = void 0;
this.#newestValue = void 0;
this.#newestContext = void 0;
this.#retired = false;
this.#failure = void 0;
this.#replace = false;
}
};
// node_modules/@earendil-works/pi-durable/dist/ids.js
function idFromNumber(value2) {
return value2;
}
function seqFromNumber(value2) {
return value2;
}
// node_modules/@earendil-works/pi-durable/dist/documents.js
function defineDoc(definition) {
validateDefinition(definition);
return { definition };
}
function defineDocFamily(definition) {
validateDefinition(definition);
return { definition };
}
function validateDefinition(definition) {
if (!Number.isSafeInteger(definition.version) || definition.version < 1) {
throw new TypeError(`Document ${definition.kind} version must be a positive integer`);
}
}
function resolveAddress(definition, args) {
let index = 0;
let scope;
switch (definition.scope) {
case "session":
scope = { kind: "session" };
break;
case "conversation":
scope = { kind: "conversation", conversationId: ownerId(args[index++], definition) };
break;
case "task":
scope = { kind: "task", taskId: ownerId(args[index++], definition) };
break;
}
const key = definition.family === true ? args[index++] : void 0;
const address = key === void 0 ? { kind: definition.kind, scope } : { kind: definition.kind, scope, key };
return { address, id: addressId(address), nextArgument: index };
}
function ownerId(value2, definition) {
if (typeof value2 !== "number" || !Number.isSafeInteger(value2)) {
throw new TypeError(`Document ${definition.kind} requires a ${definition.scope} ID`);
}
return idFromNumber(value2);
}
function addressId(address) {
const owner = address.scope.kind === "session" ? null : address.scope.kind === "conversation" ? address.scope.conversationId : address.scope.taskId;
return JSON.stringify([address.kind, address.scope.kind, owner, address.key ?? null]);
}
function documentCreate(definition, address, id) {
const key = address.key === void 0 ? {} : { key: address.key };
switch (address.scope.kind) {
case "session":
return { id, kind: address.kind, ...key, scope: address.scope };
case "task":
return { id, kind: address.kind, ...key, scope: address.scope };
case "conversation":
return {
id,
kind: address.kind,
...key,
scope: address.scope,
history: definition.history,
fork: definition.fork
};
}
}
function checkRecordScope(definition, record) {
if (record.scope.kind !== definition.scope || record.scope.kind === "conversation" && (record.history !== definition.history || record.fork !== definition.fork)) {
throw new TypeError(`Document ${record.id} (${record.kind}) does not match the supplied definition semantics`);
}
}
function checkRecordVersion(definition, record, version) {
if (version > definition.version) {
throw new Error(`Document ${record.id} (${record.kind}) has newer version ${version} than ${definition.version}`);
}
if (version < definition.version && definition.migrate === void 0) {
throw new Error(`Document ${record.id} (${record.kind}) requires migration from version ${version}`);
}
}
function materializeDocument(definition, stored) {
return materializeDocumentValue(definition, stored.record, stored.version, stored.value);
}
function materializeDocumentValue(definition, record, version, value2) {
checkRecordScope(definition, record);
checkRecordVersion(definition, record, version);
if (version === definition.version)
return value2;
return copyJson(definition.migrate(value2, version));
}
// node_modules/@earendil-works/pi-durable/dist/entries.js
function defineEntry(kind) {
if (typeof kind !== "string" || kind.length === 0)
throw new TypeError("Entry kind must be a non-empty string");
return {
kind,
is: (entry2) => entry2 !== void 0 && entry2.kind === kind
};
}
var UserEntry = defineEntry("pi.user");
var AssistantEntry = defineEntry("pi.assistant");
var SystemEntry = defineEntry("pi.system");
var ToolResultEntry = defineEntry("pi.tool-result");
var ResetEntry = defineEntry("pi.reset");
var CompactionEntry = defineEntry("pi.compaction");
// node_modules/@earendil-works/pi-durable/dist/errors.js
function errorMessage2(error) {
if (error instanceof Error)
return error.message;
try {
return String(error);
} catch {
return Object.prototype.toString.call(error);
}
}
var ReadAfterWrite = class extends Error {
/** `operation` names the call, such as `Tx.task()`. */
constructor(operation) {
super(`${operation} cannot read tables after the first table write`);
this.name = "ReadAfterWrite";
}
};
var StorageRequestError = class extends Error {
constructor(message) {
super(message);
this.name = "StorageRequestError";
}
};
var SessionFailed = class extends Error {
constructor(cause) {
super("Session failed after a storage error; close and reopen it", { cause });
this.name = "SessionFailed";
}
};
var ReadOnlySession = class extends Error {
constructor(what) {
super(`Read-only Harness: ${what} refused`);
this.name = "ReadOnlySession";
}
};
var ConversationBusy = class extends Error {
conversationId;
constructor(conversationId) {
super(`Conversation ${conversationId} is busy`);
this.name = "ConversationBusy";
this.conversationId = conversationId;
}
};
var ConversationIdle = class extends Error {
conversationId;
constructor(conversationId) {
super(`Conversation ${conversationId} is idle`);
this.name = "ConversationIdle";
this.conversationId = conversationId;
}
};
// node_modules/@earendil-works/pi-durable/dist/timers.js
var MAX_TIMER_DELAY = 2147483647;
var inWorkers = typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers";
var nativeTimer = (callback, delayMs, options) => {
if (options.background && inWorkers)
return void 0;
const arm = (remaining) => {
const next = setTimeout(() => {
if (remaining > MAX_TIMER_DELAY)
handle = arm(remaining - MAX_TIMER_DELAY);
else
callback();
}, Math.min(remaining, MAX_TIMER_DELAY));
if (options.background)
next.unref?.();
return next;
};
let handle = arm(Math.max(0, delayMs));
if (options.background && typeof handle.unref !== "function") {
clearTimeout(handle);
return void 0;
}
return () => clearTimeout(handle);
};
function hostTimers(setTimer, report2) {
const arm = setTimer ?? nativeTimer;
let reported = false;
const fallBack = (error) => {
if (reported)
return;
reported = true;
report2(error);
};
return {
foreground: (callback, delayMs) => {
try {
const disarm = arm(callback, delayMs, { background: false });
if (disarm !== void 0)
return disarm;
fallBack(new Error("HarnessOptions.setTimer declined a timer that paces work; using setTimeout"));
} catch (error) {
fallBack(error);
}
return nativeTimer(callback, delayMs, { background: false });
},
background: (callback, delayMs) => {
try {
return arm(callback, delayMs, { background: true });
} catch (error) {
report2(error);
return void 0;
}
}
};
}
// node_modules/@earendil-works/pi-durable/dist/session/cached-storage.js
var CachedStorage = class {
#storage;
#conversations = new Lru(4096);
/** Live (non-terminal) task records, until their task ends. */
#liveTasks = /* @__PURE__ */ new Map();
/**
* Tasks some task waits on, or waited on until its wait ended and it has not moved on since: how many such waits name
* each, and its ended record once it ended.
*/
#awaited = /* @__PURE__ */ new Map();
/** Per task that waits, or left its wait and has not changed since: what it waited on, and whether it left. */
#waits = /* @__PURE__ */ new Map();
// Ended task records carry inputs and outcomes, such as a tool call's arguments, so fewer are kept.
#tasks = new Lru(256);
#submissions = new Lru(256);
/** Per record with a read in flight: the reads, and how many published commits wrote it since the first began. */
#reads = /* @__PURE__ */ new Map();
constructor(storage) {
this.#storage = storage;
}
/** The backend's own scope for a publication (`Storage.publishing`), when it has one. */
get publishing() {
return scopeOf(this.#storage);
}
/** Pass the batches through; the Session applies each one with `published()` when it publishes it. */
commit(batches, receive, context) {
return this.#storage.commit(batches, receive, context);
}
/**
* Apply a batch `commit()` stored, when the Session publishes it. Its records are frozen in place and kept as
* they are, no copies: the Session's components that follow the publication, such as the scheduler's live tasks,
* hold the same objects, so a live task's record is in memory once.
*/
published(writes) {
for (const write of writes) {
switch (write.type) {
case "conversation":
this.#wrote(write.value.id);
this.#conversations.set(write.value.id, freeze(write.value));
break;
case "task":
this.#wrote(write.value.id);
this.#followWait(write.value);
this.#keepTask(freeze(write.value));
break;
case "submission":
this.#wrote(write.value.id);
this.#submissions.set(write.value.id, freeze(write.value));
break;
}
}
}
mintId() {
return this.#storage.mintId();
}
conversation(id, context) {
const cached = this.#conversations.get(id);
if (cached !== void 0)
return Promise.resolve(cached);
return this.#keep(id, () => this.#storage.conversation(id, context), (record) => this.#conversations.set(id, record));
}
scanConversations(query, limit2, cursor, context) {
return this.#storage.scanConversations(query, limit2, cursor, context);
}
entry(first, second, third) {
if (third === void 0)
return this.#storage.entry(first, second);
return this.#storage.entry(first, second, third);
}
findLatestHeadMarker(conversationId, atOrBeforeEntryId, context) {
return this.#storage.findLatestHeadMarker(conversationId, atOrBeforeEntryId, context);
}
scanEntries(query, limit2, cursor, context) {
return this.#storage.scanEntries(query, limit2, cursor, context);
}
task(id, context) {
const cached = this.#liveTasks.get(id) ?? this.#awaited.get(id)?.record ?? this.#tasks.get(id);
if (cached !== void 0)
return Promise.resolve(cached);
return this.#keep(id, () => this.#storage.task(id, context), (record) => this.#keepTask(record));
}
scanTasks(query, limit2, cursor, context) {
return this.#storage.scanTasks(query, limit2, cursor, context);
}
/** Cached as written only: this process writes every submission it settles, and a read one is usually settled. */
submission(id, context) {
const cached = this.#submissions.get(id);
return cached === void 0 ? this.#storage.submission(id, context) : Promise.resolve(cached);
}
scanSubmissions(query, limit2, cursor, context) {
return this.#storage.scanSubmissions(query, limit2, cursor, context);
}
submissionByRequest(conversationId, requestId, context) {
return this.#storage.submissionByRequest(conversationId, requestId, context);
}
findDocument(address, at, context) {
return this.#storage.findDocument(address, at, context);
}
document(id, at, context) {
return this.#storage.document(id, at, context);
}
scanDocuments(query, limit2, cursor, context) {
return this.#storage.scanDocuments(query, limit2, cursor, context);
}
close(context) {
return this.#storage.close(context);
}
/** Records kept per table, for tests that bound memory. */
get sizes() {
return {
conversations: this.#conversations.size,
tasks: this.#tasks.size,
liveTasks: this.#liveTasks.size,
awaited: this.#awaited.size,
waits: this.#waits.size,
submissions: this.#submissions.size
};
}
/** Keep a frozen task record: a live one until its task ends, an ended one in the bounded table. */
#keepTask(record) {
if (record.state.status === "terminal") {
this.#liveTasks.delete(record.id);
const awaited = this.#awaited.get(record.id);
if (awaited !== void 0)
awaited.record = record;
else
this.#tasks.set(record.id, record);
return;
}
this.#tasks.delete(record.id);
this.#liveTasks.set(record.id, record);
}
/**
* Follow a task's waits from its written record: a wait holds the ended records of its `on` until the task, after
* leaving the wait, changes again (or ends), as the phase that resumes reads their outcomes before its next commit.
*/
#followWait(record) {
const wait = this.#waits.get(record.id);
if (record.state.status === "waiting") {
if (wait !== void 0)
this.#release(wait.on);
const on = record.state.on;
this.#waits.set(record.id, { on, left: false });
for (const id of on) {
let awaited = this.#awaited.get(id);
if (awaited === void 0) {
const ended = this.#tasks.get(id);
this.#tasks.delete(id);
awaited = ended === void 0 ? { count: 0 } : { count: 0, record: ended };
this.#awaited.set(id, awaited);
}
awaited.count++;
}
return;
}
if (wait === void 0)
return;
if (!wait.left && record.state.status !== "terminal") {
wait.left = true;
return;
}
this.#waits.delete(record.id);
this.#release(wait.on);
}
/** A wait on `on` is over: what no other wait names goes back to the bounded table. */
#release(on) {
for (const id of on) {
const awaited = this.#awaited.get(id);
if (--awaited.count > 0)
continue;
this.#awaited.delete(id);
if (awaited.record !== void 0)
this.#tasks.set(id, awaited.record);
}
}
/** A published commit wrote record `id`: a read of it in flight may have missed that. */
#wrote(id) {
const reads = this.#reads.get(id);
if (reads !== void 0)
reads.version++;
}
/** Resolve with a read's result, frozen; keep a found record unless a commit published since wrote it. */
async #keep(id, read2, keep) {
let reads = this.#reads.get(id);
if (reads === void 0) {
reads = { count: 0, version: 0 };
this.#reads.set(id, reads);
}
reads.count++;
const version = reads.version;
let value2;
try {
value2 = await read2();
} finally {
if (--reads.count === 0)
this.#reads.delete(id);
}
if (value2 === void 0)
return void 0;
freeze(value2);
if (reads.version === version)
keep(value2);
return value2;
}
/** Records with a read in flight, for tests that bound memory. */
get readsInFlight() {
return this.#reads.size;
}
};
function scopeOf(storage) {
if (storage.publishing === void 0)
return void 0;
return (publish2, context) => storage.publishing(publish2, context);
}
var Lru = class {
#map = /* @__PURE__ */ new Map();
#capacity;
constructor(capacity) {
this.#capacity = capacity;
}
get(key) {
const value2 = this.#map.get(key);
if (value2 === void 0)
return void 0;
this.#map.delete(key);
this.#map.set(key, value2);
return value2;
}
get size() {
return this.#map.size;
}
delete(key) {
this.#map.delete(key);
}
set(key, value2) {
this.#map.delete(key);
this.#map.set(key, value2);
if (this.#map.size > this.#capacity)
this.#map.delete(this.#map.keys().next().value);
}
};
function freeze(value2) {
if (value2 === null || typeof value2 !== "object" || Object.isFrozen(value2))
return value2;
for (const child of Object.values(value2))
freeze(child);
return Object.freeze(value2);
}
// node_modules/@earendil-works/pi-durable/dist/session/conversation-tails.js
var LATEST_CAPACITY = 4096;
var MARKER_CAPACITY = 256;
var ConversationTails = class {
/** Newest entry ID per conversation, `null` for none. */
#latest = /* @__PURE__ */ new Map();
/** Newest head marker per conversation, `null` for none. */
#markers = /* @__PURE__ */ new Map();
/** The newest entry ID visible from `conversationId`, read with `read` when not known. */
async latest(conversationId, read2) {
const known = use(this.#latest, conversationId);
if (known !== void 0)
return known ?? void 0;
const latest = await read2();
put(this.#latest, conversationId, latest ?? null, LATEST_CAPACITY);
return latest;
}
/**
* The newest visible head marker at or before `atOrBefore` (any when `undefined`), read with `read` when not known.
* The newest marker answers every cutoff at or after it, and no marker answers every cutoff.
*/
async marker(conversationId, atOrBefore, read2) {
const marker = use(this.#markers, conversationId);
if (marker === null)
return void 0;
if (marker !== void 0 && (atOrBefore === void 0 || atOrBefore >= marker.id))
return marker;
const latest = this.#latest.get(conversationId);
const found = await read2();
if (atOrBefore === void 0 || latest !== void 0 && (latest ?? 0) <= atOrBefore) {
put(this.#markers, conversationId, found === void 0 ? null : freeze2(found), MARKER_CAPACITY);
}
return found;
}
/** The newest entry ID of `conversationId` if known, without reading: `null` for none, `undefined` when unknown. */
peek(conversationId) {
return this.#latest.get(conversationId);
}
/** At a commit's publication: apply a durable batch. */
apply(writes) {
for (const write of writes) {
if (write.type === "conversation") {
if (write.value.parent !== void 0)
continue;
put(this.#latest, write.value.id, null, LATEST_CAPACITY);
put(this.#markers, write.value.id, null, MARKER_CAPACITY);
} else if (write.type === "entry") {
const entry2 = write.value;
put(this.#latest, entry2.conversationId, entry2.id, LATEST_CAPACITY);
if (entry2.head !== void 0) {
put(this.#markers, entry2.conversationId, freeze2(entry2), MARKER_CAPACITY);
}
}
}
}
/** How many conversations have their newest entry kept, for tests that bound memory. */
get size() {
return this.#latest.size;
}
/** How many conversations have their newest head marker kept, for tests that bound memory. */
get markers() {
return this.#markers.size;
}
};
function use(map2, key) {
const value2 = map2.get(key);
if (value2 === void 0)
return void 0;
map2.delete(key);
map2.set(key, value2);
return value2;
}
function put(map2, key, value2, capacity) {
map2.delete(key);
map2.set(key, value2);
if (map2.size > capacity)
map2.delete(map2.keys().next().value);
}
function freeze2(value2) {
if (value2 === null || typeof value2 !== "object" || Object.isFrozen(value2))
return value2;
for (const child of Object.values(value2))
freeze2(child);
return Object.freeze(value2);
}
// node_modules/@earendil-works/pi-durable/dist/session/keys.js
function taskKey(id) {
return `task:${id}`;
}
function conversationKey(id) {
return `conv:${id}`;
}
function entryKey(id) {
return `entry:${id}`;
}
function appendKey(id) {
return `entry-append:${id}`;
}
function submissionKey(id) {
return `sub:${id}`;
}
function requestKey(conversationId, requestId) {
return `req:${conversationId}:${requestId}`;
}
function documentKey(addressId2) {
return `doc:${addressId2}`;
}
function incarnationKey(id) {
return `docid:${id}`;
}
function scopeKey(scope) {
switch (scope.kind) {
case "session":
return "docscope:session";
case "conversation":
return `docscope:c${scope.conversationId}`;
case "task":
return `docscope:t${scope.taskId}`;
}
}
function ownedKey(node) {
return `owned:${node}`;
}
var ROOTS_KEY = "roots";
var INTENT_KEY = "intent";
var ALL_KEYS = "*";
function tableKeys(writes, keys) {
for (const write of writes) {
switch (write.type) {
case "conversation":
keys.push(conversationKey(write.value.id));
break;
case "entry":
keys.push(entryKey(write.value.id), appendKey(write.value.conversationId));
break;
case "task":
keys.push(taskKey(write.value.id));
break;
case "submission":
keys.push(submissionKey(write.value.id));
if (write.value.requestId !== void 0) {
keys.push(requestKey(write.value.conversationId, write.value.requestId));
}
break;
}
}
}
var GatedStorage = class {
#storage;
#touch;
constructor(storage, touch) {
this.#storage = storage;
this.#touch = touch;
}
commit(batches, receive, context) {
return this.#storage.commit(batches, receive, context);
}
mintId() {
return this.#storage.mintId();
}
conversation(id, context) {
return this.#after(conversationKey(id), () => this.#storage.conversation(id, context));
}
scanConversations(query, limit2, cursor, context) {
return this.#after(ALL_KEYS, () => this.#storage.scanConversations(query, limit2, cursor, context));
}
entry(first, second, third) {
if (third === void 0) {
const id2 = first;
return this.#after(entryKey(id2), () => this.#storage.entry(id2, second));
}
const conversationId = first;
const id = second;
return this.#after(conversationKey(conversationId), () => this.#after(entryKey(id), () => this.#storage.entry(conversationId, id, third)));
}
findLatestHeadMarker(conversationId, atOrBeforeEntryId, context) {
return this.#afterEntries(conversationId, () => this.#storage.findLatestHeadMarker(conversationId, atOrBeforeEntryId, context));
}
scanEntries(query, limit2, cursor, context) {
return this.#afterEntries(query.conversationId, () => this.#storage.scanEntries(query, limit2, cursor, context));
}
task(id, context) {
return this.#after(taskKey(id), () => this.#storage.task(id, context));
}
scanTasks(query, limit2, cursor, context) {
return this.#after(ALL_KEYS, () => this.#storage.scanTasks(query, limit2, cursor, context));
}
submission(id, context) {
return this.#after(submissionKey(id), () => this.#storage.submission(id, context));
}
scanSubmissions(query, limit2, cursor, context) {
return this.#after(ALL_KEYS, () => this.#storage.scanSubmissions(query, limit2, cursor, context));
}
submissionByRequest(conversationId, requestId, context) {
return this.#after(requestKey(conversationId, requestId), () => this.#storage.submissionByRequest(conversationId, requestId, context));
}
findDocument(address, at, context) {
return this.#after(documentKey(addressId(address)), () => this.#storage.findDocument(address, at, context));
}
document(id, at, context) {
return this.#after(incarnationKey(id), () => this.#storage.document(id, at, context));
}
scanDocuments(query, limit2, cursor, context) {
return this.#after(scopeKey(query.scope), () => this.#storage.scanDocuments(query, limit2, cursor, context));
}
close(context) {
return this.#storage.close(context);
}
/**
* Run a read of a conversation's entries once neither its appends nor its creation has an unpublished writer: Storage
* refuses the read of a conversation it does not have yet.
*/
#afterEntries(conversationId, read2) {
return this.#after(conversationKey(conversationId), () => this.#after(appendKey(conversationId), read2));
}
/** Run `read` once `key` has no unpublished writer. */
#after(key, read2) {
const gate = this.#touch(key);
return gate === void 0 ? read2() : gate.then(read2);
}
};
// node_modules/@earendil-works/pi-durable/dist/types.js
var ROOT_CONVERSATION_ID = 1;
// node_modules/@earendil-works/pi-durable/dist/session/forks.js
var SCAN_PAGE_SIZE = 256;
async function prepareForkDocumentCopies(storage, parentConversationId, at, childConversationId, context) {
const entry2 = await storage.entry(parentConversationId, at, context);
if (entry2 === void 0)
throw new Error(`Entry ${at} is not visible from conversation ${parentConversationId}`);
const copies = [];
const copiedAddresses = /* @__PURE__ */ new Set();
await collectCopies(storage, { kind: "conversation", conversationId: entry2.entry.conversationId }, entry2.commitSeq, "asOf", childConversationId, copies, copiedAddresses, context);
await collectCopies(storage, { kind: "conversation", conversationId: parentConversationId }, "current", "current", childConversationId, copies, copiedAddresses, context);
return copies;
}
async function collectCopies(storage, scope, at, policy, childConversationId, copies, copiedAddresses, context) {
let cursor;
do {
const page2 = await storage.scanDocuments({ scope, at }, SCAN_PAGE_SIZE, cursor, context);
for (const source of page2.items) {
if (source.scope.kind !== "conversation" || source.fork !== policy)
continue;
const id = await storage.mintId();
const identity = {
id,
kind: source.kind,
...source.key === void 0 ? {} : { key: source.key },
scope: { kind: "conversation", conversationId: childConversationId }
};
const record = source.history === "latest" ? { ...identity, history: "latest", fork: source.fork } : { ...identity, history: "rewindable", fork: source.fork };
const copyAddress = addressId(record);
if (copiedAddresses.has(copyAddress)) {
const member = record.key === void 0 ? record.kind : `${record.kind}/${record.key}`;
throw new Error(`Fork selects multiple source documents for ${member}`);
}
copiedAddresses.add(copyAddress);
copies.push({ record, source: { id: source.id, at } });
}
cursor = page2.next;
} while (cursor !== void 0);
}
// node_modules/@earendil-works/pi-durable/dist/session/transaction.js
function applySubmissionChange(current, change) {
if (current.status === "done" || current.status === "unanswered")
return current;
if (change.status === "placed") {
if (current.status !== "queued")
throw new Error(`Submission ${current.id} is not queued`);
const status = current.type === "input" ? "placed" : "done";
return { ...current, status, entry: change.entry };
}
if (change.status === "done" && current.status !== "placed") {
throw new Error(`Submission ${current.id} is not a placed input or continue`);
}
return { ...current, ...change };
}
var INTERNAL_SCAN_PAGE_SIZE = 256;
var EMPTY_OPERATIONS = [];
var TABLE_JSON_COPY_OPTIONS = { omitUndefinedProperties: true };
var Transaction = class {
#host;
#context;
#scope;
#pendingOperations = /* @__PURE__ */ new Set();
#sealed = false;
#hasTableWrite = false;
/** Atomic batch; conversation and entry writes stage eagerly, while task and document writes assemble later. */
#writes = [];
#createdConversationIds = /* @__PURE__ */ new Set();
#forkSourceConversationIds = /* @__PURE__ */ new Set();
#forkSourceDocumentIds = /* @__PURE__ */ new Set();
/** One entry per task touched by a public read, candidate write, or document-owner lookup. */
#tasksById = /* @__PURE__ */ new Map();
/** Submissions created by this transaction, by ID. */
#submissions = /* @__PURE__ */ new Map();
/** Submission settlements and placements in staging order; resolved against the latest candidate record during assembly. */
#submissionChanges = [];
/** Write and publication plans of every staged incarnation, built during assembly. */
#plans = [];
/** Every document acquisition or retirement marker in staging order. */
#documents = [];
/** Latest transaction-local incarnation or retirement marker at each logical address. */
#latestDocumentByAddress = /* @__PURE__ */ new Map();
constructor(host, context, scope = {}) {
this.#host = host;
this.#context = context;
this.#scope = scope;
}
/** Internal: the context of the commit this transaction belongs to. */
get context() {
return this.#context;
}
/** Internal: whether a table write was staged, after which table reads throw `ReadAfterWrite`. */
get hasTableWrite() {
return this.#hasTableWrite;
}
/**
* Internal: whether `tx` is a transaction of a commit of the Session behind `host`. A brand check, so a proxy or
* another wrapper of a transaction is not one.
*/
static ownedBy(tx, host) {
return #host in tx && tx.#host === host;
}
// ─── Table reads ────────────────────────────────────────────────────────
conversation(id) {
return this.#read("conversation", () => this.#host.storage.conversation(id, this.#context));
}
entry(first, second) {
const kind = typeof first === "number" ? void 0 : first.kind;
const id = typeof first === "number" ? first : second;
return this.#read("entry", async () => {
const entry2 = (await this.#host.storage.entry(id, this.#context))?.entry;
return kind === void 0 || entry2?.kind === kind ? entry2 : void 0;
});
}
task(id) {
return this.#read("task", () => this.#committedTask(id));
}
scanConversations(query, limit2, cursor) {
return this.#read("scanConversations", () => this.#host.storage.scanConversations(query, limit2, cursor, this.#context));
}
scanEntries(query, limit2, cursor) {
return this.#read("scanEntries", () => this.#host.storage.scanEntries(query, limit2, cursor, this.#context));
}
latestHeadMarker(conversationId) {
return this.#read("latestHeadMarker", () => this.#host.latestHeadMarker(conversationId, this.#context));
}
latestEntryId(conversationId) {
return this.#read("latestEntryId", () => this.#host.latestEntryId(conversationId, this.#context));
}
scanTasks(query, limit2, cursor) {
return this.#read("scanTasks", () => this.#host.storage.scanTasks(query, limit2, cursor, this.#context));
}
/** Internal: committed submission record. */
submission(id) {
return this.#read("submission", () => this.#host.storage.submission(id, this.#context));
}
/** Committed submission with a conversation-scoped request ID. */
submissionByRequest(conversationId, requestId) {
return this.#read("submissionByRequest", () => this.#host.storage.submissionByRequest(conversationId, requestId, this.#context));
}
// ─── Table writes ───────────────────────────────────────────────────────
createConversation(options) {
return this.#write(() => this.#stageConversation(void 0, options.ownership));
}
/** Internal final-form bootstrap path for the reserved root identity. */
createRootConversation() {
return this.#write(() => this.#stageConversation(void 0, { kind: "ownerless" }, ROOT_CONVERSATION_ID));
}
forkConversation(parentConversationId, at, options) {
return this.#write(() => this.#stageConversation({ conversationId: parentConversationId, at }, options.ownership));
}
async #stageConversation(parent, ownership, reservedId) {
const ownerTaskId = ownership.kind === "task" ? ownership.taskId : void 0;
const id = reservedId ?? await this.#host.storage.mintId();
this.#assertOpen();
let owner;
if (ownerTaskId !== void 0) {
const task = await this.#currentTask(ownerTaskId);
this.#assertOpen();
if (task === void 0)
throw new Error(`Conversation owner task ${ownerTaskId} does not exist`);
owner = { conversationId: task.conversationId, taskId: ownerTaskId };
}
const record = {
id,
...parent === void 0 ? {} : { parent },
...owner === void 0 ? {} : { owner }
};
const copies = parent === void 0 ? [] : await prepareForkDocumentCopies(this.#host.storage, parent.conversationId, parent.at, id, this.#context);
this.#assertOpen();
for (const copy2 of copies) {
this.#forkSourceDocumentIds.add(copy2.source.id);
const entry2 = {
addressId: addressId(copy2.record),
address: copy2.record,
target: { kind: "fork-copy", ...copy2 },
retireOnCommit: false
};
this.#documents.push(entry2);
this.#latestDocumentByAddress.set(entry2.addressId, entry2);
}
if (parent !== void 0)
this.#forkSourceConversationIds.add(parent.conversationId);
this.#createdConversationIds.add(id);
this.#writes.push({ type: "conversation", value: record });
await this.#host.conversationCreated(this, record);
this.#assertOpen();
return record;
}
appendEntry(first, second, third) {
if (typeof first === "number")
return this.#appendEntry(first, second);
return this.#appendEntry(second, { ...third, kind: first.kind });
}
#appendEntry(conversationId, value2) {
return this.#write(async () => {
await this.#requireConversation(conversationId);
this.#assertOpen();
const id = await this.#host.storage.mintId();
this.#assertOpen();
const { head, ...rest } = value2;
const record = copyJson({
...rest,
id,
conversationId,
head: head === "self" ? id : head,
byTaskId: this.#scope.taskId
}, TABLE_JSON_COPY_OPTIONS);
this.#writes.push({ type: "entry", value: record });
return record;
});
}
createTask(task, input, options) {
return this.#write(async () => {
if (options.submissionIds !== void 0) {
let trace;
let links;
for (let index = 0; index < options.submissionIds.length; index++) {
const id2 = options.submissionIds[index];
const submission2 = this.#submissions.get(id2) ?? await this.#host.storage.submission(id2, this.#context);
if (index === 0)
trace = submission2?.trace ?? "root";
else if (submission2?.trace !== void 0) {
links ??= [];
links.push(submission2.trace);
}
}
options = { ...options, trace, links };
}
const ownership = options.ownership;
let owner;
if (ownership.kind === "task") {
owner = await this.#currentTask(ownership.taskId);
this.#assertOpen();
if (owner === void 0)
throw new Error(`Task owner ${ownership.taskId} does not exist`);
if (options.background === true)
throw new TypeError("A child task cannot be background");
if (options.conversationId !== void 0 && options.conversationId !== owner.conversationId) {
throw new Error(`A child task lives in its owner's conversation ${owner.conversationId}`);
}
}
const conversationId = owner?.conversationId ?? options.conversationId ?? this.#scope.conversationId;
if (conversationId === void 0)
throw new TypeError("Tx.createTask() requires options.conversationId");
await this.#requireConversation(conversationId);
this.#assertOpen();
const definition = task.definition;
const checkpoint = definition.initial(input);
const id = await this.#host.storage.mintId();
this.#assertOpen();
const record = copyJson({
id,
conversationId,
kind: definition.name,
version: definition.version,
input,
trace: options.trace === "root" ? void 0 : options.trace ?? this.#context.telemetry.propagation?.inject(this.#context.telemetry),
links: options.links,
...owner === void 0 ? {} : { owner: owner.id },
background: options.background ?? false,
abortRequested: false,
...options.abandonOnRestart === true ? { abandonOnRestart: true } : {},
state: { status: "pending", checkpoint }
}, TABLE_JSON_COPY_OPTIONS);
this.#tasksById.set(id, { write: { kind: "create", record } });
return id;
});
}
/** Create a raw submission record with a fresh ID; no admission rules apply. */
createSubmission(create) {
return this.#write(async () => {
await this.#requireConversation(create.conversationId);
this.#assertOpen();
const id = await this.#host.storage.mintId();
this.#assertOpen();
const record = copyJson({ ...create, id }, TABLE_JSON_COPY_OPTIONS);
this.#submissions.set(id, record);
return record;
});
}
/**
* Settle a submission. Resolved during assembly against the transaction's latest candidate record, falling back to
* committed state, so it is not a caller table read and works after the first table write.
*/
settleSubmission(id, settlement) {
this.#assertOpen();
this.#hasTableWrite = true;
this.#submissionChanges.push({ id, change: copyJson(settlement) });
}
/** Place a queued submission at `entry`; resolved during assembly like `settleSubmission()`. */
placeSubmission(id, entry2) {
this.#assertOpen();
this.#hasTableWrite = true;
this.#submissionChanges.push({ id, change: { status: "placed", entry: entry2 } });
}
/** Internal: replace one task record completely. Tasks change their own state through their runtime. */
setTask(value2) {
this.#assertOpen();
this.#hasTableWrite = true;
const task = this.#taskEntry(value2.id);
const candidate = task.write?.record;
if (candidate?.state.status === "terminal") {
throw new Error(`Task ${value2.id} already has a terminal candidate`);
}
if (candidate !== void 0 && candidate.conversationId !== value2.conversationId) {
throw new Error(`Task ${value2.id} cannot change conversations`);
}
task.write = {
kind: task.write?.kind === "create" ? "create" : "replace",
record: copyJson(this.#stampTimes(value2, candidate), TABLE_JSON_COPY_OPTIONS)
};
}
/** Internal: candidate records of the tasks this transaction created or replaced so far. */
stagedTasks() {
const records = [];
for (const task of this.#tasksById.values())
if (task.write !== void 0)
records.push(task.write.record);
return records;
}
/** Internal: IDs of the tasks this transaction creates. */
createdTaskIds() {
const ids = [];
for (const [id, task] of this.#tasksById)
if (task.write?.kind === "create")
ids.push(id);
return ids;
}
/** Internal: conversations this transaction created or forked so far. */
stagedConversations() {
const records = [];
for (const write of this.#writes)
if (write.type === "conversation")
records.push(write.value);
return records;
}
doc(token, ...args) {
try {
this.#assertOpen();
const definition = token.definition;
const resolved = resolveAddress(definition, args);
this.#assertTaskDocumentsOpen(resolved);
const latest = this.#latestDocumentByAddress.get(resolved.id);
if (latest !== void 0 && !latest.retireOnCommit) {
if (latest.draftPromise !== void 0)
return latest.draftPromise;
if (latest.target?.kind === "fork-copy") {
latest.draftPromise = this.#track(this.#acquireForkCopy(latest, definition, latest.target));
return latest.draftPromise;
}
}
const seed = definition.family === true ? copyJson(args[resolved.nextArgument]) : void 0;
const docEntry = {
addressId: resolved.id,
address: resolved.address,
definition,
retireOnCommit: false
};
this.#documents.push(docEntry);
this.#latestDocumentByAddress.set(docEntry.addressId, docEntry);
docEntry.draftPromise = this.#track(this.#acquire(docEntry, seed, latest?.retireOnCommit === true));
return docEntry.draftPromise;
} catch (error) {
return Promise.reject(error);
}
}
retireDoc(token, ...args) {
try {
this.#assertOpen();
const definition = token.definition;
const resolved = resolveAddress(definition, args);
const latest = this.#latestDocumentByAddress.get(resolved.id);
if (latest?.retireOnCommit)
return Promise.resolve();
if (latest?.target?.kind === "fork-copy") {
checkRecordScope(definition, latest.target.record);
latest.retireOnCommit = true;
return Promise.resolve();
}
if (latest?.draftPromise !== void 0) {
latest.retireOnCommit = true;
return this.#track(latest.draftPromise.then(() => void 0));
}
const entry2 = {
addressId: resolved.id,
address: resolved.address,
definition,
retireOnCommit: true
};
this.#documents.push(entry2);
this.#latestDocumentByAddress.set(entry2.addressId, entry2);
return this.#track(this.#findRetirement(entry2));
} catch (error) {
return Promise.reject(error);
}
}
async #acquire(entry2, seed, skipLoad) {
const definition = entry2.definition;
const loaded = skipLoad ? void 0 : await this.#host.load(definition, entry2.addressId, entry2.address, this.#context);
this.#assertOpen();
if (loaded !== void 0) {
checkRecordScope(definition, loaded.record);
checkRecordVersion(definition, loaded.record, loaded.storedVersion);
entry2.target = { kind: "loaded", document: loaded };
entry2.change = loaded.tracker.beginChange();
return entry2.change.state;
}
const scope = entry2.address.scope;
if (scope.kind === "conversation")
await this.#requireConversation(scope.conversationId);
if (scope.kind === "task") {
const task = await this.#currentTask(scope.taskId);
if (task === void 0)
throw new Error(`Task ${scope.taskId} does not exist`);
if (task.state.status === "terminal")
throw new Error(`Task ${scope.taskId} is terminal`);
}
this.#assertOpen();
const value2 = copyJson(definition.family === true ? definition.initial(seed) : definition.initial());
const id = await this.#host.storage.mintId();
this.#assertOpen();
const tracker = track(value2);
entry2.target = {
kind: "created",
record: documentCreate(definition, entry2.address, id),
version: definition.version,
tracker
};
entry2.change = tracker.beginChange();
return entry2.change.state;
}
async #acquireForkCopy(entry2, definition, target) {
const stored = await this.#host.storage.document(target.source.id, target.source.at, this.#context);
this.#assertOpen();
if (stored === void 0) {
throw new Error(`Fork source document ${target.source.id} cannot be read`);
}
if (stored.record.scope.kind !== "conversation" || stored.record.kind !== target.record.kind || stored.record.key !== target.record.key || stored.record.history !== target.record.history || stored.record.fork !== target.record.fork) {
throw new Error(`Fork source document ${target.source.id} does not match the copied record`);
}
const value2 = materializeDocumentValue(definition, target.record, stored.version, stored.value);
const tracker = track(value2);
entry2.definition = definition;
entry2.target = { kind: "created", record: target.record, version: definition.version, tracker };
entry2.change = tracker.beginChange();
return entry2.change.state;
}
async #findRetirement(entry2) {
const gate = this.#host.touch(documentKey(entry2.addressId));
if (gate !== void 0)
await gate;
const record = this.#host.cached(entry2.addressId)?.record ?? await this.#host.storage.findDocument(entry2.address, "current", this.#context);
this.#assertOpen();
if (record === void 0)
return;
checkRecordScope(entry2.definition, record);
entry2.target = { kind: "retire-only", record };
}
// ─── Settlement ─────────────────────────────────────────────────────────
/** Seal after callback failure: abort every change and observe every pending operation. */
async settleFailure() {
this.#sealed = true;
this.#abortChanges();
await Promise.allSettled(this.#pendingOperations);
this.#context = BACKGROUND_CONTEXT;
}
/**
* Seal after callback success, prepare every open change, and assemble the atomic batch.
* Any failure aborts every change before Storage admission.
*/
async settleSuccess() {
this.#sealed = true;
if (this.#pendingOperations.size > 0) {
this.#abortChanges();
await Promise.allSettled(this.#pendingOperations);
this.#context = BACKGROUND_CONTEXT;
throw new Error("Session commit callback settled before its pending Tx operations");
}
try {
for (const document of this.#documents) {
if (document.change !== void 0)
document.prepared = document.change.prepare();
}
return await this.#assemble();
} catch (error) {
this.#abortChanges();
throw error;
} finally {
this.#context = BACKGROUND_CONTEXT;
}
}
/** Abort every prepared change after Storage failure or when no write is required. */
discard() {
this.#abortChanges();
}
/**
* Internal: what a deferred commit holds in memory instead of storing (`CommitPersistence`), each changed incarnation
* with its operations and whether they selected a base; `undefined` when the commit must be stored. It may be held
* only when every write changes an existing `latest`, `initial`-fork conversation document at its stored version.
*/
holdable() {
if (this.#writes.some((write) => write.type !== "document.change"))
return void 0;
const held = [];
for (const plan of this.#plans) {
const { content, change } = plan;
if (content === void 0 && !plan.retire)
continue;
if (plan.retire || change?.loaded === void 0 || content?.type !== "document.change")
return void 0;
const { loaded, prepared, version } = change;
const record = loaded.record;
if (record.scope.kind !== "conversation" || record.history !== "latest" || record.fork !== "initial") {
return void 0;
}
if (loaded.storedVersion !== version)
return void 0;
held.push({ loaded, ops: prepared.ops, base: content.content.kind === "base" });
}
return held;
}
/**
* Internal: adopt a held commit (`holdable()`) in memory only. Trackers advance by pointer swap; stored versions and
* delta counts stay, as nothing was stored. Returns its publication for the Session's own observers.
*/
adoptHeld() {
const publications = [];
for (const plan of this.#plans) {
const { tracker, prepared, version, loaded } = plan.change;
if (prepared.ops.length === 0) {
prepared.abort();
continue;
}
tracker.adopt(prepared);
const record = loaded.record;
const conversationId = plan.conversationId;
publications.push({
type: "document",
kind: "change",
record,
conversationId,
version,
value: prepared.value,
ops: prepared.ops
});
}
return publications;
}
/**
* Internal: store the held changes of every incarnation this commit reads or writes in front of its own, so a stored
* document never misses an operation its later ones build on. Called right before Storage admission, after every
* fallible step, because it empties the holds: a failure earlier keeps them. Returns the holds it took.
*/
takeHeld(held) {
const taken = [];
for (const plan of this.#plans) {
if (!("createdAt" in plan.record))
continue;
const hold = held(plan.record.id);
if (hold === void 0)
continue;
taken.push(hold);
const own = plan.content?.type === "document.change" ? plan.content : void 0;
const change = plan.change;
const value2 = change?.prepared.value ?? hold.loaded.tracker.value;
const stored = storeHeld(hold, change?.prepared.ops ?? EMPTY_OPERATIONS, value2, hold.loaded.valueVersion);
const content = own?.content.kind === "base" ? own.content : stored.content;
const write = { type: "document.change", id: plan.record.id, content };
if (own !== void 0)
this.#writes[this.#writes.indexOf(own)] = write;
else
this.#insertBeforeRetirement(write);
if (!plan.retire)
plan.held = { ops: stored.ops, observed: own !== void 0 };
plan.content = write;
if (plan.record.scope.kind === "conversation")
plan.conversationId = plan.record.scope.conversationId;
}
return taken;
}
/**
* Internal: the keys this commit writes, once settled (and after `takeHeld()`), for the Session's unpublished write
* set: its table records, and the address and incarnation of every document it creates, changes, or retires, with
* the scope of every incarnation it creates or retires.
*/
writeKeys() {
const keys = [];
tableKeys(this.#writes, keys);
for (const plan of this.#plans) {
if (plan.content === void 0 && !plan.retire)
continue;
keys.push(documentKey(plan.addressId), incarnationKey(plan.record.id));
if (plan.retire || !("createdAt" in plan.record))
keys.push(scopeKey(plan.record.scope));
}
return keys;
}
/** Stage a content write for an incarnation, before its retirement when it retires. */
#insertBeforeRetirement(write) {
const at = this.#writes.findIndex((candidate) => candidate.type === "document.retire" && candidate.id === write.id);
if (at < 0)
this.#writes.push(write);
else
this.#writes.splice(at, 0, write);
}
/** Adopt every prepared change by pointer swap after Storage success and describe the publication. */
adopt(seq) {
const publications = [];
let stored;
for (const plan of this.#plans) {
const committed = "createdAt" in plan.record;
let record = committed ? plan.record : { ...plan.record, createdAt: seq };
if (plan.retire)
record = { ...record, retiredAt: seq };
const change = plan.change;
if (change !== void 0) {
const { tracker, prepared, loaded, version } = change;
if (loaded === void 0 ? !plan.retire : prepared.ops.length > 0)
tracker.adopt(prepared);
else
prepared.abort();
if (loaded !== void 0) {
if (loaded.storedVersion < version)
loaded.storedVersion = version;
if (plan.content?.type === "document.change") {
if (plan.content.content.kind === "base")
loaded.deltasSinceBase = 0;
else
loaded.deltasSinceBase++;
}
} else if (!plan.retire) {
this.#host.install({
addressId: plan.addressId,
record,
storedVersion: version,
valueVersion: version,
deltasSinceBase: 0,
tracker
});
}
}
if (plan.retire && committed)
this.#host.evict(plan.addressId, record.id);
const publication = describe(plan, record);
if (publication === void 0)
continue;
const held = plan.held;
if (held === void 0) {
publications.push(publication);
stored?.push(publication);
continue;
}
stored ??= [...publications];
if (held.observed)
publications.push(publication);
stored.push(publication.type === "document" && publication.kind === "change" ? { ...publication, ops: held.ops } : publication);
}
return { observed: publications, stored: stored ?? publications };
}
async #assemble() {
const storage = this.#host.storage;
const plans = this.#plans;
for (const document of this.#documents) {
const plan = planDocument(document);
if (plan !== void 0)
plans.push(plan);
}
this.#rejectForkSourceWrites(plans);
await this.#validateOwners();
for (const [id, task] of this.#tasksById) {
if (task.write?.kind !== "replace")
continue;
const committed = await this.#committedTask(id);
if (committed === void 0)
throw new Error(`Task ${id} does not exist`);
if (committed.state.status === "terminal")
throw new Error(`Task ${id} is already terminal`);
if (committed.conversationId !== task.write.record.conversationId) {
throw new Error(`Task ${id} cannot change conversations`);
}
}
const terminalTaskIds = /* @__PURE__ */ new Set();
for (const task of this.#tasksById.values()) {
if (task.write?.record.state.status === "terminal")
terminalTaskIds.add(task.write.record.id);
}
if (terminalTaskIds.size > 0) {
const retiring = /* @__PURE__ */ new Set();
for (const plan of plans) {
const scope = plan.record.scope;
if (scope.kind !== "task" || !terminalTaskIds.has(scope.taskId))
continue;
plan.retire = true;
retiring.add(plan.record.id);
}
const retire = (record) => {
if (retiring.has(record.id))
return;
plans.push({ addressId: addressId(record), record, retire: true });
retiring.add(record.id);
};
for (const taskId of terminalTaskIds) {
if (this.#tasksById.get(taskId)?.write?.kind === "create")
continue;
const gate = this.#host.touch(scopeKey({ kind: "task", taskId }));
if (gate !== void 0)
await gate;
const known = this.#host.taskDocuments(taskId);
if (known !== void 0) {
for (const record of known)
retire(record);
continue;
}
let cursor;
do {
const page2 = await storage.scanDocuments({ scope: { kind: "task", taskId }, at: "current" }, INTERNAL_SCAN_PAGE_SIZE, cursor, this.#context);
for (const record of page2.items)
retire(record);
cursor = page2.next;
} while (cursor !== void 0);
}
}
for (const plan of plans) {
if (!publishes(plan))
continue;
const scope = plan.record.scope;
if (scope.kind === "conversation")
plan.conversationId = scope.conversationId;
if (scope.kind !== "task")
continue;
const task = this.#taskEntry(scope.taskId);
if (task.publicationConversationId === void 0) {
const current = await this.#currentTask(scope.taskId);
if (current !== void 0)
task.publicationConversationId = current.conversationId;
}
plan.conversationId = task.publicationConversationId;
}
for (const { id, change } of this.#submissionChanges) {
const current = this.#submissions.get(id) ?? await storage.submission(id, this.#context);
if (current === void 0)
throw new Error(`Submission ${id} does not exist`);
const next = applySubmissionChange(current, change);
if (next !== current)
this.#submissions.set(id, next);
}
const writes = this.#writes;
for (const value2 of this.#submissions.values())
writes.push({ type: "submission", value: value2 });
for (const task of this.#tasksById.values()) {
if (task.write !== void 0)
writes.push({ type: "task", value: task.write.record });
}
for (const plan of plans) {
const change = plan.change;
if (plan.content?.type === "document.change" && plan.content.content.kind === "delta" && change?.loaded) {
const { prepared, version } = change;
const info = { deltasSinceBase: change.loaded.deltasSinceBase };
if (change.definition.checkpointWhen(prepared.value, prepared.ops, info)) {
plan.content = { ...plan.content, content: { version, kind: "base", value: prepared.value } };
}
}
if (plan.content !== void 0)
writes.push(plan.content);
if (plan.retire)
writes.push({ type: "document.retire", id: plan.record.id });
}
return writes;
}
// ─── Helpers ────────────────────────────────────────────────────────────
/**
* New owned work needs a live owner, judged on the owner's final candidate: not `completing`, terminal, or
* abort-marked. A task therefore cannot create owned work in the commit that finishes it (spec §5.5).
*/
async #validateOwners() {
const owners = [];
for (const write of this.#writes) {
if (write.type !== "conversation" || write.value.owner === void 0)
continue;
owners.push({ what: "Conversation owner task", taskId: write.value.owner.taskId });
}
for (const task of this.#tasksById.values()) {
const record = task.write?.kind === "create" ? task.write.record : void 0;
if (record?.owner !== void 0)
owners.push({ what: "Task owner", taskId: record.owner });
}
for (const { what, taskId } of owners) {
const task = await this.#currentTask(taskId);
if (task === void 0)
throw new Error(`${what} ${taskId} does not exist`);
if (task.state.status === "terminal" || task.state.status === "completing") {
throw new Error(`${what} ${taskId} is ${task.state.status}`);
}
if (task.abortRequested)
throw new Error(`${what} ${taskId} is abort-marked`);
}
}
#rejectForkSourceWrites(plans) {
for (const plan of plans) {
if (plan.content === void 0 && !plan.retire)
continue;
const record = plan.record;
if (this.#forkSourceDocumentIds.has(record.id)) {
throw new Error(`Cannot change fork source document ${record.id} in the fork transaction`);
}
const scope = plan.record.scope;
if (scope.kind === "conversation" && this.#forkSourceConversationIds.has(scope.conversationId) && record.scope.kind === "conversation" && record.fork === "current") {
throw new Error(`Cannot fork conversation ${scope.conversationId} while changing its current-policy documents`);
}
}
}
#abortChanges() {
for (const document of this.#documents)
document.change?.abort();
}
#assertOpen() {
if (this.#sealed)
throw new Error("Transaction has settled");
}
#assertTaskDocumentsOpen(resolved) {
const scope = resolved.address.scope;
if (scope.kind === "task" && this.#tasksById.get(scope.taskId)?.write?.record.state.status === "terminal") {
throw new Error(`Task ${scope.taskId} is terminal`);
}
}
/** Register an operation so callback settlement can reject and drain it. */
#track(operation) {
this.#pendingOperations.add(operation);
const settle3 = () => {
this.#pendingOperations.delete(operation);
};
operation.then(settle3, settle3);
return operation;
}
#read(method, read2) {
try {
this.#assertOpen();
if (this.#hasTableWrite)
throw new ReadAfterWrite(`Tx.${method}()`);
return this.#track(read2());
} catch (error) {
return Promise.reject(error);
}
}
#write(write) {
try {
this.#assertOpen();
this.#hasTableWrite = true;
return this.#track(write());
} catch (error) {
return Promise.reject(error);
}
}
async #requireConversation(id) {
if (this.#createdConversationIds.has(id))
return;
if (await this.#host.storage.conversation(id, this.#context) === void 0) {
throw new Error(`Conversation ${id} does not exist`);
}
}
/**
* Lifecycle times: `startedAt` on the first change to `running`, `endedAt` on the change to `terminal`. Once set,
* they carry over from the replaced record; records written before they existed lack them.
*/
#stampTimes(value2, candidate) {
const status = value2.state.status;
const now = (stamps) => stamps ? this.#host.now() : void 0;
const startedAt = candidate?.startedAt ?? value2.startedAt ?? now(status === "running");
const endedAt = candidate?.endedAt ?? value2.endedAt ?? now(status === "terminal");
if (startedAt === value2.startedAt && endedAt === value2.endedAt)
return value2;
return {
...value2,
...startedAt === void 0 ? {} : { startedAt },
...endedAt === void 0 ? {} : { endedAt }
};
}
#taskEntry(id) {
let task = this.#tasksById.get(id);
if (task === void 0) {
task = {};
this.#tasksById.set(id, task);
}
return task;
}
/** Latest candidate task record, falling back to committed state; not a caller table read. */
async #currentTask(id) {
return this.#tasksById.get(id)?.write?.record ?? await this.#committedTask(id);
}
#committedTask(id) {
const task = this.#taskEntry(id);
task.committedRead ??= this.#host.storage.task(id, this.#context);
return task.committedRead;
}
};
function planDocument(document) {
const target = document.target;
if (target === void 0)
return void 0;
const plan = { addressId: document.addressId, retire: document.retireOnCommit };
switch (target.kind) {
case "created": {
const prepared = document.prepared;
const { record, version, tracker } = target;
const content = { version, kind: "base", value: prepared.value };
return {
...plan,
record,
content: { type: "document.create", record, content },
change: { tracker, prepared, version }
};
}
case "fork-copy":
return {
...plan,
record: target.record,
content: { type: "document.copy", record: target.record, source: target.source }
};
case "retire-only":
return { ...plan, record: target.record };
case "loaded": {
const loaded = target.document;
const definition = document.definition;
const prepared = document.prepared;
const version = definition.version;
const id = loaded.record.id;
const content = loaded.storedVersion < version ? { type: "document.change", id, content: { version, kind: "base", value: prepared.value } } : prepared.ops.length > 0 ? { type: "document.change", id, content: { version, kind: "delta", ops: prepared.ops } } : void 0;
const change = {
tracker: loaded.tracker,
prepared,
version,
loaded,
definition
};
return { ...plan, record: loaded.record, change, ...content === void 0 ? {} : { content } };
}
}
}
function describe(plan, record) {
const conversationId = plan.conversationId;
if (plan.retire)
return { type: "document", kind: "retire", record, conversationId };
if (plan.content?.type === "document.copy") {
return { type: "document.copy", record, conversationId, source: plan.content.source };
}
const change = plan.change;
if (change === void 0 || !publishes(plan))
return void 0;
const ops2 = change.loaded === void 0 ? EMPTY_OPERATIONS : change.prepared.ops;
return {
type: "document",
kind: "change",
record,
conversationId,
version: change.version,
value: change.prepared.value,
ops: ops2
};
}
function storeHeld(hold, ops2, value2, version) {
hold.pending.push(ops2);
const taken = hold.pending.take();
if (taken.kind === "replace")
return { content: { version, kind: "base", value: value2 }, ops: [["r", value2]] };
if (hold.base)
return { content: { version, kind: "base", value: value2 }, ops: taken.ops };
return { content: { version, kind: "delta", ops: taken.ops }, ops: taken.ops };
}
function publishes(plan) {
return plan.retire || plan.change?.loaded === void 0 || plan.content !== void 0;
}
// node_modules/@earendil-works/pi-durable/dist/session/writer.js
var SESSION_FAILED = { kind: "failed" };
var Writer = class {
#host;
/** Admitted parts not yet sent, in line order. */
#queue = [];
#flight = false;
/** Per key, the newest unpublished part that writes it. */
#unpublished = /* @__PURE__ */ new Map();
/** The newest admitted part that is not yet published, whose gate opens after every earlier one's. */
#newest;
constructor(host) {
this.#host = host;
}
/** Admit a part: register its keys, queue it, and send it at once unless a call is in flight. */
admit(spec) {
const outcome = Promise.withResolvers();
outcome.promise.catch(() => {
});
const part = {
...spec,
outcome: outcome.promise,
settle: {
resolve: () => {
part.done = true;
outcome.resolve();
},
reject: (error) => {
part.done = true;
outcome.reject(error);
}
},
done: false,
gate: Promise.withResolvers()
};
for (const key of spec.keys)
this.#unpublished.set(key, part);
this.#newest = part;
this.#queue.push(part);
this.#pump();
return part;
}
/** The gate of the newest unpublished writer of `key`, or `undefined` when it has none. */
gate(key) {
return this.#unpublished.get(key)?.gate.promise;
}
/** Opens once every part admitted so far is published or never will be. */
drained() {
return this.#newest?.gate.promise;
}
/** Keys with an unpublished writer, for tests that bound memory. */
get unpublished() {
return this.#unpublished.size;
}
#pump() {
if (this.#flight || this.#queue.length === 0)
return;
this.#flight = true;
const parts = this.#queue;
this.#queue = [];
void this.#flush(parts);
}
/**
* Send and publish `parts`, then what was admitted meanwhile. Never rejects: a throw the writer did not expect fails
* the Session and settles the parts (`#abandon()`), so no outcome or gate is stranded.
*/
async #flush(parts) {
try {
await this.#send(parts);
} catch (error) {
this.#abandon(parts, error);
}
this.#flight = false;
this.#pump();
}
/** Store `parts` in one call, then publish them in order; settles every one of them. */
async #send(parts) {
const stored = parts.filter((part) => part.writes !== void 0);
const seqs = [];
let result;
let rejected;
const failed = this.#host.failure();
if (failed !== void 0) {
for (const part of parts)
this.#unpublish(part, new SessionFailed(failed.error));
return;
}
if (stored.length > 0) {
try {
result = await this.#host.commit(stored.map((part) => part.writes), (index, seq) => {
seqs[index] = seq;
}, withoutAbortSignal(stored[0].context));
} catch (error) {
rejected = { error };
}
}
const failedMeanwhile = this.#host.failure();
if (failedMeanwhile !== void 0) {
for (const part of parts)
this.#unpublish(part, new SessionFailed(failedMeanwhile.error));
return;
}
await this.#publish(parts, seqs, result, rejected);
}
/**
* Publish the received parts and held ones in order, a macrotask apart, and settle every part (group commit §3.4). A
* refusal, a rejection, or a part whose adoption or own observer throws fails the Session once the parts before it
* are published and the host observers got the last one; the parts after it are not published, and reject with
* `SessionFailed`. What the failure decides (the outcomes, and the gates of the parts it concerns) is settled only
* once the Session failed, so no job waiting at such a gate, and no later outcome, goes on as if it had not.
*/
async #publish(parts, seqs, result, rejected) {
let stop2;
const failing = [];
let storedIndex = 0;
let published = 0;
for (const part of parts) {
const index = part.writes === void 0 ? void 0 : storedIndex++;
if (stop2 !== void 0) {
const outcome = rejected !== void 0 && index !== void 0 && stop2.external !== true ? { kind: "own", error: rejected.error } : SESSION_FAILED;
failing.push({ part, outcome, published: false });
continue;
}
const seq = index === void 0 ? void 0 : seqs[index];
if (index !== void 0 && seq === void 0) {
const error = rejected !== void 0 ? rejected.error : index === result?.stored && "refused" in result ? result.refused : new Error("Storage committed without adopting the batch");
failing.push({ part, outcome: { kind: "own", error }, published: false });
stop2 = { error, at: part.index };
continue;
}
if (published++ > 0)
await hop();
let failure2;
let external;
const publication = this.#host.publishing(() => {
external = this.#host.failure();
if (external !== void 0)
return;
this.#unregister(part);
try {
if (part.writes !== void 0)
this.#host.stored(part.writes);
failure2 = part.publish(seq);
} catch (error) {
failure2 = { kind: "adoption", error };
}
}, part.context);
if (publication !== void 0)
await publication;
if (external !== void 0) {
stop2 = { error: external.error, at: part.index, external: true };
failing.push({ part, outcome: SESSION_FAILED, published: false });
continue;
}
if (failure2?.kind === "adoption") {
failing.push({ part, outcome: { kind: "own", error: failure2.error }, published: true });
stop2 = { error: failure2.error, at: part.index };
continue;
}
if (rejected !== void 0) {
if (failure2 !== void 0)
this.#host.report(failure2.error, part.context);
failing.push({ part, outcome: { kind: "own", error: rejected.error }, published: true });
continue;
}
if (failure2 !== void 0)
stop2 = { error: failure2.error, at: part.index };
const failedMeanwhile = this.#host.failure();
if (failedMeanwhile !== void 0 && failure2 === void 0) {
part.settle.reject(new SessionFailed(failedMeanwhile.error));
} else
part.settle.resolve();
this.#open(part);
}
if (rejected !== void 0 || stop2 !== void 0) {
await Promise.resolve();
const own = failing.flatMap(({ part, outcome }) => outcome.kind === "own" ? [part.index] : []);
if (rejected !== void 0)
this.#host.fail(rejected.error, own[0], own);
else
this.#host.fail(stop2.error, stop2.at, own);
}
for (const { part, outcome, published: stored } of failing) {
const error = outcome.kind === "own" ? outcome.error : this.#failed(stop2.error);
if (stored) {
part.settle.reject(error);
this.#open(part);
} else
this.#unpublish(part, error);
}
const failure = this.#host.failure();
if (failure !== void 0) {
const queued = this.#queue;
this.#queue = [];
for (const part of queued)
this.#unpublish(part, new SessionFailed(failure.error));
}
}
/**
* A throw the writer itself did not expect while sending or publishing `parts` (a bug): fail the Session at the first
* of them and settle every one not settled yet, so no outcome, gate, or close waits on it forever.
*/
#abandon(parts, error) {
this.#host.fail(error, parts[0].index, []);
for (const part of parts) {
if (!part.done)
this.#unpublish(part, this.#failed(error));
this.#unregister(part);
this.#open(part);
}
}
/** `SessionFailed` with the Session's failure, or with `error` until the Session records it. */
#failed(error) {
const failure = this.#host.failure();
return new SessionFailed(failure !== void 0 ? failure.error : error);
}
/** Settle a part that will never be published: discard it, reject it with `error`, and open its gate. */
#unpublish(part, error) {
part.discard();
part.settle.reject(error);
this.#unregister(part);
this.#open(part);
}
/** Drop the keys a part is still the newest writer of: it is published, or never will be. */
#unregister(part) {
for (const key of part.keys)
if (this.#unpublished.get(key) === part)
this.#unpublished.delete(key);
}
/** Open a part's gate: the jobs waiting for it go on. The newest part's opens `drained()` too. */
#open(part) {
part.gate.resolve();
if (this.#newest === part)
this.#newest = void 0;
}
};
function hop() {
if (typeof setImmediate === "function")
return new Promise((resolve2) => setImmediate(resolve2));
const channel = new MessageChannel();
return new Promise((resolve2) => {
channel.port1.onmessage = () => {
channel.port1.close();
resolve2();
};
channel.port2.postMessage(void 0);
});
}
// node_modules/@earendil-works/pi-durable/dist/session/session.js
var NO_HOLDS = [];
var NO_OPERATIONS = [];
var NO_KEYS = [];
var MAX_OUTSTANDING = 256;
var ignore = () => {
};
var SETTLED = Promise.resolve();
var LISTENER = { kind: "listener_error" };
var TELEMETRY = { kind: "host_error", callback: "telemetry" };
var defaultRetention = 6e5;
function documentRetention(ms) {
return typeof ms === "number" && ms >= 0 ? ms : defaultRetention;
}
var DEFAULT_PERSIST_WITHIN_MS = 1e3;
function persistWithin(ms) {
return typeof ms === "number" && ms >= 0 ? ms : DEFAULT_PERSIST_WITHIN_MS;
}
var SessionImpl = class {
#storage;
/** Newest entry and head marker per conversation; none for a read-only Session, whose Storage another process writes. */
#tails;
/**
* The current documents of each live task this Session created, so the commit that ends a task retires them without
* a scan. An entry starts with its task's creation and goes when the task is terminal: bounded by live tasks.
*/
#taskDocuments = /* @__PURE__ */ new Map();
#documents = /* @__PURE__ */ new Map();
/** Cached documents with no observer attached, by address, oldest use first, with the time of that use. */
#idleDocuments = /* @__PURE__ */ new Map();
/** Observers attached per document incarnation (record ID); a cached incarnation with any is never evicted. */
#attachedDocuments = /* @__PURE__ */ new Map();
#clock;
#documentRetentionMs;
#persistWithinMs;
/** Documents with held changes, by incarnation (record ID); each is pinned in the cache until they are stored. */
#holds = /* @__PURE__ */ new Map();
#holdTimer;
/** Refuse every commit with writes (`HarnessOptions.readOnly`). */
#readOnly;
#timers;
/** The pending eviction: a timer for the oldest idle document, or a line job when the retention is 0. */
#documentSweep;
#sweepJobs = 0;
/** Set once the host declined a background timer: then none is kept, and the end of each commit evicts what expired. */
#documentTimersUnavailable = false;
/** Host commit observers (`observeCommits()`), each behind `guardObserver()`. */
#commitListeners = /* @__PURE__ */ new Set();
/** The Session's own listeners, such as its scheduler's: they keep memory in step with storage, so a throw fails it. */
#internalListeners = /* @__PURE__ */ new Set();
#closeListeners = /* @__PURE__ */ new Set();
#host;
/** The record cache under the guard, which the writer applies each batch to at its publication. */
#cached;
#writer;
/** The Storage jobs on the line read through: each read waits while its key has an unpublished writer. */
#gated;
/** The end of the last line job: the line runs one job at a time. */
#tail = Promise.resolve();
/** Line index of the next job; outcomes are delivered in this order. */
#nextIndex = 0;
/** The job on the line, while one runs: its index, and whether it waited at a gate. */
#current;
/** Settles once every job so far has its outcome delivered. */
#fence = Promise.resolve();
#lastDelivered = -1;
/** Jobs that started on the line and have no outcome delivered yet (`MAX_OUTSTANDING`). */
#outstanding = 0;
#room;
/** The line index whose outcome the failure is: every later job's outcome is `SessionFailed`, except `#ownOutcomes`. */
#failAt;
/** Later jobs whose outcome is their own error all the same: the other parts of a storage call that rejected. */
#ownOutcomes = /* @__PURE__ */ new Set();
#closing;
#failure;
/** Set when close reaches the backend: calls that fail from then on fail because it closes. */
#failed = Promise.withResolvers();
#closed = Promise.withResolvers();
get closed() {
return this.#closed.promise;
}
/** Internal: the error that failed the Session, if one did. */
get failure() {
return this.#failure;
}
/** Internal: rejects with `SessionFailed` the moment the Session fails, before work underway has ended; never resolves. */
get failed() {
return this.#failed.promise;
}
constructor(storage, now = Date.now, documentRetentionMs = () => void 0, setTimer, readOnly = false, persistWithinMs = () => void 0) {
this.#failed.promise.catch(() => {
});
this.#readOnly = readOnly;
this.#cached = readOnly ? void 0 : new CachedStorage(storage);
this.#storage = new GuardedStorage(this.#cached ?? storage, this);
this.#gated = new GatedStorage(this.#storage, (key) => this.touch(key));
this.#writer = new Writer({
commit: (batches, receive, context) => this.#storage.commit(batches, receive, context),
stored: (writes) => {
this.#cached?.published(writes);
this.#tails?.apply(writes);
},
publishing: (publish2, context) => this.#publishing(publish2, context),
failure: () => this.#failure,
fail: (error, at, own) => this.fail(error, void 0, at, own),
report: (error, context) => this.report(error, LISTENER, context)
});
this.#tails = readOnly ? void 0 : new ConversationTails();
this.#timers = hostTimers(setTimer, (error) => this.report(error, { kind: "host_error", callback: "setTimer" }));
this.#clock = () => {
try {
return now();
} catch {
return Date.now();
}
};
this.#documentRetentionMs = () => {
try {
return documentRetention(documentRetentionMs());
} catch {
return documentRetention(void 0);
}
};
this.#persistWithinMs = () => {
try {
return persistWithin(persistWithinMs());
} catch {
return persistWithin(void 0);
}
};
this.#host = {
storage: this.#gated,
touch: (key) => this.touch(key),
now,
cached: (id) => {
const cached = this.#documents.get(id);
if (cached !== void 0)
this.#touchDocument(id);
return cached;
},
load: (definition, addressId2, address, context) => this.#loadDocument(definition, addressId2, address, context),
install: (document) => {
this.#documents.set(document.addressId, document);
this.#touchDocument(document.addressId);
},
evict: (id, recordId) => {
if (this.#documents.get(id)?.record.id === recordId)
this.#dropDocument(id);
},
conversationCreated: (tx, record) => this.conversationCreated(tx, record),
taskDocuments: (taskId) => this.#taskDocuments.get(taskId)?.values(),
latestEntryId: (conversationId, context) => this.latestEntryId(conversationId, context),
latestHeadMarker: (conversationId, context) => this.latestHeadMarker(conversationId, void 0, context)
};
}
/** The Storage behind the failure guard; every component reads and writes through it. */
get storage() {
return this.#storage;
}
/**
* Internal, on the Session line: the newest entry ID visible from `conversationId`. Known from the Session's own
* commits when it owns its Storage, so it costs no Storage read after the first.
*/
latestEntryId(conversationId, context) {
const gate = this.#touchEntries(conversationId);
const latest = () => {
const read2 = async () => (await this.#storage.scanEntries({ conversationId }, 1, void 0, context)).items[0]?.id;
return this.#tails === void 0 ? read2() : this.#tails.latest(conversationId, read2);
};
return gate === void 0 ? latest() : gate.then(latest);
}
/**
* Internal: the newest entry ID of `conversationId` as known from the Session's commits right now, without reading;
* `undefined` when not known (and always for a read-only Session).
*/
knownLatestEntryId(conversationId) {
return this.#tails?.peek(conversationId);
}
/**
* Internal, on the Session line: the newest visible head marker of `conversationId` at or before `atOrBefore`, any
* when `undefined`; known from the Session's own commits as `latestEntryId()` is.
*/
latestHeadMarker(conversationId, atOrBefore, context) {
const gate = this.#touchEntries(conversationId);
const marker = () => {
const read2 = () => this.#storage.findLatestHeadMarker(conversationId, atOrBefore, context);
return this.#tails === void 0 ? read2() : this.#tails.marker(conversationId, atOrBefore, read2);
};
return gate === void 0 ? marker() : gate.then(marker);
}
/**
* On the line: wait for what an unpublished commit wrote of a conversation's entries, its appends and its creation,
* as reading them from Storage fails for a conversation not stored yet.
*/
#touchEntries(conversationId) {
const created = this.touch(conversationKey(conversationId));
const appended = this.touch(appendKey(conversationId));
if (created === void 0)
return appended;
return appended === void 0 ? created : Promise.all([created, appended]).then(ignore);
}
/**
* Internal, on the line: wait, while `key` has an unpublished writer (for `ALL_KEYS`, while anything is unpublished),
* until it is published, then check that the Session is healthy; `undefined` when there is nothing to wait for. A
* job's every read touches its key first, so it never observes state an earlier job admitted and the writer has not
* published.
*/
touch(key) {
const gate = key === ALL_KEYS ? this.#writer.drained() : this.#writer.gate(key);
if (gate === void 0)
return void 0;
if (this.#current !== void 0)
this.#current.hit = true;
return gate.then(() => this.#assertHealthy());
}
commit(change, context, options) {
return this.commitWith(change, context, void 0, options);
}
/**
* Internal: fail the Session with `error`, the first wins, and report it once. Admission ends, and close listeners run
* now; they read the error from `failure`. The Storage guard calls this; the Harness also calls it for a throw in its
* scheduler's own commits. `at` is the line index of the job whose outcome the failure is, by default the job on the
* line: later jobs' outcomes become `SessionFailed`.
*/
fail(error, context, at, own) {
if (this.#failure !== void 0)
return;
this.#failure = { error };
this.#failAt = at ?? this.#current?.index ?? this.#lastDelivered;
if (own !== void 0)
for (const index of own)
this.#ownOutcomes.add(index);
this.#failed.reject(new SessionFailed(error));
this.close(BACKGROUND_CONTEXT).catch(() => {
});
this.report(error, { kind: "storage_failed" }, context);
}
/**
* Internal commit exposing the concrete transaction and its internal operations, such as the reserved-ID root
* bootstrap and task replacement. `scope` sets the default `tx.createTask()` conversation and the task attributed to
* appended entries.
*/
commitWith(change, context, scope, options) {
let withinMs;
try {
this.assertUsable();
withinMs = this.#deferral(options?.persistence);
} catch (error) {
return Promise.reject(error);
}
return this.#enqueue((index) => this.#runCommit(change, context, scope, withinMs, index));
}
/**
* Internal: `commitWith()` for a commit of the scheduler's own whose outcome goes only to scheduler code. When it
* writes nothing and waited at no gate, it is equivalent to having run before every unpublished commit, so its
* outcome is delivered at once, ahead of theirs. One that writes is never exempt: its outcome waits for its own
* publication and every earlier outcome, so no invocation starts on a reservation that is not durable.
*/
commitInternal(change, context) {
try {
this.assertUsable();
} catch (error) {
return Promise.reject(error);
}
return this.#enqueue((index) => this.#runCommit(change, context, void 0, void 0, index), true);
}
/**
* Internal, on the line: call `end` once the outcome of the job on the line settles, its commit published or never to
* be; at once off the line.
*/
onJobEnd(end) {
const job = this.#current;
if (job === void 0) {
end();
return;
}
if (job.ends === void 0)
job.ends = [end];
else
job.ends.push(end);
}
/** Internal: the Storage jobs on the line read through (`touch()`); off the line, use the plain one. */
get lineStorage() {
return this.#gated;
}
/** How long a commit may stay in memory before it is stored; `undefined` when it is immediate. */
#deferral(persistence) {
if (persistence?.kind !== "deferred")
return void 0;
const ms = persistence.withinMs;
if (ms === void 0)
return this.#persistWithinMs();
if (typeof ms !== "number" || !(ms >= 0)) {
throw new TypeError("CommitPersistence.withinMs must be a number of milliseconds, 0 or more");
}
return ms;
}
/** Internal: whether `tx` is the transaction of one of this Session's commits. */
ownsTransaction(tx) {
return Transaction.ownedBy(tx, this.#host);
}
/**
* Internal: run a read-only job on the mutation line so multi-read derivations observe one committed state. It reads
* through `storage`, whose reads wait for the publication of what the line admitted before; its outcome comes after
* theirs.
*/
readOnLine(job) {
try {
this.assertUsable();
} catch (error) {
return Promise.reject(error);
}
return this.#enqueue(async () => {
this.#assertHealthy();
return { value: await job(this.#gated) };
});
}
/**
* Internal: a conversation document's current incarnation and value, for a job already running on the line (see
* `readOnLine()`). Absent documents are `undefined`.
*/
async conversationDocumentOnLine(token, conversationId, context) {
const definition = token.definition;
const resolved = resolveAddress(definition, [conversationId, context]);
const loaded = await this.#loadDocument(definition, resolved.id, resolved.address, context);
if (loaded === void 0)
return void 0;
checkRecordScope(definition, loaded.record);
checkRecordVersion(definition, loaded.record, loaded.storedVersion);
return { record: loaded.record, version: loaded.valueVersion, value: loaded.tracker.value };
}
async snapshot(token, ...args) {
this.assertUsable();
const definition = token.definition;
const resolved = resolveAddress(definition, args);
const context = args[resolved.nextArgument];
const cached = this.#documents.get(resolved.id);
if (cached?.valueVersion === definition.version)
this.#touchDocument(resolved.id);
const loaded = cached?.valueVersion === definition.version ? cached : await this.#enqueue(async () => {
this.#assertHealthy();
return { value: await this.#loadDocument(definition, resolved.id, resolved.address, context) };
});
if (loaded === void 0)
return void 0;
checkRecordScope(definition, loaded.record);
checkRecordVersion(definition, loaded.record, loaded.storedVersion);
return loaded.tracker.value;
}
watchDoc(token, ...args) {
try {
this.assertUsable();
const definition = token.definition;
const resolved = resolveAddress(definition, args);
const context = args[resolved.nextArgument];
const signal = context.abortSignal;
return this.#attachDocument(definition, resolved, context, (loaded) => {
const watch2 = this.#observeDocument(definition, loaded, createWatch, endWatch);
if (signal !== void 0)
watch2.observeAbort(signal);
return watch2;
}, abortWatch);
} catch (error) {
return Promise.reject(error);
}
}
observeDoc(token, ...args) {
try {
this.assertUsable();
const definition = token.definition;
const resolved = resolveAddress(definition, args);
const observer = args[resolved.nextArgument];
const context = args[resolved.nextArgument + 1];
return this.#attachDocument(definition, resolved, context, (loaded) => {
const guarded = this.#observeDocument(definition, loaded, (_value, detach, report2) => guardObserver(observer, detach, report2), endGuarded);
return observation(loaded.tracker.value, guarded);
}, detachObservation);
} catch (error) {
return Promise.reject(error);
}
}
async snapshotAsOf(token, ...args) {
this.assertUsable();
const definition = token.definition;
const resolved = resolveAddress(definition, args);
if (resolved.address.scope.kind !== "conversation") {
throw new TypeError("Session.snapshotAsOf() requires a conversation document");
}
const conversationId = resolved.address.scope.conversationId;
const atValue = args[resolved.nextArgument];
if (typeof atValue !== "number" || !Number.isSafeInteger(atValue)) {
throw new TypeError("Session.snapshotAsOf() requires an entry ID");
}
const at = idFromNumber(atValue);
const context = args[resolved.nextArgument + 1];
return this.#enqueue(async () => {
this.#assertHealthy();
const storedEntry = await this.#gated.entry(conversationId, at, context);
if (storedEntry === void 0) {
throw new Error(`Entry ${at} is not visible from conversation ${conversationId}`);
}
const address = {
...resolved.address,
scope: { kind: "conversation", conversationId: storedEntry.entry.conversationId }
};
const record = await this.#gated.findDocument(address, storedEntry.commitSeq, context);
if (record === void 0)
return { value: void 0 };
const stored = await this.#gated.document(record.id, storedEntry.commitSeq, context);
if (stored === void 0) {
throw new Error(`Historical document ${record.id} (${record.kind}) cannot be read`);
}
return { value: materializeDocument(definition, stored) };
});
}
close(context) {
if (this.#closing === void 0) {
const cleanup = withoutAbortSignal(context);
this.#closing = Promise.resolve().then(() => this.beforeClose()).then(() => this.#maintain(async () => {
await this.#drained();
let unstored;
if (this.#failure === void 0 && this.#holds.size > 0) {
await this.#storeHolds(() => [...this.#holds.values()], cleanup).catch((error) => {
unstored = { error };
});
}
const observers = [...this.#commitListeners];
this.#commitListeners.clear();
const end = closeEnds(this.#failure).observer;
for (const observer of observers)
observer.end(end);
this.#internalListeners.clear();
this.#documents.clear();
this.#idleDocuments.clear();
this.#attachedDocuments.clear();
this.#holds.clear();
this.#taskDocuments.clear();
try {
await this.#storage.close(cleanup);
} catch (error) {
if (this.#failure === void 0) {
this.#failure = { error };
this.report(error, { kind: "storage_failed" });
}
throw error;
}
if (unstored !== void 0)
throw unstored.error;
})).finally(() => {
const failure = this.#failure;
this.#closed.resolve(failure === void 0 ? { kind: "closed" } : { kind: "failed", error: failure.error });
});
this.#notifyClose();
}
return awaitWithContext(this.#closing, context);
}
/** Run the close listeners once, each on its own: one that fails is reported, and the rest still run. */
#notifyClose() {
this.#documentSweep?.disarm?.();
this.#documentSweep = void 0;
this.#holdTimer?.disarm();
this.#holdTimer = void 0;
const listeners = [...this.#closeListeners];
this.#closeListeners.clear();
for (const listener of listeners)
contained(listener, (error) => this.report(error));
}
/**
* Internal: the Session's failure, and errors of listeners, which never fail what ran them; `info` defaults to a
* listener. A plain Session drops them.
*/
report(_error, _info = LISTENER, _context) {
}
/**
* Runs inside every transaction that creates or forks a conversation, after the conversation record is staged. A
* plain Session stages nothing; a Harness stages its built-in documents.
*/
conversationCreated(_tx, _record) {
return Promise.resolve();
}
/**
* Internal, for `beforeClose()`: on the line, after every commit admitted before the seal has settled, write what
* `writes()` returns then straight to Storage. Nothing is published, since the Session is closing; a failed Session
* writes nothing.
*/
writeAtClose(writes) {
return this.#maintain(async (index) => {
await this.#drained();
if (this.#failure !== void 0)
return;
const batch = writes();
if (batch.length === 0)
return;
const context = BACKGROUND_CONTEXT;
await this.#writer.admit({
index,
writes: batch,
keys: [],
context,
publish: () => void 0,
discard: ignore
}).outcome;
});
}
/**
* Keys a commit writes besides its records' (`Transaction.writeKeys()`), at its admission, on the line: a Harness
* adds the ownership memberships its task changes write. A plain Session adds none.
*/
membershipKeys(_tx) {
return NO_KEYS;
}
/** Runs after close seals admission and before the line closes Storage; must not reject. */
beforeClose() {
return Promise.resolve();
}
/**
* Attach a synchronous observer of every stored commit, with exactly what it stored (`CommitPublication`). Its
* `advance` runs one microtask after the commit's publication, which follows its storage call, in line order, before
* every wait the commit resolves and every abort it queues (in no order with watch listeners); it must not block or
* call Session operations. A throw is reported, detaches it, and ends it `listener_error`; `end` gets the Session's
* close after its last publication.
*/
observeCommits(observer) {
this.assertUsable();
const guarded = guardObserver(observer, () => this.#commitListeners.delete(guarded), (error, context) => this.report(error, LISTENER, context));
this.#commitListeners.add(guarded);
return { detach: () => guarded.detach() };
}
/**
* Internal: follow every commit as memory adopts it (`ObservedCommit`), for the Session's own components, whose state
* follows memory. A throw leaves that state behind, so it fails the Session instead of being reported. They run at
* the commit's publication, synchronously, so they call no Storage method, run no task code, and contain every host
* callback; the waits they resolve and the aborts they queue run after host observers.
*/
followCommits(listener) {
this.assertUsable();
this.#internalListeners.add(listener);
return () => this.#internalListeners.delete(listener);
}
/**
* Register a listener called synchronously when close begins, also when a failure closes the Session (`failure` is
* then set). It must not block or call Session operations; a throw is reported.
*/
subscribeClose(listener) {
this.assertUsable();
this.#closeListeners.add(listener);
return () => this.#closeListeners.delete(listener);
}
/** Drop every loaded tracker on the mutation line, held changes stored first; later access cold-loads from Storage. */
unloadDocuments() {
return this.#maintain(async () => {
if (this.#failure === void 0)
await this.#storeHolds(() => [...this.#holds.values()], BACKGROUND_CONTEXT);
this.#documents.clear();
this.#idleDocuments.clear();
});
}
/**
* Internal, for tests: how many documents the cache holds, how many are idle, how many incarnations are pinned, how
* many sweep jobs were queued on the line so far, how many documents have held changes, how many live tasks have
* their documents indexed, and how many conversations have their newest entry kept.
*/
get documentCacheSizes() {
return {
cached: this.#documents.size,
idle: this.#idleDocuments.size,
attached: this.#attachedDocuments.size,
sweeps: this.#sweepJobs,
held: this.#holds.size,
taskDocuments: this.#taskDocuments.size,
tails: this.#tails?.size ?? 0
};
}
/**
* Internal, for tests that bound memory: jobs whose outcome is not delivered yet, keys with an unpublished writer,
* and record reads in flight in the cache. All three are 0 once the line is idle.
*/
get lineSizes() {
return {
outstanding: this.#outstanding,
unpublished: this.#writer.unpublished,
reads: this.#cached?.readsInFlight ?? 0
};
}
/** Note a use of a cached document: an unattached one becomes the newest idle one, and an eviction is scheduled. */
#touchDocument(addressId2) {
const cached = this.#documents.get(addressId2);
if (cached === void 0 || this.#attachedDocuments.has(cached.record.id))
return;
const now = this.#clock();
const since = this.#idleDocuments.get(addressId2);
if (since !== void 0 && now - since < Math.min(1e3, this.#documentRetentionMs() / 10))
return;
this.#idleDocuments.delete(addressId2);
this.#idleDocuments.set(addressId2, now);
if (this.#documentSweep === void 0 || this.#documentSweep.at > now + this.#documentRetentionMs()) {
this.#scheduleDocumentSweep();
}
}
#dropDocument(addressId2) {
this.#documents.delete(addressId2);
this.#idleDocuments.delete(addressId2);
}
/**
* Schedule the eviction of the oldest idle document: on the line at once when the retention is 0, otherwise when it
* expires, by a background timer (`HarnessOptions.setTimer`), which never keeps the process alive. Where the host
* declines it, as the default does in Cloudflare Workers, none is kept: the end of each commit evicts what expired.
*/
#scheduleDocumentSweep() {
if (this.#closing !== void 0)
return;
let oldest;
for (const [addressId2, since] of this.#idleDocuments) {
if (this.#writer.gate(documentKey(addressId2)) !== void 0)
continue;
oldest = since;
break;
}
if (oldest === void 0)
return;
const at = oldest + this.#documentRetentionMs();
if (this.#documentSweep !== void 0 && this.#documentSweep.at <= at)
return;
this.#documentSweep?.disarm?.();
const sweep = { at, disarm: void 0 };
const run2 = () => {
this.#sweepJobs++;
this.#maintain(async () => {
if (this.#documentSweep === sweep)
this.#documentSweep = void 0;
if (this.#closing === void 0)
this.#sweepDocuments();
}).catch(() => {
});
};
const delay = at - this.#clock();
this.#documentSweep = sweep;
if (delay <= 0) {
queueMicrotask(run2);
return;
}
if (this.#documentTimersUnavailable) {
this.#documentSweep = void 0;
return;
}
const disarm = this.#timers.background(run2, delay);
if (disarm === void 0) {
this.#documentTimersUnavailable = true;
this.#documentSweep = void 0;
return;
}
sweep.disarm = disarm;
}
/** On the line: evict the idle documents whose retention passed, oldest first, then schedule the next eviction. */
#sweepDocuments() {
const expired = this.#clock() - this.#documentRetentionMs();
for (const [addressId2, since] of this.#idleDocuments) {
if (since > expired)
break;
if (this.#writer.gate(documentKey(addressId2)) !== void 0)
continue;
this.#dropDocument(addressId2);
}
this.#scheduleDocumentSweep();
}
/** Pin a cached incarnation for one observer; the returned release unpins it once, idle again after the last. */
#pinDocument(addressId2, recordId) {
this.#attachedDocuments.set(recordId, (this.#attachedDocuments.get(recordId) ?? 0) + 1);
this.#idleDocuments.delete(addressId2);
let pinned = true;
return () => {
if (!pinned)
return;
pinned = false;
const count = (this.#attachedDocuments.get(recordId) ?? 1) - 1;
if (count > 0) {
this.#attachedDocuments.set(recordId, count);
return;
}
this.#attachedDocuments.delete(recordId);
if (this.#documents.get(addressId2)?.record.id === recordId)
this.#touchDocument(addressId2);
};
}
async #runCommit(change, context, scope, withinMs, index) {
this.#assertHealthy();
context.abortSignal?.throwIfAborted();
const tx = new Transaction(this.#host, context, scope);
let result;
try {
result = await change(tx);
this.#assertHealthy();
} catch (error) {
await tx.settleFailure();
this.#sweepDocuments();
throw error;
}
let writes;
try {
writes = await tx.settleSuccess();
} catch (error) {
this.#sweepDocuments();
throw error;
}
if (writes.length === 0) {
tx.discard();
this.#sweepDocuments();
return { value: result };
}
if (this.#readOnly) {
tx.discard();
this.#sweepDocuments();
throw new ReadOnlySession("a commit with writes");
}
const discard = () => tx.discard();
if (withinMs !== void 0) {
const held = tx.holdable();
if (held !== void 0) {
const part2 = this.#writer.admit({
index,
writes: void 0,
keys: tx.writeKeys(),
context,
publish: () => this.#hold(tx, held, withinMs, context),
discard
});
this.#sweepDocuments();
return { value: result, after: part2.outcome };
}
}
let membership = this.membershipKeys(tx);
if (!Array.isArray(membership)) {
try {
membership = await membership;
} catch (error) {
tx.discard();
this.#sweepDocuments();
throw error;
}
}
const taken = this.#holds.size === 0 ? NO_HOLDS : tx.takeHeld((id) => this.#holds.get(id));
const keys = tx.writeKeys();
for (const key of membership)
keys.push(key);
const part = this.#writer.admit({
index,
writes,
keys,
context,
publish: (seq) => this.#adopt(tx, writes, taken, seq, context),
discard
});
this.#sweepDocuments();
return { value: result, after: part.outcome };
}
/**
* Publish a stored commit (`Writer`), after the read caches took its writes: adopt it in memory and run its
* publication. A throw of the adoption leaves memory behind durable state; the writer fails the Session with it.
*/
#adopt(tx, writes, taken, seq, context) {
let documents;
try {
documents = tx.adopt(seq);
} catch (error) {
return { kind: "adoption", error };
}
this.#indexTaskDocuments(tx, writes, documents, seq);
const failure = this.#publish(seq, writes, documents, context);
if (taken.length > 0)
this.#release(taken);
for (const document of documents.stored)
this.#touchDocument(addressId(document.record));
return failure === void 0 ? void 0 : { kind: "listener", error: failure.error };
}
/**
* At publication: keep `#taskDocuments` in step with a stored commit: the tasks it creates start with no documents,
* task documents it creates join their task, ones it retires leave, and tasks it ends leave the index.
*/
#indexTaskDocuments(tx, writes, documents, seq) {
for (const id of tx.createdTaskIds())
this.#taskDocuments.set(id, /* @__PURE__ */ new Map());
if (this.#taskDocuments.size === 0)
return;
for (const change of documents.stored) {
if (change.type !== "document" || change.record.scope.kind !== "task")
continue;
const known = this.#taskDocuments.get(change.record.scope.taskId);
if (known === void 0)
continue;
if (change.kind === "retire")
known.delete(change.record.id);
else if (change.record.createdAt === seq)
known.set(change.record.id, change.record);
}
for (const write of writes) {
if (write.type === "task" && write.value.state.status === "terminal")
this.#taskDocuments.delete(write.value.id);
}
}
/**
* Hold a deferred commit (`Transaction.holdable()`): adopt it in memory, queue its changes per document, pinned, by
* the earliest deadline of the document's held commits, and show it to the Session's own observers.
*/
#hold(tx, held, withinMs, context) {
let documents;
try {
documents = tx.adoptHeld();
} catch (error) {
return { kind: "adoption", error };
}
const deadline = this.#clock() + withinMs;
for (const { loaded, ops: ops2, base } of held) {
const id = loaded.record.id;
let hold = this.#holds.get(id);
if (hold === void 0) {
const unpin = this.#pinDocument(loaded.addressId, id);
hold = { loaded, pending: new PendingOps(), base: false, deadline, unpin };
this.#holds.set(id, hold);
}
hold.pending.push(ops2);
if (base)
hold.base = true;
if (deadline < hold.deadline)
hold.deadline = deadline;
}
this.#armHoldTimer();
const publication = { kind: "memory", changes: documents };
let failure;
for (const listener of [...this.#internalListeners]) {
try {
listener(publication, context);
} catch (error) {
failure ??= { kind: "listener", error };
}
}
return failure;
}
/**
* Store the held changes `select` returns in one storage transaction, through the writer, from a job on the line. A
* barrier: they are selected once every commit admitted before is published. Memory already has them, so only
* `observeCommits()` observers see it, published as the writer publishes it. A failure fails the Session, as every
* Storage failure does.
*/
async #storeHolds(select, context) {
await this.#drained();
const holds = select();
if (holds.length === 0)
return;
const writes = [];
const changes = [];
const keys = [];
for (const hold of holds) {
const { record, tracker, valueVersion: version } = hold.loaded;
const value2 = tracker.value;
const stored = storeHeld(hold, NO_OPERATIONS, value2, version);
writes.push({ type: "document.change", id: record.id, content: stored.content });
keys.push(documentKey(hold.loaded.addressId), incarnationKey(record.id));
const conversationId = record.scope.kind === "conversation" ? record.scope.conversationId : void 0;
changes.push({ type: "document", kind: "change", record, conversationId, version, value: value2, ops: stored.ops });
}
const publish2 = (seq) => {
for (const [index2, hold] of holds.entries()) {
if (writes[index2].content.kind === "base")
hold.loaded.deltasSinceBase = 0;
else
hold.loaded.deltasSinceBase++;
}
if (this.#commitListeners.size > 0)
this.#notifyHosts({ seq, changes }, context);
this.#release(holds);
return void 0;
};
const index = this.#current.index;
await this.#writer.admit({ index, writes, keys, context, publish: publish2, discard: ignore }).outcome;
}
/** After their store: forget `holds`, unpin their documents, and move the timer to the next deadline. */
#release(holds) {
for (const hold of holds) {
this.#holds.delete(hold.loaded.record.id);
hold.unpin();
}
this.#armHoldTimer();
}
/**
* Keep a foreground timer (Workers refuse background ones) for the earliest deadline of the held documents. When it
* fires, every held document is stored, in one storage transaction: a deadline is the latest time, and the others
* cost little more in the same transaction. Once fired, it stays until its job ran.
*/
#armHoldTimer() {
if (this.#closing !== void 0)
return;
let at = Infinity;
for (const hold of this.#holds.values())
if (hold.deadline < at)
at = hold.deadline;
const armed = this.#holdTimer;
if (armed !== void 0 && (armed.fired || armed.at === at))
return;
armed?.disarm();
this.#holdTimer = void 0;
if (at === Infinity)
return;
const timer = { at, disarm: () => {
}, fired: false };
const run2 = () => {
timer.fired = true;
this.#maintain(async () => {
if (this.#holdTimer === timer)
this.#holdTimer = void 0;
if (this.#closing !== void 0 || this.#failure !== void 0)
return;
await this.#storeHolds(() => [...this.#holds.values()], BACKGROUND_CONTEXT);
}).catch(() => {
});
};
this.#holdTimer = timer;
timer.disarm = this.#timers.foreground(run2, Math.max(0, at - this.#clock()));
}
/**
* At publication: publish a stored commit. Its telemetry events first, then the dispatch to `observeCommits()`
* observers, queued before the waits and aborts the observers wake, then the Session's own observers. Never throws:
* returns the first error of an own observer, which fails the Session once its storage call settled.
*/
#publish(seq, writes, documents, context) {
const changes = this.#commitListeners.size > 0 || this.#internalListeners.size > 0 ? [] : void 0;
for (const write of writes) {
switch (write.type) {
case "entry":
this.#event("pi.durable.entry", { "entry.id": write.value.id, "entry.kind": write.value.kind }, context);
changes?.push(write);
break;
case "submission":
if (write.value.status === "done" || write.value.status === "unanswered") {
this.#event("pi.durable.submission", {
"submission.id": write.value.id,
status: write.value.status,
"answer.entry_id": write.value.answer
}, context);
}
changes?.push(write);
break;
case "conversation":
case "task":
changes?.push(write);
}
}
if (changes === void 0)
return void 0;
const tables = changes.length;
for (const document of documents.observed)
changes.push(document);
const observed = { kind: "stored", seq, changes };
if (this.#commitListeners.size > 0) {
const stored = documents.stored === documents.observed ? observed : { seq, changes: [...changes.slice(0, tables), ...documents.stored] };
this.#notifyHosts(stored, context);
}
let failure;
for (const listener of [...this.#internalListeners]) {
try {
listener(observed, context);
} catch (error) {
failure ??= { error };
}
}
return failure;
}
/** At publication: record a commit's telemetry event. A throwing adapter is reported, as publication must not throw. */
#event(name, attributes, context) {
try {
context.telemetry.addEvent(name, attributes);
} catch (error) {
this.report(error, TELEMETRY, context);
}
}
/**
* At publication: call the `observeCommits()` observers with `publication` one microtask from now, and, queued
* before the Session's own observers run, before the waits they resolve and the aborts they queue. The observers are
* those attached when it runs; their guards report a throw.
*/
#notifyHosts(publication, context) {
void SETTLED.then(() => {
for (const observer of [...this.#commitListeners])
observer.advance(publication, context);
});
}
/**
* On the line, as one job: load the document at `resolved` and `attach` to it, so the attachment sees every commit
* after the value it starts from; `undefined` when absent. Cancelling `context` meanwhile rejects, after `cancel`
* undid an attachment made.
*/
async #attachDocument(definition, resolved, context, attach, cancel) {
const signal = context.abortSignal;
let cancelled = signal?.aborted ?? false;
const markCancelled = () => {
cancelled = true;
};
signal?.addEventListener("abort", markCancelled, { once: true });
try {
const attached = await this.#enqueue(async () => {
this.#assertHealthy();
if (cancelled)
throw cancellationError(signal);
const loaded = await this.#loadDocument(definition, resolved.id, resolved.address, context);
if (cancelled)
throw cancellationError(signal);
return { value: loaded === void 0 ? void 0 : attach(loaded) };
});
if (attached === void 0)
return void 0;
if (cancelled) {
cancel(attached);
throw cancellationError(signal);
}
return attached;
} finally {
signal?.removeEventListener("abort", markCancelled);
}
}
/**
* Follow the address of the incarnation `loaded`, after checking the definition, with the observer `create` makes
* from its value, the idempotent detach, and the report of a listener error; returns that observer. It gets each
* committed change there, a retirement as a `retired` change with the last value it was given and no ops (a change
* in the retiring commit is not published), and a later incarnation as a root replacement. When the commit makes the
* owner task of a task document terminal, no later commit can change the address: after its changes the commit
* subscription and the pin go, and `ownerEnded` tells the observer, which stays subscribed to the Session's close
* until it ends (its detach drops that). `end` gets the Session's close. The current incarnation is pinned in the
* cache. The detach runs before `end`; once it ran, nothing more of the commit underway reaches the observer or pins
* anything for it. `create` and `ownerEnded` are module functions where they can be, so a watch keeps no closure of
* its caller.
*/
#observeDocument(definition, loaded, create, ownerEnded) {
checkRecordScope(definition, loaded.record);
checkRecordVersion(definition, loaded.record, loaded.storedVersion);
const addressId2 = loaded.addressId;
const address = loaded.record;
let incarnation = loaded.record.id;
let value2 = loaded.tracker.value;
let version = loaded.valueVersion;
let unpin = this.#pinDocument(addressId2, incarnation);
let unsubscribeCommit = () => {
};
let unsubscribeClose = () => {
};
let attached = true;
const detach = () => {
if (!attached)
return;
attached = false;
unsubscribeCommit();
unsubscribeClose();
unpin();
};
const observer = create(loaded.tracker.value, detach, (error) => this.report(error));
unsubscribeCommit = this.followCommits((publication, context) => {
if (!attached)
return;
let ownerEnds = false;
for (const change of publication.changes) {
if (change.type === "task") {
const scope = address.scope;
if (scope.kind === "task" && change.value.id === scope.taskId && change.value.state.status === "terminal") {
ownerEnds = true;
}
continue;
}
if (change.type !== "document")
continue;
if (change.record.id !== incarnation && !atAddress(change.record, address))
continue;
if (change.kind === "retire") {
if (change.record.id !== incarnation)
continue;
const last = value2;
incarnation = void 0;
value2 = void 0;
unpin();
observer.advance({ kind: "value", value: last, ops: NO_OPERATIONS, retired: true }, context);
} else if (change.record.id !== incarnation || change.version !== version) {
if (change.record.id !== incarnation) {
incarnation = change.record.id;
unpin();
unpin = this.#pinDocument(addressId2, incarnation);
}
version = change.version;
value2 = change.value;
observer.advance({ kind: "value", value: value2, ops: [["r", value2]], retired: false }, context);
} else {
if (change.ops.length === 0)
continue;
value2 = change.value;
observer.advance({ kind: "value", value: value2, ops: change.ops, retired: false }, context);
}
if (!attached)
return;
}
if (!ownerEnds)
return;
unsubscribeCommit();
unpin();
ownerEnded(observer);
});
unsubscribeClose = this.subscribeClose(() => {
detach();
observer.end(closeEndOf(observer, closeEnds(this.#failure)));
});
return observer;
}
async #loadDocument(definition, addressId2, address, context) {
const gate = this.touch(documentKey(addressId2));
if (gate !== void 0)
await gate;
const cached = this.#documents.get(addressId2);
if (cached?.valueVersion === definition.version) {
this.#touchDocument(addressId2);
return cached;
}
if (cached !== void 0) {
const id = cached.record.id;
await this.#storeHolds(() => {
const hold = this.#holds.get(id);
return hold === void 0 ? NO_HOLDS : [hold];
}, context);
this.#dropDocument(addressId2);
}
const record = await this.#storage.findDocument(address, "current", context);
if (record === void 0)
return void 0;
const stored = await this.#storage.document(record.id, "current", context);
if (stored === void 0)
throw new Error(`Current document ${record.id} (${record.kind}) cannot be read`);
const value2 = materializeDocument(definition, stored);
const loaded = {
addressId: addressId2,
record: stored.record,
storedVersion: stored.version,
valueVersion: definition.version,
deltasSinceBase: stored.deltasSinceBase,
tracker: track(value2)
};
this.#documents.set(addressId2, loaded);
this.#touchDocument(addressId2);
return loaded;
}
/**
* Run `job` on the line, after the jobs before it, and deliver its outcome in line order: once the jobs before it
* have theirs, and once its commit, if it admitted one, is published. With `exempt`, a job that admitted no commit and
* waited at no gate is delivered as soon as it has its outcome: it is equivalent to having run before every
* unpublished commit. A job
* whose outcome comes after the one a failure is gets `SessionFailed` instead. At most `MAX_OUTSTANDING` jobs wait
* for their delivery; beyond it the line waits.
*/
#enqueue(work, exempt = false) {
const job = { index: this.#nextIndex++, hit: false };
const ran = this.#tail.then(async () => {
while (this.#outstanding >= MAX_OUTSTANDING) {
this.#room ??= Promise.withResolvers();
await this.#room.promise;
}
this.#outstanding++;
return this.#onLine(job, work);
});
this.#tail = ran.then(ignore, ignore);
const outcome = ran.then((result) => {
if (result.after === void 0) {
this.#ended(job);
return result.value;
}
return result.after.then(() => {
this.#ended(job);
return result.value;
}, (error) => {
this.#ended(job);
throw error;
});
}, (error) => {
this.#ended(job);
throw error;
});
outcome.catch(ignore);
const fence = this.#fence;
this.#fence = fence.then(() => outcome).then(ignore, ignore);
const index = job.index;
const deliver = (fenced) => (fenced ? fence.then(() => outcome) : outcome).then((value2) => {
this.#delivered(index, fenced);
if (this.#poisoned(index))
throw new SessionFailed(this.#failure.error);
return value2;
}, (error) => {
this.#delivered(index, fenced);
throw this.#poisoned(index) ? new SessionFailed(this.#failure.error) : error;
});
return exempt ? ran.then((result) => deliver(job.hit || result.after !== void 0), () => deliver(job.hit)) : deliver(true);
}
/** Whether job `index` comes after the failure's boundary without an outcome of its own: it gets `SessionFailed`. */
#poisoned(index) {
return this.#failAt !== void 0 && index > this.#failAt && !this.#ownOutcomes.has(index);
}
/** The job's outcome settled: run what waited for it (`onJobEnd()`). */
#ended(job) {
const ends = job.ends;
if (ends === void 0)
return;
job.ends = void 0;
for (const end of ends)
end();
}
/** Run a job of the Session's own upkeep on the line: no outcome to deliver, so no fence and no `SessionFailed`. */
#maintain(work) {
const job = { index: this.#nextIndex++, hit: false };
const ran = this.#tail.then(() => this.#onLine(job, work));
this.#tail = ran.then(ignore, ignore);
return ran;
}
/** Hold the line for job `index` until its line part, through admission, is done. Gates are its touches' own. */
async #onLine(job, work) {
this.#current = job;
try {
return await work(job.index);
} finally {
this.#current = void 0;
}
}
/** A `*` barrier: once every part admitted so far is published, or never will be. */
async #drained() {
const drained = this.#writer.drained();
if (drained !== void 0)
await drained;
}
/**
* Run one commit's publication inside the Storage's own scope (`Storage.publishing`), such as a store host's batch;
* directly without one. `undefined` when it ran at once, else settles once it ran. A Storage that throws instead of
* running it is reported, and the publication runs directly: the commit is stored, so it must be published.
*/
#publishing(publish2, context) {
const publishing = this.#storage.publishing;
if (publishing === void 0) {
publish2();
return void 0;
}
const done = Promise.withResolvers();
let ran = false;
const once = () => {
if (ran)
return;
ran = true;
try {
publish2();
} finally {
done.resolve();
}
};
try {
publishing(once, context);
} catch (error) {
this.report(error, LISTENER, context);
once();
}
return done.promise;
}
/** Job `index` has its outcome: let the line go on past `MAX_OUTSTANDING`. */
#delivered(index, fenced) {
if (fenced)
this.#lastDelivered = index;
this.#outstanding--;
const room = this.#room;
if (room !== void 0 && this.#outstanding < MAX_OUTSTANDING) {
this.#room = void 0;
room.resolve();
}
}
/** Internal: throw `SessionFailed` when failed, else an error when closing. */
assertUsable() {
this.#assertHealthy();
if (this.#closing !== void 0)
throw new Error("Session is closed");
}
#assertHealthy() {
if (this.#failure !== void 0)
throw new SessionFailed(this.#failure.error);
}
};
function contained(callback, onError) {
try {
const result = callback();
if (typeof result?.then === "function")
Promise.resolve(result).catch(onError);
} catch (error) {
onError(error);
}
}
function guardObserver(observer, detach, report2) {
let attached = { observer, detach, report: report2 };
const release = () => {
const released = attached;
attached = void 0;
released?.detach();
return released;
};
const fault = (current, error, context) => {
current.report(error, context);
if (release() !== void 0) {
const end = { kind: "listener_error", error: toError2(error) };
contained(() => current.observer.end(end), current.report);
}
};
return {
advance: (call, context) => {
const current = attached;
if (current === void 0)
return;
try {
const result = current.observer.advance(call, context);
if (typeof result?.then === "function") {
Promise.resolve(result).catch((error) => fault(current, error, context));
}
} catch (error) {
fault(current, error, context);
}
},
end: (end) => {
const ending = release();
if (ending !== void 0)
contained(() => ending.observer.end(end), ending.report);
},
detach: () => {
release();
}
};
}
function toError2(error) {
if (error instanceof Error)
return error;
try {
return new Error(String(error));
} catch {
return new Error(Object.prototype.toString.call(error));
}
}
var ENDED2 = { kind: "ended" };
function closeEnds(failure) {
if (failure !== void 0) {
const failed = { kind: "failed", error: failure.error };
return { watch: failed, observer: failed };
}
return { watch: ENDED2, observer: { kind: "failed", error: new Error("session closed") } };
}
function closeEndOf(follower, ends) {
return follower instanceof Watch ? ends.watch : ends.observer;
}
function observation(value2, guarded) {
return { value: value2, detach: () => guarded.detach() };
}
function createWatch(value2, detach, report2) {
return new Watch(value2, detach, report2);
}
function abortWatch(watch2) {
watch2.abort();
}
function detachObservation(attached) {
attached.detach();
}
function endWatch(watch2) {
watch2.endAfterDelivery();
}
function endGuarded(guarded) {
guarded.end(ENDED2);
}
function atAddress(record, address) {
if (record.kind !== address.kind || record.key !== address.key)
return false;
switch (record.scope.kind) {
case "session":
return address.scope.kind === "session";
case "conversation":
return address.scope.kind === "conversation" && address.scope.conversationId === record.scope.conversationId;
case "task":
return address.scope.kind === "task" && address.scope.taskId === record.scope.taskId;
}
}
function cancellationError(signal) {
return signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted", "AbortError");
}
var GuardedStorage = class {
#storage;
#latch;
/** Backend calls underway, also those off the Session line, which close waits for before it closes the backend. */
#underway = /* @__PURE__ */ new Set();
#closing = false;
constructor(storage, latch) {
this.#storage = storage;
this.#latch = latch;
}
/** The backend's own scope for a publication (`Storage.publishing`), when it has one; not a call to guard. */
get publishing() {
return scopeOf(this.#storage);
}
/**
* Guarded like every call, but its outcome is the Session writer's to judge: it publishes the batches received first,
* then fails the Session for a refusal or a rejection, and for a Session that failed meanwhile.
*/
async commit(batches, receive, context) {
this.#assertHealthy();
if (this.#closing)
throw new Error("Session is closed");
const call = (async () => this.#storage.commit(batches, receive, context))();
this.#underway.add(call);
try {
return await call;
} finally {
this.#underway.delete(call);
}
}
mintId() {
return this.#call(void 0, () => this.#storage.mintId());
}
conversation(id, context) {
return this.#call(context, () => this.#storage.conversation(id, context));
}
scanConversations(query, limit2, cursor, context) {
return this.#call(context, () => this.#storage.scanConversations(query, limit2, cursor, context));
}
entry(first, second, third) {
if (third === void 0) {
const context = second;
return this.#call(context, () => this.#storage.entry(first, context));
}
return this.#call(third, () => this.#storage.entry(first, second, third));
}
findLatestHeadMarker(conversationId, atOrBeforeEntryId, context) {
return this.#call(context, () => this.#storage.findLatestHeadMarker(conversationId, atOrBeforeEntryId, context));
}
scanEntries(query, limit2, cursor, context) {
return this.#call(context, () => this.#storage.scanEntries(query, limit2, cursor, context));
}
task(id, context) {
return this.#call(context, () => this.#storage.task(id, context));
}
scanTasks(query, limit2, cursor, context) {
return this.#call(context, () => this.#storage.scanTasks(query, limit2, cursor, context));
}
submission(id, context) {
return this.#call(context, () => this.#storage.submission(id, context));
}
scanSubmissions(query, limit2, cursor, context) {
return this.#call(context, () => this.#storage.scanSubmissions(query, limit2, cursor, context));
}
submissionByRequest(conversationId, requestId, context) {
return this.#call(context, () => this.#storage.submissionByRequest(conversationId, requestId, context));
}
findDocument(address, at, context) {
return this.#call(context, () => this.#storage.findDocument(address, at, context));
}
document(id, at, context) {
return this.#call(context, () => this.#storage.document(id, at, context));
}
scanDocuments(query, limit2, cursor, context) {
return this.#call(context, () => this.#storage.scanDocuments(query, limit2, cursor, context));
}
/**
* Close the backend once every call underway has settled, so none outlives it or fails after `closed` settles. New
* calls are refused from here on: a paged read must not start its next page while the backend closes.
*/
async close(context) {
this.#closing = true;
await Promise.allSettled([...this.#underway]);
return this.#storage.close(context);
}
/**
* Run one backend call under the guard. `read` is a read's context; `commit()` and `mintId()` pass none, so nothing
* exempts their errors: once a batch is admitted, whether it committed is unknown. A call still underway when another
* fails the Session ends with `SessionFailed` too, whatever it returns: nothing it read or wrote is used.
*/
async #call(read2, run2) {
this.#assertHealthy();
if (this.#closing)
throw new Error("Session is closed");
let result;
const call = (async () => run2())();
this.#underway.add(call);
try {
result = await call;
} catch (error) {
this.#assertHealthy();
const exempt = read2 !== void 0 && (error instanceof StorageRequestError || read2.abortSignal?.aborted === true);
if (!exempt)
this.#latch.fail(error);
throw error;
} finally {
this.#underway.delete(call);
}
this.#assertHealthy();
return result;
}
#assertHealthy() {
const failure = this.#latch.failure;
if (failure !== void 0)
throw new SessionFailed(failure.error);
}
};
// node_modules/@earendil-works/pi-durable/dist/harness/agent.js
var DEFAULT_RETRY_POLICY = {
enabled: true,
maxRetries: 3,
baseDelayMs: 2e3,
maxAgentDelayMs: 6e4
};
var DEFAULT_COMPACTION_POLICY = {
enabled: true,
reserveTokens: 16384,
keepRecentTokens: 2e4,
backgroundTokens: 32768
};
var DEFAULT_PROGRESS_POLICY = {
partialIntervalMs: 100,
outputIntervalMs: 100,
persistWithinMs: 1e3
};
var INSTRUCTIONS_KEY = "instructions";
var AgentDoc = defineDoc({
kind: "pi.agent",
version: 1,
scope: "conversation",
history: "rewindable",
fork: "asOf",
initial: () => ({}),
checkpointWhen: () => true
});
var DEFAULT_CONTEXT_RETENTION_MS = 6e5;
var DEFAULT_RESTART_LIMIT = 5;
function restartLimit(limit2) {
return typeof limit2 === "number" && limit2 >= 1 ? Math.floor(limit2) : DEFAULT_RESTART_LIMIT;
}
function resolveSettings(settings) {
const extensions = settings?.extensions;
return {
...extensions === void 0 ? {} : { extensions },
stream: { ...settings?.stream },
retry: { ...DEFAULT_RETRY_POLICY, ...settings?.retry },
compaction: { ...DEFAULT_COMPACTION_POLICY, ...settings?.compaction },
// Field by field, so an explicitly undefined interval keeps its default.
progress: {
partialIntervalMs: settings?.progress?.partialIntervalMs ?? DEFAULT_PROGRESS_POLICY.partialIntervalMs,
outputIntervalMs: settings?.progress?.outputIntervalMs ?? DEFAULT_PROGRESS_POLICY.outputIntervalMs,
persistWithinMs: persistWithin(settings?.progress?.persistWithinMs)
},
toolExecution: settings?.toolExecution ?? "parallel",
steeringMode: settings?.steeringMode ?? "one-at-a-time",
followUpMode: settings?.followUpMode ?? "one-at-a-time",
contextRetentionMs: settings?.contextRetentionMs ?? DEFAULT_CONTEXT_RETENTION_MS,
documentRetentionMs: documentRetention(settings?.documentRetentionMs),
afterFailedRun: settings?.afterFailedRun ?? "keep",
restartLimit: restartLimit(settings?.restartLimit)
};
}
async function configure(tx, conversationId, change) {
const state2 = await tx.doc(AgentDoc, conversationId);
applyChange(state2, change);
}
async function addTools(tx, conversationId, added) {
const state2 = await tx.doc(AgentDoc, conversationId);
const tools = state2.tools;
if (Array.isArray(tools)) {
for (const name of added)
if (!tools.includes(name))
tools.push(name);
} else if (tools?.remove.some((name) => added.includes(name))) {
state2.tools = { remove: tools.remove.filter((name) => !added.includes(name)) };
}
const modelTools = state2.modelTools;
if (Array.isArray(modelTools)) {
for (const name of added)
if (!modelTools.includes(name))
modelTools.push(name);
return;
}
const remove = (modelTools?.remove ?? []).filter((name) => !added.includes(name));
const add = [...modelTools?.add ?? []];
for (const name of added)
if (!add.includes(name))
add.push(name);
state2.modelTools = { ...remove.length === 0 ? {} : { remove }, add };
}
function applyChange(state2, change) {
const set = (key, value2) => {
if (value2 === void 0)
return;
if (value2 === null)
delete state2[key];
else
state2[key] = value2;
};
set("model", change.model === void 0 || change.model === null ? change.model : { ...change.model });
set("thinkingLevel", change.thinkingLevel);
const extensions = change.extensions;
set("extensions", extensions === void 0 || extensions === null ? extensions : isList(extensions) ? names(extensions) : {
...extensions.add === void 0 ? {} : { add: names(extensions.add) },
...extensions.remove === void 0 ? {} : { remove: names(extensions.remove) }
});
const tools = change.tools;
set("tools", tools === void 0 || tools === null ? tools : isList(tools) ? names(tools) : { remove: names(tools.remove) });
const modelTools = change.modelTools;
set("modelTools", modelTools === void 0 || modelTools === null ? modelTools : isList(modelTools) ? names(modelTools) : {
...modelTools.remove === void 0 ? {} : { remove: names(modelTools.remove) },
...modelTools.add === void 0 ? {} : { add: names(modelTools.add) }
});
set("instructions", change.instructions);
set("cwd", change.cwd);
const maxTurns = change.maxTurns;
if (maxTurns !== void 0 && maxTurns !== null && !(Number.isSafeInteger(maxTurns) && maxTurns >= 1)) {
throw new RangeError(`maxTurns must be an integer 1 or more, got ${String(maxTurns)}`);
}
set("maxTurns", maxTurns);
}
function isList(value2) {
return Array.isArray(value2);
}
function names(items) {
return items.map((item) => item.name);
}
async function createAgent(tx, conversation) {
if (conversation.parent !== void 0)
return;
const agent = await tx.doc(AgentDoc, conversation.id);
if (conversation.owner === void 0)
return;
const owner = await tx.doc(AgentDoc, conversation.owner.conversationId);
Object.assign(agent, copyJson(owner));
}
function agentHooks(agent, taskName) {
const handlers = [];
for (const extension of agent.extensions) {
for (const hook of extension.hooks ?? []) {
if (hook.task === taskName)
handlers.push({ extension: extension.name, handlers: hook.handlers });
}
}
return handlers;
}
function sectionExtension(agent, key) {
let found;
for (const extension of agent.extensions) {
const provides = extension.sections?.some((section) => section.key === key) === true;
const wraps = extension.wraps?.some((wrap) => "section" in wrap && wrap.section === key) === true;
if (provides || wraps)
found = extension.name;
}
return found;
}
function toolExtension(agent, name) {
let found;
for (const extension of agent.extensions) {
const provides = extension.tools?.some((tool) => tool.name === name) === true;
const wraps = extension.wraps?.some((wrap) => "tool" in wrap && wrap.tool === name) === true;
if (provides || wraps)
found = extension.name;
}
return found;
}
function resolveAgent(state2, snapshot, settings, report2) {
const extensions = selectExtensions(state2?.extensions, snapshot, settings);
const composed = /* @__PURE__ */ new Map();
for (const extension of extensions)
for (const tool of extension.tools ?? [])
composed.set(tool.name, tool);
const sections = /* @__PURE__ */ new Map();
for (const extension of extensions) {
for (const section of extension.sections ?? [])
sections.set(section.key, section);
}
for (const extension of extensions) {
for (const wrap of extension.wraps ?? []) {
const wrapReport = (error) => report2(error, extension.name);
if ("tool" in wrap)
applyWrap(composed, wrap.tool, (tool) => wrap.wrap(tool), (tool) => tool.name, wrapReport);
else
applyWrap(sections, wrap.section, (section) => wrap.wrap(section), (section) => section.key, wrapReport);
}
}
const enabled = filterTools([...composed.values()], state2?.tools);
const callableBy = (caller) => (tool) => tool.callers === void 0 || tool.callers.includes(caller);
const modelCallable = enabled.filter(callableBy("model"));
const tools = offeredTools(modelCallable, state2?.modelTools);
const offered = new Set(tools);
const deferred = modelCallable.filter((tool) => tool.deferred === true && !offered.has(tool));
const callable = enabled.filter(callableBy("tools"));
const instructions = state2?.instructions;
const agentSections = [...sections.values()];
if (instructions !== void 0)
agentSections.push({ key: INSTRUCTIONS_KEY, render: () => instructions });
const agent = {
...state2?.model === void 0 ? {} : { model: state2.model },
thinkingLevel: state2?.thinkingLevel ?? "off",
extensions,
tools,
callable,
deferred,
sections: agentSections,
...instructions === void 0 ? {} : { instructions },
...state2?.cwd === void 0 ? {} : { cwd: state2.cwd },
...state2?.maxTurns === void 0 ? {} : { maxTurns: state2.maxTurns }
};
return agent;
}
function offeredTools(tools, filter) {
if (Array.isArray(filter))
return filterTools(tools, filter);
const removed = new Set(filter?.remove ?? []);
const kept = tools.filter((tool) => tool.deferred !== true && !removed.has(tool.name));
const byName = new Map(tools.map((tool) => [tool.name, tool]));
const loaded = [...new Set(filter?.add ?? [])].flatMap((name) => {
const tool = byName.get(name);
return tool?.deferred === true && !removed.has(name) ? [tool] : [];
});
return [...kept, ...loaded];
}
function filterTools(tools, filter) {
if (filter === void 0)
return tools;
if (Array.isArray(filter)) {
const byName = new Map(tools.map((tool) => [tool.name, tool]));
return [...new Set(filter)].flatMap((name) => {
const tool = byName.get(name);
return tool === void 0 ? [] : [tool];
});
}
const removed = new Set(filter.remove);
return tools.filter((tool) => !removed.has(tool.name));
}
function selectExtensions(stored, snapshot, settings) {
let selected;
if (Array.isArray(stored))
selected = stored;
else {
const base = settings.extensions?.map((extension) => extension.name) ?? snapshot.installed().map((e) => e.name);
const edit = stored;
const removed = new Set(edit?.remove ?? []);
selected = [...base, ...edit?.add ?? []].filter((name) => !removed.has(name));
}
const extensions = [];
for (const name of new Set(selected)) {
const extension = snapshot.extension(name);
if (extension !== void 0)
extensions.push(extension);
}
return extensions;
}
function applyWrap(items, target, wrap, nameOf, report2) {
const item = items.get(target);
if (item === void 0)
return;
try {
const wrapped = wrap(item);
if (nameOf(wrapped) !== target)
throw new Error(`Wrapper renamed ${target} to ${nameOf(wrapped)}`);
items.set(target, wrapped);
} catch (error) {
items.delete(target);
report2(error);
}
}
// node_modules/@earendil-works/pi-durable/dist/harness/compaction.js
init_estimate();
// node_modules/@earendil-works/pi-ai/dist/utils/retry.js
function buildProviderErrorPattern(patterns) {
return new RegExp(patterns.join("|"), "i");
}
var NON_RETRYABLE_PROVIDER_LIMIT_ERROR_PATTERN = buildProviderErrorPattern([
// OpenCode Go/free-tier limits returned as 429 JSON error types by OpenCode's
// Zen API. These are subscription/account limits, not transient throttles.
"GoUsageLimitError",
"FreeUsageLimitError",
// OpenCode Go subscription-limit text asks users to enable available-balance
// usage after rolling/weekly/monthly limits are reached.
"Monthly usage limit reached",
"available balance",
// Generic quota/budget/billing exhaustion. `insufficient_quota` is OpenAI's
// quota/billing error code; the other strings cover common gateway wording.
"insufficient_quota",
"out of budget",
"quota exceeded",
"billing",
// Sign in with ChatGPT: the subscription's shared usage limit, which resets
// after hours rather than seconds.
"subscription_sharing_usage_limit_exceeded",
// Sign in with ChatGPT on a ChatGPT Business plan: a usage limit set by the
// workspace admin. Only the admin can raise it.
"subscription_sharing_workplace_individual_usage_limit_exceeded",
// Zhipu/Z.ai (open.bigmodel.cn) error code 1308: the plan's usage limit is
// reached, sent as HTTP 429. It resets after hours, not seconds (#11537).
'"code"\\s*:\\s*"?1308(?![0-9])'
]);
var RETRYABLE_PROVIDER_ERROR_PATTERN = buildProviderErrorPattern([
// Generic provider load, HTTP status, and server-side transient failures.
"overloaded",
"server_busy",
"servers are currently busy",
"currently experiencing high demand",
"model is at capacity",
"rate.?limit",
"too many requests",
// Status codes must not be part of a longer word or number, e.g. a request id or byte count (#11057).
"(?<![a-z0-9])(?:429|500|502|503|504|520|524)(?![a-z0-9])",
// Also matches "The service is temporarily unavailable" (#10965).
"service.?(?:is.?)?(?:temporarily.?)?unavailable",
"server.?error",
"internal.?error",
// Wrapper/provider text for transient upstream failures, including OpenRouter
// "Provider returned error" responses (#2264) and gateway wording such as
// "The upstream provider returned an error" (#10842).
"provider.?returned.?(?:an.?)?error",
"exceeded request buffer limit while retrying upstream",
// Gateway failure relaying the upstream response stream, sent as an OpenAI
// Responses `response.failed` event without an error code (#10920).
"unable to forward upstream",
// Other gateway upstream failures relayed as `response.failed` error codes (#10920).
"upstream.?request.?failed",
"upstream_stream_read_error",
"stream was interrupted",
"http/?2 stream failed",
// Network, proxy, and fetch transport failures. This includes OpenAI Codex
// raw-fetch failures such as "upstream connect", "connection refused", and
// "reset before headers" (#733), plus OpenRouter connection drops (#3317).
"network.?error",
"connection.?error",
"connection.?refused",
"connection.?lost",
"other side closed",
"fetch failed",
// node-fetch system errors, e.g. the Google ADC OAuth token refresh used by
// google-vertex. The reason is often empty (#10996).
"request to \\S+ failed, reason:",
"getaddrinfo",
"ENOTFOUND",
"EAI_AGAIN",
"upstream.?connect",
"reset before headers",
"socket hang up",
"socket connection was closed",
"timed? out",
"timeout",
"terminated",
// WebSocket transports can report close/error text instead of HTTP/fetch text.
"websocket.?closed",
"websocket.?error",
// Premature stream endings from SDKs and transports. Anthropic can throw
// "stream ended without ..." and "Anthropic stream ended before message_stop"
// (#4433); Bedrock/Smithy can throw an HTTP/2 no-response error (#3594).
"ended without",
"stream ended before message_stop",
"stream ended before a terminal response event",
"http2 request did not get a response",
// Codex CLI mid-stream disconnect, relayed by proxies that wrap the Codex CLI,
// e.g. "stream disconnected before completion: stream closed before response.completed" (#11057).
"stream disconnected before completion",
// Node ERR_HTTP2_STREAM_CANCEL: the HTTP/2 session died before the request was
// sent, e.g. after the Bedrock SDK's 5-minute session timeout (#10379).
"pending stream has been canceled",
// Provider-requested retry delay cap failures should flow through the outer
// retry policy so callers can surface/abort the backoff (#1123).
"retry delay",
// Explicit retry guidance emitted mid-stream by OpenAI Responses and Bedrock
// stream exceptions (#6019).
"you can retry your request",
"try your request again",
"please retry your request",
// gRPC based providers (e.g. NVIDIA NIM)
"ResourceExhausted",
// Sign in with ChatGPT: usage or user data temporarily unavailable. Usage
// failures can arrive mid-stream without an HTTP 503 in the message.
"subscription_sharing_usage_unavailable",
"subscription_sharing_user_unavailable"
]);
var DEFAULT_MAX_AGENT_RETRY_DELAY_MS = 6e4;
function retryDelayMs(policy, attempt) {
const delay = policy.baseDelayMs * 2 ** Math.max(0, attempt - 1);
const safeDelay = Number.isSafeInteger(delay) ? delay : Number.MAX_SAFE_INTEGER;
return Math.min(safeDelay, policy.maxAgentDelayMs ?? DEFAULT_MAX_AGENT_RETRY_DELAY_MS);
}
function isRetryableAssistantError(message) {
if (message.stopReason !== "error" || !message.errorMessage)
return false;
const errorMessage3 = message.errorMessage;
if (NON_RETRYABLE_PROVIDER_LIMIT_ERROR_PATTERN.test(errorMessage3))
return false;
return RETRYABLE_PROVIDER_ERROR_PATTERN.test(errorMessage3);
}
// node_modules/@earendil-works/pi-durable/dist/tasks.js
function defineTask(definition) {
return { definition };
}
// node_modules/@earendil-works/pi-durable/dist/harness/context.js
var SCAN_PAGE_SIZE2 = 256;
var EXCLUDED_STOP_REASONS = /* @__PURE__ */ new Set(["aborted", "error", "deferred"]);
var MISSING_RESULT_TEXT = "Tool result unavailable: history ends before this call completed.";
async function captureContextBounds(session, storage, conversationId, context, at, visible = false) {
let tail;
if (at === void 0) {
tail = await session.latestEntryId(conversationId, context);
if (tail === void 0)
return void 0;
} else {
if (!visible && await storage.entry(conversationId, at, context) === void 0) {
throw new Error(`Entry ${at} is not visible from conversation ${conversationId}`);
}
tail = at;
}
return { head: await session.latestHeadMarker(conversationId, tail, context), tail };
}
async function readContextFrom(session, storage, conversationId, context, at, previous) {
const visible = at !== void 0 && previous !== void 0 && rangeEntry(previous, at) !== void 0;
const bounds = await session.readOnLine((line) => captureContextBounds(session, line, conversationId, context, at, visible));
if (bounds === void 0)
return { view: emptyView(), range: void 0 };
freezeJson(bounds.head);
const current = at === void 0;
let range;
if (previous === void 0 || previous.bounds.head?.id !== bounds.head?.id) {
const entries2 = freezeJson(await scanRange(storage, conversationId, rangeQuery(bounds), context));
range = deriveRange(bounds, entries2, current);
} else if (bounds.tail === previous.bounds.tail) {
range = previous;
} else if (bounds.tail < previous.bounds.tail) {
range = deriveRange(bounds, previous.entries.filter((entry2) => entry2.id <= bounds.tail), false);
} else {
const minEntryId = idFromNumber(previous.bounds.tail + 1);
const added = await scanRange(storage, conversationId, { minEntryId, maxEntryId: bounds.tail }, context);
range = extendRange(previous, bounds, freezeJson(added), current);
}
if (range.current && session.knownLatestEntryId(conversationId) !== range.bounds.tail) {
range = { ...range, current: false };
}
const { view: view2 } = range;
return {
view: {
...view2,
entries: [...view2.entries],
contributions: [...view2.contributions],
messages: [...view2.messages]
},
range
};
}
async function readContext(session, storage, conversationId, context, at) {
const bounds = await session.readOnLine((line) => captureContextBounds(session, line, conversationId, context, at));
return deriveContext(storage, conversationId, bounds, context);
}
async function deriveContext(storage, conversationId, bounds, context) {
if (bounds === void 0)
return emptyView();
return deriveRange(bounds, await scanRange(storage, conversationId, rangeQuery(bounds), context), false).view;
}
function emptyView() {
return { head: void 0, entries: [], contributions: [], messages: [] };
}
function rangeEntry(range, id) {
const entries2 = range.entries;
let low = 0;
let high = entries2.length - 1;
while (low <= high) {
const middle = low + high >>> 1;
const entry2 = entries2[middle];
if (entry2.id === id)
return entry2;
if (entry2.id < id)
low = middle + 1;
else
high = middle - 1;
}
return void 0;
}
function advanceRange(range, appended) {
if (!range.current || appended.length === 0)
return range;
const added = freezeJson(appended);
let head = range.bounds.head;
for (const entry2 of added)
if (entry2.head !== void 0)
head = entry2;
const bounds = { head, tail: added.at(-1).id };
if (head?.id === range.bounds.head?.id)
return extendRange(range, bounds, added, true);
const start = head.head;
if (range.bounds.head !== void 0 && start < range.bounds.head.head)
return void 0;
const entries2 = [...range.entries, ...added].filter((entry2) => entry2.id >= start);
return deriveRange(bounds, entries2, true);
}
function deriveRange(bounds, entries2, current) {
const edits = /* @__PURE__ */ new Map();
for (const entry2 of entries2)
for (const edit of entry2.edits ?? [])
edits.set(edit.target, edit);
const active = selectActive(bounds.head, entries2);
const contributions = active.map((entry2) => contribute(entry2, edits.get(entry2.id)));
const { settled, open } = settle([], contributions.flat());
const baseline = findBaseline(bounds.head, active);
const messages = leadWithSystem([...settled, ...orderToolResults(open)], baseline);
const view2 = { head: bounds.head, entries: active, contributions, messages };
return { bounds, entries: entries2, view: view2, edited: new Set(edits.keys()), settled, open, baseline, current };
}
function extendRange(previous, bounds, added, current) {
const entries2 = [...previous.entries, ...added];
if (added.some((entry2) => entry2.edits !== void 0 || entry2.head !== void 0 || previous.edited.has(entry2.id))) {
return deriveRange(bounds, entries2, current);
}
const contributions = added.map((entry2) => contribute(entry2, void 0));
const { settled, open } = settle(previous.settled, [...previous.open, ...contributions.flat()]);
const baseline = previous.baseline !== void 0 ? previous.baseline : findBaseline(bounds.head, added);
const view2 = {
head: bounds.head,
entries: [...previous.view.entries, ...added],
contributions: [...previous.view.contributions, ...contributions],
messages: leadWithSystem([...settled, ...orderToolResults(open)], baseline)
};
return { bounds, entries: entries2, view: view2, edited: previous.edited, settled, open, baseline, current };
}
function findBaseline(head, entries2) {
for (const entry2 of entries2) {
if (head !== void 0 && entry2.id <= head.id)
continue;
if (SystemEntry.is(entry2))
return entry2.model?.find((message) => message.role === "system") ?? null;
if (head === void 0 && carriesSystemMessage(entry2))
return null;
}
return void 0;
}
function carriesSystemMessage(entry2) {
const isSystem = (message) => message.role === "system";
return (entry2.model?.some(isSystem) ?? false) || (entry2.edits?.some((edit) => edit.action === "replace" && edit.messages.some(isSystem)) ?? false);
}
function leadWithSystem(messages, baseline) {
const index = messages.findIndex((message) => message.role === "system");
if (index <= 0)
return messages;
const system = messages[index];
if (system !== baseline && messages.slice(0, index).some((message) => message.role !== "user")) {
return messages;
}
return [system, ...messages.slice(0, index), ...messages.slice(index + 1)];
}
function contribute(entry2, edit) {
if (edit?.action === "omit")
return Object.freeze([]);
const contributed = edit?.action === "replace" ? edit.messages : entry2.model ?? [];
return Object.freeze(contributed.filter((message) => message.role !== "assistant" || !EXCLUDED_STOP_REASONS.has(message.stopReason)));
}
var deeplyFrozen = /* @__PURE__ */ new WeakSet();
function freezeJson(value2) {
if (value2 === null || typeof value2 !== "object" || deeplyFrozen.has(value2))
return value2;
for (const child of Object.values(value2))
freezeJson(child);
Object.freeze(value2);
deeplyFrozen.add(value2);
return value2;
}
function settle(settled, open) {
const last = open.findLastIndex((message) => message.role === "assistant");
if (last <= 0)
return { settled, open };
return { settled: [...settled, ...orderToolResults(open.slice(0, last))], open: open.slice(last) };
}
function rangeQuery(bounds) {
const head = bounds.head;
return head === void 0 ? { maxEntryId: bounds.tail } : { minEntryId: head.head, maxEntryId: bounds.tail };
}
async function scanRange(storage, conversationId, range, context) {
const entries2 = [];
let cursor;
do {
const page2 = await storage.scanEntries({ conversationId, ...range }, SCAN_PAGE_SIZE2, cursor, context);
entries2.push(...page2.items);
cursor = page2.next;
} while (cursor !== void 0);
return entries2.reverse();
}
function selectActive(head, range) {
return head === void 0 ? range : [head, ...range.filter((entry2) => entry2.head === void 0)];
}
function orderToolResults(messages) {
const ordered = [];
for (let index = 0; index < messages.length; index++) {
const message = messages[index];
if (message.role === "toolResult")
continue;
ordered.push(message);
if (message.role !== "assistant")
continue;
const calls = message.content.filter((content) => content.type === "toolCall");
if (calls.length === 0)
continue;
const results = /* @__PURE__ */ new Map();
for (let next = index + 1; next < messages.length && messages[next].role !== "assistant"; next++) {
const candidate = messages[next];
if (candidate.role === "toolResult" && !results.has(candidate.toolCallId)) {
results.set(candidate.toolCallId, next);
}
}
for (const call of calls) {
const resultIndex = results.get(call.id);
ordered.push(resultIndex === void 0 ? missingResult(call, message.timestamp) : messages[resultIndex]);
}
}
return ordered;
}
function missingResult(call, timestamp) {
return freezeJson({
role: "toolResult",
toolCallId: call.id,
toolName: call.name,
content: [{ type: "text", text: MISSING_RESULT_TEXT }],
isError: true,
details: { reason: "missing_result" },
timestamp
});
}
// node_modules/@earendil-works/pi-ai/dist/utils/overflow.js
var OVERFLOW_PATTERNS = [
/prompt (?:is )?too long/i,
// Anthropic and z.ai token overflow
/prompt exceeds max length/i,
// z.ai CN endpoint token overflow
/request_too_large/i,
// Anthropic request byte-size overflow (HTTP 413)
/input is too long for requested model/i,
// Amazon Bedrock
/exceeds the context window/i,
// OpenAI (Completions & Responses API)
/exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\d,]+ tokens?|\s*\([\d,]+\))/i,
// OpenAI-compatible proxies (LiteLLM)
/context window exceeded/i,
// LiteLLM pre-call check (ContextWindowExceededError)
/input token count.*exceeds the maximum/i,
// Google (Gemini)
/maximum prompt length is \d+/i,
// xAI (Grok)
/reduce the length of the messages/i,
// Groq
/maximum context length is \d+ tokens/i,
// OpenRouter (most backends)
/exceeds (?:the )?maximum allowed input length of [\d,]+ tokens?/i,
// OpenRouter/Poolside
/input \(\d+ tokens\) is longer than the model'?s context length \(\d+ tokens\)/i,
// Together AI
/exceeds the limit of \d+/i,
// GitHub Copilot
/exceeds the available context size/i,
// llama.cpp server
/greater than the context length/i,
// LM Studio
/context window exceeds limit/i,
// MiniMax
/exceeded model token limit/i,
// Kimi For Coding
/too large for model with \d+ maximum context length/i,
// Mistral
/prompt has [\d,]+ tokens?, but the configured context size is [\d,]+ tokens?/i,
// DS4 server
/model_context_window_exceeded/i,
// z.ai non-standard finish_reason surfaced as error text
/prompt too long; exceeded (?:max )?context length/i,
// Ollama explicit overflow error
/range of input length should be/i,
// DashScope / Qwen Token Plan
/context[_ ]length[_ ]exceeded/i,
// Generic fallback
/too many tokens/i,
// Generic fallback
/token limit exceeded/i,
// Generic fallback
// HTTP 413 means request-size overflow regardless of provider or body text.
// Match raw SDK errors and formatProviderError's prefix, not a status mentioned in the body.
/^(?:[\w -]+ API error \(413\):|413(?:\s|:|$))/i
];
var CEREBRAS_BODYLESS_OVERFLOW_PATTERN = /^4(?:00|13)\s*(?:status code)?\s*\(no body\)/i;
var NON_OVERFLOW_PATTERNS = [
/^(Throttling error|Service unavailable):/i,
// AWS Bedrock non-overflow errors (human-readable prefixes from formatBedrockError)
/rate limit/i,
// Generic rate limiting
/too many requests/i
// Generic HTTP 429 style
];
function isContextOverflow(message, contextWindow) {
if (message.stopReason === "error" && message.errorMessage) {
const isNonOverflow = NON_OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage));
if (!isNonOverflow) {
if (OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage))) {
return true;
}
if (message.provider === "cerebras" && CEREBRAS_BODYLESS_OVERFLOW_PATTERN.test(message.errorMessage)) {
return true;
}
}
}
if (contextWindow && message.stopReason === "stop") {
const inputTokens = message.usage.input + message.usage.cacheRead;
if (inputTokens > contextWindow) {
return true;
}
}
if (contextWindow && message.stopReason === "length" && message.usage.output === 0) {
const inputTokens = message.usage.input + message.usage.cacheRead;
if (inputTokens >= contextWindow * 0.99) {
return true;
}
}
return false;
}
// node_modules/@earendil-works/pi-durable/dist/harness/generation.js
init_transcript();
// node_modules/@earendil-works/pi-durable/dist/harness/inbox.js
var InboxDoc = defineDoc({
kind: "pi.inbox",
version: 1,
scope: "conversation",
history: "latest",
fork: "initial",
initial: () => ({ items: [] }),
checkpointWhen: (value2) => value2.items.length === 0
});
async function prepareBoundary(tx, conversationId, modes) {
const head = (await tx.latestHeadMarker(conversationId))?.head;
const inbox = await tx.doc(InboxDoc, conversationId);
return {
conversationId,
inbox,
steeringMode: modes.steeringMode,
followUpMode: modes.followUpMode,
head
};
}
async function applyBoundary(tx, boundary, at, now) {
const { conversationId, inbox } = boundary;
const items = inbox.items;
const reset = hasQueuedReset(items);
const final = at === "final" || reset;
const pick = (mode, queueMode) => {
const indexes = items.flatMap((item, index) => item.mode === mode ? [index] : []);
return queueMode === "all" ? indexes : indexes.slice(0, 1);
};
const writes = items.flatMap((item, index) => item.mode === "write" ? [index] : []);
const users = [...pick("steer", boundary.steeringMode), ...final ? pick("followUp", boundary.followUpMode) : []];
users.sort((a, b) => a - b);
let first;
for (const index of writes) {
const item = items[index];
const draft = item.entry;
if (isStale(boundary, draft)) {
tx.settleSubmission(item.id, { status: "unanswered", reason: "stale" });
continue;
}
const entry2 = await tx.appendEntry(conversationId, draft);
if (draft.head !== void 0)
boundary.head = draft.head === "self" ? entry2.id : draft.head;
tx.placeSubmission(item.id, entry2.id);
first ??= entry2.id;
}
const placed = [];
for (const index of users) {
const item = items[index];
const entry2 = await appendInput(tx, conversationId, item.content, item.entry, now);
tx.placeSubmission(item.id, entry2.id);
placed.push(item.id);
first ??= entry2.id;
}
const removed = [...writes, ...users].sort((a, b) => b - a);
for (const index of removed)
items.splice(index, 1);
return { users: placed, first, reset };
}
function appendInput(tx, conversationId, content, entry2, now) {
const message = { role: "user", content, timestamp: now };
if (entry2 === void 0)
return tx.appendEntry(UserEntry, conversationId, { model: [message] });
return tx.appendEntry(conversationId, { ...pickInputEntry(entry2), model: [message] });
}
function pickInputEntry({ kind, data }) {
const picked = data === void 0 ? { kind } : { kind, data };
return copyJson(picked, { omitUndefinedProperties: true });
}
function isDisplayOnly(entry2) {
return entry2.model === void 0 && entry2.head === void 0 && entry2.edits === void 0;
}
function hasQueuedReset(items) {
return items.some((item) => item.mode === "write" && item.entry.head === "self");
}
function isStale(boundary, entry2) {
return typeof entry2.head === "number" && boundary.head !== void 0 && entry2.head < boundary.head;
}
async function removeInboxItem(tx, conversationId, id) {
const items = (await tx.doc(InboxDoc, conversationId)).items;
const index = items.findIndex((item) => item.id === id);
if (index >= 0)
items.splice(index, 1);
}
async function withdrawQueuedInputs(tx, conversationId, reason = "aborted") {
const items = (await tx.doc(InboxDoc, conversationId)).items;
for (let index = items.length - 1; index >= 0; index--) {
const item = items[index];
if (item.mode === "write")
continue;
tx.settleSubmission(item.id, { status: "unanswered", reason });
items.splice(index, 1);
}
}
// node_modules/@earendil-works/pi-durable/dist/harness/partial-changes.js
init_streaming_json();
// node_modules/@earendil-works/pi-durable/dist/harness/json.js
function assignJson(target, key, value2, plan) {
if (plan?.kind === "keep")
return;
const slots = target;
const current = key === "__proto__" && !Object.hasOwn(slots, key) ? void 0 : slots[key];
const fields = plan?.kind === "fields" ? plan.fields : void 0;
if (isRecord2(current) && isRecord2(value2)) {
for (const name of Object.keys(current))
if (!Object.hasOwn(value2, name))
delete current[name];
for (const [name, child] of Object.entries(value2))
assignJson(current, name, child, fields?.get(name));
return;
}
if (Array.isArray(current) && Array.isArray(value2) && current.length <= value2.length) {
const items = current;
for (let index = 0; index < value2.length; index++) {
if (index < items.length)
assignJson(items, index, value2[index], fields?.get(index));
else
items.push(value2[index]);
}
return;
}
if (plan?.kind === "append" && typeof current === "string" && typeof value2 === "string" && !Array.isArray(target) && current.length + plan.text.length === value2.length) {
appendText(target, String(key), plan.text);
return;
}
if (current !== value2)
slots[key] = value2;
}
function isRecord2(value2) {
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
}
// node_modules/@earendil-works/pi-durable/dist/harness/partial-changes.js
var PartialChanges = class {
#text = /* @__PURE__ */ new Map();
#toolCalls = /* @__PURE__ */ new Map();
/** Record what `event` changed. */
observe(event) {
switch (event.type) {
case "text_delta":
case "thinking_delta": {
const field = event.type === "text_delta" ? "text" : "thinking";
const pending = this.#text.get(event.contentIndex);
if (pending?.field === field)
pending.text += event.delta;
else
this.#text.set(event.contentIndex, { field, text: event.delta });
return;
}
case "toolcall_start":
this.#toolCalls.set(event.contentIndex, {
parser: new StreamingJsonParser(),
changes: [],
committed: false
});
return;
case "toolcall_delta": {
const call = this.#toolCalls.get(event.contentIndex);
if (call === void 0)
return;
for (const change of call.parser.append(event.delta)) {
if (change.path.length === 0 && !isRecord3(change.kind === "set" ? value(change) : null)) {
this.#toolCalls.delete(event.contentIndex);
return;
}
call.changes.push(change);
}
return;
}
case "text_end":
case "thinking_end":
this.#text.delete(event.contentIndex);
return;
case "toolcall_end":
this.#toolCalls.delete(event.contentIndex);
return;
}
}
/**
* Take what changed since the last call, for a commit of `message`, a copy of the partial. Clears the arguments of
* tracked tool calls in `message`: the commit writes them from the changes. Call `restore()` if the commit fails.
*/
take(message) {
const blocks = /* @__PURE__ */ new Map();
for (const [index, { field, text: text2 }] of this.#text) {
blocks.set(index, { kind: "fields", fields: /* @__PURE__ */ new Map([[field, { kind: "append", text: text2 }]]) });
}
this.#text = /* @__PURE__ */ new Map();
const toolCalls = /* @__PURE__ */ new Map();
for (const [index, call] of this.#toolCalls) {
const block = message.content[index];
if (block?.type !== "toolCall")
continue;
toolCalls.set(index, { changes: call.changes, snapshot: block.arguments });
block.arguments = {};
blocks.set(index, { kind: "fields", fields: /* @__PURE__ */ new Map([["arguments", { kind: "keep" }]]) });
call.changes = [];
}
return {
plan: { kind: "fields", fields: /* @__PURE__ */ new Map([["content", { kind: "fields", fields: blocks }]]) },
toolCalls
};
}
/**
* Write `message` with what `commit` took into `generation.message`: the message leaf by leaf with the plan, then the
* argument changes. A tracked call whose block is new here gets its arguments from its changes, which then start at
* its first piece; when the committed message lost a call whose changes were already committed (another writer reset
* it), the call falls back to its snapshot from now on.
*/
commit(generation, message, commit) {
const committedBlocks = generation.message?.content.length ?? 0;
const apply2 = [];
for (const [index, { changes, snapshot }] of commit.toolCalls) {
const call = this.#toolCalls.get(index);
if (call === void 0)
continue;
const block = message.content[index];
if (index >= committedBlocks && call.committed && block?.type === "toolCall") {
this.#toolCalls.delete(index);
block.arguments = snapshot;
continue;
}
call.committed = true;
apply2.push([index, changes]);
}
assignJson(generation, "message", message, commit.plan);
const content = generation.message?.content ?? [];
for (const [index, changes] of apply2) {
const block = content[index];
if (block?.type !== "toolCall")
continue;
for (const change of changes)
applyChange2(block, change);
}
}
/** Put back what a failed commit took, so the next commit applies it first. */
restore(commit) {
for (const [index, { changes }] of commit.toolCalls) {
const call = this.#toolCalls.get(index);
if (call !== void 0)
call.changes = [...changes, ...call.changes];
}
}
};
function applyChange2(block, change) {
const key = change.path.at(-1);
if (key === void 0) {
const root2 = change.kind === "set" ? value(change) : void 0;
if (isRecord3(root2))
block.arguments = root2;
return;
}
let parent = block.arguments;
for (const segment of change.path.slice(0, -1)) {
parent = parent[segment];
}
const slots = parent;
if (change.kind === "set")
slots[key] = value(change);
else if (Array.isArray(parent))
slots[key] = `${slots[key]}${change.text}`;
else
appendText(parent, String(key), change.text);
}
function value(change) {
return change.value;
}
function isRecord3(value2) {
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
}
// node_modules/@earendil-works/pi-durable/dist/harness/prompt.js
init_transcript();
function replaySections(messages) {
const shown = /* @__PURE__ */ new Map();
for (const message of messages) {
if (message.role !== "system" || message.sections === void 0)
continue;
for (const [key, value2] of Object.entries(message.sections)) {
if (value2 === null)
shown.delete(key);
else
shown.set(key, value2);
}
}
return shown;
}
async function renderSections(sections, input, shown, report2, context) {
const desired = /* @__PURE__ */ new Map();
for (const section of sections) {
let text2;
try {
text2 = await section.render(input, context);
} catch (error) {
if (context.abortSignal?.aborted)
throw error;
report2(error, section);
const kept = shown.get(section.key);
if (kept !== void 0)
desired.set(section.key, kept);
continue;
}
if (text2 === void 0)
continue;
desired.set(section.key, section.tag === false ? text2 : `<${section.key}>
${text2}
</${section.key}>`);
}
return desired;
}
function planSystemEntries(view2, desired, tools, timestamp) {
const head = view2.head;
if (head !== void 0 && !view2.entries.some((entry2) => SystemEntry.is(entry2) && entry2.id > head.id)) {
const edits = view2.entries.filter((entry2) => SystemEntry.is(entry2)).map((entry2) => ({ target: entry2.id, action: "omit" }));
const baseline = systemEntry(Object.fromEntries(desired), { toolsRemoved: [], toolsAdded: tools.map(toToolDeclaration) }, timestamp);
return [edits.length === 0 ? baseline : { ...baseline, edits }];
}
const sections = planSections(replaySections(view2.messages), desired);
const changes = planTools(getCurrentTools(view2.messages), tools);
if (changes.toolsRemoved.length === 0 && changes.toolsAdded.length === 0) {
return sections.map((patch) => systemEntry(patch, void 0, timestamp));
}
if (sections.length === 0)
return [systemEntry(void 0, changes, timestamp)];
return sections.map((patch, index) => systemEntry(patch, index === sections.length - 1 ? changes : void 0, timestamp));
}
function planTools(offered, desired) {
const wanted = new Map(desired.map((tool) => [tool.name, tool]));
const kept = offered.filter((tool) => {
const next = wanted.get(tool.name);
return next !== void 0 && declarationsEqual(tool, next);
});
const keptNames = new Set(kept.map((tool) => tool.name));
const added = desired.filter((tool) => !keptNames.has(tool.name));
const replayed = [...kept, ...added];
if (replayed.some((tool, index) => tool.name !== desired[index].name)) {
return {
toolsRemoved: offered.map((tool) => ({ name: tool.name })),
toolsAdded: desired.map(toToolDeclaration)
};
}
return {
toolsRemoved: offered.filter((tool) => !keptNames.has(tool.name)).map((tool) => ({ name: tool.name })),
toolsAdded: added.map(toToolDeclaration)
};
}
function planSections(shown, desired) {
const patchedOrder = [
...[...shown.keys()].filter((key) => desired.has(key)),
...[...desired.keys()].filter((key) => !shown.has(key))
];
const desiredOrder = [...desired.keys()];
if (patchedOrder.some((key, index) => key !== desiredOrder[index])) {
return [Object.fromEntries([...shown.keys()].map((key) => [key, null])), Object.fromEntries(desired)];
}
const patch = {};
for (const [key, value2] of shown) {
const next = desired.get(key);
if (next !== value2)
patch[key] = next ?? null;
}
for (const [key, value2] of desired)
if (!shown.has(key))
patch[key] = value2;
return Object.keys(patch).length === 0 ? [] : [patch];
}
function systemEntry(sections, tools, timestamp) {
const message = {
role: "system",
content: "",
...sections === void 0 ? {} : { sections },
...tools === void 0 || tools.toolsRemoved.length === 0 ? {} : { toolsRemoved: tools.toolsRemoved },
...tools === void 0 || tools.toolsAdded.length === 0 ? {} : { toolsAdded: tools.toolsAdded },
timestamp
};
return { model: [message] };
}
// node_modules/@earendil-works/pi-ai/dist/utils/uuid.js
var MAX_UUID_V7_TIMESTAMP = 281474976710655;
var MAX_SEQUENCE = (1n << 41n) - 1n;
var lastOrdinaryTimestamp = -1;
var sequence;
function uuidv7(timestampMs) {
const requestedTimestamp = timestampMs ?? Date.now();
if (!Number.isInteger(requestedTimestamp) || requestedTimestamp < 0 || requestedTimestamp > MAX_UUID_V7_TIMESTAMP) {
throw new RangeError(`UUIDv7 timestamp must be an integer between 0 and ${MAX_UUID_V7_TIMESTAMP}`);
}
const effectiveTimestamp = timestampMs === void 0 ? Math.max(requestedTimestamp, lastOrdinaryTimestamp) : timestampMs;
if (timestampMs === void 0)
lastOrdinaryTimestamp = effectiveTimestamp;
const bytes2 = new Uint8Array(16);
globalThis.crypto.getRandomValues(bytes2);
if (sequence === void 0) {
sequence = BigInt(bytes2[1]) << 32n | BigInt(bytes2[2]) << 24n | BigInt(bytes2[3]) << 16n | BigInt(bytes2[4]) << 8n | BigInt(bytes2[5]);
} else {
if (sequence === MAX_SEQUENCE)
throw new RangeError("UUIDv7 generator sequence exhausted");
sequence++;
}
const timestamp = BigInt(effectiveTimestamp);
for (let index = 5; index >= 0; index--) {
bytes2[index] = Number(timestamp >> BigInt((5 - index) * 8)) & 255;
}
bytes2[6] = 112 | Number(sequence >> 37n & 0x0fn);
bytes2[7] = Number(sequence >> 29n & 0xffn);
bytes2[8] = 128 | Number(sequence >> 23n & 0x3fn);
bytes2[9] = Number(sequence >> 15n & 0xffn);
bytes2[10] = Number(sequence >> 7n & 0xffn);
bytes2[11] = Number((sequence & 0x7fn) << 1n) | bytes2[11] & 1;
const hex = Array.from(bytes2, (byte) => byte.toString(16).padStart(2, "0"));
return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
}
// node_modules/@earendil-works/pi-durable/dist/harness/provider.js
var ProviderDoc = defineDoc({
kind: "pi.provider",
version: 1,
scope: "conversation",
history: "latest",
fork: "initial",
initial: () => ({ sessionId: uuidv7() }),
checkpointWhen: () => true
});
async function ensureProviderSessionId(runtime, context) {
const existing = await runtime.snapshot(ProviderDoc, runtime.conversationId, context);
if (existing !== void 0)
return existing.sessionId;
let created;
await runtime.commit(async (tx) => {
created = (await tx.doc(ProviderDoc, runtime.conversationId)).sessionId;
return void 0;
}, context);
if (created === void 0)
throw new Error(`Conversation ${runtime.conversationId} has no provider session ID`);
return created;
}
// node_modules/@earendil-works/pi-durable/dist/harness/scheduler.js
init_dist();
// node_modules/@earendil-works/pi-durable/dist/harness/telemetry.js
init_dist();
var entry = {
description: "A transcript entry was committed; content remains in the transcript.",
attributes: {
"entry.id": { type: "number", required: true, description: "Transcript entry ID.", cardinality: "high" },
"entry.kind": { type: "string", required: true, description: "Entry kind." }
}
};
var reportAttributes = {
type: {
type: "string",
required: true,
description: "Report kind (`Report.kind`).",
values: [
"storage_failed",
"task_faulted",
"task_interrupted",
"migration_failed",
"task_outdated",
"task_error",
"extension_error",
"host_error",
"listener_error"
]
},
reason: {
type: "string",
required: false,
description: "Fixed report reason, when present.",
values: ["threw", "restart_limit", "interrupted", "missing_task", "task_too_old", "migration_failed"]
},
extension: { type: "string", required: false, description: "Registered extension name, when present." },
"task.id": { type: "number", required: false, description: "Task ID, when present.", cardinality: "high" }
};
var report = {
description: "A report was raised; no error payload is recorded.",
attributes: reportAttributes
};
var submission = {
description: "A submission was settled.",
attributes: {
"submission.id": { type: "number", required: true, description: "Submission ID.", cardinality: "high" },
status: { type: "string", required: true, values: ["done", "unanswered"], description: "Settlement." },
"answer.entry_id": { type: "number", required: false, description: "Answer entry ID.", cardinality: "high" }
}
};
var DURABLE_TELEMETRY_SCHEMA = defineTelemetrySchema({
version: 1,
spans: {
"pi.durable.submit": {
description: "Public submission admission: with its commit for submit(draft, context); the admission only for submit(tx, draft), whose result is provisional (a later throw or storage failure of the caller's commit leaves no submission) and whose commit events go to the caller's commit context. Inputs and continues start root traces linked to their callers; writes are children. Internal admissions emit phase events only.",
parents: { kind: "any" },
startAttributes: {
"submission.type": {
type: "string",
required: true,
values: ["input", "write", "continue"],
description: "Submission type."
},
"conversation.id": { type: "number", required: true, description: "Conversation ID.", cardinality: "high" }
},
endAttributes: {
"submission.id": { type: "number", description: "Admitted submission ID.", cardinality: "high" },
result: {
type: "string",
values: ["queued", "placed", "done"],
description: "Admission result; stale writes report done."
}
},
events: { "pi.durable.entry": entry, "pi.durable.submission": submission, "pi.durable.report": report },
status: { default: "ok", errorWhen: "Admission failed." }
},
"pi.durable.phase": {
description: "One task phase invocation, including its decision commit, never a wait or restart.",
parents: { kind: "any" },
startAttributes: {
"task.id": { type: "number", required: true, description: "Task ID.", cardinality: "high" },
"task.name": { type: "string", required: true, description: "Registered task name." },
phase: { type: "string", required: true, description: "Invoked checkpoint phase." },
kind: { type: "string", required: true, values: ["run", "abort"], description: "Invocation kind." },
attempt: { type: "number", required: false, description: "Checkpoint attempt, when present." },
resumed: {
type: "boolean",
required: true,
description: "First invocation of a task loaded in this process."
}
},
endAttributes: {
outcome: { type: "string", description: "next=<phase>, waiting, sleeping, done, faulted, or aborted." },
"tool.name": { type: "string", description: "Called tool name." },
"tool.call_id": { type: "string", description: "Transcript tool call ID.", cardinality: "high" }
},
events: {
"pi.durable.entry": entry,
"pi.durable.submission": submission,
"pi.durable.report": report,
"pi.durable.checkpoint": {
description: "The running checkpoint's phase changed while the invocation continued.",
attributes: { phase: { type: "string", required: true, description: "Committed checkpoint phase." } }
},
"pi.durable.replay": {
description: "A nested tool call was answered from its stored result.",
attributes: { "tool.name": { type: "string", required: true, description: "Called tool name." } }
}
},
status: {
default: "ok",
errorWhen: "Faulted, failed, and orphaned outcomes use task_faulted, task_failed, and task_orphaned with a diagnostic capped at 500 characters. Aborted outcomes keep status ok."
}
}
},
metrics: {
"pi.durable.reports": {
kind: "counter",
description: "Reports raised, grouped by their fixed kind.",
attributes: { type: reportAttributes.type }
},
"pi.durable.phase.duration": {
kind: "histogram",
unit: "ms",
description: "Duration of a phase invocation and its decision commit.",
attributes: {
task: { type: "string", required: true, description: "Registered task name." },
phase: { type: "string", required: true, description: "Invoked checkpoint phase." },
outcome: { type: "string", required: true, description: "Phase outcome." }
}
},
"pi.durable.tasks.active": {
kind: "upDownCounter",
description: "Live tasks held by this Harness; decremented at terminal settlement or close.",
attributes: { task: { type: "string", required: true, description: "Registered task name." } }
}
}
});
// node_modules/@earendil-works/pi-durable/dist/harness/util.js
var Waiters = class {
#sets = /* @__PURE__ */ new Map();
add(key, context) {
const signal = context.abortSignal;
if (signal?.aborted)
return Promise.reject(signal.reason);
const waiter = Promise.withResolvers();
const set = this.#sets.get(key) ?? /* @__PURE__ */ new Set();
this.#sets.set(key, set.add(waiter));
if (signal !== void 0) {
const onAbort = () => {
set.delete(waiter);
if (set.size === 0 && this.#sets.get(key) === set)
this.#sets.delete(key);
waiter.reject(signal.reason);
};
signal.addEventListener("abort", onAbort, { once: true });
const detach = () => signal.removeEventListener("abort", onAbort);
waiter.promise.then(detach, detach);
}
return waiter.promise;
}
keys() {
return [...this.#sets.keys()];
}
resolve(key, value2) {
const set = this.#sets.get(key);
this.#sets.delete(key);
for (const waiter of set ?? [])
waiter.resolve(value2);
}
rejectAll(error) {
const sets = [...this.#sets.values()];
this.#sets.clear();
for (const set of sets)
for (const waiter of set)
waiter.reject(error);
}
};
async function scanAll(scan) {
const items = [];
let cursor;
do {
const page2 = await scan(cursor);
items.push(...page2.items);
cursor = page2.next;
} while (cursor !== void 0);
return items;
}
function closedError(session) {
const failure = session.failure;
return failure === void 0 ? new Error("Harness is closed") : new SessionFailed(failure.error);
}
function optionalExtension(extension) {
return extension === void 0 ? {} : { extension };
}
function conversationEntries(conversationId, query) {
return {
conversationId,
...query.minEntryId === void 0 ? {} : { minEntryId: query.minEntryId },
...query.maxEntryId === void 0 ? {} : { maxEntryId: query.maxEntryId },
...query.order === void 0 ? {} : { order: query.order }
};
}
// node_modules/@earendil-works/pi-durable/dist/harness/scheduler.js
var SCAN_PAGE_SIZE3 = 256;
var NO_KEYS2 = [];
var LIVE_STATUSES = ["pending", "running", "waiting", "sleeping", "completing"];
function blockedSubject(record) {
return {
id: record.id,
kind: record.kind,
version: record.version,
abortRequested: record.abortRequested,
...record.abortReason === void 0 ? {} : { abortReason: record.abortReason },
status: record.state.status
};
}
var CONTINUE = { kind: "continue" };
var PROGRESS = { kind: "progress" };
var END = { kind: "end" };
var CASCADE = { kind: "cascade" };
function conversationNode(id) {
return `c${id}`;
}
function conversationOf(node) {
return Number(node.slice(1));
}
function parentNode(node) {
return node.owner ?? conversationNode(node.conversationId);
}
var TaskScheduler = class {
#telemetry;
#activeMetric;
#durationMetric;
#resumed = /* @__PURE__ */ new Set();
#session;
#storage;
#registry;
#models;
#agent;
#settings;
#env;
#now;
#onWake;
#timers;
#writeAtClose;
#report;
#settleOutcome;
#limitsRestarts;
#withdrawInputs;
#conversation;
#context;
#live = /* @__PURE__ */ new Map();
/**
* Context range last read through a task runtime, per conversation: a later read, by any of its tasks, scans only
* newer entries. `idleSince` is the Harness time it was first seen idle. Derived and never persisted; dropped at the
* first idle check after `settings.contextRetentionMs` of idleness, and at close.
*/
#contexts = /* @__PURE__ */ new Map();
/**
* The idle kept contexts by `idleSince`, oldest first: the expiry order, so neither an expiry nor finding the next one
* scans `#contexts`. Kept sorted also when the Harness clock goes back (see `#markIdle`).
*/
#idleOrder = /* @__PURE__ */ new Map();
/** At least the newest `idleSince` in `#idleOrder` (drops do not lower it): an older one added means the clock went back. */
#idleNewest = Number.NEGATIVE_INFINITY;
/**
* A chain load resolved what `#idle()` treats as unknown for a live task whose chain is not loaded, which can make a
* scope idle without a task change below it; the next idle check then covers every scope.
*/
#unknownsChanged = false;
/** Idle checks that covered every scope (`idleState`, a test diagnostic). */
#fullIdleChecks = 0;
/** Background timer for the earliest expiry of an idle context, unless the host declined it (see `#scheduleExpiry`). */
#expiry;
#invocations = /* @__PURE__ */ new Map();
#taskWaiters = new Waiters();
/** Idle waiters by conversation; `undefined` waits for the whole Harness. */
#idleWaiters = new Waiters();
/** Definition whose migration failed per task; retried only once the registry resolves another definition. */
#failedMigrations = /* @__PURE__ */ new Map();
/** Owner task of each known conversation, `null` when ownerless. */
#edges = /* @__PURE__ */ new Map();
/** Ownership fields of the known terminal tasks, which walks pass through. */
#settled = /* @__PURE__ */ new Map();
/**
* Ended tasks and conversations found unneeded, dropped by `#sweep()` at the end of the commit's publication unless
* needed again by then: a chain load installs nodes before the work below them is listed.
*/
#dropQueue = /* @__PURE__ */ new Set();
/**
* The tree downward around live work: each node's child nodes that are live tasks or have nodes listed below them.
* A conversation's parent is its owner task; ownerless ones with work are in `#roots`.
*/
#below = /* @__PURE__ */ new Map();
#roots = /* @__PURE__ */ new Set();
/** Known tasks whose chain may not be loaded; every other known task's chain is, and stays, loaded. */
#unloaded = /* @__PURE__ */ new Set();
/** Live tasks with cancellation intent, the sources of abort cascades (spec §5.4). */
#intent = /* @__PURE__ */ new Set();
/** Live tasks that are not `completing`, the candidates of a reservation pass; ones found waiting leave it. */
#runnable = /* @__PURE__ */ new Set();
/** `completing` tasks the next finalize pass checks: those that started holding, and holders of ended work. */
#finalizeChecks = /* @__PURE__ */ new Set();
/** Live waiting tasks by each task in their `on`. */
#waiters = /* @__PURE__ */ new Map();
/**
* `failFast` waiters the next reconcile checks for a failed task in `on`: at open, when they start waiting, and when
* one of their tasks fails.
*/
#failFastChecks = /* @__PURE__ */ new Set();
/**
* Live tasks with `abandonOnRestart` found at open, from an earlier Harness. The first reservation pass abort-marks
* them with reason `restart`, so nothing of them or below them runs a phase again.
*/
#abandoned = /* @__PURE__ */ new Set();
/** Sleeping live tasks, due or not: the candidates of `#wakeDue()`. */
#sleeping = /* @__PURE__ */ new Set();
/** Timer for the earliest sleep, without `onWake` while scheduling runs. */
#timer;
/** Last value given to `onWake`, so an unchanged one is not repeated. */
#lastWake;
#wakeScheduled = false;
#blockedListeners = /* @__PURE__ */ new Set();
/** A registry snapshot that threw for the task graph was reported; it is read per record, so only once. */
#snapshotReported = false;
#reconcileScheduled = false;
/** Reconcile passes underway with work (they may overlap): their commits finalize held outcomes and mark cascades. */
#reconcilingWork = 0;
#sweepScheduled = false;
/**
* Nodes chain loads installed for jobs whose commits are not published yet, with how many such jobs: the sweep keeps
* them, as work a pending commit creates below them needs them.
*/
#pins = /* @__PURE__ */ new Map();
/** Keys the decision region underway reads (`#region()`); set only while one runs. */
#reading;
#cascadePending = false;
#unsubscribeRegistry = () => {
};
#enabled = false;
#readOnly;
#closing = false;
#dirty = false;
#draining = false;
constructor(options) {
this.#telemetry = options.telemetry ?? NOOP_TELEMETRY_CONTEXT;
const metrics = createTypedMetrics(this.#telemetry.metrics ?? NOOP_TELEMETRY_METRICS, [DURABLE_TELEMETRY_SCHEMA]);
this.#activeMetric = metrics.upDownCounter("pi.durable.tasks.active");
this.#durationMetric = metrics.histogram("pi.durable.phase.duration");
this.#session = options.session;
this.#storage = options.storage;
this.#registry = options.registry;
this.#models = options.models;
this.#agent = options.agent;
this.#settings = options.settings;
this.#env = options.env;
this.#now = options.now;
this.#onWake = options.onWake;
this.#timers = options.timers;
this.#writeAtClose = options.writeAtClose;
this.#report = options.report;
this.#settleOutcome = options.settleOutcome;
this.#limitsRestarts = options.limitsRestarts;
this.#withdrawInputs = options.withdrawInputs;
this.#conversation = options.conversation;
this.#context = options.context;
this.#readOnly = options.readOnly === true;
}
/**
* Load live tasks and change surviving `running` tasks back to `pending`, counting the restart. Dispatches nothing;
* a task cut off `settings.restartLimit` times ends when it is next reserved. Read-only, it only loads them: a
* `running` task stays as committed, running in another process.
*/
async open(context) {
this.#session.followCommits((publication) => this.#observe(publication));
this.#session.subscribeClose(() => this.#seal());
this.#unsubscribeRegistry = this.#registry.subscribe(() => {
this.#notifyBlocked();
this.#kick();
});
await this.#session.commitWith(async (tx) => {
await this.#published();
const scans = [];
for (const status of LIVE_STATUSES) {
scans.push(await scanAll((cursor) => tx.scanTasks({ status }, SCAN_PAGE_SIZE3, cursor)));
}
for (const records of scans) {
for (const record of records) {
this.#track(void 0, record);
this.#resumed.add(record.id);
if (this.#readOnly)
continue;
if (record.abandonOnRestart === true)
this.#abandoned.add(record.id);
if (record.state.status === "running") {
const restarts = (record.restarts ?? 0) + 1;
const pending = withState(record, { status: "pending", checkpoint: record.state.checkpoint });
tx.setTask({ ...pending, restarts });
}
if (record.state.status === "waiting" && record.state.policy === "failFast") {
this.#failFastChecks.add(record.id);
}
}
}
}, context);
if (this.#readOnly)
return;
this.#cascadePending = true;
this.#scheduleReconcile();
this.#scheduleWake();
}
/**
* Enable scheduling, and make sleeping tasks that are due runnable: a host wakeup, such as an alarm, calls this.
* Idempotent; the kick does nothing once closing.
*/
resume() {
if (this.#readOnly)
throw new ReadOnlySession("running tasks");
this.#enabled = true;
this.#wakeDue();
this.#kick();
}
/**
* Why a live task cannot run here, if it cannot: its definition is missing, too old, or failed to migrate. A running
* task, an abort-marked one, and one holding its outcome are never blocked.
*/
blockedReason(record) {
const status = record.status;
if (status === "running" || status === "completing" || status === "terminal")
return void 0;
if (record.abortRequested && record.abortReason === void 0)
return void 0;
let snapshot;
try {
snapshot = this.#registry.snapshot();
} catch (error) {
if (!this.#snapshotReported)
this.#report(error, REGISTRY);
this.#snapshotReported = true;
return void 0;
}
const fit = this.#fit(record, snapshot.task(record.kind));
if ("reason" in fit)
return fit.reason;
return fit.migrates && fit.task.definition.migrate === void 0 ? "migration_failed" : void 0;
}
/** Call `listener` when blocked reasons may have changed without a commit: a registry change or a failed migration. */
subscribeBlocked(listener) {
this.#blockedListeners.add(listener);
return () => this.#blockedListeners.delete(listener);
}
/**
* When the Session next needs a process: `active` while some task can run now or is running, `at` for the earliest
* sleep not yet due. Synchronous, from memory; a task whose chain is not loaded yet counts as it would alone.
*/
wake() {
if (this.#readOnly)
return { active: false };
const now = this.#now();
const active = this.#invocations.size > 0 || this.#reconcilingWork > 0 || this.#reconcileWork() || this.#runsNow(now);
let at;
for (const id of this.#sleeping) {
const record = this.#live.get(id);
const state2 = record?.state;
if (state2?.status === "sleeping" && !record.abortRequested && state2.until > now) {
at = at === void 0 ? state2.until : Math.min(at, state2.until);
}
}
return at === void 0 ? { active } : { active, at };
}
/** Whether a live task can run now: the scan `wake()` needs only while no invocation runs. */
#runsNow(now) {
let snapshot;
let snapshotFailed = false;
for (const record of this.#live.values()) {
const state2 = record.state;
if (state2.status === "completing")
continue;
if (state2.status === "waiting" && !record.abortRequested && state2.on.some((id) => this.#live.has(id)))
continue;
if (state2.status === "sleeping" && !record.abortRequested && state2.until > now)
continue;
if (record.abortRequested && this.#waitingOn(record, true).length > 0)
continue;
if (!record.abortRequested || record.abortReason !== void 0) {
if (snapshot === void 0 && !snapshotFailed) {
try {
snapshot = this.#registry.snapshot();
} catch (error) {
snapshotFailed = true;
this.#report(error, REGISTRY);
}
}
if (snapshot !== void 0 && "reason" in this.#fit(record, snapshot.task(record.kind)))
continue;
}
return true;
}
return false;
}
/**
* Signal every invocation and wait for them, then write the tasks they ran back as `pending` (`writeAtClose`), as a
* close is not a crash. Close calls this after every close listener has run, so waits, watches, and streams a task
* holds end with the Session's reason, not as cancelled by its signal.
*/
async join() {
const stopped = [...this.#invocations.values()];
for (const invocation of stopped)
invocation.controller.abort();
await Promise.allSettled(stopped.map((invocation) => invocation.done));
if (stopped.length === 0)
return;
await this.#writeAtClose(() => stopped.flatMap((invocation) => {
const record = this.#live.get(invocation.taskId);
if (record?.state.status !== "running")
return [];
const value2 = withState(record, { status: "pending", checkpoint: record.state.checkpoint });
return [{ type: "task", value: value2 }];
})).catch(() => {
});
}
/**
* Commit the abort mark, or settle a task that no registered definition can take as `orphaned` when nothing it owns
* is live, then join the run invocation seen on the line; the commit listener signalled it. The abort invocation
* starts once the task's ordinary owned work is gone. A `completing` task is only marked. A request replaces a
* `restart` mark, so a task abandoned after a restart that waits for its definition is orphaned; with `keepRestart`,
* as for an owner's own cleanup, such a task keeps its mark and waits on.
*/
async abort(id, context, keepRestart = false) {
const marked = await this.#session.commitWith(async (tx) => {
const current = await tx.task(id);
if (current === void 0)
throw new Error(`Task ${id} does not exist`);
if (current.state.status === "terminal")
return { result: "terminal" };
const invocation = this.#invocations.get(id);
if (keepRestart && current.abortReason === "restart")
return { result: "marked" };
if (invocation === void 0 && current.state.status !== "completing") {
await this.#loadScopes(false);
const owns = await this.#region(() => this.#hasOwnedLive(id), this.#reloadScopes);
const resolution = owns ? void 0 : this.#resolve(current, this.#registry.snapshot());
if (resolution?.kind === "blocked") {
await this.#terminate(tx, current, { status: "orphaned", reason: resolution.reason });
return { result: "marked" };
}
}
if (!current.abortRequested || current.abortReason !== void 0)
tx.setTask(withAbortMark(current));
return { result: "marked", run: invocation?.mode === "run" ? invocation : void 0 };
}, context);
if (marked.run !== void 0) {
await awaitWithContext(Promise.race([marked.run.done, this.#session.failed]), context);
}
return marked.result;
}
async waitForTask(id, context) {
const found = await this.#session.readOnLine(async (storage) => {
if (this.#closing)
throw closedError(this.#session);
if (await this.#region(() => this.#liveRecord(id) !== void 0)) {
return { promise: this.#taskWaiters.add(id, context) };
}
const record = await storage.task(id, context);
if (record === void 0)
throw new Error(`Task ${id} does not exist`);
return { promise: Promise.resolve(record) };
});
return found.promise;
}
/**
* Resolve when ordinary traversal from the conversation, or from every ownerless conversation, reaches no live
* non-background task.
*/
waitForIdle(conversationId, context) {
if (this.#closing)
return Promise.reject(closedError(this.#session));
if (this.#idle(conversationId))
return Promise.resolve();
this.#scheduleReconcile();
return this.#idleWaiters.add(conversationId, context);
}
/**
* `Conversation.abort()`: in one commit, withdraw the queued inputs and mark every live non-background task that
* ordinary traversal from the conversation reaches; resolves once the scope is idle. With `background`, traversal
* crosses background boundaries, and the wait also covers every task it reached.
*/
async abortConversation(conversationId, background, context) {
const reached = await this.#session.commitWith(async (tx) => {
await this.#published();
const queued = await this.#loadScopes(true);
const scope = { conversation: conversationId };
const reached2 = [];
const walk = this.#walkDown(conversationNode(conversationId), { crossBackground: background });
for (const { node, live } of walk) {
if (live === void 0 || node.background && !background)
continue;
reached2.push(live.id);
if (!live.abortRequested || live.abortReason !== void 0)
tx.setTask(withAbortMark(live));
}
for (const id of queued) {
if (this.#inScope({ conversation: id }, scope, background) === true)
await this.#withdrawInputs(tx, id);
}
return reached2;
}, context);
if (background)
for (const id of reached)
await this.waitForTask(id, context);
await this.waitForIdle(conversationId, context);
}
/**
* The ownership memberships a commit's task and conversation changes write (group commit §4.2), at its admission on
* the line: for each task created or made terminal, every node from its parent up to and including the nearest live
* task, or the root conversation, and then the roots too, conservatively, as a pending end may unlist the root a
* creation finds listed; for each conversation created under a task, that task; and the intent set when
* a change sets, upgrades, or clears a mark or a held or ended outcome other than `completed`. Loads the chains it
* walks; the nodes it installs stay until the commit is published.
*/
membershipKeys(tx) {
const tasks = tx.stagedTasks();
const conversations = tx.stagedConversations();
if (tasks.length === 0 && conversations.every((record) => record.owner === void 0))
return NO_KEYS2;
return this.#membershipKeys(tx, tasks, conversations);
}
async #membershipKeys(tx, tasks, conversations) {
const keys = /* @__PURE__ */ new Set();
const overlay = overlayOf(tx);
const created = new Set(tx.createdTaskIds());
const reached = /* @__PURE__ */ new Map();
for (const record of tasks) {
if (intentChanges(this.#live.get(record.id), record))
keys.add(INTENT_KEY);
if (!created.has(record.id) && record.state.status !== "terminal")
continue;
await this.#loadChain(parentOf(record), overlay);
if (await this.#chainKeys(parentNode(record), overlay, keys, reached) !== void 0)
keys.add(ROOTS_KEY);
}
for (const conversation of conversations) {
const owner = conversation.owner?.taskId;
if (owner === void 0)
continue;
await this.#loadChain({ task: owner }, overlay);
await this.#chainKeys(owner, overlay, keys, reached);
}
return [...keys];
}
/**
* Add the memberships from `start` up to and including the nearest live task, or the root conversation, which it
* returns. `reached` keeps, per node walked, where its walk ended, so a chain several tasks of a commit share is
* walked once. Whether an ancestor is live can change under a pending commit, so it is read after a touch of the
* ancestor's record: a pending end must not stop the chain early. Ownership fields are immutable, so not keyed.
*/
async #chainKeys(start, overlay, keys, reached) {
const walked = [];
let root2;
let node = start;
while (node !== void 0 && node !== null) {
const key = ownedKey(node);
if (reached.has(key)) {
root2 = reached.get(key);
break;
}
keys.add(key);
walked.push(key);
if (typeof node === "string") {
const conversation = conversationOf(node);
node = this.#edge(conversation, overlay);
if (node === null)
root2 = conversation;
continue;
}
let record = overlay.tasks.get(node);
if (record === void 0) {
const gate = this.#session.touch(taskKey(node));
if (gate !== void 0) {
await gate;
await this.#loadChain({ task: node }, overlay);
}
record = this.#live.get(node);
}
if (record !== void 0 && record.state.status !== "terminal")
break;
const above = record ?? this.#settled.get(node);
node = above === void 0 ? void 0 : parentNode(above);
}
for (const key of walked)
reached.set(key, root2);
return root2;
}
// ─── Scheduling ────────────────────────────────────────────────────────
#observe(publication) {
if (publication.kind === "memory")
return;
this.#advanceContexts(publication);
const updated = [];
const failed = [];
let changed = false;
let dirty = /* @__PURE__ */ new Set();
for (const change of publication.changes) {
if (change.type === "conversation" && !this.#edges.has(change.value.id)) {
this.#setEdge(change.value.id, change.value.owner?.taskId ?? null);
}
}
for (const change of publication.changes) {
if (change.type !== "task")
continue;
changed = true;
const record = change.value;
const previous = this.#live.get(record.id);
if (failedOutcome(record) && (previous === void 0 || !failedOutcome(previous)))
failed.push(record.id);
this.#track(previous, record);
const liveness = previous === void 0 || record.state.status === "terminal";
if (liveness && dirty !== void 0 && !this.#addScopesAbove(record, dirty))
dirty = void 0;
if (record.state.status === "terminal") {
this.#failedMigrations.delete(record.id);
this.#failFastChecks.delete(record.id);
this.#taskWaiters.resolve(record.id, record);
this.#scheduleReconcile();
continue;
}
if (record.abortRequested && previous?.abortRequested !== true) {
this.#cascadePending = true;
const invocation = this.#invocations.get(record.id);
if (invocation?.mode === "run")
queueMicrotask(() => invocation.controller.abort());
}
if (previous?.abortReason !== void 0 && record.abortReason === void 0)
this.#cascadePending = true;
const status = record.state.status;
if (status === "completing" && previous?.state.status !== "completing") {
if (cancellationIntent(record))
this.#cascadePending = true;
this.#scheduleReconcile();
}
if (status === "waiting" && record.state.policy === "failFast" && previous?.state.status !== "waiting") {
this.#failFastChecks.add(record.id);
this.#scheduleReconcile();
}
if (previous === void 0)
updated.push(record);
}
for (const id of failed) {
for (const waiter of this.#waiters.get(id) ?? []) {
const state2 = this.#live.get(waiter)?.state;
if (state2?.status === "waiting" && state2.policy === "failFast") {
this.#failFastChecks.add(waiter);
this.#scheduleReconcile();
}
}
}
for (const change of publication.changes) {
if (change.type !== "submission" || change.value.status !== "queued" || change.value.type !== "input")
continue;
if (this.#intent.size === 0)
continue;
const conversation = change.value.conversationId;
if (!this.#known(conversationNode(conversation)) || this.#belowCancelled({ conversation })) {
this.#cascadePending = true;
}
}
for (const record of updated) {
if (this.#unloaded.has(record.id))
this.#scheduleReconcile();
else if (!record.background && !record.abortRequested && this.#belowCancelled(parentOf(record))) {
this.#cascadePending = true;
}
}
if (this.#cascadePending)
this.#scheduleReconcile();
this.#sweep();
if (!changed)
return;
this.#settleIdle(dirty);
this.#kick();
}
/**
* Add the conversations above `record` to `scopes`: those whose idleness a change of it can change. False when a node
* on the way up is not known. A conversation already in `scopes` has everything above it there too.
*/
#addScopesAbove(record, scopes) {
for (const step of this.#above(parentOf(record))) {
if ("unknown" in step)
return false;
if (!("conversation" in step))
continue;
if (scopes.has(step.conversation))
return true;
scopes.add(step.conversation);
}
return true;
}
/**
* Extend each kept context range with the entries a stored commit appended to its conversation, so a later read
* needs no Storage scan. Entries are published in ID order.
*/
#advanceContexts(publication) {
if (this.#contexts.size === 0)
return;
let appended;
for (const change of publication.changes) {
if (change.type !== "entry" || !this.#contexts.has(change.value.conversationId))
continue;
appended ??= /* @__PURE__ */ new Map();
const entries2 = appended.get(change.value.conversationId);
if (entries2 === void 0)
appended.set(change.value.conversationId, [change.value]);
else
entries2.push(change.value);
}
if (appended === void 0)
return;
for (const [conversationId, entries2] of appended) {
const kept = this.#contexts.get(conversationId);
if (kept.idleSince !== void 0 && kept.expiresAt !== void 0 && kept.expiresAt <= this.#now()) {
this.#dropContext(conversationId);
continue;
}
const range = advanceRange(kept.range, entries2);
if (range === void 0)
this.#dropContext(conversationId);
else
kept.range = range;
}
}
/**
* `settings.contextRetentionMs`, or 0 when the host's settings throw. Kept contexts are only a cache, so dropping them
* is safe, while a throw here would escape commit listeners, reconciliation, and the expiry timer.
*/
#contextRetentionMs() {
try {
return this.#settings().contextRetentionMs;
} catch (error) {
this.#report(error, SETTINGS);
return 0;
}
}
/**
* After task changes below the conversations in `scopes` (every conversation when undefined): resolve their idle
* waiters and the Harness-wide ones, drop the kept contexts whose idle period passed the retention, then start or end
* the idle periods of the kept contexts in `scopes`. A task change can change the idleness only of the conversations
* above it, so no check visits every conversation.
*/
#settleIdle(scopes) {
const all = scopes === void 0 || this.#unknownsChanged;
this.#unknownsChanged = false;
if (all)
this.#fullIdleChecks++;
this.#resolveIdleWaiters(all ? void 0 : scopes);
const now = this.#now();
const retention = this.#contextRetentionMs();
this.#expireContexts(now, retention);
for (const conversationId of all ? [...this.#contexts.keys()] : scopes) {
const kept = this.#contexts.get(conversationId);
if (kept === void 0)
continue;
if (!this.#idle(conversationId)) {
if (kept.idleSince === void 0)
continue;
kept.idleSince = void 0;
this.#idleOrder.delete(conversationId);
} else if (retention <= 0) {
this.#dropContext(conversationId);
} else if (kept.idleSince === void 0) {
kept.idleSince = now;
kept.expiresAt = now + retention;
this.#markIdle(conversationId, now);
}
}
this.#scheduleExpiry();
}
/** Resolve the idle waiters of the conversations in `scopes` (all when undefined) and the Harness-wide ones. */
#resolveIdleWaiters(scopes) {
for (const conversationId of this.#idleWaiters.keys()) {
if (conversationId !== void 0 && scopes !== void 0 && !scopes.has(conversationId))
continue;
if (this.#idle(conversationId))
this.#idleWaiters.resolve(conversationId);
}
}
/**
* Drop the kept contexts idle for at least `retention`, oldest first, with the retention setting of now; with no
* retention, every idle one, also those whose idle period a clock that went back makes start after now.
*/
#expireContexts(now, retention) {
for (const [conversationId, idleSince] of this.#idleOrder) {
if (retention > 0 && now - idleSince < retention)
return;
this.#dropContext(conversationId);
}
}
/**
* Start the idle period of a kept context in the expiry order. An idle period older than the newest one kept, which
* a clock that went back starts, sorts the order again, and the newest is taken from what is kept then.
*/
#markIdle(conversationId, idleSince) {
this.#idleOrder.delete(conversationId);
this.#idleOrder.set(conversationId, idleSince);
if (this.#idleOrder.size === 1 || idleSince >= this.#idleNewest) {
this.#idleNewest = idleSince;
return;
}
const sorted = [...this.#idleOrder].sort((a, b) => a[1] - b[1]);
this.#idleOrder.clear();
for (const [id, since] of sorted)
this.#idleOrder.set(id, since);
this.#idleNewest = sorted.at(-1)[1];
}
/** Forget a kept context, idle or not, and its place in the expiry order. */
#dropContext(conversationId) {
this.#contexts.delete(conversationId);
this.#idleOrder.delete(conversationId);
}
/**
* Drop the expired contexts when the earliest idle context expires, on a background timer, which never keeps the
* process alive. Where the host declines it, as the default does in Cloudflare Workers, none is kept: a pending timer
* could keep a Durable Object from being evicted, and eviction frees the contexts. There, task changes alone check
* expiry.
*/
#scheduleExpiry() {
const oldest = this.#idleOrder.values().next();
const at = oldest.done === true ? void 0 : oldest.value + this.#contextRetentionMs();
if (this.#expiry !== void 0 && this.#expiry.at === at)
return;
this.#expiry?.disarm();
this.#expiry = void 0;
if (at === void 0 || this.#closing)
return;
const disarm = this.#timers.background(() => {
this.#expiry = void 0;
this.#expireContexts(this.#now(), this.#contextRetentionMs());
this.#scheduleExpiry();
}, at - this.#now());
if (disarm !== void 0)
this.#expiry = { at, disarm };
}
// ─── Ownership ───────────────────────────────────────────────────────────
#scheduleReconcile() {
if (this.#reconcileScheduled || this.#closing || this.#readOnly)
return;
this.#reconcileScheduled = true;
queueMicrotask(() => void this.#reconcile());
}
/**
* One commit that applies what committed records imply: abort marks below live owners with cancellation intent
* (spec §5.4), `failFast` marks (spec §5.5), withdrawn queued inputs below cancelled owners, and the final terminal
* record of every `completing` task whose ordinary owned work is gone. The durable records are the intent, so this
* also repairs whatever a crash left unapplied. Resolves idle waiters that the loaded edges decide.
*/
async #reconcile() {
this.#reconcileScheduled = false;
const work = this.#reconcileWork();
if (work)
this.#reconcilingWork++;
try {
await this.#session.commitInternal(async (tx) => {
if (this.#closing)
return;
const cascade = this.#cascadePending;
const queued = await this.#loadScopes(cascade);
if (cascade)
this.#cascadePending = false;
const marks = await this.#marks();
for (const { record, reason } of marks.values())
tx.setTask(withAbortMark(record, reason));
const withdrawn = await this.#region(() => queued.filter((id) => this.#belowCancelled({ conversation: id })), this.#reloadScopes);
for (const id of withdrawn)
await this.#withdrawInputs(tx, id);
await this.#finalize(tx);
}, this.#context);
} catch (error) {
this.#failSession(error);
}
if (work)
this.#reconcilingWork--;
this.#scheduleWake();
if (this.#unknownsChanged) {
this.#settleIdle(void 0);
return;
}
this.#resolveIdleWaiters(void 0);
this.#expireContexts(this.#now(), this.#contextRetentionMs());
this.#scheduleExpiry();
}
/**
* The abort marks committed records imply (spec §5.4, §5.5): every live foreground task below a live owner with
* cancellation intent, which is its nearest one (a walk down from each owner with intent does not enter another,
* whose own walk covers what is below it), and every other live task in the `on` of a `failFast` waiter one of whose
* tasks failed. A cascade from an abandoned owner passes its `restart` reason on; any other intent marks, or upgrades
* a `restart` mark, as a request. Collected first, so a request wins over a `restart` mark of the same pass. Derived
* again on every pass, as loading edges can reveal a cancelled owner. Takes the `failFast` checks once its decision
* stands.
*/
async #marks() {
const ended = /* @__PURE__ */ new Map();
for (; ; ) {
const plan = await this.#region(() => this.#planMarks(ended), this.#reloadScopes);
if ("missing" in plan) {
for (const id of plan.missing)
ended.set(id, await this.#session.lineStorage.task(id, this.#context) ?? null);
continue;
}
for (const id of plan.checked)
this.#failFastChecks.delete(id);
return plan.marks;
}
}
/** `#marks()`' decision region; the `failFast` members it needs from Storage first, when `ended` lacks them. */
#planMarks(ended) {
const marks = /* @__PURE__ */ new Map();
const mark = (found, reason) => {
const record = this.#liveRecord(found.id);
const staged = marks.get(record.id);
if (staged !== void 0 && staged.reason === void 0)
return;
if (record.abortRequested && (record.abortReason === void 0 || reason !== void 0))
return;
marks.set(record.id, { record, reason });
};
this.#record(INTENT_KEY);
for (const id of this.#intent) {
const owner = this.#liveRecord(id);
const restart = owner.abortReason === "restart" && !failedOutcome(owner);
for (const { node, live } of this.#walkDown(id, { enter: (below) => !this.#intent.has(below) })) {
if (live !== void 0 && !node.background)
mark(live, restart ? "restart" : void 0);
}
}
const checked = [...this.#failFastChecks];
const missing = [];
for (const id of checked) {
const waiter = this.#liveRecord(id);
if (waiter?.state.status !== "waiting")
continue;
let failed = false;
for (const member of waiter.state.on) {
const record = this.#liveRecord(member) ?? ended.get(member);
if (record === void 0)
missing.push(member);
else if (record !== null && failedOutcome(record))
failed = true;
}
if (!failed)
continue;
for (const member of waiter.state.on) {
const record = this.#liveRecord(member);
if (record !== void 0 && !failedOutcome(record))
mark(record, void 0);
}
}
return missing.length > 0 ? { missing } : { marks, checked };
}
/** Whether a reconcile pass would have work: a cascade to derive, held outcomes to check, or `failFast` waits. */
#reconcileWork() {
return this.#cascadePending || this.#finalizeChecks.size > 0 || this.#failFastChecks.size > 0;
}
/**
* Write the terminal record of every `completing` task without live ordinary owned work. Finalizing one can free its
* owner, so this repeats over the commit's candidates until nothing changes. A held scheduler outcome gets its
* Harness cleanup here. In rounds, one decision region each: the holders the tasks of one round free are checked once,
* in the next, so a holder of many tasks that end together is walked once, not once per task. The first round takes
* the `completing` tasks to check once its decision stands.
*/
async #finalize(tx) {
const done = /* @__PURE__ */ new Set();
const overlay = overlayOf(tx);
let round;
for (; ; ) {
const ids = round;
const plan = await this.#region(() => this.#planRound(ids ?? [...this.#finalizeChecks], overlay, done), this.#reloadScopes);
if (ids === void 0)
this.#finalizeChecks.clear();
for (const { record, terminal } of plan.finalized) {
tx.setTask(terminal);
overlay.tasks.set(record.id, terminal);
done.add(record.id);
const outcome = record.state.outcome;
if (outcome.status === "faulted" || outcome.status === "orphaned") {
await this.#settleOutcome(tx, record, outcome);
}
}
if (plan.next.length === 0)
return;
round = plan.next;
}
}
/**
* One finalize round's decision: which of `ids` are `completing` without live ordinary owned work below them, in the
* commit's candidates with the round's own finalizations applied in order, and the holders above them to check next.
* Tasks finalized have no live work below them, so walks down skip them. It applies the round's terminal records to
* `overlay` while it decides and takes them back before it returns, so a run again starts from the same candidates.
*/
#planRound(ids, overlay, finalized) {
const tasks = overlay.tasks;
const round = /* @__PURE__ */ new Set();
const done = { has: (id) => round.has(id) || finalized.has(id) };
const ended = [];
const next = /* @__PURE__ */ new Set();
try {
for (const id of ids) {
const staged = tasks.get(id);
const record = staged ?? this.#liveRecord(id);
if (record?.state.status !== "completing" || done.has(id))
continue;
if (this.#hasOwnedLive(id, overlay, done))
continue;
const terminal = withState(record, { status: "terminal", outcome: record.state.outcome });
tasks.set(id, terminal);
round.add(id);
ended.push({ record, terminal, staged: staged !== void 0 });
const above = this.#nearestLiveAbove(record, overlay);
if (above?.state.status === "completing")
next.add(above.id);
}
} finally {
for (const { record, staged } of ended) {
if (staged)
tasks.set(record.id, record);
else
tasks.delete(record.id);
}
}
return { finalized: ended, next: [...next] };
}
/**
* Load the owner chains of the tasks in `#unloaded` and, with `queued`, of every conversation with queued inputs,
* on the Session line; returns the latter. Reads through the line's Storage, so it may run inside a commit callback.
*/
async #loadScopes(queued) {
for (const id of [...this.#unloaded]) {
if (this.#unloaded.has(id))
await this.#loadChain({ task: id });
}
if (!queued)
return [];
const submissions = await scanAll((cursor) => this.#session.lineStorage.scanSubmissions({ status: "queued" }, SCAN_PAGE_SIZE3, cursor, this.#context));
const inputs = submissions.filter((submission2) => submission2.type === "input");
const conversations = [...new Set(inputs.map((submission2) => submission2.conversationId))];
for (const id of conversations)
await this.#loadChain({ conversation: id });
return conversations;
}
/**
* Load the owner edges and task nodes from `start` up to its ownerless root. A known task outside `#unloaded` ends the
* walk, as its chain is loaded; the `#unloaded` tasks passed have a loaded chain afterwards. Loading a node can reveal
* a cancelled owner, so it makes the next reconcile derive cascade marks. The nodes it installs stay until the job's
* commit is published (`#pin()`).
*/
async #loadChain(start, overlay) {
const passed = [];
let installed = false;
let at = start;
try {
while (at !== void 0) {
if ("task" in at) {
const id = at.task;
let node = this.#live.get(id) ?? this.#settled.get(id);
if (node === void 0 && overlay?.tasks.has(id) === true)
break;
if (node !== void 0 && !this.#unloaded.has(id))
break;
if (node === void 0) {
const record = await this.#session.lineStorage.task(id, this.#context);
if (record === void 0)
return;
node = nodeOf(record);
if (record.state.status === "terminal") {
this.#settle(id, node);
this.#pin(id);
installed = true;
}
this.#scheduleReconcile();
}
passed.push(id);
at = parentOf(node);
} else {
let edge = this.#edge(at.conversation, overlay);
if (edge === void 0) {
const record = await this.#session.lineStorage.conversation(at.conversation, this.#context);
edge = record?.owner?.taskId ?? null;
this.#setEdge(at.conversation, edge);
this.#pin(conversationNode(at.conversation));
installed = true;
this.#scheduleReconcile();
}
at = edge === null ? void 0 : { task: edge };
}
}
} finally {
if (passed.some((id) => this.#live.has(id)) || installed && this.#liveUnloaded()) {
this.#unknownsChanged = true;
this.#scheduleReconcile();
}
}
for (const id of passed)
this.#unloaded.delete(id);
}
/** Whether a live task's chain is not loaded yet: one `#idle()` counts as inside every scope it may be in. */
#liveUnloaded() {
for (const id of this.#unloaded)
if (this.#live.has(id))
return true;
return false;
}
#setEdge(conversationId, owner) {
this.#edges.set(conversationId, owner);
this.#relist(conversationNode(conversationId));
this.#dropIfUnneeded(conversationNode(conversationId));
}
/** Know a terminal task a chain load read, so walks pass through it; its own chain is not loaded yet. */
#settle(id, node) {
this.#settled.set(id, node);
this.#unloaded.add(id);
this.#relist(id);
this.#dropIfUnneeded(id);
}
/** Queue an ended task or a conversation for the sweep when nothing is listed below it. */
#dropIfUnneeded(node) {
if (typeof node !== "string" && this.#live.has(node))
return;
if (this.#below.has(node))
return;
this.#dropQueue.add(node);
this.#scheduleSweep();
}
/**
* Sweep in a job of its own on the Session line, after the operation underway: a rejected commit, one with nothing to
* write, and a read publish nothing, so the sweep at the end of `#observe` would not run for what they loaded.
*/
#scheduleSweep() {
if (this.#sweepScheduled || this.#closing)
return;
this.#sweepScheduled = true;
this.#session.readOnLine(async () => {
this.#sweepScheduled = false;
this.#sweep();
}).catch(() => {
});
}
/**
* Drop the queued nodes that are still unneeded: not live, nothing listed below. Runs once a publication is fully
* tracked, and as a job of its own on the line, never inside an operation: work a commit creates below a chain its
* own callback loaded keeps that chain. A flat loop: unlisting already queued every node on the way up that lost its
* last listed node.
*/
#sweep() {
for (const node of this.#dropQueue) {
if (this.#below.has(node) || this.#pins.has(node))
continue;
if (typeof node === "string") {
this.#edges.delete(conversationOf(node));
this.#roots.delete(conversationOf(node));
} else if (!this.#live.has(node)) {
this.#settled.delete(node);
this.#unloaded.delete(node);
}
}
this.#dropQueue.clear();
}
/**
* Run `decide`, a decision region (group commit §6): synchronous, reading scheduler memory and recording the keys it
* reads, staging nothing and changing no scheduler state. When a key it read has an unpublished writer, its result,
* or its error, is dropped: once that writer is published, `refresh` reloads what the region needs and it runs
* again. A waiting job holds the line, so unpublished writes only shrink, and the runs converge. What a region read
* that had no unpublished writer gets none for the rest of the job, so its result stands while the job applies it.
*/
async #region(decide, refresh) {
for (; ; ) {
const keys = /* @__PURE__ */ new Set();
this.#reading = keys;
let result;
try {
result = { value: decide() };
} catch (error) {
result = { error };
} finally {
this.#reading = void 0;
}
const gates = [];
for (const key of keys) {
const gate = this.#session.touch(key);
if (gate !== void 0)
gates.push(gate);
}
if (gates.length === 0) {
if ("error" in result)
throw result.error;
return result.value;
}
await Promise.all(gates);
await refresh?.();
}
}
/** Load the chains a region walks, again after it waited: what was published meanwhile may list new work. */
#reloadScopes = () => this.#loadScopes(false);
/** In a decision region, note that it reads `key`; anywhere else, nothing. */
#record(key) {
this.#reading?.add(key);
}
/** A live task's committed record, read by a decision region. */
#liveRecord(id) {
this.#record(taskKey(id));
return this.#live.get(id);
}
/**
* Keep `node`, which a chain load of the job on the line installed, until that job's commit is published or fails:
* work it creates below the node needs it, and the sweep would drop it as unneeded before then.
*/
#pin(node) {
this.#pins.set(node, (this.#pins.get(node) ?? 0) + 1);
this.#session.onJobEnd(() => {
const count = this.#pins.get(node) - 1;
if (count > 0) {
this.#pins.set(node, count);
return;
}
this.#pins.delete(node);
this.#dropIfUnneeded(node);
});
}
/**
* Bring the scheduler's sets in line with a task's committed record. A task that ended may free the nearest live task
* above it: one holding its outcome finalizes, an abort-marked one runs its abort handler; its waiters may run.
*/
#track(previous, record) {
const id = record.id;
const invocation = this.#invocations.get(id);
if (invocation !== void 0)
invocation.record = record;
if (record.state.status === "terminal") {
if (previous !== void 0 && !this.#closing)
this.#countActive(-1, record.kind);
this.#resumed.delete(id);
} else if (previous === void 0 && !this.#closing) {
this.#countActive(1, record.kind);
}
if (previous?.state.status === "waiting")
for (const on of previous.state.on)
deleteFrom(this.#waiters, on, id);
if (record.state.status === "terminal") {
const node = nodeOf(record);
this.#live.delete(id);
this.#sleeping.delete(id);
this.#intent.delete(id);
this.#runnable.delete(id);
this.#finalizeChecks.delete(id);
this.#settled.set(id, node);
this.#release(node);
for (const waiter of this.#waiters.get(id) ?? [])
this.#runnable.add(waiter);
this.#relist(id);
this.#dropIfUnneeded(id);
return;
}
this.#live.set(id, record);
if (previous === void 0) {
if (!this.#known(parentNode(record)))
this.#unloaded.add(id);
this.#relist(id);
}
if (cancellationIntent(record))
this.#intent.add(id);
else
this.#intent.delete(id);
if (record.state.status === "completing") {
this.#runnable.delete(id);
this.#finalizeChecks.add(id);
} else {
this.#runnable.add(id);
}
if (record.state.status === "waiting")
for (const on of record.state.on)
addTo(this.#waiters, on, id);
if (record.state.status === "sleeping")
this.#sleeping.add(id);
else
this.#sleeping.delete(id);
}
/** The nearest live task above ended ordinary work may be free now: one holding its outcome, or an aborting one. */
#release(node, overlay) {
const above = this.#nearestLiveAbove(node, overlay);
if (above?.state.status === "completing")
this.#finalizeChecks.add(above.id);
else if (above?.abortRequested === true)
this.#runnable.add(above.id);
return above;
}
/**
* List `start` under its parent node in `#below` while it is a live task or has nodes listed below it, and unlist it
* otherwise; then its parent, as far up as that changes. So `#below` holds exactly the tree around live work; a
* parent that loses its last listed node is queued for the sweep. A loop, as ownership chains can be deeper than the
* call stack.
*/
#relist(start) {
let node = start;
for (; ; ) {
const needed = typeof node !== "string" && this.#live.has(node) || this.#below.has(node);
let parent;
if (typeof node === "string") {
parent = this.#edges.get(conversationOf(node));
} else {
const known = this.#live.get(node) ?? this.#settled.get(node);
if (known === void 0)
return;
parent = parentNode(known);
}
if (parent === void 0)
return;
if (parent === null) {
const root2 = conversationOf(node);
if (needed)
this.#roots.add(root2);
else
this.#roots.delete(root2);
return;
}
if (this.#below.get(parent)?.has(node) === true === needed)
return;
if (needed) {
const first = !this.#below.has(parent);
addTo(this.#below, parent, node);
if (!first)
return;
} else {
deleteFrom(this.#below, parent, node);
if (this.#below.has(parent))
return;
this.#dropIfUnneeded(parent);
}
node = parent;
}
}
/**
* The nearest live task above ended ordinary work `node`, in the overlay's view: the one that work held, if any. Work
* at or below a background task holds nothing above it.
*/
#nearestLiveAbove(node, overlay) {
this.#record(INTENT_KEY);
for (let current = node; !current.background; ) {
const owner = current.owner ?? this.#edge(current.conversationId, overlay);
if (owner === void 0 || owner === null)
return void 0;
const record = overlay?.tasks.get(owner) ?? this.#liveRecord(owner);
if (record !== void 0 && record.state.status !== "terminal")
return record;
const above = record ?? this.#settled.get(owner);
if (above === void 0)
return void 0;
current = above;
}
return void 0;
}
/** Whether the chain above `node` is loaded, without walking: known tasks outside `#unloaded` have a loaded chain. */
#known(node) {
if (typeof node !== "string") {
return (this.#live.has(node) || this.#settled.has(node)) && !this.#unloaded.has(node);
}
const owner = this.#edges.get(conversationOf(node));
return owner === null || owner !== void 0 && this.#known(owner);
}
/** Owner task of a conversation, `null` when ownerless, `undefined` while not loaded. */
#edge(id, overlay) {
if (overlay?.edges.has(id) === true)
return overlay.edges.get(id);
this.#record(conversationKey(id));
return this.#edges.get(id);
}
#node(id, overlay) {
return overlay?.tasks.get(id) ?? this.#live.get(id) ?? this.#settled.get(id);
}
/** Walk up from `start`: owner tasks and conversations, ending at an ownerless root or an edge not loaded yet. */
*#above(start, overlay) {
let at = start;
while (at !== void 0) {
if ("task" in at) {
const node = this.#node(at.task, overlay);
if (node === void 0) {
yield { unknown: true };
return;
}
yield { task: at.task, node };
at = parentOf(node);
} else {
yield { conversation: at.conversation };
const edge = this.#edge(at.conversation, overlay);
if (edge === void 0) {
yield { unknown: true };
return;
}
at = edge === null ? void 0 : { task: edge };
}
}
}
/**
* The tasks below `start` that a walk down reaches: those `#below` lists and, under an overlay, the commit's new tasks,
* with its candidates in place of committed records. Background tasks are reached but not entered, unless
* `crossBackground`, and neither are the tasks `enter` rejects. A loop, as chains can be deeper than the call stack.
*/
*#walkDown(start, options = {}) {
const { overlay, crossBackground = false, enter } = options;
const links = overlay === void 0 ? void 0 : this.#links(overlay);
const pending = [start];
for (let at = pending.pop(); at !== void 0; at = pending.pop()) {
this.#record(ownedKey(at));
for (const children of [this.#below.get(at), links?.get(at)]) {
for (const child of children ?? []) {
if (typeof child === "string") {
pending.push(child);
continue;
}
const record = overlay?.tasks.get(child) ?? this.#live.get(child);
const node = record ?? this.#settled.get(child);
if (node === void 0)
continue;
const live = record !== void 0 && record.state.status !== "terminal" ? record : void 0;
yield { id: child, node, live };
if ((crossBackground || !node.background) && (enter === void 0 || enter(child)))
pending.push(child);
}
}
}
}
/**
* The links walks down need for the commit's new tasks: each one under its parent node, then each node above it that
* `#below` does not list yet, until one it lists, a live task (always listed), or the chain's end.
*/
#links(overlay) {
if (overlay.links !== void 0)
return overlay.links;
const links = /* @__PURE__ */ new Map();
for (const record of overlay.tasks.values()) {
if (this.#live.has(record.id) || this.#settled.has(record.id))
continue;
let child = record.id;
let parent = parentNode(record);
while (parent !== void 0 && parent !== null && links.get(parent)?.has(child) !== true) {
addTo(links, parent, child);
if (typeof parent !== "string" && (this.#live.has(parent) || overlay.tasks.has(parent)))
break;
let above;
if (typeof parent === "string") {
above = this.#edge(conversationOf(parent), overlay);
} else {
const fields = this.#settled.get(parent);
above = fields === void 0 ? void 0 : parentNode(fields);
}
if (above !== void 0 && above !== null && this.#below.get(above)?.has(parent) === true)
break;
child = parent;
parent = above;
}
}
overlay.links = links;
return links;
}
/**
* The live ordinary owned work of `owner` (spec §5.5): the live non-background tasks below it that a walk down reaches
* without entering a background task; with `first`, only the first. Candidates in `overlay` replace committed records;
* the walk does not enter tasks in `done`, which have none. Owner chains must be loaded.
*/
#ownedLive(owner, options = {}) {
const { overlay, first = false, done } = options;
const found = [];
const walk = this.#walkDown(owner, {
...overlay === void 0 ? {} : { overlay },
...done === void 0 ? {} : { enter: (id) => !done.has(id) }
});
for (const { id, node, live } of walk) {
if (live === void 0 || node.background)
continue;
found.push(id);
if (first)
break;
}
return found;
}
#hasOwnedLive(owner, overlay, done) {
const options = {
first: true,
...overlay === void 0 ? {} : { overlay },
...done === void 0 ? {} : { done }
};
return this.#ownedLive(owner, options).length > 0;
}
/**
* Whether ordinary traversal from `scope` reaches `start`: walking up reaches the scope's conversation, or an
* ownerless one for `roots`, without crossing a background owner, unless `crossBackground`. `undefined` while an
* edge is not loaded.
*/
#inScope(start, scope, crossBackground = false) {
this.#record(INTENT_KEY);
for (const step of this.#above(start)) {
if ("unknown" in step)
return void 0;
if ("conversation" in step) {
if ("conversation" in scope && step.conversation === scope.conversation)
return true;
} else if (step.node.background && !crossBackground) {
return false;
}
}
return "roots" in scope;
}
/**
* Whether a live owner's cancellation intent reaches `start`: walking up finds an owner with intent before a
* background owner without it. Terminal owners never cascade (spec §5.4).
*/
#belowCancelled(start) {
return this.#cancellingOwner(start) !== void 0;
}
/** The nearest live owner above `start` whose cancellation intent reaches it, if any; see `#belowCancelled`. */
#cancellingOwner(start) {
this.#record(INTENT_KEY);
if (this.#intent.size === 0)
return void 0;
for (const step of this.#above(start)) {
if ("unknown" in step)
return void 0;
if (!("task" in step))
continue;
const live = this.#live.get(step.task);
if (live !== void 0 && cancellationIntent(live))
return live;
if (step.node.background)
return void 0;
}
return void 0;
}
/**
* Count a task in or out of `pi.durable.tasks.active`. Commit observers count at a commit's publication, which must not
* throw, so a throwing adapter is reported.
*/
#countActive(delta, kind) {
try {
this.#activeMetric.add(delta, { task: kind });
} catch (error) {
this.#report(error, TELEMETRY2);
}
}
/** Fail the Session, which reports it, for a throw in one of the scheduler's own commits; ignored once closing. */
#failSession(error, context) {
if (!this.#closing)
this.#session.fail(error, context);
}
/** Close listener: runs synchronously once admission is sealed, before `join()`, or when the Session fails. */
#seal() {
for (const record of this.#live.values())
this.#countActive(-1, record.kind);
this.#resumed.clear();
this.#closing = true;
try {
this.#unsubscribeRegistry();
} catch (error2) {
this.#report(error2, REGISTRY);
}
const error = closedError(this.#session);
this.#taskWaiters.rejectAll(error);
this.#idleWaiters.rejectAll(error);
this.#contexts.clear();
this.#idleOrder.clear();
this.#expiry?.disarm();
this.#expiry = void 0;
this.#timer?.disarm();
this.#timer = void 0;
}
/**
* Recompute the wake in a microtask the line never waits for, with no order relative to host commit listeners (one
* already queued serves later changes too): arm the built-in timer, or tell `onWake` of a change.
*/
#scheduleWake() {
if (this.#wakeScheduled || this.#closing || this.#readOnly)
return;
this.#wakeScheduled = true;
queueMicrotask(() => {
this.#wakeScheduled = false;
if (this.#closing)
return;
const wake = this.wake();
if (this.#onWake === void 0) {
this.#armTimer(this.#enabled ? wake.at : void 0);
return;
}
const last = this.#lastWake;
if (last !== void 0 && last.active === wake.active && last.at === wake.at)
return;
try {
this.#onWake(wake);
this.#lastWake = wake;
} catch (error) {
this.#report(error, ON_WAKE);
}
});
}
/**
* Keep the timer for the earliest sleep. It keeps the process alive, unlike the context expiry timer: a process with a
* sleeping task has work left, such as a retry backoff. Rechecks the clock when it fires, so a wake before `until`
* only arms it again.
*/
#armTimer(at) {
if (this.#timer !== void 0 && this.#timer.at === at)
return;
this.#timer?.disarm();
this.#timer = void 0;
if (at === void 0 || this.#closing)
return;
const disarm = this.#timers.foreground(() => {
this.#timer = void 0;
this.#wakeDue();
this.#kick();
}, at - this.#now());
this.#timer = { at, disarm };
}
/** Make every sleeping task whose time has come a reservation candidate. */
#wakeDue() {
for (const id of this.#sleeping) {
const record = this.#live.get(id);
if (record !== void 0 && !this.#notDue(record))
this.#runnable.add(id);
}
}
/**
* The report info of a task's failure, with the extension that installed its definition: the code that failed is
* that extension's. Built-in tasks have none.
*/
/** What a report about `task`'s own code says of it: the task, and the extension that installed its definition. */
#aboutTask(task) {
let extension;
if ("extension" in task)
extension = task.extension;
else {
try {
const snapshot = this.#registry.snapshot();
extension = installerOf(snapshot, snapshot.task(task.kind));
} catch {
}
}
return { task: reportTask(task), ...optionalExtension(extension) };
}
/** `settings.restartLimit`, or the default when the host's settings throw. */
#restartLimit() {
try {
return this.#settings().restartLimit;
} catch (error) {
this.#report(error, SETTINGS);
return DEFAULT_RESTART_LIMIT;
}
}
#notifyBlocked() {
for (const listener of [...this.#blockedListeners]) {
try {
listener();
} catch (error) {
this.#report(error, { kind: "listener_error" });
}
}
}
/** A sleep whose `until` the clock has not reached; an abort mark ends a sleep. */
#notDue(record) {
const state2 = record.state;
return state2.status === "sleeping" && !record.abortRequested && state2.until > this.#now();
}
#kick() {
this.#scheduleWake();
this.#dirty = true;
if (this.#draining || !this.#enabled || this.#closing)
return;
this.#draining = true;
queueMicrotask(() => void this.#drain());
}
async #drain() {
try {
while (this.#dirty && this.#enabled && !this.#closing) {
this.#dirty = false;
for (const reservation of await this.#reserve())
this.#start(reservation);
}
} catch (error) {
this.#failSession(error);
} finally {
this.#draining = false;
if (this.#dirty)
this.#kick();
}
}
/**
* Reserve every eligible task in one commit; orphan abort-marked tasks no definition can take, unless abandoned after
* a restart. The first pass after open only abort-marks the abandoned tasks, so later passes see the marks.
*/
async #reserve() {
const reservations = [];
const faulted = [];
let abandoned = [];
try {
await this.#session.commitInternal(async (tx) => {
if (!this.#enabled || this.#closing)
return;
if (this.#abandoned.size > 0) {
const ids = [...this.#abandoned];
const unmarked = await this.#region(() => ids.map((id) => this.#liveRecord(id)).filter((record) => record !== void 0 && !record.abortRequested));
for (const record of unmarked)
tx.setTask(withAbortMark(record, "restart"));
abandoned = ids;
return;
}
await this.#loadScopes(false);
this.#wakeDue();
const plan = await this.#region(() => this.#planReservation(), this.#reloadScopes);
for (const id of plan.dropped)
this.#runnable.delete(id);
if (plan.cascade) {
this.#cascadePending = true;
this.#scheduleReconcile();
}
let snapshot;
for (const record of plan.ready) {
const id = record.id;
const mode = record.abortRequested ? "abort" : "run";
const cutOff = record.restarts !== void 0 && record.restarts >= this.#restartLimit();
if (cutOff && (mode === "abort" || !this.#limitsRestarts(record.kind))) {
const message = mode === "abort" ? `Abort handler of task ${id} (${record.kind}) was cut off ${record.restarts} times` : `Task ${id} (${record.kind}) was cut off ${record.restarts} times without progress`;
await this.#terminate(tx, record, {
status: "faulted",
error: { message, detail: { reason: "restart_limit" } }
});
faulted.push({ record, message });
continue;
}
snapshot ??= this.#registry.snapshot();
const resolution = this.#resolve(record, snapshot);
if (resolution.kind === "blocked") {
if (mode === "abort" && record.abortReason === void 0) {
await this.#terminate(tx, record, { status: "orphaned", reason: resolution.reason });
}
continue;
}
if (resolution.record !== record || record.state.status !== "running") {
tx.setTask(withState(resolution.record, {
status: "running",
checkpoint: resolution.record.state.checkpoint
}));
}
this.#runnable.delete(id);
const invocation = this.#createInvocation(record, mode, installerOf(snapshot, resolution.task));
reservations.push({ invocation, task: resolution.task, snapshot });
}
}, this.#context);
} catch (error) {
for (const { invocation } of reservations) {
this.#invocations.delete(invocation.taskId);
this.#runnable.add(invocation.taskId);
invocation.finish();
}
throw error;
}
for (const { record, message } of faulted) {
this.#report(new Error(message), {
kind: "task_faulted",
...this.#aboutTask(recordTask(record)),
reason: "restart_limit"
});
}
for (const id of abandoned)
this.#abandoned.delete(id);
if (abandoned.length > 0)
this.#dirty = true;
return reservations;
}
/**
* A reservation pass's decision region: the candidates it drops (gone, holding, waiting, asleep, or with an
* invocation), whether one waits for a cascade, and the runnable records to resolve. Iterating the candidates is not
* keyed: a pass that misses a task a pending commit makes runnable only delays it, as does skipping one with an
* invocation without reading its record, or a waiter's check whether what it waits on is still live.
*/
#planReservation() {
const dropped = [];
const ready = [];
let cascade = false;
for (const id of this.#runnable) {
if (this.#invocations.has(id)) {
dropped.push(id);
continue;
}
const record = this.#liveRecord(id);
if (record === void 0 || record.state.status === "completing" || this.#waitingOn(record, true).length > 0 || this.#notDue(record)) {
dropped.push(id);
continue;
}
if (!record.abortRequested && !record.background && this.#belowCancelled(parentOf(record))) {
cascade = true;
continue;
}
ready.push(record);
}
return { dropped, cascade, ready };
}
/**
* Live tasks a task waits for before its next invocation: its live ordinary owned work when abort-marked, since
* abort runs bottom-up, otherwise the live part of the `on` of a wait.
*/
#waitingOn(record, first = false) {
if (record.abortRequested)
return this.#ownedLive(record.id, { first });
if (record.state.status !== "waiting")
return [];
if (!first)
return record.state.on.filter((id) => this.#live.has(id));
const live = record.state.on.find((id) => this.#live.has(id));
return live === void 0 ? [] : [live];
}
/** Resolve the record's definition by kind, migrating an older stored version. */
#resolve(record, snapshot) {
const fit = this.#fit(record, snapshot.task(record.kind));
if ("reason" in fit)
return { kind: "blocked", reason: fit.reason };
if (!fit.migrates)
return { kind: "ready", task: fit.task, record };
const definition = erased(fit.task);
try {
if (definition.migrate === void 0)
throw missingMigration(record, definition);
const migrated = definition.migrate(record.input, record.state.checkpoint, record.version);
const state2 = { ...record.state, checkpoint: copyJson(migrated.checkpoint) };
const migratedRecord = { ...record, version: definition.version, input: copyJson(migrated.input), state: state2 };
return { kind: "ready", task: fit.task, record: migratedRecord };
} catch (error) {
this.#failedMigrations.set(record.id, { task: fit.task, error });
queueMicrotask(() => this.#notifyBlocked());
this.#scheduleWake();
const extension = installerOf(snapshot, fit.task);
this.#report(error, { kind: "migration_failed", ...this.#aboutTask({ ...recordTask(record), extension }) });
return { kind: "blocked", reason: "migration_failed" };
}
}
#fit(record, task) {
if (task === void 0)
return { reason: "missing_task" };
const version = task.definition.version;
if (version === record.version)
return { task, migrates: false };
if (version < record.version)
return { reason: "task_too_old" };
const failed = this.#failedMigrations.get(record.id);
if (failed?.task === task)
return { reason: "migration_failed", error: failed.error };
return { task, migrates: true };
}
/** Sizes of the ownership indexes, for tests that bound the scheduler's memory. */
get indexSizes() {
let below = 0;
for (const children of this.#below.values())
below += children.size;
return {
live: this.#live.size,
settled: this.#settled.size,
edges: this.#edges.size,
below,
roots: this.#roots.size,
unloaded: this.#unloaded.size,
dropQueue: this.#dropQueue.size,
pins: this.#pins.size
};
}
/**
* The kept contexts' idle state, for tests (a diagnostic, computed on demand): how many are kept and how many are
* idle, how many disagree with a full recompute (an idle period without `#idle()`, or `#idle()` without one; an
* expiry order that differs from the idle periods, or is not sorted), and how many idle checks covered every scope.
*/
get idleState() {
let mismatches = 0;
let idle = 0;
for (const [conversationId, kept] of this.#contexts) {
if (kept.idleSince !== void 0)
idle++;
if (kept.idleSince !== void 0 !== this.#idle(conversationId))
mismatches++;
if (this.#idleOrder.get(conversationId) !== kept.idleSince)
mismatches++;
}
let previous = Number.NEGATIVE_INFINITY;
for (const [conversationId, idleSince] of this.#idleOrder) {
if (idleSince < previous || this.#contexts.get(conversationId)?.idleSince !== idleSince)
mismatches++;
previous = idleSince;
}
return {
contexts: this.#contexts.size,
idleContexts: idle,
idleMismatches: mismatches,
fullIdleChecks: this.#fullIdleChecks
};
}
/**
* Scheduling state and every live task with its derived state, read on the Session line. Runs no task code: a
* pending migration shows as `ready` with `migrates`, and only a migration the scheduler already tried, or one that
* cannot exist, shows as failed.
*/
async inspect(snapshot) {
await this.#published();
await this.#loadScopes(false);
const tasks = [];
for (const record of this.#live.values())
tasks.push({ record, state: this.#inspectTask(record, snapshot) });
const scheduling = this.#closing ? "closing" : this.#enabled ? "running" : "paused";
return { scheduling, tasks };
}
#inspectTask(record, snapshot) {
if (this.#invocations.has(record.id))
return { kind: "running" };
if (record.state.status === "completing")
return { kind: "completing" };
const on = this.#waitingOn(record);
if (on.length > 0)
return { kind: "waiting", on };
if (this.#notDue(record))
return { kind: "sleeping", until: record.state.until };
const fit = this.#fit(record, snapshot.task(record.kind));
if ("reason" in fit)
return { kind: "blocked", ...fit };
if (fit.migrates && fit.task.definition.migrate === void 0) {
return { kind: "blocked", reason: "migration_failed", error: missingMigration(record, erased(fit.task)) };
}
return { kind: "pending", migrates: fit.migrates };
}
#createInvocation(record, mode, extension) {
const controller = new AbortController();
const { promise: done, resolve: finish } = Promise.withResolvers();
const invocation = {
taskId: record.id,
kind: record.kind,
extension,
conversationId: record.conversationId,
mode,
controller,
links: record.startedAt === void 0 ? record.links : void 0,
context: withAbortSignal(controller.signal, this.#context),
record,
watches: /* @__PURE__ */ new Set(),
timers: /* @__PURE__ */ new Set(),
ended: false,
done,
finish: () => finish()
};
this.#invocations.set(record.id, invocation);
return invocation;
}
#start(reservation) {
const invocation = reservation.invocation;
void (async () => {
try {
if (invocation.mode === "run")
await this.#run(reservation);
else
await this.#runAbort(reservation);
} catch (error) {
this.#report(error, { kind: "task_error", ...this.#aboutTask(invocation) }, invocation.context);
} finally {
this.#end(invocation);
invocation.record = void 0;
invocation.links = void 0;
invocation.fault = void 0;
invocation.finish();
this.#kick();
}
})();
}
/** Run phase handlers, each preceded by a step that decides on the line whether the invocation continues. */
async #run(reservation) {
const invocation = reservation.invocation;
const state2 = { task: reservation.task, snapshot: reservation.snapshot, reported: void 0 };
const phase = { snapshot: () => state2.snapshot, task: () => state2.task, agent: void 0 };
const runtime = this.#runtime(invocation, phase);
const progress = (tx, current2) => this.#progress(tx, current2, state2, invocation.extension, invocation.context);
let current = await this.#step(invocation, (task) => this.#rules(task, void 0), progress);
while (current !== void 0 && !this.#closing) {
const task = current;
current = await this.#phase(invocation, task, async () => {
const checkpoint = task.state.checkpoint;
phase.agent = void 0;
let previous;
try {
await erased(state2.task).phases[checkpoint.phase](task, runtime, invocation.context);
previous = { checkpoint };
} catch (error) {
previous = { checkpoint, failure: { error } };
}
return this.#step(invocation, (next) => this.#rules(next, previous), progress);
});
}
}
/** A phase owns its decision commit, not the next handler, a durable wait, or recovery. */
#phase(invocation, task, run2) {
const parent = task.trace === void 0 ? this.#telemetry : this.#telemetry.propagation?.extract(task.trace) ?? this.#telemetry;
const checkpoint = task.state.checkpoint;
const attempt = checkpoint.attempt;
const resumed = this.#resumed.delete(task.id);
return createTypedSpanStarter(parent, [DURABLE_TELEMETRY_SCHEMA])("pi.durable.phase", {
"task.id": task.id,
"task.name": task.kind,
phase: checkpoint.phase,
kind: invocation.mode,
resumed,
...attempt === void 0 ? {} : { attempt }
}, async (span) => {
if (span.propagation !== void 0 && invocation.links !== void 0) {
for (const carrier of invocation.links)
span.addLink({ context: span.propagation.extract(carrier) });
}
const previous = invocation.context;
invocation.context = withTelemetry(span, previous);
const started = performance.now();
try {
return await run2();
} finally {
invocation.context = previous;
const state2 = invocation.record.state;
const terminal = invocation.fault ?? (state2.status === "terminal" || state2.status === "completing" ? state2.outcome : void 0);
const outcome = terminal !== void 0 ? terminal.status === "completed" ? "done" : terminal.status === "aborted" ? "aborted" : "faulted" : state2.status === "waiting" || state2.status === "sleeping" ? state2.status : invocation.ended || this.#closing ? "aborted" : `next=${state2.checkpoint.phase}`;
span.setAttributes({ outcome });
if (terminal?.status === "faulted" || terminal?.status === "failed" || terminal?.status === "orphaned") {
const message = terminal.status === "orphaned" ? terminal.reason : terminal.error.message;
span.setStatus({
status: "error",
error: { name: `task_${terminal.status}`, message: ownedSlice2(message, 0, 500) }
});
} else if (outcome === "aborted") {
span.setStatus({ status: "ok" });
}
this.#durationMetric.record(performance.now() - started, { task: task.kind, phase: checkpoint.phase, outcome }, span);
}
});
}
/**
* Precedence rules for a run invocation, a decision region of its step. Rules 1 (terminal, `completing`, `waiting`, or
* `sleeping`) and 2 (closing) are applied by `#step`. Progress (rule 5) is decided by `#progress()` once the decision
* stands, as it takes a registry snapshot.
*/
#rules(current, previous) {
if (current.abortRequested)
return END;
if (!current.background && this.#belowCancelled(parentOf(current)))
return CASCADE;
if (previous === void 0)
return CONTINUE;
if (previous.failure !== void 0)
return { kind: "fault", error: previous.failure.error };
if (jsonEqual(current.state.checkpoint, previous.checkpoint)) {
const message = `Task ${current.kind} phase ${previous.checkpoint.phase} returned without durable progress`;
return { kind: "fault", error: new Error(message) };
}
return PROGRESS;
}
/**
* Rule 5, progress: refresh the snapshot; hand over to a replacement definition that can take the task, writing it
* back as `pending`, or keep running under the old one, reported once per resolved definition. Returns whether the
* invocation continues.
*/
#progress(tx, current, state2, extension, context) {
state2.snapshot = this.#registry.snapshot();
const next = state2.snapshot.task(current.kind);
if (next === state2.task)
return true;
if (next !== void 0 && canReserve(next, current)) {
tx.setTask(withState(current, { status: "pending", checkpoint: current.state.checkpoint }));
return false;
}
if (state2.reported === void 0 || state2.reported.task !== next) {
state2.reported = { task: next };
this.#report(new Error(`Task ${current.id} keeps running under its old ${current.kind} definition`), {
kind: "task_outdated",
...this.#aboutTask({ ...recordTask(current), extension }),
reason: outdatedReason(next, current)
}, context);
}
return true;
}
/** Run the abort handler once; rules 1, 2, and 4 apply, and returning without an outcome faults. */
async #runAbort(reservation) {
const invocation = reservation.invocation;
const current = this.#live.get(invocation.taskId);
if (current === void 0 || this.#closing)
return;
await this.#phase(invocation, current, async () => {
let failure;
try {
const phase = {
snapshot: () => reservation.snapshot,
task: () => reservation.task,
agent: void 0
};
const runtime = this.#runtime(invocation, phase);
await erased(reservation.task).abort(current, runtime, invocation.context);
} catch (error) {
failure = { error };
}
const message = `Abort handler of task ${invocation.taskId} returned without a terminal outcome`;
await this.#step(invocation, () => ({ kind: "fault", error: failure?.error ?? new Error(message) }));
});
}
/**
* One decision on the Session line, before a phase: a decision region (`#region()`) that reads the task's record. A
* task that is no longer running (rule 1: terminal, `completing`, `waiting`, or `sleeping`) or a closing Harness (rule
* 2) ends the invocation without a write; otherwise `plan` decides, and a decision that stands is applied: the
* invocation continues, with `progress` for rule 5, or ends, with a fault written. Ending happens inside the callback,
* before a fault's Harness cleanup. A rejected step, such as admission after close, also ends the invocation. Its
* outcome goes to the invocation only, so it is a scheduler commit (`commitInternal()`).
*/
async #step(invocation, plan, progress) {
let fault;
try {
const continued = await this.#session.commitInternal(async (tx) => {
const decided = await this.#region(() => {
const found = this.#liveRecord(invocation.taskId);
if (found?.state.status !== "running" || this.#closing)
return { plan: END };
const current2 = found;
return { current: current2, plan: plan(current2) };
});
const { current } = decided;
const step = decided.plan;
if (step.kind === "continue")
return current;
if (step.kind === "progress" && progress(tx, current))
return current;
this.#end(invocation);
if (step.kind === "cascade") {
this.#cascadePending = true;
this.#scheduleReconcile();
}
if (step.kind === "fault") {
fault = { error: step.error };
const message = errorMessage2(step.error);
invocation.fault = { status: "faulted", error: { message } };
await this.#terminate(tx, current, invocation.fault);
}
return void 0;
}, withoutAbortSignal(invocation.context));
if (fault !== void 0)
this.#report(fault.error, { kind: "task_faulted", ...this.#aboutTask(invocation), reason: "threw" }, invocation.context);
return continued;
} catch (error) {
this.#end(invocation);
this.#failSession(error, invocation.context);
return void 0;
}
}
/**
* Write an outcome the scheduler decided. While the task's ordinary owned work is live it holds as `completing` and
* its Harness cleanup waits for the final commit (spec §5.5, rule 4); otherwise it is terminal with its cleanup.
*/
async #terminate(tx, record, outcome) {
await this.#loadScopes(false);
if (await this.#region(() => this.#hasOwnedLive(record.id, overlayOf(tx)), this.#reloadScopes)) {
tx.setTask(withState(record, { status: "completing", outcome }));
return;
}
tx.setTask(withState(record, { status: "terminal", outcome }));
await this.#settleOutcome(tx, record, outcome);
}
/**
* Replace a running task's state with what it committed. A terminal state holds as `completing` while ordinary owned
* work is live, judged on the commit's candidates, so work the same commit creates below the task counts. A wait is
* validated first.
*/
async #commitState(tx, invocation, current, next) {
if (next.status === "waiting")
await this.#validateWait(tx, invocation, current, next.on, next.policy);
if (next.status === "sleeping")
validateSleep(invocation, current.id, next.until);
if (next.status === "terminal") {
const overlay = overlayOf(tx);
await this.#loadScopes(false);
for (const record of overlay.tasks.values())
await this.#loadChain(parentOf(record), overlay);
if (await this.#region(() => this.#hasOwnedLive(current.id, overlayOf(tx)), this.#reloadScopes)) {
tx.setTask(withState(progressed(current), { status: "completing", outcome: next.outcome }));
return;
}
}
const same = jsonEqual(current.state, next);
tx.setTask(withState(same ? current : progressed(current), next));
}
/**
* A wait names existing tasks, and `failFast` only tasks the waiter owns. It may not close a cycle in the wait-for
* graph, whose edges run from each task to what it waits on and to its live ordinary owned work (spec §5.5); waiting
* on itself or on an owner holding it are the shortest such cycles. An abort handler cannot wait.
*
* Invariant: the wait-for graph is acyclic. Only a wait adds an edge between existing tasks, as a new task has only
* incoming edges, so checking each wait maintains it.
*/
async #validateWait(tx, invocation, current, on, policy) {
if (invocation.mode === "abort")
throw new Error(`Abort handler of task ${current.id} cannot wait`);
await this.#loadScopes(false);
const ended = /* @__PURE__ */ new Map();
for (; ; ) {
const checked = await this.#region(() => this.#checkWait(current, on, policy, overlayOf(tx), ended), this.#reloadScopes);
if (checked === void 0)
return;
if ("missing" in checked) {
for (const id of checked.missing)
ended.set(id, await this.#session.lineStorage.task(id, this.#context) ?? null);
continue;
}
throw checked.error;
}
}
/**
* `#validateWait()`'s decision region: why the wait is refused, `undefined` when it may be stored, or the tasks in
* `on` it needs from Storage first, when `ended` lacks them.
*/
#checkWait(current, on, policy, overlay, ended) {
const targets = [];
const missing = [];
for (const id of on) {
const member = overlay.tasks.get(id) ?? this.#liveRecord(id) ?? ended.get(id);
if (member === void 0) {
missing.push(id);
continue;
}
if (member === null)
return { error: new Error(`Task ${id} does not exist`) };
if (policy === "failFast" && member.owner !== current.id) {
return { error: new Error(`Task ${current.id} can wait failFast only on tasks it owns; ${id} is not one`) };
}
if (member.state.status !== "terminal" && member.owner !== current.id)
targets.push(id);
}
if (missing.length > 0)
return { missing };
if (targets.length === 0)
return void 0;
const cycle = this.#waitCycle(current.id, targets, overlay);
if (cycle === void 0)
return void 0;
return {
error: new Error(`Task ${current.id} cannot wait on ${cycle[0]}: ${[current.id, ...cycle].join(" -> ")} is a wait cycle`)
};
}
/**
* The path from a member of `on` back to `task` in the wait-for graph, if the wait would close a cycle (spec §5.1).
* An edge X -> Y means X cannot settle before Y: Y is in the `on` of waiting X that is not abort-marked, or Y is live
* ordinary owned work of X, which holds X as `completing`. Each task is visited once and each subtree walked once,
* so a check is bounded by the live work it reaches. Part of a decision region: it records every record it reads.
* Owned work is found by walks down, which need the chains of every live task loaded.
*/
#waitCycle(task, on, overlay) {
const from = /* @__PURE__ */ new Map();
const walked = /* @__PURE__ */ new Set();
const pending = [];
const reach = (id, via) => {
if (from.has(id))
return;
from.set(id, via);
pending.push(id);
};
const path3 = (end) => {
const steps = [];
for (let at = end; at !== void 0; at = from.get(at))
steps.unshift(at);
return steps;
};
for (const id of on)
reach(id, void 0);
for (let id = pending.pop(); id !== void 0; id = pending.pop()) {
if (id === task)
return path3(id);
const record = overlay.tasks.get(id) ?? this.#liveRecord(id);
if (record === void 0 || record.state.status === "terminal")
continue;
if (record.state.status === "waiting" && !record.abortRequested) {
for (const member of record.state.on)
reach(member, id);
}
if (walked.has(id))
continue;
walked.add(id);
const found = [];
const walk = this.#walkDown(id, { overlay, enter: (below) => !walked.has(below) });
for (const { id: below, node, live } of walk) {
if (live === void 0 || node.background)
continue;
found.push(below);
reach(below, id);
}
for (const below of found)
walked.add(below);
}
return void 0;
}
/** End an invocation: its runtime operations reject from now on, its signal aborts, its watches stop, and its task is free. */
#end(invocation) {
if (invocation.ended)
return;
invocation.ended = true;
if (this.#invocations.get(invocation.taskId) === invocation) {
this.#invocations.delete(invocation.taskId);
if (this.#live.has(invocation.taskId))
this.#runnable.add(invocation.taskId);
}
for (const watch2 of invocation.watches)
void watch2.stop();
for (const disarm of invocation.timers)
disarm();
invocation.timers.clear();
invocation.controller.abort(endedError(invocation));
}
/** No live non-background task in the scope; a task whose owner edges are not loaded yet counts as inside. */
#idle(conversationId) {
const scope = conversationId === void 0 ? { roots: true } : { conversation: conversationId };
if (conversationId === void 0)
this.#record(ROOTS_KEY);
for (const id of this.#unloaded) {
const record = this.#live.get(id);
if (record !== void 0 && !record.background && this.#inScope(parentOf(record), scope) !== false)
return false;
}
const starts = conversationId === void 0 ? this.#roots : [conversationId];
for (const start of starts) {
for (const { node, live } of this.#walkDown(conversationNode(start))) {
if (live !== void 0 && !node.background)
return false;
}
}
return true;
}
// ─── Invocation runtime ──────────────────────────────────────────────────
#runtime(invocation, phase) {
const agent = () => {
if (invocation.ended)
return Promise.reject(endedError(invocation));
if (phase.agent === void 0) {
phase.agent = this.#agent(invocation.conversationId, phase.snapshot(), invocation.context);
phase.agent.catch(() => {
});
}
return phase.agent;
};
const hooks = {
each: async (name, invoke) => {
for (const { extension, handlers } of agentHooks(await agent(), phase.task().definition.name)) {
const handler = handlers[name];
if (typeof handler !== "function")
continue;
try {
await invoke(handler.bind(handlers));
} catch (error) {
if (invocation.controller.signal.aborted)
throw error;
this.#report(error, { kind: "extension_error", extension, task: reportTask(invocation) }, invocation.context);
}
}
}
};
const settings = this.#settings;
const models2 = this.#models;
return {
taskId: invocation.taskId,
conversationId: invocation.conversationId,
signal: invocation.controller.signal,
get models() {
return models2();
},
agent: (context) => invocation.ended ? Promise.reject(endedError(invocation)) : awaitWithContext(agent(), context),
get settings() {
return settings();
},
env: (context) => this.#read(invocation, () => this.#env(invocation.conversationId, context)),
hooks,
get registry() {
return phase.snapshot();
},
commit: async (change, context, options) => {
let checkpoint;
let interrupted2;
await this.#gated(invocation, async (tx, current) => {
const next = await change(tx, current);
if (next !== void 0)
await this.#commitState(tx, invocation, current, next);
if (next?.status === "running" && current.state.checkpoint.phase !== next.checkpoint.phase) {
checkpoint = next.checkpoint.phase;
}
if (next?.status === "terminal") {
const restarts = current.restarts ?? 0;
const reason = next.outcome.status === "failed" ? interruptionOf(next.outcome.error) : void 0;
if (reason !== void 0 && next.outcome.status === "failed") {
interrupted2 = { message: next.outcome.error.message, reason, restarts };
} else {
const message = endedByCrashesStates.get(next);
if (message !== void 0)
interrupted2 = { message, reason: "restart_limit", restarts };
}
}
}, context, options);
if (interrupted2 !== void 0) {
this.#report(new Error(interrupted2.message), {
kind: "task_interrupted",
...this.#aboutTask(invocation),
reason: interrupted2.reason,
restarts: interrupted2.restarts
}, invocation.context);
}
if (checkpoint !== void 0) {
invocation.context.telemetry.addEvent("pi.durable.checkpoint", {
phase: checkpoint
});
}
},
memo: ((name, ...rest) => {
if (rest.length === 1) {
return this.#read(invocation, async () => memoOf(this.#live.get(invocation.taskId), name));
}
const candidate = rest[0];
return this.#gated(invocation, (tx, current) => {
const winner = memoOf(current, name);
if (winner !== void 0)
return winner;
tx.setTask({ ...current, memos: { ...current.memos, [name]: candidate } });
return candidate;
}, rest[1]);
}),
sleepUntil: (until, checkpoint, context) => this.#gated(invocation, (tx, current) => this.#commitState(tx, invocation, current, { status: "sleeping", checkpoint, until }), context),
watchDoc: ((...args) => this.#watchDoc(invocation, args)),
snapshot: ((...args) => this.#read(invocation, () => sessionMethod(this.#session, "snapshot")(...args))),
snapshotAsOf: ((...args) => this.#read(invocation, () => sessionMethod(this.#session, "snapshotAsOf")(...args))),
getTask: ((id, context) => this.#read(invocation, () => this.#session.readOnLine((storage) => storage.task(id, context)))),
waitForTask: ((id, context) => this.#read(invocation, () => this.waitForTask(id, withAbortSignal(invocation.controller.signal, context)))),
ownedTasks: (context) => this.#read(invocation, () => this.#session.readOnLine(async () => {
if (invocation.ended)
throw endedError(invocation);
context.abortSignal?.throwIfAborted();
const owned = await this.#region(() => {
this.#record(ownedKey(invocation.taskId));
const records = [];
for (const node of this.#below.get(invocation.taskId) ?? []) {
const record = typeof node === "string" ? void 0 : this.#liveRecord(node);
if (record?.owner === invocation.taskId)
records.push(record);
}
return records;
});
return owned.sort((a, b) => a.id - b.id).map((record) => copyJson(record));
})),
abortOwned: (id, context) => this.#read(invocation, async () => {
const bound = withAbortSignal(invocation.controller.signal, context);
const record = await this.#session.readOnLine((storage) => storage.task(id, bound));
if (record?.owner !== invocation.taskId) {
throw new Error(`Task ${id} is not owned by task ${invocation.taskId}`);
}
if (record.state.status === "terminal")
return;
await this.abort(id, bound, true);
await this.waitForTask(id, bound);
}),
outcomes: ((ids, context) => this.#read(invocation, () => this.#session.readOnLine(async (storage) => {
const outcomes = [];
for (const id of ids) {
const state2 = (await storage.task(id, context))?.state;
if (state2?.status !== "terminal")
throw new Error(`Task ${id} is not terminal`);
outcomes.push(state2.outcome);
}
return outcomes;
}))),
conversation: (id, context) => this.#read(invocation, () => this.#conversation(id, {
signal: invocation.controller.signal,
check: () => {
if (invocation.ended)
throw endedError(invocation);
}
}, context)),
entry: ((...args) => {
const [token, id, context] = args.length === 2 ? [void 0, args[0], args[1]] : [args[0], args[1], args[2]];
return this.#read(invocation, async () => {
const kept = this.#contexts.get(invocation.conversationId);
const entry2 = (kept === void 0 ? void 0 : rangeEntry(kept.range, id)) ?? (await this.#session.readOnLine((storage) => storage.entry(invocation.conversationId, id, context)))?.entry;
return token === void 0 || entry2?.kind === token.kind ? entry2 : void 0;
});
}),
entries: (query, limit2, cursor, context) => this.#read(invocation, () => this.#session.readOnLine((storage) => storage.scanEntries(conversationEntries(invocation.conversationId, query), limit2, cursor, context))),
context: (conversationId, context, options) => this.#read(invocation, async () => {
const read2 = await readContextFrom(this.#session, this.#storage, conversationId, context, options?.at, this.#contexts.get(conversationId)?.range);
const { view: view2 } = read2;
const range = read2.range?.current === true && this.#session.knownLatestEntryId(conversationId) !== read2.range.bounds.tail ? { ...read2.range, current: false } : read2.range;
const kept = this.#contexts.get(conversationId);
if (range !== void 0 && !this.#closing && !invocation.ended && (kept === void 0 || kept.range.bounds.tail <= range.bounds.tail)) {
if (!this.#idle(conversationId)) {
this.#contexts.set(conversationId, { range, idleSince: void 0 });
this.#idleOrder.delete(conversationId);
} else if (this.#contextRetentionMs() > 0) {
const idleSince = kept?.idleSince ?? this.#now();
const expiresAt = kept?.idleSince !== void 0 && kept.expiresAt !== void 0 ? kept.expiresAt : idleSince + this.#contextRetentionMs();
this.#contexts.set(conversationId, { range, idleSince, expiresAt });
if (kept?.idleSince === void 0)
this.#markIdle(conversationId, idleSince);
this.#scheduleExpiry();
}
}
return view2;
}),
now: () => {
if (invocation.ended)
throw endedError(invocation);
return this.#now();
},
setTimer: (callback, delayMs) => {
if (invocation.ended)
return () => {
};
const disarm = this.#timers.foreground(() => {
invocation.timers.delete(disarm);
if (!invocation.ended)
callback();
}, delayMs);
invocation.timers.add(disarm);
return () => {
invocation.timers.delete(disarm);
disarm();
};
},
report: (error, from) => {
if (invocation.ended)
throw endedError(invocation);
const task = reportTask(invocation);
this.#report(error, from === void 0 ? { kind: "task_error", ...this.#aboutTask(invocation) } : from.kind === "extension" ? { kind: "extension_error", task, ...optionalExtension(from.extension) } : { kind: "host_error", callback: from.callback, task }, invocation.context);
}
};
}
/**
* On the line: wait until every commit admitted before is published, for a decision that reads what cannot be keyed,
* every live task (open, inspection) or every task a conversation abort reaches.
*/
async #published() {
const gate = this.#session.touch(ALL_KEYS);
if (gate !== void 0)
await gate;
}
/** Run a committed-state read unless the invocation has ended. */
async #read(invocation, read2) {
if (invocation.ended)
throw endedError(invocation);
return read2();
}
/** Commit after rereading the task on the line and gating the invocation. */
#gated(invocation, change, context, options) {
if (invocation.ended)
return Promise.reject(endedError(invocation));
return this.#session.commitWith(async (tx) => {
if (invocation.ended)
throw endedError(invocation);
if (this.#closing)
throw closedError(this.#session);
const current = await this.#region(() => {
const found = this.#liveRecord(invocation.taskId);
if (found === void 0)
throw new Error(`Task ${invocation.taskId} is terminal`);
if (found.state.status !== "running")
throw new Error(`Task ${invocation.taskId} is ${found.state.status}`);
if (invocation.mode === "run" && found.abortRequested) {
throw new Error(`Task ${invocation.taskId} has a durable abort mark`);
}
return found;
});
if (invocation.ended)
throw endedError(invocation);
return change(tx, current);
}, context, { conversationId: invocation.conversationId, taskId: invocation.taskId }, options);
}
async #watchDoc(invocation, args) {
if (invocation.ended)
throw endedError(invocation);
const watch2 = await sessionMethod(this.#session, "watchDoc")(...args);
if (watch2 === void 0)
return void 0;
if (invocation.ended) {
void watch2.stop();
throw endedError(invocation);
}
invocation.watches.add(watch2);
void watch2.closed.then(() => invocation.watches.delete(watch2));
return watch2;
}
};
var REGISTRY = { kind: "host_error", callback: "registry" };
var SETTINGS = { kind: "host_error", callback: "settings" };
var ON_WAKE = { kind: "host_error", callback: "onWake" };
var TELEMETRY2 = { kind: "host_error", callback: "telemetry" };
function installerOf(snapshot, task) {
if (task === void 0)
return void 0;
return snapshot.installed().findLast((installed) => installed.tasks?.includes(task) === true)?.name;
}
function reportTask(task) {
return { id: task.taskId, kind: task.kind, conversationId: task.conversationId };
}
function recordTask(record) {
return { taskId: record.id, kind: record.kind, conversationId: record.conversationId };
}
var endedByCrashesStates = /* @__PURE__ */ new WeakMap();
function endedByCrashes(state2, message) {
endedByCrashesStates.set(state2, message);
return state2;
}
function interruptionOf(error) {
const detail = error.detail;
if (typeof detail !== "object" || detail === null || !("reason" in detail))
return void 0;
return detail.reason === "restart_limit" || detail.reason === "interrupted" ? detail.reason : void 0;
}
function withAbortMark(record, reason) {
const { abortReason: _reason, restarts: _restarts, ...rest } = record;
return { ...rest, abortRequested: true, ...reason === void 0 ? {} : { abortReason: reason } };
}
function cancellationIntent(record) {
return record.state.status !== "terminal" && (record.abortRequested || failedOutcome(record));
}
function intentChanges(previous, next) {
return (previous?.abortRequested ?? false) !== next.abortRequested || previous?.abortReason !== next.abortReason || (previous !== void 0 && failedOutcome(previous)) !== failedOutcome(next) || (previous !== void 0 && cancellationIntent(previous)) !== cancellationIntent(next);
}
function failedOutcome(record) {
const state2 = record.state;
return (state2.status === "completing" || state2.status === "terminal") && state2.outcome.status !== "completed";
}
function parentOf(node) {
return node.owner !== void 0 ? { task: node.owner } : { conversation: node.conversationId };
}
function nodeOf(record) {
return {
conversationId: record.conversationId,
...record.owner === void 0 ? {} : { owner: record.owner },
background: record.background
};
}
function overlayOf(tx) {
const tasks = new Map(tx.stagedTasks().map((record) => [record.id, record]));
const edges = new Map(tx.stagedConversations().map((record) => [record.id, record.owner?.taskId ?? null]));
return { tasks, edges };
}
function addTo(map2, key, value2) {
const values = map2.get(key);
if (values === void 0)
map2.set(key, /* @__PURE__ */ new Set([value2]));
else
values.add(value2);
}
function deleteFrom(map2, key, value2) {
const values = map2.get(key);
if (values === void 0)
return;
values.delete(value2);
if (values.size === 0)
map2.delete(key);
}
function memoOf(record, name) {
const memos = record?.memos;
return memos !== void 0 && Object.hasOwn(memos, name) ? memos[name] : void 0;
}
function sessionMethod(session, name) {
return session[name].bind(session);
}
function missingMigration(record, definition) {
return new Error(`Task ${record.kind} version ${definition.version} has no migration from ${record.version}`);
}
function erased(task) {
return task.definition;
}
function endedError(invocation) {
return new Error(`Task ${invocation.taskId} invocation has ended`);
}
function progressed(record) {
if (record.restarts === void 0)
return record;
const { restarts: _restarts, ...rest } = record;
return rest;
}
function withState(record, state2) {
if (state2.status !== "terminal" && state2.status !== "completing")
return { ...record, state: state2 };
const { memos: _memos, restarts: _restarts, ...rest } = record;
return { ...rest, state: state2 };
}
function outdatedReason(task, record) {
if (task === void 0)
return "missing_task";
return task.definition.version < record.version ? "task_too_old" : "migration_failed";
}
function canReserve(task, record) {
const definition = task.definition;
return definition.version === record.version || definition.version > record.version && definition.migrate !== void 0;
}
function validateSleep(invocation, task, until) {
if (invocation.mode === "abort")
throw new Error(`Abort handler of task ${task} cannot sleep`);
if (typeof until !== "number" || !Number.isFinite(until) || until < 0) {
throw new Error(`Task ${task} cannot sleep until ${until}: not a time in milliseconds`);
}
}
function jsonEqual(left, right) {
if (left === right)
return true;
if (typeof left !== "object" || typeof right !== "object" || left === null || right === null)
return false;
if (Array.isArray(left) || Array.isArray(right)) {
if (!Array.isArray(left) || !Array.isArray(right) || left.length !== right.length)
return false;
return left.every((value2, index) => jsonEqual(value2, right[index]));
}
const keys = Object.keys(left);
if (keys.length !== Object.keys(right).length)
return false;
return keys.every((key) => Object.hasOwn(right, key) && jsonEqual(left[key], right[key]));
}
// node_modules/@earendil-works/chord/dist/output.js
var NEWLINE = 10;
var INVALID_OUTPUT = /[\x00-\x08\x0b-\x1f\ufff9-\ufffb]/g;
var ESCAPE_SEQUENCE = /\x1b[\]PX^_][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]|\x1b[\x20-\x2f]*[\x30-\x7e]/g;
var encoder = new TextEncoder();
var decoder = new TextDecoder("utf-8", { ignoreBOM: true });
function sanitizeOutput(text2) {
return text2.replace(ESCAPE_SEQUENCE, "").replace(INVALID_OUTPUT, "");
}
function boundOutput(text2, limits) {
const bytes2 = encoder.encode(text2);
const [from, to] = limits.retain === "head" ? headRange(bytes2, limits) : tailRange(bytes2, limits);
const kept = bytes2.subarray(from, to);
return {
text: kept.length === bytes2.length ? text2 : decoder.decode(kept),
bytes: kept.length,
droppedBytes: bytes2.length - kept.length,
droppedLines: lineCount(bytes2) - lineCount(kept)
};
}
function headRange(bytes2, limits) {
if (limits.maxLines === 0 || limits.maxBytes === 0)
return [0, 0];
let end = bytes2.length;
let lines2 = 0;
for (let index = bytes2.indexOf(NEWLINE); index !== -1; index = bytes2.indexOf(NEWLINE, index + 1)) {
if (++lines2 === limits.maxLines) {
end = index + 1;
break;
}
}
if (end > limits.maxBytes) {
const newline = bytes2.lastIndexOf(NEWLINE, limits.maxBytes - 1);
end = newline === -1 ? characterEnd(bytes2, limits.maxBytes) : newline + 1;
}
return [0, end];
}
function tailRange(bytes2, limits) {
if (limits.maxLines === 0 || limits.maxBytes === 0)
return [bytes2.length, bytes2.length];
const last = bytes2[bytes2.length - 1] === NEWLINE ? bytes2.length - 2 : bytes2.length - 1;
let start = 0;
let lines2 = 1;
for (let index = last < 0 ? -1 : bytes2.lastIndexOf(NEWLINE, last); index !== -1; ) {
if (lines2 === limits.maxLines) {
start = index + 1;
break;
}
lines2++;
index = index === 0 ? -1 : bytes2.lastIndexOf(NEWLINE, index - 1);
}
if (bytes2.length - start > limits.maxBytes) {
const from = bytes2.length - limits.maxBytes;
const newline = bytes2.indexOf(NEWLINE, from - 1);
start = newline !== -1 && newline + 1 < bytes2.length ? newline + 1 : characterStart(bytes2, from);
}
return [start, bytes2.length];
}
function characterEnd(bytes2, index) {
let end = index;
while (end > 0 && ((bytes2[end] ?? 0) & 192) === 128)
end--;
return end;
}
function characterStart(bytes2, index) {
let start = index;
while (start < bytes2.length && ((bytes2[start] ?? 0) & 192) === 128)
start++;
return start;
}
function lineCount(bytes2) {
if (bytes2.length === 0)
return 0;
let newlines = 0;
for (let index = bytes2.indexOf(NEWLINE); index !== -1; index = bytes2.indexOf(NEWLINE, index + 1))
newlines++;
return newlines + (bytes2[bytes2.length - 1] === NEWLINE ? 0 : 1);
}
var OutputBuffer = class {
#limits;
/**
* Decoder of byte chunks. A string chunk or a skip ends an incomplete character of earlier bytes (it becomes U+FFFD);
* the next byte chunk then starts a new character. As in `StreamDecoder`, only a byte-order mark at the very start of
* the output is dropped, never a U+FEFF later in it.
*/
#decoder = new TextDecoder("utf-8", { ignoreBOM: true });
#started = false;
/** Stored chunks: for head the start of the stream, for tail a suffix that still contains the next window. */
#chunks = [];
#storedBytes = 0;
#storedNewlines = 0;
#full = false;
#totalBytes = 0;
#totalNewlines = 0;
#endsWithNewline = true;
constructor(limits) {
this.#limits = limits;
}
/** Bytes currently held; bounded by the limits plus one chunk. */
get storedBytes() {
return this.#storedBytes;
}
/**
* Accept a chunk; returns whether anything was accepted. `skipped` is output omitted right before the chunk, which
* must be more than the tail window by at least one byte or line; only tail retention accepts it.
*/
push(chunk, skipped) {
const pending = typeof chunk === "string" || skipped !== void 0 ? this.#decoder.decode() : "";
let text2 = typeof chunk === "string" ? chunk : this.#decoder.decode(chunk, { stream: true });
const first = !this.#started && pending === "" && skipped === void 0;
if (pending !== "" || text2 !== "" || skipped !== void 0)
this.#started = true;
if (first && typeof chunk !== "string" && text2.startsWith("\uFEFF"))
text2 = text2.slice(1);
if (skipped === void 0)
return this.#accept(pending + text2);
if (this.#limits.retain !== "tail")
throw new Error("Skipped output requires tail retention");
this.#accept(pending);
this.#skip(skipped);
this.#accept(text2);
return true;
}
/** Count omitted output; nothing stored before it can be in the window once the text after it arrives. */
#skip(skipped) {
if (skipped.bytes === 0)
return;
this.#totalBytes += skipped.bytes;
this.#totalNewlines += skipped.newlines;
this.#endsWithNewline = skipped.endsWithNewline;
this.#chunks = [];
this.#storedBytes = 0;
this.#storedNewlines = 0;
}
/** Flush an incomplete trailing character as a replacement character; call when the stream ends. */
end() {
this.#accept(this.#decoder.decode());
}
#accept(text2) {
if (text2.length === 0)
return false;
const bytes2 = utf8ByteLength(text2);
const newlines = countNewlines(text2);
this.#totalBytes += bytes2;
this.#totalNewlines += newlines;
this.#endsWithNewline = text2.endsWith("\n");
if (this.#full)
return true;
this.#chunks.push({ text: text2, bytes: bytes2, newlines });
this.#storedBytes += bytes2;
this.#storedNewlines += newlines;
if (this.#limits.retain === "head") {
this.#full = this.#storedBytes > this.#limits.maxBytes || this.#storedNewlines >= this.#limits.maxLines;
return true;
}
while (this.#chunks.length > 1) {
const first = this.#chunks[0];
const bytesAfter = this.#storedBytes - first.bytes;
const newlinesAfter = this.#storedNewlines - first.newlines;
if (bytesAfter <= this.#limits.maxBytes + 1 && newlinesAfter <= this.#limits.maxLines + 1)
break;
this.#chunks.shift();
this.#storedBytes = bytesAfter;
this.#storedNewlines = newlinesAfter;
}
return true;
}
/** Retained, sanitized output and what the limits dropped from the whole stream. */
snapshot() {
const stored = this.#chunks.length === 1 ? this.#chunks[0].text : this.#chunks.map((chunk) => chunk.text).join("");
const kept = boundOutput(stored, this.#limits);
const storedLines = lines(this.#storedNewlines, stored === "" || stored.endsWith("\n"));
const keptLines = storedLines - kept.droppedLines;
if (this.#limits.retain === "tail" || this.#chunks.length > 1) {
const text2 = this.#limits.retain === "tail" ? tailMargin(stored, this.#limits) : stored;
const bytes2 = this.#limits.retain === "tail" ? utf8ByteLength(text2) : this.#storedBytes;
this.#chunks = text2 === "" ? [] : [{ text: text2, bytes: bytes2, newlines: countNewlines(text2) }];
this.#storedBytes = bytes2;
this.#storedNewlines = this.#chunks[0]?.newlines ?? 0;
}
return {
text: sanitizeOutput(kept.text),
droppedBytes: this.#totalBytes - kept.bytes,
droppedLines: lines(this.#totalNewlines, this.#endsWithNewline) - keptLines
};
}
};
function tailMargin(text2, limits) {
const bytes2 = encoder.encode(text2);
const byteStart = bytes2.length > limits.maxBytes ? characterEnd(bytes2, bytes2.length - limits.maxBytes - 1) : 0;
let lineStart = 0;
let newlines = 0;
for (let index = bytes2.lastIndexOf(NEWLINE); index !== -1; index = bytes2.lastIndexOf(NEWLINE, index - 1)) {
if (++newlines > limits.maxLines) {
lineStart = index;
break;
}
if (index === 0)
break;
}
const start = Math.max(byteStart, lineStart);
return start === 0 ? text2 : decoder.decode(bytes2.subarray(start));
}
function lines(newlines, terminated) {
return newlines + (terminated ? 0 : 1);
}
var runtimeBuffer = globalThis.Buffer;
var nonAsciiPattern = /[^\x00-\x7f]/;
function utf8ByteLength(content) {
if (runtimeBuffer)
return runtimeBuffer.byteLength(content, "utf8");
const firstNonAscii = content.search(nonAsciiPattern);
if (firstNonAscii === -1)
return content.length;
let bytes2 = firstNonAscii;
for (let i = firstNonAscii; i < content.length; i++) {
const code = content.charCodeAt(i);
if (code <= 127)
bytes2 += 1;
else if (code <= 2047)
bytes2 += 2;
else if (code >= 55296 && code <= 56319 && i + 1 < content.length) {
const next = content.charCodeAt(i + 1);
if (next >= 56320 && next <= 57343) {
bytes2 += 4;
i++;
} else
bytes2 += 3;
} else
bytes2 += 3;
}
return bytes2;
}
function countNewlines(text2) {
let count = 0;
for (let index = text2.indexOf("\n"); index !== -1; index = text2.indexOf("\n", index + 1))
count++;
return count;
}
var PROGRESS_BYTES_PER_SECOND = 100 * 1024;
var SYSTEM_CLOCK = {
now: () => Date.now(),
setTimer: (callback, delayMs) => {
const timer = setTimeout(callback, delayMs);
return () => clearTimeout(timer);
}
};
var Progress = class {
#write;
#onError;
#minIntervalMs;
#clock;
#waiters = [];
#timer;
#inFlight;
#nextAt = 0;
#dirty = false;
#stopped = false;
constructor(write, onError, minIntervalMs, clock = SYSTEM_CLOCK) {
this.#write = write;
this.#onError = onError;
this.#minIntervalMs = minIntervalMs;
this.#clock = clock;
}
/** Schedule a commit. */
mark() {
this.#dirty = true;
this.#schedule();
}
/** Schedule a commit; the promise settles with the commit that includes this change. */
markAndWait() {
const waiter = Promise.withResolvers();
this.#waiters.push(waiter);
this.mark();
return waiter.promise;
}
/** Stop committing and wait for the commit in flight; returns the waiters the final commit must settle. */
async stop() {
this.#stopped = true;
this.#timer?.();
this.#timer = void 0;
await this.#inFlight;
return this.#waiters.splice(0);
}
#schedule() {
if (this.#stopped || this.#timer !== void 0 || this.#inFlight !== void 0)
return;
const wait = this.#nextAt - this.#clock.now();
if (wait <= 0)
this.#flush();
else
this.#timer = this.#clock.setTimer(() => {
this.#timer = void 0;
this.#schedule();
}, wait);
}
#flush() {
if (this.#stopped || !this.#dirty)
return;
this.#dirty = false;
const waiters = this.#waiters.splice(0);
const started = this.#clock.now();
this.#inFlight = this.#write().then((bytes2) => {
this.#nextAt = started + Math.max(this.#minIntervalMs, bytes2 * 1e3 / PROGRESS_BYTES_PER_SECOND);
for (const waiter of waiters)
waiter.resolve();
}, (error) => {
this.#nextAt = started + this.#minIntervalMs;
for (const waiter of waiters)
waiter.reject(error);
this.#onError(error);
}).finally(() => {
this.#inFlight = void 0;
if (this.#dirty)
this.#schedule();
});
}
};
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/date.js
var DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
function IsLeapYear(year) {
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
}
function IsDate(value2) {
const matches = DATE.exec(value2);
if (!matches)
return false;
const year = +matches[1];
const month = +matches[2];
const day = +matches[3];
return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 && IsLeapYear(year) ? 29 : DAYS[month]);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/time.js
var TIME = /^(\d\d):(\d\d):(\d\d)(?:\.\d+)?(?:([Zz])|([+-])(\d\d):(\d\d))?$/;
function IsTime(value2, strictTimeZone = true) {
const matches = TIME.exec(value2);
if (!matches)
return false;
if (strictTimeZone && !matches[4] && !matches[5])
return false;
const hr = +matches[1];
const min = +matches[2];
const sec = +matches[3];
if (hr > 23 || min > 59 || sec > 60)
return false;
if (matches[5]) {
const tzH2 = +matches[6];
const tzM2 = +matches[7];
if (tzH2 > 23 || tzM2 > 59)
return false;
}
if (sec < 60)
return true;
const tzSign = matches[5] === "-" ? -1 : 1;
const tzH = +(matches[6] || 0);
const tzM = +(matches[7] || 0);
const totalUtcMin = hr * 60 + min - tzSign * (tzH * 60 + tzM);
return (totalUtcMin % 1440 + 1440) % 1440 === 1439;
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/date_time.js
function IsDateTime(value2) {
const dateTime = value2.split(/T/i);
return dateTime.length === 2 && IsDate(dateTime[0]) && IsTime(dateTime[1]);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/duration.js
var Duration = /^P((\d+Y(\d+M(\d+D)?)?|\d+M(\d+D)?|\d+D)(T(\d+H(\d+M(\d+S)?)?|\d+M(\d+S)?|\d+S))?|T(\d+H(\d+M(\d+S)?)?|\d+M(\d+S)?|\d+S)|\d+W)$/;
function IsDuration(value2) {
return Duration.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/email.js
var Email = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[^"\\]|\\[\x20-\x7e])*")@(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*|\[(?:IPv6:[a-f0-9:]+|(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?:\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})\])$/i;
function IsEmail(value2) {
return Email.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idna/pattern/pattern.js
var RE_RULE_HYPHEN_PLACEMENT = /^(?!-).*(?<!-)$/;
var RE_RULE_NOT_RESERVED_ACE = /^(?!..--)/;
var RE_ASCII_LDH = /^[a-zA-Z0-9-]*$/;
var RE_NON_ASCII = /[^\p{ASCII}]/u;
var RE_ASCII_DIGIT = /[0-9]/;
var RE_ARABIC_INDIC_DIGIT = /[\u{0660}-\u{0669}]/u;
var RE_EXT_ARABIC_INDIC_DIGIT = /[\u{06f0}-\u{06f9}]/u;
var RE_COMMON_SEPARATOR = /[\u{002e}\u{002c}\u{003a}\u{002f}]/u;
var RE_EUROPEAN_SEPARATOR = /[\u{002d}\u{002b}]/u;
var RE_MARK_NONSPACING = /\p{Mn}/u;
var RE_MARK_SPACING_COMBINING = /\p{Mc}/u;
var RE_COMBINING_MARK = /[\p{Mn}\p{Mc}\p{Me}]/u;
var RE_LETTER = /\p{L}/u;
var RE_NUMBER_DECIMAL = /\p{Nd}/u;
var RE_SCRIPT_GREEK = /\p{Script=Greek}/u;
var RE_SCRIPT_HEBREW = /\p{Script=Hebrew}/u;
var RE_SCRIPT_JAPANESE = /[\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Han}]/u;
var RE_SCRIPT_ARABIC_LETTER = /[\p{Script=Arabic}\p{Script=Syriac}\p{Script=Thaana}\p{Script=Mandaic}]/u;
var RE_VIRAMA = /[\u{094d}\u{09cd}\u{0a4d}\u{0acd}\u{0b4d}\u{0bcd}\u{0c4d}\u{0ccd}\u{0d3b}\u{0d3c}\u{0d4d}\u{0dca}\u{1b44}\u{1baa}\u{1bab}\u{a9c0}\u{11046}\u{1107f}\u{110b9}\u{11133}\u{11134}\u{111c0}\u{11235}\u{1134d}\u{11442}\u{114c2}\u{115bf}\u{1163f}\u{116b6}\u{11c3f}\u{11d44}\u{11d45}]/u;
var RE_RFC5892_DISALLOWED = /[\u{0640}\u{07fa}\u{302e}\u{302f}\u{3031}\u{3032}\u{3033}\u{3034}\u{3035}\u{303b}]/u;
var RE_CONTEXTO_EXCEPTIONS = /[\u{00b7}\u{0375}\u{05f3}\u{05f4}\u{200c}\u{200d}\u{30fb}]/u;
var RE_PVALID_EXCEPTIONS = /[\u{00df}\u{03c2}\u{06fd}\u{06fe}\u{0f0b}\u{3007}]/u;
var RE_EUROPEAN_NUMBER = new RegExp([RE_ASCII_DIGIT, RE_EXT_ARABIC_INDIC_DIGIT].map((regexp) => regexp.source).join("|"), "u");
var RE_PERMITTED_CATEGORY = new RegExp([
RE_LETTER,
RE_EUROPEAN_SEPARATOR,
RE_COMMON_SEPARATOR,
RE_NUMBER_DECIMAL,
RE_MARK_NONSPACING,
RE_MARK_SPACING_COMBINING,
RE_CONTEXTO_EXCEPTIONS,
RE_PVALID_EXCEPTIONS
].map((regexp) => regexp.source).join("|"), "u");
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idna/label/ascii.js
function IsAsciiLabel(value2) {
return RE_RULE_HYPHEN_PLACEMENT.test(value2) && RE_RULE_NOT_RESERVED_ACE.test(value2) && RE_ASCII_LDH.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idna/format/puny.js
var PUNYCODE_BASE = 36;
var PUNYCODE_TMIN = 1;
var PUNYCODE_TMAX = 26;
var PUNYCODE_SKEW = 38;
var PUNYCODE_DAMP = 700;
var PUNYCODE_INITIAL_BIAS = 72;
var PUNYCODE_INITIAL_N = 128;
function ThrowDontCare() {
throw null;
}
function IsAcePrefixed(value2) {
return value2.toLowerCase().startsWith("xn--");
}
function Adapt(delta, numPoints, firstTime) {
delta = firstTime ? Math.floor(delta / PUNYCODE_DAMP) : delta >> 1;
delta += Math.floor(delta / numPoints);
let k = 0;
while (delta > (PUNYCODE_BASE - PUNYCODE_TMIN) * PUNYCODE_TMAX >> 1) {
delta = Math.floor(delta / (PUNYCODE_BASE - PUNYCODE_TMIN));
k += PUNYCODE_BASE;
}
return k + Math.floor((PUNYCODE_BASE - PUNYCODE_TMIN + 1) * delta / (delta + PUNYCODE_SKEW));
}
function Decode(value2) {
const output = [];
let n = PUNYCODE_INITIAL_N;
let i = 0;
let bias = PUNYCODE_INITIAL_BIAS;
const delimIdx = value2.lastIndexOf("-");
if (delimIdx > 0) {
for (let j = 0; j < delimIdx; j++) {
const cp = value2.charCodeAt(j);
if (cp >= 128)
ThrowDontCare();
output.push(cp);
}
}
let inIdx = delimIdx < 0 ? 0 : delimIdx + 1;
while (inIdx < value2.length) {
const oldi = i;
let w = 1;
let k = PUNYCODE_BASE;
while (true) {
if (inIdx >= value2.length)
ThrowDontCare();
const ch = value2.charCodeAt(inIdx++);
let digit;
if (ch >= 97 && ch <= 122)
digit = ch - 97;
else if (ch >= 48 && ch <= 57)
digit = ch - 48 + 26;
else
ThrowDontCare();
i += digit * w;
const t = k <= bias ? PUNYCODE_TMIN : k >= bias + PUNYCODE_TMAX ? PUNYCODE_TMAX : k - bias;
if (digit < t)
break;
w *= PUNYCODE_BASE - t;
k += PUNYCODE_BASE;
}
const outLen = output.length + 1;
bias = Adapt(i - oldi, outLen, oldi === 0);
n += Math.floor(i / outLen);
i %= outLen;
output.splice(i, 0, n);
i++;
}
return String.fromCodePoint(...output);
}
function DigitToChar(digit) {
return digit < 26 ? String.fromCharCode(digit + 97) : String.fromCharCode(digit - 26 + 48);
}
var RE_REPLACE_NON_ASCII = new RegExp(RE_NON_ASCII.source, "gu");
function Encode(input) {
const basic = input.replace(RE_REPLACE_NON_ASCII, "");
const basicLength = basic.length;
const result = basicLength > 0 ? [basic, "-"] : [];
const codePoints2 = Array.from(input, (char) => char.codePointAt(0));
let n = PUNYCODE_INITIAL_N;
let delta = 0;
let bias = PUNYCODE_INITIAL_BIAS;
let handledCPCount = basicLength;
while (handledCPCount < codePoints2.length) {
let m = Infinity;
for (const cp of codePoints2) {
if (cp >= n && cp < m)
m = cp;
}
delta += (m - n) * (handledCPCount + 1);
n = m;
for (const cp of codePoints2) {
if (cp < n)
delta++;
if (cp === n) {
let q = delta;
for (let k = PUNYCODE_BASE; ; k += PUNYCODE_BASE) {
const t = k <= bias ? PUNYCODE_TMIN : k >= bias + PUNYCODE_TMAX ? PUNYCODE_TMAX : k - bias;
if (q < t)
break;
const digit = t + (q - t) % (PUNYCODE_BASE - t);
result.push(DigitToChar(digit));
q = Math.floor((q - t) / (PUNYCODE_BASE - t));
}
result.push(DigitToChar(q));
bias = Adapt(delta, handledCPCount + 1, handledCPCount === basicLength);
delta = 0;
handledCPCount++;
}
}
delta++;
n++;
}
return result.join("");
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idna/format/bidi.js
var RE_RTL_ALLOWED = /^(?:R|AL|AN|EN|ES|CS|ET|ON|BN|NSM)$/;
var RE_LTR_ALLOWED = /^(?:L|EN|ES|CS|ET|ON|BN|NSM)$/;
var RE_RTL_CLASSES = /^(?:R|AL|AN)$/;
function HasBidiChars(value2) {
if (IsAcePrefixed(value2)) {
try {
return HasRightToLeftCharacters(Decode(value2.slice(4).toLowerCase()));
} catch {
return false;
}
}
return HasRightToLeftCharacters(value2);
}
function GetBidiClass(codePoint) {
const char = String.fromCodePoint(codePoint);
return RE_EUROPEAN_NUMBER.test(char) ? "EN" : RE_ARABIC_INDIC_DIGIT.test(char) ? "AN" : (
// Pattern.RE_EUROPEAN_SEPARATOR.test(char) ? 'ES' : // (no-spec-coverage)
// Pattern.RE_COMMON_SEPARATOR.test(char) ? 'CS' : // (no-spec-coverage)
RE_MARK_NONSPACING.test(char) ? "NSM" : RE_SCRIPT_HEBREW.test(char) ? "R" : RE_SCRIPT_ARABIC_LETTER.test(char) ? "AL" : RE_LETTER.test(char) ? "L" : "ON"
);
}
function HasRightToLeftCharacters(value2) {
for (const ch of value2)
if (RE_RTL_CLASSES.test(GetBidiClass(ch.codePointAt(0))))
return true;
return false;
}
function SatisfiesBidiRule(value2) {
let isRtl = false;
let allowed = RE_LTR_ALLOWED;
let sawEN = false;
let sawAN = false;
let isFirst = true;
for (const ch of value2) {
const bidiClass = GetBidiClass(ch.codePointAt(0));
if (isFirst) {
if (bidiClass !== "L" && bidiClass !== "R" && bidiClass !== "AL")
return false;
isRtl = bidiClass === "R" || bidiClass === "AL";
allowed = isRtl ? RE_RTL_ALLOWED : RE_LTR_ALLOWED;
isFirst = false;
}
if (!allowed.test(bidiClass))
return false;
if (bidiClass === "EN")
sawEN = true;
else if (bidiClass === "AN")
sawAN = true;
}
if (isRtl && sawEN && sawAN)
return false;
return true;
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idna/label/unicode.js
function ExceedsMaxALabelLength(value2) {
return RE_NON_ASCII.test(value2) && Encode(value2).length + 4 > 63;
}
function HasInvalidHyphens(chars) {
if (chars[0] === "-" || chars[chars.length - 1] === "-")
return true;
return chars.slice(2).join("").startsWith("--");
}
function IsUnicodeLabel(value2) {
if (ExceedsMaxALabelLength(value2))
return false;
if (HasRightToLeftCharacters(value2) && !SatisfiesBidiRule(value2))
return false;
const chars = [...value2];
const codePoints2 = chars.map((c) => c.codePointAt(0));
const length = codePoints2.length;
if (HasInvalidHyphens(chars))
return false;
if (RE_COMBINING_MARK.test(chars[0]))
return false;
let hasJapanese = false;
for (let i = 0; i < length; i++) {
const codePoint = codePoints2[i];
const char = chars[i];
if (RE_RFC5892_DISALLOWED.test(char))
return false;
if (!RE_PERMITTED_CATEGORY.test(char))
return false;
if (RE_SCRIPT_JAPANESE.test(char))
hasJapanese = true;
const prev = codePoints2[i - 1], next = codePoints2[i + 1];
switch (codePoint) {
case 183:
if (prev !== 108 || next !== 108)
return false;
break;
// MIDDLE DOT (Catalan)
case 885:
if (!next || !RE_SCRIPT_GREEK.test(chars[i + 1]))
return false;
break;
// Greek KERAIA
case 1523:
case 1524:
if (!prev || !RE_SCRIPT_HEBREW.test(chars[i - 1]))
return false;
break;
// Hebrew GERESH
case 8204:
if (!prev || prev < 128 && !RE_VIRAMA.test(chars[i - 1]))
return false;
break;
case 8205:
if (!prev || !RE_VIRAMA.test(chars[i - 1]))
return false;
break;
case 12539:
break;
}
}
if (value2.includes("\u30FB") && !hasJapanese)
return false;
return true;
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idna/label/puny.js
function IsPunyLabel(value2) {
if (!IsAcePrefixed(value2))
return false;
try {
const body = value2.slice(4).toLowerCase();
if (body.lastIndexOf("-") === 0)
return false;
const decoded = Decode(body);
if (!RE_NON_ASCII.test(decoded))
return false;
return IsUnicodeLabel(decoded);
} catch {
return false;
}
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idna/hostname.js
function IsValidLabelLength(value2) {
return value2.length > 0 && value2.length <= 63;
}
function IsLabel(value2) {
return IsValidLabelLength(value2) && (IsPunyLabel(value2) || IsAsciiLabel(value2));
}
function IsHostname(value2) {
if (value2.length === 0 || value2.length > 253)
return false;
if (value2.charCodeAt(value2.length - 1) === 46)
return false;
return value2.split(".").every((label) => IsLabel(label));
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idna/idn-hostname.js
function IsValidLabelLength2(value2) {
return value2.length > 0 && value2.length <= 63;
}
function IsLabel2(value2) {
return IsValidLabelLength2(value2) && (IsPunyLabel(value2) || IsUnicodeLabel(value2));
}
function NormalizeHostname(value2) {
return value2.replace(/[\uff01-\uff5e]/g, (char) => String.fromCharCode(char.charCodeAt(0) - 65248)).normalize("NFC").replace(/[\u00ad\u034f\u180b-\u180d\u200b\ufe00-\ufe0f\u{e0100}-\u{e01ef}]/gu, "").replace(/[\u002E\u3002\uFF0E\uFF61]/g, ".");
}
function IsIdnHostname(value2) {
if (value2.length === 0 || value2.includes(" "))
return false;
const normalized = NormalizeHostname(value2);
if (normalized.length > 253)
return false;
const labels = normalized.split(".");
const hasBidiChars = labels.some((label) => HasBidiChars(label));
return labels.every((label) => IsLabel2(label) && (!hasBidiChars || SatisfiesBidiRule(label)));
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/hostname.js
function IsHostname2(value2) {
return IsHostname(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idn_email.js
var IdnEmail = /^(?:[A-Za-z0-9!#$%&'*+/=?^_`{|}~\u{0080}-\u{10FFFF}-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~\u{0080}-\u{10FFFF}-]+)*|"(?:[^"\\]|\\.)*")@[\p{L}\p{N}](?:[\p{L}\p{N}-]{0,62})(?<!-)(?:\.[\p{L}\p{N}](?:[\p{L}\p{N}-]{0,62})(?<!-))*$/iu;
function IsIdnEmail(value2) {
return IdnEmail.test(value2.normalize("NFC"));
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/idn_hostname.js
function IsIdnHostname2(value2) {
return IsIdnHostname(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/ipv4.js
var IPv4 = /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/;
function IsIPv4(value2) {
return IPv4.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/ipv6.js
var IPv6 = /^(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:)?[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)$/i;
function IsIPv6(value2) {
return IPv6.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/iri.js
var IpvFutureMatchMaxLength = 2048;
var IpvFutureMatch = /\[[vV][0-9a-fA-F]+\.[^\]]+\]/;
var InvalidIriChars = /[\x00-\x20<>^`{|}\\]/;
var InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
function NarrowIpvFuture(value2) {
return value2.length < IpvFutureMatchMaxLength ? value2.replace(IpvFutureMatch, "[::1]") : value2;
}
function IsIri(value2) {
if (InvalidIriChars.test(value2))
return false;
if (InvalidPercentEncoding.test(value2))
return false;
return URL.canParse(NarrowIpvFuture(value2));
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/iri_reference.js
var InvalidIriChars2 = /[\x00-\x20\x7F\\]|%(?![0-9a-fA-F]{2})/;
var MalformedScheme = /^[a-zA-Z][a-zA-Z0-9+\-.]*\/\//;
function IsIriReference(value2) {
return !InvalidIriChars2.test(value2) && !MalformedScheme.test(value2) && URL.canParse(value2, "http://example.com");
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/json_pointer.js
var JsonPointer = /^(?:\/(?:[^~/]|~0|~1)*)*$/;
function IsJsonPointer(value2) {
return JsonPointer.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/json_pointer_uri_fragment.js
var JsonPointerUriFragment = /^#(?:\/(?:[a-z0-9_\-.!$&'()*+,;:=@]|%[0-9a-f]{2}|~0|~1)*)*$/i;
function IsJsonPointerUriFragment(value2) {
return JsonPointerUriFragment.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/regex.js
function IsRegex(value2) {
try {
new RegExp(value2, "u");
return true;
} catch {
return false;
}
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/relative_json_pointer.js
var RelativeJsonPointer = /^(?:0|[1-9][0-9]*)(?:#|(?:\/(?:[^~/]|~0|~1)*)*)$/;
function IsRelativeJsonPointer(value2) {
return RelativeJsonPointer.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/uri.js
var Uri = /^[a-z][a-z0-9+\-.]*:(?:\/\/(?:(?:[-a-z0-9._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:[\da-f]{1,4}:){6}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|::(?:[\da-f]{1,4}:){5}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:[\da-f]{1,4})?::(?:[\da-f]{1,4}:){4}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,1}[\da-f]{1,4})?::(?:[\da-f]{1,4}:){3}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,2}[\da-f]{1,4})?::(?:[\da-f]{1,4}:){2}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,3}[\da-f]{1,4})?::[\da-f]{1,4}:(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,4}[\da-f]{1,4})?::(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,5}[\da-f]{1,4})?::[\da-f]{1,4}|(?:(?:[\da-f]{1,4}:){0,6}[\da-f]{1,4})?::)|v[0-9a-f]+\.[-a-z0-9._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)|(?:[-a-z0-9._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?(?:\?(?:[-a-z0-9._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[-a-z0-9._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
function IsUri(value2) {
return Uri.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/uri_reference.js
var UriReference = /^(?:[a-z][a-z0-9+\-.]*:(?:\/\/(?:(?:[-a-z0-9._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:[\da-f]{1,4}:){6}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|::(?:[\da-f]{1,4}:){5}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:[\da-f]{1,4})?::(?:[\da-f]{1,4}:){4}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,1}[\da-f]{1,4})?::(?:[\da-f]{1,4}:){3}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,2}[\da-f]{1,4})?::(?:[\da-f]{1,4}:){2}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,3}[\da-f]{1,4})?::[\da-f]{1,4}:(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,4}[\da-f]{1,4})?::(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,5}[\da-f]{1,4})?::[\da-f]{1,4}|(?:(?:[\da-f]{1,4}:){0,6}[\da-f]{1,4})?::)|v[0-9a-f]+\.[-a-z0-9._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)|(?:[-a-z0-9._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:\/\/(?:(?:[-a-z0-9._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:[\da-f]{1,4}:){6}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|::(?:[\da-f]{1,4}:){5}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:[\da-f]{1,4})?::(?:[\da-f]{1,4}:){4}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,1}[\da-f]{1,4})?::(?:[\da-f]{1,4}:){3}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,2}[\da-f]{1,4})?::(?:[\da-f]{1,4}:){2}(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,3}[\da-f]{1,4})?::[\da-f]{1,4}:(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,4}[\da-f]{1,4})?::(?:[\da-f]{1,4}:[\da-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d))|(?:(?:[\da-f]{1,4}:){0,5}[\da-f]{1,4})?::[\da-f]{1,4}|(?:(?:[\da-f]{1,4}:){0,6}[\da-f]{1,4})?::)|v[0-9a-f]+\.[-a-z0-9._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)|(?:[-a-z0-9._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[-a-z0-9._~!$&'()*+,;=@]|%[0-9a-f]{2})+(?:\/(?:[-a-z0-9._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?)(?:\?(?:[-a-z0-9._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[-a-z0-9._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
function IsUriReference(value2) {
return UriReference.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/uri_template.js
var UriTemplate = /^(?:(?:[^\x00-\x20"<>%\\^`{|}\x7f]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?:\.(?:[a-z0-9_]|%[0-9a-f]{2})+)*(?::[1-9]\d{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?:\.(?:[a-z0-9_]|%[0-9a-f]{2})+)*(?::[1-9]\d{0,3}|\*)?)*\})*$/i;
function IsUriTemplate(value2) {
return UriTemplate.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/url.js
function IsUrl(value2) {
return URL.canParse(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/typebox/uuid.js
var Uuid = /^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i;
function IsUuid(value2) {
return Uuid.test(value2);
}
// node_modules/@earendil-works/pi-schema/dist/formats/index.js
var formats = Object.freeze({
date: IsDate,
"date-time": IsDateTime,
duration: IsDuration,
email: IsEmail,
hostname: IsHostname2,
"idn-email": IsIdnEmail,
"idn-hostname": IsIdnHostname2,
ipv4: IsIPv4,
ipv6: IsIPv6,
iri: IsIri,
"iri-reference": IsIriReference,
"json-pointer": IsJsonPointer,
"json-pointer-uri-fragment": IsJsonPointerUriFragment,
regex: IsRegex,
"relative-json-pointer": IsRelativeJsonPointer,
time: IsTime,
uri: IsUri,
"uri-reference": IsUriReference,
"uri-template": IsUriTemplate,
url: IsUrl,
uuid: IsUuid
});
// node_modules/@earendil-works/pi-ai/dist/utils/validation.js
var validatorCache = /* @__PURE__ */ new WeakMap();
function getValidator(schema) {
const cached = validatorCache.get(schema);
if (cached) {
return cached;
}
const validator = compile(schema, { formats, coerce: true, unresolvedRefs: "reject" });
validatorCache.set(schema, validator);
return validator;
}
function formatValidationPath(pointer2) {
if (pointer2 === "")
return "root";
return pointer2.slice(1).split("/").map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~")).join(".");
}
function validateToolArguments(tool, toolCall) {
if (toolCall.argumentsError) {
throw new Error(`Invalid arguments for tool "${toolCall.name}": ${toolCall.argumentsError}`);
}
const result = getValidator(tool.parameters).parse(structuredClone(toolCall.arguments));
if (result.ok) {
return result.value;
}
const errors = result.errors.map((error) => ` - ${formatValidationPath(error.path)}: ${error.message}`).join("\n");
const errorMessage3 = `Validation failed for tool "${toolCall.name}":
${errors}
Received arguments:
${JSON.stringify(toolCall.arguments, null, 2)}`;
throw new Error(errorMessage3);
}
// node_modules/@earendil-works/pi-durable/dist/truncate.js
var DEFAULT_MAX_LINES = 2e3;
var DEFAULT_MAX_BYTES = 50 * 1024;
function splitLinesForCounting(content) {
if (content.length === 0)
return [];
const lines2 = content.split("\n");
if (content.endsWith("\n"))
lines2.pop();
return lines2;
}
function formatSize(bytes2) {
if (bytes2 < 1024) {
return `${bytes2}B`;
} else if (bytes2 < 1024 * 1024) {
return `${(bytes2 / 1024).toFixed(1)}KB`;
} else {
return `${(bytes2 / (1024 * 1024)).toFixed(1)}MB`;
}
}
function truncateHeadOf(prefix, totals, options = {}) {
const maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
const totalBytes = totals.bytes;
const lines2 = splitLinesForCounting(prefix);
const totalLines = totals.lines;
if (totalLines <= maxLines && totalBytes <= maxBytes) {
return {
content: prefix,
truncated: false,
truncatedBy: null,
totalLines,
totalBytes,
outputLines: totalLines,
outputBytes: totalBytes,
lastLinePartial: false,
firstLineExceedsLimit: false,
maxLines,
maxBytes
};
}
const firstLineBytes = utf8ByteLength(lines2[0]);
if (firstLineBytes > maxBytes) {
return {
content: "",
truncated: true,
truncatedBy: "bytes",
totalLines,
totalBytes,
outputLines: 0,
outputBytes: 0,
lastLinePartial: false,
firstLineExceedsLimit: true,
maxLines,
maxBytes
};
}
const outputLinesArr = [];
let outputBytesCount = 0;
let truncatedBy = "lines";
for (let i = 0; i < lines2.length && i < maxLines; i++) {
const line = lines2[i];
const lineBytes = utf8ByteLength(line) + (i > 0 ? 1 : 0);
if (outputBytesCount + lineBytes > maxBytes) {
truncatedBy = "bytes";
break;
}
outputLinesArr.push(line);
outputBytesCount += lineBytes;
}
if (truncatedBy !== "bytes")
truncatedBy = outputLinesArr.length < totalLines ? "lines" : "bytes";
const outputContent = outputLinesArr.join("\n");
const finalOutputBytes = utf8ByteLength(outputContent);
return {
content: outputContent,
truncated: true,
truncatedBy,
totalLines,
totalBytes,
outputLines: outputLinesArr.length,
outputBytes: finalOutputBytes,
lastLinePartial: false,
firstLineExceedsLimit: false,
maxLines,
maxBytes
};
}
// node_modules/@earendil-works/pi-durable/dist/harness/usage.js
var UsageDoc = defineDoc({
kind: "pi.usage",
version: 1,
scope: "conversation",
history: "latest",
fork: "initial",
initial: () => ({ models: {}, tools: {} }),
checkpointWhen: () => true
});
async function recordUsage(tx, conversationId, bucket, key, usage) {
const totals = (await tx.doc(UsageDoc, conversationId))[bucket];
const total = Object.hasOwn(totals, key) ? totals[key] : void 0;
if (total === void 0)
totals[key] = copyJson(usage, { omitUndefinedProperties: true });
else
addUsage(total, usage);
}
function addUsage(total, usage) {
total.input += usage.input;
total.output += usage.output;
total.cacheRead += usage.cacheRead;
total.cacheWrite += usage.cacheWrite;
total.totalTokens += usage.totalTokens;
if (usage.cacheWrite1h !== void 0)
total.cacheWrite1h = (total.cacheWrite1h ?? 0) + usage.cacheWrite1h;
if (usage.reasoning !== void 0)
total.reasoning = (total.reasoning ?? 0) + usage.reasoning;
total.cost.input += usage.cost.input;
total.cost.output += usage.cost.output;
total.cost.cacheRead += usage.cost.cacheRead;
total.cost.cacheWrite += usage.cost.cacheWrite;
total.cost.total += usage.cost.total;
}
function addUsageState(sum, state2) {
for (const bucket of ["models", "tools"]) {
for (const [key, usage] of Object.entries(state2[bucket])) {
const total = Object.hasOwn(sum[bucket], key) ? sum[bucket][key] : void 0;
if (total !== void 0)
addUsage(total, usage);
else
Object.defineProperty(sum[bucket], key, {
value: structuredClone(usage),
enumerable: true,
writable: true
});
}
}
}
// node_modules/@earendil-works/pi-durable/dist/harness/tool.js
var MADE_NESTED_CALLS = "pi.tool.madeNestedCalls";
var NestedCallDoc = defineDocFamily({
kind: "pi.tool.nested-call",
version: 1,
scope: "task",
family: true,
initial: () => ({}),
// The document retires with its task.
checkpointWhen: () => false
});
var ToolTask = defineTask({
name: "pi.tool",
version: 3,
initial: () => ({ phase: "call" }),
// Version 1 had only model-issued calls, without `kind`; version 3 added `unoffered`, absent in version 2 inputs.
migrate: (input, checkpoint, fromVersion) => ({
input: fromVersion === 1 ? { kind: "model", ...input } : input,
checkpoint
}),
phases: {
call: async (task, runtime, context) => {
const call = await readCall(runtime, task.input, context);
if (cutOffTooOften(task, runtime))
return endCutOff(runtime, task, call, context);
const tool = isUnoffered(task.input) ? void 0 : await resolveTool(runtime, task.input, call.name, context);
if (tool === void 0) {
const error = harnessError("tool_unavailable", `Tool ${call.name} is not available`);
return reject(runtime, task.input, call, void 0, error, context);
}
const prepared = prepare(tool, call.arguments);
const checked = "error" in prepared ? prepared : validate(tool, call, prepared.args);
if ("error" in checked)
return reject(runtime, task.input, call, tool, invalid(checked.error), context);
let args = checked.args;
let block;
await runtime.hooks.each("beforeTool", async (hook) => {
if (block !== void 0)
return;
try {
const decision = await hook({ ...call, arguments: args }, runtime, context);
if (decision?.block !== void 0)
block = decision.block;
else if (decision?.arguments !== void 0)
args = decision.arguments;
} catch (error) {
if (runtime.signal.aborted)
throw error;
block = errorMessage2(error);
}
});
if (block !== void 0) {
const blocked = harnessError("blocked", `Tool call blocked: ${block}`);
return reject(runtime, task.input, call, tool, blocked, context);
}
const validated = validate(tool, call, args);
if ("error" in validated)
return reject(runtime, task.input, call, tool, invalid(validated.error), context);
const final = copyJson(validated.args, { omitUndefinedProperties: true });
await runtime.commit(async (tx) => {
const slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);
if (slot !== void 0)
slot.status = "running";
if (slot !== void 0 && "parentTaskId" in slot)
slot.arguments = final;
return void 0;
}, context, PROGRESS_COMMIT);
await runtime.commit(() => {
const intent = { phase: "execute", arguments: final, replay: tool.replay ?? "unsafe" };
return { status: "running", checkpoint: intent };
}, context);
await run(runtime, task.input, call, tool, final, context);
},
/** Recovery after intent: rerun only when the stored and the current policy both say `safe`. */
execute: async (task, runtime, context) => {
const { arguments: args, replay } = task.state.checkpoint;
const call = await readCall(runtime, task.input, context);
if (cutOffTooOften(task, runtime))
return endCutOff(runtime, task, call, context);
const tool = await resolveTool(runtime, task.input, call.name, context);
if (replay === "safe" && tool?.replay === "safe") {
await runtime.commit(async (tx) => {
const slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);
if (slot !== void 0) {
clearProgress(slot);
slot.status = "running";
if ("parentTaskId" in slot)
slot.arguments = args;
}
return void 0;
}, context);
return run(runtime, task.input, call, tool, args, context);
}
const message = `Tool ${call.name} was interrupted and may have partially run`;
const ending = { status: "failed", message };
await settleFromSlot(runtime, task.input, call, { tool }, ending, "interrupted", message, context);
}
},
abort: async (task, runtime, context) => {
const call = await readCall(runtime, task.input, context);
const [code, message] = isUnoffered(task.input) ? ["tool_unavailable", `Tool ${call.name} is not available`] : task.abortReason !== "restart" ? ["aborted", `Tool ${call.name} was aborted`] : task.state.checkpoint.phase === "execute" ? ["interrupted", `Tool ${call.name} was interrupted by a restart and may have partially run`] : ["abandoned", `Tool ${call.name} was not started: its caller ended with a restart`];
const hooks = (task.restarts ?? 0) < runtime.settings.restartLimit - 1 ? { tool: await toolForLimits(runtime, task.input, call.name, context) } : void 0;
await settleFromSlot(runtime, task.input, call, hooks, { status: "aborted" }, code, message, context);
}
});
async function endCutOff(runtime, task, call, context) {
const message = `Tool ${call.name} was interrupted ${cutOffCount(task)}; it is not run again`;
const ending = { status: "failed", message, reason: "restart_limit" };
const hooks = salvageable(task, runtime) ? { tool: await toolForLimits(runtime, task.input, call.name, context) } : void 0;
await settleFromSlot(runtime, task.input, call, hooks, ending, "restart_limit", message, context);
}
async function reject(runtime, input, call, tool, result, context) {
const settled = await afterHarnessResult(runtime, input, call, tool, result, void 0, context);
await settle2(runtime, input, call, COMPLETED, settled, context);
}
async function settleFromSlot(runtime, input, call, hooks, ending, code, message, context) {
const live = await runtime.snapshot(LiveDoc, runtime.conversationId, context);
const { result, truncation } = fromSlot(live === void 0 ? void 0 : toolSlot(live, runtime.taskId), code, message);
const settled = hooks !== void 0 ? await afterHarnessResult(runtime, input, call, hooks.tool, result, truncation, context) : truncation === void 0 ? result : { ...result, diagnostics: [...result.diagnostics ?? [], truncation] };
await settle2(runtime, input, call, ending, settled, context);
}
async function toolForLimits(runtime, input, name, context) {
if (isUnoffered(input))
return void 0;
return resolveTool(runtime, input, name, context).catch(() => void 0);
}
function isUnoffered(input) {
return input.kind === "model" && input.unoffered === true;
}
async function resolveTool(runtime, input, name, context) {
const agent = await runtime.agent(context);
return (input.kind === "model" ? agent.tools : agent.callable).find((tool) => tool.name === name);
}
function outputLimits(tool) {
return {
maxBytes: tool?.outputLimits?.maxBytes ?? DEFAULT_MAX_BYTES,
maxLines: tool?.outputLimits?.maxLines ?? DEFAULT_MAX_LINES,
retain: tool?.outputLimits?.retain ?? "head"
};
}
async function readCall(runtime, input, context) {
if (input.kind === "nested") {
context.telemetry.setAttributes({
"tool.name": input.call.name,
"tool.call_id": input.call.id
});
return { ...input.call, parent: { taskId: input.parent, callId: input.parentCallId } };
}
const entry2 = await runtime.entry(AssistantEntry, input.assistant, context);
const message = entry2?.model?.[0];
const call = message?.role === "assistant" ? message.content.find((content) => content.type === "toolCall" && content.id === input.callId) : void 0;
if (call === void 0)
throw new Error(`Entry ${input.assistant} has no tool call ${input.callId}`);
context.telemetry.setAttributes({
"tool.name": call.name,
"tool.call_id": call.id
});
return call;
}
function prepare(tool, args) {
if (tool.prepareArguments === void 0)
return { args };
try {
return { args: tool.prepareArguments(args) };
} catch (error) {
return { error: errorMessage2(error) };
}
}
function validate(tool, call, args) {
try {
return { args: validateToolArguments(tool, { ...call, arguments: args }) };
} catch (error) {
return { error: errorMessage2(error) };
}
}
function invalid(message) {
return harnessError("invalid_arguments", message);
}
async function run(runtime, input, call, tool, args, context) {
const limits = outputLimits(tool);
const reported = { output: new OutputBuffer(limits), limits, diagnostics: [], details: void 0 };
const streams = input.kind === "model" || input.progress !== false;
const progress = publishProgress(runtime, reported, streams, context);
const admissions = [];
const resumes = tool.replay === "safe";
let sequence2 = 0;
let madeNestedMemo;
let ended = false;
const assertLive = () => {
if (ended)
throw new Error(`Tool call ${call.id} has settled`);
};
let env;
const api = {
taskId: runtime.taskId,
conversationId: runtime.conversationId,
callId: call.id,
registry: runtime.registry,
agent: runtime.agent,
get models() {
return runtime.models;
},
get env() {
return env;
},
now: () => runtime.now(),
output: (chunk, skipped) => {
assertLive();
if (reported.output.push(chunk, skipped))
progress.mark();
},
outputWindow: limits.retain === "tail" ? {
maxBytes: limits.maxBytes,
maxLines: limits.maxLines,
minIntervalMs: runtime.settings.progress.outputIntervalMs,
bytesPerSecond: PROGRESS_BYTES_PER_SECOND
} : void 0,
retainedOutput: () => {
assertLive();
const retained = reported.output.snapshot();
return { text: retained.text, truncated: retained.droppedBytes > 0 };
},
diagnostic: (diagnostic) => {
assertLive();
reported.diagnostics.push(copyJson(diagnostic, { omitUndefinedProperties: true }));
progress.mark();
},
details: async (value2, detailsContext) => {
assertLive();
detailsContext.abortSignal?.throwIfAborted();
reported.details = copyJson(value2, { omitUndefinedProperties: true });
const committed = progress.markAndWait();
committed.catch(() => {
});
return awaitWithContext(committed, detailsContext);
},
commit: async (change, commitContext, options) => {
let result2;
await runtime.commit(async (tx) => {
result2 = await change(tx);
return void 0;
}, commitContext, options);
return result2;
},
memo: runtime.memo,
createTask: async (task, input2, options, taskContext) => {
const child = options.ownership.kind === "task" && !resumes ? { abandonOnRestart: true, ...options } : options;
let id;
await runtime.commit(async (tx) => {
id = await tx.createTask(task, input2, child);
return void 0;
}, taskContext);
return id;
},
getTask: runtime.getTask,
waitForTask: runtime.waitForTask,
conversation: runtime.conversation,
snapshot: runtime.snapshot,
snapshotAsOf: runtime.snapshotAsOf,
watchDoc: runtime.watchDoc,
executeTool: async (name, toolArgs, callContext, options = {}) => {
assertLive();
const key = options.key ?? String(++sequence2);
if (options.key !== void 0)
checkKey(options.key);
madeNestedMemo ??= runtime.memo(MADE_NESTED_CALLS, true, callContext).catch((error) => {
madeNestedMemo = void 0;
throw error;
});
const admission = madeNestedMemo.then(() => startNestedCall(runtime, call.id, name, toolArgs, { key, progress: options.progress, abandonOnRestart: !resumes }, callContext));
admissions.push(admission);
const id = await admission;
const settled = await runtime.waitForTask(id, callContext);
const stored = (await runtime.snapshot(NestedCallDoc, runtime.taskId, key, callContext))?.result;
return stored === void 0 ? fallbackResult(id, name, settled.state.outcome) : copyJson(stored);
}
};
let result;
let ending = COMPLETED;
let durationMs;
try {
env = await runtime.env(context);
const startedAt = performance.now();
try {
result = await tool.execute(args, api, context);
} finally {
durationMs = Math.round(performance.now() - startedAt);
}
} catch (error) {
if (runtime.signal.aborted) {
ended = true;
for (const waiter of await progress.stop())
waiter.reject(error);
throw error;
}
result = { isError: true, diagnostics: [toolDiagnostic("tool_error", errorMessage2(error))] };
ending = { status: "failed", message: `Tool ${call.name} threw` };
}
ended = true;
await Promise.allSettled(admissions);
reported.output.end();
const pending = await progress.stop();
try {
const settled = await finalResult(runtime, input, call, tool, result, reported, context);
await settle2(runtime, input, call, ending, settled, context, durationMs);
} catch (error) {
for (const waiter of pending)
waiter.reject(error);
throw error;
}
for (const waiter of pending)
waiter.resolve();
}
function progressClock(runtime) {
let last = 0;
return {
now: () => {
try {
last = runtime.now();
} catch {
}
return last;
},
setTimer: (callback, delayMs) => runtime.setTimer(callback, delayMs)
};
}
function publishProgress(runtime, reported, enabled, context) {
let written = { text: "", details: void 0, diagnostics: 0 };
return new Progress(async () => {
if (!enabled)
return 0;
const snapshot = reported.output.snapshot();
const current = { text: snapshot.text, details: reported.details, diagnostics: reported.diagnostics.length };
const added = reported.diagnostics.slice(written.diagnostics, current.diagnostics);
const detailsChanged = current.details !== written.details;
let bytes2 = 0;
if (snapshot.text !== written.text) {
const shared = snapshot.text.startsWith(written.text) ? written.text.length : overlap(written.text, snapshot.text, 65536);
bytes2 += utf8ByteLength(snapshot.text.slice(shared));
}
if (detailsChanged)
bytes2 += utf8ByteLength(JSON.stringify(current.details ?? null));
if (added.length > 0)
bytes2 += utf8ByteLength(JSON.stringify(added));
await runtime.commit(async (tx) => {
const slot = toolSlot(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);
if (slot === void 0)
return void 0;
if ((slot.output ?? "") !== snapshot.text)
slot.output = snapshot.text;
if (snapshot.droppedBytes > 0)
slot.droppedBytes = snapshot.droppedBytes;
if (snapshot.droppedLines > 0)
slot.droppedLines = snapshot.droppedLines;
if (detailsChanged && current.details !== void 0) {
assignJson(slot, "details", current.details);
}
if (added.length > 0) {
if (slot.diagnostics === void 0)
slot.diagnostics = [];
for (const diagnostic of added)
slot.diagnostics.push(diagnostic);
}
return void 0;
}, context, PROGRESS_COMMIT);
written = current;
return bytes2;
}, (error) => {
if (!runtime.signal.aborted)
runtime.report(error);
}, runtime.settings.progress.outputIntervalMs, progressClock(runtime));
}
async function finalResult(runtime, input, call, tool, result, reported, context) {
const harness2 = [];
const retained = result.output === void 0 ? reported.output.snapshot() : void 0;
const output = retained === void 0 ? result.output : retained.text === "" ? [] : [{ type: "text", text: retained.text }];
let final = {
...result,
output,
details: result.details === void 0 ? reported.details : result.details,
diagnostics: [...reported.diagnostics, ...result.diagnostics ?? []]
};
await runtime.hooks.each("afterTool", async (hook) => {
final = await hook(call, final, runtime, context) ?? final;
});
if (retained !== void 0 && retained.droppedBytes > 0 && final.output === output) {
harness2.push(truncated(retained, reported.limits.retain));
}
const bounded = boundContent(final.output ?? [], reported.limits);
if (bounded.droppedBytes > 0)
harness2.push(truncated(bounded, reported.limits.retain));
const broken = structuredOutputError(tool, final);
if (broken !== void 0) {
const { structuredOutput: _dropped, ...rest } = final;
if (input.kind === "nested") {
final = { ...rest, isError: true };
harness2.push(toolDiagnostic("invalid_structured_output", broken));
} else {
final = rest;
const extension = await runtime.agent(context).then((agent) => toolExtension(agent, tool.name), () => void 0);
runtime.report(new Error(broken), { kind: "extension", ...optionalExtension(extension) });
}
}
if (input.kind === "nested" && tool.structuredOutputSchema === void 0) {
final = { ...final, structuredOutput: outputValue(bounded.content) };
}
if (input.kind === "nested" && tool.structuredOutputSchema !== void 0 && final.isError === true && final.structuredOutput === void 0 && ![...final.diagnostics ?? [], ...harness2].some((diagnostic) => diagnostic.severity === "error")) {
const text2 = bounded.content.flatMap((item) => item.type === "text" ? [item.text] : []).join("\n");
if (text2 !== "")
harness2.push(toolDiagnostic("tool_error", text2));
}
return { ...final, output: bounded.content, diagnostics: [...final.diagnostics ?? [], ...harness2] };
}
async function afterHarnessResult(runtime, input, call, tool, result, truncation, context) {
let final = result;
await runtime.hooks.each("afterTool", async (hook) => {
final = await hook(call, final, runtime, context) ?? final;
});
const harness2 = [];
if (truncation !== void 0 && final.output === result.output)
harness2.push(truncation);
const limits = outputLimits(tool);
const bounded = boundContent(final.output ?? [], limits);
if (bounded.droppedBytes > 0)
harness2.push(truncated(bounded, limits.retain));
const { structuredOutput: _dropped, ...rest } = final;
const value2 = input.kind === "nested" && final.isError !== true && tool?.structuredOutputSchema === void 0 ? { structuredOutput: outputValue(bounded.content) } : {};
return { ...rest, ...value2, output: bounded.content, diagnostics: [...rest.diagnostics ?? [], ...harness2] };
}
var structuredValidators = /* @__PURE__ */ new WeakMap();
function structuredOutputError(tool, result) {
const schema = tool.structuredOutputSchema;
const value2 = result.structuredOutput;
if (schema === void 0) {
return value2 === void 0 ? void 0 : `Tool ${tool.name} returned structuredOutput but declares no structuredOutputSchema`;
}
if (value2 === void 0) {
return result.isError === true ? void 0 : `Tool ${tool.name} returned no structuredOutput`;
}
let validator = structuredValidators.get(schema);
if (validator === void 0) {
validator = compile(schema, { formats, unresolvedRefs: "reject" });
structuredValidators.set(schema, validator);
}
if (validator.check(value2))
return void 0;
const [first] = validator.errors(value2);
const path3 = first?.path.slice(1).split("/").map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~")).join(".") || "root";
return `Tool ${tool.name} returned structuredOutput that does not match its schema: ${path3}: ${first?.message ?? "invalid"}`;
}
async function settle2(runtime, input, call, ending, result, context, durationMs) {
const nestedIds = (await runtime.ownedTasks(context)).filter((record) => record.kind === ToolTask.definition.name && record.input.kind === "nested").map((record) => record.id);
const madeNested = await runtime.memo(MADE_NESTED_CALLS, context) === true;
await Promise.all(nestedIds.map((id) => runtime.abortOwned(id, context)));
await runtime.commit(async (tx) => {
const conversationId = runtime.conversationId;
const live = await tx.doc(LiveDoc, conversationId);
const slot = toolSlot(live, runtime.taskId);
let settled;
if (input.kind === "nested") {
const nested = nestedResult(runtime.taskId, result, durationMs);
if (nested.usage !== void 0)
await recordUsage(tx, conversationId, "tools", call.name, nested.usage);
const state2 = await tx.doc(NestedCallDoc, input.parent, input.key, null);
if (state2.taskId !== runtime.taskId)
throw new Error(`Nested call ${call.id} is not in its caller's index`);
state2.result = nested;
if (slot !== void 0 && "parentTaskId" in slot) {
finishSlot(slot);
slot.summary = summaryOf(nested, result.output ?? []);
}
settled = { kind: "nested" };
} else {
const timing = { timestamp: runtime.now(), durationMs };
const entry2 = await appendToolResult(tx, conversationId, call, result, timing);
if (slot !== void 0 && !("parentTaskId" in slot)) {
finishSlot(slot);
slot.entry = entry2.id;
}
const control = result.control === void 0 || ending.status !== "completed" ? {} : { control: copyJson(result.control, { omitUndefinedProperties: true }) };
settled = { kind: "model", entryId: entry2.id, ...control };
}
if (madeNested)
removeNestedSlots(live, runtime.taskId);
if (ending.status === "aborted")
return { status: "terminal", outcome: { status: "aborted", result: settled } };
if (ending.status === "failed") {
const error = {
message: ending.message,
...ending.reason === void 0 ? {} : { detail: { reason: ending.reason } }
};
return { status: "terminal", outcome: { status: "failed", error, result: settled } };
}
return { status: "terminal", outcome: { status: "completed", result: settled } };
}, context);
}
function nestedResult(taskId, result, durationMs) {
const nested = {
taskId,
structuredOutput: result.structuredOutput,
isError: result.isError ?? false,
details: result.details,
diagnostics: result.diagnostics ?? [],
usage: result.usage,
durationMs
};
return copyJson(nested, {
omitUndefinedProperties: true
});
}
async function startNestedCall(runtime, parentCallId, name, args, options, context) {
const key = options.key;
const call = {
type: "toolCall",
id: `${parentCallId}/${key}`,
name,
arguments: copyJson(args, { omitUndefinedProperties: true })
};
let id;
let replayed = false;
await runtime.commit(async (tx) => {
const state2 = await tx.doc(NestedCallDoc, runtime.taskId, key, null);
const existing = state2.taskId;
if (existing !== void 0) {
const input2 = (await tx.task(existing))?.input;
const same = input2?.kind === "nested" && input2.call.name === name && jsonEqual2(input2.call.arguments, call.arguments);
if (!same)
throw new Error(`Nested call ${call.id} was already made with another tool or other arguments`);
id = existing;
replayed = state2.result !== void 0;
return void 0;
}
const input = {
kind: "nested",
parent: runtime.taskId,
parentCallId,
key,
call,
...options.progress === false ? { progress: false } : {}
};
const created = await tx.createTask(ToolTask, input, {
ownership: { kind: "task", taskId: runtime.taskId },
abandonOnRestart: options.abandonOnRestart
});
state2.taskId = created;
const live = await tx.doc(LiveDoc, runtime.conversationId);
live.nestedTools ??= [];
const slot = {
callId: call.id,
parentCallId,
parentTaskId: runtime.taskId,
name,
taskId: created,
arguments: call.arguments,
status: "pending"
};
live.nestedTools.push(slot);
id = created;
return void 0;
}, context);
if (replayed) {
context.telemetry.addEvent("pi.durable.replay", { "tool.name": name });
}
return id;
}
function outputValue(output) {
if (output.length === 0)
return "";
if (output.length > 1)
return output;
const [only] = output;
return only.type === "text" ? only.text : only;
}
function fallbackResult(taskId, name, outcome) {
const message = outcome.status === "faulted" ? `Tool ${name} failed: ${outcome.error.message}` : outcome.status === "orphaned" ? `Tool ${name} could not resume: ${outcome.reason}` : `Tool ${name} ended without a result`;
const error = harnessError(outcome.status, message);
return { taskId, isError: true, diagnostics: error.diagnostics ?? [] };
}
var COMPLETED = { status: "completed" };
function fromSlot(slot, code, message) {
const droppedBytes = slot?.droppedBytes ?? 0;
const result = {
output: slot?.output === void 0 || slot.output === "" ? [] : [{ type: "text", text: slot.output }],
isError: true,
...slot?.details === void 0 ? {} : { details: slot.details },
diagnostics: [...slot?.diagnostics ?? [], toolDiagnostic(code, message)]
};
if (droppedBytes === 0)
return { result };
return { result, truncation: truncated({ droppedBytes, droppedLines: slot?.droppedLines ?? 0 }) };
}
function harnessError(code, message) {
return { output: [], isError: true, diagnostics: [toolDiagnostic(code, message)] };
}
function toolDiagnostic(code, message) {
return { severity: "error", code, message };
}
function truncated(dropped, retain) {
const kept = retain === void 0 ? "" : ` to its ${retain === "head" ? "beginning" : "end"}`;
return {
severity: "warn",
code: "truncated",
message: `Output truncated${kept}: ${dropped.droppedLines} lines, ${dropped.droppedBytes} bytes dropped`
};
}
var MAX_SUMMARY_ERROR_CHARS = 500;
function summaryOf(result, output) {
const error = result.isError ? ownedSlice2(errorTextOf(result, output), 0, MAX_SUMMARY_ERROR_CHARS) : "";
return {
isError: result.isError,
...result.durationMs === void 0 ? {} : { durationMs: result.durationMs },
...result.usage === void 0 ? {} : { usage: result.usage },
...error === "" ? {} : { error }
};
}
function errorTextOf(result, output) {
const errors = result.diagnostics.filter((diagnostic) => diagnostic.severity === "error");
if (errors.length > 0)
return errors.map((diagnostic) => diagnostic.message).join("\n");
return output.flatMap((item) => item.type === "text" ? [item.text] : []).join("\n");
}
async function appendToolResult(tx, conversationId, call, result, meta) {
const { timestamp, durationMs } = meta;
const diagnostics = [...result.diagnostics ?? []];
const content = [...result.output ?? []];
if (diagnostics.length > 0)
content.push({ type: "text", text: renderDiagnostics(diagnostics) });
const message = {
role: "toolResult",
toolCallId: call.id,
toolName: call.name,
content,
...result.details === void 0 ? {} : { details: result.details },
...result.usage === void 0 ? {} : { usage: result.usage },
isError: result.isError ?? false,
...durationMs === void 0 ? {} : { durationMs },
timestamp
};
if (result.usage !== void 0)
await recordUsage(tx, conversationId, "tools", call.name, result.usage);
return tx.appendEntry(ToolResultEntry, conversationId, { model: [message], data: { diagnostics } });
}
function renderDiagnostics(diagnostics) {
return `<harness>
${diagnostics.map((diagnostic) => `[${diagnostic.severity}] ${diagnostic.message}`).join("\n")}
</harness>`;
}
function boundContent(content, limits) {
const texts = content.filter((item) => item.type === "text");
const bounded = boundOutput(texts.map((item) => item.text).join(""), limits);
if (bounded.droppedBytes === 0)
return { content, droppedBytes: 0, droppedLines: 0 };
const keep = limits.retain === "head" ? texts[0] : texts.at(-1);
const result = [];
for (const item of content) {
if (item.type !== "text")
result.push(item);
else if (item === keep)
result.push({ ...item, text: bounded.text });
}
return { content: result, droppedBytes: bounded.droppedBytes, droppedLines: bounded.droppedLines };
}
function checkKey(key) {
if (key === "" || key.includes("/") || key === "__proto__" || /^[1-9][0-9]*$/.test(key)) {
throw new Error(`Nested call key ${JSON.stringify(key)} must be non-empty, without "/", not "__proto__", and not a positive integer`);
}
}
function jsonEqual2(a, b) {
if (a === b)
return true;
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null)
return false;
if (Array.isArray(a) || Array.isArray(b)) {
return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, i) => jsonEqual2(item, b[i]));
}
const keys = Object.keys(a);
return keys.length === Object.keys(b).length && keys.every((key) => Object.hasOwn(b, key) && jsonEqual2(a[key], b[key]));
}
// node_modules/@earendil-works/pi-durable/dist/harness/generation.js
var DEFAULT_POLL_AFTER_MS = 5e3;
var GenerationTask = defineTask({
name: "pi.generation",
version: 2,
initial: () => ({ phase: "prepare", attempt: 1 }),
// Version 2 leaves calls to tools not offered in a sequential round's `pending`, flagged `unoffered` in their slots.
// A version 1 Harness would start their tool tasks unflagged, resolving the name, so it leaves version 2 blocked
// instead. A version 1 checkpoint has no such calls and is kept as it is.
migrate: (input, checkpoint) => ({
input,
checkpoint
}),
phases: {
/**
* Render the system prompt and tool loadout and append the positional `pi.system` entries they need, then move to
* `request`. The agent and settings resolved here are fixed for this request. Only the Harness writes model
* context to a busy conversation, so the context read here is still current at the commit; display-only entries
* may land meanwhile.
*/
prepare: async (task, runtime, context) => {
if (cutOffTooOften(task, runtime))
return endCutOff2(runtime, task, context);
const { conversationId } = runtime;
const agent = await runtime.agent(context);
const settings = runtime.settings;
const { model: model3, thinkingLevel } = agent;
const resolved = model3 === void 0 ? void 0 : runtime.models.getModel(model3.provider, model3.modelId);
if (model3 === void 0 || resolved === void 0)
return failNoModel(runtime, model3, context);
const { attempt, compacted, overflow, threshold: blocked } = task.state.checkpoint;
if (compacted !== void 0 && overflow !== void 0) {
const [outcome] = await runtime.outcomes([compacted], context);
if (outcome?.status !== "completed" || outcome.result.entryId === void 0) {
return failModelError(runtime, overflow, context);
}
}
if (compacted !== void 0 && blocked === true) {
const [outcome] = await runtime.outcomes([compacted], context);
if (outcome !== void 0 && outcome.status !== "completed") {
return failModelError(runtime, compactionFailure(outcome), context);
}
}
const view2 = await runtime.context(conversationId, context);
const last = view2.messages.findLast((message) => message.role !== "system");
if (last?.role !== "user" && last?.role !== "toolResult")
return failNothingToAnswer(runtime, context);
const shown = replaySections(view2.messages);
let env;
try {
env = await runtime.env(context);
} catch (error) {
if (context.abortSignal?.aborted)
throw error;
runtime.report(error, { kind: "host", callback: "env" });
}
const input = { conversationId, agent, env, shown: Object.fromEntries(shown), read: runtime };
const desired = await renderSections(agent.sections, input, shown, (error, section) => runtime.report(error, {
kind: "extension",
...optionalExtension(sectionExtension(agent, section.key))
}), context);
const entries2 = planSystemEntries(view2, desired, agent.tools, runtime.now());
const threshold = compacted === void 0 ? thresholdCompaction(view2, entries2, resolved.contextWindow, compactionPolicy(settings, model3)) : void 0;
if (threshold === "blocking") {
await runtime.commit(async (tx) => {
const child = await createCompaction(tx, conversationId, { reason: "threshold" }, runtime.taskId);
const checkpoint = { phase: "prepare", attempt, compacted: child, threshold: true };
return { status: "waiting", checkpoint, on: [child], policy: "allSettled" };
}, context);
return;
}
await runtime.commit(async (tx) => {
let cutoff = await tx.latestEntryId(conversationId);
for (const entry2 of entries2)
cutoff = (await tx.appendEntry(SystemEntry, conversationId, entry2)).id;
if (threshold === "background" && (await tx.doc(LiveDoc, conversationId)).compactions === void 0) {
await createCompaction(tx, conversationId, { reason: "threshold" });
}
const request2 = {
attempt,
...compacted === void 0 ? {} : { compacted },
model: model3,
thinkingLevel,
streamOptions: settings.stream,
cutoff
};
return { status: "running", checkpoint: { phase: "request", ...request2 } };
}, context);
},
request: async (task, runtime, context) => {
if (cutOffTooOften(task, runtime))
return endCutOff2(runtime, task, context);
if (task.restarts !== void 0)
return interrupted(runtime, task.state.checkpoint, context);
const { attempt, compacted, model: ref, thinkingLevel, streamOptions, cutoff } = task.state.checkpoint;
const conversationId = runtime.conversationId;
await runtime.commit(async (tx) => {
const live = await tx.doc(LiveDoc, conversationId);
await convertPartial(tx, live, conversationId);
live.generation = { attempt };
return void 0;
}, context, PROGRESS_COMMIT);
const model3 = runtime.models.getModel(ref.provider, ref.modelId);
if (model3 === void 0)
return failNoModel(runtime, ref, context);
const view2 = await runtime.context(conversationId, context, { at: cutoff });
let messages = view2.messages;
await runtime.hooks.each("beforeRequest", async (hook) => {
const replaced = await hook({ messages }, runtime, context);
if (replaced !== void 0)
messages = replaced.messages;
});
const options = {
...streamOptions,
signal: runtime.signal,
telemetry: context.telemetry,
sessionId: await ensureProviderSessionId(runtime, context),
...thinkingLevel === "off" ? {} : { reasoning: thinkingLevel },
onPayload: (payload) => providerPayload(runtime, model3, payload, context)
};
const message = await streamResponse(runtime, model3, messages, options, attempt, context);
const request2 = { attempt, compacted, model: ref, thinkingLevel, cutoff, messages: view2.messages };
await classify2(runtime, request2, message, context);
},
/** After the backoff's sleep; a run before `until` (an early wake, or a record of an earlier version) sleeps again. */
retry: async (task, runtime, context) => {
const { attempt, compacted, until, poll } = task.state.checkpoint;
if (cutOffTooOften(task, runtime))
return endCutOff2(runtime, task, context);
if (until > runtime.now())
return runtime.sleepUntil(until, task.state.checkpoint, context);
await runtime.commit(async (tx) => {
const live = await tx.doc(LiveDoc, runtime.conversationId);
const kept = compacted === void 0 ? {} : { compacted };
if (poll !== void 0) {
const pollAt = runtime.now();
live.generation = { attempt: attempt + 1, deferred: { pollAt } };
return {
status: "running",
checkpoint: { phase: "poll", attempt: attempt + 1, ...kept, ...poll, pollAt }
};
}
live.generation = { attempt: attempt + 1 };
return { status: "running", checkpoint: { phase: "prepare", attempt: attempt + 1, ...kept } };
}, context);
},
/** After the sleep until `pollAt`; a run before it (an early wake, or a record of an earlier version) sleeps again. */
poll: async (task, runtime, context) => {
const { attempt, compacted, model: ref, thinkingLevel, cutoff, handle, pollAt } = task.state.checkpoint;
if (cutOffTooOften(task, runtime))
return endCutOff2(runtime, task, context);
if (task.restarts !== void 0)
return interrupted(runtime, task.state.checkpoint, context);
if (pollAt > runtime.now())
return runtime.sleepUntil(pollAt, task.state.checkpoint, context);
const model3 = runtime.models.getModel(ref.provider, ref.modelId);
if (model3 === void 0)
return failNoModel(runtime, ref, context);
const message = await runtime.models.fetchDeferred(model3, handle, {
signal: runtime.signal,
telemetry: context.telemetry
});
const request2 = { attempt, compacted, model: ref, thinkingLevel, cutoff, pollAt };
await classify2(runtime, request2, message, context);
},
tools: async (task, runtime, context) => {
if (cutOffTooOften(task, runtime))
return endCutOff2(runtime, task, context);
const { assistant, tools, pending } = task.state.checkpoint;
const [next, ...rest] = pending;
if (next === void 0)
return finishToolRound(runtime, assistant, tools, context);
await runtime.commit(async (tx) => {
const live = await tx.doc(LiveDoc, runtime.conversationId);
const slot = live.tools?.find((slot2) => slot2.callId === next && slot2.taskId === void 0);
const taskId = await createToolTask(tx, runtime, assistant, next, slot?.unoffered);
if (slot !== void 0)
slot.taskId = taskId;
const checkpoint = {
phase: "tools",
assistant,
tools: [...tools, taskId],
pending: rest
};
return { status: "waiting", checkpoint, on: [taskId], policy: "allSettled" };
}, context);
},
/**
* Ask the `afterRun` hooks for tasks and create them, as the generation's children, in the commit that moves to
* `drain`; without any, end the run now.
*/
finish: async (task, runtime, context) => {
const { run: run2 } = task.state.checkpoint;
if (cutOffTooOften(task, runtime))
return endAnsweredCutOff(runtime, task, run2.answer, context);
const prepared = [];
await runtime.hooks.each("afterRun", async (hook) => {
const asked = await hook(run2, runtime, context);
if (asked !== void 0)
prepareRunEndTasks(runtime, asked.tasks, prepared);
});
if (prepared.length === 0)
return endAnsweredRun(runtime, run2.answer, context);
await runtime.commit(async (tx) => {
const tasks = [];
for (const { task: task2, input } of prepared) {
tasks.push(await tx.createTask(task2, input, { ownership: { kind: "task", taskId: runtime.taskId } }));
}
const live = await tx.doc(LiveDoc, runtime.conversationId);
if (live.run?.taskId === runtime.taskId && live.run.afterRun !== void 0)
live.run.afterRun.tasks = tasks;
const checkpoint = { phase: "drain", answer: run2.answer, tasks };
return { status: "waiting", checkpoint, on: tasks, policy: "allSettled" };
}, context);
},
/** The after-run tasks are terminal, whatever their outcomes: end the run. */
drain: async (task, runtime, context) => {
const { answer: answer2 } = task.state.checkpoint;
if (cutOffTooOften(task, runtime))
return endAnsweredCutOff(runtime, task, answer2, context);
return endAnsweredRun(runtime, answer2, context);
}
},
abort: async (task, runtime, context) => {
const checkpoint = task.state.checkpoint;
const polled = deferredOf(checkpoint);
if (polled !== void 0)
await cancelDeferred(runtime, polled, context);
const conversationId = runtime.conversationId;
const unstarted = checkpoint.phase === "tools" ? await readCalls(runtime, checkpoint.assistant, checkpoint.pending, context) : [];
await runtime.commit(async (tx) => {
const live = await tx.doc(LiveDoc, conversationId);
await convertPartial(tx, live, conversationId);
for (const call of unstarted) {
const unoffered = live.tools?.find((slot) => slot.callId === call.id)?.unoffered === true;
const result = unoffered ? harnessError("tool_unavailable", `Tool ${call.name} is not available`) : harnessError("aborted", `Tool ${call.name} was aborted`);
await appendToolResult(tx, conversationId, call, result, { timestamp: runtime.now() });
}
endRun(tx, live, runtime.taskId, { status: "unanswered", reason: "aborted" });
return { status: "terminal", outcome: { status: "aborted" } };
}, context);
}
});
async function readCalls(runtime, assistant, callIds, context) {
const message = (await runtime.entry(AssistantEntry, assistant, context))?.model?.[0];
const calls = message?.role === "assistant" ? message.content.filter((content) => content.type === "toolCall") : [];
return callIds.flatMap((id) => calls.filter((call) => call.id === id).slice(0, 1));
}
function createToolTask(tx, runtime, assistant, callId, unoffered) {
return tx.createTask(ToolTask, { kind: "model", assistant, callId, ...unoffered === void 0 ? {} : { unoffered } }, { ownership: { kind: "task", taskId: runtime.taskId } });
}
function thresholdCompaction(view2, planned, contextWindow, policy) {
if (!policy.enabled || contextWindow <= 0)
return void 0;
const tokens = estimateContext(view2, planned.flatMap((entry2) => entry2.model ?? []));
const blocking = contextWindow - policy.reserveTokens;
const background = blocking - policy.backgroundTokens;
const over = tokens > blocking ? "blocking" : policy.backgroundTokens > 0 && tokens > background ? "background" : void 0;
if (over === void 0 || selectCut(view2, policy.keepRecentTokens) === void 0)
return void 0;
return over;
}
function compactionFailure(outcome) {
switch (outcome.status) {
case "failed":
case "faulted":
return `Compaction failed: ${outcome.error.message}`;
case "orphaned":
return `Compaction failed: ${outcome.reason}`;
case "aborted":
return "Compaction was aborted";
}
}
async function failModelError(runtime, text2, context) {
await runtime.commit(async (tx) => {
const failure = await prepareFailure(tx, runtime);
const live = await tx.doc(LiveDoc, runtime.conversationId);
await endFailedRun(tx, runtime, live, failure, { status: "unanswered", reason: "model_error", detail: text2 });
return {
status: "terminal",
outcome: { status: "failed", error: { message: text2, detail: { reason: "model_error" } } }
};
}, context);
}
async function interrupted(runtime, checkpoint, context) {
const { attempt, compacted } = checkpoint;
const policy = runtime.settings.retry;
const retry = policy.enabled && attempt <= policy.maxRetries;
const until = retry ? runtime.now() + retryDelayMs(policy, attempt) : 0;
const polled = checkpoint.phase === "poll" ? checkpoint : void 0;
const text2 = polled === void 0 ? `The host stopped while the model was answering, on attempt ${attempt}` : `The host stopped while the deferred answer was fetched, on attempt ${attempt}`;
if (!retry && polled !== void 0)
await cancelDeferred(runtime, polled, context);
await runtime.commit(async (tx) => {
const failure = retry ? void 0 : await prepareFailure(tx, runtime);
const live = await tx.doc(LiveDoc, runtime.conversationId);
await convertPartial(tx, live, runtime.conversationId);
if (failure === void 0) {
live.generation = { attempt, retry: { at: until, error: text2 } };
const poll = polled === void 0 ? {} : {
poll: {
model: polled.model,
...polled.thinkingLevel === void 0 ? {} : { thinkingLevel: polled.thinkingLevel },
cutoff: polled.cutoff,
handle: polled.handle
}
};
const next = { phase: "retry", attempt, ...compacted === void 0 ? {} : { compacted }, until, ...poll };
return { status: "sleeping", checkpoint: next, until };
}
await endFailedRun(tx, runtime, live, failure, { status: "unanswered", reason: "interrupted", detail: text2 });
return {
status: "terminal",
outcome: { status: "failed", error: { message: text2, detail: { reason: "interrupted" } } }
};
}, context);
}
async function endCutOff2(runtime, task, context) {
const checkpoint = task.state.checkpoint;
const text2 = `The generation was interrupted ${cutOffCount(task)} in its ${checkpoint.phase} phase`;
const salvage = salvageable(task, runtime);
const polled = deferredOf(checkpoint);
if (salvage && polled !== void 0)
await cancelDeferred(runtime, polled, context);
await runtime.commit(async (tx) => {
const failure = await prepareFailure(tx, runtime);
const live = await tx.doc(LiveDoc, runtime.conversationId);
if (salvage)
await convertPartial(tx, live, runtime.conversationId);
await endFailedRun(tx, runtime, live, failure, { status: "unanswered", reason: "restart_limit", detail: text2 });
return {
status: "terminal",
outcome: { status: "failed", error: { message: text2, detail: { reason: "restart_limit" } } }
};
}, context);
}
function deferredOf(checkpoint) {
if (checkpoint.phase === "poll")
return checkpoint;
return checkpoint.phase === "retry" ? checkpoint.poll : void 0;
}
async function cancelDeferred(runtime, checkpoint, context) {
const model3 = runtime.models.getModel(checkpoint.model.provider, checkpoint.model.modelId);
if (model3 === void 0)
return;
try {
await runtime.models.cancelDeferred(model3, checkpoint.handle, {
signal: runtime.signal,
telemetry: context.telemetry
});
} catch (error) {
runtime.report(error, { kind: "host", callback: "models" });
}
}
async function failNoModel(runtime, ref, context) {
const message = ref === void 0 ? "No model is configured" : `Model ${ref.provider}/${ref.modelId} is not available`;
await runtime.commit(async (tx) => {
const failure = await prepareFailure(tx, runtime);
const live = await tx.doc(LiveDoc, runtime.conversationId);
await endFailedRun(tx, runtime, live, failure, {
status: "unanswered",
reason: "no_model",
detail: message,
settlement: { status: "unanswered", reason: "no_model" }
});
return { status: "terminal", outcome: { status: "failed", error: { message, detail: { reason: "no_model" } } } };
}, context);
}
async function failNothingToAnswer(runtime, context) {
const message = "The conversation has nothing to answer";
await runtime.commit(async (tx) => {
const failure = await prepareFailure(tx, runtime);
const live = await tx.doc(LiveDoc, runtime.conversationId);
await endFailedRun(tx, runtime, live, failure, { status: "unanswered", reason: "nothing_to_answer" });
const error = { message, detail: { reason: "nothing_to_answer" } };
return { status: "terminal", outcome: { status: "failed", error } };
}, context);
}
async function prepareFailure(tx, runtime) {
const settings = runtime.settings;
const policy = settings.afterFailedRun;
if (policy !== "continue")
return { policy };
return { policy, boundary: await prepareBoundary(tx, runtime.conversationId, settings) };
}
async function endFailedRun(tx, runtime, live, failure, end) {
const conversationId = runtime.conversationId;
endRun(tx, live, runtime.taskId, end);
if (failure.policy === "withdraw")
await withdrawQueuedInputs(tx, conversationId, "run_failed");
if (failure.boundary === void 0)
return;
const { users, first } = await applyBoundary(tx, failure.boundary, "final", runtime.now());
if (users.length > 0)
await startRun(tx, conversationId, live, { inputs: users, first }, { keepFailure: true });
}
async function convertPartial(tx, live, conversationId) {
const partial2 = live.generation?.message;
if (partial2 === void 0)
return;
const message = copyJson(partial2);
await appendAssistant(tx, conversationId, { ...message, stopReason: "aborted" });
}
async function providerPayload(runtime, model3, payload, context) {
let current = payload;
await runtime.hooks.each("beforeProviderRequest", async (hook) => {
const replaced = await hook({ model: model3, payload: current }, runtime, context);
if (replaced !== void 0)
current = replaced.payload;
});
return current;
}
async function streamResponse(runtime, model3, messages, options, attempt, context) {
const interval = runtime.settings.progress.partialIntervalMs;
let pending;
let timer;
let inFlight;
let stopped = false;
const changes = new PartialChanges();
const flush = () => {
timer = void 0;
const partial2 = pending;
pending = void 0;
if (partial2 === void 0 || stopped)
return;
inFlight = (async () => {
const message = copyJson(partial2, { omitUndefinedProperties: true });
const taken = changes.take(message);
try {
await runtime.commit(async (tx) => {
const live = await tx.doc(LiveDoc, runtime.conversationId);
live.generation ??= { attempt };
changes.commit(live.generation, message, taken);
return void 0;
}, context, PROGRESS_COMMIT);
} catch (error) {
changes.restore(taken);
throw error;
}
})().catch((error) => {
if (!runtime.signal.aborted)
runtime.report(error);
}).finally(() => {
inFlight = void 0;
if (pending !== void 0 && !stopped)
timer = runtime.setTimer(flush, interval);
});
};
try {
const events = runtime.models.streamSimple(model3, { messages: [...messages] }, options);
for await (const event of events) {
if (event.type === "done" || event.type === "error" || event.partial.content.length === 0)
continue;
changes.observe(event);
pending = event.partial;
if (timer === void 0 && inFlight === void 0)
timer = runtime.setTimer(flush, interval);
}
return await events.result();
} finally {
stopped = true;
timer?.();
await inFlight;
}
}
async function classify2(runtime, request2, message, context) {
runtime.signal.throwIfAborted();
const conversationId = runtime.conversationId;
const { attempt, compacted, model: ref, thinkingLevel, cutoff } = request2;
if (thinkingLevel !== void 0)
message.thinkingLevel = thinkingLevel;
if (message.stopReason === "deferred" && message.deferred !== void 0) {
const handle = message.deferred;
const pollAt = Math.max(runtime.now() + (handle.pollAfterMs ?? DEFAULT_POLL_AFTER_MS), request2.pollAt === void 0 ? Number.NEGATIVE_INFINITY : request2.pollAt + 1);
await runtime.commit(async (tx) => {
(await tx.doc(LiveDoc, conversationId)).generation = { attempt, deferred: { pollAt } };
const checkpoint = {
phase: "poll",
attempt,
...compacted === void 0 ? {} : { compacted },
model: ref,
...thinkingLevel === void 0 ? {} : { thinkingLevel },
cutoff,
handle,
pollAt
};
return { status: "sleeping", checkpoint, until: pollAt };
}, context);
return;
}
await runtime.hooks.each("afterResponse", (hook) => hook(message, runtime, context));
const calls = message.content.filter((content) => content.type === "toolCall");
if (message.stopReason === "toolUse" && calls.length > 0) {
return startToolRound(runtime, request2, message, calls, context);
}
if (message.stopReason === "stop" || message.stopReason === "length" || message.stopReason === "toolUse") {
return answer(runtime, message, context);
}
const settings = runtime.settings;
const overflow = message.stopReason === "error" && isContextOverflow(message);
const compaction = compactionPolicy(settings, ref);
if (overflow && compacted === void 0 && compaction.enabled) {
const view2 = await runtime.context(conversationId, context, { at: cutoff });
if (selectCut(view2, compaction.keepRecentTokens) !== void 0) {
const text2 = message.errorMessage ?? "Context overflow";
await runtime.commit(async (tx) => {
const live = await tx.doc(LiveDoc, conversationId);
await appendAssistant(tx, conversationId, message);
delete live.generation;
const child = await createCompaction(tx, conversationId, { reason: "overflow" }, runtime.taskId);
const checkpoint = { phase: "prepare", attempt, compacted: child, overflow: text2 };
return { status: "waiting", checkpoint, on: [child], policy: "allSettled" };
}, context);
return;
}
}
const policy = settings.retry;
const retry = message.stopReason === "error" && !overflow && isRetryableAssistantError(message) && policy.enabled && attempt <= policy.maxRetries;
const until = retry ? runtime.now() + retryDelayMs(policy, attempt) : 0;
await runtime.commit(async (tx) => {
const failure = retry ? void 0 : await prepareFailure(tx, runtime);
const live = await tx.doc(LiveDoc, conversationId);
await appendAssistant(tx, conversationId, message);
if (failure === void 0) {
live.generation = { attempt, retry: { at: until, error: message.errorMessage ?? "" } };
const checkpoint = {
phase: "retry",
attempt,
...compacted === void 0 ? {} : { compacted },
until
};
return { status: "sleeping", checkpoint, until };
}
const text2 = message.errorMessage ?? `Model response ended with stop reason ${message.stopReason}`;
await endFailedRun(tx, runtime, live, failure, { status: "unanswered", reason: "model_error", detail: text2 });
return {
status: "terminal",
outcome: { status: "failed", error: { message: text2, detail: { reason: "model_error" } } }
};
}, context);
}
async function answer(runtime, message, context) {
let continuation;
await runtime.hooks.each("onYield", async (hook) => {
if (continuation !== void 0)
return;
continuation = (await hook(message, runtime, context))?.continue;
});
const afterRun = await asksAfterRun(runtime, context);
const conversationId = runtime.conversationId;
await runtime.commit(async (tx) => {
const boundary = await prepareBoundary(tx, conversationId, runtime.settings);
const live = await tx.doc(LiveDoc, conversationId);
const entry2 = await appendAssistant(tx, conversationId, message);
const result = { status: "terminal", outcome: { status: "completed", result: { entryId: entry2.id } } };
const continues = takesContinuation(continuation, boundary) ? continuation : void 0;
if (continues === void 0 && afterRun) {
const held = holdRun(tx, live, runtime, { reason: "answer", answer: entry2.id, last: entry2.id });
if (held !== void 0)
return held;
}
const { users, first } = await applyBoundary(tx, boundary, "final", runtime.now());
if (continues !== void 0) {
const user = { role: "user", content: continues, timestamp: runtime.now() };
await tx.appendEntry(UserEntry, conversationId, { model: [user] });
if (live.run?.taskId === runtime.taskId)
live.run.turns = 0;
handOver(live, runtime.taskId, await createGeneration(tx, conversationId));
delete live.generation;
return result;
}
endRun(tx, live, runtime.taskId, { status: "done", answer: entry2.id });
if (users.length > 0)
await startRun(tx, conversationId, live, { inputs: users, first });
return result;
}, context);
}
async function asksAfterRun(runtime, context) {
const hooks = agentHooks(await runtime.agent(context), GenerationTask.definition.name);
return hooks.some(({ handlers }) => typeof handlers.afterRun === "function");
}
function holdRun(tx, live, runtime, end) {
const run2 = live.run;
if (run2?.taskId !== runtime.taskId)
return void 0;
for (const id of run2.inputs)
tx.settleSubmission(id, { status: "done", answer: end.answer });
run2.inputs = [];
run2.afterRun = {};
delete live.generation;
delete live.tools;
delete live.nestedTools;
const summary = { ...end, first: run2.first ?? end.answer };
return { status: "running", checkpoint: { phase: "finish", run: summary } };
}
function prepareRunEndTasks(runtime, requests, prepared) {
const rejected = [];
for (const request2 of requests) {
try {
const name = request2.task.definition.name;
if (name.startsWith("pi."))
throw new Error(`An afterRun hook cannot start the built-in task ${name}`);
const installed = runtime.registry.task(name);
if (installed === void 0)
throw new Error(`Task ${name} is not installed`);
const input = copyJson(request2.input, { omitUndefinedProperties: true });
const definition = installed.definition;
const checkpoint = copyJson(definition.initial(input), { omitUndefinedProperties: true });
if (!Object.hasOwn(definition.phases, checkpoint.phase)) {
throw new Error(`Task ${name} starts at the unknown phase ${String(checkpoint.phase)}`);
}
prepared.push({ task: { definition: { ...definition, initial: () => checkpoint } }, input });
} catch (error) {
rejected.push(error);
}
}
if (rejected.length === 1)
throw rejected[0];
if (rejected.length > 1)
throw new AggregateError(rejected, `${rejected.length} afterRun task requests were rejected`);
}
async function endAnsweredRun(runtime, answer2, context) {
const conversationId = runtime.conversationId;
await runtime.commit(async (tx) => {
const boundary = await prepareBoundary(tx, conversationId, runtime.settings);
const live = await tx.doc(LiveDoc, conversationId);
const { users, first } = await applyBoundary(tx, boundary, "final", runtime.now());
endRun(tx, live, runtime.taskId, { status: "done", answer: answer2 });
if (users.length > 0)
await startRun(tx, conversationId, live, { inputs: users, first });
return { status: "terminal", outcome: { status: "completed", result: { entryId: answer2 } } };
}, context);
}
async function endAnsweredCutOff(runtime, task, answer2, context) {
const text2 = `The generation was interrupted ${cutOffCount(task)} in its ${task.state.checkpoint.phase} phase`;
await runtime.commit(async (tx) => {
const live = await tx.doc(LiveDoc, runtime.conversationId);
endRun(tx, live, runtime.taskId, { status: "done", answer: answer2 });
const completed = { status: "terminal", outcome: { status: "completed", result: { entryId: answer2 } } };
return endedByCrashes(completed, text2);
}, context);
}
function takesContinuation(continuation, boundary) {
const items = boundary.inbox.items;
return continuation !== void 0 && !items.some((item) => item.mode === "steer" || item.mode === "followUp") && !hasQueuedReset(items);
}
async function startToolRound(runtime, request2, message, calls, context) {
const conversationId = runtime.conversationId;
const messages = request2.messages ?? (await runtime.context(conversationId, context, { at: request2.cutoff })).messages;
const offered = new Set(getCurrentTools(messages).map((tool) => tool.name));
const tools = (await runtime.agent(context)).tools;
const sequential = runtime.settings.toolExecution === "sequential" || calls.some((call) => offered.has(call.name) && tools.find((tool) => tool.name === call.name)?.executionMode === "sequential");
await runtime.commit(async (tx) => {
const live = await tx.doc(LiveDoc, conversationId);
const entry2 = await appendAssistant(tx, conversationId, message);
const slots = [];
const tools2 = [];
const pending = [];
for (const call of calls) {
const unoffered = offered.has(call.name) ? {} : { unoffered: true };
if (sequential && tools2.length > 0) {
pending.push(call.id);
slots.push({ callId: call.id, name: call.name, status: "pending", ...unoffered });
continue;
}
const taskId = await createToolTask(tx, runtime, entry2.id, call.id, unoffered.unoffered);
tools2.push(taskId);
slots.push({ callId: call.id, name: call.name, taskId, status: "pending", ...unoffered });
}
delete live.generation;
live.tools = slots;
if (live.run?.taskId === runtime.taskId) {
live.run.turns += 1;
live.run.first ??= entry2.id;
}
const checkpoint = { phase: "tools", assistant: entry2.id, tools: tools2, pending };
return { status: "waiting", checkpoint, on: tools2, policy: "allSettled" };
}, context);
}
async function finishToolRound(runtime, assistant, tools, context) {
const conversationId = runtime.conversationId;
const controls = /* @__PURE__ */ new Map();
const outcomes = await runtime.outcomes(tools, context);
tools.forEach((id, index) => {
const outcome = outcomes[index];
controls.set(id, outcome.status === "completed" && outcome.result.kind !== "nested" ? outcome.result.control : void 0);
});
const slots = (await runtime.snapshot(LiveDoc, conversationId, context))?.tools ?? [];
const results = slots.flatMap((slot) => slot.entry === void 0 ? [] : [slot.entry]);
await runtime.hooks.each("afterTools", (hook) => hook(assistant, results, runtime, context));
const ordered = slots.map((slot) => slot.taskId === void 0 ? void 0 : controls.get(slot.taskId));
const terminate = slots.length > 0 && ordered.every((control) => control?.terminate === true);
const added = ordered.flatMap((control) => control?.addTools ?? []);
const handoff = ordered.findLast((control) => control?.handoff !== void 0)?.handoff;
const maxTurns = (await runtime.agent(context)).maxTurns;
const afterRun = terminate && await asksAfterRun(runtime, context);
await runtime.commit(async (tx) => {
const boundary = await prepareBoundary(tx, conversationId, runtime.settings);
if (added.length > 0)
await addTools(tx, conversationId, added);
const live = await tx.doc(LiveDoc, conversationId);
const now = runtime.now();
let last = results.reduce((newest, id) => id > newest ? id : newest, assistant);
if (handoff !== void 0) {
const message = { role: "user", content: handoff, timestamp: now };
const entry2 = await tx.appendEntry(ResetEntry, conversationId, { head: "self", model: [message] });
boundary.head = entry2.id;
last = entry2.id;
}
const turns = live.run?.taskId === runtime.taskId ? live.run.turns : 0;
const held = afterRun ? holdRun(tx, live, runtime, { reason: "terminate", answer: assistant, last }) : void 0;
if (held !== void 0)
return held;
if (terminate) {
const { users, first } = await applyBoundary(tx, boundary, "final", now);
endRun(tx, live, runtime.taskId, { status: "done", answer: assistant });
if (users.length > 0)
await startRun(tx, conversationId, live, { inputs: users, first });
} else if (maxTurns !== void 0 && turns >= maxTurns) {
const policy = runtime.settings.afterFailedRun;
const failure = { policy, ...policy === "continue" ? { boundary } : {} };
await endFailedRun(tx, runtime, live, failure, {
status: "unanswered",
reason: "turn_limit",
detail: turns === 1 ? "1 turn" : `${turns} turns`
});
} else {
const { users, first, reset } = await applyBoundary(tx, boundary, "postTools", now);
if (reset) {
endRun(tx, live, runtime.taskId, { status: "unanswered", reason: "reset" });
if (users.length > 0) {
await startRun(tx, conversationId, live, { inputs: users, first }, { keepFailure: true });
}
} else {
delete live.tools;
delete live.nestedTools;
if (live.run?.taskId === runtime.taskId)
live.run.inputs.push(...users);
handOver(live, runtime.taskId, await createGeneration(tx, conversationId));
}
}
return { status: "terminal", outcome: { status: "completed", result: { entryId: assistant } } };
}, context);
}
async function appendAssistant(tx, conversationId, message) {
await recordUsage(tx, conversationId, "models", `${message.provider}/${message.model}`, message.usage);
return tx.appendEntry(AssistantEntry, conversationId, { model: [message] });
}
async function startRun(tx, conversationId, live, run2, options) {
const { inputs, first } = run2;
const taskId = await createGeneration(tx, conversationId, { submissionIds: inputs });
live.run = { taskId, inputs, turns: 0, ...first === void 0 ? {} : { first } };
if (options?.keepFailure !== true)
delete live.runFailure;
}
function createGeneration(tx, conversationId, telemetry = {}) {
return tx.createTask(GenerationTask, {}, { ownership: { kind: "conversation" }, conversationId, ...telemetry });
}
function handOver(live, from, to) {
if (live.run?.taskId === from)
live.run.taskId = to;
}
// node_modules/@earendil-works/pi-durable/dist/harness/live.js
var LiveDoc = defineDoc({
kind: "pi.live",
version: 3,
scope: "conversation",
history: "latest",
fork: "initial",
initial: () => ({}),
// Version 1 named a compaction's trigger `reason`, in `compactions` and `compactionFailure`. Versions 1 and 2 (as
// builds before `run.turns` stored it) may lack `run.turns`: a run in flight across the upgrade counts its turns
// from 0. Version 2 already names the trigger `trigger`, so renaming leaves it alone.
migrate: (value2) => {
const live = value2;
const { run: run2, compactions, compactionFailure: compactionFailure2 } = live;
return {
...value2,
...run2 === void 0 ? {} : { run: { ...run2, turns: typeof run2.turns === "number" ? run2.turns : 0 } },
...compactions === void 0 ? {} : { compactions: compactions.map(renameReason) },
...compactionFailure2 === void 0 ? {} : { compactionFailure: renameReason(compactionFailure2) }
};
},
// REMINDER: a complete base whenever nothing runs (spec §8.2): no generation and no running tool slot. That holds
// while idle, in the commit handing a generation over to its tool round, and between tools, so the delta chain
// spans at most one generation or the overlapping execution of one round's tools. A slot holds output only while
// running, so every base is small; a nested call's result lives in its caller's task documents, never here. Do not
// add a delta-count bound; the tool output benchmark checks this rule.
checkpointWhen: (value2) => value2.generation === void 0 && !(value2.tools ?? []).some((slot) => slot.status === "running") && !(value2.nestedTools ?? []).some((slot) => slot.status === "running")
});
function renameReason(value2) {
return Object.fromEntries(Object.entries(value2).map(([key, field]) => [key === "reason" ? "trigger" : key, field]));
}
var PROGRESS_COMMIT = { persistence: { kind: "deferred" } };
var RUN_TASK_KINDS = /* @__PURE__ */ new Set(["pi.generation"]);
var TOOL_TASK_KIND = "pi.tool";
var COMPACTION_TASK_KIND = "pi.compaction";
var LIMITS_RESTARTS = /* @__PURE__ */ new Set([...RUN_TASK_KINDS, TOOL_TASK_KIND, COMPACTION_TASK_KIND]);
function cutOffTooOften(task, runtime) {
return task.restarts !== void 0 && task.restarts >= runtime.settings.restartLimit;
}
function salvageable(task, runtime) {
return (task.restarts ?? 0) <= runtime.settings.restartLimit;
}
function cutOffCount(task) {
const restarts = task.restarts ?? 0;
return restarts === 1 ? "once" : `${restarts} times in a row`;
}
function endRun(tx, live, taskId, end) {
if (live.run?.taskId === taskId) {
const inputs = [...live.run.inputs];
const { first } = live.run;
if (end.status === "done") {
for (const id of inputs)
tx.settleSubmission(id, { status: "done", answer: end.answer });
} else if (live.run.afterRun === void 0) {
const { reason, detail } = end;
const settlement = end.settlement ?? {
status: "unanswered",
reason,
...detail === void 0 ? {} : { detail }
};
for (const id of inputs)
tx.settleSubmission(id, settlement);
live.runFailure = {
taskId,
inputs,
reason,
...detail === void 0 ? {} : { detail },
...first === void 0 ? {} : { first }
};
}
delete live.run;
}
delete live.generation;
delete live.tools;
delete live.nestedTools;
}
function addCompactionStatus(live, status) {
live.compactions ??= [];
live.compactions.push(status);
}
function compactionStatus(live, taskId) {
return live.compactions?.find((status) => status.taskId === taskId);
}
function removeCompactionStatus(live, taskId) {
const statuses = live.compactions;
if (statuses === void 0)
return;
const index = statuses.findIndex((status) => status.taskId === taskId);
if (index >= 0)
statuses.splice(index, 1);
if (statuses.length === 0)
delete live.compactions;
}
function failCompactionStatus(live, taskId, error) {
const status = compactionStatus(live, taskId);
if (status !== void 0)
live.compactionFailure = { taskId: status.taskId, trigger: status.trigger, error };
removeCompactionStatus(live, taskId);
}
function toolSlot(live, taskId) {
const slot = live.tools?.find((each) => each.taskId === taskId);
if (slot !== void 0 || live.nestedTools === void 0)
return slot;
const nested = live.nestedTools;
let low = 0;
let high = nested.length - 1;
while (low <= high) {
const middle = low + high >>> 1;
const candidate = nested[middle];
if (candidate.taskId === taskId)
return candidate;
if (candidate.taskId < taskId)
low = middle + 1;
else
high = middle - 1;
}
return void 0;
}
function finishSlot(slot) {
slot.status = "done";
clearProgress(slot);
}
function removeNestedSlots(live, taskId) {
const nested = live.nestedTools;
if (nested === void 0)
return;
const removed = /* @__PURE__ */ new Set([taskId]);
for (const slot of nested)
if (removed.has(slot.parentTaskId))
removed.add(slot.taskId);
for (let index = nested.length - 1; index >= 0; index--) {
if (removed.has(nested[index].parentTaskId))
nested.splice(index, 1);
}
if (nested.length === 0)
delete live.nestedTools;
}
function clearProgress(slot) {
delete slot.output;
delete slot.droppedBytes;
delete slot.droppedLines;
delete slot.details;
delete slot.diagnostics;
}
async function settleSchedulerOutcome(tx, record, outcome) {
if (record.kind === TOOL_TASK_KIND) {
const live2 = await tx.doc(LiveDoc, record.conversationId);
const slot = toolSlot(live2, record.id);
if (slot !== void 0)
finishSlot(slot);
removeNestedSlots(live2, record.id);
return;
}
const detail = outcome.status === "faulted" ? outcome.error.detail : void 0;
const cutOff = typeof detail === "object" && detail !== null && "reason" in detail && detail.reason === "restart_limit";
if (record.kind === COMPACTION_TASK_KIND) {
const live2 = await tx.doc(LiveDoc, record.conversationId);
if (cutOff)
removeCompactionStatus(live2, record.id);
else
failCompactionStatus(live2, record.id, outcome.status === "faulted" ? outcome.error.message : outcome.reason);
return;
}
if (!RUN_TASK_KINDS.has(record.kind))
return;
const live = await tx.doc(LiveDoc, record.conversationId);
if (live.run?.taskId !== record.id)
return;
if (!cutOff)
await convertPartial(tx, live, record.conversationId);
endRun(tx, live, record.id, outcome.status === "faulted" ? { status: "unanswered", reason: cutOff ? "aborted" : "faulted", detail: outcome.error.message } : {
status: "unanswered",
reason: "orphaned",
detail: outcome.reason,
settlement: { status: "unanswered", reason: outcome.reason }
});
}
// node_modules/@earendil-works/pi-durable/dist/harness/submissions.js
init_dist();
var Submissions = class {
#telemetry;
#session;
#now;
/** Read at each admission, on the Session line. */
#queueModes;
/** Enable task scheduling; submitting or waiting asks for progress. */
#resume;
#waiters = new Waiters();
#closed = false;
constructor(session, now, queueModes, resume, telemetry = NOOP_TELEMETRY_CONTEXT) {
this.#telemetry = telemetry;
this.#session = session;
this.#now = now;
this.#queueModes = queueModes;
this.#resume = resume;
session.followCommits((publication) => this.#observe(publication));
session.subscribeClose(() => {
this.#closed = true;
this.#waiters.rejectAll(closedError(this.#session));
});
}
/** Admit a submission in one commit; see `admitSubmission()`. */
async submit(conversationId, draft, context) {
const { id } = await this.#traced(conversationId, draft, context, (span) => this.#session.commitWith((tx) => admitSubmission(tx, conversationId, draft, this.#now(), this.#queueModes(), span), withTelemetry(span, context)));
return new SubmissionHandle(id, this);
}
/**
* Admit a submission inside the caller's commit `tx`, with the rules of `submit()`. The admission is stored or lost
* with that commit. It must come before the commit's first table write, another admission's included.
*/
async admit(tx, conversationId, draft) {
if (!this.#session.ownsTransaction(tx))
throw new Error("The transaction belongs to another Session");
if (tx.hasTableWrite)
throw new ReadAfterWrite("submit(tx, draft)");
const admission = await this.#traced(conversationId, draft, tx.context, (span) => admitSubmission(tx, conversationId, draft, this.#now(), this.#queueModes(), span));
return admission.id;
}
/** Run one admission in its `pi.durable.submit` span, asking for progress first, as the run it starts needs it. */
#traced(conversationId, draft, context, admit) {
this.#resume();
const startsRun = draft.type !== "write";
const parent = startsRun ? this.#telemetry : context.telemetry;
return createTypedSpanStarter(parent, [DURABLE_TELEMETRY_SCHEMA])("pi.durable.submit", {
"submission.type": draft.type,
"conversation.id": conversationId
}, async (span) => {
if (startsRun)
span.addLink({ context: context.telemetry });
try {
const admission = await admit(span);
span.setAttributes({ "submission.id": admission.id, result: admission.status });
return admission;
} catch (error) {
span.setStatus({ status: "error" });
throw error;
}
});
}
/** Handle for an existing submission, or `undefined`. */
async get(id, context) {
const record = await this.#session.readOnLine((storage) => storage.submission(id, context));
return record === void 0 ? void 0 : new SubmissionHandle(record.id, this);
}
async status(id, context) {
const record = await this.#session.readOnLine((storage) => storage.submission(id, context));
if (record === void 0)
throw new Error(`Submission ${id} does not exist`);
return record;
}
async wait(id, context) {
this.#resume();
const found = await this.#session.readOnLine(async (storage) => {
const record = await storage.submission(id, context);
if (record === void 0)
throw new Error(`Submission ${id} does not exist`);
if (isSettled(record))
return { promise: Promise.resolve(record) };
if (this.#closed)
throw closedError(this.#session);
return { promise: this.#waiters.add(id, context) };
});
return found.promise;
}
/** Withdraw a queued submission and remove its inbox item; placed inputs and settled submissions are reported. */
abort(id, context, conversationId) {
return this.#session.commitWith(async (tx) => {
const record = await tx.submission(id);
if (record === void 0 || conversationId !== void 0 && record.conversationId !== conversationId) {
return "not_found";
}
if (record.status === "queued") {
tx.settleSubmission(id, { status: "unanswered", reason: "aborted" });
await removeInboxItem(tx, record.conversationId, id);
return "aborted";
}
return record.status === "placed" ? "already_placed" : "settled";
}, context);
}
#observe(publication) {
if (publication.kind === "memory")
return;
for (const change of publication.changes) {
if (change.type !== "submission" || !isSettled(change.value))
continue;
this.#waiters.resolve(change.value.id, change.value);
}
}
};
var SubmissionHandle = class {
id;
#submissions;
constructor(id, submissions) {
this.id = id;
this.#submissions = submissions;
}
status(context) {
return this.#submissions.status(this.id, context);
}
wait(context) {
return this.#submissions.wait(this.id, context);
}
async abort(context) {
const result = await this.#submissions.abort(this.id, context);
if (result === "not_found")
throw new Error(`Submission ${this.id} does not exist`);
return result;
}
};
function isSettled(record) {
return record.status === "done" || record.status === "unanswered";
}
function checkInputEntry(entry2) {
const { kind } = entry2;
if (typeof kind !== "string" || kind.length === 0 || kind.startsWith("pi.")) {
throw new TypeError(`An input entry's kind must be a non-empty string not starting with "pi.", got ${String(kind)}`);
}
}
async function admitSubmission(tx, conversationId, draft, now, queueModes, span) {
if (draft.type === "input" && draft.entry !== void 0)
checkInputEntry(draft.entry);
if (draft.requestId !== void 0) {
const existing = await tx.submissionByRequest(conversationId, draft.requestId);
if (existing !== void 0) {
if (existing.type !== draft.type) {
throw new Error(`Request ${draft.requestId} already identifies a submission of type ${existing.type}`);
}
return { id: existing.id, status: existing.status === "unanswered" ? "done" : existing.status };
}
}
const fields = { conversationId, requestId: draft.requestId, trace: span?.propagation?.inject(span) };
if (draft.type === "write" && isDisplayOnly(draft.entry) && !hasQueuedReset((await tx.doc(InboxDoc, conversationId)).items)) {
const entry3 = await tx.appendEntry(conversationId, draft.entry);
const write = { ...fields, type: "write", status: "done", entry: entry3.id };
return { id: (await tx.createSubmission(write)).id, status: "done" };
}
const live = await tx.doc(LiveDoc, conversationId);
const busy = live.run !== void 0;
if (draft.type === "input" && draft.whenBusy === "steer" && live.run !== void 0 && span?.propagation !== void 0) {
const run2 = await tx.task(live.run.taskId);
if (run2?.trace !== void 0)
span.addLink({ context: span.propagation.extract(run2.trace) });
}
if (busy && draft.type === "input" && draft.whenBusy === "reject")
throw new ConversationBusy(conversationId);
if (!busy && draft.type === "input" && draft.whenIdle === "reject")
throw new ConversationIdle(conversationId);
if (draft.type === "continue") {
if (busy)
throw new ConversationBusy(conversationId);
const boundary2 = await prepareBoundary(tx, conversationId, queueModes);
const { id: id2 } = await tx.createSubmission({ ...fields, type: "continue", status: "placed" });
const { users, first } = await applyBoundary(tx, boundary2, "final", now);
await startRun(tx, conversationId, live, { inputs: [...users, id2], first: live.runFailure?.first ?? first });
return { id: id2, status: "placed" };
}
const boundary = busy ? void 0 : await prepareBoundary(tx, conversationId, queueModes);
if (boundary === void 0 || boundary.inbox.items.length > 0) {
const { id: id2 } = await tx.createSubmission({
...fields,
type: draft.type,
status: "queued"
});
const value2 = copyJson(draft.type === "write" ? draft.entry : draft.content, {
omitUndefinedProperties: true
});
const items = (boundary?.inbox ?? await tx.doc(InboxDoc, conversationId)).items;
if (draft.type === "write")
items.push({ id: id2, mode: "write", entry: value2 });
else {
const mode = draft.whenBusy === "steer" ? "steer" : "followUp";
const content = value2;
const entry3 = draft.entry === void 0 ? {} : { entry: pickInputEntry(draft.entry) };
items.push({ id: id2, mode, content, ...entry3 });
}
if (boundary === void 0)
return { id: id2, status: "queued" };
const { users, first } = await applyBoundary(tx, boundary, "final", now);
if (users.length > 0)
await startRun(tx, conversationId, live, { inputs: users, first });
return { id: id2, status: draft.type === "write" ? "done" : users.at(-1) === id2 ? "placed" : "queued" };
}
if (draft.type === "write") {
if (isStale(boundary, draft.entry)) {
const stale = { status: "unanswered", reason: "stale" };
return {
id: (await tx.createSubmission({ ...fields, type: "write", ...stale })).id,
status: "done"
};
}
const entry3 = await tx.appendEntry(conversationId, draft.entry);
const write = { ...fields, type: "write", status: "done", entry: entry3.id };
return { id: (await tx.createSubmission(write)).id, status: "done" };
}
const entry2 = await appendInput(tx, conversationId, draft.content, draft.entry, now);
const input = { ...fields, type: "input", status: "placed", entry: entry2.id };
const { id } = await tx.createSubmission(input);
await startRun(tx, conversationId, live, { inputs: [id], first: entry2.id });
return { id, status: "placed" };
}
// node_modules/@earendil-works/pi-durable/dist/harness/compaction.js
var TOOL_RESULT_MAX_CHARS = 2e3;
var SUMMARY_PREFIX = "The conversation history before this point was compacted into the following summary:\n\n<summary>\n";
var SUMMARY_SUFFIX = "\n</summary>";
var SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.
Do NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;
var SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work. If the conversation starts with an earlier summary, preserve its information and fold the newer messages into it.
Use this EXACT format:
## Goal
[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]
## Constraints & Preferences
- [Any constraints, preferences, or requirements mentioned by user]
- [Or "(none)" if none were mentioned]
## Progress
### Done
- [x] [Completed tasks/changes]
### In Progress
- [ ] [Current work]
### Blocked
- [Issues preventing progress, if any]
## Key Decisions
- **[Decision]**: [Brief rationale]
## Next Steps
1. [Ordered list of what should happen next]
## Critical Context
- [Any data, examples, or references needed to continue]
- [Or "(none)" if not applicable]
Keep each section concise. Preserve exact file paths, function names, and error messages.`;
var CompactionTask = defineTask({
name: "pi.compaction",
version: 1,
initial: () => ({ phase: "select" }),
phases: {
select: async (task, runtime, context) => {
if (cutOffTooOften(task, runtime))
return failCutOff(runtime, task, context);
const { conversationId } = runtime;
const agent = await runtime.agent(context);
const settings = runtime.settings;
const ref = agent.model;
const model3 = ref === void 0 ? void 0 : runtime.models.getModel(ref.provider, ref.modelId);
if (ref === void 0 || model3 === void 0)
return failNoModel2(runtime, ref, context);
const policy = compactionPolicy(settings, ref);
const view2 = await runtime.context(conversationId, context);
const cut = selectCut(view2, policy.keepRecentTokens);
if (cut === void 0)
return complete(runtime, context);
const firstKept = view2.entries[cut].id;
const { reason, instructions } = task.input;
const compaction = {
reason,
entries: view2.entries.slice(0, cut),
messages: summarizedMessages(view2, cut),
firstKept,
...instructions === void 0 ? {} : { instructions }
};
let decision;
await runtime.hooks.each("beforeCompact", async (hook) => {
if (decision === void 0)
decision = await hook(compaction, runtime, context);
});
if (decision !== void 0 && "decline" in decision)
return complete(runtime, context);
if (decision !== void 0)
return place(runtime, firstKept, decision.summary, context);
const request2 = {
attempt: 1,
model: ref,
thinkingLevel: agent.thinkingLevel,
streamOptions: settings.stream,
maxTokens: Math.min(Math.floor(0.8 * policy.reserveTokens), model3.maxTokens > 0 ? model3.maxTokens : Number.POSITIVE_INFINITY),
tail: view2.entries.reduce((tail, entry2) => entry2.id > tail ? entry2.id : tail, firstKept),
firstKept
};
await runtime.commit(() => ({ status: "running", checkpoint: { phase: "summarize", ...request2 } }), context);
},
summarize: async (task, runtime, context) => {
if (cutOffTooOften(task, runtime))
return failCutOff(runtime, task, context);
const { phase: _, ...request2 } = task.state.checkpoint;
const { model: ref, thinkingLevel, streamOptions, maxTokens, tail, firstKept, attempt } = request2;
const model3 = runtime.models.getModel(ref.provider, ref.modelId);
if (model3 === void 0)
return failNoModel2(runtime, ref, context);
const view2 = await runtime.context(runtime.conversationId, context, { at: tail });
const cut = view2.entries.findIndex((entry2) => entry2.id === firstKept);
const now = runtime.now();
const messages = [
{ role: "system", content: SUMMARIZATION_SYSTEM_PROMPT, timestamp: now },
{
role: "user",
content: [{ type: "text", text: summaryPrompt(summarizedMessages(view2, cut), task.input.instructions) }],
timestamp: now
}
];
const { deferred: _deferred, ...forwarded } = streamOptions;
const options = {
...forwarded,
cacheRetention: "none",
maxTokens,
signal: runtime.signal,
telemetry: context.telemetry,
sessionId: await ensureProviderSessionId(runtime, context),
...thinkingLevel === "off" ? {} : { reasoning: thinkingLevel }
};
const message = await runtime.models.completeSimple(model3, { messages }, options);
runtime.signal.throwIfAborted();
const summary = summaryText(message);
const policy = runtime.settings.retry;
const retry = message.stopReason === "error" && isRetryableAssistantError(message) && policy.enabled && attempt <= policy.maxRetries;
const until = retry ? runtime.now() + retryDelayMs(policy, attempt) : 0;
await runtime.commit(async (tx, current) => {
await recordUsage(tx, runtime.conversationId, "models", `${message.provider}/${message.model}`, message.usage);
const live = await tx.doc(LiveDoc, runtime.conversationId);
if (summary !== void 0)
return placeSummary(tx, runtime, current, live, firstKept, summary);
if (retry) {
const status = compactionStatus(live, runtime.taskId);
if (status !== void 0)
status.retry = { at: until, error: message.errorMessage ?? "" };
const checkpoint = { phase: "retry", ...request2, until };
return { status: "sleeping", checkpoint, until };
}
const text2 = summaryFailure(message);
failCompactionStatus(live, runtime.taskId, text2);
return {
status: "terminal",
outcome: { status: "failed", error: { message: text2, detail: { reason: "model_error" } } }
};
}, context);
},
/** After the backoff's sleep; a run before `until` (an early wake, or a record of an earlier version) sleeps again. */
retry: async (task, runtime, context) => {
const { phase: _, until, ...request2 } = task.state.checkpoint;
if (cutOffTooOften(task, runtime))
return failCutOff(runtime, task, context);
if (until > runtime.now())
return runtime.sleepUntil(until, task.state.checkpoint, context);
const attempt = request2.attempt + 1;
await runtime.commit(async (tx) => {
const status = compactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);
if (status !== void 0) {
status.attempt = attempt;
delete status.retry;
}
return { status: "running", checkpoint: { phase: "summarize", ...request2, attempt } };
}, context);
}
},
abort: async (_task, runtime, context) => {
await runtime.commit(async (tx) => {
removeCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);
return { status: "terminal", outcome: { status: "aborted" } };
}, context);
}
});
async function createCompaction(tx, conversationId, input, owner) {
const ownership = owner === void 0 ? { kind: "conversation" } : { kind: "task", taskId: owner };
const background = owner === void 0 && input.reason !== "manual";
const taskId = await tx.createTask(CompactionTask, input, { ownership, conversationId, background });
const status = { taskId, trigger: input.reason, blocking: owner !== void 0, attempt: 1 };
addCompactionStatus(await tx.doc(LiveDoc, conversationId), status);
return taskId;
}
function compactionPolicy(settings, model3) {
const { modelOverrides, ...policy } = settings.compaction;
const override = modelOverrides?.[`${model3.provider}/${model3.modelId}`];
return {
enabled: override?.enabled ?? policy.enabled,
reserveTokens: override?.reserveTokens ?? policy.reserveTokens,
keepRecentTokens: override?.keepRecentTokens ?? policy.keepRecentTokens,
backgroundTokens: override?.backgroundTokens ?? policy.backgroundTokens
};
}
function selectCut(view2, keepRecentTokens) {
const { contributions } = view2;
const start = view2.head === void 0 ? 0 : 1;
const candidates = [];
for (let index = start; index < contributions.length; index++) {
if (isCandidate(contributions, index))
candidates.push(index);
}
let kept = 0;
let cut;
for (let index = contributions.length - 1; index >= start; index--) {
for (const message of contributions[index])
kept += estimateMessageTokens(message);
if (kept < keepRecentTokens)
continue;
cut = candidates.find((candidate) => candidate >= index) ?? candidates.at(-1);
break;
}
if (cut === void 0)
return void 0;
for (let index = start; index < cut; index++)
if (contributions[index].length > 0)
return cut;
return void 0;
}
function isCandidate(contributions, index) {
const first = contributions[index][0];
if (first?.role === "assistant")
return true;
if (first?.role !== "user")
return false;
let calls = /* @__PURE__ */ new Set();
for (let before = index - 1; before >= 0; before--) {
const assistant = contributions[before].findLast((message) => message.role === "assistant");
if (assistant === void 0)
continue;
calls = new Set(assistant.content.flatMap((content) => content.type === "toolCall" ? [content.id] : []));
break;
}
if (calls.size === 0)
return true;
for (let after = index; after < contributions.length; after++) {
for (const [position, message] of contributions[after].entries()) {
if (message.role === "assistant" && (after > index || position > 0))
return true;
if (message.role === "toolResult" && calls.has(message.toolCallId))
return false;
}
}
return true;
}
function summarizedMessages(view2, cut) {
return orderToolResults(view2.contributions.slice(0, cut).flat());
}
function estimateContext(view2, extra) {
let measured;
const after = view2.head?.id ?? Number.NEGATIVE_INFINITY;
for (let index = view2.entries.length - 1; index >= 0 && measured === void 0; index--) {
if (view2.entries[index].id <= after)
continue;
measured = view2.contributions[index].findLast((message) => message.role === "assistant" && calculateContextTokens(message.usage) > 0);
}
const from = measured === void 0 ? 0 : view2.messages.lastIndexOf(measured) + 1;
let tokens = measured === void 0 ? 0 : calculateContextTokens(measured.usage);
for (const message of view2.messages.slice(from))
tokens += estimateMessageTokens(message);
for (const message of extra)
tokens += estimateMessageTokens(message);
return tokens;
}
function summaryText(message) {
if (message.stopReason !== "stop" || message.content.some((content) => content.type === "toolCall"))
return void 0;
const text2 = message.content.flatMap((content) => content.type === "text" ? [content.text] : []).join("\n").trim();
return text2.length === 0 ? void 0 : text2;
}
function summaryFailure(message) {
if (message.stopReason === "error" || message.stopReason === "aborted") {
return `Summarization failed: ${message.errorMessage ?? message.stopReason}`;
}
if (message.stopReason === "length")
return "Summarization hit the token limit; the summary is incomplete";
if (message.content.some((content) => content.type === "toolCall"))
return "Summarization attempted to call a tool";
return "Summarization produced no text";
}
function summaryPrompt(messages, instructions) {
const focus = instructions === void 0 ? "" : `
Additional focus: ${instructions}`;
return `<conversation>
${serializeConversation(messages)}
</conversation>
${SUMMARIZATION_PROMPT}${focus}`;
}
function serializeConversation(messages) {
const parts = [];
for (const message of messages) {
if (message.role === "user") {
const text2 = contentText2(message.content);
if (text2.length > 0)
parts.push(`[User]: ${text2}`);
} else if (message.role === "assistant") {
const text2 = message.content.flatMap((content) => content.type === "text" ? [content.text] : []);
const calls = message.content.flatMap((content) => content.type === "toolCall" ? [
`${content.name}(${Object.entries(content.arguments).map(([key, value2]) => `${key}=${JSON.stringify(value2)}`).join(", ")})`
] : []);
if (text2.length > 0)
parts.push(`[Assistant]: ${text2.join("\n")}`);
if (calls.length > 0)
parts.push(`[Assistant tool calls]: ${calls.join("; ")}`);
} else if (message.role === "toolResult") {
const text2 = contentText2(message.content);
if (text2.length > 0)
parts.push(`[Tool result]: ${truncate(text2, TOOL_RESULT_MAX_CHARS)}`);
}
}
return parts.join("\n\n");
}
function contentText2(content) {
if (typeof content === "string")
return content;
return content.flatMap((block) => block.type === "text" && block.text !== void 0 ? [block.text] : []).join("\n");
}
function truncate(text2, maxChars) {
if (text2.length <= maxChars)
return text2;
return `${text2.slice(0, maxChars)}
[... ${text2.length - maxChars} more characters truncated]`;
}
async function place(runtime, firstKept, summary, context) {
await runtime.commit(async (tx, current) => placeSummary(tx, runtime, current, await tx.doc(LiveDoc, runtime.conversationId), firstKept, summary), context);
}
async function placeSummary(tx, runtime, current, live, firstKept, summary) {
removeCompactionStatus(live, runtime.taskId);
delete live.compactionFailure;
const text2 = `${SUMMARY_PREFIX}${summary}${SUMMARY_SUFFIX}`;
const entry2 = {
kind: CompactionEntry.kind,
head: firstKept,
model: [{ role: "user", content: [{ type: "text", text: text2 }], timestamp: runtime.now() }],
data: { reason: current.input.reason }
};
const result = current.owner === void 0 ? {
submissionId: (await admitSubmission(tx, runtime.conversationId, { type: "write", requestId: `compaction:${runtime.taskId}`, entry: entry2 }, runtime.now(), runtime.settings)).id
} : { entryId: (await tx.appendEntry(runtime.conversationId, entry2)).id };
return { status: "terminal", outcome: { status: "completed", result } };
}
async function complete(runtime, context) {
await runtime.commit(async (tx) => {
removeCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId);
return { status: "terminal", outcome: { status: "completed", result: {} } };
}, context);
}
async function failCutOff(runtime, task, context) {
const message = `Compaction was interrupted ${cutOffCount(task)}`;
await runtime.commit(async (tx) => {
failCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId, message);
return {
status: "terminal",
outcome: { status: "failed", error: { message, detail: { reason: "restart_limit" } } }
};
}, context);
}
async function failNoModel2(runtime, ref, context) {
const message = ref === void 0 ? "No model is configured" : `Model ${ref.provider}/${ref.modelId} is not available`;
await runtime.commit(async (tx) => {
failCompactionStatus(await tx.doc(LiveDoc, runtime.conversationId), runtime.taskId, message);
return { status: "terminal", outcome: { status: "failed", error: { message, detail: { reason: "no_model" } } } };
}, context);
}
// node_modules/@earendil-works/pi-durable/dist/harness/define.js
function defineExtension(extension) {
return extension;
}
function defineTool(tool) {
return tool;
}
// node_modules/@earendil-works/pi-durable/dist/harness/harness.js
init_identity();
init_dist();
// node_modules/@earendil-works/pi-durable/dist/harness/registry.js
var SECTION_KEY = /^[a-z][a-z0-9_-]*$/;
var BUILTIN_TASKS = [GenerationTask, ToolTask, CompactionTask];
var RegistryState = class {
#extensions;
#byName;
#tasks;
constructor(extensions) {
this.#extensions = extensions;
this.#byName = new Map(extensions.map((extension) => [extension.name, extension]));
const tasks = /* @__PURE__ */ new Map();
for (const task of BUILTIN_TASKS)
tasks.set(task.definition.name, task);
for (const extension of extensions) {
for (const task of extension.tasks ?? []) {
const name = task.definition.name;
if (tasks.has(name))
throw new Error(`Task ${name} of extension ${extension.name} is already installed`);
tasks.set(name, task);
}
}
this.#tasks = tasks;
}
installed() {
return this.#extensions;
}
extension(name) {
return this.#byName.get(name);
}
tools() {
return this.#extensions.flatMap((extension) => (extension.tools ?? []).map((tool) => ({ extension, tool })));
}
sections() {
return this.#extensions.flatMap((extension) => (extension.sections ?? []).map((section) => ({ extension, section })));
}
tasks() {
return [...this.#tasks.values()];
}
task(name) {
return this.#tasks.get(name);
}
};
var RegistryImpl = class {
#current = new RegistryState([]);
#listeners = /* @__PURE__ */ new Set();
snapshot() {
return this.#current;
}
subscribe(listener) {
this.#listeners.add(listener);
return () => this.#listeners.delete(listener);
}
install(extension) {
validateExtension(extension);
const current = this.#current.installed();
const index = current.findIndex((installed) => installed.name === extension.name);
const next = index < 0 ? [...current, extension] : current.map((installed, at) => at === index ? extension : installed);
this.#publish(next);
}
uninstall(extension) {
const current = this.#current.installed();
if (!current.some((installed) => installed.name === extension.name))
return;
this.#publish(current.filter((installed) => installed.name !== extension.name));
}
/** Build and validate the next state, which throws on a task name collision, then publish it synchronously. */
#publish(extensions) {
this.#current = new RegistryState(extensions);
for (const listener of [...this.#listeners])
listener();
}
};
function validateExtension(extension) {
const tools = /* @__PURE__ */ new Set();
for (const tool of extension.tools ?? []) {
if (tools.has(tool.name))
throw new Error(`Extension ${extension.name} has two tools named ${tool.name}`);
tools.add(tool.name);
}
const sections = /* @__PURE__ */ new Set();
for (const { key } of extension.sections ?? []) {
if (!SECTION_KEY.test(key))
throw new TypeError(`Section key ${JSON.stringify(key)} must match ${SECTION_KEY}`);
if (key === INSTRUCTIONS_KEY)
throw new Error(`Section key ${key} is reserved for the agent's instructions`);
if (sections.has(key))
throw new Error(`Extension ${extension.name} has two sections with key ${key}`);
sections.add(key);
}
}
function createRegistry() {
return new RegistryImpl();
}
// node_modules/@earendil-works/pi-durable/dist/harness/task-graph.js
var LIVE_STATUSES2 = ["pending", "running", "waiting", "sleeping", "completing"];
var SCAN_PAGE_SIZE4 = 256;
var TaskGraphView = class {
#session;
#blocking;
#mount;
#closed = false;
constructor(session, blocking) {
this.#session = session;
this.#blocking = blocking;
session.followCommits((publication, context) => {
if (this.#mount === void 0 || publication.kind === "memory")
return;
advance(this.#mount, publication, context, blocking.blocked, (error) => session.report(error));
});
blocking.subscribeBlocked(() => this.#refreshBlocked());
session.subscribeClose(() => {
this.#closed = true;
const ends = closeEnds(this.#session.failure);
for (const observer of [...this.#mount?.observers ?? []]) {
contained(() => observer.end(closeEndOf(observer, ends)), (error) => session.report(error));
}
this.#mount = void 0;
});
}
/**
* Attach a synchronous observer of the graph (`Harness.observeTaskGraph()`), behind `guardObserver()`; `context`
* governs only the attachment.
*/
async observe(observer, context) {
let value2;
const attached = await this.#attach((current, release) => {
value2 = current;
return guardObserver(observer, release, (error) => this.#session.report(error));
}, context);
const signal = context.abortSignal;
if (signal?.aborted) {
attached.detach();
throw signal.reason;
}
return observation(value2, attached.observer);
}
/** A serialized watch of the graph, an observer of its mount; aborting `context` ends it `aborted`. */
async watch(context) {
const { observer } = await this.#attach((value2, release) => new Watch(value2, release, (error) => this.#session.report(error)), context);
const signal = context.abortSignal;
if (signal?.aborted) {
observer.abort();
throw signal.reason;
}
if (signal !== void 0)
observer.observeAbort(signal);
return observer;
}
/** Register an observer created from the current revision, atomically on the Session line. */
#attach(create, context) {
return this.#session.readOnLine(async (storage) => {
const mount = this.#mount ?? {
...await this.#build(storage, context),
observers: /* @__PURE__ */ new Set()
};
const detach = () => {
mount.observers.delete(observer);
if (mount.observers.size === 0 && this.#mount === mount)
this.#mount = void 0;
};
const observer = create(mount.value, detach);
if (this.#closed)
throw closedError(this.#session);
context.abortSignal?.throwIfAborted();
this.#mount = mount;
mount.observers.add(observer);
return { observer, detach };
});
}
/** On the Session line: derive every node's blocked reason again, and publish the ones that changed. */
#refreshBlocked() {
if (this.#mount === void 0 || this.#closed)
return;
this.#session.readOnLine(async () => {
const mount = this.#mount;
if (mount === void 0)
return;
const ops2 = [];
for (const [key, record] of mount.records) {
const blocked = this.#blocking.blocked(record);
if (blocked === mount.value.tasks[key]?.blocked)
continue;
ops2.push(blocked === void 0 ? ["d", ["tasks", key, "blocked"]] : ["s", ["tasks", key, "blocked"], blocked]);
}
publish(mount, ops2, BACKGROUND_CONTEXT, (error) => this.#session.report(error));
}).catch(() => {
});
}
/** Read the graph on the line, through the line's `storage`. */
async #build(storage, context) {
const tasks = {};
const live = /* @__PURE__ */ new Map();
const records = [];
for (const status of LIVE_STATUSES2) {
records.push(...await scanAll((cursor) => storage.scanTasks({ status }, SCAN_PAGE_SIZE4, cursor, context)));
}
records.sort((a, b) => a.id - b.id);
for (const record of records) {
const owned = await scanAll((cursor) => storage.scanConversations({ ownerTaskId: record.id }, SCAN_PAGE_SIZE4, cursor, context));
const conversations = owned.map((conversation) => conversation.id).sort((a, b) => a - b);
const subject = blockedSubject(record);
tasks[String(record.id)] = nodeOf2(record, conversations, this.#blocking.blocked(subject));
live.set(String(record.id), subject);
}
return { value: { tasks }, records: live };
}
};
function advance(mount, publication, context, blocked, report2) {
const ops2 = [];
const changed = /* @__PURE__ */ new Map();
const node = (key) => changed.has(key) ? changed.get(key) : mount.value.tasks[key];
for (const change of publication.changes) {
if (change.type !== "task")
continue;
const record = change.value;
const key = String(record.id);
const previous = node(key);
if (record.state.status === "terminal") {
mount.records.delete(key);
if (previous === void 0)
continue;
ops2.push(["d", ["tasks", key]]);
changed.set(key, void 0);
continue;
}
const subject = blockedSubject(record);
mount.records.set(key, subject);
const next = nodeOf2(record, previous?.conversations ?? [], blocked(subject));
if (previous !== void 0 && JSON.stringify(next) === JSON.stringify(previous))
continue;
ops2.push(["s", ["tasks", key], next]);
changed.set(key, next);
}
const created = /* @__PURE__ */ new Map();
for (const change of publication.changes) {
if (change.type !== "conversation" || change.value.owner === void 0)
continue;
const key = String(change.value.owner.taskId);
if (node(key) !== void 0)
created.set(key, [...created.get(key) ?? [], change.value.id]);
}
for (const [key, ids] of created) {
const conversations = [...node(key).conversations, ...ids].sort((a, b) => a - b);
ops2.push(["s", ["tasks", key, "conversations"], conversations]);
}
publish(mount, ops2, context, report2);
}
function publish(mount, ops2, context, report2) {
if (ops2.length === 0)
return;
mount.value = applyImmutable(mount.value, ops2);
const frameContext = withoutAbortSignal(context);
const call = { kind: "value", value: mount.value, ops: ops2, retired: false };
for (const observer of [...mount.observers])
contained(() => observer.advance(call, frameContext), report2);
}
function nodeOf2(record, conversations, blocked) {
return {
id: record.id,
kind: record.kind,
conversationId: record.conversationId,
...record.owner === void 0 ? {} : { owner: record.owner },
background: record.background,
abortRequested: record.abortRequested,
state: stateOf(record),
conversations,
...blocked === void 0 ? {} : { blocked }
};
}
function stateOf(record) {
const state2 = record.state;
switch (state2.status) {
case "pending":
case "running":
return { status: state2.status, phase: phaseOf(state2.checkpoint) };
case "waiting":
return { status: "waiting", phase: phaseOf(state2.checkpoint), on: [...state2.on], policy: state2.policy };
case "sleeping":
return { status: "sleeping", phase: phaseOf(state2.checkpoint), until: state2.until };
// Terminal records never reach here: they leave the graph.
case "completing":
case "terminal":
return { status: "completing", outcome: state2.outcome.status };
}
}
function phaseOf(checkpoint) {
return checkpoint.phase;
}
// node_modules/@earendil-works/pi-durable/dist/harness/view.js
var DEFAULT_WINDOW_MIN = 50;
var MOUNTED = [
AgentDoc,
LiveDoc,
InboxDoc,
ProviderDoc,
UsageDoc
];
var MOUNTED_KINDS = new Set(MOUNTED.map((token) => token.definition.kind));
var SCAN_PAGE_SIZE5 = 256;
var VIEWS = /* @__PURE__ */ new WeakMap();
function resolveWindow(window2) {
const min = window2?.min ?? DEFAULT_WINDOW_MIN;
if (!Number.isSafeInteger(min) || min < 1)
throw new RangeError(`Window min must be an integer >= 1, got ${min}`);
const max = window2?.max ?? 2 * min;
if (!Number.isSafeInteger(max) || max < min) {
throw new RangeError(`Window max must be an integer >= min (${min}), got ${max}`);
}
const from = window2?.from;
if (from !== void 0 && !Number.isSafeInteger(from)) {
throw new RangeError(`Window from must be an entry ID, got ${from}`);
}
return { from, min, max };
}
var ConversationViews = class {
#session;
#mounts = /* @__PURE__ */ new Map();
#closed = false;
constructor(session) {
this.#session = session;
VIEWS.set(session, this);
session.followCommits((publication, context) => {
for (const [id, mount] of this.#mounts)
advance2(id, mount, publication, context, (error) => this.report(error));
});
session.subscribeClose(() => {
this.#closed = true;
const ends = closeEnds(this.#session.failure);
for (const mount of this.#mounts.values())
for (const windowed of [...mount.observers]) {
contained(() => windowed.observer.end(closeEndOf(windowed.observer, ends)), (error) => this.report(error));
}
this.#mounts.clear();
});
}
/** Report an observer's listener error through the Harness. */
report(error) {
this.#session.report(error);
}
/**
* Attach a synchronous observer of the view (`Harness.observeConversation()`), behind `guardObserver()`; `context`
* governs only the attachment.
*/
async observe(id, observer, context, window2) {
let value2;
const attached = await this.attach(id, window2, (current, release) => {
value2 = current;
return guardObserver(observer, release, (error) => this.report(error));
}, context);
const signal = context.abortSignal;
if (signal?.aborted) {
attached.detach();
throw signal.reason;
}
return observation(value2, attached.observer);
}
/** A serialized watch of the view, an observer of its mount; aborting `context` ends it `aborted`. */
async watch(id, context, window2) {
const { observer } = await this.attach(id, window2, (value2, release) => new Watch(value2, release, (error) => this.#session.report(error)), context);
const signal = context.abortSignal;
if (signal?.aborted) {
observer.abort();
throw signal.reason;
}
if (signal !== void 0)
observer.observeAbort(signal);
return observer;
}
/**
* Register an observer created from its window's first revision, atomically on the Session line: it sees every later
* publication and nothing earlier. `release` drops it, and the mount with its last observer.
*/
async attach(id, window2, create, context) {
const bounds = resolveWindow(window2);
return this.#session.readOnLine(async (storage) => {
const mount = this.#mounts.get(id) ?? await this.#build(storage, id, context);
const { entries: entries2, before } = await loadWindow(storage, id, bounds, context);
const value2 = view(mount.conversation, entries2, before, mount.docs);
let windowed;
const detach = () => {
if (windowed !== void 0)
mount.observers.delete(windowed);
if (mount.observers.size === 0 && this.#mounts.get(id) === mount)
this.#mounts.delete(id);
};
const observer = create(value2, detach);
if (this.#closed)
throw closedError(this.#session);
context.abortSignal?.throwIfAborted();
windowed = { min: bounds.min, max: bounds.max, value: value2, observer };
this.#mounts.set(id, mount);
mount.observers.add(windowed);
return { observer, detach };
});
}
/** Hydrate a mount on the line, through the line's `storage`. */
async #build(storage, id, context) {
const conversation = await storage.conversation(id, context);
if (conversation === void 0)
throw new Error(`Conversation ${id} does not exist`);
const docs = {};
const incarnations = /* @__PURE__ */ new Map();
for (const token of MOUNTED) {
const loaded = await this.#session.conversationDocumentOnLine(token, id, context);
if (loaded === void 0)
continue;
docs[token.definition.kind] = loaded.value;
incarnations.set(token.definition.kind, { id: loaded.record.id, version: loaded.version });
}
return { conversation, docs, incarnations, observers: /* @__PURE__ */ new Set() };
}
};
function view(conversation, entries2, before, docs) {
return before === void 0 ? { conversation, entries: entries2, docs } : { conversation, entries: entries2, before, docs };
}
async function loadWindow(storage, conversationId, bounds, context) {
const { from, min, max } = bounds;
if (from !== void 0) {
const since = await scanUpTo(storage, { conversationId, minEntryId: from, order: "ascending" }, max + 1, context);
if (since.length <= max) {
const query = { conversationId, maxEntryId: idFromNumber(from - 1) };
const previous = (await storage.scanEntries(query, 1, void 0, context)).items[0];
return { entries: since, before: previous?.id };
}
}
const newest = await scanUpTo(storage, { conversationId }, min + 1, context);
const before = newest.length > min ? newest.pop().id : void 0;
return { entries: newest.reverse(), before };
}
async function scanUpTo(storage, query, limit2, context) {
const entries2 = [];
let cursor;
do {
const page2 = await storage.scanEntries(query, Math.min(SCAN_PAGE_SIZE5, limit2 - entries2.length), cursor, context);
entries2.push(...page2.items);
cursor = page2.next;
} while (cursor !== void 0 && entries2.length < limit2);
return entries2;
}
function advance2(id, mount, publication, context, report2) {
const docOps = [];
const appended = [];
for (const change of publication.changes) {
if (change.type === "entry" && change.value.conversationId === id) {
appended.push(change.value);
continue;
}
if (change.type !== "document" || change.conversationId !== id)
continue;
const kind = change.record.kind;
if (!MOUNTED_KINDS.has(kind) || change.record.key !== void 0)
continue;
const path3 = ["docs", kind];
const mounted = mount.incarnations.get(kind);
if (change.kind === "retire") {
if (mounted?.id !== change.record.id)
continue;
mount.incarnations.delete(kind);
docOps.push(["d", path3]);
} else if (mounted?.id === change.record.id && mounted.version === change.version) {
for (const op2 of change.ops)
docOps.push(prefixed(op2, path3));
} else {
mount.incarnations.set(kind, { id: change.record.id, version: change.version });
docOps.push(["s", path3, change.value]);
}
}
if (docOps.length === 0 && appended.length === 0)
return;
if (docOps.length > 0)
mount.docs = applyImmutable({ docs: mount.docs }, docOps).docs;
const frameContext = withoutAbortSignal(context);
const inserted = appended;
for (const windowed of [...mount.observers]) {
const previous = windowed.value;
let entries2 = previous.entries;
let before = previous.before;
let ops2 = docOps;
if (appended.length > 0) {
ops2 = [...docOps, ["p", ["entries"], entries2.length, 0, inserted]];
entries2 = entries2.concat(appended);
if (entries2.length > windowed.max) {
const drop = entries2.length - windowed.min;
before = entries2[drop - 1].id;
entries2 = entries2.slice(drop);
ops2.push(["p", ["entries"], 0, drop, []], ["s", ["before"], before]);
}
}
windowed.value = view(mount.conversation, entries2, before, mount.docs);
const call = { kind: "value", value: windowed.value, ops: ops2, retired: false };
contained(() => windowed.observer.advance(call, frameContext), report2);
}
}
function prefixed(op2, prefix) {
const at = (path3) => [...prefix, ...path3];
switch (op2[0]) {
case "r":
return ["s", prefix, op2[1]];
case "p":
return ["p", at(op2[1]), op2[2], op2[3], op2[4]];
case "m":
return ["m", at(op2[1]), op2[2]];
case "s":
return ["s", at(op2[1]), op2[2]];
case "d":
return ["d", at(op2[1])];
case "a":
return ["a", at(op2[1]), op2[2]];
case "t":
return ["t", at(op2[1]), op2[2]];
}
}
// node_modules/@earendil-works/pi-durable/dist/harness/harness.js
var SCAN_PAGE_SIZE6 = 256;
var SCHEDULER_INDEX_SIZES = /* @__PURE__ */ Symbol.for("pi-durable.schedulerIndexSizes");
var SCHEDULER_IDLE_STATE = /* @__PURE__ */ Symbol.for("pi-durable.schedulerIdleState");
var ConversationImpl = class {
id;
#host;
constructor(id, host) {
this.id = id;
this.#host = host;
}
agent(context) {
return this.#host.harness.resolveAgent(this.id, void 0, context);
}
configure(change, context) {
return this.#host.harness.commitWith((tx) => configure(tx, this.id, change), context);
}
submit(first, second) {
if ("type" in first)
return this.#host.submissions.submit(this.id, first, second);
return this.#host.submissions.admit(first, this.id, second);
}
async compact(instructions, context) {
this.#host.tasks.resume();
const input = { reason: "manual", ...instructions === void 0 ? {} : { instructions } };
return this.#host.harness.commitWith((tx) => createCompaction(tx, this.id, input), context);
}
async reset(handoff, context) {
const model3 = handoff === void 0 ? {} : { model: [{ role: "user", content: handoff, timestamp: this.#host.now() }] };
const entry2 = { kind: ResetEntry.kind, head: "self", ...model3 };
await this.#host.submissions.submit(this.id, { type: "write", entry: entry2 }, context);
}
commit(change, context, options) {
return this.#host.harness.commitWith(change, context, { conversationId: this.id }, options);
}
context(context, options) {
return readContext(this.#host.harness, this.#host.storage, this.id, context, options?.at);
}
entries(query, limit2, cursor, context) {
const scan = conversationEntries(this.id, query);
return this.#host.harness.readOnLine((storage) => storage.scanEntries(scan, limit2, cursor, context));
}
fork(at, options, context) {
return this.#host.create({ kind: "fork", parentId: this.id, at, ownership: options.ownership }, options, context);
}
async abort(context, options) {
this.#host.tasks.resume();
return this.#host.tasks.abortConversation(this.id, options?.background === true, context);
}
async waitForIdle(context) {
this.#host.tasks.resume();
return this.#host.tasks.waitForIdle(this.id, context);
}
watch(context, window2) {
return this.#host.views.watch(this.id, context, window2);
}
};
var DEFAULT_HARNESS_IDENTITY = { attribution: PI_ATTRIBUTION };
function currentModels(models2, identity) {
const merged = mergeClientIdentity(DEFAULT_HARNESS_IDENTITY, identity) ?? DEFAULT_HARNESS_IDENTITY;
if (typeof models2 === "function")
return () => withClientIdentity(models2(), merged);
const wrapped = withClientIdentity(models2, merged);
return () => wrapped;
}
function currentSettings(settings) {
return typeof settings === "function" ? settings : () => settings;
}
var HarnessImpl = class extends SessionImpl {
#options;
#hostSettings;
#report;
#host;
#tasks;
#submissions;
#taskGraph;
constructor(rawStorage, options, context) {
const report2 = safeReport(options.onReport, options.telemetry ?? NOOP_TELEMETRY_CONTEXT);
const now = safeNow(options.now, report2);
const hostSettings = currentSettings(options.settings);
super(rawStorage, now, () => hostSettings()?.documentRetentionMs, options.setTimer, options.readOnly === true, () => hostSettings()?.progress?.persistWithinMs);
const storage = this.storage;
this.#options = options;
this.#report = report2;
this.#hostSettings = hostSettings;
const settings = () => resolveSettings(hostSettings());
this.#tasks = new TaskScheduler({
telemetry: options.telemetry,
session: this,
storage,
registry: options.registry,
models: currentModels(options.models, options.identity),
agent: (id, snapshot, callContext) => this.resolveAgent(id, snapshot, callContext),
settings,
env: (id, callContext) => this.buildEnv(id, callContext),
now,
onWake: options.onWake,
timers: hostTimers(options.setTimer, (error) => report2(error, { kind: "host_error", callback: "setTimer" })),
writeAtClose: (writes) => this.writeAtClose(writes),
report: this.#report,
limitsRestarts: (kind) => LIMITS_RESTARTS.has(kind),
settleOutcome: settleSchedulerOutcome,
withdrawInputs: withdrawQueuedInputs,
conversation: async (id, binding, callContext) => {
const record = await this.readOnLine((line) => line.conversation(id, callContext));
return record === void 0 ? void 0 : boundConversation(id, binding, this.#submissions, this.#tasks);
},
context: withoutAbortSignal(context),
readOnly: options.readOnly === true
});
this.#submissions = new Submissions(this, now, settings, () => this.#tasks.resume(), options.telemetry);
this.#taskGraph = new TaskGraphView(this, {
blocked: (record) => this.#tasks.blockedReason(record),
subscribeBlocked: (listener) => this.#tasks.subscribeBlocked(listener)
});
this.#host = {
harness: this,
storage,
tasks: this.#tasks,
submissions: this.#submissions,
views: new ConversationViews(this),
now,
create: (target, createOptions, context2) => this.#create(target, createOptions, context2)
};
}
/** Resolve a conversation's committed `pi.agent` against `snapshot`, or the current one, and the current settings. */
async resolveAgent(id, snapshot, context) {
const registry2 = snapshot ?? this.#options.registry.snapshot();
const state2 = await this.snapshot(AgentDoc, id, context);
return resolveAgent(state2, registry2, resolveSettings(this.#hostSettings()), (error, extension) => this.#report(error, { kind: "extension_error", conversationId: id, extension }, context));
}
/** Build a conversation's environment from its current `cwd`; `undefined` without an `env` option. */
async buildEnv(id, context) {
const build = this.#options.env;
if (build === void 0)
return void 0;
const cwd = (await this.snapshot(AgentDoc, id, context))?.cwd;
return build({ conversationId: id, ...cwd === void 0 ? {} : { cwd }, read: this }, context);
}
/** Reconcile surviving `running` tasks to `pending`; part of open. */
openTasks(context) {
return this.#tasks.open(context);
}
resume() {
this.assertUsable();
this.#tasks.resume();
}
wake() {
this.assertUsable();
return this.#tasks.wake();
}
getTask(id, context) {
return this.readOnLine((storage) => storage.task(id, context));
}
/** Internal, for tests: sizes of the scheduler's ownership indexes. */
get [SCHEDULER_INDEX_SIZES]() {
return this.#tasks.indexSizes;
}
/** Internal, for tests: the kept contexts' idle state and its disagreements with a full recompute. */
get [SCHEDULER_IDLE_STATE]() {
return this.#tasks.idleState;
}
inspect(context) {
return this.readOnLine(async (storage) => {
const { scheduling, tasks } = await this.#tasks.inspect(this.#options.registry.snapshot());
const scan = (status) => scanAll((cursor) => storage.scanSubmissions({ status }, SCAN_PAGE_SIZE6, cursor, context));
const submissions = [...await scan("queued"), ...await scan("placed")].sort((a, b) => a.id - b.id);
return { scheduling, tasks, submissions };
});
}
submission(id, context) {
return this.#submissions.get(id, context);
}
abortSubmission(id, context, conversationId) {
return this.#submissions.abort(id, context, conversationId);
}
abortTask(id, context) {
return this.#tasks.abort(id, context);
}
async waitForTask(id, context) {
this.#tasks.resume();
return this.#tasks.waitForTask(id, context);
}
async waitForIdle(context) {
this.#tasks.resume();
return this.#tasks.waitForIdle(void 0, context);
}
/** Sum every conversation's committed `pi.usage`. Each document is read at its own point; totals only grow. */
async usage(context) {
const conversations = await this.readOnLine((storage) => scanAll((cursor) => storage.scanConversations({}, SCAN_PAGE_SIZE6, cursor, context)));
const total = UsageDoc.definition.initial();
for (const { id } of conversations) {
const state2 = await this.snapshot(UsageDoc, id, context);
if (state2 !== void 0)
addUsageState(total, state2);
}
return total;
}
watchTaskGraph(context) {
return this.#taskGraph.watch(context);
}
async observeTaskGraph(observer, context) {
this.assertUsable();
return this.#taskGraph.observe(observer, context);
}
async observeConversation(id, observer, context, window2) {
this.assertUsable();
return this.#host.views.observe(id, observer, context, window2);
}
root(context, options) {
return this.#create({ kind: "root" }, options ?? {}, context);
}
async conversation(id, context) {
this.assertUsable();
const record = await this.readOnLine((storage) => storage.conversation(id, context));
return record === void 0 ? void 0 : new ConversationImpl(record.id, this.#host);
}
createConversation(options, context) {
return this.#create({ kind: "independent", ownership: options.ownership }, options, context);
}
report(error, info = { kind: "listener_error" }, context) {
this.#report(error, info, context);
}
/** The ownership memberships a commit's task changes write, from the scheduler's index. */
membershipKeys(tx) {
return this.#tasks.membershipKeys(tx);
}
/** Signal and join task invocations after the close listeners and before Storage closes; writes no task outcome. */
beforeClose() {
return this.#tasks.join();
}
async #create(target, options, context) {
this.assertUsable();
const id = await this.commitWith(async (tx) => {
if (target.kind === "root" && await tx.conversation(ROOT_CONVERSATION_ID) !== void 0) {
return ROOT_CONVERSATION_ID;
}
const record = target.kind === "root" ? await tx.createRootConversation() : target.kind === "fork" ? await tx.forkConversation(target.parentId, target.at, { ownership: target.ownership }) : await tx.createConversation({ ownership: target.ownership });
if (options.agent !== void 0)
await configure(tx, record.id, options.agent);
if (options.init !== void 0)
await options.init(tx, record.id);
return record.id;
}, context);
return new ConversationImpl(id, this.#host);
}
/**
* The built-in creation hook, in every commit that creates or forks a conversation: empty `pi.live`, `pi.inbox`, and
* `pi.usage`, a fresh `pi.provider`, the conversation's `pi.agent` (see `createAgent()`), then
* `HarnessOptions.conversationCreated`.
*/
async conversationCreated(tx, record) {
await tx.doc(LiveDoc, record.id);
await tx.doc(InboxDoc, record.id);
await tx.doc(UsageDoc, record.id);
await tx.doc(ProviderDoc, record.id);
await createAgent(tx, record);
await this.#options.conversationCreated?.(tx, record);
}
};
function safeReport(onReport, telemetry) {
const reports = createTypedMetrics(telemetry.metrics ?? NOOP_TELEMETRY_METRICS, [DURABLE_TELEMETRY_SCHEMA]).counter("pi.durable.reports");
return (error, info, context) => {
if (onReport !== void 0) {
contained(() => onReport({ ...info, error }), () => {
});
}
const attributes = {
type: info.kind
};
switch (info.kind) {
case "task_faulted":
case "task_interrupted":
case "task_outdated":
attributes.reason = info.reason;
attributes.extension = info.extension;
attributes["task.id"] = info.task.id;
break;
case "migration_failed":
case "task_error":
case "extension_error":
attributes.extension = info.extension;
attributes["task.id"] = info.task?.id;
break;
case "host_error":
attributes["task.id"] = info.task?.id;
break;
}
try {
reports.add(1, { type: info.kind });
context?.telemetry.addEvent("pi.durable.report", attributes);
} catch {
}
};
}
function safeNow(now, report2) {
if (now === void 0)
return Date.now;
let reported = false;
return () => {
try {
return now();
} catch (error) {
if (!reported) {
reported = true;
report2(error, { kind: "host_error", callback: "now" });
}
return Date.now();
}
};
}
function boundConversation(id, binding, submissions, tasks) {
const bind = (context) => withAbortSignal(binding.signal, context);
const bound = (operation) => {
return async (context) => {
binding.check();
return operation(bind(context));
};
};
async function submit(first, second) {
binding.check();
if (!("type" in first)) {
binding.signal.throwIfAborted();
return submissions.admit(first, id, second);
}
const submission2 = await submissions.submit(id, first, bind(second));
return {
id: submission2.id,
status: bound((callContext) => submission2.status(callContext)),
wait: bound((callContext) => submission2.wait(callContext)),
abort: bound((callContext) => submission2.abort(callContext))
};
}
return {
id,
submit,
abort: async (context, options) => {
binding.check();
return tasks.abortConversation(id, options?.background === true, bind(context));
},
waitForIdle: bound((callContext) => tasks.waitForIdle(id, callContext))
};
}
var Harness = {
/** Open a Harness over storage. The registry may keep changing while the Harness runs. */
async open(storage, options, context) {
context.abortSignal?.throwIfAborted();
const snapshot = options.registry.snapshot();
const missing = BUILTIN_TASKS.filter((task) => snapshot.task(task.definition.name) === void 0);
if (missing.length > 0) {
const names2 = missing.map((task) => task.definition.name).join(", ");
throw new Error(`Registry lacks built-in tasks ${names2}; create it with createRegistry()`);
}
const harness2 = new HarnessImpl(storage, options, context);
try {
await harness2.openTasks(context);
} catch (error) {
await harness2.close(withoutAbortSignal(context)).catch(() => {
});
throw error;
}
return harness2;
}
};
// node_modules/@earendil-works/pi-durable/dist/storage/scan.js
function scanStart(requested, cursor, fallback) {
if (requested !== void 0 && requested !== "ascending" && requested !== "descending") {
throw new StorageRequestError(`Invalid scan order: ${String(requested)}`);
}
if (cursor === void 0)
return { order: requested ?? fallback, after: void 0 };
const { after, order: stored } = cursor;
if (typeof after !== "number" || !Number.isSafeInteger(after))
throw new StorageRequestError("Invalid storage cursor");
if (stored !== void 0 && stored !== "ascending" && stored !== "descending") {
throw new StorageRequestError("Invalid storage cursor");
}
const order = stored ?? fallback;
if (requested !== void 0 && requested !== order) {
throw new StorageRequestError(`The cursor continues a ${order} scan; the query asks for ${requested}`);
}
return { order, after };
}
function nextCursor(id, order) {
return { after: id, order };
}
// node_modules/@earendil-works/pi-durable/dist/tools/env.js
function requireEnv(api) {
if (api.env === void 0)
throw new Error("No execution environment is configured");
return api.env;
}
// node_modules/@earendil-works/pi-durable/dist/tools/bash.js
var MAX_TIMEOUT_SECONDS = 2147483647 / 1e3;
var bashSchema = obj({
command: str({ description: "Bash command to execute" }),
timeout: opt(num({ description: "Timeout in seconds (optional, no default timeout)" }))
}, { open: true });
var powershellSchema = obj({
command: str({ description: "PowerShell command to execute" }),
timeout: opt(num({ description: "Timeout in seconds (optional, no default timeout)" }))
}, { open: true });
var shellStructuredOutputSchema = obj({
output: str({ description: "Combined stdout and stderr: the retained tail, as the model sees it" }),
truncated: bool({ description: "Whether earlier output was dropped" }),
fullOutputPath: opt(str({ description: "File with the complete output, when it was spilled" })),
exitCode: num()
}, { open: true });
function validateTimeout(timeout) {
if (timeout === void 0)
return;
if (!Number.isFinite(timeout) || timeout <= 0) {
throw new Error("Invalid timeout: must be a finite number of seconds");
}
if (timeout > MAX_TIMEOUT_SECONDS) {
throw new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);
}
}
async function prepareExecution(command, options, api, context) {
const execution = {
command: options?.commandPrefix ? `${options.commandPrefix}
${command}` : command,
cwd: requireEnv(api).cwd,
env: {},
inheritEnv: true
};
await options?.prepare?.(execution, api, context);
return execution;
}
async function runCommand(commands, execution, timeout, api, context) {
const env = requireEnv(api);
let result;
for (const command of commands) {
result = await env.exec(command, {
cwd: execution.cwd,
env: execution.env,
inheritEnv: execution.inheritEnv,
...timeout === void 0 ? {} : { timeout },
onOutput: (text2, _context, info) => api.output(text2, info.skipped),
spill: { afterBytes: DEFAULT_MAX_BYTES, afterLines: DEFAULT_MAX_LINES },
// An environment may then omit output outside the retained tail and report the omission.
...api.outputWindow === void 0 ? {} : { window: api.outputWindow }
}, context);
if (result.ok || result.error.code !== "spawn_error")
break;
}
if (result === void 0)
throw new Error("No command to run");
const spillPath = result.ok ? result.value.spillPath : result.error.spillPath;
if (spillPath !== void 0) {
api.diagnostic({ severity: "info", code: "full_output", message: `Full output: ${spillPath}` });
}
if (!result.ok) {
if (result.error.code === "aborted" && context.abortSignal?.aborted)
throw result.error;
if (result.error.code === "timeout")
throw new Error(`Command timed out after ${timeout} seconds`);
if (result.error.code === "aborted")
throw new Error("Command aborted");
throw result.error;
}
const exitCode = result.value.exitCode;
const retained = api.retainedOutput();
const structuredOutput = {
output: retained.text,
truncated: retained.truncated,
...spillPath === void 0 ? {} : { fullOutputPath: spillPath },
exitCode
};
if (exitCode === 0)
return { structuredOutput };
const exited = { severity: "error", code: "exit_code", message: `Command exited with code ${exitCode}` };
return { structuredOutput, isError: true, diagnostics: [exited] };
}
function createBashTool(options) {
return defineTool({
name: "bash",
description: `Execute a bash command in the current working directory. Returns combined stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,
parameters: bashSchema,
structuredOutputSchema: shellStructuredOutputSchema,
outputLimits: { retain: "tail" },
async execute(args, api, context) {
validateTimeout(args.timeout);
const execution = await prepareExecution(args.command, options, api, context);
return runCommand([execution.command], execution, args.timeout, api, context);
}
});
}
// node_modules/diff/libesm/diff/base.js
var Diff = class {
diff(oldStr, newStr, options = {}) {
let callback;
if (typeof options === "function") {
callback = options;
options = {};
} else if ("callback" in options) {
callback = options.callback;
}
const oldString = this.castInput(oldStr, options);
const newString = this.castInput(newStr, options);
const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
const newTokens = this.removeEmpty(this.tokenize(newString, options));
return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
}
diffWithOptionsObj(oldTokens, newTokens, options, callback) {
var _a5;
const done = (value2) => {
value2 = this.postProcess(value2, options);
if (callback) {
setTimeout(function() {
callback(value2);
}, 0);
return void 0;
} else {
return value2;
}
};
const newLen = newTokens.length, oldLen = oldTokens.length;
let editLength = 1;
let maxEditLength = newLen + oldLen;
if (options.maxEditLength != null) {
maxEditLength = Math.min(maxEditLength, options.maxEditLength);
}
const maxExecutionTime = (_a5 = options.timeout) !== null && _a5 !== void 0 ? _a5 : Infinity;
const abortAfterTimestamp = Date.now() + maxExecutionTime;
const bestPath = [{ oldPos: -1, lastComponent: void 0 }];
let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
}
let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
const execEditLength = () => {
for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
let basePath;
const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
if (removePath) {
bestPath[diagonalPath - 1] = void 0;
}
let canAdd = false;
if (addPath) {
const addPathNewPos = addPath.oldPos - diagonalPath;
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
}
const canRemove = removePath && removePath.oldPos + 1 < oldLen;
if (!canAdd && !canRemove) {
bestPath[diagonalPath] = void 0;
continue;
}
if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
basePath = this.addToPath(addPath, true, false, 0, options);
} else {
basePath = this.addToPath(removePath, false, true, 1, options);
}
newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
} else {
bestPath[diagonalPath] = basePath;
if (basePath.oldPos + 1 >= oldLen) {
maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
}
if (newPos + 1 >= newLen) {
minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
}
}
}
editLength++;
};
if (callback) {
(function exec() {
setTimeout(function() {
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
return callback(void 0);
}
if (!execEditLength()) {
exec();
}
}, 0);
})();
} else {
while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
const ret = execEditLength();
if (ret) {
return ret;
}
}
}
}
addToPath(path3, added, removed, oldPosInc, options) {
const last = path3.lastComponent;
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
return {
oldPos: path3.oldPos + oldPosInc,
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
};
} else {
return {
oldPos: path3.oldPos + oldPosInc,
lastComponent: { count: 1, added, removed, previousComponent: last }
};
}
}
extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
const newLen = newTokens.length, oldLen = oldTokens.length;
let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
newPos++;
oldPos++;
commonCount++;
if (options.oneChangePerToken) {
basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
}
}
if (commonCount && !options.oneChangePerToken) {
basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
}
basePath.oldPos = oldPos;
return newPos;
}
equals(left, right, options) {
if (options.comparator) {
return options.comparator(left, right);
} else {
return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
}
}
removeEmpty(array) {
const ret = [];
for (let i = 0; i < array.length; i++) {
if (array[i]) {
ret.push(array[i]);
}
}
return ret;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
castInput(value2, options) {
return value2;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
tokenize(value2, options) {
return Array.from(value2);
}
join(chars) {
return chars.join("");
}
postProcess(changeObjects, options) {
return changeObjects;
}
get useLongestToken() {
return false;
}
buildValues(lastComponent, newTokens, oldTokens) {
const components = [];
let nextComponent;
while (lastComponent) {
components.push(lastComponent);
nextComponent = lastComponent.previousComponent;
delete lastComponent.previousComponent;
lastComponent = nextComponent;
}
components.reverse();
const componentLen = components.length;
let componentPos = 0, newPos = 0, oldPos = 0;
for (; componentPos < componentLen; componentPos++) {
const component = components[componentPos];
if (!component.removed) {
if (!component.added && this.useLongestToken) {
let value2 = newTokens.slice(newPos, newPos + component.count);
value2 = value2.map(function(value3, i) {
const oldValue = oldTokens[oldPos + i];
return oldValue.length > value3.length ? oldValue : value3;
});
component.value = this.join(value2);
} else {
component.value = this.join(newTokens.slice(newPos, newPos + component.count));
}
newPos += component.count;
if (!component.added) {
oldPos += component.count;
}
} else {
component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
oldPos += component.count;
}
}
return components;
}
};
// node_modules/diff/libesm/diff/line.js
var LineDiff = class extends Diff {
constructor() {
super(...arguments);
this.tokenize = tokenize;
}
equals(left, right, options) {
if (options.ignoreWhitespace) {
if (!options.newlineIsToken || !left.includes("\n")) {
left = left.trim();
}
if (!options.newlineIsToken || !right.includes("\n")) {
right = right.trim();
}
} else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
if (left.endsWith("\n")) {
left = left.slice(0, -1);
}
if (right.endsWith("\n")) {
right = right.slice(0, -1);
}
}
return super.equals(left, right, options);
}
};
var lineDiff = new LineDiff();
function diffLines(oldStr, newStr, options) {
return lineDiff.diff(oldStr, newStr, options);
}
function tokenize(value2, options) {
if (options.stripTrailingCr) {
value2 = value2.replace(/\r\n/g, "\n");
}
const retLines = [], linesAndNewlines = value2.split(/(\n|\r\n)/);
if (!linesAndNewlines[linesAndNewlines.length - 1]) {
linesAndNewlines.pop();
}
for (let i = 0; i < linesAndNewlines.length; i++) {
const line = linesAndNewlines[i];
if (i % 2 && !options.newlineIsToken) {
retLines[retLines.length - 1] += line;
} else {
retLines.push(line);
}
}
return retLines;
}
// node_modules/diff/libesm/patch/create.js
var INCLUDE_HEADERS = {
includeIndex: true,
includeUnderline: true,
includeFileHeaders: true
};
var FILE_HEADERS_ONLY = {
includeIndex: false,
includeUnderline: false,
includeFileHeaders: true
};
function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
let optionsObj;
if (!options) {
optionsObj = {};
} else if (typeof options === "function") {
optionsObj = { callback: options };
} else {
optionsObj = options;
}
if (typeof optionsObj.context === "undefined") {
optionsObj.context = 4;
}
const context = optionsObj.context;
if (optionsObj.newlineIsToken) {
throw new Error("newlineIsToken may not be used with patch-generation functions, only with diffing functions");
}
if (!optionsObj.callback) {
return diffLinesResultToPatch(diffLines(oldStr, newStr, optionsObj));
} else {
const { callback } = optionsObj;
diffLines(oldStr, newStr, Object.assign(Object.assign({}, optionsObj), { callback: (diff) => {
const patch = diffLinesResultToPatch(diff);
callback(patch);
} }));
}
function diffLinesResultToPatch(diff) {
if (!diff) {
return;
}
diff.push({ value: "", lines: [] });
function contextLines(lines2) {
return lines2.map(function(entry2) {
return " " + entry2;
});
}
const hunks = [];
let oldRangeStart = 0, newRangeStart = 0, curRange = [], oldLine = 1, newLine = 1;
for (let i = 0; i < diff.length; i++) {
const current = diff[i], lines2 = current.lines || splitLines(current.value);
current.lines = lines2;
if (current.added || current.removed) {
if (!oldRangeStart) {
const prev = diff[i - 1];
oldRangeStart = oldLine;
newRangeStart = newLine;
if (prev) {
curRange = context > 0 ? contextLines(prev.lines.slice(-context)) : [];
oldRangeStart -= curRange.length;
newRangeStart -= curRange.length;
}
}
for (const line of lines2) {
curRange.push((current.added ? "+" : "-") + line);
}
if (current.added) {
newLine += lines2.length;
} else {
oldLine += lines2.length;
}
} else {
if (oldRangeStart) {
if (lines2.length <= context * 2 && i < diff.length - 2) {
for (const line of contextLines(lines2)) {
curRange.push(line);
}
} else {
const contextSize = Math.min(lines2.length, context);
for (const line of contextLines(lines2.slice(0, contextSize))) {
curRange.push(line);
}
const hunk = {
oldStart: oldRangeStart,
oldLines: oldLine - oldRangeStart + contextSize,
newStart: newRangeStart,
newLines: newLine - newRangeStart + contextSize,
lines: curRange
};
hunks.push(hunk);
oldRangeStart = 0;
newRangeStart = 0;
curRange = [];
}
}
oldLine += lines2.length;
newLine += lines2.length;
}
}
for (const hunk of hunks) {
for (let i = 0; i < hunk.lines.length; i++) {
if (hunk.lines[i].endsWith("\n")) {
hunk.lines[i] = hunk.lines[i].slice(0, -1);
} else {
hunk.lines.splice(i + 1, 0, "\\ No newline at end of file");
i++;
}
}
}
return {
oldFileName,
newFileName,
oldHeader,
newHeader,
hunks
};
}
}
function formatPatch(patch, headerOptions) {
if (!headerOptions) {
headerOptions = INCLUDE_HEADERS;
}
if (Array.isArray(patch)) {
if (patch.length > 1 && !headerOptions.includeFileHeaders) {
throw new Error("Cannot omit file headers on a multi-file patch. (The result would be unparseable; how would a tool trying to apply the patch know which changes are to which file?)");
}
return patch.map((p) => formatPatch(p, headerOptions)).join("\n");
}
const ret = [];
if (headerOptions.includeIndex && patch.oldFileName == patch.newFileName) {
ret.push("Index: " + patch.oldFileName);
}
if (headerOptions.includeUnderline) {
ret.push("===================================================================");
}
if (headerOptions.includeFileHeaders) {
ret.push("--- " + patch.oldFileName + (typeof patch.oldHeader === "undefined" ? "" : " " + patch.oldHeader));
ret.push("+++ " + patch.newFileName + (typeof patch.newHeader === "undefined" ? "" : " " + patch.newHeader));
}
for (let i = 0; i < patch.hunks.length; i++) {
const hunk = patch.hunks[i];
if (hunk.oldLines === 0) {
hunk.oldStart -= 1;
}
if (hunk.newLines === 0) {
hunk.newStart -= 1;
}
ret.push("@@ -" + hunk.oldStart + "," + hunk.oldLines + " +" + hunk.newStart + "," + hunk.newLines + " @@");
for (const line of hunk.lines) {
ret.push(line);
}
}
return ret.join("\n") + "\n";
}
function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
if (typeof options === "function") {
options = { callback: options };
}
if (!(options === null || options === void 0 ? void 0 : options.callback)) {
const patchObj = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
if (!patchObj) {
return;
}
return formatPatch(patchObj, options === null || options === void 0 ? void 0 : options.headerOptions);
} else {
const { callback } = options;
structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, Object.assign(Object.assign({}, options), { callback: (patchObj) => {
if (!patchObj) {
callback(void 0);
} else {
callback(formatPatch(patchObj, options.headerOptions));
}
} }));
}
}
function splitLines(text2) {
const hasTrailingNl = text2.endsWith("\n");
const result = text2.split("\n").map((line) => line + "\n");
if (hasTrailingNl) {
result.pop();
} else {
result.push(result.pop().slice(0, -1));
}
return result;
}
// node_modules/@earendil-works/pi-durable/dist/tools/edit-diff.js
function detectLineEnding(content) {
const crlfIdx = content.indexOf("\r\n");
const lfIdx = content.indexOf("\n");
if (lfIdx === -1)
return "\n";
if (crlfIdx === -1)
return "\n";
return crlfIdx < lfIdx ? "\r\n" : "\n";
}
function normalizeToLF(text2) {
return text2.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
}
function restoreLineEndings(text2, ending) {
return ending === "\r\n" ? text2.replace(/\n/g, "\r\n") : text2;
}
function normalizeForFuzzyMatch(text2) {
return text2.normalize("NFKC").split("\n").map((line) => line.trimEnd()).join("\n").replace(/[\u2018\u2019\u201A\u201B]/g, "'").replace(/[\u201C\u201D\u201E\u201F]/g, '"').replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212]/g, "-").replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, " ");
}
function splitLinesWithEndings(content) {
return content.match(/[^\n]*\n|[^\n]+/g) ?? [];
}
function getLineSpans(content) {
let offset = 0;
return splitLinesWithEndings(content).map((line) => {
const span = { start: offset, end: offset + line.length };
offset = span.end;
return span;
});
}
function getReplacementLineRange(lines2, replacement) {
const replacementStart = replacement.matchIndex;
const replacementEnd = replacement.matchIndex + replacement.matchLength;
let startLine = -1;
for (let i = 0; i < lines2.length; i++) {
const line = lines2[i];
if (replacementStart >= line.start && replacementStart < line.end) {
startLine = i;
break;
}
}
if (startLine === -1) {
throw new Error("Replacement range is outside the base content.");
}
let endLine = startLine;
while (endLine < lines2.length && lines2[endLine].end < replacementEnd) {
endLine++;
}
if (endLine >= lines2.length) {
throw new Error("Replacement range is outside the base content.");
}
return { startLine, endLine: endLine + 1 };
}
function applyReplacements(content, replacements, offset = 0) {
let result = content;
for (let i = replacements.length - 1; i >= 0; i--) {
const replacement = replacements[i];
const matchIndex = replacement.matchIndex - offset;
result = result.substring(0, matchIndex) + replacement.newText + result.substring(matchIndex + replacement.matchLength);
}
return result;
}
function applyReplacementsPreservingUnchangedLines(originalContent, baseContent, replacements) {
const originalLines = splitLinesWithEndings(originalContent);
const baseLines = getLineSpans(baseContent);
if (originalLines.length !== baseLines.length) {
throw new Error("Cannot preserve unchanged lines because the base content has a different line count.");
}
const groups = [];
const sortedReplacements = [...replacements].sort((a, b) => a.matchIndex - b.matchIndex);
for (const replacement of sortedReplacements) {
const range = getReplacementLineRange(baseLines, replacement);
const current = groups[groups.length - 1];
if (current && range.startLine < current.endLine) {
current.endLine = Math.max(current.endLine, range.endLine);
current.replacements.push(replacement);
continue;
}
groups.push({ ...range, replacements: [replacement] });
}
let originalLineIndex = 0;
let result = "";
for (const group of groups) {
result += originalLines.slice(originalLineIndex, group.startLine).join("");
const groupStartOffset = baseLines[group.startLine].start;
const groupEndOffset = baseLines[group.endLine - 1].end;
result += applyReplacements(baseContent.slice(groupStartOffset, groupEndOffset), group.replacements, groupStartOffset);
originalLineIndex = group.endLine;
}
result += originalLines.slice(originalLineIndex).join("");
return result;
}
function fuzzyFindText(content, oldText) {
const exactIndex = content.indexOf(oldText);
if (exactIndex !== -1) {
return {
found: true,
index: exactIndex,
matchLength: oldText.length,
usedFuzzyMatch: false,
contentForReplacement: content
};
}
const fuzzyContent = normalizeForFuzzyMatch(content);
const fuzzyOldText = normalizeForFuzzyMatch(oldText);
const fuzzyIndex = fuzzyContent.indexOf(fuzzyOldText);
if (fuzzyIndex === -1) {
return {
found: false,
index: -1,
matchLength: 0,
usedFuzzyMatch: false,
contentForReplacement: content
};
}
return {
found: true,
index: fuzzyIndex,
matchLength: fuzzyOldText.length,
usedFuzzyMatch: true,
contentForReplacement: fuzzyContent
};
}
function stripBom(content) {
return content.startsWith("\uFEFF") ? { bom: "\uFEFF", text: content.slice(1) } : { bom: "", text: content };
}
function countOccurrences(content, oldText) {
const fuzzyContent = normalizeForFuzzyMatch(content);
const fuzzyOldText = normalizeForFuzzyMatch(oldText);
return fuzzyContent.split(fuzzyOldText).length - 1;
}
function getNotFoundError(path3, editIndex, totalEdits) {
if (totalEdits === 1) {
return new Error(`Could not find the exact text in ${path3}. The old text must match exactly including all whitespace and newlines.`);
}
return new Error(`Could not find edits[${editIndex}] in ${path3}. The oldText must match exactly including all whitespace and newlines.`);
}
function getDuplicateError(path3, editIndex, totalEdits, occurrences) {
if (totalEdits === 1) {
return new Error(`Found ${occurrences} occurrences of the text in ${path3}. The text must be unique. Please provide more context to make it unique.`);
}
return new Error(`Found ${occurrences} occurrences of edits[${editIndex}] in ${path3}. Each oldText must be unique. Please provide more context to make it unique.`);
}
function getEmptyOldTextError(path3, editIndex, totalEdits) {
if (totalEdits === 1) {
return new Error(`oldText must not be empty in ${path3}.`);
}
return new Error(`edits[${editIndex}].oldText must not be empty in ${path3}.`);
}
function getNoChangeError(path3, totalEdits) {
if (totalEdits === 1) {
return new Error(`No changes made to ${path3}. The replacement produced identical content. This might indicate an issue with special characters or the text not existing as expected.`);
}
return new Error(`No changes made to ${path3}. The replacements produced identical content.`);
}
function applyEditsToNormalizedContent(normalizedContent, edits, path3) {
const normalizedEdits = edits.map((edit) => ({
oldText: normalizeToLF(edit.oldText),
newText: normalizeToLF(edit.newText)
}));
for (let i = 0; i < normalizedEdits.length; i++) {
if (normalizedEdits[i].oldText.length === 0) {
throw getEmptyOldTextError(path3, i, normalizedEdits.length);
}
}
const initialMatches = normalizedEdits.map((edit) => fuzzyFindText(normalizedContent, edit.oldText));
const usedFuzzyMatch = initialMatches.some((match) => match.usedFuzzyMatch);
const replacementBaseContent = usedFuzzyMatch ? normalizeForFuzzyMatch(normalizedContent) : normalizedContent;
const matchedEdits = [];
for (let i = 0; i < normalizedEdits.length; i++) {
const edit = normalizedEdits[i];
const matchResult = fuzzyFindText(replacementBaseContent, edit.oldText);
if (!matchResult.found) {
throw getNotFoundError(path3, i, normalizedEdits.length);
}
const occurrences = countOccurrences(replacementBaseContent, edit.oldText);
if (occurrences > 1) {
throw getDuplicateError(path3, i, normalizedEdits.length, occurrences);
}
matchedEdits.push({
editIndex: i,
matchIndex: matchResult.index,
matchLength: matchResult.matchLength,
newText: edit.newText
});
}
matchedEdits.sort((a, b) => a.matchIndex - b.matchIndex);
for (let i = 1; i < matchedEdits.length; i++) {
const previous = matchedEdits[i - 1];
const current = matchedEdits[i];
if (previous.matchIndex + previous.matchLength > current.matchIndex) {
throw new Error(`edits[${previous.editIndex}] and edits[${current.editIndex}] overlap in ${path3}. Merge them into one edit or target disjoint regions.`);
}
}
const baseContent = normalizedContent;
const newContent = usedFuzzyMatch ? applyReplacementsPreservingUnchangedLines(normalizedContent, replacementBaseContent, matchedEdits) : applyReplacements(replacementBaseContent, matchedEdits);
if (baseContent === newContent) {
throw getNoChangeError(path3, normalizedEdits.length);
}
return { baseContent, newContent };
}
function generateUnifiedPatch(path3, oldContent, newContent, contextLines = 4) {
return createTwoFilesPatch(path3, path3, oldContent, newContent, void 0, void 0, {
context: contextLines,
headerOptions: FILE_HEADERS_ONLY
});
}
function generateDiffString(oldContent, newContent, contextLines = 4) {
const parts = diffLines(oldContent, newContent);
const output = [];
const oldLines = oldContent.split("\n");
const newLines = newContent.split("\n");
const maxLineNum = Math.max(oldLines.length, newLines.length);
const lineNumWidth = String(maxLineNum).length;
let oldLineNum = 1;
let newLineNum = 1;
let lastWasChange = false;
let firstChangedLine;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
const raw = part.value.split("\n");
if (raw[raw.length - 1] === "") {
raw.pop();
}
if (part.added || part.removed) {
if (firstChangedLine === void 0) {
firstChangedLine = newLineNum;
}
for (const line of raw) {
if (part.added) {
const lineNum = String(newLineNum).padStart(lineNumWidth, " ");
output.push(`+${lineNum} ${line}`);
newLineNum++;
} else {
const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
output.push(`-${lineNum} ${line}`);
oldLineNum++;
}
}
lastWasChange = true;
} else {
const nextPartIsChange = i < parts.length - 1 && (parts[i + 1].added || parts[i + 1].removed);
const hasLeadingChange = lastWasChange;
const hasTrailingChange = nextPartIsChange;
if (hasLeadingChange && hasTrailingChange) {
if (raw.length <= contextLines * 2) {
for (const line of raw) {
const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
output.push(` ${lineNum} ${line}`);
oldLineNum++;
newLineNum++;
}
} else {
const leadingLines = raw.slice(0, contextLines);
const trailingLines = raw.slice(raw.length - contextLines);
const skippedLines = raw.length - leadingLines.length - trailingLines.length;
for (const line of leadingLines) {
const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
output.push(` ${lineNum} ${line}`);
oldLineNum++;
newLineNum++;
}
output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
oldLineNum += skippedLines;
newLineNum += skippedLines;
for (const line of trailingLines) {
const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
output.push(` ${lineNum} ${line}`);
oldLineNum++;
newLineNum++;
}
}
} else if (hasLeadingChange) {
const shownLines = raw.slice(0, contextLines);
const skippedLines = raw.length - shownLines.length;
for (const line of shownLines) {
const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
output.push(` ${lineNum} ${line}`);
oldLineNum++;
newLineNum++;
}
if (skippedLines > 0) {
output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
oldLineNum += skippedLines;
newLineNum += skippedLines;
}
} else if (hasTrailingChange) {
const skippedLines = Math.max(0, raw.length - contextLines);
if (skippedLines > 0) {
output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
oldLineNum += skippedLines;
newLineNum += skippedLines;
}
for (const line of raw.slice(skippedLines)) {
const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
output.push(` ${lineNum} ${line}`);
oldLineNum++;
newLineNum++;
}
} else {
oldLineNum += raw.length;
newLineNum += raw.length;
}
lastWasChange = false;
}
}
return { diff: output.join("\n"), firstChangedLine };
}
// node_modules/@earendil-works/pi-durable/dist/env/decode.js
function rangeDecoder() {
return new TextDecoder("utf-8", { ignoreBOM: true });
}
function startsWithBom(firstBytes) {
return firstBytes[0] === 239 && firstBytes[1] === 187 && firstBytes[2] === 191;
}
// node_modules/@earendil-works/pi-durable/dist/env/line-scan.js
var NEWLINE2 = 10;
var encoder2 = new TextEncoder();
function decodedBytes(text2) {
return text2 === "" ? 0 : encoder2.encode(text2).length;
}
var LineScanner = class {
#startLine;
#endLine;
#position = 0;
#newlines = 0;
#lineStart = 0;
#start;
#end;
#firstLineEnd;
#lastLineStart;
#selectedBytes = 0;
#firstLineBytes = 0;
#selection;
#firstLine;
/** The first bytes, held until it is known whether they are a byte-order mark. */
#head = [];
#bom = false;
/** `startLine` and `endLine` must be non-negative integers with `endLine > startLine`; `endLine` absent: to the end. */
constructor(startLine, endLine = Number.POSITIVE_INFINITY) {
if (!Number.isSafeInteger(startLine) || startLine < 0 || !(endLine > startLine)) {
throw new RangeError("Invalid line range");
}
if (endLine !== Number.POSITIVE_INFINITY && !Number.isSafeInteger(endLine))
throw new RangeError("Invalid line range");
this.#startLine = startLine;
this.#endLine = endLine;
if (startLine === 0)
this.#begin(0);
}
push(chunk) {
if (this.#head !== void 0) {
const take = Math.min(3 - this.#head.length, chunk.length);
this.#head.push(...chunk.subarray(0, take));
if (this.#head.length < 3)
return;
this.#releaseHead();
chunk = chunk.subarray(take);
}
this.#process(chunk);
}
#releaseHead() {
const head = Uint8Array.from(this.#head ?? []);
this.#head = void 0;
this.#bom = startsWithBom(head);
this.#process(head);
}
#process(chunk) {
const base = this.#position;
let from = 0;
for (let index = chunk.indexOf(NEWLINE2); index !== -1; index = chunk.indexOf(NEWLINE2, index + 1)) {
this.#feed(chunk, base, from, index);
const line = this.#newlines;
const position = base + index;
if (line === this.#startLine)
this.#endFirstLine(position);
if (line === this.#endLine - 1)
this.#endSelection(position);
this.#feed(chunk, base, index, index + 1);
from = index + 1;
this.#newlines++;
this.#lineStart = position + 1;
if (this.#newlines === this.#startLine)
this.#begin(this.#lineStart);
if (this.#newlines === this.#endLine - 1)
this.#lastLineStart = this.#lineStart;
}
this.#feed(chunk, base, from, chunk.length);
this.#position += chunk.length;
}
finish() {
if (this.#head !== void 0)
this.#releaseHead();
const size = this.#position;
if (this.#start === void 0) {
return {
newlines: this.#newlines,
start: size,
end: size,
firstLineEnd: size,
lastLineStart: size,
selectedBytes: 0,
firstLineBytes: 0
};
}
if (this.#firstLineEnd === void 0)
this.#endFirstLine(size);
if (this.#end === void 0)
this.#endSelection(size);
return {
newlines: this.#newlines,
start: this.#start,
end: this.#end ?? size,
firstLineEnd: this.#firstLineEnd ?? size,
// A selection that reaches past the last line ends with the last line.
lastLineStart: this.#lastLineStart ?? this.#lineStart,
selectedBytes: this.#selectedBytes,
firstLineBytes: this.#firstLineBytes
};
}
#begin(start) {
this.#start = start;
if (this.#startLine === this.#endLine - 1)
this.#lastLineStart = start;
this.#selection = rangeDecoder();
this.#firstLine = rangeDecoder();
}
#endFirstLine(position) {
this.#firstLineEnd = position;
if (this.#firstLine !== void 0)
this.#firstLineBytes += decodedBytes(this.#firstLine.decode());
this.#firstLine = void 0;
}
#endSelection(position) {
this.#end = position;
if (this.#selection !== void 0)
this.#selectedBytes += decodedBytes(this.#selection.decode());
this.#selection = void 0;
}
/** Feed `chunk[from, to)`, which starts at file offset `base`, to the decoders of the ranges still open. */
#feed(chunk, base, from, to) {
if (this.#bom && base + from < 3)
from = Math.min(to, 3 - base);
if (to <= from)
return;
const bytes2 = chunk.subarray(from, to);
if (this.#selection !== void 0) {
this.#selectedBytes += decodedBytes(this.#selection.decode(bytes2, { stream: true }));
}
if (this.#firstLine !== void 0) {
this.#firstLineBytes += decodedBytes(this.#firstLine.decode(bytes2, { stream: true }));
}
}
};
// node_modules/@earendil-works/pi-durable/dist/env/index.js
function getOrThrow(result) {
if (!result.ok)
throw result.error;
return result.value;
}
// node_modules/@earendil-works/pi-durable/dist/tools/file-mutation-queue.js
var queues = /* @__PURE__ */ new Map();
async function mutationKey(env, path3, context) {
const absolutePath = getOrThrow(await env.absolutePath(path3, context));
return `${env.id}\0${await canonical(env, absolutePath, context)}`;
}
async function canonical(env, absolutePath, context) {
const result = await env.canonicalPath(absolutePath, context);
if (result.ok)
return result.value;
if (result.error.code === "not_supported")
return absolutePath;
if (result.error.code !== "not_found")
throw result.error;
const parent = getOrThrow(await env.joinPath([absolutePath, ".."], context));
if (parent === absolutePath || !absolutePath.startsWith(parent))
return absolutePath;
const name = absolutePath.slice(parent.length + (/[/\\]$/.test(parent) ? 0 : 1));
return getOrThrow(await env.joinPath([await canonical(env, parent, context), name], context));
}
async function withFileMutationQueue(env, path3, fn, context) {
const key = await mutationKey(env, path3, context);
const previous = queues.get(key) ?? Promise.resolve();
let release = () => {
};
const done = new Promise((resolve2) => {
release = resolve2;
});
const tail = previous.then(() => done);
queues.set(key, tail);
await previous;
try {
return await fn();
} finally {
release();
if (queues.get(key) === tail)
queues.delete(key);
}
}
// node_modules/@earendil-works/pi-durable/dist/tools/path-utils.js
var UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
var NARROW_NO_BREAK_SPACE = "\u202F";
function normalizeToolPath(path3) {
const normalized = path3.replace(UNICODE_SPACES, " ");
return normalized.startsWith("@") ? normalized.slice(1) : normalized;
}
async function resolveToolPath(env, path3, context) {
return getOrThrow(await env.absolutePath(normalizeToolPath(path3), context));
}
async function resolveReadToolPath(env, path3, context) {
const resolved = await resolveToolPath(env, path3, context);
const variants = [
resolved,
resolved.replace(/ (AM|PM)\./gi, `${NARROW_NO_BREAK_SPACE}$1.`),
resolved.normalize("NFD"),
resolved.replace(/'/g, "\u2019"),
resolved.normalize("NFD").replace(/'/g, "\u2019")
];
for (const variant of new Set(variants)) {
if (getOrThrow(await env.exists(variant, context)))
return variant;
}
return resolved;
}
// node_modules/@earendil-works/pi-durable/dist/tools/edit.js
var replaceEditSchema = obj({
oldText: str({
description: "Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call."
}),
newText: str({ description: "Replacement text for this targeted edit." })
}, { open: true });
var editSchema = obj({
path: str({ description: "Path to the file to edit (relative or absolute)" }),
edits: arr(replaceEditSchema, {
description: "One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead."
})
}, { open: true });
function isSingleEditInput(value2) {
if (!value2 || typeof value2 !== "object" || Array.isArray(value2))
return false;
const edit = value2;
return typeof edit.oldText === "string" && typeof edit.newText === "string";
}
function prepareEditArguments(input) {
if (!input || typeof input !== "object" || Array.isArray(input))
return input;
const args = { ...input };
if (typeof args.edits === "string") {
try {
const parsed = JSON.parse(args.edits);
if (Array.isArray(parsed)) {
args.edits = parsed;
} else if (isSingleEditInput(parsed)) {
args.edits = [parsed];
}
} catch {
}
} else if (isSingleEditInput(args.edits)) {
args.edits = [args.edits];
}
const legacy = args;
if (typeof legacy.oldText !== "string" || typeof legacy.newText !== "string")
return legacy;
const edits = Array.isArray(legacy.edits) ? [...legacy.edits] : [];
edits.push({ oldText: legacy.oldText, newText: legacy.newText });
const { oldText: _oldText, newText: _newText, ...rest } = legacy;
return { ...rest, edits };
}
function validateEditInput(input) {
if (!Array.isArray(input.edits) || input.edits.length === 0) {
throw new Error("Edit tool input is invalid. edits must contain at least one replacement.");
}
return { path: input.path, edits: input.edits };
}
function editAccessError(path3, error) {
return new Error(`Could not edit file: ${path3}. Error code: ${error.code}.`, { cause: error });
}
function createEditTool() {
return defineTool({
name: "edit",
description: "Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.",
parameters: editSchema,
prepareArguments: prepareEditArguments,
async execute(args, api, context) {
const { path: path3, edits } = validateEditInput(args);
const env = requireEnv(api);
const absolutePath = await resolveToolPath(env, path3, context);
return withFileMutationQueue(env, absolutePath, async () => {
if (context.abortSignal?.aborted)
throw new Error("Operation aborted");
const info = await env.fileInfo(absolutePath, context);
if (!info.ok)
throw editAccessError(path3, info.error);
if (info.value.kind !== "file" && info.value.kind !== "symlink") {
throw new Error(`Could not edit file: ${path3}. Path is not a file.`);
}
const readResult = await env.readTextFile(absolutePath, context);
if (!readResult.ok)
throw editAccessError(path3, readResult.error);
if (context.abortSignal?.aborted)
throw new Error("Operation aborted");
const { bom, text: content } = stripBom(readResult.value);
const originalEnding = detectLineEnding(content);
const normalizedContent = normalizeToLF(content);
const { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path3);
if (context.abortSignal?.aborted)
throw new Error("Operation aborted");
const finalContent = bom + restoreLineEndings(newContent, originalEnding);
const writeResult = await env.writeFile(absolutePath, finalContent, context);
if (!writeResult.ok)
throw editAccessError(path3, writeResult.error);
if (context.abortSignal?.aborted)
throw new Error("Operation aborted");
const diffResult = generateDiffString(baseContent, newContent);
const details = {
diff: diffResult.diff,
patch: generateUnifiedPatch(path3, baseContent, newContent),
...diffResult.firstChangedLine === void 0 ? {} : { firstChangedLine: diffResult.firstChangedLine }
};
return {
output: [{ type: "text", text: `Successfully replaced ${edits.length} block(s) in ${path3}.` }],
details
};
}, context);
}
});
}
// node_modules/@earendil-works/pi-durable/dist/tools/image.js
var PNG_SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10];
var HEADER_BYTES = 32;
var BLOCK_BYTES = 64 * 1024;
async function detectSupportedImageMimeTypeOf(source) {
const header = await source.read(0, HEADER_BYTES);
if (!startsWith(header, PNG_SIGNATURE))
return detectSupportedImageMimeType(header);
return isPng(header) && !await isAnimatedPngOf(source) ? "image/png" : void 0;
}
async function isAnimatedPngOf(source) {
let block = new Uint8Array(0);
let blockStart = 0;
const bytesAt = async (offset2, length) => {
if (offset2 < blockStart || offset2 + length > blockStart + block.length) {
blockStart = offset2;
block = await source.read(offset2, BLOCK_BYTES);
}
return block.subarray(offset2 - blockStart, offset2 - blockStart + length);
};
let offset = PNG_SIGNATURE.length;
while (offset + 8 <= source.size) {
const chunkHeader = await bytesAt(offset, 8);
const chunkLength = readUint32BE(chunkHeader, 0);
if (startsWithAscii(chunkHeader, 4, "acTL"))
return true;
if (startsWithAscii(chunkHeader, 4, "IDAT"))
return false;
const nextOffset = offset + 8 + chunkLength + 4;
if (nextOffset <= offset || nextOffset > source.size)
return false;
offset = nextOffset;
}
return false;
}
function detectSupportedImageMimeType(buffer) {
if (startsWith(buffer, [255, 216, 255]))
return buffer[3] === 247 ? void 0 : "image/jpeg";
if (startsWith(buffer, PNG_SIGNATURE))
return isPng(buffer) && !isAnimatedPng(buffer) ? "image/png" : void 0;
if (startsWithAscii(buffer, 0, "GIF87a") || startsWithAscii(buffer, 0, "GIF89a"))
return "image/gif";
if (startsWithAscii(buffer, 0, "RIFF") && startsWithAscii(buffer, 8, "WEBP"))
return "image/webp";
if (startsWithAscii(buffer, 0, "BM") && isBmp(buffer))
return "image/bmp";
return void 0;
}
function isPng(buffer) {
return buffer.length >= 16 && readUint32BE(buffer, PNG_SIGNATURE.length) === 13 && startsWithAscii(buffer, 12, "IHDR");
}
function isAnimatedPng(buffer) {
let offset = PNG_SIGNATURE.length;
while (offset + 8 <= buffer.length) {
const chunkLength = readUint32BE(buffer, offset);
const chunkTypeOffset = offset + 4;
if (startsWithAscii(buffer, chunkTypeOffset, "acTL"))
return true;
if (startsWithAscii(buffer, chunkTypeOffset, "IDAT"))
return false;
const nextOffset = offset + 8 + chunkLength + 4;
if (nextOffset <= offset || nextOffset > buffer.length)
return false;
offset = nextOffset;
}
return false;
}
function imageDimensions(bytes2, mimeType) {
switch (mimeType) {
case "image/png":
return bytes2.length < 24 ? void 0 : { width: readUint32BE(bytes2, 16), height: readUint32BE(bytes2, 20) };
case "image/gif":
return bytes2.length < 10 ? void 0 : { width: readUint16LE(bytes2, 6), height: readUint16LE(bytes2, 8) };
case "image/webp":
if (bytes2.length < 30)
return void 0;
if (startsWithAscii(bytes2, 12, "VP8 "))
return { width: readUint16LE(bytes2, 26) & 16383, height: readUint16LE(bytes2, 28) & 16383 };
if (startsWithAscii(bytes2, 12, "VP8L")) {
const bits = readUint32LE(bytes2, 21);
return { width: (bits & 16383) + 1, height: (bits >>> 14 & 16383) + 1 };
}
if (startsWithAscii(bytes2, 12, "VP8X")) {
const uint24 = (offset) => readUint16LE(bytes2, offset) + ((bytes2[offset + 2] ?? 0) << 16);
return { width: uint24(24) + 1, height: uint24(27) + 1 };
}
return void 0;
case "image/jpeg":
for (let offset = 2; offset + 9 <= bytes2.length; ) {
if (bytes2[offset] !== 255)
return void 0;
const marker = bytes2[offset + 1];
if (marker === 255) {
offset++;
continue;
}
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) {
return { width: readUint16BE(bytes2, offset + 7), height: readUint16BE(bytes2, offset + 5) };
}
offset += 2 + readUint16BE(bytes2, offset + 2);
}
return void 0;
default:
return void 0;
}
}
function isBmp(buffer) {
if (buffer.length < 26)
return false;
const declaredFileSize = readUint32LE(buffer, 2);
const pixelDataOffset = readUint32LE(buffer, 10);
const dibHeaderSize = readUint32LE(buffer, 14);
if (declaredFileSize !== 0 && declaredFileSize < 26)
return false;
if (pixelDataOffset < 14 + dibHeaderSize)
return false;
if (declaredFileSize !== 0 && pixelDataOffset >= declaredFileSize)
return false;
let colorPlanes;
let bitsPerPixel;
if (dibHeaderSize === 12) {
colorPlanes = readUint16LE(buffer, 22);
bitsPerPixel = readUint16LE(buffer, 24);
} else if (dibHeaderSize >= 40 && dibHeaderSize <= 124) {
if (buffer.length < 30)
return false;
colorPlanes = readUint16LE(buffer, 26);
bitsPerPixel = readUint16LE(buffer, 28);
} else {
return false;
}
return colorPlanes === 1 && [1, 4, 8, 16, 24, 32].includes(bitsPerPixel);
}
function readUint16LE(buffer, offset) {
return (buffer[offset] ?? 0) + ((buffer[offset + 1] ?? 0) << 8);
}
function readUint16BE(buffer, offset) {
return ((buffer[offset] ?? 0) << 8) + (buffer[offset + 1] ?? 0);
}
function readUint32BE(buffer, offset) {
return (buffer[offset] ?? 0) * 16777216 + ((buffer[offset + 1] ?? 0) << 16) + ((buffer[offset + 2] ?? 0) << 8) + (buffer[offset + 3] ?? 0);
}
function readUint32LE(buffer, offset) {
return (buffer[offset] ?? 0) + ((buffer[offset + 1] ?? 0) << 8) + ((buffer[offset + 2] ?? 0) << 16) + (buffer[offset + 3] ?? 0) * 16777216;
}
function startsWith(buffer, bytes2) {
if (buffer.length < bytes2.length)
return false;
return bytes2.every((byte, index) => buffer[index] === byte);
}
function startsWithAscii(buffer, offset, text2) {
if (buffer.length < offset + text2.length)
return false;
for (let index = 0; index < text2.length; index++) {
if (buffer[offset + index] !== text2.charCodeAt(index))
return false;
}
return true;
}
// node_modules/@earendil-works/pi-durable/dist/tools/image-processor.js
var DEFAULT_IMAGE_LIMITS = { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4.5 * 1024 * 1024 };
var INLINE_IMAGE_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
function toBase64(bytes2) {
const parts = [];
for (let i = 0; i < bytes2.length; i += 8192) {
parts.push(String.fromCharCode.apply(null, bytes2.subarray(i, i + 8192)));
}
return btoa(parts.join(""));
}
function base64Length(byteLength) {
return Math.ceil(byteLength / 3) * 4;
}
// node_modules/@earendil-works/pi-durable/dist/tools/read.js
var readSchema = obj({
path: str({ description: "Path to the file to read (relative or absolute)" }),
offset: opt(num({ description: "Line number to start reading from (1-indexed)" })),
limit: opt(num({ description: "Maximum number of lines to read" }))
}, { open: true });
var readStructuredOutputSchema = union([
str(),
obj({ type: lit("image"), data: str(), mimeType: str() }, { open: true })
]);
var READ_CHUNK = 64 * 1024;
function sliceIndex(value2) {
return Number.isNaN(value2) ? 0 : Math.trunc(value2);
}
async function readHead(reader, start, end, skipBom, context) {
const decoder2 = rangeDecoder();
let text2 = "";
let newlines = 0;
for (let position = skipBom && start === 0 ? 3 : start; position < end; ) {
const bytes2 = getOrThrow(await reader.read(position, Math.min(READ_CHUNK, end - position), context));
if (bytes2.length === 0)
break;
position += bytes2.length;
const decoded = decoder2.decode(bytes2, { stream: true });
text2 += decoded;
for (let index = decoded.indexOf("\n"); index !== -1; index = decoded.indexOf("\n", index + 1))
newlines++;
if (newlines >= DEFAULT_MAX_LINES || utf8ByteLength(text2) > DEFAULT_MAX_BYTES + 1)
return text2;
}
return text2 + decoder2.decode();
}
function createReadTool(options = {}) {
const formats2 = options.images === void 0 ? "jpg, png, gif, webp" : "jpg, png, gif, webp, bmp";
return defineTool({
name: "read",
description: `Read the contents of a file. Supports text files and images (${formats2}). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,
parameters: readSchema,
structuredOutputSchema: readStructuredOutputSchema,
async execute(args, api, context) {
const { path: path3, offset, limit: limit2 } = args;
const env = requireEnv(api);
const absolutePath = await resolveReadToolPath(env, path3, context);
const reader = getOrThrow(await env.openBinaryReader(absolutePath, void 0, context));
try {
for (let attempt = 0; ; attempt++) {
const before = getOrThrow(await reader.info(context));
const mimeType = await detectSupportedImageMimeTypeOf({
size: before.size,
read: async (position, length) => getOrThrow(await reader.read(position, length, context))
});
const result = mimeType === void 0 ? await readText(reader, path3, offset, limit2, context) : await readImage(reader, before, path3, mimeType, options.images, await imageModel(api, context), context);
const after = getOrThrow(await reader.info(context));
const unchanged = after.size === before.size && after.mtimeMs === before.mtimeMs;
if (unchanged || mimeType === void 0 && after.size > before.size)
return result;
if (attempt === 1)
throw new Error(`${path3} changed while it was read`);
}
} finally {
await reader.close(context);
}
}
});
}
async function readImage(reader, info, path3, mimeType, processor, { vision, limits }, context) {
let image;
const notes = [];
if (processor !== void 0) {
const bytes2 = getOrThrow(await reader.read(0, info.size, context));
const prepared = await processor.prepare(bytes2, mimeType, limits);
if (prepared === void 0)
return imageError(`${path3} is an image (${mimeType}) that cannot be prepared for the model`);
image = prepared;
if (prepared.convertedFrom !== void 0)
notes.push(`Converted from ${prepared.convertedFrom} to ${prepared.mimeType}.`);
if (prepared.resized !== void 0) {
const { from, to } = prepared.resized;
const scale = (from.width / to.width).toFixed(2);
notes.push(`Resized from ${from.width}x${from.height} to ${to.width}x${to.height}. Multiply coordinates by ${scale} to map them to the original.`);
}
} else {
if (!INLINE_IMAGE_TYPES.has(mimeType)) {
return imageError(`${path3} is an image (${mimeType}) that needs converting, and no image processor is configured`);
}
const unshrinkable = "and no image processor is configured to shrink it";
if (base64Length(info.size) > limits.maxBytes) {
return imageError(`${path3} is an image (${mimeType}) of ${formatSize(info.size)}, too large to send, ${unshrinkable}`);
}
const bytes2 = getOrThrow(await reader.read(0, info.size, context));
const size = imageDimensions(bytes2, mimeType);
if (size === void 0)
return imageError(`${path3} is an image (${mimeType}) whose size cannot be read`);
if (size.width > limits.maxWidth || size.height > limits.maxHeight) {
return imageError(`${path3} is an image (${mimeType}) of ${size.width}x${size.height}, larger than ${limits.maxWidth}x${limits.maxHeight}, ${unshrinkable}`);
}
image = { data: toBase64(bytes2), mimeType };
}
if (!vision)
notes.push("The current model does not support images; it sees a placeholder instead.");
const diagnostics = [
{ severity: "info", code: "image", message: [`Read image file [${image.mimeType}].`, ...notes].join(" ") }
];
const block = { type: "image", data: image.data, mimeType: image.mimeType };
return { output: [block], structuredOutput: block, diagnostics };
}
async function imageModel(api, context) {
const ref = (await api.agent(context)).model;
const model3 = ref === void 0 ? void 0 : api.models.getModel(ref.provider, ref.modelId);
const resize = model3?.inputLimits?.images?.resize;
return {
vision: model3?.input.includes("image") ?? true,
limits: {
maxWidth: resize?.maxWidth ?? DEFAULT_IMAGE_LIMITS.maxWidth,
maxHeight: resize?.maxHeight ?? DEFAULT_IMAGE_LIMITS.maxHeight,
maxBytes: resize?.maxBytes ?? DEFAULT_IMAGE_LIMITS.maxBytes
}
};
}
function imageError(message) {
return { output: [], isError: true, diagnostics: [{ severity: "error", code: "unsupported_image", message }] };
}
async function readText(reader, path3, offset, limit2, context) {
const startLine = offset ? Math.max(0, offset - 1) : 0;
const startLineDisplay = startLine + 1;
const sliceStart = sliceIndex(startLine);
const scanStart2 = Number.isSafeInteger(sliceStart) ? sliceStart : 0;
const requestedEnd = limit2 === void 0 ? void 0 : Math.max(scanStart2 + 1, sliceIndex(startLine + limit2));
const scanEnd = requestedEnd !== void 0 && Number.isSafeInteger(requestedEnd) ? requestedEnd : void 0;
const scanOf = async (endLine) => getOrThrow(await reader.scanLines({ startLine: scanStart2, ...endLine === void 0 ? {} : { endLine } }, context));
let scan = await scanOf(scanEnd);
const totalFileLines = scan.newlines + 1;
if (startLine >= totalFileLines) {
throw new Error(`Offset ${offset} is beyond end of file (${totalFileLines} lines total)`);
}
let userLimitedLines;
let selectedLineCount = totalFileLines - sliceStart;
if (limit2 !== void 0) {
const endLine = Math.min(startLine + limit2, totalFileLines);
userLimitedLines = endLine - startLine;
const relativeEnd = sliceIndex(endLine);
const sliceEnd = relativeEnd < 0 ? Math.max(totalFileLines + relativeEnd, 0) : relativeEnd;
selectedLineCount = Math.max(0, sliceEnd - sliceStart);
if (selectedLineCount > 0 && relativeEnd < 0)
scan = await scanOf(sliceEnd);
}
const empty = selectedLineCount === 0;
const endsWithNewline = !empty && scan.lastLineStart === scan.end && scan.lastLineStart > scan.start;
const totals = {
lines: empty || scan.selectedBytes === 0 ? 0 : selectedLineCount - (endsWithNewline ? 1 : 0),
bytes: empty ? 0 : scan.selectedBytes
};
const firstBytes = getOrThrow(await reader.read(0, 3, context));
const head = empty ? "" : await readHead(reader, scan.start, scan.end, startsWithBom(firstBytes), context);
const { content: headText, ...truncation } = truncateHeadOf(head, totals);
const diagnostics = [];
let outputText = headText;
let details;
if (truncation.firstLineExceedsLimit) {
const integral = Number.isInteger(startLine);
const lineBytes = new TextEncoder().encode(integral ? head.split("\n")[0] ?? "" : "");
const lineSize = integral ? scan.firstLineBytes : 0;
const end = characterEnd(lineBytes, DEFAULT_MAX_BYTES);
outputText = new TextDecoder().decode(lineBytes.subarray(0, end));
diagnostics.push({
severity: "warn",
code: "truncated",
message: `Line ${startLineDisplay} is ${formatSize(lineSize)}, exceeds the ${formatSize(DEFAULT_MAX_BYTES)} limit; showing its first ${formatSize(end)}. Use bash: sed -n '${startLineDisplay}p' ${path3} | tail -c +${end + 1}`
});
details = { truncation: { ...truncation, outputBytes: end, outputLines: 1 } };
} else if (truncation.truncated) {
const endLineDisplay = startLineDisplay + truncation.outputLines - 1;
const nextOffset = endLineDisplay + 1;
const limitText = truncation.truncatedBy === "lines" ? "" : ` (${formatSize(DEFAULT_MAX_BYTES)} limit)`;
diagnostics.push({
severity: "info",
code: "truncated",
message: `Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}${limitText}. Use offset=${nextOffset} to continue.`
});
details = { truncation };
} else if (userLimitedLines !== void 0 && startLine + userLimitedLines < totalFileLines) {
const remaining = totalFileLines - (startLine + userLimitedLines);
const nextOffset = startLine + userLimitedLines + 1;
diagnostics.push({
severity: "info",
message: `${remaining} more lines in file. Use offset=${nextOffset} to continue.`
});
}
return {
output: outputText === "" ? [] : [{ type: "text", text: outputText }],
structuredOutput: outputText,
...details === void 0 ? {} : { details },
diagnostics
};
}
// node_modules/@earendil-works/pi-durable/dist/tools/write.js
var writeSchema = obj({
path: str({ description: "Path to the file to write (relative or absolute)" }),
content: str({ description: "Content to write to the file" })
}, { open: true });
function createWriteTool() {
return defineTool({
name: "write",
description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
parameters: writeSchema,
async execute(args, api, context) {
const { path: path3, content } = args;
const env = requireEnv(api);
const absolutePath = await resolveToolPath(env, path3, context);
return withFileMutationQueue(env, absolutePath, async () => {
if (context.abortSignal?.aborted)
throw new Error("Operation aborted");
getOrThrow(await env.writeFile(absolutePath, content, context));
if (context.abortSignal?.aborted)
throw new Error("Operation aborted");
return { output: [{ type: "text", text: `Successfully wrote to ${path3}` }] };
}, context);
}
});
}
// node_modules/@earendil-works/pi-durable/dist/tools/index.js
function createCodingTools(options = {}) {
return defineExtension({
name: "coding-tools",
tools: [createReadTool(options), createWriteTool(), createEditTool(), createBashTool()]
});
}
var CodingTools = createCodingTools();
// node_modules/@earendil-works/chord/dist/sqlite/schema.js
function validateSqliteSchemaPrefix(prefix) {
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(prefix)) {
throw new Error(`Invalid SQLite schema prefix ${JSON.stringify(prefix)}`);
}
if (prefix.toLowerCase().startsWith("sqlite_")) {
throw new Error(`SQLite schema prefix ${JSON.stringify(prefix)} is reserved`);
}
}
// node_modules/@earendil-works/chord/dist/sqlite/migrations.js
async function applySqliteMigrations(database, migrations, options) {
const { table } = options;
validateSqliteSchemaPrefix(table);
for (let index = 0; index < migrations.length; index++) {
if (migrations[index]?.version !== index + 1) {
throw new Error("SQLite migrations must have contiguous versions starting at 1");
}
}
await database.transaction(async (transaction) => {
await transaction.exec(`CREATE TABLE IF NOT EXISTS ${table} (
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
version INTEGER NOT NULL CHECK (version >= 0)
) STRICT`);
await transaction.run(`INSERT OR IGNORE INTO ${table} (singleton, version) VALUES (1, 0)`);
const row = await transaction.get(`SELECT version FROM ${table} WHERE singleton = 1`);
if (row === void 0)
throw new Error("SQLite schema metadata is missing");
const currentVersion = migrations.at(-1)?.version ?? 0;
if (row.version > currentVersion) {
throw new Error(`SQLite schema version ${row.version} is newer than supported version ${currentVersion}`);
}
for (const migration of migrations) {
if (migration.version <= row.version)
continue;
for (const statement of migration.statements)
await transaction.exec(statement);
await transaction.run(`UPDATE ${table} SET version = ? WHERE singleton = 1`, migration.version);
}
});
}
// node_modules/@earendil-works/pi-durable/dist/storage/sqlite/schema.js
var TABLE_NAMES = {
durableSchema: "durable_schema",
durableMetadata: "durable_metadata",
recordIds: "record_ids",
conversations: "conversations",
entries: "entries",
tasks: "tasks",
submissions: "submissions",
documents: "documents",
documentRevisions: "document_revisions"
};
var INDEX_NAMES = {
conversationsByOwnerConversation: "conversations_by_owner_conversation",
conversationsByOwnerTask: "conversations_by_owner_task",
entriesByConversation: "entries_by_conversation",
entryHeadsByConversation: "entry_heads_by_conversation",
tasksByStatus: "tasks_by_status",
tasksByConversation: "tasks_by_conversation",
tasksByKind: "tasks_by_kind",
tasksByAbortRequested: "tasks_by_abort_requested",
tasksByBackground: "tasks_by_background",
submissionsByRequest: "submissions_by_request",
submissionsByConversation: "submissions_by_conversation",
submissionsByStatus: "submissions_by_status",
documentsByAddress: "documents_by_address",
documentsByScope: "documents_by_scope",
documentsByScopeKind: "documents_by_scope_kind",
documentRevisionsByKind: "document_revisions_by_kind"
};
function prefixIdentifiers(names2, prefix) {
return Object.fromEntries(Object.entries(names2).map(([key, name]) => [key, `${prefix}${name}`]));
}
function createSqliteSchema(prefix) {
if (prefix !== void 0)
validateSqliteSchemaPrefix(prefix);
const actualPrefix = prefix ?? "";
return {
tables: prefixIdentifiers(TABLE_NAMES, actualPrefix),
indexes: prefixIdentifiers(INDEX_NAMES, actualPrefix)
};
}
var DEFAULT_SQLITE_SCHEMA = createSqliteSchema();
// node_modules/@earendil-works/pi-durable/dist/storage/sqlite/migrations.js
function createSqliteMigrations(schema) {
const { tables, indexes } = schema;
const initialSchema = [
`CREATE TABLE ${tables.durableMetadata} (
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
next_id TEXT NOT NULL,
next_seq INTEGER NOT NULL
) STRICT`,
`INSERT INTO ${tables.durableMetadata} (singleton, next_id, next_seq) VALUES (1, '2', 1)`,
`CREATE TABLE ${tables.recordIds} (
id INTEGER PRIMARY KEY,
record_type TEXT NOT NULL CHECK (record_type IN ('conversation', 'entry', 'task', 'submission', 'document'))
) STRICT`,
`CREATE TABLE ${tables.conversations} (
id INTEGER PRIMARY KEY,
owner_conversation_id INTEGER,
owner_task_id INTEGER,
record TEXT NOT NULL CHECK (json_valid(record))
) STRICT`,
`CREATE INDEX ${indexes.conversationsByOwnerConversation} ON ${tables.conversations} (owner_conversation_id, id)`,
`CREATE INDEX ${indexes.conversationsByOwnerTask} ON ${tables.conversations} (owner_task_id, id)`,
`CREATE TABLE ${tables.entries} (
id INTEGER PRIMARY KEY,
conversation_id INTEGER NOT NULL,
head INTEGER,
commit_seq INTEGER NOT NULL,
record TEXT NOT NULL CHECK (json_valid(record))
) STRICT`,
`CREATE INDEX ${indexes.entriesByConversation} ON ${tables.entries} (conversation_id, id DESC)`,
`CREATE INDEX ${indexes.entryHeadsByConversation} ON ${tables.entries} (conversation_id, id DESC) WHERE head IS NOT NULL`,
`CREATE TABLE ${tables.tasks} (
id INTEGER PRIMARY KEY,
conversation_id INTEGER NOT NULL,
kind TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'waiting', 'completing', 'terminal')),
abort_requested INTEGER NOT NULL CHECK (abort_requested IN (0, 1)),
background INTEGER NOT NULL CHECK (background IN (0, 1)),
record TEXT NOT NULL CHECK (json_valid(record))
) STRICT`,
`CREATE INDEX ${indexes.tasksByStatus} ON ${tables.tasks} (status, id)`,
`CREATE INDEX ${indexes.tasksByConversation} ON ${tables.tasks} (conversation_id, id)`,
`CREATE INDEX ${indexes.tasksByKind} ON ${tables.tasks} (kind, id)`,
`CREATE INDEX ${indexes.tasksByAbortRequested} ON ${tables.tasks} (abort_requested, id)`,
`CREATE INDEX ${indexes.tasksByBackground} ON ${tables.tasks} (background, id)`,
`CREATE TABLE ${tables.submissions} (
id INTEGER PRIMARY KEY,
conversation_id INTEGER NOT NULL,
request_id TEXT,
status TEXT NOT NULL CHECK (status IN ('queued', 'placed', 'done', 'unanswered')),
record TEXT NOT NULL CHECK (json_valid(record))
) STRICT`,
`CREATE INDEX ${indexes.submissionsByRequest} ON ${tables.submissions} (conversation_id, request_id)`,
`CREATE INDEX ${indexes.submissionsByConversation} ON ${tables.submissions} (conversation_id, id)`,
`CREATE INDEX ${indexes.submissionsByStatus} ON ${tables.submissions} (status, id)`,
`CREATE TABLE ${tables.documents} (
id INTEGER PRIMARY KEY,
kind TEXT NOT NULL,
family INTEGER NOT NULL CHECK (family IN (0, 1)),
key_value TEXT NOT NULL,
scope_kind TEXT NOT NULL CHECK (scope_kind IN ('session', 'conversation', 'task')),
owner_id INTEGER NOT NULL,
created_at INTEGER NOT NULL,
retired_at INTEGER,
record TEXT NOT NULL CHECK (json_valid(record))
) STRICT`,
`CREATE INDEX ${indexes.documentsByAddress}
ON ${tables.documents} (kind, scope_kind, owner_id, family, key_value, created_at DESC, retired_at)`,
`CREATE INDEX ${indexes.documentsByScope} ON ${tables.documents} (scope_kind, owner_id, id)`,
`CREATE INDEX ${indexes.documentsByScopeKind} ON ${tables.documents} (scope_kind, owner_id, kind, id)`,
`CREATE TABLE ${tables.documentRevisions} (
document_id INTEGER NOT NULL,
seq INTEGER NOT NULL,
kind TEXT NOT NULL CHECK (kind IN ('base', 'delta')),
version INTEGER NOT NULL,
content TEXT NOT NULL CHECK (json_valid(content)),
PRIMARY KEY (document_id, seq)
) STRICT`,
`CREATE INDEX ${indexes.documentRevisionsByKind} ON ${tables.documentRevisions} (document_id, kind, seq DESC)`
];
const rebuiltTasks = `${tables.tasks}_v2`;
const sleepingStatus = [
`CREATE TABLE ${rebuiltTasks} (
id INTEGER PRIMARY KEY,
conversation_id INTEGER NOT NULL,
kind TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'waiting', 'sleeping', 'completing', 'terminal')),
abort_requested INTEGER NOT NULL CHECK (abort_requested IN (0, 1)),
background INTEGER NOT NULL CHECK (background IN (0, 1)),
record TEXT NOT NULL CHECK (json_valid(record))
) STRICT`,
`INSERT INTO ${rebuiltTasks} (id, conversation_id, kind, status, abort_requested, background, record)
SELECT id, conversation_id, kind, status, abort_requested, background, record FROM ${tables.tasks}`,
`DROP TABLE ${tables.tasks}`,
`ALTER TABLE ${rebuiltTasks} RENAME TO ${tables.tasks}`,
`CREATE INDEX ${indexes.tasksByStatus} ON ${tables.tasks} (status, id)`,
`CREATE INDEX ${indexes.tasksByConversation} ON ${tables.tasks} (conversation_id, id)`,
`CREATE INDEX ${indexes.tasksByKind} ON ${tables.tasks} (kind, id)`,
`CREATE INDEX ${indexes.tasksByAbortRequested} ON ${tables.tasks} (abort_requested, id)`,
`CREATE INDEX ${indexes.tasksByBackground} ON ${tables.tasks} (background, id)`
];
return [
{ version: 1, statements: initialSchema },
{ version: 2, statements: sleepingStatus }
];
}
var SQLITE_MIGRATIONS = createSqliteMigrations(DEFAULT_SQLITE_SCHEMA);
var CURRENT_SQLITE_SCHEMA_VERSION = SQLITE_MIGRATIONS.at(-1)?.version ?? 0;
async function applySqliteMigrationsForSchema(database, schema, migrations = createSqliteMigrations(schema)) {
await applySqliteMigrations(database, migrations, { table: schema.tables.durableSchema });
}
// node_modules/@earendil-works/pi-durable/dist/storage/sqlite/storage.js
var parseJson = (value2) => JSON.parse(value2);
var encodeJson = (value2) => JSON.stringify(value2);
var encodeIndexedString = (value2) => JSON.stringify(value2);
var cursorId = (cursor) => {
const after = cursor?.after;
if (after === void 0)
return void 0;
if (typeof after !== "number" || !Number.isSafeInteger(after))
throw new StorageRequestError("Invalid storage cursor");
return idFromNumber(after);
};
var page = (values, limit2, order = "ascending") => {
const items = values.slice(0, limit2);
if (values.length <= limit2)
return { items };
return { items, next: nextCursor(items.at(-1).id, order) };
};
var scanSql = (start) => start.order === "ascending" ? { clause: "id > ?", param: start.after ?? -1, direction: "ASC" } : { clause: "id < ?", param: start.after ?? Number.MAX_SAFE_INTEGER, direction: "DESC" };
var scopeColumns = (scope) => {
switch (scope.kind) {
case "session":
return { scopeKind: "session", ownerId: 0 };
case "conversation":
return { scopeKind: "conversation", ownerId: scope.conversationId };
case "task":
return { scopeKind: "task", ownerId: scope.taskId };
}
};
var addressParts = (address) => {
const scope = scopeColumns(address.scope);
return {
kind: encodeIndexedString(address.kind),
...scope,
family: address.key === void 0 ? 0 : 1,
keyValue: encodeIndexedString(address.key ?? "")
};
};
var addressKey = (address) => {
const parts = addressParts(address);
return JSON.stringify([parts.kind, parts.scopeKind, parts.ownerId, parts.family, parts.keyValue]);
};
var isAliveAt = (record, at) => {
if (at === "current")
return record.retiredAt === void 0;
return record.createdAt <= at && (record.retiredAt === void 0 || at < record.retiredAt);
};
var isCurrentOnly = (record) => record.scope.kind !== "conversation" || record.history === "latest";
var writeId = (write) => {
switch (write.type) {
case "conversation":
case "entry":
case "task":
case "submission":
return write.value.id;
case "document.create":
case "document.copy":
return write.record.id;
case "document.change":
case "document.retire":
return void 0;
}
};
function watchCalls(executor, calls) {
const watched = async (call) => {
try {
return await call();
} catch (error) {
calls.failed = true;
throw error;
}
};
return {
exec: (sql) => watched(() => executor.exec(sql)),
run: (sql, ...params) => watched(() => executor.run(sql, ...params)),
runCounted: (sql, ...params) => watched(() => executor.runCounted(sql, ...params)),
get: (sql, ...params) => watched(() => executor.get(sql, ...params)),
all: (sql, ...params) => watched(() => executor.all(sql, ...params))
};
}
var SqliteStorage = class _SqliteStorage {
db;
schema;
nextId;
closed = false;
closing;
admittedReads = 0;
readsDrained;
constructor(db, schema, nextId) {
this.db = db;
this.schema = schema;
this.nextId = nextId;
}
/** Initialize storage over an owned SQLite database facade. */
static async open(db, options = {}) {
try {
const schema = createSqliteSchema(options.prefix);
await applySqliteMigrationsForSchema(db, schema);
const metadata = await db.get(`SELECT next_id, next_seq FROM ${schema.tables.durableMetadata} WHERE singleton = 1`);
if (metadata === void 0)
throw new Error("Durable SQLite metadata is missing");
return new _SqliteStorage(db, schema, Number(metadata.next_id));
} catch (error) {
try {
await db.close();
} catch {
}
throw error;
}
}
/**
* Commit `batches` in one SQL transaction, each with its own seq. Each batch is checked before it writes anything,
* against the state the earlier ones left, and the first one refused ends the batch: the transaction commits the ones
* before it. No savepoints, which Durable Objects do not allow: the checks run before the writes instead.
*/
async commit(batches, receive, _context) {
this.assertOpen();
const seqs = [];
let refused;
let candidateNextId = this.nextId;
await this.db.transaction(async (transaction) => {
const metadata = await this.readMetadata(transaction);
let next = metadata.next_seq;
const calls = { failed: false };
const checked = watchCalls(transaction, calls);
for (const writes of batches) {
let documentActions;
calls.failed = false;
try {
documentActions = this.prepareDocumentActions(writes);
await this.checkBatch(checked, writes, documentActions);
} catch (error) {
if (calls.failed)
throw error;
refused = { error };
break;
}
const seq = seqFromNumber(next++);
await this.applyBatch(transaction, writes, documentActions, seq);
seqs.push(seq);
candidateNextId = Math.max(candidateNextId, this.candidateNextId(writes));
}
if (seqs.length > 0) {
await this.writeMetadata(transaction, Math.max(Number(metadata.next_id), candidateNextId), next);
}
});
this.nextId = Math.max(this.nextId, candidateNextId);
for (const [index, seq] of seqs.entries())
receive(index, seq);
return refused === void 0 ? { stored: seqs.length } : { stored: seqs.length, refused: refused.error };
}
async readMetadata(executor) {
const metadata = await executor.get(`SELECT next_id, next_seq FROM ${this.schema.tables.durableMetadata} WHERE singleton = 1`);
if (metadata === void 0)
throw new Error("Durable SQLite metadata is missing");
return metadata;
}
async writeMetadata(executor, nextId, nextSeq) {
await executor.run(`UPDATE ${this.schema.tables.durableMetadata} SET next_id = ?, next_seq = ? WHERE singleton = 1`, String(nextId), nextSeq);
}
/** Durable's own checks of one batch, copy resolution included, before it writes anything. */
async checkBatch(executor, writes, documentActions) {
await this.checkGlobalIds(executor, writes);
await this.checkDocumentActions(executor, documentActions);
await this.resolveCopies(executor, documentActions);
}
async applyBatch(executor, writes, documentActions, seq) {
for (const write of writes)
await this.applyTableWrite(executor, write, seq);
await this.applyDocumentActions(executor, documentActions, seq);
}
async mintId() {
this.assertOpen();
if (!Number.isSafeInteger(this.nextId))
throw new Error("ID space is exhausted");
return idFromNumber(this.nextId++);
}
async conversation(id, _context) {
this.assertOpen();
const row = await this.db.get(`SELECT record FROM ${this.schema.tables.conversations} WHERE id = ?`, id);
return row === void 0 ? void 0 : parseJson(row.record);
}
async scanConversations(query, limit2, cursor, _context) {
this.assertOpen();
const start = scanStart(query.order, cursor, "ascending");
const scan = scanSql(start);
const clauses = [scan.clause];
const params = [scan.param];
if (query.ownerConversationId !== void 0) {
clauses.push("owner_conversation_id = ?");
params.push(query.ownerConversationId);
}
if (query.ownerTaskId !== void 0) {
clauses.push("owner_task_id = ?");
params.push(query.ownerTaskId);
}
params.push(limit2 + 1);
const rows = await this.db.all(`SELECT record FROM ${this.schema.tables.conversations} WHERE ${clauses.join(" AND ")} ORDER BY id ${scan.direction} LIMIT ?`, ...params);
return page(rows.map((row) => parseJson(row.record)), limit2, start.order);
}
entry(idOrConversationId, idOrContext, context) {
return this.admitRead(() => this.readEntry(idOrConversationId, idOrContext, context));
}
findLatestHeadMarker(conversationId, atOrBeforeEntryId, _context) {
return this.admitRead(() => this.readLatestHeadMarker(conversationId, atOrBeforeEntryId));
}
scanEntries(query, limit2, cursor, _context) {
return this.admitRead(() => this.readEntries(query, limit2, cursor));
}
async readEntry(idOrConversationId, idOrContext, context) {
const id = context === void 0 ? idFromNumber(idOrConversationId) : typeof idOrContext === "number" ? idFromNumber(idOrContext) : void 0;
if (id === void 0)
throw new StorageRequestError("Storage.entry() requires an entry ID");
let conversation;
if (context !== void 0) {
const conversationId = idFromNumber(idOrConversationId);
conversation = await this.readConversation(conversationId);
if (conversation === void 0)
throw new StorageRequestError(`Unknown conversation: ${conversationId}`);
}
const row = await this.db.get(`SELECT record, commit_seq FROM ${this.schema.tables.entries} WHERE id = ?`, id);
if (row === void 0)
return void 0;
const entry2 = parseJson(row.record);
if (conversation !== void 0) {
let upperEntryId = Number.POSITIVE_INFINITY;
while (conversation.id !== entry2.conversationId) {
if (conversation.parent === void 0)
return void 0;
upperEntryId = Math.min(upperEntryId, conversation.parent.at);
conversation = await this.readConversation(conversation.parent.conversationId);
}
if (entry2.id > upperEntryId)
return void 0;
}
return { entry: entry2, commitSeq: seqFromNumber(row.commit_seq) };
}
async readLatestHeadMarker(conversationId, atOrBeforeEntryId) {
let conversation = await this.readConversation(conversationId);
if (conversation === void 0)
throw new StorageRequestError(`Unknown conversation: ${conversationId}`);
let upper = atOrBeforeEntryId;
while (true) {
const row = upper === void 0 ? await this.db.get(`SELECT record FROM ${this.schema.tables.entries} WHERE conversation_id = ? AND head IS NOT NULL ORDER BY id DESC LIMIT 1`, conversation.id) : await this.db.get(`SELECT record FROM ${this.schema.tables.entries} WHERE conversation_id = ? AND head IS NOT NULL AND id <= ? ORDER BY id DESC LIMIT 1`, conversation.id, upper);
if (row !== void 0)
return parseJson(row.record);
if (conversation.parent === void 0)
return void 0;
upper = upper === void 0 ? conversation.parent.at : Math.min(upper, conversation.parent.at);
conversation = await this.readConversation(conversation.parent.conversationId);
}
}
async readEntries(query, limit2, cursor) {
const { order, after } = scanStart(query.order, cursor, "descending");
if (order === "ascending")
return this.readEntriesAscending(query, limit2, after);
let conversation = await this.readConversation(query.conversationId);
if (conversation === void 0)
throw new StorageRequestError(`Unknown conversation: ${query.conversationId}`);
let upper = query.maxEntryId;
if (after !== void 0)
upper = Math.min(upper ?? Number.MAX_SAFE_INTEGER, after - 1);
const values = [];
while (true) {
const clauses = ["conversation_id = ?"];
const params = [conversation.id];
if (query.minEntryId !== void 0) {
clauses.push("id >= ?");
params.push(query.minEntryId);
}
if (upper !== void 0) {
clauses.push("id <= ?");
params.push(upper);
}
params.push(limit2 + 1 - values.length);
const rows = await this.db.all(`SELECT record FROM ${this.schema.tables.entries} WHERE ${clauses.join(" AND ")} ORDER BY id DESC LIMIT ?`, ...params);
values.push(...rows.map((row) => parseJson(row.record)));
if (values.length > limit2 || conversation.parent === void 0)
break;
upper = upper === void 0 ? conversation.parent.at : Math.min(upper, conversation.parent.at);
if (query.minEntryId !== void 0 && upper < query.minEntryId)
break;
conversation = await this.readConversation(conversation.parent.conversationId);
}
return page(values, limit2, "descending");
}
/** Oldest first: the fork chain's segments from the root conversation forward, each up to its fork point. */
async readEntriesAscending(query, limit2, after) {
const segments = [];
let conversation = await this.readConversation(query.conversationId);
if (conversation === void 0)
throw new StorageRequestError(`Unknown conversation: ${query.conversationId}`);
let upper = query.maxEntryId;
while (true) {
segments.push({ conversationId: conversation.id, upper });
if (conversation.parent === void 0)
break;
upper = upper === void 0 ? conversation.parent.at : Math.min(upper, conversation.parent.at);
if (query.minEntryId !== void 0 && upper < query.minEntryId)
break;
conversation = await this.readConversation(conversation.parent.conversationId);
}
let lower = query.minEntryId;
if (after !== void 0)
lower = Math.max(lower ?? after + 1, after + 1);
const values = [];
for (const segment of segments.reverse()) {
const clauses = ["conversation_id = ?"];
const params = [segment.conversationId];
if (lower !== void 0) {
clauses.push("id >= ?");
params.push(lower);
}
if (segment.upper !== void 0) {
clauses.push("id <= ?");
params.push(segment.upper);
}
params.push(limit2 + 1 - values.length);
const rows = await this.db.all(`SELECT record FROM ${this.schema.tables.entries} WHERE ${clauses.join(" AND ")} ORDER BY id ASC LIMIT ?`, ...params);
values.push(...rows.map((row) => parseJson(row.record)));
if (values.length > limit2)
break;
}
return page(values, limit2, "ascending");
}
async task(id, _context) {
this.assertOpen();
const row = await this.db.get(`SELECT record FROM ${this.schema.tables.tasks} WHERE id = ?`, id);
return row === void 0 ? void 0 : parseJson(row.record);
}
async scanTasks(query, limit2, cursor, _context) {
this.assertOpen();
const start = scanStart(query.order, cursor, "ascending");
const scan = scanSql(start);
const clauses = [scan.clause];
const params = [scan.param];
if (query.conversationId !== void 0) {
clauses.push("conversation_id = ?");
params.push(query.conversationId);
}
if (query.kind !== void 0) {
clauses.push("kind = ?");
params.push(encodeIndexedString(query.kind));
}
if (query.status !== void 0) {
clauses.push("status = ?");
params.push(query.status);
}
if (query.abortRequested !== void 0) {
clauses.push("abort_requested = ?");
params.push(query.abortRequested ? 1 : 0);
}
if (query.background !== void 0) {
clauses.push("background = ?");
params.push(query.background ? 1 : 0);
}
params.push(limit2 + 1);
const rows = await this.db.all(`SELECT record FROM ${this.schema.tables.tasks} WHERE ${clauses.join(" AND ")} ORDER BY id ${scan.direction} LIMIT ?`, ...params);
return page(rows.map((row) => parseJson(row.record)), limit2, start.order);
}
async submission(id, _context) {
this.assertOpen();
const row = await this.db.get(`SELECT record FROM ${this.schema.tables.submissions} WHERE id = ?`, id);
return row === void 0 ? void 0 : parseJson(row.record);
}
async scanSubmissions(query, limit2, cursor, _context) {
this.assertOpen();
const start = scanStart(query.order, cursor, "ascending");
const scan = scanSql(start);
const clauses = [scan.clause];
const params = [scan.param];
if (query.conversationId !== void 0) {
clauses.push("conversation_id = ?");
params.push(query.conversationId);
}
if (query.status !== void 0) {
clauses.push("status = ?");
params.push(query.status);
}
params.push(limit2 + 1);
const rows = await this.db.all(`SELECT record FROM ${this.schema.tables.submissions} WHERE ${clauses.join(" AND ")} ORDER BY id ${scan.direction} LIMIT ?`, ...params);
return page(rows.map((row) => parseJson(row.record)), limit2, start.order);
}
async submissionByRequest(conversationId, requestId, _context) {
this.assertOpen();
const row = await this.db.get(`SELECT record FROM ${this.schema.tables.submissions} WHERE conversation_id = ? AND request_id = ?`, conversationId, encodeIndexedString(requestId));
return row === void 0 ? void 0 : parseJson(row.record);
}
async findDocument(address, at, _context) {
this.assertOpen();
const parts = addressParts(address);
const sql = at === "current" ? `SELECT record FROM ${this.schema.tables.documents}
WHERE kind = ? AND scope_kind = ? AND owner_id = ? AND family = ? AND key_value = ?
AND retired_at IS NULL ORDER BY created_at DESC LIMIT 1` : `SELECT record FROM ${this.schema.tables.documents}
WHERE kind = ? AND scope_kind = ? AND owner_id = ? AND family = ? AND key_value = ?
AND created_at <= ? AND (retired_at IS NULL OR retired_at > ?)
ORDER BY created_at DESC LIMIT 1`;
const params = [parts.kind, parts.scopeKind, parts.ownerId, parts.family, parts.keyValue];
if (at !== "current")
params.push(at, at);
const row = await this.db.get(sql, ...params);
return row === void 0 ? void 0 : parseJson(row.record);
}
async document(id, at, _context) {
this.assertOpen();
return this.db.transaction((transaction) => this.materializeDocument(transaction, id, at));
}
async scanDocuments(query, limit2, cursor, _context) {
this.assertOpen();
const scope = scopeColumns(query.scope);
const clauses = ["scope_kind = ?", "owner_id = ?", "id > ?"];
const params = [scope.scopeKind, scope.ownerId, cursorId(cursor) ?? -1];
if (query.kind !== void 0) {
clauses.push("kind = ?");
params.push(encodeIndexedString(query.kind));
}
if (query.at === "current") {
clauses.push("retired_at IS NULL");
} else {
clauses.push("created_at <= ?", "(retired_at IS NULL OR retired_at > ?)");
params.push(query.at, query.at);
}
params.push(limit2 + 1);
const rows = await this.db.all(`SELECT record FROM ${this.schema.tables.documents} WHERE ${clauses.join(" AND ")} ORDER BY id LIMIT ?`, ...params);
return page(rows.map((row) => parseJson(row.record)), limit2);
}
close(_context) {
if (this.closing === void 0) {
this.closed = true;
this.closing = this.closeDatabase();
}
return this.closing;
}
async closeDatabase() {
if (this.admittedReads > 0) {
await new Promise((resolve2) => {
this.readsDrained = resolve2;
});
}
await this.db.close();
}
/**
* Run a read that issues several queries. Close waits for admitted reads, so their later queries never reach a
* closed database. Single-query reads and transactions are already ordered before close by the database.
*/
async admitRead(read2) {
this.assertOpen();
this.admittedReads++;
try {
return await read2();
} finally {
if (--this.admittedReads === 0)
this.readsDrained?.();
}
}
async readConversation(id) {
const row = await this.db.get(`SELECT record FROM ${this.schema.tables.conversations} WHERE id = ?`, id);
return row === void 0 ? void 0 : parseJson(row.record);
}
async materializeDocument(executor, id, at) {
const row = await executor.get(`SELECT record FROM ${this.schema.tables.documents} WHERE id = ?`, id);
if (row === void 0)
return void 0;
const record = parseJson(row.record);
if (at !== "current" && isCurrentOnly(record)) {
throw new StorageRequestError(`Document ${id} does not retain historical content`);
}
if (!isAliveAt(record, at))
return void 0;
const upper = at === "current" ? Number.MAX_SAFE_INTEGER : at;
const base = await executor.get(`SELECT seq, kind, version, content FROM ${this.schema.tables.documentRevisions}
WHERE document_id = ? AND kind = 'base' AND seq <= ? ORDER BY seq DESC LIMIT 1`, id, upper);
if (base === void 0)
throw new Error(`Document ${id} is missing a required base`);
let value2 = parseJson(base.content);
const tail = await executor.all(`SELECT seq, kind, version, content FROM ${this.schema.tables.documentRevisions}
WHERE document_id = ? AND seq > ? AND seq <= ? ORDER BY seq`, id, base.seq, upper);
for (const revision of tail) {
if (revision.kind !== "delta" || revision.version !== base.version) {
throw new Error(`Document ${id} crosses a stored version boundary without a base`);
}
value2 = apply(value2, parseJson(revision.content));
}
return { record, version: base.version, value: value2, deltasSinceBase: tail.length };
}
candidateNextId(writes) {
let nextId = this.nextId;
for (const write of writes) {
const id = writeId(write);
if (id !== void 0)
nextId = Math.max(nextId, id + 1);
}
return nextId;
}
async checkGlobalIds(executor, writes) {
const claimed = /* @__PURE__ */ new Map();
for (const write of writes) {
if (write.type === "document.change" || write.type === "document.retire")
continue;
const document = write.type === "document.create" || write.type === "document.copy";
const table = document ? "document" : write.type;
const id = document ? write.record.id : write.value.id;
const existing = (await executor.get(`SELECT record_type FROM ${this.schema.tables.recordIds} WHERE id = ?`, id))?.record_type;
const earlier = claimed.get(id);
if (table === "conversation" || table === "entry" || table === "document") {
if (existing !== void 0)
throw new Error(`ID ${id} already belongs to ${existing}`);
if (earlier !== void 0)
throw new Error(`ID ${id} is written more than once`);
} else {
if (existing !== void 0 && existing !== table)
throw new Error(`ID ${id} already belongs to ${existing}`);
if (earlier !== void 0 && earlier !== table)
throw new Error(`ID ${id} is written as two record types`);
}
claimed.set(id, table);
}
}
prepareDocumentActions(writes) {
const actions = /* @__PURE__ */ new Map();
for (const write of writes) {
if (write.type !== "document.create" && write.type !== "document.copy" && write.type !== "document.change" && write.type !== "document.retire") {
continue;
}
const id = write.type === "document.create" || write.type === "document.copy" ? write.record.id : write.id;
let action = actions.get(id);
if (action === void 0) {
action = { retire: false };
actions.set(id, action);
}
switch (write.type) {
case "document.create":
if (action.create !== void 0 || action.content !== void 0 || action.copy !== void 0) {
throw new Error(`Document ${id} has more than one content command`);
}
action.create = write.record;
action.content = write.content;
break;
case "document.copy":
if (action.create !== void 0 || action.content !== void 0 || action.copy !== void 0) {
throw new Error(`Document ${id} has more than one content command`);
}
action.create = write.record;
action.copy = write.source;
break;
case "document.change":
if (action.content !== void 0 || action.copy !== void 0) {
throw new Error(`Document ${id} has more than one content command`);
}
action.content = write.content;
break;
case "document.retire":
if (action.retire)
throw new Error(`Document ${id} is retired more than once`);
action.retire = true;
break;
}
}
return actions;
}
async checkDocumentActions(executor, actions) {
const liveCounts = /* @__PURE__ */ new Map();
for (const [id, action] of actions) {
if (action.copy !== void 0 && actions.has(action.copy.id)) {
throw new Error(`Document copy ${id} source is changed in the copy batch`);
}
const row = await executor.get(`SELECT record FROM ${this.schema.tables.documents} WHERE id = ?`, id);
const existing = row === void 0 ? void 0 : parseJson(row.record);
if (action.create === void 0 && existing === void 0)
throw new Error(`Unknown document: ${id}`);
if (action.create !== void 0 && existing !== void 0)
throw new Error(`Document ${id} already exists`);
if (existing?.retiredAt !== void 0)
throw new Error(`Document ${id} is retired`);
if (action.content?.kind === "delta") {
const previous = await executor.get(`SELECT version FROM ${this.schema.tables.documentRevisions} WHERE document_id = ? ORDER BY seq DESC LIMIT 1`, id);
if (previous === void 0)
throw new Error(`Document ${id} delta has no base`);
if (previous.version !== action.content.version) {
throw new Error(`Document ${id} version transition requires a base`);
}
}
const record = action.create ?? existing;
const key = addressKey(record);
let live = liveCounts.get(key);
if (live === void 0)
live = await this.currentDocumentId(executor, record) === void 0 ? 0 : 1;
if (action.retire && existing !== void 0)
live--;
if (action.create !== void 0 && !action.retire)
live++;
liveCounts.set(key, live);
}
for (const live of liveCounts.values()) {
if (live > 1)
throw new Error("Document address already has a current incarnation");
}
}
async currentDocumentId(executor, address) {
const parts = addressParts(address);
const id = (await executor.get(`SELECT id FROM ${this.schema.tables.documents}
WHERE kind = ? AND scope_kind = ? AND owner_id = ? AND family = ? AND key_value = ? AND retired_at IS NULL
LIMIT 1`, parts.kind, parts.scopeKind, parts.ownerId, parts.family, parts.keyValue))?.id;
return id === void 0 ? void 0 : idFromNumber(id);
}
async applyTableWrite(executor, write, seq) {
switch (write.type) {
case "conversation":
await this.claimId(executor, write.value.id, "conversation");
await executor.run(`INSERT INTO ${this.schema.tables.conversations} (id, owner_conversation_id, owner_task_id, record) VALUES (?, ?, ?, ?)`, write.value.id, write.value.owner?.conversationId ?? null, write.value.owner?.taskId ?? null, encodeJson(write.value));
break;
case "entry":
await this.claimId(executor, write.value.id, "entry");
await executor.run(`INSERT INTO ${this.schema.tables.entries} (id, conversation_id, head, commit_seq, record) VALUES (?, ?, ?, ?, ?)`, write.value.id, write.value.conversationId, write.value.head ?? null, seq, encodeJson(write.value));
break;
case "task":
await this.claimId(executor, write.value.id, "task");
await executor.run(`INSERT INTO ${this.schema.tables.tasks} (id, conversation_id, kind, status, abort_requested, background, record)
VALUES (?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET conversation_id = excluded.conversation_id, kind = excluded.kind,
status = excluded.status, abort_requested = excluded.abort_requested,
background = excluded.background, record = excluded.record`, write.value.id, write.value.conversationId, encodeIndexedString(write.value.kind), write.value.state.status, write.value.abortRequested ? 1 : 0, write.value.background ? 1 : 0, encodeJson(write.value));
break;
case "submission":
await this.claimId(executor, write.value.id, "submission");
await executor.run(`INSERT INTO ${this.schema.tables.submissions} (id, conversation_id, request_id, status, record) VALUES (?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET conversation_id = excluded.conversation_id,
request_id = excluded.request_id, status = excluded.status, record = excluded.record`, write.value.id, write.value.conversationId, write.value.requestId === void 0 ? null : encodeIndexedString(write.value.requestId), write.value.status, encodeJson(write.value));
break;
case "document.create":
case "document.copy":
case "document.change":
case "document.retire":
break;
}
}
async claimId(executor, id, table) {
await executor.run(`INSERT OR IGNORE INTO ${this.schema.tables.recordIds} (id, record_type) VALUES (?, ?)`, id, table);
}
/** Resolve each copy to a base of its source's state before this batch, which may not change the source. */
async resolveCopies(executor, actions) {
for (const [id, action] of actions) {
if (action.copy === void 0)
continue;
try {
const stored = await this.materializeDocument(executor, action.copy.id, action.copy.at);
if (stored === void 0)
throw new Error(`Fork source document ${action.copy.id} cannot be read`);
const create = action.create;
if (stored.record.scope.kind !== "conversation" || create.scope.kind !== "conversation" || stored.record.kind !== create.kind || stored.record.key !== create.key || stored.record.history !== create.history || stored.record.fork !== create.fork) {
throw new Error(`Fork source document ${action.copy.id} does not match the copied record`);
}
action.content = { kind: "base", version: stored.version, value: stored.value };
} catch (error) {
throw new Error(`Document copy ${id} was rejected`, { cause: error });
}
}
}
async applyDocumentActions(executor, actions, seq) {
for (const [id, action] of actions) {
const content = action.content;
let record;
if (action.create !== void 0) {
record = {
...action.create,
createdAt: seq,
...action.retire ? { retiredAt: seq } : {}
};
const parts = addressParts(record);
await this.claimId(executor, id, "document");
await executor.run(`INSERT INTO ${this.schema.tables.documents}
(id, kind, family, key_value, scope_kind, owner_id, created_at, retired_at, record)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, id, parts.kind, parts.family, parts.keyValue, parts.scopeKind, parts.ownerId, seq, action.retire ? seq : null, encodeJson(record));
} else {
const row = await executor.get(`SELECT record FROM ${this.schema.tables.documents} WHERE id = ?`, id);
record = parseJson(row.record);
}
if (content !== void 0) {
if (content.kind === "base" && isCurrentOnly(record)) {
await executor.run(`DELETE FROM ${this.schema.tables.documentRevisions} WHERE document_id = ?`, id);
}
const encodedContent = content.kind === "base" ? encodeJson(content.value) : encodeJson(content.ops);
await executor.run(`INSERT INTO ${this.schema.tables.documentRevisions} (document_id, seq, kind, version, content) VALUES (?, ?, ?, ?, ?)`, id, seq, content.kind, content.version, encodedContent);
}
if (action.retire) {
if (action.create === void 0) {
record = { ...record, retiredAt: seq };
await executor.run(`UPDATE ${this.schema.tables.documents} SET retired_at = ?, record = ? WHERE id = ?`, seq, encodeJson(record), id);
}
if (isCurrentOnly(record)) {
await executor.run(`DELETE FROM ${this.schema.tables.documentRevisions} WHERE document_id = ?`, id);
}
}
}
}
assertOpen() {
if (this.closed)
throw new Error("SqliteStorage is closed");
}
};
// sqlite.ts
var op = (kind, sql = "", params = []) => Deno.core.ops.op_sql(kind, sql, params.map((p) => p instanceof Uint8Array ? Array.from(p) : typeof p === "bigint" ? Number(p) : p));
async function openStorage(path3) {
op("open", path3);
let tail = Promise.resolve();
const queue = (call) => {
const result = tail.then(call);
tail = result.then(() => {
}, () => {
});
return result;
};
const executor = {
exec: async (sql) => {
op("exec", sql);
},
run: async (sql, ...params) => {
op("run", sql, params);
},
runCounted: async (sql, ...params) => op("run", sql, params).changes,
get: async (sql, ...params) => (await executor.all(sql, ...params))[0],
all: async (sql, ...params) => op("all", sql, params).map((row) => Object.fromEntries(Object.entries(row).map(([key, value2]) => [key, Array.isArray(value2) ? new Uint8Array(value2) : value2])))
};
const database = Object.fromEntries(Object.entries(executor).map(([name, method]) => [name, (...args) => queue(() => method(...args))]));
database.transaction = (callback) => queue(async () => {
op("exec", "BEGIN IMMEDIATE");
try {
const result = await callback(executor);
op("exec", "COMMIT");
return result;
} catch (error) {
op("exec", "ROLLBACK");
throw error;
}
});
database.close = () => queue(async () => {
op("close");
});
return SqliteStorage.open(database);
}
// environment.ts
var ops = Deno.core.ops;
var ok = (value2) => ({ ok: true, value: value2 });
var path2 = (cwd, input) => {
const parts = [];
for (const p of (input.startsWith("/") ? input : `${cwd}/${input}`).split("/")) {
if (p === "..") parts.pop();
else if (p && p !== ".") parts.push(p);
}
return "/" + parts.join("/");
};
function environment(cwd = "/") {
const call = (kind, p, bytes2 = []) => ops.op_file(kind, path2(cwd, p), bytes2);
const env = {
id: "world",
cwd,
absolutePath: async (p) => ok(path2(cwd, p)),
canonicalPath: async () => ({ ok: false, error: { code: "not_supported", message: "The VFS does not expose canonical paths" } }),
joinPath: async (parts) => ok(path2(cwd, parts.join("/"))),
fileInfo: (p) => call("stat", p),
exists: async (p) => {
const result = await call("stat", p);
return result.ok ? ok(true) : result.error.code === "not_found" ? ok(false) : result;
},
readBinaryFile: async (p) => {
const r = await call("read", p);
return r.ok ? ok(new Uint8Array(r.value)) : r;
},
readTextFile: async (p) => {
const r = await env.readBinaryFile(p);
return r.ok ? ok(new TextDecoder().decode(r.value)) : r;
},
writeFile: async (p, content) => {
const full = path2(cwd, p);
const parent = full.slice(0, full.lastIndexOf("/")) || "/";
const created = await env.createDir(parent, { recursive: true });
if (!created.ok) return created;
return call("write", full, Array.from(typeof content === "string" ? new TextEncoder().encode(content) : content));
},
createDir: async (p, options) => {
const full = path2(cwd, p);
if (!options?.recursive) return call("mkdir", full);
let current = "";
for (const part of full.split("/").filter(Boolean)) {
current += "/" + part;
const exists = await call("stat", current);
if (!exists.ok) {
const r = await call("mkdir", current);
if (!r.ok) return r;
}
}
return ok(void 0);
},
openBinaryReader: async (p) => {
const data = await env.readBinaryFile(p);
if (!data.ok) return data;
const info = await env.fileInfo(p);
return ok({
info: async () => info,
read: async (offset, length) => ok(data.value.slice(offset, offset + length)),
scanLines: async (options) => {
const scanner = new LineScanner(options.startLine, options.endLine);
scanner.push(data.value);
return ok(scanner.finish());
},
close: async () => {
}
});
},
exec: async (command, options, context) => {
try {
const rid = ops.op_exec(command, options?.cwd ?? cwd, options?.timeout);
const decoders = { stdout: new TextDecoder(), stderr: new TextDecoder() };
let result;
while (true) {
const chunk = await ops.op_exec_next(rid);
if (!chunk.stream) {
result = chunk;
break;
}
options?.onOutput?.(decoders[chunk.stream].decode(new Uint8Array(chunk.bytes), { stream: true }), context, { stream: chunk.stream });
}
if (result.error) throw new Error(result.error);
for (const stream2 of ["stdout", "stderr"]) {
const text2 = decoders[stream2].decode();
if (text2) options?.onOutput?.(text2, context, { stream: stream2 });
}
return ok({ exitCode: result.exitCode });
} catch (error) {
return { ok: false, error };
}
},
cleanup: async () => {
}
};
return env;
}
// main.ts
if (!process.env.PI_PROXY_BASE_URL || !process.env.PI_PROXY_API_KEY) {
throw new Error("PI_PROXY_BASE_URL and PI_PROXY_API_KEY are required");
}
var models = createModels();
var provider2 = openaiProvider();
var model2 = {
id: "gpt-6.1-sol",
name: "gpt-6.1-sol",
provider: "openai",
api: "openai-responses",
baseUrl: `${process.env.PI_PROXY_BASE_URL}/v1`,
reasoning: true,
input: ["text"],
thinkingLevelMap: { off: null, minimal: null },
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 2e5,
maxTokens: 4096
};
models.setProvider({
...provider2,
baseUrl: model2.baseUrl,
getModels: () => [model2],
auth: { apiKey: { name: "Sausage proxy", resolve: async () => ({
auth: {
apiKey: process.env.PI_PROXY_API_KEY,
baseUrl: model2.baseUrl,
headers: { "Shopify-Usage-Tag": JSON.stringify(["pi", "sausage"]) }
},
source: "PI_PROXY_API_KEY"
}) } }
});
var registry = createRegistry();
registry.install(CodingTools);
var harness = await Harness.open(await openStorage(globalThis.storagePath), {
models,
registry,
env: (target) => environment(target.cwd ?? "/")
}, BACKGROUND_CONTEXT);
var root = await harness.root(BACKGROUND_CONTEXT, { agent: { model: { provider: "openai", modelId: model2.id }, thinkingLevel: "low", cwd: "/", extensions: [CodingTools] } });
var watch = await root.watch(BACKGROUND_CONTEXT);
var emitted = /* @__PURE__ */ new Map();
var partial = "";
var text = (message) => message?.content?.filter((b) => b.type === "text").map((b) => b.text).join("") ?? "";
var render = (view2) => {
for (const entry2 of view2.entries) {
if (entry2.kind !== "pi.assistant") continue;
const value2 = text(entry2.model?.[0]);
if (emitted.has(entry2.id)) continue;
if (value2.startsWith(partial)) Deno.core.ops.op_output(value2.slice(partial.length));
else Deno.core.ops.op_output(value2);
partial = "";
emitted.set(entry2.id, value2);
}
const live = text(view2.docs["pi.live"]?.generation?.message);
if (live.startsWith(partial)) Deno.core.ops.op_output(live.slice(partial.length));
partial = live;
};
for (const entry2 of watch.value.entries) {
if (entry2.kind === "pi.assistant") emitted.set(entry2.id, text(entry2.model?.[0]));
}
watch.start((event) => {
if (event.kind === "value") render(event.value);
});
harness.resume();
await harness.waitForIdle(BACKGROUND_CONTEXT);
while (true) {
const line = await Deno.core.ops.op_input();
if (line === null) break;
if (!line.trim()) continue;
const submission2 = await root.submit({ type: "input", content: line, requestId: crypto.randomUUID() }, BACKGROUND_CONTEXT);
const result = await submission2.wait(BACKGROUND_CONTEXT);
await harness.waitForIdle(BACKGROUND_CONTEXT);
const final = await root.watch(BACKGROUND_CONTEXT);
render(final.value);
await final.stop();
Deno.core.ops.op_output("\n");
if (result.status !== "done") throw new Error(`Run ended: ${JSON.stringify(result)}`);
}
await watch.stop();
await harness.close(BACKGROUND_CONTEXT);