openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
719 lines (718 loc) • 29.8 kB
JavaScript
import { p as clampPositiveTimerTimeoutMs } from "./number-coercion-CLj0HTDM.js";
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { t as hasNonEmptyString } from "./string-coerce-CIXf7egm.js";
import { r as truncateUtf16Safe } from "./utf16-slice-D_ngcYKd.js";
import { C as createChildDiagnosticTraceContext, D as freezeDiagnosticTraceContext, t as areDiagnosticsEnabledForProcess, x as formatPropagatedDiagnosticTraceparent } from "./diagnostic-events-Cwe92uV3.js";
import { n as emitDiagnosticsTimelineEvent } from "./diagnostics-timeline-CRX1LXmg.js";
import { t as isPromiseLike } from "./promise-like-D7-l5Fsp.js";
import { t as getGlobalHookRunner, y as fireAndForgetBoundedHook } from "./hook-runner-global-0kfmMG4T.js";
import { c as normalizeUsage, n as derivePromptTokens } from "./usage-CtmV8Xxq.js";
import { l as getStreamLlmRuntime } from "./stream-Ci9pOvq7.js";
import { o as createAnthropicVertexStreamFnForModel } from "./ai-transport-runtime-host-BaTpzgPr.js";
import { b as emitCoreModelRequestEndedDiagnosticEvent, x as emitCoreModelRequestStartedDiagnosticEvent, y as emitCoreSemanticRunProgressDiagnosticEvent } from "./diagnostic-run-activity-CJrEba4R.js";
import { a as diagnosticProviderRequestIdHash, i as diagnosticHttpStatusCode, n as diagnosticErrorFailureKind, t as diagnosticErrorCategory } from "./diagnostic-error-metadata-BgNm5seU.js";
import { t as cloneDiagnosticContentValue } from "./diagnostic-llm-content-CAc71KJ1.js";
import { t as createModelCallStreamProgressReporter } from "./diagnostic-model-stream-progress-DkFkdHqx.js";
import { createBoundaryAwareStreamFnForModel, withProviderAcceptanceObserver } from "@openclaw/ai/transports";
import { notifyLlmRequestActivity, onLlmRequestActivity } from "@openclaw/ai/internal/runtime";
import { stripSystemPromptCacheBoundary } from "@openclaw/ai/internal/shared";
//#region src/agents/embedded-agent-runner/stream-resolution.ts
const embeddedAgentBaseStreamFnCache = /* @__PURE__ */ new WeakMap();
function resolveEmbeddedAgentBaseStreamFn(params) {
const cached = embeddedAgentBaseStreamFnCache.get(params.session);
if (cached !== void 0 || embeddedAgentBaseStreamFnCache.has(params.session)) {
if (!cached) throw new Error("Agent session has no lifecycle-owned base stream.");
return cached;
}
const baseStreamFn = params.session.agent.streamFn;
embeddedAgentBaseStreamFnCache.set(params.session, baseStreamFn);
if (!baseStreamFn) throw new Error("Agent session has no lifecycle-owned base stream.");
return baseStreamFn;
}
function resolveEmbeddedStreamRuntime(owner) {
const runtime = owner.llmRuntime ?? getStreamLlmRuntime(owner.currentStreamFn);
if (!runtime) throw new Error("Embedded stream has no lifecycle runtime owner.");
return runtime;
}
function isDefaultOpenClawStreamFnForModel(model, streamFn, llmRuntime) {
if (!streamFn || streamFn === llmRuntime.streamSimple) return true;
const api = typeof model.api === "string" ? model.api.trim() : "";
if (!api) return false;
const provider = llmRuntime.registry.getApiProvider(api);
return streamFn === provider?.streamSimple || streamFn === provider?.stream;
}
function isOpenAICodexResponsesModel(model) {
return model.provider === "openai" && model.api === "openai-chatgpt-responses";
}
function resolveOpenClawNativeCodexResponsesStreamFn(params) {
if (!isOpenAICodexResponsesModel(params.model)) return;
if (!isDefaultOpenClawStreamFnForModel(params.model, params.currentStreamFn, params.llmRuntime) && getStreamLlmRuntime(params.currentStreamFn) !== params.llmRuntime) return;
return params.currentStreamFn ?? params.llmRuntime.streamSimple;
}
async function resolveEmbeddedAgentApiKey(params) {
const resolvedApiKey = params.resolvedApiKey?.trim();
if (resolvedApiKey) return resolvedApiKey;
return params.authStorage ? await params.authStorage.getApiKey(params.provider) : void 0;
}
function resolveEmbeddedAgentStream(params) {
const llmRuntime = resolveEmbeddedStreamRuntime(params);
const wrapOptions = {
runSignal: params.signal,
resolvedApiKey: params.resolvedApiKey,
authProfileId: params.authProfileId,
authStorage: params.authStorage,
providerId: params.model.provider,
promptCacheKey: params.promptCacheKey
};
const stripCacheBoundary = (context) => context.systemPrompt ? {
...context,
systemPrompt: stripSystemPromptCacheBoundary(context.systemPrompt)
} : context;
if (params.providerStreamFn) return {
streamFn: wrapEmbeddedAgentStreamFn(params.providerStreamFn, {
...wrapOptions,
transformContext: stripCacheBoundary
}),
strategy: "provider"
};
const currentStreamFn = params.currentStreamFn ?? llmRuntime.streamSimple;
if (params.model.provider === "anthropic-vertex") {
const vertexStreamFn = createAnthropicVertexStreamFnForModel(params.model);
return {
streamFn: params.signal ? wrapEmbeddedAgentStreamFn(vertexStreamFn, {
runSignal: params.signal,
providerId: params.model.provider
}) : vertexStreamFn,
strategy: "anthropic-vertex"
};
}
const nativeStreamFn = resolveOpenClawNativeCodexResponsesStreamFn({
model: params.model,
currentStreamFn: params.currentStreamFn,
llmRuntime
});
if (nativeStreamFn) return {
streamFn: wrapEmbeddedAgentStreamFn(nativeStreamFn, {
...wrapOptions,
sessionId: params.sessionId,
transformContext: stripCacheBoundary
}),
strategy: "openclaw-native-codex-responses"
};
const isDefault = isDefaultOpenClawStreamFnForModel(params.model, params.currentStreamFn, llmRuntime);
if (isDefault || hasNonEmptyString(params.resolvedApiKey) || params.transportAuthAvailable || params.model.api === "anthropic-messages" && params.model.provider !== "anthropic") {
const boundaryAwareStreamFn = createBoundaryAwareStreamFnForModel(params.model);
if (boundaryAwareStreamFn) return {
streamFn: wrapEmbeddedAgentStreamFn(boundaryAwareStreamFn, {
...wrapOptions,
sessionId: params.sessionId
}),
strategy: `boundary-aware:${params.model.api}`
};
}
const promptCacheKey = params.promptCacheKey?.trim();
return {
streamFn: !promptCacheKey && !params.signal ? currentStreamFn : wrapEmbeddedAgentStreamFn(currentStreamFn, {
runSignal: params.signal,
providerId: params.model.provider,
promptCacheKey
}),
strategy: isDefault ? "stream-simple" : "session-custom"
};
}
/** Preserve request activity across cancellation composition without retaining completed turns. */
function composeRunSignal(callerSignal, runSignal) {
const composedSignal = AbortSignal.any([callerSignal, runSignal]);
onLlmRequestActivity(composedSignal, () => {
if (!composedSignal.aborted) notifyLlmRequestActivity(callerSignal);
});
return composedSignal;
}
function wrapEmbeddedAgentStreamFn(inner, params) {
const transformContext = params.transformContext ?? ((context) => context);
const mergeRunSignal = (options) => {
const embeddedOptions = options;
const callerSignal = embeddedOptions?.signal;
const signal = callerSignal && params.runSignal && callerSignal !== params.runSignal ? composeRunSignal(callerSignal, params.runSignal) : callerSignal ?? params.runSignal;
let merged = params.sessionId && !embeddedOptions?.sessionId ? {
...embeddedOptions,
sessionId: params.sessionId
} : embeddedOptions;
const promptCacheKey = params.promptCacheKey?.trim();
if (promptCacheKey && !merged?.promptCacheKey) merged = {
...merged,
promptCacheKey
};
if (params.authProfileId && !merged?.authProfileId) merged = {
...merged,
authProfileId: params.authProfileId
};
return signal ? {
...merged,
signal
} : merged;
};
if (!params.authStorage && !params.resolvedApiKey) return (m, context, options) => inner(m, transformContext(context), mergeRunSignal(options));
const { authStorage, providerId, resolvedApiKey } = params;
return async (m, context, options) => {
const selectedApiKey = await resolveEmbeddedAgentApiKey({
provider: providerId,
resolvedApiKey,
authStorage
}) ?? options?.apiKey;
return inner(m, transformContext(context), {
...mergeRunSignal(options),
apiKey: selectedApiKey
});
};
}
//#endregion
//#region src/agents/embedded-agent-runner/run/attempt.model-diagnostic-lifecycle.ts
const TRACEPARENT_HEADER_NAME = "traceparent";
const TIMELINE_ATTRIBUTE_MAX_LENGTH = 256;
function baseModelCallEvent(ctx, callId, trace, promptStats) {
return {
runId: ctx.runId,
callId,
...ctx.sessionKey && { sessionKey: ctx.sessionKey },
...ctx.sessionId && { sessionId: ctx.sessionId },
provider: ctx.provider,
model: ctx.model,
...ctx.api && { api: ctx.api },
...ctx.transport && { transport: ctx.transport },
observationUnit: "request",
...ctx.contextTokenBudget ? { contextTokenBudget: ctx.contextTokenBudget } : {},
...ctx.contextWindowSource ? { contextWindowSource: ctx.contextWindowSource } : {},
...ctx.contextWindowReferenceTokens ? { contextWindowReferenceTokens: ctx.contextWindowReferenceTokens } : {},
...promptStats ? { promptStats } : {},
trace
};
}
function modelContentPrivateData(modelContent) {
return modelContent ? { modelContent } : void 0;
}
function boundedTimelineAttribute(value) {
return truncateUtf16Safe(value?.trim() ?? "", TIMELINE_ATTRIBUTE_MAX_LENGTH) || void 0;
}
function emitProviderRequestTimelineEvent(eventBase, startedAt, durationMs, ok, responseStatus, providerAcceptanceKind) {
const provider = boundedTimelineAttribute(eventBase.provider);
const model = boundedTimelineAttribute(eventBase.model);
const api = boundedTimelineAttribute(eventBase.api);
const transport = boundedTimelineAttribute(eventBase.transport);
emitDiagnosticsTimelineEvent({
type: "provider.request",
name: "provider.request",
timestamp: new Date(startedAt).toISOString(),
runId: eventBase.runId,
spanId: eventBase.callId,
durationMs,
provider,
operation: api ?? transport ?? "model.call",
ok,
...responseStatus !== void 0 ? { status: responseStatus } : {},
attributes: {
...model ? { model } : {},
...api ? { api } : {},
...transport ? { transport } : {},
providerAccepted: providerAcceptanceKind !== void 0,
...providerAcceptanceKind ? { providerAcceptanceKind } : {}
}
});
}
function modelCallErrorFields(err) {
const upstreamRequestIdHash = diagnosticProviderRequestIdHash(err);
const failureKind = diagnosticErrorFailureKind(err);
return {
errorCategory: diagnosticErrorCategory(err),
...failureKind ? {
failureKind,
memory: processMemoryUsageSnapshot()
} : {},
...upstreamRequestIdHash ? { upstreamRequestIdHash } : {}
};
}
function processMemoryUsageSnapshot() {
try {
const memory = process.memoryUsage();
return {
rssBytes: memory.rss,
heapTotalBytes: memory.heapTotal,
heapUsedBytes: memory.heapUsed,
externalBytes: memory.external,
arrayBuffersBytes: memory.arrayBuffers
};
} catch {
return;
}
}
function modelCallHookEventBase(eventBase) {
return {
runId: eventBase.runId,
callId: eventBase.callId,
...eventBase.sessionKey ? { sessionKey: eventBase.sessionKey } : {},
...eventBase.sessionId ? { sessionId: eventBase.sessionId } : {},
provider: eventBase.provider,
model: eventBase.model,
...eventBase.api ? { api: eventBase.api } : {},
...eventBase.transport ? { transport: eventBase.transport } : {},
...eventBase.contextTokenBudget ? { contextTokenBudget: eventBase.contextTokenBudget } : {},
...eventBase.contextWindowSource ? { contextWindowSource: eventBase.contextWindowSource } : {},
...eventBase.contextWindowReferenceTokens ? { contextWindowReferenceTokens: eventBase.contextWindowReferenceTokens } : {}
};
}
function modelCallHookContext(eventBase) {
return Object.freeze({
runId: eventBase.runId,
trace: eventBase.trace,
...eventBase.sessionKey ? { sessionKey: eventBase.sessionKey } : {},
...eventBase.sessionId ? { sessionId: eventBase.sessionId } : {},
modelProviderId: eventBase.provider,
modelId: eventBase.model,
...eventBase.contextTokenBudget ? { contextTokenBudget: eventBase.contextTokenBudget } : {},
...eventBase.contextWindowSource ? { contextWindowSource: eventBase.contextWindowSource } : {},
...eventBase.contextWindowReferenceTokens ? { contextWindowReferenceTokens: eventBase.contextWindowReferenceTokens } : {}
});
}
function dispatchModelCallStartedHook(eventBase) {
const hookRunner = getGlobalHookRunner();
if (!hookRunner?.hasHooks("model_call_started")) return;
const event = Object.freeze(modelCallHookEventBase(eventBase));
const hookCtx = modelCallHookContext(eventBase);
fireAndForgetBoundedHook(() => hookRunner.runModelCallStarted(event, hookCtx), "model_call_started plugin hook failed");
}
function dispatchModelCallEndedHook(eventBase, fields) {
const hookRunner = getGlobalHookRunner();
if (!hookRunner?.hasHooks("model_call_ended")) return;
const event = Object.freeze({
...modelCallHookEventBase(eventBase),
...fields
});
const hookCtx = modelCallHookContext(eventBase);
fireAndForgetBoundedHook(() => hookRunner.runModelCallEnded(event, hookCtx), "model_call_ended plugin hook failed");
}
function emitModelCallEnded(eventBase, startedAt, observer, failure, ownerGeneration) {
if (observer.state.terminalEventEmitted) return;
observer.state.terminalEventEmitted = true;
const durationMs = Date.now() - startedAt;
const sizeTimingFields = observer.sizeTimingFields();
const fields = failure ? modelCallErrorFields(failure.error) : void 0;
const terminal = fields ? {
type: "model.call.error",
...fields
} : { type: "model.call.completed" };
const errorStatus = failure ? diagnosticHttpStatusCode(failure.error) : void 0;
const responseStatus = observer.state.responseStatus ?? (errorStatus === void 0 ? void 0 : Number(errorStatus));
emitProviderRequestTimelineEvent(eventBase, startedAt, durationMs, failure === void 0, responseStatus, observer.state.providerAcceptanceKind);
emitCoreModelRequestEndedDiagnosticEvent({
...terminal,
...eventBase,
durationMs,
...sizeTimingFields,
...observer.usageField()
}, ownerGeneration, modelContentPrivateData(observer.completedContent()));
if (!observer.state.suppressPluginHooks) dispatchModelCallEndedHook(eventBase, {
durationMs,
outcome: failure ? "error" : "completed",
...sizeTimingFields,
...fields
});
}
function withDiagnosticRequestContext(options, trace, observer, callId) {
const traceparent = formatPropagatedDiagnosticTraceparent(trace);
const originalOnPayload = options?.onPayload;
const originalOnResponse = options?.onResponse;
const onPayload = (payload, model) => {
if (!originalOnPayload) {
observer.assignRequestPayloadBytes(payload);
return;
}
const result = originalOnPayload(payload, model);
if (isPromiseLike(result)) return result.then((replacement) => {
observer.assignRequestPayloadBytes(replacement ?? payload);
return replacement;
});
observer.assignRequestPayloadBytes(result ?? payload);
return result;
};
const onResponse = (response, model) => {
observer.state.responseStatus = response.status;
return originalOnResponse?.(response, model);
};
const headers = {};
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (key.toLowerCase() === TRACEPARENT_HEADER_NAME) continue;
headers[key] = value;
}
if (traceparent) headers[TRACEPARENT_HEADER_NAME] = traceparent;
const requestOptions = {
...options,
requestId: callId,
...(options?.headers || traceparent) && { headers },
onPayload,
onResponse
};
return withProviderAcceptanceObserver(requestOptions, (acceptance) => {
observer.state.providerAcceptanceKind = acceptance.kind;
if (acceptance.kind === "http_response") observer.state.responseStatus = acceptance.status;
});
}
function createModelLifecycle(params) {
const callId = params.ctx.nextCallId();
const trace = freezeDiagnosticTraceContext(createChildDiagnosticTraceContext(params.ctx.trace));
const observer = params.createObserver(areDiagnosticsEnabledForProcess());
const eventBase = baseModelCallEvent(params.ctx, callId, trace, observer.promptStats);
emitCoreModelRequestStartedDiagnosticEvent(eventBase, params.ctx.ownerGeneration, params.requestTimeoutMs, modelContentPrivateData(observer.modelContent));
if (params.ctx.suppressPluginHooks !== true) dispatchModelCallStartedHook(eventBase);
params.ctx.onStarted?.();
const startedAt = Date.now();
return {
eventBase,
observer,
propagatedOptions: withDiagnosticRequestContext(params.options, trace, observer, callId),
startedAt,
emitCompleted() {
emitModelCallEnded(eventBase, startedAt, observer, observer.state.terminalError ? { error: observer.state.terminalError } : void 0, params.ctx.ownerGeneration);
},
emitError(err) {
emitModelCallEnded(eventBase, startedAt, observer, { error: err }, params.ctx.ownerGeneration);
}
};
}
//#endregion
//#region src/agents/embedded-agent-runner/run/attempt.model-diagnostic-observation.ts
const MODEL_CALL_SEMANTIC_PROGRESS_REASON = "model_call:semantic_result";
function utf8JsonByteLength(value) {
try {
return Buffer.byteLength(JSON.stringify(value), "utf8");
} catch {
return;
}
}
function assignRequestPayloadBytes(state, payload) {
const bytes = utf8JsonByteLength(payload);
if (bytes !== void 0) state.requestPayloadBytes = bytes;
}
function utf8StringByteLength(value) {
return Buffer.byteLength(value, "utf8");
}
function jsonCharLength(value) {
try {
return JSON.stringify(value)?.length;
} catch {
return;
}
}
function streamDeltaByteLength(chunk) {
const type = chunk.type;
if ((type === "text_delta" || type === "thinking_delta" || type === "toolcall_delta") && typeof chunk.delta === "string") return utf8StringByteLength(chunk.delta);
}
function responseStreamChunkByteLengthUnchecked(chunk) {
if (!isRecord(chunk)) return utf8JsonByteLength(chunk);
const deltaBytes = streamDeltaByteLength(chunk);
if (deltaBytes !== void 0) return deltaBytes;
if (!("partial" in chunk)) return utf8JsonByteLength(chunk);
const { partial: _partial, ...snapshotlessChunk } = chunk;
return utf8JsonByteLength(snapshotlessChunk);
}
function responseStreamChunkByteLength(chunk) {
try {
return responseStreamChunkByteLengthUnchecked(chunk);
} catch {
return;
}
}
function streamContextModelContentFields(policy, streamContext) {
if (!policy?.anyModelContent || !isRecord(streamContext)) return;
const content = {
...policy.inputMessages && Array.isArray(streamContext.messages) ? { inputMessages: cloneDiagnosticContentValue(streamContext.messages) } : {},
...policy.systemPrompt && typeof streamContext.systemPrompt === "string" ? { systemPrompt: streamContext.systemPrompt } : {},
...policy.toolDefinitions && Array.isArray(streamContext.tools) ? { toolDefinitions: cloneDiagnosticContentValue(streamContext.tools) } : {}
};
return Object.keys(content).length > 0 ? content : void 0;
}
function streamContextModelPromptStats(streamContext) {
if (!isRecord(streamContext)) return;
const messages = Array.isArray(streamContext.messages) ? streamContext.messages : void 0;
const tools = Array.isArray(streamContext.tools) ? streamContext.tools : void 0;
const systemPrompt = typeof streamContext.systemPrompt === "string" ? streamContext.systemPrompt : void 0;
const inputMessagesChars = messages ? jsonCharLength(messages) : void 0;
const toolDefinitionsChars = tools ? jsonCharLength(tools) : void 0;
const systemPromptChars = systemPrompt?.length;
if (messages === void 0 && tools === void 0 && systemPromptChars === void 0 && inputMessagesChars === void 0 && toolDefinitionsChars === void 0) return;
const totalChars = (inputMessagesChars ?? 0) + (systemPromptChars ?? 0) + (toolDefinitionsChars ?? 0);
return {
...messages ? { inputMessagesCount: messages.length } : {},
...inputMessagesChars !== void 0 ? { inputMessagesChars } : {},
...systemPromptChars !== void 0 ? { systemPromptChars } : {},
...tools ? { toolDefinitionsCount: tools.length } : {},
...toolDefinitionsChars !== void 0 ? { toolDefinitionsChars } : {},
totalChars
};
}
function normalizedModelCallUsage(rawUsage) {
if (!isRecord(rawUsage)) return;
const usage = normalizeUsage(rawUsage);
if (!usage) return;
const promptTokens = derivePromptTokens(usage);
return {
...usage,
...promptTokens !== void 0 ? { promptTokens } : {}
};
}
function observeModelCallTerminalMessage(state, value) {
if (!isRecord(value)) return;
let rawUsage;
try {
rawUsage = value.usage;
if (value.role === "assistant" && (value.stopReason === "error" || value.stopReason === "aborted")) state.terminalError ??= Object.assign(new Error(typeof value.errorMessage === "string" ? value.errorMessage : value.stopReason), { code: value.stopReason === "aborted" ? "ABORT_ERR" : value.errorCode });
} catch {
return;
}
const usage = normalizedModelCallUsage(rawUsage);
if (usage) state.usage = usage;
}
function observeOutputMessageContent(state, chunk) {
if (!isRecord(chunk)) return;
let type;
let message;
try {
type = chunk.type;
message = type === "done" ? chunk.message : type === "error" ? chunk.error : void 0;
} catch {
return;
}
if (message !== void 0) {
observeModelCallTerminalMessage(state, message);
if (state.contentCapture?.outputMessages) state.outputMessages = [cloneDiagnosticContentValue(message)];
}
}
function observeResultMessageContent(state, startedAt, result) {
state.timeToFirstByteMs ??= Math.max(0, Date.now() - startedAt);
observeModelCallTerminalMessage(state, result);
if (state.contentCapture?.outputMessages && state.outputMessages === void 0) state.outputMessages = [cloneDiagnosticContentValue(result)];
if (state.responseStreamBytes === 0) {
const bytes = utf8JsonByteLength(result);
if (bytes !== void 0) state.responseStreamBytes = bytes;
}
}
function isNormalizedToolCall(value) {
if (!isRecord(value) || value.type !== "toolCall") return false;
return typeof value.id === "string" && value.id.trim().length > 0 && typeof value.name === "string" && value.name.trim().length > 0 && isRecord(value.arguments);
}
function isSemanticModelCallResult(result) {
try {
if (!isRecord(result) || result.role !== "assistant" || result.stopReason === "error" || result.stopReason === "aborted" || !Array.isArray(result.content)) return false;
return result.stopReason === "toolUse" && result.content.some(isNormalizedToolCall) || result.content.some((item) => isRecord(item) && item.type === "text" && typeof item.text === "string" && item.text.trim().length > 0);
} catch {
return false;
}
}
function maybeEmitModelCallSemanticProgress(eventBase, state, result) {
if (state.semanticProgressEmitted || !isSemanticModelCallResult(result)) return;
state.semanticProgressEmitted = true;
emitCoreSemanticRunProgressDiagnosticEvent({
runId: eventBase.runId,
...eventBase.sessionKey ? { sessionKey: eventBase.sessionKey } : {},
...eventBase.sessionId ? { sessionId: eventBase.sessionId } : {},
reason: MODEL_CALL_SEMANTIC_PROGRESS_REASON
});
}
function observeResponseChunk(state, startedAt, chunk) {
state.timeToFirstByteMs ??= Math.max(0, Date.now() - startedAt);
observeOutputMessageContent(state, chunk);
const bytes = responseStreamChunkByteLength(chunk);
if (bytes !== void 0) state.responseStreamBytes += bytes;
}
function modelCallSizeTimingFields(state) {
return {
...state.requestPayloadBytes !== void 0 ? { requestPayloadBytes: state.requestPayloadBytes } : {},
...state.responseStreamBytes > 0 ? { responseStreamBytes: state.responseStreamBytes } : {},
...state.timeToFirstByteMs !== void 0 ? { timeToFirstByteMs: state.timeToFirstByteMs } : {}
};
}
function modelCallCompletedContent(state) {
if (!state.modelContent && !state.outputMessages) return;
return {
...state.modelContent,
...state.outputMessages ? { outputMessages: state.outputMessages } : {}
};
}
function modelCallUsageField(state) {
return state.usage ? { usage: state.usage } : {};
}
function createModelObserver(params) {
const modelContent = streamContextModelContentFields(params.contentCapture, params.streamContext);
const promptStats = params.capturePromptStats ? streamContextModelPromptStats(params.streamContext) : void 0;
const state = {
responseStreamBytes: 0,
modelContent,
contentCapture: params.contentCapture,
suppressPluginHooks: params.suppressPluginHooks
};
const reportStreamProgress = createModelCallStreamProgressReporter();
return {
state,
promptStats,
modelContent,
assignRequestPayloadBytes(payload) {
assignRequestPayloadBytes(state, payload);
},
observeResponseChunk(startedAt, chunk) {
observeResponseChunk(state, startedAt, chunk);
},
observeFinalResult(eventBase, startedAt, result) {
observeResultMessageContent(state, startedAt, result);
maybeEmitModelCallSemanticProgress(eventBase, state, result);
},
maybeEmitStreamProgress(eventBase) {
reportStreamProgress(eventBase);
},
sizeTimingFields() {
return modelCallSizeTimingFields(state);
},
completedContent() {
return modelCallCompletedContent(state);
},
usageField() {
return modelCallUsageField(state);
}
};
}
//#endregion
//#region src/agents/embedded-agent-runner/run/attempt.model-diagnostic-events.ts
const MODEL_CALL_STREAM_RETURN_TIMEOUT_MS = 1e3;
function asyncIteratorFactory(value) {
if (value === null || typeof value !== "object") return;
try {
const asyncIterator = value[Symbol.asyncIterator];
if (typeof asyncIterator !== "function") return;
return () => asyncIterator.call(value);
} catch {
return;
}
}
async function safeReturnIterator(iterator) {
let returnResult;
try {
returnResult = iterator.return?.();
} catch {
return;
}
if (!returnResult) return;
let timeout;
try {
await Promise.race([Promise.resolve(returnResult).catch(() => void 0), new Promise((resolve) => {
timeout = setTimeout(resolve, MODEL_CALL_STREAM_RETURN_TIMEOUT_MS);
const unref = typeof timeout === "object" && timeout ? timeout.unref : void 0;
if (unref) unref.call(timeout);
})]);
} finally {
if (timeout) clearTimeout(timeout);
}
}
async function* observeModelCallIterator(iterator, lifecycle) {
let iteratorSettled = false;
try {
for (;;) {
const next = await iterator.next();
if (next.done) {
iteratorSettled = true;
break;
}
lifecycle.observer.observeResponseChunk(lifecycle.startedAt, next.value);
lifecycle.observer.maybeEmitStreamProgress(lifecycle.eventBase);
yield next.value;
}
lifecycle.emitCompleted();
} catch (err) {
iteratorSettled = true;
lifecycle.emitError(err);
throw err;
} finally {
if (!iteratorSettled) {
await safeReturnIterator(iterator);
lifecycle.emitCompleted();
}
}
}
function observeModelCallFinalResult(result, lifecycle) {
lifecycle.observer.observeFinalResult(lifecycle.eventBase, lifecycle.startedAt, result);
lifecycle.emitCompleted();
return result;
}
function createObservedResultFunction(stream, lifecycle) {
if (!isRecord(stream) || typeof stream.result !== "function") return;
const resultFn = stream.result;
return (...args) => {
try {
const result = resultFn.apply(stream, args);
if (isPromiseLike(result)) return result.then((resolved) => observeModelCallFinalResult(resolved, lifecycle), (err) => {
lifecycle.emitError(err);
throw err;
});
return observeModelCallFinalResult(result, lifecycle);
} catch (err) {
lifecycle.emitError(err);
throw err;
}
};
}
function observeModelCallStream(stream, createIterator, lifecycle) {
const observedIterator = () => observeModelCallIterator(createIterator(), lifecycle)[Symbol.asyncIterator]();
const observedResult = createObservedResultFunction(stream, lifecycle);
let hasNonConfigurableIterator;
try {
hasNonConfigurableIterator = Object.getOwnPropertyDescriptor(stream, Symbol.asyncIterator)?.configurable === false;
} catch {
hasNonConfigurableIterator = true;
}
if (hasNonConfigurableIterator) return {
[Symbol.asyncIterator]: observedIterator,
...observedResult ? { result: observedResult } : {}
};
return new Proxy(stream, { get(target, property, receiver) {
if (property === Symbol.asyncIterator) return observedIterator;
if (property === "result" && observedResult) return observedResult;
const value = Reflect.get(target, property, receiver);
return typeof value === "function" ? value.bind(target) : value;
} });
}
function observeModelCallResult(result, lifecycle) {
const createIterator = asyncIteratorFactory(result);
if (createIterator) return observeModelCallStream(result, createIterator, lifecycle);
lifecycle.emitCompleted();
return result;
}
/**
* Wraps a model stream function with diagnostic model-call lifecycle events,
* traceparent propagation, request/response byte accounting, optional captured
* model content, progress heartbeats, and plugin hook dispatch.
*/
function wrapStreamFnWithDiagnosticModelCallEvents(streamFn, ctx) {
return ((model, streamContext, options) => {
const lifecycle = createModelLifecycle({
ctx,
options,
requestTimeoutMs: clampPositiveTimerTimeoutMs((isRecord(model) ? model.requestTimeoutMs : void 0) ?? ctx.requestTimeoutMs),
createObserver: (capturePromptStats) => createModelObserver({
streamContext,
contentCapture: ctx.contentCapture,
suppressPluginHooks: ctx.suppressPluginHooks,
capturePromptStats
})
});
try {
const result = streamFn(model, streamContext, lifecycle.propagatedOptions);
if (isPromiseLike(result)) return result.then((resolved) => observeModelCallResult(resolved, lifecycle), (err) => {
lifecycle.emitError(err);
throw err;
});
return observeModelCallResult(result, lifecycle);
} catch (err) {
lifecycle.emitError(err);
throw err;
}
});
}
//#endregion
export { resolveEmbeddedAgentStream as i, resolveEmbeddedAgentApiKey as n, resolveEmbeddedAgentBaseStreamFn as r, wrapStreamFnWithDiagnosticModelCallEvents as t };