@onereach/step-create-chat-completion 0.0.7-rc.67 → 0.0.7-rc.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +13 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["defaultOptions","memoizeTag","memoizeTag","stepEvents"],"sources":["../src/errors/step-error.ts","../src/errors/error-filter.ts","../src/utils/create-method-decorator.ts","../src/decorators/background-thread-error-filter.ts","../src/utils/process-abort-controller.ts","../src/utils/thread-utilities.ts","../src/decorators/error-filter.ts","../src/schemas/otel-config.ts","../src/schemas/data-in.ts","../src/threads/base/base.ts","../src/threads/base/constants.ts","../src/threads/cancel/constants.ts","../src/threads/cancel/cancel-context.ts","../src/threads/history/types.ts","../src/threads/history/history-context.ts","../src/threads/request/constants.ts","../src/threads/content/constants.ts","../src/threads/request/response-handlers/abstract-response-handler.ts","../src/threads/request/response-handlers/simple-response-handler.ts","../src/threads/request/response-handlers/stream-response-handler.ts","../src/threads/request/factories/response-handler.ts","../src/services/thread-service-with-data.ts","../src/threads/request/services/openai-request.ts","../src/threads/request/services/otel-helpers/attributes.ts","../src/threads/request/services/otel-helpers/events.ts","../src/threads/request/services/otel-helpers/metrics/operation-duration.ts","../src/threads/request/services/otel-helpers/metrics/time-per-output-chunk.ts","../src/threads/request/services/otel-helpers/metrics/time-to-first-chunk.ts","../src/threads/request/services/otel-helpers/metrics/token-usage.ts","../src/utils/openai-stream-reducer.ts","../src/threads/request/services/otel-helpers/traces.ts","../src/threads/request/services/openai-request-otel.ts","../src/threads/request/request-context.ts","../src/threads/tools/worker/constants.ts","../src/threads/tools/worker/tools-context-worker.ts","../src/threads/tools/context/constants.ts","../src/threads/tools/context/tools-context.ts","../src/threads/content/abstract-content-context.ts","../src/threads/content/simple/constants.ts","../src/threads/content/simple/simple-content-context.ts","../src/utils/extract-tts-phrases.ts","../src/threads/content/stream/schemas/stream-chunk.ts","../src/threads/content/stream/worker/constants.ts","../src/threads/content/stream/worker/stream-content-context-worker.ts","../src/threads/content/stream/context/constants.ts","../src/threads/content/stream/context/stream-content-context.ts","../src/utils/validate-flow-sdk-version.ts","../src/threads/content/content-context-utilities.ts","../src/threads/main/step.ts","../src/index.ts"],"sourcesContent":["import BaseError from '@onereach/flow-sdk/errors/base.js';\n\nexport const ErrorCode = {\n UNKNOWN: 'UNKNOWN',\n STEP_LOGIC_ISSUE: 'STEP_LOGIC_ISSUE',\n AUTH: 'AUTH',\n TIMEOUT: 'TIMEOUT',\n VALIDATION: 'VALIDATION',\n INVALID_REQUEST: 'INVALID_REQUEST',\n RATE_LIMITED: 'RATE_LIMITED',\n LLM_FINISH_LENGTH: 'LLM_FINISH_LENGTH',\n SERVER_ERROR: 'SERVER_ERROR',\n UNSUPPORTED: 'UNSUPPORTED',\n} as const;\n\nexport class CreateChatCompletionStepError extends BaseError<{\n code: keyof typeof ErrorCode;\n data?: unknown;\n}> {}\n\nexport class AbortRequestError extends BaseError {}\n","import TimeoutError from '@onereach/flow-sdk/errors/timeout.js';\nimport * as z from 'zod/mini';\n\nimport { CreateChatCompletionStepError, ErrorCode } from './step-error.ts';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\nconst defaultPreserveErrors = [CreateChatCompletionStepError, TimeoutError] as const;\nexport function errorFilter<P extends readonly AnyErrorClass[] = typeof defaultPreserveErrors>(\n error: unknown,\n options: ErrorFilterOptions<P> = {},\n): InstancesOf<P> | CreateChatCompletionStepError | TimeoutError {\n const {\n preserveErrors = defaultPreserveErrors,\n unknownMessage = 'Unknown error',\n unknownCode = ErrorCode.UNKNOWN,\n } = options;\n\n // if error is CreateChatCompletionStepError or TimeoutError, return it directly\n if (preserveErrors?.some((ErrorClass) => error instanceof ErrorClass)) {\n return error as InstancesOf<P>;\n }\n\n // validation errors\n if (error instanceof z.core.$ZodError) {\n return new CreateChatCompletionStepError(z.prettifyError(error), error, {\n code: ErrorCode.VALIDATION,\n });\n }\n\n // if error is a string assume it's an error message\n if (typeof error === 'string') {\n return new CreateChatCompletionStepError(error, {\n code: ErrorCode.UNKNOWN,\n });\n }\n\n if (error instanceof Error) {\n // timeout errors\n if (error.message.includes('Request timed out')) {\n return new TimeoutError('Timeout', error, { code: ErrorCode.TIMEOUT });\n }\n\n // TODO: fix interpreting of this kind of errors\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n const responseErrorMessage: string | undefined = (error as unknown as any)?.response?.data?.error?.message;\n if (responseErrorMessage != undefined) {\n return new CreateChatCompletionStepError(responseErrorMessage, error, {\n code: ErrorCode.SERVER_ERROR,\n });\n }\n\n return new CreateChatCompletionStepError(unknownMessage, error, {\n code: unknownCode,\n });\n }\n\n // catch all for unknown errors\n return new CreateChatCompletionStepError(unknownMessage, {\n code: unknownCode,\n data: error,\n });\n}\n\nexport type ErrorFilterOptions<P extends readonly AnyErrorClass[]> = {\n /** Array of error classes that should not be wrapped */\n preserveErrors?: P;\n /** Error message to use when message is unknown */\n unknownMessage?: string;\n /** Error code to use when message is unknown */\n unknownCode?: keyof typeof ErrorCode;\n};\n\n/** Any Error class */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyErrorClass<E extends Error = Error> = new (...arguments_: any[]) => E;\n\n/** Turn a tuple/array of constructors into a union of their instance types. */\nexport type InstancesOf<Ctors extends readonly AnyErrorClass[]> =\n Ctors[number] extends AnyErrorClass<infer I> ? I : never;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Creates a method decorator that can be used with or without options.\n * @param apply - Function that applies the decorator logic with given options.\n * @param defaultOptions - Default options to use if none are provided.\n */\nexport function createMethodDecoratorWithOptionalArguments<A, T extends AnyFunction = AnyFunction>(\n apply: (\n options: A,\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ) => T | TypedPropertyDescriptor<T> | void,\n defaultOptions: A,\n): MethodDecoratorWithOptionalArguments<A, T> {\n function runApply(\n options: A,\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ): TypedPropertyDescriptor<T> | void {\n const maybe = apply(options, target, propertyKey, descriptor);\n\n // If the decorator factory returned a wrapped function, assign it to the descriptor here\n if (typeof maybe === 'function') {\n const originalMethod = descriptor.value;\n const wrappedMethod = maybe as typeof originalMethod;\n\n if (originalMethod?.name != undefined) {\n try {\n Object.defineProperty(wrappedMethod, 'name', { value: originalMethod.name });\n } catch {\n // ignore if name is non-configurable\n }\n }\n\n descriptor.value = wrappedMethod;\n return descriptor;\n }\n\n // If a descriptor was returned or decorator mutated descriptor in-place, use that\n return maybe ?? descriptor;\n }\n\n return function decoratorOrFactory(\n argument0?: object | A,\n argument1?: string | symbol,\n argument2?: TypedPropertyDescriptor<T>,\n ): any {\n if (\n argument0 !== null &&\n typeof argument0 === 'object' &&\n (typeof argument1 === 'string' || typeof argument1 === 'symbol') &&\n argument2 !== null &&\n typeof argument2 === 'object'\n ) {\n // Called as plain decorator: @Decorator\n return runApply(defaultOptions, argument0, argument1, argument2);\n }\n\n // Called as decorator factory: @Decorator(options)\n const options = (argument0 as A) ?? defaultOptions;\n return (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => {\n return runApply(options, target, propertyKey, descriptor);\n };\n };\n}\n\nexport type AnyFunction = (...arguments_: any[]) => any;\n\nexport type MethodDecoratorWithOptionalArguments<A, T extends AnyFunction = AnyFunction> =\n // Plain method decorator (three arguments)\n ((\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ) => TypedPropertyDescriptor<T> | void) &\n // Decorator factory (optional options argument)\n ((options?: A) => MethodDecorator);\n","/* eslint-disable unicorn/prefer-await */\n/* eslint-disable unicorn/no-this-outside-of-class */\nimport type { Step } from '@onereach/flow-sdk/step.js';\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\n\nimport { errorFilter } from '../errors/error-filter.ts';\nimport { createMethodDecoratorWithOptionalArguments } from '../utils/create-method-decorator.ts';\n\nconst defaultOptions: BackgroundThreadErrorFilterOptions = { allowHandleError: false, useErrorFilter: true };\n\n/**\n * Since errors in hooks are fatal and can't be processed this decorator allows to wrap hook handler\n * and manage errors by ending a thread with the error (preventing sending error to `error` exit)\n * @param options.allowHandleError - Default `false`. If `false` in case of error will end thread with error as result, if `true` will allow to handle error via 'error' exit\n * @param options.useErrorFilter - Default `true`. If `true` every error wild be processed with `errorFilter` utility function\n */\nexport const BackgroundThreadErrorFilter = createMethodDecoratorWithOptionalArguments(\n (options, _target, propertyKey, descriptor) => {\n const originalMethod = descriptor.value;\n if (!originalMethod || typeof originalMethod !== 'function') return;\n\n return function (this: Step, ...arguments_: Parameters<typeof originalMethod>): ReturnType<typeof originalMethod> {\n try {\n const result: unknown = originalMethod.apply(this, arguments_);\n\n if (result instanceof Promise) {\n return result.catch((error) => errorHandler.call(this, options, error, propertyKey));\n }\n\n return result;\n } catch (error) {\n return errorHandler.call(this, options, error, propertyKey) as ReturnType<typeof originalMethod>;\n }\n } as typeof originalMethod;\n },\n defaultOptions,\n);\n\nfunction errorHandler(\n this: Step,\n options: BackgroundThreadErrorFilterOptions,\n error: unknown,\n propertyKey: string | symbol,\n): void {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n const filteredError = options.useErrorFilter ? errorFilter(error) : error;\n\n if (filteredError instanceof Error) {\n if (options.allowHandleError) {\n // Send it to the 'error' exit and stop here\n this.thread.enqueue({ name: ACTION.error, error: filteredError });\n return;\n }\n // End the thread with the error and stop here\n this.end(filteredError);\n return;\n }\n\n // Only throw if it's not an Error instance and you truly want to bubble it\n throw filteredError;\n}\n\nexport type BackgroundThreadErrorFilterOptions = {\n allowHandleError?: boolean;\n useErrorFilter?: boolean;\n};\n","import type { CONFIG, IThread } from '@onereach/flow-sdk/types/index.js';\n\n/**\n * Create an AbortController in process cache.\n * It will be available during flow execution, but will disappear in the end of execution\n *\n * @throws If controller already exists will throw an error.\n */\nexport function createAbortController<T extends CONFIG>({\n thread,\n ...options\n}: AbortControllerParameters<T>): AbortController {\n const cacheKey = getAbortControllerKey({ thread, ...options });\n const process = thread.process;\n\n if (process.cache[cacheKey] != undefined) throw new Error(`AbortController for key '${cacheKey}' already exists`);\n\n return (process.cache[cacheKey] = new AbortController());\n}\n\n/**\n * Get instance of AbortController from process cache\n */\nexport function getAbortController<T extends CONFIG>({\n thread,\n ...options\n}: AbortControllerParameters<T>): AbortController | undefined {\n const cacheKey = getAbortControllerKey({ thread, ...options });\n return thread.process.cache[cacheKey] as AbortController | undefined;\n}\n\n/**\n * Remove instance of AbortController from the cache\n *\n * If it does not exists, will not throw an error\n */\nexport function deleteAbortController<T extends CONFIG>({ thread, ...options }: AbortControllerParameters<T>): void {\n const cacheKey = getAbortControllerKey({ thread, ...options });\n delete thread.process.cache[cacheKey];\n}\n\nexport function getAbortControllerKey<T extends CONFIG>({\n thread,\n prefix,\n stepId = thread.currentStepId,\n}: AbortControllerParameters<T>): string {\n const normalizedPrefix = prefix ? `${prefix}:` : '';\n return `${normalizedPrefix}abrt_ctrl:${stepId}`;\n}\n\nexport type AbortControllerParameters<T extends CONFIG> = {\n /** thread to access flow process */\n thread: IThread<T>;\n\n /** Optional step id to use for unique name. If not present will use `thread.currentStepId` */\n stepId?: string;\n\n /** Optional prefix in name if you need to create several controllers */\n prefix?: string;\n};\n","import { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { CONFIG, IThread, IThreadId, IThreadOptions, RESULT } from '@onereach/flow-sdk/types/index.js';\n\n/**\n * Runs a new thread or reuses an existing one (if it ended).\n * @param thread The step to run the thread for.\n * @throws Error if the thread is not ended or if the state is not provided.\n */\nexport async function runChildThread<ThreadConfig extends CONFIG & ManagedThreadConfig, StepConfig extends CONFIG>(\n thread: IThread<StepConfig>,\n { id, state, local, ...options }: IThreadOptions<ThreadConfig>,\n { force }: { force?: boolean } = {},\n): Promise<RESULT<ThreadConfig>> {\n const threadToRun = thread.process.getThread<ThreadConfig>(id);\n thread.log.DEBUG?.(`runThread: thread with id '${id}'`, options);\n\n if (threadToRun == undefined) {\n // create thread\n return await thread.thread.runThread<ThreadConfig>({\n ...options,\n id,\n state,\n local: {\n ...local,\n parent: thread.thread.id,\n active: true,\n },\n });\n }\n\n if (!force && !threadToRun.ended && threadToRun.local.active)\n throw new Error(`Thread with id '${id}' has not ended yet, cannot start it again`);\n if (state == undefined) throw new Error(`Thread with id '${id}' must have a state to run`);\n\n // reuse existing thread\n threadToRun.local.active = true;\n return await threadToRun.enqueueAndRun({\n name: ACTION.goto,\n state: {\n ...state,\n active: true,\n },\n });\n}\n\nexport function isThreadBusy<StepConfig extends CONFIG, ThreadConfig extends CONFIG & ManagedThreadConfig>(\n thread: IThread<StepConfig>,\n threadId: IThreadId,\n): boolean {\n const threadToCheck = thread.process.getThread<ThreadConfig>(threadId);\n return Boolean(threadToCheck != undefined && threadToCheck.local.active && !threadToCheck.ended);\n}\n\nexport function listChildThreads<StepConfig extends CONFIG, ChildThreadConfig extends CONFIG & ManagedThreadConfig>(\n thread: IThread<StepConfig>,\n parentThreadId: IThreadId = thread.id,\n): IThread<ChildThreadConfig>[] {\n const childThreads = [];\n for (const threadId in thread.process.threads) {\n const item = thread.process.threads[threadId]! as unknown as IThread<ChildThreadConfig>;\n if (item?.local.parent === parentThreadId) childThreads.push(item);\n }\n return childThreads;\n}\n\nexport async function stopThread<ThreadConfig extends CONFIG & ManagedThreadConfig, StepConfig extends CONFIG>(\n thread: IThread<StepConfig>,\n id: IThreadId,\n { result, stopChildThreads }: { result?: RESULT<ThreadConfig>; stopChildThreads?: boolean } = {},\n): Promise<void> {\n const threadToStop = thread.process.getThread<ThreadConfig>(id);\n thread.log.DEBUG?.(`stopThread: thread with id '${id}'`);\n\n if (!threadToStop) return;\n\n if (stopChildThreads) await endChildThreads(threadToStop, result);\n\n if (!threadToStop.local.active) return;\n\n threadToStop.local.active = false;\n if (threadToStop.ended) return;\n\n await threadToStop.enqueueAndRun({ name: ACTION.ending, result });\n}\n\nexport async function endChildThreads<ThreadConfig extends CONFIG, StepConfig extends CONFIG>(\n thread: IThread<StepConfig>,\n result?: RESULT<ThreadConfig>,\n options: { throw?: boolean } = {},\n): Promise<PromiseSettledResult<void>[]> {\n const childThreads = listChildThreads(thread);\n const stopTasks = childThreads.map(\n async (child) => await stopThread(thread, child.id, { stopChildThreads: true, result }),\n );\n const stopResults = await Promise.allSettled(stopTasks);\n\n const throwError = options.throw ?? true;\n if (throwError) {\n const failedTask = stopResults.find((task) => task.status === 'rejected');\n if (failedTask) throw failedTask.reason;\n }\n\n return stopResults;\n}\n\nexport type ManagedThreadLocal = {\n active: boolean;\n parent: IThreadId;\n};\n\nexport type ManagedThreadConfig = {\n local: ManagedThreadLocal;\n};\n","/* eslint-disable unicorn/prefer-await */\n/* eslint-disable unicorn/no-this-outside-of-class */\nimport type { Step } from '@onereach/flow-sdk/step.js';\n\nimport { errorFilter } from '../errors/error-filter.ts';\nimport { createMethodDecoratorWithOptionalArguments } from '../utils/create-method-decorator.ts';\n\nconst defaultOptions = {};\n\n/**\n * Will wrap method with `errorFilter` for every error.\n */\nexport const ErrorFilter = createMethodDecoratorWithOptionalArguments((_options, _target, propertyKey, descriptor) => {\n const originalMethod = descriptor.value;\n\n if (!originalMethod || typeof originalMethod !== 'function') return;\n\n return function (this: Step, ...arguments_: Parameters<typeof originalMethod>): ReturnType<typeof originalMethod> {\n try {\n const result: unknown = originalMethod.apply(this, arguments_);\n\n if (result instanceof Promise) {\n return result.catch((error: unknown) => {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n throw errorFilter(error);\n }) as ReturnType<typeof originalMethod>;\n }\n\n return result;\n } catch (error) {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n throw errorFilter(error);\n }\n };\n}, defaultOptions);\n","/* eslint-disable unicorn/max-nested-calls */\nimport * as z from 'zod/mini';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\nexport const otelConfigSchema = z.object({\n /** Whether to capture message content for OpenTelemetry traces. */\n captureMessageContentInTraces: z.optional(z.boolean()),\n\n /** Whether to capture message content for OpenTelemetry logs. */\n captureMessageContentInLogs: z.optional(z.boolean()),\n\n /** The carrier object to use for OpenTelemetry propagation. */\n carrier: z.optional(z.record(z.string(), z.any())),\n});\n\nexport type OtelConfig = z.infer<typeof otelConfigSchema>;\n","/* eslint-disable unicorn/max-nested-calls */\nimport * as z from 'zod/mini';\n\nimport { otelConfigSchema } from './otel-config.ts';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\n// string that prevents\nconst stringNoUndefinedSchema = z.string().check(\n z.trim(),\n z.refine((value) => !['undefined', 'null'].includes(value), {\n error: 'Unexpected undefined or null merge-field value',\n }),\n);\n\nconst messageSchema = z.discriminatedUnion('role', [\n z.object({\n role: z.literal('system'),\n content: stringNoUndefinedSchema,\n }),\n z.object({\n role: z.literal('user'),\n content: stringNoUndefinedSchema,\n name: z.optional(stringNoUndefinedSchema.check(z.minLength(1), z.maxLength(64))),\n }),\n z.object({\n role: z.literal('assistant'),\n content: z.nullable(stringNoUndefinedSchema),\n\n // TODO: add support for annotations and refusal\n // params to support in the future\n // refusal: z.nullable(z.string().check(z.trim(), z.minLength(1))),\n // annotations: z.optional(z.array(z.any())), // TODO: replace z.any() with more details\n tool_calls: z.optional(\n z.array(\n z.object({\n id: stringNoUndefinedSchema.check(z.minLength(1)),\n type: z.literal('function'),\n function: z.object({\n name: stringNoUndefinedSchema.check(z.minLength(1)),\n arguments: stringNoUndefinedSchema.check(z.minLength(1)),\n }),\n }),\n ),\n ),\n }),\n z.object({\n role: z.literal('tool'),\n content: stringNoUndefinedSchema,\n name: z.optional(stringNoUndefinedSchema.check(z.minLength(1), z.maxLength(64))),\n tool_call_id: stringNoUndefinedSchema.check(z.minLength(1)),\n }),\n]);\nexport type Message = z.infer<typeof messageSchema>;\n\nconst functionParametersBaseSchema = z.object({\n type: z.literal('object'),\n properties: z.record(\n z.string().check(z.minLength(1), z.maxLength(64)),\n z.object({\n type: z.enum(['string', 'number', 'boolean', 'array', 'object']),\n description: z.optional(z.string().check(z.maxLength(1000))),\n items: z.optional(\n z.object({\n type: z.enum(['string', 'number', 'boolean', 'object']),\n description: z.optional(z.string().check(z.maxLength(1000))),\n }),\n ),\n }),\n ),\n // next two params would be injected with z.transform()\n // required: z.optional(z.array(z.string().check(z.minLength(1), z.maxLength(64)))),\n // additionalProperties: z._default(z.literal(false), false),\n});\n\nexport const dataInSchema = z\n .object({\n provider: stringNoUndefinedSchema.check(z.minLength(1)),\n model: stringNoUndefinedSchema.check(z.minLength(1)),\n accountKey: optionalStringValue(stringNoUndefinedSchema),\n\n typeOfStep: z.enum(['chat', 'completion']),\n\n systemMessage: z.optional(stringNoUndefinedSchema),\n userMessage: z.optional(stringNoUndefinedSchema),\n switchAssistantsMessage: z._default(z.boolean(), false), // Add assistant's first message\n assistantsFirstMessage: z.optional(stringNoUndefinedSchema),\n\n // llm generation\n temperature: optionalStringValue(z.coerce.number().check(z.gte(0), z.lte(2))),\n topP: optionalStringValue(z.coerce.number().check(z.gte(0), z.lte(1))),\n maxTokens: optionalStringValue(z.coerce.number().check(z.int(), z.gte(1))),\n presencePenalty: optionalStringValue(z.coerce.number().check(z.gte(-2), z.lte(2))),\n frequencyPenalty: optionalStringValue(z.coerce.number().check(z.gte(-2), z.lte(2))),\n n: optionalStringValue(z.coerce.number().check(z.int(), z.gte(1), z.lte(128))),\n stop: z.optional(\n z\n .array(\n z.object({\n token: z.string().check(z.minLength(1), z.maxLength(64)),\n }),\n )\n .check(z.maxLength(4)),\n ),\n reasoningEffort: optionalStringValue(z.enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh'])),\n\n // streaming\n streamResponse: z._default(z.boolean(), false),\n streamSettings: z.optional(\n z.object({\n maxBufferLength: z.coerce.number().check(\n z.overwrite((value) => (value === 0 ? 50 : value)), // default value is 50\n z.int(),\n z.gte(1),\n z.lte(32_768),\n ),\n debounceDuration: z.coerce.number().check(z.int(), z.gte(0), z.lte(10_000)), // in milliseconds\n /** `length` packs by maxBufferLength; `phrase` flushes on TTS-friendly punctuation boundaries. */\n chunkMode: z.optional(z.enum(['length', 'phrase'])),\n /** Minimum phrase size before a punctuation boundary can flush (phrase mode only). */\n minPhraseLength: optionalStringValue(\n z.coerce.number().check(\n z.overwrite((value) => (value === 0 ? 20 : value)),\n z.int(),\n z.gte(1),\n z.lte(1024),\n ),\n ),\n }),\n ),\n\n // history\n customHistory: z._default(z.boolean(), false), // only for 'chat' mode\n historyLength: optionalStringValue(z.coerce.number().check(z.int(), z.gte(1), z.lte(100))),\n historyMode: z.optional(z.enum(['mergefield', 'codeHistory'])),\n historyMergefield: z.optional(z.array(messageSchema)),\n historyCode: z.optional(z.array(messageSchema)),\n\n // function calls\n functionsList: z.array(\n z.object({\n name: stringNoUndefinedSchema.check(z.minLength(1), z.maxLength(64)),\n description: z.optional(stringNoUndefinedSchema.check(z.maxLength(1000))),\n parameters: z.optional(\n z.pipe(\n functionParametersBaseSchema,\n z.transform<\n z.infer<typeof functionParametersBaseSchema> & { additionalProperties: false; required: string[] }\n >((object) => {\n object.required = Object.keys(object.properties);\n object.additionalProperties = false;\n return object;\n }),\n ),\n ),\n strict: z.boolean(),\n }),\n ),\n\n // state management\n useState: z.optional(z.boolean()),\n stateSettings: z.optional(\n z.object({\n stateFunction: z.function(),\n // stateFunction: z.function({\n // output: z.union([z.string(), z.promise(z.string())]),\n // }),\n }),\n ),\n\n // OpenTelemetry\n otel: z.optional(otelConfigSchema),\n\n processError: z.boolean(),\n processTimeout: z.boolean(),\n timeoutDuration: stringNoUndefinedSchema.check(z.trim(), z.minLength(1)),\n })\n .check(\n z.refine((data) => !data.streamResponse || data.provider === 'openai', {\n error: 'Streaming is only supported for OpenAI provider',\n }),\n z.refine((data) => !data.streamResponse || data.streamSettings !== undefined, {\n error: 'Missing \"Stream settings\" for response streaming mode',\n }),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n data.customHistory ||\n !data.switchAssistantsMessage ||\n data.assistantsFirstMessage !== undefined,\n { error: 'Missing \"Assistant\\'s first message\" value' },\n ),\n z.refine((data) => data.customHistory || data.userMessage !== undefined, {\n error: 'Missing \"User message\" value',\n }),\n z.refine((data) => data.typeOfStep !== 'chat' || !data.customHistory || data.historyMode !== undefined, {\n error: 'Missing \"History mode\" value',\n }),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n !data.customHistory ||\n data.historyMode !== 'mergefield' ||\n data.historyMergefield !== undefined,\n { error: 'Missing \"History\" data via merge-field' },\n ),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n !data.customHistory ||\n data.historyMode !== 'mergefield' ||\n data.historyMergefield?.find?.((message) => message.role === 'user'),\n {\n error: 'Missing at least one message with role \"user\" message in \"History\" data via merge-field',\n },\n ),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n !data.customHistory ||\n data.historyMode !== 'codeHistory' ||\n data.historyCode !== undefined,\n { error: 'Missing \"History\" data as code' },\n ),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n !data.customHistory ||\n data.historyMode !== 'codeHistory' ||\n data.historyCode?.find?.((message) => message.role === 'user'),\n {\n error: 'Missing at least one message with role \"user\" message in \"History\" data via code',\n },\n ),\n z.refine((data) => !data.useState || data.stateSettings != undefined, {\n error: 'Missing state settings',\n }),\n );\n\nexport type DataIn = z.infer<typeof dataInSchema>;\nexport type { OtelConfig } from './otel-config.ts';\n\n/**\n * Convert empty string to undefined before running schema validation\n * @param schema schema to validate against\n * @param defaultValue optional default value\n */\nfunction optionalStringValue<T extends z.core.SomeType>(schema: T) {\n return z.optional(\n z.pipe(\n z.union([z.undefined(), z.literal(''), schema]),\n z.transform((value) => (value === '' ? undefined : value)),\n ),\n );\n}\n","// eslint-disable-next-line import-x/no-named-as-default\nimport Step from '@onereach/flow-sdk/step.js';\n\nimport { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { dataInSchema } from '../../schemas/data-in.ts';\n\nimport type { BaseConfig } from './types.ts';\n\n// TODO: convert it into class decorator\nexport class BaseStep<T extends BaseConfig> extends Step<T> {\n @ErrorFilter\n public async resolveDataIn() {\n const dataIn = await super.resolveDataIn();\n\n // TODO: add some caching since this logic runs for every thread class\n // validate dataIn against schema\n return dataInSchema.parse(dataIn);\n }\n}\n","export const baseClassIdPrefix = 'llm_cmp';\n","export const cancelContextClassId = 'cncl_ctrl';\n\nexport const parentEvents = {\n cancel: 'st_cancel',\n} as const;\n\nexport const cancelContentEvents = {\n cancel: 'cnl_cancel',\n} as const;\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport type { IThreadId, IThread, IStepId } from '@onereach/flow-sdk/types/index.js';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { AbortRequestError } from '../../errors/step-error.ts';\nimport { getAbortController } from '../../utils/process-abort-controller.ts';\nimport { runChildThread, stopThread } from '../../utils/thread-utilities.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { ChatCompletionConfig } from '../main/types.ts';\n\nimport { cancelContextClassId, parentEvents, cancelContentEvents } from './constants.ts';\nimport type { CancelContextConfig } from './types.ts';\n\nexport class CancelContext extends BaseStep<CancelContextConfig> {\n public static readonly class = cancelContextClassId;\n\n public static async start(thread: IThread<ChatCompletionConfig>): Promise<void> {\n await runChildThread<CancelContextConfig, ChatCompletionConfig>(\n thread,\n {\n id: this.getThreadId(thread.step.id),\n state: {\n step: thread.step.id,\n class: this.class,\n },\n background: true,\n },\n { force: true },\n );\n }\n\n public static async stop(thread: IThread<ChatCompletionConfig>): Promise<void> {\n await stopThread(thread, this.getThreadId(thread.step.id));\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ---------------------------------------\n\n @BackgroundThreadErrorFilter\n public runStep(): void {\n this.triggers.local({ name: cancelContentEvents.cancel }, this.onCancel).otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n initialize(): void {\n this.log.DEBUG?.(`Initializing ${CancelContext.name} thread`);\n }\n\n @BackgroundThreadErrorFilter\n public onCancel(): void {\n this.log.DEBUG?.('Canceling LLM request');\n const parentThreadId = this.local.parent;\n const parentThread = this.process.getThread<ChatCompletionConfig>(parentThreadId);\n\n if (!parentThread || parentThread.ended) return this.end();\n\n const abortController = getAbortController({ thread: this.thread });\n if (abortController) {\n // LLM request is active\n abortController.abort(new AbortRequestError('Request cancelled'));\n } else {\n // LLM request already ended\n void this.process.enqueueAndRun({ name: parentEvents.cancel, thread: parentThreadId });\n }\n }\n}\n","import type { IEvent } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageParam } from 'openai/resources';\n\nimport { BaseConfig } from '../base/types.ts';\n\nexport const historyContextClassId = 'hst_ctrl';\n\nexport const historyContextEvents = {\n appendToHistory: 'hst_append',\n prepareHistory: 'hst_prepare',\n adjustOnCancel: 'hst_cncl',\n} as const;\nexport type HistoryContextEventName = typeof historyContextEvents;\n\nexport type HistoryContextAppendParameters = {\n message: ChatCompletionMessageParam | ChatCompletionMessageParam[];\n};\nexport type HistoryContextEventAppendToHistory = IEvent<\n HistoryContextAppendParameters,\n HistoryContextEventName['appendToHistory']\n>;\nexport type HistoryContextEventPrepareHistory = IEvent<unknown, HistoryContextEventName['prepareHistory']>;\nexport type HistoryContextEventAdjustOnCancel = IEvent<unknown, HistoryContextEventName['adjustOnCancel']>;\nexport type HistoryContextEvent =\n | HistoryContextEventAppendToHistory\n | HistoryContextEventPrepareHistory\n | HistoryContextEventAdjustOnCancel;\n\nexport type HistoryContextState = {\n class: typeof historyContextClassId;\n\n /** messages to send to OpenAI API */\n messages: ChatCompletionMessageParam[];\n};\n\nexport interface HistoryContextConfig extends BaseConfig {\n state: HistoryContextState;\n events: HistoryContextEvent;\n}\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport type { CONFIG, IThreadId, IThread, IStepId } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageParam } from 'openai/resources.js';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { ChatCompletionConfig } from '../main/types.ts';\n\nimport { historyContextClassId, historyContextEvents } from './types.ts';\nimport type {\n HistoryContextConfig,\n HistoryContextEventName,\n HistoryContextAppendParameters,\n HistoryContextEventAppendToHistory,\n} from './types.ts';\n\nexport class HistoryContext extends BaseStep<HistoryContextConfig> {\n public static readonly class = historyContextClassId;\n\n public static async start(thread: IThread<ChatCompletionConfig>): Promise<void> {\n const historyThreadId = this.getThreadId(thread.step.id);\n const historyThread = thread.process.getThread<HistoryContextConfig>(historyThreadId);\n\n if (historyThread != undefined) return; // thread already exists\n\n // create tools context thread\n await thread.process.runThread<HistoryContextConfig>({\n id: historyThreadId,\n background: true,\n state: {\n step: thread.step.id,\n class: this.class,\n\n messages: [],\n },\n });\n }\n\n public static async prepareHistory<T extends ChatCompletionConfig>(thread: IThread<T>): Promise<void> {\n await thread.process.enqueueAndRun<HistoryContextEventName['prepareHistory']>({\n thread: this.getThreadId(thread.step.id),\n name: historyContextEvents.prepareHistory,\n });\n }\n\n public static async appendToHistory<T extends ChatCompletionConfig>(\n thread: IThread<T>,\n message: ChatCompletionMessageParam | ChatCompletionMessageParam[],\n ): Promise<void> {\n await thread.process.enqueueAndRun<HistoryContextEventName['appendToHistory'], HistoryContextAppendParameters>({\n thread: this.getThreadId(thread.step.id),\n name: historyContextEvents.appendToHistory,\n params: { message },\n });\n }\n\n public static async adjustOnCancel<T extends ChatCompletionConfig>(thread: IThread<T>): Promise<void> {\n await thread.process.enqueueAndRun<HistoryContextEventName['adjustOnCancel']>({\n thread: this.getThreadId(thread.step.id),\n name: historyContextEvents.adjustOnCancel,\n });\n }\n\n public static getHistory<T extends CONFIG>(thread: IThread<T>): ChatCompletionMessageParam[] {\n return thread.process.getSafeThread<HistoryContextConfig>(this.getThreadId(thread.step.id)).state.messages;\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ---------------------------------------\n\n @BackgroundThreadErrorFilter\n public runStep(): void {\n this.triggers\n .local(historyContextEvents.prepareHistory, this.onPrepareHistory)\n .local(historyContextEvents.appendToHistory, this.onAppendToHistory)\n .local(historyContextEvents.adjustOnCancel, this.onAdjustOnCancel)\n .otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n public initialize(): void {\n this.log.DEBUG?.(`Initializing ${HistoryContext.name} thread`);\n }\n\n @BackgroundThreadErrorFilter\n public onAdjustOnCancel(): void {\n let message;\n while ((message = this.state.messages.at(-1))) {\n if (['system', 'user'].includes(message.role)) break;\n if (message.role === 'assistant' && message.tool_calls == undefined) break;\n\n const removedMessage = this.state.messages.pop();\n this.log.DEBUG?.('Removed message from history', removedMessage);\n }\n }\n\n @BackgroundThreadErrorFilter\n public onPrepareHistory(): void {\n this.log.DEBUG?.('Preparing history');\n\n const {\n customHistory,\n historyLength,\n systemMessage,\n typeOfStep,\n userMessage,\n historyMode,\n historyMergefield,\n historyCode,\n assistantsFirstMessage,\n } = this.data;\n\n // 1. text completion mode\n if (typeOfStep === 'completion') {\n this.state.messages = [\n {\n role: 'user',\n content: userMessage!, // never would be undefined due to validation against schema\n },\n ];\n return;\n }\n\n // 2. chat mode (custom history)\n if (customHistory) {\n this.state.messages = historyMode === 'mergefield' ? historyMergefield! : historyCode!;\n return;\n }\n\n // 3. chat mode (step managed history)\n let messages = this.state.messages;\n\n // is a fresh conversation?\n if (messages.length === 0 && assistantsFirstMessage != undefined && assistantsFirstMessage.length > 0) {\n messages.push({\n role: 'assistant',\n content: assistantsFirstMessage,\n });\n }\n\n // if last message is a tool response, assume user message is already in history\n if (messages.at(-1)?.role !== 'tool') {\n messages.push({\n role: 'user',\n content: userMessage!, // never would be undefined due to validation against schema\n // TODO: add support for optional user name\n // name: userName,\n });\n }\n\n // trim history length\n const hasToolCalls = messages.some((message) => message.role === 'tool');\n if (!hasToolCalls && historyLength != undefined && historyLength > 0) {\n messages = messages.slice(-1 * historyLength);\n }\n\n // add system message as first message if it exists\n if (systemMessage != undefined && systemMessage.length > 0) {\n const systemMessageRecord = {\n role: 'system' as const,\n content: systemMessage,\n };\n\n if (messages[0]?.role === 'system') {\n messages[0] = systemMessageRecord; // replace existing system message\n } else {\n messages.unshift(systemMessageRecord); // add system message as first message\n }\n }\n\n // store history\n this.state.messages = messages;\n }\n\n @BackgroundThreadErrorFilter\n public onAppendToHistory(event: HistoryContextEventAppendToHistory): void {\n this.log.DEBUG?.('Appending message to history', event.params);\n\n const { message } = event.params;\n const messages = Array.isArray(message) ? message : [message];\n this.state.messages.push(...messages);\n }\n}\n","export const requestContextClassId = 'rqst_ctx';\n","export const contentContextEvents = {\n handleContent: 'hnd_cnt',\n} as const;\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport { setImmediate } from 'node:timers/promises';\nimport type { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletion, ChatCompletionChunk } from 'openai/resources/index.js';\n\nimport { contentContextEvents } from '../../content/constants.ts';\nimport type { RequestContextConfig } from '../types.ts';\n\nexport abstract class AbstractResponseHandler extends BasicThreadService<RequestContextConfig> {\n public abstract handle(response: ChatCompletion | Stream<ChatCompletionChunk>): Promise<void>;\n\n protected async handleContentByParentThread(content: ChatCompletion | ChatCompletionChunk): Promise<void> {\n await setImmediate();\n await this.thread.process.enqueueAndRun({\n thread: this.thread.local.parent,\n name: contentContextEvents.handleContent,\n params: { content },\n });\n }\n}\n","import type { ChatCompletion } from 'openai/resources.js';\n\nimport { deleteAbortController } from '../../../utils/process-abort-controller.ts';\n\nimport { AbstractResponseHandler } from './abstract-response-handler.ts';\n\nexport class SimpleResponseHandler extends AbstractResponseHandler {\n public async handle(response: ChatCompletion): Promise<void> {\n this.log.DEBUG?.('Start processing response from LLM');\n await this.handleContentByParentThread(response);\n deleteAbortController({ thread: this.thread });\n }\n}\n","import type { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletionChunk } from 'openai/resources.js';\n\nimport { deleteAbortController } from '../../../utils/process-abort-controller.ts';\n\nimport { AbstractResponseHandler } from './abstract-response-handler.ts';\n\nexport class StreamResponseHandler extends AbstractResponseHandler {\n public async handle(response: Stream<ChatCompletionChunk>): Promise<void> {\n this.log.DEBUG?.('Start processing stream of chunks from LLM');\n\n for await (const chunk of response) {\n // send each chunk to the controller thread for processing\n await this.handleContentByParentThread(chunk);\n }\n\n deleteAbortController({ thread: this.thread });\n }\n}\n","import type { IThread } from '@onereach/flow-sdk/types/index.js';\n\nimport type { AbstractResponseHandler } from '../response-handlers/abstract-response-handler.ts';\nimport { SimpleResponseHandler } from '../response-handlers/simple-response-handler.ts';\nimport { StreamResponseHandler } from '../response-handlers/stream-response-handler.ts';\nimport type { RequestContextConfig } from '../types.ts';\n\nexport function responseHandlerFactory({\n thread,\n isStreaming,\n}: ResponseHandlerFactoryParameters): AbstractResponseHandler {\n if (isStreaming) return new StreamResponseHandler(thread);\n return new SimpleResponseHandler(thread);\n}\n\nexport type ResponseHandlerFactoryParameters = {\n thread: IThread<RequestContextConfig>;\n isStreaming: boolean;\n};\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport type { CONFIG, IN, IThread } from '@onereach/flow-sdk/types/index.js';\n\nexport class ThreadServiceWithData<\n TConfig extends CONFIG,\n TData extends IN<CONFIG> = IN<TConfig>,\n> extends BasicThreadService<TConfig> {\n protected readonly data: TData;\n\n constructor(thread: IThread<TConfig>, data: TData) {\n super(thread);\n this.data = data;\n }\n}\n","import OpenAI from 'openai';\nimport type { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletionCreateParams } from 'openai/resources/chat/completions.mjs';\nimport type {\n ChatCompletion,\n ChatCompletionChunk,\n ChatCompletionMessageParam,\n ChatCompletionTool,\n} from 'openai/resources.mjs';\nimport timestring from 'timestring';\nimport { Memoize } from 'typescript-memoize';\nimport * as z from 'zod/mini';\n\nimport { CreateChatCompletionStepError, ErrorCode } from '../../../errors/step-error.ts';\nimport { ThreadServiceWithData } from '../../../services/thread-service-with-data.ts';\nimport type { RequestContextConfig } from '../types.ts';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\nexport class OpenAIRequestService extends ThreadServiceWithData<RequestContextConfig> {\n /**\n * Makes a request to the OpenAI API to create a chat completion.\n */\n public async makeChatCompletionRequest(\n messages: ChatCompletionMessageParam[],\n signal?: AbortSignal,\n ): Promise<ChatCompletion | Stream<ChatCompletionChunk>> {\n const {\n model,\n temperature,\n topP,\n maxTokens,\n frequencyPenalty,\n presencePenalty,\n n,\n streamResponse,\n reasoningEffort,\n } = this.data;\n\n const request: ChatCompletionCreateParams = {\n messages: structuredClone(messages), // clone to avoid mutation\n model,\n temperature,\n top_p: topP,\n max_tokens: maxTokens,\n frequency_penalty: frequencyPenalty,\n presence_penalty: presencePenalty,\n stop: this.stopSequences,\n n,\n reasoning_effort: reasoningEffort,\n stream: streamResponse,\n tools: this.tools,\n };\n this.log.DEBUG?.('LLM request', request);\n\n try {\n const response = await this.doChatCompletionRequest(request, { signal });\n\n if (!streamResponse) this.log.DEBUG?.('LLM response', response);\n\n return response;\n } catch (error) {\n if (error instanceof Error === false) throw error;\n\n throw new CreateChatCompletionStepError('Chat completion request failed', error, {\n code: ErrorCode.SERVER_ERROR,\n data: request,\n });\n }\n }\n\n protected async doChatCompletionRequest(\n request: ChatCompletionCreateParams,\n options?: OpenAI.RequestOptions,\n ): Promise<ChatCompletion | Stream<ChatCompletionChunk>> {\n // TODO: remove this cast\n return (await this.openAiClient.chat.completions.create(request, options)) as unknown as Promise<\n ChatCompletion | Stream<ChatCompletionChunk>\n >;\n }\n\n protected get tools(): ChatCompletionTool[] | undefined {\n const { functionsList } = this.data;\n\n if (!Array.isArray(functionsList) || functionsList.length === 0) return undefined;\n\n return functionsList.map((tool) => ({\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: !tool.parameters || Object.keys(tool.parameters).length === 0 ? undefined : tool.parameters,\n strict: tool.strict,\n },\n }));\n }\n\n /**\n * Returns the OpenAI client instance configured with the step's data.\n */\n protected get openAiClient(): OpenAI {\n const { accountKey } = this.data;\n\n const clientOptions = {\n baseURL: this.openAiBaseUrl,\n apiKey: '_fake_key_',\n defaultHeaders: {\n Authorization: this.config.authorization,\n 'x-or-session-id': this.session.get<string>(['reporting', 'sessionId']),\n ...(accountKey ? { 'x-or-account-token-name': accountKey } : undefined),\n },\n timeout: this.timeoutMs,\n };\n\n return new OpenAI(clientOptions);\n }\n\n protected get openAiBaseUrl(): string {\n return `${this.config.env.OPENAI_API_URL}/${this.data.provider}`;\n }\n\n protected get stopSequences(): string[] {\n const list = this.data.stop ?? [];\n return list.map((item) => item.token).filter((token) => token.length > 0);\n }\n\n /**\n * Returns the timeout duration in milliseconds.\n */\n @Memoize()\n protected get timeoutMs(): number {\n const value = timestring(this.data.timeoutDuration, 'ms');\n\n // 1 second to 10 minutes\n return z.number().check(z.int(), z.gte(1000), z.lte(600_000)).parse(value);\n }\n}\n","import type { Attributes, AttributeValue } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_OPERATION_NAME,\n GEN_AI_OPERATION_NAME_VALUE_CHAT,\n ATTR_GEN_AI_PROVIDER_NAME,\n ATTR_GEN_AI_REQUEST_MODEL,\n ATTR_GEN_AI_REQUEST_STREAM,\n ATTR_GEN_AI_OUTPUT_TYPE,\n GEN_AI_OUTPUT_TYPE_VALUE_TEXT,\n GEN_AI_OUTPUT_TYPE_VALUE_JSON,\n ATTR_GEN_AI_REQUEST_CHOICE_COUNT,\n ATTR_GEN_AI_REQUEST_SEED,\n ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY,\n ATTR_GEN_AI_REQUEST_MAX_TOKENS,\n ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY,\n ATTR_GEN_AI_REQUEST_STOP_SEQUENCES,\n ATTR_GEN_AI_REQUEST_TEMPERATURE,\n ATTR_GEN_AI_REQUEST_TOP_P,\n ATTR_GEN_AI_RESPONSE_FINISH_REASONS,\n ATTR_GEN_AI_RESPONSE_ID,\n ATTR_GEN_AI_RESPONSE_MODEL,\n ATTR_GEN_AI_USAGE_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,\n ATTR_GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_REASONING_OUTPUT_TOKENS,\n ATTR_GEN_AI_INPUT_MESSAGES,\n ATTR_GEN_AI_OUTPUT_MESSAGES,\n GEN_AI_PROVIDER_NAME_VALUE_ANTHROPIC,\n GEN_AI_PROVIDER_NAME_VALUE_AWS_BEDROCK,\n GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_INFERENCE,\n GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_OPENAI,\n GEN_AI_PROVIDER_NAME_VALUE_COHERE,\n GEN_AI_PROVIDER_NAME_VALUE_DEEPSEEK,\n GEN_AI_PROVIDER_NAME_VALUE_GCP_GEMINI,\n GEN_AI_PROVIDER_NAME_VALUE_GCP_GEN_AI,\n GEN_AI_PROVIDER_NAME_VALUE_GCP_VERTEX_AI,\n GEN_AI_PROVIDER_NAME_VALUE_GROQ,\n GEN_AI_PROVIDER_NAME_VALUE_IBM_WATSONX_AI,\n GEN_AI_PROVIDER_NAME_VALUE_MISTRAL_AI,\n GEN_AI_PROVIDER_NAME_VALUE_OPENAI,\n GEN_AI_PROVIDER_NAME_VALUE_PERPLEXITY,\n GEN_AI_PROVIDER_NAME_VALUE_X_AI,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport type { ChatCompletionCreateParams, ChatCompletionChunk } from 'openai/resources';\nimport type { ChatCompletion } from 'openai/resources.js';\n\n/**\n * Attributes common to span, metrics, log events.\n * See more details in {@link [official docs](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)}\n * @param request - The chat completion request parameters.\n * @param provider - The name of the provider\n * @param baseURL - The custom base URL for the provider (optional)\n * @returns The common attributes.\n */\n\nexport function getCommonAttributes(\n request: ChatCompletionCreateParams,\n provider: Provider,\n baseURL?: string,\n): Attributes {\n return {\n [ATTR_GEN_AI_OPERATION_NAME]: GEN_AI_OPERATION_NAME_VALUE_CHAT,\n [ATTR_GEN_AI_PROVIDER_NAME]: provider,\n [ATTR_GEN_AI_REQUEST_MODEL]: request.model,\n ...getAttributesFromBaseURL(baseURL),\n };\n}\n/**\n * Span attributes.\n * See more details in {@link [official docs](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)}\n */\n\nexport function getRequestSpanAttributes(request: ChatCompletionCreateParams): Attributes {\n const attributes: Attributes = {\n [ATTR_GEN_AI_REQUEST_STREAM]: Boolean(request.stream),\n\n // does not capture image and speech output types but it's sufficient for current step capabilities\n [ATTR_GEN_AI_OUTPUT_TYPE]:\n request.response_format == undefined || request.response_format.type === 'text'\n ? GEN_AI_OUTPUT_TYPE_VALUE_TEXT\n : GEN_AI_OUTPUT_TYPE_VALUE_JSON,\n };\n\n if (request.n != undefined && request.n > 1) {\n attributes[ATTR_GEN_AI_REQUEST_CHOICE_COUNT] = request.n;\n }\n if (request.seed != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_SEED] = request.seed;\n }\n if (request.frequency_penalty != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY] = request.frequency_penalty;\n }\n if (request.max_completion_tokens != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_MAX_TOKENS] = request.max_completion_tokens;\n } else if (request.max_tokens != undefined) {\n // `max_tokens` is deprecated in favour of `max_completion_tokens`.\n attributes[ATTR_GEN_AI_REQUEST_MAX_TOKENS] = request.max_tokens;\n }\n if (request.presence_penalty != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY] = request.presence_penalty;\n }\n if (request.stop != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = Array.isArray(request.stop) ? request.stop : [request.stop];\n }\n if (request.temperature != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_TEMPERATURE] = request.temperature;\n }\n if (request.top_p != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_TOP_P] = request.top_p;\n }\n return attributes;\n}\n/**\n * Span attributes.\n * See more details in {@link [official docs](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)}\n */\n\nexport function getResponseSpanAttributes(result: ChatCompletion | ChatCompletionChunk): Attributes {\n return {\n [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: result.choices\n .map((choice) => choice.finish_reason)\n .filter((reason) => reason != undefined),\n\n [ATTR_GEN_AI_RESPONSE_ID]: result.id,\n [ATTR_GEN_AI_RESPONSE_MODEL]: result.model,\n\n ...(result.usage && {\n [ATTR_GEN_AI_USAGE_INPUT_TOKENS]: result.usage.prompt_tokens,\n [ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: result.usage.completion_tokens,\n }),\n ...(result.usage?.prompt_tokens_details && {\n [ATTR_GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS]: result.usage.prompt_tokens_details.cached_tokens,\n }),\n ...(result.usage?.completion_tokens_details && {\n [ATTR_GEN_AI_USAGE_REASONING_OUTPUT_TOKENS]: result.usage.completion_tokens_details.reasoning_tokens,\n }),\n };\n}\n/**\n * Get the messages with inference details.\n * @param request - The chat completion request parameters.\n * @param result - The chat completion result.\n * @returns The messages attributes.\n */\n\nexport function getMessagesAttributes(request: ChatCompletionCreateParams, result: ChatCompletion): Attributes {\n return {\n // TODO: validate against schema https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-input-messages.json\n [ATTR_GEN_AI_INPUT_MESSAGES]: request.messages.map((message) => ({\n ...message,\n\n role: message.role,\n parts: Array.isArray(message.content)\n ? message.content.map((part) => {\n switch (part.type) {\n case 'text': {\n return {\n type: 'text',\n content: part.text,\n };\n }\n case 'input_audio': {\n return {\n type: 'blob',\n modality: 'audio',\n mime_type: `audio/${part.input_audio.format}`,\n content: part.input_audio.data,\n };\n }\n case 'file': {\n return {\n type: 'file',\n modality: 'document', // ???\n file_id: part.file.file_id,\n };\n }\n case 'image_url': {\n try {\n new URL(part.image_url.url);\n return {\n type: 'uri',\n modality: 'image',\n uri: part.image_url.url,\n };\n } catch {\n return {\n type: 'blob',\n modality: 'image',\n content: part.image_url.url,\n };\n }\n }\n case 'refusal': {\n return {\n type: 'refusal',\n content: part.refusal,\n };\n }\n default: {\n return part;\n }\n }\n })\n : [\n {\n type: 'text',\n content: message.content,\n },\n ],\n })) as unknown as AttributeValue,\n\n // TODO: validate against schema https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-output-messages.json\n [ATTR_GEN_AI_OUTPUT_MESSAGES]: result.choices.map((choice) => ({\n role: choice.message.role,\n finish_reason:\n choice.finish_reason === 'tool_calls' || choice.finish_reason === 'function_call'\n ? 'tool_call'\n : choice.finish_reason,\n parts: [\n ...(choice.message.content\n ? [\n {\n type: 'text',\n content: choice.message.content,\n },\n ]\n : []),\n (choice.message.tool_calls ?? []).map((toolCall) =>\n toolCall.type === 'function'\n ? {\n type: 'tool_call',\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n }\n : toolCall,\n ),\n ],\n })) as unknown as AttributeValue,\n };\n}\nexport type Provider =\n | typeof GEN_AI_PROVIDER_NAME_VALUE_ANTHROPIC\n | typeof GEN_AI_PROVIDER_NAME_VALUE_AWS_BEDROCK\n | typeof GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_INFERENCE\n | typeof GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_OPENAI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_COHERE\n | typeof GEN_AI_PROVIDER_NAME_VALUE_DEEPSEEK\n | typeof GEN_AI_PROVIDER_NAME_VALUE_GCP_GEMINI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_GCP_GEN_AI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_GCP_VERTEX_AI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_GROQ\n | typeof GEN_AI_PROVIDER_NAME_VALUE_IBM_WATSONX_AI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_MISTRAL_AI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_OPENAI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_PERPLEXITY\n | typeof GEN_AI_PROVIDER_NAME_VALUE_X_AI;\nconst SERVER_PORT_FROM_URL_PROTOCOL: PortFromProtocol = {\n 'https:': 443,\n 'http:': 80,\n};\n\nexport function getAttributesFromBaseURL(baseURL?: string): Attributes | undefined {\n if (!baseURL) {\n return;\n }\n\n let url: URL;\n try {\n url = new URL(baseURL);\n } catch {\n return;\n }\n\n return {\n [ATTR_SERVER_ADDRESS]: url.hostname,\n [ATTR_SERVER_PORT]: url.port ? Number(url.port) : SERVER_PORT_FROM_URL_PROTOCOL[url.protocol],\n };\n}\ntype PortFromProtocol = { [key: string]: number };\n","import type { Attributes, Context } from '@opentelemetry/api';\nimport type { Logger } from '@opentelemetry/api-logs';\nimport { SeverityNumber } from '@opentelemetry/api-logs';\nimport { EVENT_GEN_AI_CLIENT_INFERENCE_OPERATION_DETAILS } from '@opentelemetry/semantic-conventions/incubating';\nimport type { ChatCompletion, ChatCompletionCreateParams } from 'openai/resources';\n\nimport { OtelConfig } from '../../../../schemas/data-in.ts';\n\nimport { getMessagesAttributes, getResponseSpanAttributes } from './attributes.ts';\n\nexport function getInferenceDetailsEmitter({\n logger,\n spanAttributes,\n config,\n request,\n context,\n}: InferenceOperationDetailsEmitterParameters): InferenceOperationDetailsEmitter {\n return function (response: ChatCompletion): void {\n // Report llm client inference operation details as log event\n logger.emit({\n context: context,\n eventName: EVENT_GEN_AI_CLIENT_INFERENCE_OPERATION_DETAILS,\n severityNumber: SeverityNumber.INFO,\n attributes: {\n ...spanAttributes,\n ...getResponseSpanAttributes(response),\n\n ...(config?.captureMessageContentInLogs && getMessagesAttributes(request, response)),\n },\n });\n };\n}\n\nexport type InferenceOperationDetailsEmitterParameters = {\n logger: Logger;\n spanAttributes: Attributes;\n request: ChatCompletionCreateParams;\n context?: Context;\n config?: OtelConfig;\n};\n\nexport type InferenceOperationDetailsEmitter = (response: ChatCompletion) => void;\n","import type { Meter, Histogram, Attributes, Context } from '@opentelemetry/api';\nimport {\n METRIC_GEN_AI_CLIENT_OPERATION_DURATION,\n ATTR_GEN_AI_RESPONSE_MODEL,\n} from '@opentelemetry/semantic-conventions/incubating';\n\nexport function operationDurationHistogram(meter: Meter): Histogram<Attributes> {\n return meter.createHistogram(METRIC_GEN_AI_CLIENT_OPERATION_DURATION, {\n description: 'GenAI operation duration',\n unit: 's',\n advice: {\n explicitBucketBoundaries: [\n 0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92,\n ],\n },\n });\n}\n\nexport function getOperationDurationRecorder({\n meter,\n attributes,\n context,\n startTime = Date.now(),\n}: OperationDurationRecorderParameters): OperationDurationRecorder {\n const metric = operationDurationHistogram(meter);\n return function (responseModel?: string, durationSec?: number): void {\n metric.record(\n durationSec ?? (Date.now() - startTime) / 1000,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n },\n context,\n );\n };\n}\n\nexport type OperationDurationRecorderParameters = {\n meter: Meter;\n attributes: Attributes;\n context?: Context;\n startTime?: number;\n};\n\nexport type OperationDurationRecorder = (responseModel?: string, durationSec?: number) => void;\n","import type { Attributes, Context, Histogram, Meter } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_RESPONSE_MODEL,\n METRIC_GEN_AI_CLIENT_OPERATION_TIME_PER_OUTPUT_CHUNK,\n} from '@opentelemetry/semantic-conventions/incubating';\n\nexport function getTimePerOutputChunkHistogram(meter: Meter): Histogram<Attributes> {\n return meter.createHistogram(METRIC_GEN_AI_CLIENT_OPERATION_TIME_PER_OUTPUT_CHUNK, {\n description: 'GenAI operation time per output chunk',\n unit: 's',\n advice: {\n explicitBucketBoundaries: [\n 0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92,\n ],\n },\n });\n}\n\nexport function getTimePerOutputChunkRecorder({\n meter,\n attributes,\n context,\n}: TimePerOutputChunkRecorderParameters): TimePerOutputChunkRecorder {\n return function (durationSec: number, responseModel?: string): void {\n getTimePerOutputChunkHistogram(meter).record(\n durationSec,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n },\n context,\n );\n };\n}\n\nexport type TimePerOutputChunkRecorderParameters = {\n meter: Meter;\n attributes: Attributes;\n context?: Context;\n};\n\nexport type TimePerOutputChunkRecorder = (durationSec: number, responseModel?: string) => void;\n","import type { Attributes, Context, Histogram, Meter } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_RESPONSE_MODEL,\n METRIC_GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK,\n} from '@opentelemetry/semantic-conventions/incubating';\n\nexport function getTimeToFirstChunkHistogram(meter: Meter): Histogram<Attributes> {\n return meter.createHistogram(METRIC_GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK, {\n description: 'GenAI operation time to first chunk',\n unit: 's',\n advice: {\n explicitBucketBoundaries: [\n 0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92,\n ],\n },\n });\n}\n\nexport function getTimeToFirstChunkRecorder({\n meter,\n attributes,\n context,\n}: TimeToFirstChunkRecorderParameters): TimeToFirstChunkRecorder {\n return function (durationSec: number, responseModel?: string): void {\n getTimeToFirstChunkHistogram(meter).record(\n durationSec,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n },\n context,\n );\n };\n}\n\nexport type TimeToFirstChunkRecorderParameters = {\n meter: Meter;\n attributes: Attributes;\n context?: Context;\n};\n\nexport type TimeToFirstChunkRecorder = (durationSec: number, responseModel?: string) => void;\n","import type { Meter, Histogram, Attributes, Context } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_RESPONSE_MODEL,\n ATTR_GEN_AI_TOKEN_TYPE,\n GEN_AI_TOKEN_TYPE_VALUE_INPUT,\n GEN_AI_TOKEN_TYPE_VALUE_OUTPUT,\n METRIC_GEN_AI_CLIENT_TOKEN_USAGE,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport { CompletionUsage } from 'openai/resources';\n\nexport function tokenUsageHistogram(meter: Meter): Histogram<Attributes> {\n return meter.createHistogram(METRIC_GEN_AI_CLIENT_TOKEN_USAGE, {\n description: 'Measures number of input and output tokens used',\n unit: '{token}',\n advice: {\n explicitBucketBoundaries: [\n 1, 4, 16, 64, 256, 1024, 4096, 16_384, 65_536, 262_144, 1_048_576, 4_194_304, 16_777_216, 67_108_864,\n ],\n },\n });\n}\n\nexport function getTokenUsageRecorder({\n meter,\n context,\n attributes,\n}: TokenUsageRecorderParameters): TokenUsageRecorder {\n const metric = tokenUsageHistogram(meter);\n return function (usage?: CompletionUsage, responseModel?: string): void {\n if (usage?.prompt_tokens != undefined) {\n metric.record(\n usage.prompt_tokens,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n [ATTR_GEN_AI_TOKEN_TYPE]: GEN_AI_TOKEN_TYPE_VALUE_INPUT,\n },\n context,\n );\n }\n if (usage?.completion_tokens != undefined) {\n metric.record(\n usage.completion_tokens,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n [ATTR_GEN_AI_TOKEN_TYPE]: GEN_AI_TOKEN_TYPE_VALUE_OUTPUT,\n },\n context,\n );\n }\n };\n}\n\nexport type TokenUsageRecorderParameters = {\n meter: Meter;\n attributes: Attributes;\n context?: Context;\n};\n\nexport type TokenUsageRecorder = (usage?: CompletionUsage, responseModel?: string) => void;\n","import type {\n ChatCompletion,\n ChatCompletionChunk,\n ChatCompletionMessage,\n ChatCompletionMessageFunctionToolCall,\n ChatCompletionMessageToolCall,\n} from 'openai/resources.js';\n\nimport type { ToolsContextParsedArguments } from '../threads/tools/worker/types.ts';\n\nexport class OpenAiStreamReducer<TArguments = ToolsContextParsedArguments> {\n protected result: Partial<ChatCompletion>;\n protected readonly onToolCall?: OnToolCallCallback<TArguments>;\n\n constructor(memo: Partial<ChatCompletion>, onToolCall?: OnToolCallCallback<TArguments>) {\n this.result = memo;\n this.onToolCall = onToolCall;\n }\n\n public reduceChunk(chunk: ChatCompletionChunk): void {\n if (Object.keys(this.result).length === 0) {\n const { choices, ...rest } = chunk; // eslint-disable-line @typescript-eslint/no-unused-vars\n Object.assign(this.result, rest);\n\n if (this.result.object != undefined) {\n this.result.object = 'chat.completion';\n }\n }\n\n if (chunk.usage) {\n this.result.usage = chunk.usage;\n // return\n }\n\n for (const choice of chunk.choices) {\n this.reduceChunkChoice(choice);\n }\n }\n\n protected reduceChunkChoice(choice: ChatCompletionChunk.Choice): void {\n let existing = this.result.choices?.[choice.index];\n\n if (!existing) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { delta, ...rest } = choice;\n existing = rest as ChatCompletion.Choice;\n this.result.choices ??= [];\n this.result.choices[choice.index] = existing;\n }\n\n if (choice.finish_reason != undefined) {\n existing.finish_reason = choice.finish_reason;\n }\n\n if (choice.logprobs != undefined) {\n existing.logprobs = choice.logprobs;\n }\n\n if (choice.delta?.content !== undefined) {\n const { content, ...delta } = choice.delta;\n existing.message ??= delta as ChatCompletionMessage;\n if (content === null) {\n // eslint-disable-next-line unicorn/no-null\n existing.message.content ??= null;\n } else {\n existing.message.content ??= '';\n existing.message.content += content;\n }\n }\n\n if (choice.delta?.tool_calls != undefined) {\n const { tool_calls, ...delta } = choice.delta;\n existing.message ??= delta as ChatCompletionMessage;\n existing.message.tool_calls ??= [];\n\n for (const deltaToolCall of tool_calls) {\n const index = deltaToolCall.index;\n if (existing.message.tool_calls[index] == undefined) {\n existing.message.tool_calls[index] = structuredClone(deltaToolCall) as ChatCompletionMessageFunctionToolCall;\n } else {\n const toolCall = existing.message.tool_calls[index];\n if (!('function' in toolCall) || toolCall.function == undefined) continue;\n\n toolCall.function.arguments += deltaToolCall.function?.arguments ?? '';\n }\n\n // set immediate to not block the event loop\n if (choice.index === 0 && this.onToolCall != undefined) {\n this.tryParseToolCall(existing.message.tool_calls[index]);\n }\n }\n }\n }\n\n protected tryParseToolCall(toolCall: ChatCompletionMessageToolCall): void {\n try {\n if (!('function' in toolCall) || toolCall.function == undefined) return;\n const parsedArguments = JSON.parse(toolCall.function.arguments) as TArguments;\n if (this.onToolCall != undefined) void this.onToolCall(toolCall, parsedArguments);\n } catch {\n // if failed to parse, just ignore it assume it's not fully loaded yet\n }\n }\n}\n\nexport type OnToolCallCallback<TArguments = ToolsContextParsedArguments> = (\n toolCall: ChatCompletionMessageFunctionToolCall,\n parsedArguments: TArguments,\n) => void | Promise<void>;\n","import { context, propagation, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';\nimport type { Attributes, Context, Span, Tracer } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_OPERATION_NAME,\n ATTR_GEN_AI_REQUEST_MODEL,\n ATTR_GEN_AI_RESPONSE_FINISH_REASONS,\n ATTR_GEN_AI_RESPONSE_TIME_TO_FIRST_CHUNK,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletionChunk, ChatCompletionCreateParams, CompletionUsage } from 'openai/resources';\nimport type { ChatCompletion } from 'openai/resources.js';\n\nimport { OtelConfig } from '../../../../schemas/data-in.ts';\nimport type { ToolsContextParsedArguments } from '../../../../types.ts';\nimport { OpenAiStreamReducer } from '../../../../utils/openai-stream-reducer.ts';\n\nimport { getResponseSpanAttributes, getCommonAttributes, getRequestSpanAttributes, Provider } from './attributes.ts';\nimport type { InferenceOperationDetailsEmitter } from './events.ts';\nimport type { OperationDurationRecorder } from './metrics/operation-duration.ts';\nimport { TimePerOutputChunkRecorder } from './metrics/time-per-output-chunk.ts';\nimport { TimeToFirstChunkRecorder } from './metrics/time-to-first-chunk.ts';\nimport { TokenUsageRecorder } from './metrics/token-usage.ts';\n\n/**\n * Get the parent context from the carrier.\n * @param carrier - The carrier object.\n * @returns The parent context or undefined if the carrier is empty.\n */\nexport function getParentContext(carrier?: Record<string, unknown>): Context | undefined {\n if (!carrier || Object.keys(carrier).length === 0) return;\n\n return propagation.extract(context.active(), carrier);\n}\n\nexport async function* wrapResponseStreamWithSpan(\n responsePromise: Promise<Stream<ChatCompletionChunk>>,\n span: Span,\n\n emitInferenceOperationDetails: InferenceOperationDetailsEmitter,\n recordOperationDuration: OperationDurationRecorder,\n recordTokenUsage: TokenUsageRecorder,\n recordTimeToFirstChunk: TimeToFirstChunkRecorder,\n recordTimePerOutputChunk: TimePerOutputChunkRecorder,\n): AsyncGenerator<ChatCompletionChunk> {\n const finishReasons: string[] = [];\n const responseAttributes: Attributes = {};\n let responseModel: string | undefined;\n let usage: CompletionUsage | undefined;\n let chunkIndex = 0;\n let lastChunkTimestamp = Date.now();\n\n try {\n const stream = await responsePromise;\n\n // Capture the context that has our span attached\n const spanContext = trace.setSpan(context.active(), span);\n\n // Bind the response stream so each iteration resumes with spanContext active\n const boundStream = context.bind(spanContext, stream);\n\n const chatCompletion: Partial<ChatCompletion> = {};\n const reducer = new OpenAiStreamReducer<ToolsContextParsedArguments>(chatCompletion);\n\n for await (const chunk of boundStream) {\n reducer.reduceChunk(chunk);\n\n const finishReason = chunk.choices.map((choice) => choice?.finish_reason).filter((reason) => reason != undefined);\n finishReasons.push(...finishReason);\n\n Object.assign(responseAttributes, getResponseSpanAttributes(chunk));\n\n if (chunk.model) responseModel ??= chunk.model;\n if (chunk.usage) usage ??= chunk.usage;\n\n if (chunkIndex === 0) {\n const timeToFirstChunk = (Date.now() - lastChunkTimestamp) / 1000;\n recordTimeToFirstChunk(timeToFirstChunk, responseModel);\n responseAttributes[ATTR_GEN_AI_RESPONSE_TIME_TO_FIRST_CHUNK] = timeToFirstChunk;\n } else {\n recordTimePerOutputChunk((Date.now() - lastChunkTimestamp) / 1000, responseModel);\n }\n chunkIndex += 1;\n lastChunkTimestamp = Date.now();\n\n yield chunk;\n }\n\n Object.assign(responseAttributes, {\n [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: finishReasons,\n });\n\n span.setAttributes(responseAttributes);\n span.setStatus({ code: SpanStatusCode.OK });\n\n // Report llm client inference operation details as log event\n emitInferenceOperationDetails(chatCompletion as ChatCompletion);\n\n // Record metrics\n recordOperationDuration(responseModel);\n recordTokenUsage(usage, responseModel);\n } catch (error) {\n let errorInstance: Error;\n if (error instanceof Error) {\n errorInstance = error;\n } else if (typeof error === 'string') {\n errorInstance = new Error(error);\n } else {\n errorInstance = new Error(String(error));\n }\n span.recordException(errorInstance);\n span.setStatus({ code: SpanStatusCode.ERROR, message: errorInstance.message });\n\n throw error;\n } finally {\n span.end();\n }\n}\n\nexport async function wrapResponseWithSpan(\n responsePromise: Promise<ChatCompletion>,\n span: Span,\n\n emitInferenceOperationDetails: InferenceOperationDetailsEmitter,\n recordOperationDuration: OperationDurationRecorder,\n recordTokenUsage: TokenUsageRecorder,\n): Promise<ChatCompletion> {\n try {\n const response = await responsePromise;\n const responseSpanAttributes = getResponseSpanAttributes(response);\n\n span.setAttributes(responseSpanAttributes);\n\n // Report llm client inference operation details as log event\n emitInferenceOperationDetails(response);\n\n // Record metrics\n recordOperationDuration(response.model);\n recordTokenUsage(response.usage, response.model);\n\n return response;\n } finally {\n span.end();\n }\n}\n\nexport function startChatCompletionsSpan({\n tracer,\n request,\n provider,\n openAiBaseURL,\n config,\n}: StartChatCompletionsSpanParameters): StartChatCompletionsSpanResult {\n // TODO: better map provider in data to a type\n const commonAttributes = getCommonAttributes(request, provider, openAiBaseURL);\n\n const attributes: Attributes = {\n ...commonAttributes,\n ...getRequestSpanAttributes(request),\n };\n\n const span: Span = tracer.startSpan(\n `${attributes[ATTR_GEN_AI_OPERATION_NAME] as string} ${attributes[ATTR_GEN_AI_REQUEST_MODEL] as string}`,\n {\n kind: SpanKind.CLIENT,\n attributes,\n },\n getParentContext(config?.carrier),\n );\n const spanContext: Context = trace.setSpan(context.active(), span);\n\n return { span, spanContext, commonAttributes, spanAttributes: attributes };\n}\n\nexport type StartChatCompletionsSpanParameters = {\n tracer: Tracer;\n request: ChatCompletionCreateParams;\n provider: Provider;\n openAiBaseURL?: string;\n config?: OtelConfig;\n};\n\nexport type StartChatCompletionsSpanResult = {\n span: Span;\n spanContext: Context;\n commonAttributes: Attributes;\n spanAttributes: Attributes;\n};\n","import { metrics, trace } from '@opentelemetry/api';\nimport type { Meter, Tracer } from '@opentelemetry/api';\nimport { logs } from '@opentelemetry/api-logs';\nimport type { Logger } from '@opentelemetry/api-logs';\nimport type { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletion, ChatCompletionChunk } from 'openai/resources.js';\nimport { Memoize } from 'typescript-memoize';\n\nimport { OpenAIRequestService } from './openai-request.ts';\nimport { Provider } from './otel-helpers/attributes.ts';\nimport { getInferenceDetailsEmitter } from './otel-helpers/events.ts';\nimport { getOperationDurationRecorder } from './otel-helpers/metrics/operation-duration.ts';\nimport { getTimePerOutputChunkRecorder } from './otel-helpers/metrics/time-per-output-chunk.ts';\nimport { getTimeToFirstChunkRecorder } from './otel-helpers/metrics/time-to-first-chunk.ts';\nimport { getTokenUsageRecorder } from './otel-helpers/metrics/token-usage.ts';\nimport {\n wrapResponseStreamWithSpan,\n startChatCompletionsSpan,\n StartChatCompletionsSpanResult,\n wrapResponseWithSpan,\n} from './otel-helpers/traces.ts';\n\n/**\n * OpenAIRequestOtelService is a service that wraps the OpenAIRequestService and adds OpenTelemetry tracing, metrics and logging.\n */\nexport class OpenAIRequestOtelService extends OpenAIRequestService {\n @Memoize()\n private get tracer(): Tracer {\n return trace.getTracer('create-llm-chat-completion-step');\n }\n\n @Memoize()\n private get meter(): Meter {\n return metrics.getMeter('create-llm-chat-completion-step');\n }\n\n @Memoize()\n private get logger(): Logger {\n return logs.getLogger('create-llm-chat-completion-step');\n }\n\n protected async doChatCompletionRequest(\n ...arguments_: Parameters<OpenAIRequestService['doChatCompletionRequest']>\n ): Promise<ChatCompletion | Stream<ChatCompletionChunk>> {\n const request = arguments_[0];\n\n let startInfo: StartChatCompletionsSpanResult | undefined;\n // TODO: make this configurable in this.data\n const otelConfig = this.data.otel ?? {};\n\n try {\n startInfo = startChatCompletionsSpan({\n tracer: this.tracer,\n request,\n // TODO: better map provider in data to a type\n provider: this.data.provider as Provider,\n openAiBaseURL: this.openAiBaseUrl,\n config: otelConfig,\n });\n } catch (error) {\n this.log.WARN?.('Unexpected error starting OpenTelemetry span:', error);\n return super.doChatCompletionRequest(...arguments_);\n }\n const { span, spanContext, commonAttributes, spanAttributes } = startInfo;\n\n this.log.DEBUG?.('OpenTelemetry span started', {\n spanAttributes,\n });\n\n const emitInferenceOperationDetails = getInferenceDetailsEmitter({\n logger: this.logger,\n context: spanContext,\n spanAttributes,\n config: otelConfig,\n request,\n });\n const recordOperationDuration = getOperationDurationRecorder({\n meter: this.meter,\n attributes: commonAttributes,\n context: spanContext,\n });\n const recordTokenUsage = getTokenUsageRecorder({\n meter: this.meter,\n attributes: commonAttributes,\n context: spanContext,\n });\n\n const responsePromise = super.doChatCompletionRequest(...arguments_);\n\n if (request.stream) {\n const recordTimeToFirstChunk = getTimeToFirstChunkRecorder({\n meter: this.meter,\n attributes: commonAttributes,\n context: spanContext,\n });\n const recordTimePerOutputChunk = getTimePerOutputChunkRecorder({\n meter: this.meter,\n attributes: commonAttributes,\n context: spanContext,\n });\n\n const wrappedStream = wrapResponseStreamWithSpan(\n responsePromise as Promise<Stream<ChatCompletionChunk>>,\n span,\n emitInferenceOperationDetails,\n recordOperationDuration,\n recordTokenUsage,\n recordTimeToFirstChunk,\n recordTimePerOutputChunk,\n ) as unknown as Stream<ChatCompletionChunk>;\n\n return wrappedStream;\n }\n\n return wrapResponseWithSpan(\n responsePromise as Promise<ChatCompletion>,\n span,\n emitInferenceOperationDetails,\n recordOperationDuration,\n recordTokenUsage,\n );\n }\n}\n","import type { IStepId, IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageParam } from 'openai/resources.js';\nimport { clear, Memoize } from 'typescript-memoize';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { createAbortController, deleteAbortController } from '../../utils/process-abort-controller.ts';\nimport { runChildThread } from '../../utils/thread-utilities.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { ContentContextConfig } from '../content/types.ts';\nimport { HistoryContext } from '../history/history-context.ts';\n\nimport { requestContextClassId } from './constants.ts';\nimport { responseHandlerFactory } from './factories/response-handler.ts';\nimport type { AbstractResponseHandler } from './response-handlers/abstract-response-handler.ts';\nimport { OpenAIRequestOtelService } from './services/openai-request-otel.ts';\nimport type { OpenAIRequestService } from './services/openai-request.ts';\nimport type { RequestContextConfig, RequestContextResult } from './types.ts';\n\nconst memoizeTag = ['requestInit'];\n\nexport class RequestContext extends BaseStep<RequestContextConfig> {\n public static readonly class = requestContextClassId;\n\n public static async start<T extends ContentContextConfig>(thread: IThread<T>): Promise<RequestContextResult> {\n return await runChildThread<RequestContextConfig, T>(thread, {\n id: this.getThreadId(thread.step.id),\n state: {\n step: thread.step.id,\n class: this.class,\n },\n background: true,\n });\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ---------------------------------------\n\n private cancel() {\n this.end({ status: 'cancel' } satisfies RequestContextResult);\n }\n\n private complete() {\n this.end({ status: 'ok' });\n }\n\n private async getHistory(): Promise<ChatCompletionMessageParam[]> {\n const history = HistoryContext.getHistory(this.thread);\n\n if (!this.data.useState) return history;\n\n const historyClone = [...history];\n const content = (await this.data.stateSettings?.stateFunction()) as string;\n const message = {\n role: 'developer', //'assistant', // TODO: allow to choose what type to use developer, system, assistant, user\n content,\n } as ChatCompletionMessageParam;\n\n // TODO: allow to choose placement in history\n if (history.at(0)?.role === 'system') {\n // insert right after system message\n historyClone.splice(1, 0, message);\n } else if (history.at(-1)?.role === 'user') {\n const insertionIndex = Math.max(historyClone.length - 1, 0);\n historyClone.splice(insertionIndex, 0, message);\n } else {\n historyClone.push(message);\n }\n return historyClone;\n }\n\n @Memoize()\n private get openAiService(): OpenAIRequestService {\n return new OpenAIRequestOtelService(this.thread, this.data);\n }\n\n @Memoize({ tags: memoizeTag })\n private get responseHandler(): AbstractResponseHandler {\n const isStreaming = this.data.streamResponse;\n return responseHandlerFactory({\n thread: this.thread,\n isStreaming,\n });\n }\n\n @BackgroundThreadErrorFilter\n public async runStep(): Promise<void> {\n clear(memoizeTag);\n const abortController = createAbortController({ thread: this.thread });\n try {\n const response = await this.openAiService.makeChatCompletionRequest(\n await this.getHistory(),\n abortController.signal,\n );\n await this.responseHandler.handle(response);\n this.complete();\n } catch (error) {\n if (abortController?.signal.aborted) return this.cancel();\n throw error;\n } finally {\n deleteAbortController({ thread: this.thread });\n }\n }\n}\n","export const toolsContextWorkerClassId = 'tl_wrk';\n","import type { IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageFunctionToolCall } from 'openai/resources.js';\n\nimport { ErrorFilter } from '../../../decorators/error-filter.ts';\nimport { runChildThread } from '../../../utils/thread-utilities.ts';\nimport { BaseStep } from '../../base/base.ts';\nimport { baseClassIdPrefix } from '../../base/constants.ts';\nimport type { ToolsContextConfig } from '../context/types.ts';\n\nimport { toolsContextWorkerClassId } from './constants.ts';\nimport type { ToolsContextWorkerConfig, ToolsContextParsedArguments } from './types.ts';\n\nexport class ToolsContextWorker extends BaseStep<ToolsContextWorkerConfig> {\n public static readonly class = toolsContextWorkerClassId;\n\n public static async start(\n thread: IThread<ToolsContextConfig>,\n toolCall: ChatCompletionMessageFunctionToolCall,\n ): Promise<void> {\n // parse tool call arguments if they are in string format\n const parsedArguments = JSON.parse(toolCall.function?.arguments) as ToolsContextParsedArguments;\n\n await runChildThread<ToolsContextWorkerConfig, ToolsContextConfig>(thread, {\n id: this.getThreadId(toolCall),\n state: {\n step: thread.step.id,\n class: this.class,\n },\n local: {\n toolCall,\n parsedArguments,\n\n // TODO: figure out how to remove these params without breaking typing\n parent: thread.id,\n active: true,\n },\n });\n }\n\n public static getThreadId(toolCall: ChatCompletionMessageFunctionToolCall): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${toolCall.id}`;\n }\n\n // -----------------------------------------------------------------------------------\n\n /**\n * Initializes the tool worker thread to handle processing of repackaged content chunks.\n */\n @ErrorFilter\n public runStep(): void {\n const { toolCall, parsedArguments } = this.local;\n\n this.log.DEBUG?.('Initializing tool worker thread', toolCall);\n this.exitStep(this.getExitName(/*toolCall*/), {\n function: {\n name: toolCall.function.name,\n arguments: parsedArguments, // use parsed arguments\n },\n });\n }\n\n protected getExitName(/*toolCall: ChatCompletionMessageFunctionToolCall*/): string {\n // TODO: add support for exits based on individual functions\n return 'function';\n }\n}\n","export const toolsContextClassId = 'tl_ctrl';\n\nexport const toolContextEvents = {\n callTool: 'tl_run_call',\n lastToolCallReceived: 'tl_rsp_end',\n} as const;\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { IActionEvent, IStepId, IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageFunctionToolCall, ChatCompletionToolMessageParam } from 'openai/resources.js';\n\nimport { BackgroundThreadErrorFilter } from '../../../decorators/background-thread-error-filter.ts';\nimport { errorFilter } from '../../../errors/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../../errors/step-error.ts';\nimport { runChildThread } from '../../../utils/thread-utilities.ts';\nimport { BaseStep } from '../../base/base.ts';\nimport { baseClassIdPrefix } from '../../base/constants.ts';\nimport type { ContentContextConfig } from '../../content/types.ts';\nimport { ToolsContextWorker } from '../worker/tools-context-worker.ts';\nimport type { ToolsContextWorkerConfig } from '../worker/types.ts';\n\nimport { toolContextEvents, toolsContextClassId } from './constants.ts';\nimport type {\n ToolsContextConfig,\n ToolContextEventName,\n CallToolParameters,\n ToolsContextEventCallTool,\n} from './types.ts';\n\nexport class ToolsContext extends BaseStep<ToolsContextConfig> {\n public static readonly class = toolsContextClassId;\n\n public static async start<T extends ContentContextConfig>(thread: IThread<T>): Promise<void> {\n const threadId = this.getThreadId(thread.step.id);\n await runChildThread<ToolsContextConfig, T>(thread, {\n id: threadId,\n state: {\n step: thread.step.id,\n class: this.class,\n\n /** tool calls from LLM response */\n tasks: {},\n\n /** flag to indicate if there are more tasks to process */\n expectMoreTasks: true,\n },\n background: true,\n });\n }\n\n public static async callTool<T extends ContentContextConfig>(\n thread: IThread<T>,\n toolCall: ChatCompletionMessageFunctionToolCall,\n ): Promise<void> {\n await thread.process.enqueueAndRun<ToolContextEventName['callTool'], CallToolParameters>({\n thread: this.getThreadId(thread.step.id),\n name: toolContextEvents.callTool,\n params: { toolCall },\n });\n }\n\n /**\n * Notify tools context thread that no more tool calls are expected\n */\n public static async lastToolCallReceived<T extends ContentContextConfig>(thread: IThread<T>): Promise<void> {\n await thread.process.enqueueAndRun<ToolContextEventName['lastToolCallReceived']>({\n thread: this.getThreadId(thread.step.id),\n name: toolContextEvents.lastToolCallReceived,\n });\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ---------------------------------------\n\n @BackgroundThreadErrorFilter\n public runStep(): void {\n this.triggers\n .local(toolContextEvents.callTool, this.onCallTool)\n .local(toolContextEvents.lastToolCallReceived, this.onLastToolCallReceived)\n .otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n public initialize(): void {\n this.log.DEBUG?.(`Initializing ${ToolsContext.name} thread`);\n }\n\n @BackgroundThreadErrorFilter\n public onCallTool(event: ToolsContextEventCallTool): void {\n const { toolCall } = event.params;\n\n // TODO: support other tool types\n if (toolCall.type !== 'function') {\n throw new CreateChatCompletionStepError('Only function tools are supported at the moment', {\n code: ErrorCode.UNSUPPORTED,\n });\n }\n\n this.state.tasks[toolCall.id] = {\n call: toolCall,\n status: 'pending',\n };\n\n this.startToolWorkerThread(toolCall);\n }\n\n @BackgroundThreadErrorFilter\n public onLastToolCallReceived(): void {\n this.log.DEBUG?.('No more tool calls expected', this.state.tasks);\n this.state.expectMoreTasks = false; // set flag to indicate no more tasks expected\n this.tryEndToolsContextThread();\n }\n\n @BackgroundThreadErrorFilter\n public onWorkerThreadEnd(event: IActionEvent<ToolsContextWorkerConfig, ACTION.end>): void {\n this.log.DEBUG?.('Tool caller worker thread has ended', event);\n\n const { result } = event.params.thread;\n\n if (result == undefined) {\n throw new CreateChatCompletionStepError(`${ToolsContextWorker.name} thread ended unexpectedly`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${ToolsContextWorker.name} thread ended with an error`,\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n\n // if thread was cancelled do nothing\n if (result.status === 'cancel') return;\n\n // TODO: validate structure of the result (zod?)\n this.log.DEBUG?.(`Tool worker thread completed successfully`, {\n toolCallId: result.toolCallId,\n result: result.data,\n });\n this.setToolCallResult(result.toolCallId, result.data);\n\n this.tryEndToolsContextThread();\n }\n\n /**\n * Starts the tool worker thread to process the tool call.\n */\n protected startToolWorkerThread(toolCall: ChatCompletionMessageFunctionToolCall): void {\n this.triggers.hook<ToolsContextWorkerConfig, ACTION.end>(\n { name: ACTION.end, thread: ToolsContextWorker.getThreadId(toolCall) },\n this.onWorkerThreadEnd,\n );\n\n void ToolsContextWorker.start(this.thread, toolCall);\n }\n\n protected setToolCallResult(toolCallId: string, result: unknown): void {\n const toolCall = this.state.tasks[toolCallId];\n\n if (toolCall == undefined) {\n throw new CreateChatCompletionStepError(`Unknown tool call with id '${toolCallId}'`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n toolCall.status = 'completed';\n toolCall.result = result;\n }\n\n protected tryEndToolsContextThread(): void {\n if (this.state.expectMoreTasks) return;\n\n // TODO: handle errored out tool calls\n\n // check if all tool calls are completed\n const hasActiveTasks = Object.values(this.state.tasks).some((task) => task.status === 'pending');\n if (hasActiveTasks) return;\n\n this.log.DEBUG?.('All tool calls completed or failed', this.state.tasks);\n this.end({\n status: 'ok',\n messages: this.messages,\n });\n }\n\n protected get messages(): ChatCompletionToolMessageParam[] {\n return Object.values(this.state.tasks).map((task) => ({\n role: 'tool',\n tool_call_id: task.call.id,\n content: JSON.stringify(task.result),\n }));\n }\n}\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { IActionEvent, STATE } from '@onereach/flow-sdk/types/index.js';\nimport { setImmediate } from 'node:timers/promises';\nimport type { ChatCompletionMessageFunctionToolCall } from 'openai/resources.js';\nimport { clear, Memoize } from 'typescript-memoize';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { errorFilter } from '../../errors/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../errors/step-error.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { RequestContext } from '../request/request-context.ts';\nimport type { RequestContextConfig } from '../request/types.ts';\nimport { ToolsContext } from '../tools/context/tools-context.ts';\nimport type { ToolsContextConfig } from '../tools/context/types.ts';\n\nimport { contentContextEvents } from './constants.ts';\nimport type { ContentContextConfig, ContentContextHandleContentEvent, ContentContextResult } from './types.ts';\n\nconst memoizeTag = ['toolsInit'];\n\nexport abstract class AbstractContentContext<T extends ContentContextConfig> extends BaseStep<T> {\n public static get class(): string {\n throw new Error('Define \"class\" static field');\n }\n\n public static getInitialState<T extends ContentContextConfig>(): STATE<T> {\n throw new Error('Define \"getInitialState\" static method');\n }\n\n // ----------------------------------------------\n\n @BackgroundThreadErrorFilter\n public runStep(): void | Promise<void> {\n // reset init of tools thread on a fresh start\n clear(memoizeTag);\n\n // TODO: add hook for end of ToolsContext thread\n this.triggers\n .local(contentContextEvents.handleContent, this.onHandleContent)\n .hook<RequestContextConfig, ACTION.end>(\n { name: ACTION.end, thread: RequestContext.getThreadId(this.thread.step.id) },\n this.onRequestContextEnd,\n )\n .otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n public initialize() {\n this.log.DEBUG?.(`Initializing ${this.constructor.name} thread`);\n\n void RequestContext.start(this.thread);\n }\n\n public abstract onHandleContent(event: ContentContextHandleContentEvent): void | Promise<void>;\n protected abstract onAllContentReceived(): void | Promise<void>;\n protected abstract tryToComplete(): void | Promise<void>;\n\n @BackgroundThreadErrorFilter\n public async onRequestContextEnd(event: IActionEvent<RequestContextConfig, ACTION.end>): Promise<void> {\n const { result } = event.params.thread;\n this.log.DEBUG?.(`${RequestContext.name} thread ended with result`, result);\n\n if (result == undefined) {\n throw new CreateChatCompletionStepError(`${RequestContext.name} thread ended unexpectedly`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${RequestContext.name} thread ended with an error`,\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n\n // TODO: figure out better way to check for correct structure of the event (zod?)\n\n // do nothing on cancel\n if (result.status === 'cancel') return this.cancel();\n\n if (result.status !== 'ok') {\n throw new CreateChatCompletionStepError(`Unexpected end of the ${RequestContext.name} thread`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n data: event.params.result,\n });\n }\n\n this.state.requestComplete = true;\n await this.onAllContentReceived();\n\n if (this.state.toolsReady != undefined) {\n await setImmediate();\n // notify ToolsContext no more tool calls will be made\n await ToolsContext.lastToolCallReceived(this.thread);\n }\n\n await this.tryToComplete();\n }\n\n @BackgroundThreadErrorFilter\n public async onToolsContextEnd(event: IActionEvent<ToolsContextConfig, ACTION.end>): Promise<void> {\n const { result } = event.params.thread;\n\n this.log.DEBUG?.(`${ToolsContext.name} thread ended`, result);\n\n if (result == undefined) {\n throw new CreateChatCompletionStepError(`${ToolsContext.name} thread ended unexpectedly`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${ToolsContext.name} thread ended with an error`,\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n\n // TODO: validate result with zod schema\n\n // do nothing on cancel\n if (result.status === 'cancel') return;\n\n const { status, messages } = result;\n\n if (status !== 'ok' || !Array.isArray(messages)) {\n throw new CreateChatCompletionStepError(`Unexpected end of the ${ToolsContext.name} thread`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n data: event.params.result,\n });\n }\n\n this.state.toolsResults = messages;\n this.state.toolsReady = true;\n\n await this.tryToComplete();\n }\n\n protected async callFunction(toolCall: ChatCompletionMessageFunctionToolCall) {\n // wait for ToolController needed\n this.state.toolsReady = false;\n await this.initToolsContextThread();\n await ToolsContext.callTool(this.thread, toolCall);\n }\n\n protected handleMultipleChoices(): void {\n const { chatCompletion } = this.state;\n\n const choices = chatCompletion?.choices ?? [];\n if (choices?.length > 1) {\n this.log.WARN?.('Multiple choices received from LLM, but only the first one will be processed', {\n choices: choices.length,\n });\n }\n }\n\n @Memoize({ tags: memoizeTag })\n protected async initToolsContextThread() {\n // wait for the end of ToolsContext thread\n this.triggers.hook<ToolsContextConfig, ACTION.end>(\n { name: ACTION.end, thread: ToolsContext.getThreadId(this.thread.step.id) },\n this.onToolsContextEnd,\n );\n\n await ToolsContext.start(this.thread);\n }\n\n protected cancel(): void {\n this.end({ status: 'cancel' } as ContentContextResult);\n }\n\n protected complete() {\n const { chatCompletion } = this.state;\n\n // TODO: add validation for ChatCompletion structure\n if (chatCompletion == undefined) {\n throw new CreateChatCompletionStepError('Missing chat completion content to return value', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n this.end({\n status: 'ok',\n chatCompletion,\n toolsResults: this.state.toolsResults ?? [],\n } as ContentContextResult);\n }\n}\n","export const simpleContentContextClassId = 'cnt_cxt_smp';\n","import type { STATE } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageFunctionToolCall } from 'openai/resources';\n\nimport { BackgroundThreadErrorFilter } from '../../../decorators/background-thread-error-filter.ts';\nimport { AbstractContentContext } from '../abstract-content-context.ts';\n\nimport { simpleContentContextClassId } from './constants.ts';\nimport type { SimpleContentContextConfig, SimpleContentContextHandleContentEvent } from './types.ts';\n\nexport class SimpleContentContext extends AbstractContentContext<SimpleContentContextConfig> {\n public static readonly class = simpleContentContextClassId;\n\n public static getInitialState(): STATE<SimpleContentContextConfig> {\n return {\n class: this.class,\n\n requestComplete: false,\n };\n }\n\n // ----------------------------------------------\n\n @BackgroundThreadErrorFilter\n public async onHandleContent(event: SimpleContentContextHandleContentEvent) {\n const { content } = event.params;\n\n this.state.chatCompletion = content;\n\n // Process tool calls if any\n const toolCalls = content.choices[0]?.message.tool_calls;\n if (toolCalls != undefined) {\n for (const toolCall of toolCalls) {\n // TODO: throw an error if tool call is not a function\n await this.callFunction(toolCall as ChatCompletionMessageFunctionToolCall);\n }\n }\n }\n\n @BackgroundThreadErrorFilter\n public onAllContentReceived() {\n this.handleMultipleChoices();\n }\n\n protected tryToComplete() {\n const { requestComplete, toolsReady } = this.state;\n\n // need to wait for request and tools to finish processing\n if (!requestComplete || toolsReady === false) return;\n\n this.complete();\n }\n}\n","export type ExtractTtsPhrasesOptions = {\n /** Hard ceiling for a single emitted phrase. */\n maxLength: number;\n /** Minimum characters before a boundary is eligible to flush. */\n minLength: number;\n};\n\nexport type ExtractTtsPhrasesResult = {\n phrases: string[];\n remainder: string;\n};\n\n/** Common abbreviations that should not end a sentence on `.`. */\nconst ABBREVIATIONS = new Set([\n 'mr',\n 'mrs',\n 'ms',\n 'dr',\n 'prof',\n 'sr',\n 'jr',\n 'vs',\n 'etc',\n 'eg',\n 'ie',\n 'us',\n 'uk',\n 'st',\n 'approx',\n 'dept',\n 'est',\n]);\n\n/** Sentence-ending punctuation, optional closing quotes/brackets, then space or end. */\nconst STRONG_BOUNDARY = /[.!?][\"')\\]]*(?=\\s|$)/g;\n\n/** Clause / line breaks suitable for TTS pauses. */\nconst SOFT_BOUNDARY = /[;:\\u{2014}\\u{2013}][\"')\\]]*(?=\\s|$)|(?:\\r?\\n)/gu;\n\n/** Comma breaks — only used once the buffer is already reasonably long. */\nconst WEAK_BOUNDARY = /,[\"')\\]]*(?=\\s|$)/g;\n\n/**\n * Extracts complete TTS-friendly phrases from a streaming text buffer.\n * Incomplete text stays in `remainder` until a boundary, max-length force-split, or flush.\n */\nexport function extractTtsPhrases(buffer: string, options: ExtractTtsPhrasesOptions): ExtractTtsPhrasesResult {\n const { maxLength, minLength } = options;\n if (maxLength < 1) {\n throw new Error('maxLength must be >= 1');\n }\n\n const effectiveMinLength = Math.max(1, Math.min(minLength, maxLength));\n const weakMinLength = Math.min(maxLength, Math.max(effectiveMinLength * 2, effectiveMinLength));\n\n const phrases: string[] = [];\n let start = 0;\n\n while (start < buffer.length) {\n const slice = buffer.slice(start);\n\n const strongCut = findFirstBoundary(slice, STRONG_BOUNDARY, effectiveMinLength, isValidSentenceEnd);\n if (strongCut != undefined) {\n phrases.push(slice.slice(0, strongCut));\n start += strongCut;\n continue;\n }\n\n const softCut = findFirstBoundary(slice, SOFT_BOUNDARY, effectiveMinLength);\n if (softCut != undefined) {\n phrases.push(slice.slice(0, softCut));\n start += softCut;\n continue;\n }\n\n const weakCut = findFirstBoundary(slice, WEAK_BOUNDARY, weakMinLength);\n if (weakCut != undefined) {\n phrases.push(slice.slice(0, weakCut));\n start += weakCut;\n continue;\n }\n\n if (slice.length >= maxLength) {\n const afterWhitespace = lastWhitespaceBefore(slice, maxLength);\n // Keep the separating whitespace with the remainder so joining chunks preserves text.\n let cut = afterWhitespace ?? maxLength;\n if (afterWhitespace != undefined) {\n while (cut > 0 && /\\s/.test(slice[cut - 1]!)) {\n cut -= 1;\n }\n }\n if (cut < 1) {\n cut = maxLength;\n }\n phrases.push(slice.slice(0, cut));\n start += cut;\n continue;\n }\n\n break;\n }\n\n return {\n phrases: phrases.filter((phrase) => phrase.length > 0),\n remainder: buffer.slice(start),\n };\n}\n\n/**\n * Returns the index after the last whitespace at or before `maxLength`,\n * or `undefined` if there is no whitespace in that window.\n */\nexport function lastWhitespaceBefore(text: string, maxLength: number): number | undefined {\n const limit = Math.min(text.length, maxLength);\n for (let index = limit - 1; index >= 1; index -= 1) {\n if (/\\s/.test(text[index]!)) {\n return index + 1;\n }\n }\n return undefined;\n}\n\nfunction findFirstBoundary(\n slice: string,\n pattern: RegExp,\n minCut: number,\n isValid?: (match: RegExpExecArray, slice: string) => boolean,\n): number | undefined {\n const regex = new RegExp(pattern.source, pattern.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(slice)) != undefined) {\n const cut = match.index + match[0].length;\n if (cut < minCut) continue;\n if (isValid != undefined && !isValid(match, slice)) continue;\n return cut;\n }\n return undefined;\n}\n\nfunction isValidSentenceEnd(match: RegExpExecArray, slice: string): boolean {\n const punctuation = match[0]?.at(0);\n if (punctuation !== '.') return true;\n\n const before = slice[match.index - 1];\n const afterPeriod = slice[match.index + 1];\n if (before != undefined && /\\d/.test(before) && afterPeriod != undefined && /\\d/.test(afterPeriod)) {\n return false;\n }\n\n const prefix = slice.slice(0, match.index);\n const tokenMatch = prefix.match(/((?:[A-Za-z]\\.)+[A-Za-z]|[A-Za-z]+)$/);\n if (tokenMatch == undefined) return true;\n\n const token = tokenMatch[1]!.toLowerCase().replaceAll('.', '');\n if (ABBREVIATIONS.has(token)) return false;\n\n // Single-letter initials (e.g. \"U.S.\", \"A.\") are treated as abbreviations.\n if (/^[A-Za-z]$/.test(tokenMatch[1]!)) return false;\n\n return true;\n}\n","/* eslint-disable unicorn/max-nested-calls */\nimport type { ChatCompletionChunk } from 'openai/resources';\nimport * as z from 'zod/mini';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\nexport const streamChunkEventSchema = z.looseObject({\n name: z.string(),\n params: z.looseObject({\n content: z.looseObject({\n id: z.string(),\n object: z.literal('chat.completion.chunk'),\n created: z.number(),\n model: z.string(),\n service_tier: z.nullish(z.enum(['default', 'auto', 'flex', 'scale', 'priority'])),\n choices: z.array(\n z.looseObject({\n index: z.number().check(z.int(), z.gte(0)),\n delta: z.looseObject({\n role: z.optional(z.enum(['developer', 'system', 'user', 'assistant', 'tool'])),\n content: z.nullish(z.string()),\n refusal: z.nullish(z.string()),\n tool_calls: z.optional(\n z.array(\n z.looseObject({\n index: z.number().check(z.int(), z.gte(0)),\n id: z.optional(z.string()),\n type: z.optional(z.literal('function')),\n function: z.looseObject({\n name: z.optional(z.string()),\n arguments: z.optional(z.string()),\n }),\n }) satisfies z.core.$ZodType<ChatCompletionChunk.Choice.Delta.ToolCall>,\n ),\n ),\n }),\n logprobs: z.nullish(z.any()), // logprobs may be null or omitted\n finish_reason: z.nullable(z.enum(['stop', 'length', 'tool_calls', 'content_filter'])),\n }),\n ),\n\n logprobs: z.nullish(\n z.looseObject({\n content: z.nullable(z.array(z.looseObject({}))),\n refusal: z.nullable(z.array(z.looseObject({}))),\n }),\n ),\n\n usage: z.nullish(\n z.looseObject({\n prompt_tokens: z.number(),\n completion_tokens: z.number(),\n total_tokens: z.number(),\n completion_tokens_details: z.optional(\n z.looseObject({\n accepted_prediction_tokens: z.optional(z.number()),\n audio_tokens: z.optional(z.number()),\n reasoning_tokens: z.optional(z.number()),\n rejected_prediction_tokens: z.optional(z.number()),\n }),\n ),\n prompt_tokens_details: z.optional(\n z.looseObject({\n audio_tokens: z.optional(z.number()),\n cached_tokens: z.optional(z.number()),\n }),\n ),\n }),\n ),\n }) satisfies z.core.$ZodType<ChatCompletionChunk>,\n }),\n});\n\nexport type StreamChunkEvent = z.infer<typeof streamChunkEventSchema>;\n","export const streamContentContextWorkerClassId = 'str_wrk';\n\nexport const streamWorkerExits = {\n chunk: 'chunk',\n} as const;\n","import type { IStepId, IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\n\nimport { ErrorFilter } from '../../../../decorators/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../../../errors/step-error.ts';\nimport { isThreadBusy, runChildThread } from '../../../../utils/thread-utilities.ts';\nimport { BaseStep } from '../../../base/base.ts';\nimport { baseClassIdPrefix } from '../../../base/constants.ts';\nimport type { StreamContentContextConfig } from '../context/types.ts';\n\nimport { streamContentContextWorkerClassId, streamWorkerExits } from './constants.ts';\nimport type { StreamContentContextWorkerConfig, ContentChunkEvent } from './types.ts';\n\nexport class StreamContentContextWorker extends BaseStep<StreamContentContextWorkerConfig> {\n public static readonly class = streamContentContextWorkerClassId;\n\n public static async start(thread: IThread<StreamContentContextConfig>, event: ContentChunkEvent): Promise<void> {\n await runChildThread<StreamContentContextWorkerConfig, StreamContentContextConfig>(thread, {\n id: this.getThreadId(thread.step.id),\n state: {\n step: thread.step.id,\n class: this.class,\n\n event,\n },\n });\n }\n\n public static isBusy(thread: IThread<StreamContentContextConfig>): boolean {\n return isThreadBusy<StreamContentContextConfig, StreamContentContextWorkerConfig>(\n thread,\n this.getThreadId(thread.step.id),\n );\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ----------------------------------------------\n\n @ErrorFilter\n public runStep(): void {\n if ('event' in this.state === false || this.state.event == undefined) {\n throw new CreateChatCompletionStepError('Stream worker thread state must contain an event to process', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n const chunk = this.state.event;\n this.log.DEBUG?.('Executing stream worker thread', chunk);\n this.exitStep(streamWorkerExits.chunk, { chunk });\n }\n}\n","export const streamContentContextClassId = 'cnt_cxt_str';\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { IActionEvent, STATE } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletion, ChatCompletionChunk, ChatCompletionMessageFunctionToolCall } from 'openai/resources.js';\nimport { clear, Memoize } from 'typescript-memoize';\n\nimport { BackgroundThreadErrorFilter } from '../../../../decorators/background-thread-error-filter.ts';\nimport { errorFilter } from '../../../../errors/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../../../errors/step-error.ts';\nimport { extractTtsPhrases, lastWhitespaceBefore } from '../../../../utils/extract-tts-phrases.ts';\nimport { OpenAiStreamReducer } from '../../../../utils/openai-stream-reducer.ts';\nimport { AbstractContentContext } from '../../abstract-content-context.ts';\nimport { streamChunkEventSchema } from '../schemas/stream-chunk.ts';\nimport { StreamContentContextWorker } from '../worker/stream-content-context-worker.ts';\nimport type { StreamContentContextWorkerConfig, ContentChunkEvent } from '../worker/types.ts';\n\nimport { streamContentContextClassId } from './constants.ts';\nimport type { StreamContentContextConfig, StreamContentContextHandleContentEvent, ContentEvent } from './types.ts';\n\nconst memoizeTag = ['streamInit'];\n\nexport class StreamContentContext extends AbstractContentContext<StreamContentContextConfig> {\n public static readonly class = streamContentContextClassId;\n\n public static getInitialState(): STATE<StreamContentContextConfig> {\n return {\n class: this.class,\n\n requestComplete: false,\n workerComplete: false,\n\n partialChatCompletion: {},\n events: [],\n lastChunkReceived: false,\n index: -1,\n holdback: '',\n };\n }\n\n // ---------------------------------------\n\n private onToolCall(toolCall: ChatCompletionMessageFunctionToolCall): void {\n this.log.DEBUG?.('Tool call received', toolCall);\n void this.callFunction(toolCall);\n }\n\n /**\n * Tries to flush the queue of response chunks to the controller thread.\n * If the first event in the queue is not full, it waits for a debounce duration before flushing.\n * If the first event is full, it flushes it immediately.\n */\n private scheduleNextContentEvent(): void {\n this.promoteDebouncedHoldback();\n\n const firstEvent = this.state.events[0];\n\n if (firstEvent == undefined || !this.isEventReady(firstEvent) || 'lastChunkReceived' in firstEvent) return;\n\n this.tryRunWorker();\n }\n\n /**\n * Compacts the content into the controller thread's events queue.\n * Length mode splits by `maxChunkContentLength`.\n * Phrase mode holds text until TTS-friendly punctuation boundaries.\n */\n private addContentToQueue(content: string): void {\n if (this.isPhraseChunkMode) {\n this.addPhraseContentToQueue(content);\n return;\n }\n\n this.addLengthContentToQueue(content);\n }\n\n private addLengthContentToQueue(content: string): void {\n // extend content chunk in the last event to max event size\n const lastEvent: ContentEvent | undefined = this.state.events.at(-1);\n\n if (lastEvent != undefined) {\n if ('lastChunkReceived' in lastEvent) {\n this.log.WARN?.('A new chunk received after the `lastChunkReceived` event. Ignoring it.');\n return;\n }\n\n if (lastEvent.content.length < this.maxChunkContentLength) {\n const mergedChunk = `${lastEvent.content}${content}`;\n lastEvent.content = mergedChunk.slice(0, this.maxChunkContentLength);\n\n content = mergedChunk.slice(this.maxChunkContentLength);\n }\n }\n\n // split chunk into max socket size events\n while (content) {\n this.enqueueChunk(content.slice(0, this.maxChunkContentLength));\n content = content.slice(this.maxChunkContentLength);\n }\n }\n\n private addPhraseContentToQueue(content: string): void {\n const lastEvent: ContentEvent | undefined = this.state.events.at(-1);\n if (lastEvent != undefined && 'lastChunkReceived' in lastEvent) {\n this.log.WARN?.('A new chunk received after the `lastChunkReceived` event. Ignoring it.');\n return;\n }\n\n this.promoteDebouncedHoldback();\n\n this.state.holdback = `${this.state.holdback}${content}`;\n this.state.holdbackTs ??= Date.now();\n\n const { phrases, remainder } = extractTtsPhrases(this.state.holdback, {\n maxLength: this.maxChunkContentLength,\n minLength: this.minPhraseLength,\n });\n\n for (const phrase of phrases) {\n this.enqueueChunk(phrase);\n }\n\n this.state.holdback = remainder;\n if (!remainder) this.state.holdbackTs = undefined;\n }\n\n /**\n * Promotes aged holdback text into the event queue when debounce has elapsed.\n */\n private promoteDebouncedHoldback(): void {\n if (!this.isPhraseChunkMode) return;\n if (!this.state.holdback || this.state.holdbackTs == undefined) return;\n if (Date.now() - this.state.holdbackTs < this.debounceDuration) return;\n\n this.flushHoldback();\n }\n\n /**\n * Flushes any remaining holdback into the queue (end of stream or debounce).\n * Still respects max length, preferring whitespace cuts.\n */\n private flushHoldback(): void {\n let content = this.state.holdback;\n if (!content) return;\n\n this.state.holdback = '';\n this.state.holdbackTs = undefined;\n\n // Prefer phrase boundaries even on force flush; allow short final phrases.\n const { phrases, remainder } = extractTtsPhrases(content, {\n maxLength: this.maxChunkContentLength,\n minLength: 1,\n });\n\n for (const phrase of phrases) {\n this.enqueueChunk(phrase);\n }\n\n content = remainder;\n while (content) {\n let cut =\n content.length > this.maxChunkContentLength\n ? (lastWhitespaceBefore(content, this.maxChunkContentLength) ?? this.maxChunkContentLength)\n : content.length;\n if (cut < content.length) {\n // Keep separating whitespace with the remainder.\n let trimmedCut = cut;\n while (trimmedCut > 0 && /\\s/.test(content[trimmedCut - 1]!)) {\n trimmedCut -= 1;\n }\n if (trimmedCut >= 1) cut = trimmedCut;\n }\n this.enqueueChunk(content.slice(0, cut));\n content = content.slice(cut);\n }\n }\n\n private enqueueChunk(content: string): void {\n if (!content) return;\n\n this.state.index += 1;\n\n const event: ContentChunkEvent = {\n content,\n index: this.state.index,\n ts: Date.now(),\n };\n this.log.DEBUG?.('Add new event into the queue', event);\n this.state.events.push(event);\n }\n\n /**\n * Processes the next event in the controller thread's queue.\n * If the worker thread is busy, it skips processing.\n * If the event is the termination marker, it notifies the end of the controller thread.\n * If the event is ready for processing, it starts the worker thread to handle it.\n */\n private tryRunWorker(): void {\n this.promoteDebouncedHoldback();\n\n // skip if worker thread is busy\n if (StreamContentContextWorker.isBusy(this.thread)) {\n this.log.DEBUG?.('Skip event processing. Worker thread is busy');\n return;\n }\n\n const event: ContentEvent | undefined = this.getEventToProcess();\n\n if (event == undefined) return;\n\n if ('lastChunkReceived' in event) {\n // if last chunk received, stop ContentContext thread with aggregated response\n this.log.DEBUG?.(\n `Stopping ${StreamContentContext.name} thread. All response content chunks were processed and no new chunks are coming`,\n );\n\n this.state.workerComplete = true;\n\n this.tryToComplete();\n return;\n }\n\n this.log.DEBUG?.('Notify stream worker thread about response chunk to process', event);\n\n void StreamContentContextWorker.start(this.thread, event);\n }\n\n private isEventReady(event: ContentEvent): boolean {\n if (event == undefined) return false;\n if ('lastChunkReceived' in event) return true;\n if (event.content == undefined) return false; // TODO: is it even possible? add test for this use-case\n\n // Phrase-mode events are sealed when enqueued — flush immediately.\n if (this.isPhraseChunkMode) return true;\n\n const eventDelay = Date.now() - event.ts;\n return (\n this.state.lastChunkReceived ||\n eventDelay >= this.debounceDuration ||\n event.content.length >= this.maxChunkContentLength\n );\n }\n\n private getEventToProcess(): ContentEvent | undefined {\n const firstEvent = this.state.events[0];\n\n if (firstEvent == undefined) return undefined;\n if (!this.isEventReady(firstEvent)) return undefined;\n if ('lastChunkReceived' in firstEvent) return firstEvent;\n\n this.state.events.shift();\n return firstEvent;\n }\n\n protected tryToComplete(): void {\n const { chatCompletion, toolsReady, requestComplete, workerComplete } = this.state;\n if (!workerComplete || !requestComplete || toolsReady === false || chatCompletion == undefined) return;\n\n const completionMessage = chatCompletion.choices?.[0]?.message;\n if (completionMessage == undefined) {\n throw new CreateChatCompletionStepError('Missing completion message in chat completion result', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n this.complete();\n }\n\n /**\n * Handles the notification that all response chunks were received from the OpenAI API.\n */\n @BackgroundThreadErrorFilter\n protected onAllContentReceived(): void {\n this.log.DEBUG?.('All LLM response chunks were received. No more response chunks expected');\n\n // TODO: maybe validate that completionResult is correct?\n this.state.chatCompletion = this.state.partialChatCompletion as ChatCompletion;\n\n this.handleMultipleChoices();\n\n // flush any incomplete phrase holdback before the end marker\n this.flushHoldback();\n\n // mark chunk as last in the stream, so it worker thread will have it in its data out\n if (this.state.events.length > 0) {\n const lastEvent = this.state.events.at(-1)! as ContentChunkEvent;\n lastEvent.last = true;\n }\n\n // add fake event as marker for end of stream\n // in rare cases when processing of last chunk already started and we need to mark that all chunks were processed\n this.state.events.push({ lastChunkReceived: true });\n\n // mark last chunk was received in stream content context thread state\n this.state.lastChunkReceived = true;\n\n // force processing of the top chunk in the content queue\n this.tryRunWorker();\n }\n\n @Memoize({ tags: memoizeTag })\n protected get maxChunkContentLength(): number {\n return this.data.streamSettings?.maxBufferLength ?? 100;\n }\n\n @Memoize({ tags: memoizeTag })\n protected get debounceDuration(): number {\n return this.data.streamSettings?.debounceDuration ?? 200;\n }\n\n @Memoize({ tags: memoizeTag })\n protected get isPhraseChunkMode(): boolean {\n return this.data.streamSettings?.chunkMode === 'phrase';\n }\n\n @Memoize({ tags: memoizeTag })\n protected get minPhraseLength(): number {\n return this.data.streamSettings?.minPhraseLength ?? 20;\n }\n\n @BackgroundThreadErrorFilter\n public async runStep(): Promise<void> {\n await super.runStep();\n\n clear(memoizeTag);\n\n this.triggers.hook<StreamContentContextWorkerConfig, ACTION.end>(\n { name: ACTION.end, thread: StreamContentContextWorker.getThreadId(this.thread.step.id) },\n this.onWorkerThreadEnd,\n );\n }\n\n /**\n * Handler of the worker thread end event.\n */\n @BackgroundThreadErrorFilter\n public onWorkerThreadEnd(event: IActionEvent<StreamContentContextWorkerConfig, ACTION.end>): void {\n const { result } = event.params.thread;\n\n this.log.DEBUG?.(`${StreamContentContextWorker.name} thread finished processing chunk`, result);\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${StreamContentContextWorker.name} thread ended with an error`,\n });\n throw resultError;\n }\n\n if (result?.status === 'cancel') return;\n\n // check if there are more tool calls or content chunks to process\n this.tryRunWorker();\n }\n\n /**\n * Handles a single chunk of the streaming response from the OpenAI API.\n */\n @BackgroundThreadErrorFilter\n public onHandleContent(event: StreamContentContextHandleContentEvent): void {\n const parsedEvent = streamChunkEventSchema.parse(event);\n const chunk = parsedEvent.params.content satisfies ChatCompletionChunk;\n\n const streamReducer = new OpenAiStreamReducer(this.state.partialChatCompletion, this.onToolCall.bind(this));\n streamReducer.reduceChunk(chunk);\n\n for (const chunkChoice of chunk.choices) {\n // this.log.DEBUG?.('LLM stream response chunk', chunkChoice);\n\n // skip streaming additional choices (if n > 1)\n if (chunkChoice.index > 0) continue;\n\n // aggregate content\n const content = chunkChoice.delta?.content;\n if (content != undefined && content.length > 0) {\n this.addContentToQueue(content);\n this.scheduleNextContentEvent();\n }\n }\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\nexport async function validateFlowSdkVersion(minVersion: string): Promise<void> {\n if (typeof minVersion !== 'string' || !/^\\d+\\.\\d+\\.\\d+$/.test(minVersion)) {\n throw new Error(`Invalid minimum version format: ${minVersion}`);\n }\n\n const packageJsonPath = require.resolve('@onereach/flow-sdk/package.json');\n if (!packageJsonPath) {\n throw new Error(`Could not find package.json for @onereach/flow-sdk`);\n }\n // Read the package.json file to get the version\n const packageJsonContent = await readFile(packageJsonPath, 'utf8');\n\n const { version } = JSON.parse(packageJsonContent) as { version: string };\n const { groups } = /^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)/.exec(version) || {};\n\n if (!groups) throw new Error(`Invalid Flow SDK version format: ${version}`);\n\n const major = Math.trunc(Number(groups.major ?? '0'));\n const minor = Math.trunc(Number(groups.minor ?? '0'));\n const patch = Math.trunc(Number(groups.patch ?? '0'));\n\n if (\n major == undefined ||\n minor == undefined ||\n patch == undefined ||\n Number.isNaN(major) ||\n Number.isNaN(minor) ||\n Number.isNaN(patch)\n ) {\n throw new Error(`Invalid version format: ${version}`);\n }\n\n const [minMajor, minMinor, minPatch] = minVersion.split('.').map((x) => Math.trunc(Number(x)));\n\n if (\n minMajor == undefined ||\n minMinor == undefined ||\n minPatch == undefined ||\n Number.isNaN(minMajor) ||\n Number.isNaN(minMinor) ||\n Number.isNaN(minPatch)\n ) {\n throw new Error(`Invalid minimum version format: ${minVersion}`);\n }\n\n if (\n major < minMajor ||\n (major === minMajor && minor < minMinor) ||\n (major === minMajor && minor === minMinor && patch < minPatch)\n ) {\n throw new Error(\n `Flow SDK version '${version}' is lower than required minimum version '${minVersion}' for the step`,\n );\n }\n}\n","import type { IStepId, IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\nimport { Memoize } from 'typescript-memoize';\n\nimport { runChildThread, stopThread } from '../../utils/thread-utilities.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { ChatCompletionConfig } from '../main/types.ts';\n\nimport { SimpleContentContext } from './simple/simple-content-context.ts';\nimport { StreamContentContext } from './stream/context/stream-content-context.ts';\nimport type { ContentContextConfig } from './types.ts';\n\nexport class ContentContextUtilities {\n private Constructor: ContentContextConstructor;\n\n private constructor(Constructor: ContentContextConstructor) {\n this.Constructor = Constructor;\n }\n\n @Memoize()\n static factory(isStreaming: boolean): ContentContextUtilities {\n const Constructor: ContentContextConstructor = isStreaming ? StreamContentContext : SimpleContentContext;\n return new ContentContextUtilities(Constructor);\n }\n\n public async start(thread: IThread<ChatCompletionConfig>): Promise<void> {\n const initialState = this.Constructor.getInitialState();\n await runChildThread<ContentContextConfig, ChatCompletionConfig>(thread, {\n id: this.getThreadId(thread.step.id),\n state: {\n ...initialState,\n requestComplete: false,\n step: thread.step.id,\n class: this.Constructor.class,\n },\n background: true,\n });\n }\n\n public async cancel(thread: IThread<ChatCompletionConfig>): Promise<void> {\n await stopThread<ContentContextConfig, ChatCompletionConfig>(thread, this.getThreadId(thread.step.id), {\n result: { status: 'cancel' },\n stopChildThreads: true,\n });\n }\n\n public getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.Constructor.class}_${stepId}`;\n }\n}\n\nexport type ContentContextConstructor = typeof SimpleContentContext | typeof StreamContentContext;\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { IActionEvent } from '@onereach/flow-sdk/types/index.js';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { errorFilter } from '../../errors/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../errors/step-error.ts';\nimport { endChildThreads } from '../../utils/thread-utilities.ts';\nimport { validateFlowSdkVersion } from '../../utils/validate-flow-sdk-version.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { CancelContext } from '../cancel/cancel-context.ts';\nimport { parentEvents as stepEvents } from '../cancel/constants.ts';\nimport { ContentContextUtilities } from '../content/content-context-utilities.ts';\nimport type { ContentContextConfig } from '../content/types.ts';\nimport { HistoryContext } from '../history/history-context.ts';\nimport { HistoryContextConfig } from '../history/types.ts';\n\nimport { ChatCompletionConfig } from './types.ts';\n\nconst MINIMAL_FLOW_SDK_VERSION = '8.0.72';\n\nexport class CreateChatCompletionStep extends BaseStep<ChatCompletionConfig> {\n private async tryToExitStep(): Promise<void> {\n const { cancelled, contentReady, chatCompletion, toolsResults } = this.state;\n\n if (cancelled) {\n // TODO: cleanup history with tool responses from it if \"second\" response was cancelled\n this.resetState();\n return;\n }\n\n if (!contentReady) return;\n\n if (chatCompletion == undefined) {\n throw new CreateChatCompletionStepError('Missing chat completion result, but request is marked as processed', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n const completionMessage = chatCompletion.choices?.[0]?.message;\n if (completionMessage == undefined) {\n throw new CreateChatCompletionStepError('Missing completion message in chat completion result', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n await Promise.all([\n // add completion message and possible tool results to history\n HistoryContext.appendToHistory(this.thread, [completionMessage, ...toolsResults]),\n // at this point there's nothing to cancel, so CancelContext thread is not needed anymore\n CancelContext.stop(this.thread),\n ]);\n\n const finishReason = chatCompletion.choices[0]?.finish_reason;\n if (finishReason === 'length') {\n // TODO: allow to proceed with partial data?\n throw new CreateChatCompletionStepError('Reached limit of tokens for LLM completion response', {\n code: ErrorCode.LLM_FINISH_LENGTH,\n });\n }\n if (finishReason === 'tool_calls') {\n // reset the step and run request again\n this.thread.jumpTo(this.currentStepId);\n return;\n }\n\n // both tools and content are ready, we can exit the step\n this.log.DEBUG?.('Exiting step with collected data', chatCompletion);\n this.exitStep('next', chatCompletion);\n }\n\n /**\n * Reset the step so it can handle new request\n *\n * - Reset state of initial thread (e.g. main) to original state;\n * - End CancelContext thread;\n * - End ContentController (with child thread);\n *\n * @throws if there any issues with stopping threads\n */\n private async resetStep(): Promise<void> {\n this.resetState();\n this.state.cancelled = true;\n\n const resetResults = await Promise.allSettled([\n endChildThreads(this.thread, { status: 'cancel' }),\n HistoryContext.adjustOnCancel(this.thread),\n ]);\n const failedTask = resetResults.find((task) => task.status === 'rejected');\n if (failedTask) throw failedTask.reason;\n }\n\n private resetState(): void {\n this.state.contentReady = false;\n this.state.chatCompletion = undefined;\n this.state.toolsResults = [];\n }\n\n private validateMergeFieldType(): void {\n const { functionsList } = this.data;\n if (!Array.isArray(functionsList) || functionsList.length === 0) return; // no functions used\n\n if (this.dataOut == undefined || this.getMergeField(this.dataOut).type !== 'thread') {\n throw new CreateChatCompletionStepError('Merge-field type has to be \"Thread\" if you are using functions', {\n code: ErrorCode.VALIDATION,\n });\n }\n }\n\n private get contentContext(): ContentContextUtilities {\n const isStreaming = this.data.streamResponse;\n return ContentContextUtilities.factory(isStreaming);\n }\n\n @ErrorFilter\n public runStep(): void {\n this.triggers.hook<ContentContextConfig, ACTION.end>(\n { name: ACTION.end, thread: this.contentContext.getThreadId(this.thread.step.id) },\n this.onContentContextEnd,\n );\n this.triggers.hook<HistoryContextConfig, ACTION.end>(\n { name: ACTION.end, thread: HistoryContext.getThreadId(this.thread.step.id) },\n this.onHistoryContextEnd,\n );\n this.triggers.local(stepEvents.cancel, this.onCancel);\n this.triggers.otherwise(this.initialize);\n }\n\n @ErrorFilter\n public async initialize(): Promise<void> {\n await validateFlowSdkVersion(MINIMAL_FLOW_SDK_VERSION);\n this.validateMergeFieldType();\n\n this.resetState();\n this.state.cancelled = false;\n\n await Promise.all([HistoryContext.start(this.thread), CancelContext.start(this.thread)]);\n\n // prepare messages history for the request\n await HistoryContext.prepareHistory(this.thread);\n\n // starting ContentContext thread will initiate the request to LLM\n await this.contentContext.start(this.thread);\n }\n\n @BackgroundThreadErrorFilter({ allowHandleError: true })\n public async onContentContextEnd(event: IActionEvent<ContentContextConfig, ACTION.end>): Promise<void> {\n try {\n const { result } = event.params.thread;\n this.log.DEBUG?.('ContentContext thread ended with result', result);\n\n if (result == undefined) {\n throw new CreateChatCompletionStepError('ContentContext thread ended unexpectedly', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: 'ContentContext thread ended with an error',\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n\n if (result.status === 'cancel') {\n await this.resetStep();\n return;\n }\n\n // TODO: figure out better way to check for correct structure of the event (zod?)\n const { status, chatCompletion, toolsResults } = result;\n\n if (status !== 'ok' || chatCompletion == undefined || toolsResults == undefined) {\n throw new CreateChatCompletionStepError('Unexpected end of the ContentContext thread', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n data: event.params.result,\n });\n }\n\n this.log.DEBUG?.('Create Chat Completion result', chatCompletion);\n\n this.state.contentReady = true;\n this.state.chatCompletion = chatCompletion;\n this.state.toolsResults = toolsResults;\n\n await this.tryToExitStep();\n } catch (error) {\n try {\n await this.resetStep();\n } catch (resetError) {\n this.log.WARN?.('Failed to reset step', resetError);\n }\n throw error;\n }\n }\n\n @BackgroundThreadErrorFilter({ allowHandleError: true })\n public async onHistoryContextEnd(event: IActionEvent<HistoryContextConfig, ACTION.end>): Promise<void> {\n try {\n const { result } = event.params.thread;\n this.log.DEBUG?.(`${HistoryContext.name} thread ended with result`, result);\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${HistoryContext.name} thread ended with an error`,\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n } catch (error) {\n try {\n await CancelContext.stop(this.thread);\n } catch (stopError) {\n this.log.WARN?.('Failed to stop CancelContext thread', stopError);\n }\n throw error;\n }\n }\n\n @ErrorFilter\n public async onCancel(): Promise<void> {\n await this.resetStep();\n }\n}\n","import { install } from 'source-map-support';\n\nimport { CancelContext } from './threads/cancel/cancel-context.ts';\nimport { SimpleContentContext } from './threads/content/simple/simple-content-context.ts';\nimport { StreamContentContext } from './threads/content/stream/context/stream-content-context.ts';\nimport { StreamContentContextWorker } from './threads/content/stream/worker/stream-content-context-worker.ts';\nimport { HistoryContext } from './threads/history/history-context.ts';\nimport { RequestContext } from './threads/request/request-context.ts';\nimport { ToolsContext } from './threads/tools/context/tools-context.ts';\nimport { ToolsContextWorker } from './threads/tools/worker/tools-context-worker.ts';\n\n// enable source map support for better error stack traces\n// eslint-disable-next-line unicorn/no-top-level-side-effects\ninstall();\n\nexport const states = {\n [HistoryContext.class]: HistoryContext,\n [RequestContext.class]: RequestContext,\n [ToolsContext.class]: ToolsContext,\n [ToolsContextWorker.class]: ToolsContextWorker,\n [SimpleContentContext.class]: SimpleContentContext,\n [StreamContentContext.class]: StreamContentContext,\n [StreamContentContextWorker.class]: StreamContentContextWorker,\n [CancelContext.class]: CancelContext,\n};\n\nexport { CreateChatCompletionStep as step } from './threads/main/step.ts';\n\nexport type * from './types.ts';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["defaultOptions","memoizeTag","memoizeTag","stepEvents"],"sources":["../src/errors/step-error.ts","../src/errors/error-filter.ts","../src/utils/create-method-decorator.ts","../src/decorators/background-thread-error-filter.ts","../src/utils/process-abort-controller.ts","../src/utils/thread-utilities.ts","../src/decorators/error-filter.ts","../src/schemas/otel-config.ts","../src/schemas/data-in.ts","../src/threads/base/base.ts","../src/threads/base/constants.ts","../src/threads/cancel/constants.ts","../src/threads/cancel/cancel-context.ts","../src/threads/history/types.ts","../src/threads/history/history-context.ts","../src/threads/request/constants.ts","../src/threads/content/constants.ts","../src/threads/request/response-handlers/abstract-response-handler.ts","../src/threads/request/response-handlers/simple-response-handler.ts","../src/threads/request/response-handlers/stream-response-handler.ts","../src/threads/request/factories/response-handler.ts","../src/services/thread-service-with-data.ts","../src/threads/request/services/openai-request.ts","../src/threads/request/services/otel-helpers/attributes.ts","../src/threads/request/services/otel-helpers/events.ts","../src/threads/request/services/otel-helpers/metrics/operation-duration.ts","../src/threads/request/services/otel-helpers/metrics/time-per-output-chunk.ts","../src/threads/request/services/otel-helpers/metrics/time-to-first-chunk.ts","../src/threads/request/services/otel-helpers/metrics/token-usage.ts","../src/utils/openai-stream-reducer.ts","../src/threads/request/services/otel-helpers/traces.ts","../src/threads/request/services/openai-request-otel.ts","../src/threads/request/request-context.ts","../src/threads/tools/worker/constants.ts","../src/threads/tools/worker/tools-context-worker.ts","../src/threads/tools/context/constants.ts","../src/threads/tools/context/tools-context.ts","../src/threads/content/abstract-content-context.ts","../src/threads/content/simple/constants.ts","../src/threads/content/simple/simple-content-context.ts","../src/utils/extract-tts-phrases.ts","../src/threads/content/stream/schemas/stream-chunk.ts","../src/threads/content/stream/worker/constants.ts","../src/threads/content/stream/worker/stream-content-context-worker.ts","../src/threads/content/stream/context/constants.ts","../src/threads/content/stream/context/stream-content-context.ts","../src/utils/validate-flow-sdk-version.ts","../src/threads/content/content-context-utilities.ts","../src/threads/main/step.ts","../src/index.ts"],"sourcesContent":["import BaseError from '@onereach/flow-sdk/errors/base.js';\n\nexport const ErrorCode = {\n UNKNOWN: 'UNKNOWN',\n STEP_LOGIC_ISSUE: 'STEP_LOGIC_ISSUE',\n AUTH: 'AUTH',\n TIMEOUT: 'TIMEOUT',\n VALIDATION: 'VALIDATION',\n INVALID_REQUEST: 'INVALID_REQUEST',\n RATE_LIMITED: 'RATE_LIMITED',\n LLM_FINISH_LENGTH: 'LLM_FINISH_LENGTH',\n SERVER_ERROR: 'SERVER_ERROR',\n UNSUPPORTED: 'UNSUPPORTED',\n} as const;\n\nexport class CreateChatCompletionStepError extends BaseError<{\n code: keyof typeof ErrorCode;\n data?: unknown;\n}> {}\n\nexport class AbortRequestError extends BaseError {}\n","import TimeoutError from '@onereach/flow-sdk/errors/timeout.js';\nimport * as z from 'zod/mini';\n\nimport { CreateChatCompletionStepError, ErrorCode } from './step-error.ts';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\nconst defaultPreserveErrors = [CreateChatCompletionStepError, TimeoutError] as const;\nexport function errorFilter<P extends readonly AnyErrorClass[] = typeof defaultPreserveErrors>(\n error: unknown,\n options: ErrorFilterOptions<P> = {},\n): InstancesOf<P> | CreateChatCompletionStepError | TimeoutError {\n const {\n preserveErrors = defaultPreserveErrors,\n unknownMessage = 'Unknown error',\n unknownCode = ErrorCode.UNKNOWN,\n } = options;\n\n // if error is CreateChatCompletionStepError or TimeoutError, return it directly\n if (preserveErrors?.some((ErrorClass) => error instanceof ErrorClass)) {\n return error as InstancesOf<P>;\n }\n\n // validation errors\n if (error instanceof z.core.$ZodError) {\n return new CreateChatCompletionStepError(z.prettifyError(error), error, {\n code: ErrorCode.VALIDATION,\n });\n }\n\n // if error is a string assume it's an error message\n if (typeof error === 'string') {\n return new CreateChatCompletionStepError(error, {\n code: ErrorCode.UNKNOWN,\n });\n }\n\n if (error instanceof Error) {\n // timeout errors\n if (error.message.includes('Request timed out')) {\n return new TimeoutError('Timeout', error, { code: ErrorCode.TIMEOUT });\n }\n\n // TODO: fix interpreting of this kind of errors\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n const responseErrorMessage: string | undefined = (error as unknown as any)?.response?.data?.error?.message;\n if (responseErrorMessage != undefined) {\n return new CreateChatCompletionStepError(responseErrorMessage, error, {\n code: ErrorCode.SERVER_ERROR,\n });\n }\n\n return new CreateChatCompletionStepError(unknownMessage, error, {\n code: unknownCode,\n });\n }\n\n // catch all for unknown errors\n return new CreateChatCompletionStepError(unknownMessage, {\n code: unknownCode,\n data: error,\n });\n}\n\nexport type ErrorFilterOptions<P extends readonly AnyErrorClass[]> = {\n /** Array of error classes that should not be wrapped */\n preserveErrors?: P;\n /** Error message to use when message is unknown */\n unknownMessage?: string;\n /** Error code to use when message is unknown */\n unknownCode?: keyof typeof ErrorCode;\n};\n\n/** Any Error class */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyErrorClass<E extends Error = Error> = new (...arguments_: any[]) => E;\n\n/** Turn a tuple/array of constructors into a union of their instance types. */\nexport type InstancesOf<Ctors extends readonly AnyErrorClass[]> =\n Ctors[number] extends AnyErrorClass<infer I> ? I : never;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * Creates a method decorator that can be used with or without options.\n * @param apply - Function that applies the decorator logic with given options.\n * @param defaultOptions - Default options to use if none are provided.\n */\nexport function createMethodDecoratorWithOptionalArguments<A, T extends AnyFunction = AnyFunction>(\n apply: (\n options: A,\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ) => T | TypedPropertyDescriptor<T> | void,\n defaultOptions: A,\n): MethodDecoratorWithOptionalArguments<A, T> {\n function runApply(\n options: A,\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ): TypedPropertyDescriptor<T> | void {\n const maybe = apply(options, target, propertyKey, descriptor);\n\n // If the decorator factory returned a wrapped function, assign it to the descriptor here\n if (typeof maybe === 'function') {\n const originalMethod = descriptor.value;\n const wrappedMethod = maybe as typeof originalMethod;\n\n if (originalMethod?.name != undefined) {\n try {\n Object.defineProperty(wrappedMethod, 'name', { value: originalMethod.name });\n } catch {\n // ignore if name is non-configurable\n }\n }\n\n descriptor.value = wrappedMethod;\n return descriptor;\n }\n\n // If a descriptor was returned or decorator mutated descriptor in-place, use that\n return maybe ?? descriptor;\n }\n\n return function decoratorOrFactory(\n argument0?: object | A,\n argument1?: string | symbol,\n argument2?: TypedPropertyDescriptor<T>,\n ): any {\n if (\n argument0 !== null &&\n typeof argument0 === 'object' &&\n (typeof argument1 === 'string' || typeof argument1 === 'symbol') &&\n argument2 !== null &&\n typeof argument2 === 'object'\n ) {\n // Called as plain decorator: @Decorator\n return runApply(defaultOptions, argument0, argument1, argument2);\n }\n\n // Called as decorator factory: @Decorator(options)\n const options = (argument0 as A) ?? defaultOptions;\n return (target: object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => {\n return runApply(options, target, propertyKey, descriptor);\n };\n };\n}\n\nexport type AnyFunction = (...arguments_: any[]) => any;\n\nexport type MethodDecoratorWithOptionalArguments<A, T extends AnyFunction = AnyFunction> =\n // Plain method decorator (three arguments)\n ((\n target: object,\n propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<T>,\n ) => TypedPropertyDescriptor<T> | void) &\n // Decorator factory (optional options argument)\n ((options?: A) => MethodDecorator);\n","/* eslint-disable unicorn/prefer-await */\n/* eslint-disable unicorn/no-this-outside-of-class */\nimport type { Step } from '@onereach/flow-sdk/step.js';\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\n\nimport { errorFilter } from '../errors/error-filter.ts';\nimport { createMethodDecoratorWithOptionalArguments } from '../utils/create-method-decorator.ts';\n\nconst defaultOptions: BackgroundThreadErrorFilterOptions = { allowHandleError: false, useErrorFilter: true };\n\n/**\n * Since errors in hooks are fatal and can't be processed this decorator allows to wrap hook handler\n * and manage errors by ending a thread with the error (preventing sending error to `error` exit)\n * @param options.allowHandleError - Default `false`. If `false` in case of error will end thread with error as result, if `true` will allow to handle error via 'error' exit\n * @param options.useErrorFilter - Default `true`. If `true` every error wild be processed with `errorFilter` utility function\n */\nexport const BackgroundThreadErrorFilter = createMethodDecoratorWithOptionalArguments(\n (options, _target, propertyKey, descriptor) => {\n const originalMethod = descriptor.value;\n if (!originalMethod || typeof originalMethod !== 'function') return;\n\n return function (this: Step, ...arguments_: Parameters<typeof originalMethod>): ReturnType<typeof originalMethod> {\n try {\n const result: unknown = originalMethod.apply(this, arguments_);\n\n if (result instanceof Promise) {\n return result.catch((error) => errorHandler.call(this, options, error, propertyKey));\n }\n\n return result;\n } catch (error) {\n return errorHandler.call(this, options, error, propertyKey) as ReturnType<typeof originalMethod>;\n }\n } as typeof originalMethod;\n },\n defaultOptions,\n);\n\nfunction errorHandler(\n this: Step,\n options: BackgroundThreadErrorFilterOptions,\n error: unknown,\n propertyKey: string | symbol,\n): void {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n const filteredError = options.useErrorFilter ? errorFilter(error) : error;\n\n if (filteredError instanceof Error) {\n if (options.allowHandleError) {\n // Send it to the 'error' exit and stop here\n this.thread.enqueue({ name: ACTION.error, error: filteredError });\n return;\n }\n // End the thread with the error and stop here\n this.end(filteredError);\n return;\n }\n\n // Only throw if it's not an Error instance and you truly want to bubble it\n throw filteredError;\n}\n\nexport type BackgroundThreadErrorFilterOptions = {\n allowHandleError?: boolean;\n useErrorFilter?: boolean;\n};\n","import type { CONFIG, IThread } from '@onereach/flow-sdk/types/index.js';\n\n/**\n * Create an AbortController in process cache.\n * It will be available during flow execution, but will disappear in the end of execution\n *\n * @throws If controller already exists will throw an error.\n */\nexport function createAbortController<T extends CONFIG>({\n thread,\n ...options\n}: AbortControllerParameters<T>): AbortController {\n const cacheKey = getAbortControllerKey({ thread, ...options });\n const process = thread.process;\n\n if (process.cache[cacheKey] != undefined) throw new Error(`AbortController for key '${cacheKey}' already exists`);\n\n return (process.cache[cacheKey] = new AbortController());\n}\n\n/**\n * Get instance of AbortController from process cache\n */\nexport function getAbortController<T extends CONFIG>({\n thread,\n ...options\n}: AbortControllerParameters<T>): AbortController | undefined {\n const cacheKey = getAbortControllerKey({ thread, ...options });\n return thread.process.cache[cacheKey] as AbortController | undefined;\n}\n\n/**\n * Remove instance of AbortController from the cache\n *\n * If it does not exists, will not throw an error\n */\nexport function deleteAbortController<T extends CONFIG>({ thread, ...options }: AbortControllerParameters<T>): void {\n const cacheKey = getAbortControllerKey({ thread, ...options });\n delete thread.process.cache[cacheKey];\n}\n\nexport function getAbortControllerKey<T extends CONFIG>({\n thread,\n prefix,\n stepId = thread.currentStepId,\n}: AbortControllerParameters<T>): string {\n const normalizedPrefix = prefix ? `${prefix}:` : '';\n return `${normalizedPrefix}abrt_ctrl:${stepId}`;\n}\n\nexport type AbortControllerParameters<T extends CONFIG> = {\n /** thread to access flow process */\n thread: IThread<T>;\n\n /** Optional step id to use for unique name. If not present will use `thread.currentStepId` */\n stepId?: string;\n\n /** Optional prefix in name if you need to create several controllers */\n prefix?: string;\n};\n","import { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { CONFIG, IThread, IThreadId, IThreadOptions, RESULT } from '@onereach/flow-sdk/types/index.js';\n\n/**\n * Runs a new thread or reuses an existing one (if it ended).\n * @param thread The step to run the thread for.\n * @throws Error if the thread is not ended or if the state is not provided.\n */\nexport async function runChildThread<ThreadConfig extends CONFIG & ManagedThreadConfig, StepConfig extends CONFIG>(\n thread: IThread<StepConfig>,\n { id, state, local, ...options }: IThreadOptions<ThreadConfig>,\n { force }: { force?: boolean } = {},\n): Promise<RESULT<ThreadConfig>> {\n const threadToRun = thread.process.getThread<ThreadConfig>(id);\n thread.log.DEBUG?.(`runThread: thread with id '${id}'`, options);\n\n if (threadToRun == undefined) {\n // create thread\n return await thread.thread.runThread<ThreadConfig>({\n ...options,\n id,\n state,\n local: {\n ...local,\n parent: thread.thread.id,\n active: true,\n },\n });\n }\n\n if (!force && !threadToRun.ended && threadToRun.local.active)\n throw new Error(`Thread with id '${id}' has not ended yet, cannot start it again`);\n if (state == undefined) throw new Error(`Thread with id '${id}' must have a state to run`);\n\n // reuse existing thread\n threadToRun.local.active = true;\n return await threadToRun.enqueueAndRun({\n name: ACTION.goto,\n state: {\n ...state,\n active: true,\n },\n });\n}\n\nexport function isThreadBusy<StepConfig extends CONFIG, ThreadConfig extends CONFIG & ManagedThreadConfig>(\n thread: IThread<StepConfig>,\n threadId: IThreadId,\n): boolean {\n const threadToCheck = thread.process.getThread<ThreadConfig>(threadId);\n return Boolean(threadToCheck != undefined && threadToCheck.local.active && !threadToCheck.ended);\n}\n\nexport function listChildThreads<StepConfig extends CONFIG, ChildThreadConfig extends CONFIG & ManagedThreadConfig>(\n thread: IThread<StepConfig>,\n parentThreadId: IThreadId = thread.id,\n): IThread<ChildThreadConfig>[] {\n const childThreads = [];\n for (const threadId in thread.process.threads) {\n const item = thread.process.threads[threadId]! as unknown as IThread<ChildThreadConfig>;\n if (item?.local.parent === parentThreadId) childThreads.push(item);\n }\n return childThreads;\n}\n\nexport async function stopThread<ThreadConfig extends CONFIG & ManagedThreadConfig, StepConfig extends CONFIG>(\n thread: IThread<StepConfig>,\n id: IThreadId,\n { result, stopChildThreads }: { result?: RESULT<ThreadConfig>; stopChildThreads?: boolean } = {},\n): Promise<void> {\n const threadToStop = thread.process.getThread<ThreadConfig>(id);\n thread.log.DEBUG?.(`stopThread: thread with id '${id}'`);\n\n if (!threadToStop) return;\n\n if (stopChildThreads) await endChildThreads(threadToStop, result);\n\n if (!threadToStop.local.active) return;\n\n threadToStop.local.active = false;\n if (threadToStop.ended) return;\n\n await threadToStop.enqueueAndRun({ name: ACTION.ending, result });\n}\n\nexport async function endChildThreads<ThreadConfig extends CONFIG, StepConfig extends CONFIG>(\n thread: IThread<StepConfig>,\n result?: RESULT<ThreadConfig>,\n options: { throw?: boolean } = {},\n): Promise<PromiseSettledResult<void>[]> {\n const childThreads = listChildThreads(thread);\n const stopTasks = childThreads.map(\n async (child) => await stopThread(thread, child.id, { stopChildThreads: true, result }),\n );\n const stopResults = await Promise.allSettled(stopTasks);\n\n const throwError = options.throw ?? true;\n if (throwError) {\n const failedTask = stopResults.find((task) => task.status === 'rejected');\n if (failedTask) throw failedTask.reason;\n }\n\n return stopResults;\n}\n\nexport type ManagedThreadLocal = {\n active: boolean;\n parent: IThreadId;\n};\n\nexport type ManagedThreadConfig = {\n local: ManagedThreadLocal;\n};\n","/* eslint-disable unicorn/prefer-await */\n/* eslint-disable unicorn/no-this-outside-of-class */\nimport type { Step } from '@onereach/flow-sdk/step.js';\n\nimport { errorFilter } from '../errors/error-filter.ts';\nimport { createMethodDecoratorWithOptionalArguments } from '../utils/create-method-decorator.ts';\n\nconst defaultOptions = {};\n\n/**\n * Will wrap method with `errorFilter` for every error.\n */\nexport const ErrorFilter = createMethodDecoratorWithOptionalArguments((_options, _target, propertyKey, descriptor) => {\n const originalMethod = descriptor.value;\n\n if (!originalMethod || typeof originalMethod !== 'function') return;\n\n return function (this: Step, ...arguments_: Parameters<typeof originalMethod>): ReturnType<typeof originalMethod> {\n try {\n const result: unknown = originalMethod.apply(this, arguments_);\n\n if (result instanceof Promise) {\n return result.catch((error: unknown) => {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n throw errorFilter(error);\n }) as ReturnType<typeof originalMethod>;\n }\n\n return result;\n } catch (error) {\n const methodName = propertyKey.toString();\n this.log.DEBUG?.(`Error in method '${methodName}'`, error);\n throw errorFilter(error);\n }\n };\n}, defaultOptions);\n","/* eslint-disable unicorn/max-nested-calls */\nimport * as z from 'zod/mini';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\nexport const otelConfigSchema = z.object({\n /** Whether to capture message content for OpenTelemetry traces. */\n captureMessageContentInTraces: z.optional(z.boolean()),\n\n /** Whether to capture message content for OpenTelemetry logs. */\n captureMessageContentInLogs: z.optional(z.boolean()),\n\n /** The carrier object to use for OpenTelemetry propagation. */\n carrier: z.optional(z.record(z.string(), z.any())),\n});\n\nexport type OtelConfig = z.infer<typeof otelConfigSchema>;\n","/* eslint-disable unicorn/max-nested-calls */\nimport * as z from 'zod/mini';\n\nimport { otelConfigSchema } from './otel-config.ts';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\n// string that prevents\nconst stringNoUndefinedSchema = z.string().check(\n z.trim(),\n z.refine((value) => !['undefined', 'null'].includes(value), {\n error: 'Unexpected undefined or null merge-field value',\n }),\n);\n\nconst messageSchema = z.discriminatedUnion('role', [\n z.object({\n role: z.literal('system'),\n content: stringNoUndefinedSchema,\n }),\n z.object({\n role: z.literal('user'),\n content: stringNoUndefinedSchema,\n name: z.optional(stringNoUndefinedSchema.check(z.minLength(1), z.maxLength(64))),\n }),\n z.object({\n role: z.literal('assistant'),\n content: z.nullable(stringNoUndefinedSchema),\n\n // TODO: add support for annotations and refusal\n // params to support in the future\n // refusal: z.nullable(z.string().check(z.trim(), z.minLength(1))),\n // annotations: z.optional(z.array(z.any())), // TODO: replace z.any() with more details\n tool_calls: z.optional(\n z.array(\n z.object({\n id: stringNoUndefinedSchema.check(z.minLength(1)),\n type: z.literal('function'),\n function: z.object({\n name: stringNoUndefinedSchema.check(z.minLength(1)),\n arguments: stringNoUndefinedSchema.check(z.minLength(1)),\n }),\n }),\n ),\n ),\n }),\n z.object({\n role: z.literal('tool'),\n content: stringNoUndefinedSchema,\n name: z.optional(stringNoUndefinedSchema.check(z.minLength(1), z.maxLength(64))),\n tool_call_id: stringNoUndefinedSchema.check(z.minLength(1)),\n }),\n]);\nexport type Message = z.infer<typeof messageSchema>;\n\nconst functionParametersBaseSchema = z.object({\n type: z.literal('object'),\n properties: z.record(\n z.string().check(z.minLength(1), z.maxLength(64)),\n z.object({\n type: z.enum(['string', 'number', 'boolean', 'array', 'object']),\n description: z.optional(z.string().check(z.maxLength(1000))),\n items: z.optional(\n z.object({\n type: z.enum(['string', 'number', 'boolean', 'object']),\n description: z.optional(z.string().check(z.maxLength(1000))),\n }),\n ),\n }),\n ),\n // next two params would be injected with z.transform()\n // required: z.optional(z.array(z.string().check(z.minLength(1), z.maxLength(64)))),\n // additionalProperties: z._default(z.literal(false), false),\n});\n\nexport const dataInSchema = z\n .object({\n provider: stringNoUndefinedSchema.check(z.minLength(1)),\n model: stringNoUndefinedSchema.check(z.minLength(1)),\n accountKey: optionalStringValue(stringNoUndefinedSchema),\n\n typeOfStep: z.enum(['chat', 'completion']),\n\n systemMessage: z.optional(stringNoUndefinedSchema),\n userMessage: z.optional(stringNoUndefinedSchema),\n switchAssistantsMessage: z._default(z.boolean(), false), // Add assistant's first message\n assistantsFirstMessage: z.optional(stringNoUndefinedSchema),\n\n // llm generation\n temperature: optionalStringValue(z.coerce.number().check(z.gte(0), z.lte(2))),\n topP: optionalStringValue(z.coerce.number().check(z.gte(0), z.lte(1))),\n maxTokens: optionalStringValue(z.coerce.number().check(z.int(), z.gte(1))),\n presencePenalty: optionalStringValue(z.coerce.number().check(z.gte(-2), z.lte(2))),\n frequencyPenalty: optionalStringValue(z.coerce.number().check(z.gte(-2), z.lte(2))),\n n: optionalStringValue(z.coerce.number().check(z.int(), z.gte(1), z.lte(128))),\n stop: z.optional(\n z\n .array(\n z.object({\n token: z.string().check(z.minLength(1), z.maxLength(64)),\n }),\n )\n .check(z.maxLength(4)),\n ),\n reasoningEffort: optionalStringValue(z.enum(['none', 'minimal', 'low', 'medium', 'high', 'xhigh'])),\n\n // streaming\n streamResponse: z._default(z.boolean(), false),\n streamSettings: z.optional(\n z.object({\n maxBufferLength: z.coerce.number().check(\n z.overwrite((value) => (value === 0 ? 50 : value)), // default value is 50\n z.int(),\n z.gte(1),\n z.lte(32_768),\n ),\n debounceDuration: z.coerce.number().check(z.int(), z.gte(0), z.lte(10_000)), // in milliseconds\n /** `length` packs by maxBufferLength; `phrase` flushes on TTS-friendly punctuation boundaries. */\n chunkMode: z.optional(z.enum(['length', 'phrase'])),\n /** Minimum phrase size before a punctuation boundary can flush (phrase mode only). */\n minPhraseLength: optionalStringValue(\n z.coerce.number().check(\n z.overwrite((value) => (value === 0 ? 20 : value)),\n z.int(),\n z.gte(1),\n z.lte(1024),\n ),\n ),\n }),\n ),\n\n // history\n customHistory: z._default(z.boolean(), false), // only for 'chat' mode\n historyLength: optionalStringValue(z.coerce.number().check(z.int(), z.gte(1), z.lte(100))),\n historyMode: z.optional(z.enum(['mergefield', 'codeHistory'])),\n historyMergefield: z.optional(z.array(messageSchema)),\n historyCode: z.optional(z.array(messageSchema)),\n\n // function calls\n functionsList: z.array(\n z.object({\n name: stringNoUndefinedSchema.check(z.minLength(1), z.maxLength(64)),\n description: z.optional(stringNoUndefinedSchema.check(z.maxLength(1000))),\n parameters: z.optional(\n z.pipe(\n functionParametersBaseSchema,\n z.transform<\n z.infer<typeof functionParametersBaseSchema> & { additionalProperties: false; required: string[] }\n >((object) => {\n object.required = Object.keys(object.properties);\n object.additionalProperties = false;\n return object;\n }),\n ),\n ),\n strict: z.boolean(),\n }),\n ),\n\n // state management\n useState: z.optional(z.boolean()),\n stateSettings: z.optional(\n z.object({\n stateFunction: z.function(),\n // stateFunction: z.function({\n // output: z.union([z.string(), z.promise(z.string())]),\n // }),\n stateMessageType: optionalStringValue(z.enum(['developer', 'system', 'assistant', 'user'])),\n stateMessagePosition: optionalStringValue(z.enum(['top', 'bottom'])),\n }),\n ),\n\n // OpenTelemetry\n otel: z.optional(otelConfigSchema),\n\n processError: z.boolean(),\n processTimeout: z.boolean(),\n timeoutDuration: stringNoUndefinedSchema.check(z.trim(), z.minLength(1)),\n })\n .check(\n z.refine((data) => !data.streamResponse || data.provider === 'openai', {\n error: 'Streaming is only supported for OpenAI provider',\n }),\n z.refine((data) => !data.streamResponse || data.streamSettings !== undefined, {\n error: 'Missing \"Stream settings\" for response streaming mode',\n }),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n data.customHistory ||\n !data.switchAssistantsMessage ||\n data.assistantsFirstMessage !== undefined,\n { error: 'Missing \"Assistant\\'s first message\" value' },\n ),\n z.refine((data) => data.customHistory || data.userMessage !== undefined, {\n error: 'Missing \"User message\" value',\n }),\n z.refine((data) => data.typeOfStep !== 'chat' || !data.customHistory || data.historyMode !== undefined, {\n error: 'Missing \"History mode\" value',\n }),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n !data.customHistory ||\n data.historyMode !== 'mergefield' ||\n data.historyMergefield !== undefined,\n { error: 'Missing \"History\" data via merge-field' },\n ),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n !data.customHistory ||\n data.historyMode !== 'mergefield' ||\n data.historyMergefield?.find?.((message) => message.role === 'user'),\n {\n error: 'Missing at least one message with role \"user\" message in \"History\" data via merge-field',\n },\n ),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n !data.customHistory ||\n data.historyMode !== 'codeHistory' ||\n data.historyCode !== undefined,\n { error: 'Missing \"History\" data as code' },\n ),\n z.refine(\n (data) =>\n data.typeOfStep !== 'chat' ||\n !data.customHistory ||\n data.historyMode !== 'codeHistory' ||\n data.historyCode?.find?.((message) => message.role === 'user'),\n {\n error: 'Missing at least one message with role \"user\" message in \"History\" data via code',\n },\n ),\n z.refine((data) => !data.useState || data.stateSettings != undefined, {\n error: 'Missing state settings',\n }),\n );\n\nexport type DataIn = z.infer<typeof dataInSchema>;\nexport type { OtelConfig } from './otel-config.ts';\n\n/**\n * Convert empty string to undefined before running schema validation\n * @param schema schema to validate against\n * @param defaultValue optional default value\n */\nfunction optionalStringValue<T extends z.core.SomeType>(schema: T) {\n return z.optional(\n z.pipe(\n z.union([z.undefined(), z.literal(''), schema]),\n z.transform((value) => (value === '' ? undefined : value)),\n ),\n );\n}\n","// eslint-disable-next-line import-x/no-named-as-default\nimport Step from '@onereach/flow-sdk/step.js';\n\nimport { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { dataInSchema } from '../../schemas/data-in.ts';\n\nimport type { BaseConfig } from './types.ts';\n\n// TODO: convert it into class decorator\nexport class BaseStep<T extends BaseConfig> extends Step<T> {\n @ErrorFilter\n public async resolveDataIn() {\n const dataIn = await super.resolveDataIn();\n\n // TODO: add some caching since this logic runs for every thread class\n // validate dataIn against schema\n return dataInSchema.parse(dataIn);\n }\n}\n","export const baseClassIdPrefix = 'llm_cmp';\n","export const cancelContextClassId = 'cncl_ctrl';\n\nexport const parentEvents = {\n cancel: 'st_cancel',\n} as const;\n\nexport const cancelContentEvents = {\n cancel: 'cnl_cancel',\n} as const;\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport type { IThreadId, IThread, IStepId } from '@onereach/flow-sdk/types/index.js';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { AbortRequestError } from '../../errors/step-error.ts';\nimport { getAbortController } from '../../utils/process-abort-controller.ts';\nimport { runChildThread, stopThread } from '../../utils/thread-utilities.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { ChatCompletionConfig } from '../main/types.ts';\n\nimport { cancelContextClassId, parentEvents, cancelContentEvents } from './constants.ts';\nimport type { CancelContextConfig } from './types.ts';\n\nexport class CancelContext extends BaseStep<CancelContextConfig> {\n public static readonly class = cancelContextClassId;\n\n public static async start(thread: IThread<ChatCompletionConfig>): Promise<void> {\n await runChildThread<CancelContextConfig, ChatCompletionConfig>(\n thread,\n {\n id: this.getThreadId(thread.step.id),\n state: {\n step: thread.step.id,\n class: this.class,\n },\n background: true,\n },\n { force: true },\n );\n }\n\n public static async stop(thread: IThread<ChatCompletionConfig>): Promise<void> {\n await stopThread(thread, this.getThreadId(thread.step.id));\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ---------------------------------------\n\n @BackgroundThreadErrorFilter\n public runStep(): void {\n this.triggers.local({ name: cancelContentEvents.cancel }, this.onCancel).otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n initialize(): void {\n this.log.DEBUG?.(`Initializing ${CancelContext.name} thread`);\n }\n\n @BackgroundThreadErrorFilter\n public onCancel(): void {\n this.log.DEBUG?.('Canceling LLM request');\n const parentThreadId = this.local.parent;\n const parentThread = this.process.getThread<ChatCompletionConfig>(parentThreadId);\n\n if (!parentThread || parentThread.ended) return this.end();\n\n const abortController = getAbortController({ thread: this.thread });\n if (abortController) {\n // LLM request is active\n abortController.abort(new AbortRequestError('Request cancelled'));\n } else {\n // LLM request already ended\n void this.process.enqueueAndRun({ name: parentEvents.cancel, thread: parentThreadId });\n }\n }\n}\n","import type { IEvent } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageParam } from 'openai/resources';\n\nimport { BaseConfig } from '../base/types.ts';\n\nexport const historyContextClassId = 'hst_ctrl';\n\nexport const historyContextEvents = {\n appendToHistory: 'hst_append',\n prepareHistory: 'hst_prepare',\n adjustOnCancel: 'hst_cncl',\n} as const;\nexport type HistoryContextEventName = typeof historyContextEvents;\n\nexport type HistoryContextAppendParameters = {\n message: ChatCompletionMessageParam | ChatCompletionMessageParam[];\n};\nexport type HistoryContextEventAppendToHistory = IEvent<\n HistoryContextAppendParameters,\n HistoryContextEventName['appendToHistory']\n>;\nexport type HistoryContextEventPrepareHistory = IEvent<unknown, HistoryContextEventName['prepareHistory']>;\nexport type HistoryContextEventAdjustOnCancel = IEvent<unknown, HistoryContextEventName['adjustOnCancel']>;\nexport type HistoryContextEvent =\n | HistoryContextEventAppendToHistory\n | HistoryContextEventPrepareHistory\n | HistoryContextEventAdjustOnCancel;\n\nexport type HistoryContextState = {\n class: typeof historyContextClassId;\n\n /** messages to send to OpenAI API */\n messages: ChatCompletionMessageParam[];\n};\n\nexport interface HistoryContextConfig extends BaseConfig {\n state: HistoryContextState;\n events: HistoryContextEvent;\n}\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport type { CONFIG, IThreadId, IThread, IStepId } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageParam } from 'openai/resources.js';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { ChatCompletionConfig } from '../main/types.ts';\n\nimport { historyContextClassId, historyContextEvents } from './types.ts';\nimport type {\n HistoryContextConfig,\n HistoryContextEventName,\n HistoryContextAppendParameters,\n HistoryContextEventAppendToHistory,\n} from './types.ts';\n\nexport class HistoryContext extends BaseStep<HistoryContextConfig> {\n public static readonly class = historyContextClassId;\n\n public static async start(thread: IThread<ChatCompletionConfig>): Promise<void> {\n const historyThreadId = this.getThreadId(thread.step.id);\n const historyThread = thread.process.getThread<HistoryContextConfig>(historyThreadId);\n\n if (historyThread != undefined) return; // thread already exists\n\n // create tools context thread\n await thread.process.runThread<HistoryContextConfig>({\n id: historyThreadId,\n background: true,\n state: {\n step: thread.step.id,\n class: this.class,\n\n messages: [],\n },\n });\n }\n\n public static async prepareHistory<T extends ChatCompletionConfig>(thread: IThread<T>): Promise<void> {\n await thread.process.enqueueAndRun<HistoryContextEventName['prepareHistory']>({\n thread: this.getThreadId(thread.step.id),\n name: historyContextEvents.prepareHistory,\n });\n }\n\n public static async appendToHistory<T extends ChatCompletionConfig>(\n thread: IThread<T>,\n message: ChatCompletionMessageParam | ChatCompletionMessageParam[],\n ): Promise<void> {\n await thread.process.enqueueAndRun<HistoryContextEventName['appendToHistory'], HistoryContextAppendParameters>({\n thread: this.getThreadId(thread.step.id),\n name: historyContextEvents.appendToHistory,\n params: { message },\n });\n }\n\n public static async adjustOnCancel<T extends ChatCompletionConfig>(thread: IThread<T>): Promise<void> {\n await thread.process.enqueueAndRun<HistoryContextEventName['adjustOnCancel']>({\n thread: this.getThreadId(thread.step.id),\n name: historyContextEvents.adjustOnCancel,\n });\n }\n\n public static getHistory<T extends CONFIG>(thread: IThread<T>): ChatCompletionMessageParam[] {\n return thread.process.getSafeThread<HistoryContextConfig>(this.getThreadId(thread.step.id)).state.messages;\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ---------------------------------------\n\n @BackgroundThreadErrorFilter\n public runStep(): void {\n this.triggers\n .local(historyContextEvents.prepareHistory, this.onPrepareHistory)\n .local(historyContextEvents.appendToHistory, this.onAppendToHistory)\n .local(historyContextEvents.adjustOnCancel, this.onAdjustOnCancel)\n .otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n public initialize(): void {\n this.log.DEBUG?.(`Initializing ${HistoryContext.name} thread`);\n }\n\n @BackgroundThreadErrorFilter\n public onAdjustOnCancel(): void {\n let message;\n while ((message = this.state.messages.at(-1))) {\n if (['system', 'user'].includes(message.role)) break;\n if (message.role === 'assistant' && message.tool_calls == undefined) break;\n\n const removedMessage = this.state.messages.pop();\n this.log.DEBUG?.('Removed message from history', removedMessage);\n }\n }\n\n @BackgroundThreadErrorFilter\n public onPrepareHistory(): void {\n this.log.DEBUG?.('Preparing history');\n\n const {\n customHistory,\n historyLength,\n systemMessage,\n typeOfStep,\n userMessage,\n historyMode,\n historyMergefield,\n historyCode,\n assistantsFirstMessage,\n } = this.data;\n\n // 1. text completion mode\n if (typeOfStep === 'completion') {\n this.state.messages = [\n {\n role: 'user',\n content: userMessage!, // never would be undefined due to validation against schema\n },\n ];\n return;\n }\n\n // 2. chat mode (custom history)\n if (customHistory) {\n this.state.messages = historyMode === 'mergefield' ? historyMergefield! : historyCode!;\n return;\n }\n\n // 3. chat mode (step managed history)\n let messages = this.state.messages;\n\n // is a fresh conversation?\n if (messages.length === 0 && assistantsFirstMessage != undefined && assistantsFirstMessage.length > 0) {\n messages.push({\n role: 'assistant',\n content: assistantsFirstMessage,\n });\n }\n\n // if last message is a tool response, assume user message is already in history\n if (messages.at(-1)?.role !== 'tool') {\n messages.push({\n role: 'user',\n content: userMessage!, // never would be undefined due to validation against schema\n // TODO: add support for optional user name\n // name: userName,\n });\n }\n\n // trim history length\n const hasToolCalls = messages.some((message) => message.role === 'tool');\n if (!hasToolCalls && historyLength != undefined && historyLength > 0) {\n messages = messages.slice(-1 * historyLength);\n }\n\n // add system message as first message if it exists\n if (systemMessage != undefined && systemMessage.length > 0) {\n const systemMessageRecord = {\n role: 'system' as const,\n content: systemMessage,\n };\n\n if (messages[0]?.role === 'system') {\n messages[0] = systemMessageRecord; // replace existing system message\n } else {\n messages.unshift(systemMessageRecord); // add system message as first message\n }\n }\n\n // store history\n this.state.messages = messages;\n }\n\n @BackgroundThreadErrorFilter\n public onAppendToHistory(event: HistoryContextEventAppendToHistory): void {\n this.log.DEBUG?.('Appending message to history', event.params);\n\n const { message } = event.params;\n const messages = Array.isArray(message) ? message : [message];\n this.state.messages.push(...messages);\n }\n}\n","export const requestContextClassId = 'rqst_ctx';\n","export const contentContextEvents = {\n handleContent: 'hnd_cnt',\n} as const;\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport { setImmediate } from 'node:timers/promises';\nimport type { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletion, ChatCompletionChunk } from 'openai/resources/index.js';\n\nimport { contentContextEvents } from '../../content/constants.ts';\nimport type { RequestContextConfig } from '../types.ts';\n\nexport abstract class AbstractResponseHandler extends BasicThreadService<RequestContextConfig> {\n public abstract handle(response: ChatCompletion | Stream<ChatCompletionChunk>): Promise<void>;\n\n protected async handleContentByParentThread(content: ChatCompletion | ChatCompletionChunk): Promise<void> {\n await setImmediate();\n await this.thread.process.enqueueAndRun({\n thread: this.thread.local.parent,\n name: contentContextEvents.handleContent,\n params: { content },\n });\n }\n}\n","import type { ChatCompletion } from 'openai/resources.js';\n\nimport { deleteAbortController } from '../../../utils/process-abort-controller.ts';\n\nimport { AbstractResponseHandler } from './abstract-response-handler.ts';\n\nexport class SimpleResponseHandler extends AbstractResponseHandler {\n public async handle(response: ChatCompletion): Promise<void> {\n this.log.DEBUG?.('Start processing response from LLM');\n await this.handleContentByParentThread(response);\n deleteAbortController({ thread: this.thread });\n }\n}\n","import type { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletionChunk } from 'openai/resources.js';\n\nimport { deleteAbortController } from '../../../utils/process-abort-controller.ts';\n\nimport { AbstractResponseHandler } from './abstract-response-handler.ts';\n\nexport class StreamResponseHandler extends AbstractResponseHandler {\n public async handle(response: Stream<ChatCompletionChunk>): Promise<void> {\n this.log.DEBUG?.('Start processing stream of chunks from LLM');\n\n for await (const chunk of response) {\n // send each chunk to the controller thread for processing\n await this.handleContentByParentThread(chunk);\n }\n\n deleteAbortController({ thread: this.thread });\n }\n}\n","import type { IThread } from '@onereach/flow-sdk/types/index.js';\n\nimport type { AbstractResponseHandler } from '../response-handlers/abstract-response-handler.ts';\nimport { SimpleResponseHandler } from '../response-handlers/simple-response-handler.ts';\nimport { StreamResponseHandler } from '../response-handlers/stream-response-handler.ts';\nimport type { RequestContextConfig } from '../types.ts';\n\nexport function responseHandlerFactory({\n thread,\n isStreaming,\n}: ResponseHandlerFactoryParameters): AbstractResponseHandler {\n if (isStreaming) return new StreamResponseHandler(thread);\n return new SimpleResponseHandler(thread);\n}\n\nexport type ResponseHandlerFactoryParameters = {\n thread: IThread<RequestContextConfig>;\n isStreaming: boolean;\n};\n","import { BasicThreadService } from '@onereach/flow-sdk/services/basic.js';\nimport type { CONFIG, IN, IThread } from '@onereach/flow-sdk/types/index.js';\n\nexport class ThreadServiceWithData<\n TConfig extends CONFIG,\n TData extends IN<CONFIG> = IN<TConfig>,\n> extends BasicThreadService<TConfig> {\n protected readonly data: TData;\n\n constructor(thread: IThread<TConfig>, data: TData) {\n super(thread);\n this.data = data;\n }\n}\n","import OpenAI from 'openai';\nimport type { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletionCreateParams } from 'openai/resources/chat/completions.mjs';\nimport type {\n ChatCompletion,\n ChatCompletionChunk,\n ChatCompletionMessageParam,\n ChatCompletionTool,\n} from 'openai/resources.mjs';\nimport timestring from 'timestring';\nimport { Memoize } from 'typescript-memoize';\nimport * as z from 'zod/mini';\n\nimport { CreateChatCompletionStepError, ErrorCode } from '../../../errors/step-error.ts';\nimport { ThreadServiceWithData } from '../../../services/thread-service-with-data.ts';\nimport type { RequestContextConfig } from '../types.ts';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\nexport class OpenAIRequestService extends ThreadServiceWithData<RequestContextConfig> {\n /**\n * Makes a request to the OpenAI API to create a chat completion.\n */\n public async makeChatCompletionRequest(\n messages: ChatCompletionMessageParam[],\n signal?: AbortSignal,\n ): Promise<ChatCompletion | Stream<ChatCompletionChunk>> {\n const {\n model,\n temperature,\n topP,\n maxTokens,\n frequencyPenalty,\n presencePenalty,\n n,\n streamResponse,\n reasoningEffort,\n } = this.data;\n\n const request: ChatCompletionCreateParams = {\n messages: structuredClone(messages), // clone to avoid mutation\n model,\n temperature,\n top_p: topP,\n max_tokens: maxTokens,\n frequency_penalty: frequencyPenalty,\n presence_penalty: presencePenalty,\n stop: this.stopSequences,\n n,\n reasoning_effort: reasoningEffort,\n stream: streamResponse,\n tools: this.tools,\n };\n this.log.DEBUG?.('LLM request', request);\n\n try {\n const response = await this.doChatCompletionRequest(request, { signal });\n\n if (!streamResponse) this.log.DEBUG?.('LLM response', response);\n\n return response;\n } catch (error) {\n if (error instanceof Error === false) throw error;\n\n throw new CreateChatCompletionStepError('Chat completion request failed', error, {\n code: ErrorCode.SERVER_ERROR,\n data: request,\n });\n }\n }\n\n protected async doChatCompletionRequest(\n request: ChatCompletionCreateParams,\n options?: OpenAI.RequestOptions,\n ): Promise<ChatCompletion | Stream<ChatCompletionChunk>> {\n // TODO: remove this cast\n return (await this.openAiClient.chat.completions.create(request, options)) as unknown as Promise<\n ChatCompletion | Stream<ChatCompletionChunk>\n >;\n }\n\n protected get tools(): ChatCompletionTool[] | undefined {\n const { functionsList } = this.data;\n\n if (!Array.isArray(functionsList) || functionsList.length === 0) return undefined;\n\n return functionsList.map((tool) => ({\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: !tool.parameters || Object.keys(tool.parameters).length === 0 ? undefined : tool.parameters,\n strict: tool.strict,\n },\n }));\n }\n\n /**\n * Returns the OpenAI client instance configured with the step's data.\n */\n protected get openAiClient(): OpenAI {\n const { accountKey } = this.data;\n\n const clientOptions = {\n baseURL: this.openAiBaseUrl,\n apiKey: '_fake_key_',\n defaultHeaders: {\n Authorization: this.config.authorization,\n 'x-or-session-id': this.session.get<string>(['reporting', 'sessionId']),\n ...(accountKey ? { 'x-or-account-token-name': accountKey } : undefined),\n },\n timeout: this.timeoutMs,\n };\n\n return new OpenAI(clientOptions);\n }\n\n protected get openAiBaseUrl(): string {\n return `${this.config.env.OPENAI_API_URL}/${this.data.provider}`;\n }\n\n protected get stopSequences(): string[] {\n const list = this.data.stop ?? [];\n return list.map((item) => item.token).filter((token) => token.length > 0);\n }\n\n /**\n * Returns the timeout duration in milliseconds.\n */\n @Memoize()\n protected get timeoutMs(): number {\n const value = timestring(this.data.timeoutDuration, 'ms');\n\n // 1 second to 10 minutes\n return z.number().check(z.int(), z.gte(1000), z.lte(600_000)).parse(value);\n }\n}\n","import type { Attributes, AttributeValue } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_OPERATION_NAME,\n GEN_AI_OPERATION_NAME_VALUE_CHAT,\n ATTR_GEN_AI_PROVIDER_NAME,\n ATTR_GEN_AI_REQUEST_MODEL,\n ATTR_GEN_AI_REQUEST_STREAM,\n ATTR_GEN_AI_OUTPUT_TYPE,\n GEN_AI_OUTPUT_TYPE_VALUE_TEXT,\n GEN_AI_OUTPUT_TYPE_VALUE_JSON,\n ATTR_GEN_AI_REQUEST_CHOICE_COUNT,\n ATTR_GEN_AI_REQUEST_SEED,\n ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY,\n ATTR_GEN_AI_REQUEST_MAX_TOKENS,\n ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY,\n ATTR_GEN_AI_REQUEST_STOP_SEQUENCES,\n ATTR_GEN_AI_REQUEST_TEMPERATURE,\n ATTR_GEN_AI_REQUEST_TOP_P,\n ATTR_GEN_AI_RESPONSE_FINISH_REASONS,\n ATTR_GEN_AI_RESPONSE_ID,\n ATTR_GEN_AI_RESPONSE_MODEL,\n ATTR_GEN_AI_USAGE_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,\n ATTR_GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_REASONING_OUTPUT_TOKENS,\n ATTR_GEN_AI_INPUT_MESSAGES,\n ATTR_GEN_AI_OUTPUT_MESSAGES,\n GEN_AI_PROVIDER_NAME_VALUE_ANTHROPIC,\n GEN_AI_PROVIDER_NAME_VALUE_AWS_BEDROCK,\n GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_INFERENCE,\n GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_OPENAI,\n GEN_AI_PROVIDER_NAME_VALUE_COHERE,\n GEN_AI_PROVIDER_NAME_VALUE_DEEPSEEK,\n GEN_AI_PROVIDER_NAME_VALUE_GCP_GEMINI,\n GEN_AI_PROVIDER_NAME_VALUE_GCP_GEN_AI,\n GEN_AI_PROVIDER_NAME_VALUE_GCP_VERTEX_AI,\n GEN_AI_PROVIDER_NAME_VALUE_GROQ,\n GEN_AI_PROVIDER_NAME_VALUE_IBM_WATSONX_AI,\n GEN_AI_PROVIDER_NAME_VALUE_MISTRAL_AI,\n GEN_AI_PROVIDER_NAME_VALUE_OPENAI,\n GEN_AI_PROVIDER_NAME_VALUE_PERPLEXITY,\n GEN_AI_PROVIDER_NAME_VALUE_X_AI,\n ATTR_SERVER_ADDRESS,\n ATTR_SERVER_PORT,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport type { ChatCompletionCreateParams, ChatCompletionChunk } from 'openai/resources';\nimport type { ChatCompletion } from 'openai/resources.js';\n\n/**\n * Attributes common to span, metrics, log events.\n * See more details in {@link [official docs](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)}\n * @param request - The chat completion request parameters.\n * @param provider - The name of the provider\n * @param baseURL - The custom base URL for the provider (optional)\n * @returns The common attributes.\n */\n\nexport function getCommonAttributes(\n request: ChatCompletionCreateParams,\n provider: Provider,\n baseURL?: string,\n): Attributes {\n return {\n [ATTR_GEN_AI_OPERATION_NAME]: GEN_AI_OPERATION_NAME_VALUE_CHAT,\n [ATTR_GEN_AI_PROVIDER_NAME]: provider,\n [ATTR_GEN_AI_REQUEST_MODEL]: request.model,\n ...getAttributesFromBaseURL(baseURL),\n };\n}\n/**\n * Span attributes.\n * See more details in {@link [official docs](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)}\n */\n\nexport function getRequestSpanAttributes(request: ChatCompletionCreateParams): Attributes {\n const attributes: Attributes = {\n [ATTR_GEN_AI_REQUEST_STREAM]: Boolean(request.stream),\n\n // does not capture image and speech output types but it's sufficient for current step capabilities\n [ATTR_GEN_AI_OUTPUT_TYPE]:\n request.response_format == undefined || request.response_format.type === 'text'\n ? GEN_AI_OUTPUT_TYPE_VALUE_TEXT\n : GEN_AI_OUTPUT_TYPE_VALUE_JSON,\n };\n\n if (request.n != undefined && request.n > 1) {\n attributes[ATTR_GEN_AI_REQUEST_CHOICE_COUNT] = request.n;\n }\n if (request.seed != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_SEED] = request.seed;\n }\n if (request.frequency_penalty != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY] = request.frequency_penalty;\n }\n if (request.max_completion_tokens != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_MAX_TOKENS] = request.max_completion_tokens;\n } else if (request.max_tokens != undefined) {\n // `max_tokens` is deprecated in favour of `max_completion_tokens`.\n attributes[ATTR_GEN_AI_REQUEST_MAX_TOKENS] = request.max_tokens;\n }\n if (request.presence_penalty != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY] = request.presence_penalty;\n }\n if (request.stop != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = Array.isArray(request.stop) ? request.stop : [request.stop];\n }\n if (request.temperature != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_TEMPERATURE] = request.temperature;\n }\n if (request.top_p != undefined) {\n attributes[ATTR_GEN_AI_REQUEST_TOP_P] = request.top_p;\n }\n return attributes;\n}\n/**\n * Span attributes.\n * See more details in {@link [official docs](https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.md)}\n */\n\nexport function getResponseSpanAttributes(result: ChatCompletion | ChatCompletionChunk): Attributes {\n return {\n [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: result.choices\n .map((choice) => choice.finish_reason)\n .filter((reason) => reason != undefined),\n\n [ATTR_GEN_AI_RESPONSE_ID]: result.id,\n [ATTR_GEN_AI_RESPONSE_MODEL]: result.model,\n\n ...(result.usage && {\n [ATTR_GEN_AI_USAGE_INPUT_TOKENS]: result.usage.prompt_tokens,\n [ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: result.usage.completion_tokens,\n }),\n ...(result.usage?.prompt_tokens_details && {\n [ATTR_GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS]: result.usage.prompt_tokens_details.cached_tokens,\n }),\n ...(result.usage?.completion_tokens_details && {\n [ATTR_GEN_AI_USAGE_REASONING_OUTPUT_TOKENS]: result.usage.completion_tokens_details.reasoning_tokens,\n }),\n };\n}\n/**\n * Get the messages with inference details.\n * @param request - The chat completion request parameters.\n * @param result - The chat completion result.\n * @returns The messages attributes.\n */\n\nexport function getMessagesAttributes(request: ChatCompletionCreateParams, result: ChatCompletion): Attributes {\n return {\n // TODO: validate against schema https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-input-messages.json\n [ATTR_GEN_AI_INPUT_MESSAGES]: request.messages.map(({content, ...message}) => ({\n ...message,\n\n role: message.role,\n parts: Array.isArray(content)\n ? content.map((part) => {\n switch (part.type) {\n case 'text': {\n return {\n type: 'text',\n content: part.text,\n };\n }\n case 'input_audio': {\n return {\n type: 'blob',\n modality: 'audio',\n mime_type: `audio/${part.input_audio.format}`,\n content: part.input_audio.data,\n };\n }\n case 'file': {\n return {\n type: 'file',\n modality: 'document', // ???\n file_id: part.file.file_id,\n };\n }\n case 'image_url': {\n try {\n new URL(part.image_url.url);\n return {\n type: 'uri',\n modality: 'image',\n uri: part.image_url.url,\n };\n } catch {\n return {\n type: 'blob',\n modality: 'image',\n content: part.image_url.url,\n };\n }\n }\n case 'refusal': {\n return {\n type: 'refusal',\n content: part.refusal,\n };\n }\n default: {\n return part;\n }\n }\n })\n : [\n {\n type: 'text',\n content: content,\n },\n ],\n })) as unknown as AttributeValue,\n\n // TODO: validate against schema https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-output-messages.json\n [ATTR_GEN_AI_OUTPUT_MESSAGES]: result.choices.map((choice) => ({\n role: choice.message.role,\n finish_reason:\n choice.finish_reason === 'tool_calls' || choice.finish_reason === 'function_call'\n ? 'tool_call'\n : choice.finish_reason,\n parts: [\n ...(choice.message.content\n ? [\n {\n type: 'text',\n content: choice.message.content,\n },\n ]\n : []),\n (choice.message.tool_calls ?? []).map((toolCall) =>\n toolCall.type === 'function'\n ? {\n type: 'tool_call',\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n }\n : toolCall,\n ),\n ],\n })) as unknown as AttributeValue,\n };\n}\nexport type Provider =\n | typeof GEN_AI_PROVIDER_NAME_VALUE_ANTHROPIC\n | typeof GEN_AI_PROVIDER_NAME_VALUE_AWS_BEDROCK\n | typeof GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_INFERENCE\n | typeof GEN_AI_PROVIDER_NAME_VALUE_AZURE_AI_OPENAI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_COHERE\n | typeof GEN_AI_PROVIDER_NAME_VALUE_DEEPSEEK\n | typeof GEN_AI_PROVIDER_NAME_VALUE_GCP_GEMINI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_GCP_GEN_AI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_GCP_VERTEX_AI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_GROQ\n | typeof GEN_AI_PROVIDER_NAME_VALUE_IBM_WATSONX_AI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_MISTRAL_AI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_OPENAI\n | typeof GEN_AI_PROVIDER_NAME_VALUE_PERPLEXITY\n | typeof GEN_AI_PROVIDER_NAME_VALUE_X_AI;\nconst SERVER_PORT_FROM_URL_PROTOCOL: PortFromProtocol = {\n 'https:': 443,\n 'http:': 80,\n};\n\nexport function getAttributesFromBaseURL(baseURL?: string): Attributes | undefined {\n if (!baseURL) {\n return;\n }\n\n let url: URL;\n try {\n url = new URL(baseURL);\n } catch {\n return;\n }\n\n return {\n [ATTR_SERVER_ADDRESS]: url.hostname,\n [ATTR_SERVER_PORT]: url.port ? Number(url.port) : SERVER_PORT_FROM_URL_PROTOCOL[url.protocol],\n };\n}\ntype PortFromProtocol = { [key: string]: number };\n","import type { Attributes, Context } from '@opentelemetry/api';\nimport type { Logger } from '@opentelemetry/api-logs';\nimport { SeverityNumber } from '@opentelemetry/api-logs';\nimport { EVENT_GEN_AI_CLIENT_INFERENCE_OPERATION_DETAILS } from '@opentelemetry/semantic-conventions/incubating';\nimport type { ChatCompletion, ChatCompletionCreateParams } from 'openai/resources';\n\nimport { OtelConfig } from '../../../../schemas/data-in.ts';\n\nimport { getMessagesAttributes, getResponseSpanAttributes } from './attributes.ts';\n\nexport function getInferenceDetailsEmitter({\n logger,\n spanAttributes,\n config,\n request,\n context,\n}: InferenceOperationDetailsEmitterParameters): InferenceOperationDetailsEmitter {\n return function (response: ChatCompletion): void {\n // Report llm client inference operation details as log event\n logger.emit({\n context: context,\n eventName: EVENT_GEN_AI_CLIENT_INFERENCE_OPERATION_DETAILS,\n severityNumber: SeverityNumber.INFO,\n attributes: {\n ...spanAttributes,\n ...getResponseSpanAttributes(response),\n\n ...(config?.captureMessageContentInLogs && getMessagesAttributes(request, response)),\n },\n });\n };\n}\n\nexport type InferenceOperationDetailsEmitterParameters = {\n logger: Logger;\n spanAttributes: Attributes;\n request: ChatCompletionCreateParams;\n context?: Context;\n config?: OtelConfig;\n};\n\nexport type InferenceOperationDetailsEmitter = (response: ChatCompletion) => void;\n","import type { Meter, Histogram, Attributes, Context } from '@opentelemetry/api';\nimport {\n METRIC_GEN_AI_CLIENT_OPERATION_DURATION,\n ATTR_GEN_AI_RESPONSE_MODEL,\n} from '@opentelemetry/semantic-conventions/incubating';\n\nexport function operationDurationHistogram(meter: Meter): Histogram<Attributes> {\n return meter.createHistogram(METRIC_GEN_AI_CLIENT_OPERATION_DURATION, {\n description: 'GenAI operation duration',\n unit: 's',\n advice: {\n explicitBucketBoundaries: [\n 0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92,\n ],\n },\n });\n}\n\nexport function getOperationDurationRecorder({\n meter,\n attributes,\n context,\n startTime = Date.now(),\n}: OperationDurationRecorderParameters): OperationDurationRecorder {\n const metric = operationDurationHistogram(meter);\n return function (responseModel?: string, durationSec?: number): void {\n metric.record(\n durationSec ?? (Date.now() - startTime) / 1000,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n },\n context,\n );\n };\n}\n\nexport type OperationDurationRecorderParameters = {\n meter: Meter;\n attributes: Attributes;\n context?: Context;\n startTime?: number;\n};\n\nexport type OperationDurationRecorder = (responseModel?: string, durationSec?: number) => void;\n","import type { Attributes, Context, Histogram, Meter } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_RESPONSE_MODEL,\n METRIC_GEN_AI_CLIENT_OPERATION_TIME_PER_OUTPUT_CHUNK,\n} from '@opentelemetry/semantic-conventions/incubating';\n\nexport function getTimePerOutputChunkHistogram(meter: Meter): Histogram<Attributes> {\n return meter.createHistogram(METRIC_GEN_AI_CLIENT_OPERATION_TIME_PER_OUTPUT_CHUNK, {\n description: 'GenAI operation time per output chunk',\n unit: 's',\n advice: {\n explicitBucketBoundaries: [\n 0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92,\n ],\n },\n });\n}\n\nexport function getTimePerOutputChunkRecorder({\n meter,\n attributes,\n context,\n}: TimePerOutputChunkRecorderParameters): TimePerOutputChunkRecorder {\n return function (durationSec: number, responseModel?: string): void {\n getTimePerOutputChunkHistogram(meter).record(\n durationSec,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n },\n context,\n );\n };\n}\n\nexport type TimePerOutputChunkRecorderParameters = {\n meter: Meter;\n attributes: Attributes;\n context?: Context;\n};\n\nexport type TimePerOutputChunkRecorder = (durationSec: number, responseModel?: string) => void;\n","import type { Attributes, Context, Histogram, Meter } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_RESPONSE_MODEL,\n METRIC_GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK,\n} from '@opentelemetry/semantic-conventions/incubating';\n\nexport function getTimeToFirstChunkHistogram(meter: Meter): Histogram<Attributes> {\n return meter.createHistogram(METRIC_GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK, {\n description: 'GenAI operation time to first chunk',\n unit: 's',\n advice: {\n explicitBucketBoundaries: [\n 0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92,\n ],\n },\n });\n}\n\nexport function getTimeToFirstChunkRecorder({\n meter,\n attributes,\n context,\n}: TimeToFirstChunkRecorderParameters): TimeToFirstChunkRecorder {\n return function (durationSec: number, responseModel?: string): void {\n getTimeToFirstChunkHistogram(meter).record(\n durationSec,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n },\n context,\n );\n };\n}\n\nexport type TimeToFirstChunkRecorderParameters = {\n meter: Meter;\n attributes: Attributes;\n context?: Context;\n};\n\nexport type TimeToFirstChunkRecorder = (durationSec: number, responseModel?: string) => void;\n","import type { Meter, Histogram, Attributes, Context } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_RESPONSE_MODEL,\n ATTR_GEN_AI_TOKEN_TYPE,\n GEN_AI_TOKEN_TYPE_VALUE_INPUT,\n GEN_AI_TOKEN_TYPE_VALUE_OUTPUT,\n METRIC_GEN_AI_CLIENT_TOKEN_USAGE,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport { CompletionUsage } from 'openai/resources';\n\nexport function tokenUsageHistogram(meter: Meter): Histogram<Attributes> {\n return meter.createHistogram(METRIC_GEN_AI_CLIENT_TOKEN_USAGE, {\n description: 'Measures number of input and output tokens used',\n unit: '{token}',\n advice: {\n explicitBucketBoundaries: [\n 1, 4, 16, 64, 256, 1024, 4096, 16_384, 65_536, 262_144, 1_048_576, 4_194_304, 16_777_216, 67_108_864,\n ],\n },\n });\n}\n\nexport function getTokenUsageRecorder({\n meter,\n context,\n attributes,\n}: TokenUsageRecorderParameters): TokenUsageRecorder {\n const metric = tokenUsageHistogram(meter);\n return function (usage?: CompletionUsage, responseModel?: string): void {\n if (usage?.prompt_tokens != undefined) {\n metric.record(\n usage.prompt_tokens,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n [ATTR_GEN_AI_TOKEN_TYPE]: GEN_AI_TOKEN_TYPE_VALUE_INPUT,\n },\n context,\n );\n }\n if (usage?.completion_tokens != undefined) {\n metric.record(\n usage.completion_tokens,\n {\n ...attributes,\n [ATTR_GEN_AI_RESPONSE_MODEL]: responseModel ?? 'unknown',\n [ATTR_GEN_AI_TOKEN_TYPE]: GEN_AI_TOKEN_TYPE_VALUE_OUTPUT,\n },\n context,\n );\n }\n };\n}\n\nexport type TokenUsageRecorderParameters = {\n meter: Meter;\n attributes: Attributes;\n context?: Context;\n};\n\nexport type TokenUsageRecorder = (usage?: CompletionUsage, responseModel?: string) => void;\n","import type {\n ChatCompletion,\n ChatCompletionChunk,\n ChatCompletionMessage,\n ChatCompletionMessageFunctionToolCall,\n ChatCompletionMessageToolCall,\n} from 'openai/resources.js';\n\nimport type { ToolsContextParsedArguments } from '../threads/tools/worker/types.ts';\n\nexport class OpenAiStreamReducer<TArguments = ToolsContextParsedArguments> {\n protected result: Partial<ChatCompletion>;\n protected readonly onToolCall?: OnToolCallCallback<TArguments>;\n\n constructor(memo: Partial<ChatCompletion>, onToolCall?: OnToolCallCallback<TArguments>) {\n this.result = memo;\n this.onToolCall = onToolCall;\n }\n\n public reduceChunk(chunk: ChatCompletionChunk): void {\n if (Object.keys(this.result).length === 0) {\n const { choices, ...rest } = chunk; // eslint-disable-line @typescript-eslint/no-unused-vars\n Object.assign(this.result, rest);\n\n if (this.result.object != undefined) {\n this.result.object = 'chat.completion';\n }\n }\n\n if (chunk.usage) {\n this.result.usage = chunk.usage;\n // return\n }\n\n for (const choice of chunk.choices) {\n this.reduceChunkChoice(choice);\n }\n }\n\n protected reduceChunkChoice(choice: ChatCompletionChunk.Choice): void {\n let existing = this.result.choices?.[choice.index];\n\n if (!existing) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { delta, ...rest } = choice;\n existing = rest as ChatCompletion.Choice;\n this.result.choices ??= [];\n this.result.choices[choice.index] = existing;\n }\n\n if (choice.finish_reason != undefined) {\n existing.finish_reason = choice.finish_reason;\n }\n\n if (choice.logprobs != undefined) {\n existing.logprobs = choice.logprobs;\n }\n\n if (choice.delta?.content !== undefined) {\n const { content, ...delta } = choice.delta;\n existing.message ??= delta as ChatCompletionMessage;\n if (content === null) {\n // eslint-disable-next-line unicorn/no-null\n existing.message.content ??= null;\n } else {\n existing.message.content ??= '';\n existing.message.content += content;\n }\n }\n\n if (choice.delta?.tool_calls != undefined) {\n const { tool_calls, ...delta } = choice.delta;\n existing.message ??= delta as ChatCompletionMessage;\n existing.message.tool_calls ??= [];\n\n for (const deltaToolCall of tool_calls) {\n const index = deltaToolCall.index;\n if (existing.message.tool_calls[index] == undefined) {\n existing.message.tool_calls[index] = structuredClone(deltaToolCall) as ChatCompletionMessageFunctionToolCall;\n } else {\n const toolCall = existing.message.tool_calls[index];\n if (!('function' in toolCall) || toolCall.function == undefined) continue;\n\n toolCall.function.arguments += deltaToolCall.function?.arguments ?? '';\n }\n\n // set immediate to not block the event loop\n if (choice.index === 0 && this.onToolCall != undefined) {\n this.tryParseToolCall(existing.message.tool_calls[index]);\n }\n }\n }\n }\n\n protected tryParseToolCall(toolCall: ChatCompletionMessageToolCall): void {\n try {\n if (!('function' in toolCall) || toolCall.function == undefined) return;\n const parsedArguments = JSON.parse(toolCall.function.arguments) as TArguments;\n if (this.onToolCall != undefined) void this.onToolCall(toolCall, parsedArguments);\n } catch {\n // if failed to parse, just ignore it assume it's not fully loaded yet\n }\n }\n}\n\nexport type OnToolCallCallback<TArguments = ToolsContextParsedArguments> = (\n toolCall: ChatCompletionMessageFunctionToolCall,\n parsedArguments: TArguments,\n) => void | Promise<void>;\n","import { context, propagation, SpanKind, SpanStatusCode, trace } from '@opentelemetry/api';\nimport type { Attributes, Context, Span, Tracer } from '@opentelemetry/api';\nimport {\n ATTR_GEN_AI_OPERATION_NAME,\n ATTR_GEN_AI_REQUEST_MODEL,\n ATTR_GEN_AI_RESPONSE_FINISH_REASONS,\n ATTR_GEN_AI_RESPONSE_TIME_TO_FIRST_CHUNK,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletionChunk, ChatCompletionCreateParams, CompletionUsage } from 'openai/resources';\nimport type { ChatCompletion } from 'openai/resources.js';\n\nimport { OtelConfig } from '../../../../schemas/data-in.ts';\nimport type { ToolsContextParsedArguments } from '../../../../types.ts';\nimport { OpenAiStreamReducer } from '../../../../utils/openai-stream-reducer.ts';\n\nimport { getResponseSpanAttributes, getCommonAttributes, getRequestSpanAttributes, Provider } from './attributes.ts';\nimport type { InferenceOperationDetailsEmitter } from './events.ts';\nimport type { OperationDurationRecorder } from './metrics/operation-duration.ts';\nimport { TimePerOutputChunkRecorder } from './metrics/time-per-output-chunk.ts';\nimport { TimeToFirstChunkRecorder } from './metrics/time-to-first-chunk.ts';\nimport { TokenUsageRecorder } from './metrics/token-usage.ts';\n\n/**\n * Get the parent context from the carrier.\n * @param carrier - The carrier object.\n * @returns The parent context or undefined if the carrier is empty.\n */\nexport function getParentContext(carrier?: Record<string, unknown>): Context | undefined {\n if (!carrier || Object.keys(carrier).length === 0) return;\n\n return propagation.extract(context.active(), carrier);\n}\n\nexport async function* wrapResponseStreamWithSpan(\n responsePromise: Promise<Stream<ChatCompletionChunk>>,\n span: Span,\n\n emitInferenceOperationDetails: InferenceOperationDetailsEmitter,\n recordOperationDuration: OperationDurationRecorder,\n recordTokenUsage: TokenUsageRecorder,\n recordTimeToFirstChunk: TimeToFirstChunkRecorder,\n recordTimePerOutputChunk: TimePerOutputChunkRecorder,\n): AsyncGenerator<ChatCompletionChunk> {\n const finishReasons: string[] = [];\n const responseAttributes: Attributes = {};\n let responseModel: string | undefined;\n let usage: CompletionUsage | undefined;\n let chunkIndex = 0;\n let lastChunkTimestamp = Date.now();\n\n try {\n const stream = await responsePromise;\n\n // Capture the context that has our span attached\n const spanContext = trace.setSpan(context.active(), span);\n\n // Bind the response stream so each iteration resumes with spanContext active\n const boundStream = context.bind(spanContext, stream);\n\n const chatCompletion: Partial<ChatCompletion> = {};\n const reducer = new OpenAiStreamReducer<ToolsContextParsedArguments>(chatCompletion);\n\n for await (const chunk of boundStream) {\n reducer.reduceChunk(chunk);\n\n const finishReason = chunk.choices.map((choice) => choice?.finish_reason).filter((reason) => reason != undefined);\n finishReasons.push(...finishReason);\n\n Object.assign(responseAttributes, getResponseSpanAttributes(chunk));\n\n if (chunk.model) responseModel ??= chunk.model;\n if (chunk.usage) usage ??= chunk.usage;\n\n if (chunkIndex === 0) {\n const timeToFirstChunk = (Date.now() - lastChunkTimestamp) / 1000;\n recordTimeToFirstChunk(timeToFirstChunk, responseModel);\n responseAttributes[ATTR_GEN_AI_RESPONSE_TIME_TO_FIRST_CHUNK] = timeToFirstChunk;\n } else {\n recordTimePerOutputChunk((Date.now() - lastChunkTimestamp) / 1000, responseModel);\n }\n chunkIndex += 1;\n lastChunkTimestamp = Date.now();\n\n yield chunk;\n }\n\n Object.assign(responseAttributes, {\n [ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: finishReasons,\n });\n\n span.setAttributes(responseAttributes);\n span.setStatus({ code: SpanStatusCode.OK });\n\n // Report llm client inference operation details as log event\n emitInferenceOperationDetails(chatCompletion as ChatCompletion);\n\n // Record metrics\n recordOperationDuration(responseModel);\n recordTokenUsage(usage, responseModel);\n } catch (error) {\n let errorInstance: Error;\n if (error instanceof Error) {\n errorInstance = error;\n } else if (typeof error === 'string') {\n errorInstance = new Error(error);\n } else {\n errorInstance = new Error(String(error));\n }\n span.recordException(errorInstance);\n span.setStatus({ code: SpanStatusCode.ERROR, message: errorInstance.message });\n\n throw error;\n } finally {\n span.end();\n }\n}\n\nexport async function wrapResponseWithSpan(\n responsePromise: Promise<ChatCompletion>,\n span: Span,\n\n emitInferenceOperationDetails: InferenceOperationDetailsEmitter,\n recordOperationDuration: OperationDurationRecorder,\n recordTokenUsage: TokenUsageRecorder,\n): Promise<ChatCompletion> {\n try {\n const response = await responsePromise;\n const responseSpanAttributes = getResponseSpanAttributes(response);\n\n span.setAttributes(responseSpanAttributes);\n\n // Report llm client inference operation details as log event\n emitInferenceOperationDetails(response);\n\n // Record metrics\n recordOperationDuration(response.model);\n recordTokenUsage(response.usage, response.model);\n\n return response;\n } finally {\n span.end();\n }\n}\n\nexport function startChatCompletionsSpan({\n tracer,\n request,\n provider,\n openAiBaseURL,\n config,\n}: StartChatCompletionsSpanParameters): StartChatCompletionsSpanResult {\n // TODO: better map provider in data to a type\n const commonAttributes = getCommonAttributes(request, provider, openAiBaseURL);\n\n const attributes: Attributes = {\n ...commonAttributes,\n ...getRequestSpanAttributes(request),\n };\n\n const span: Span = tracer.startSpan(\n `${attributes[ATTR_GEN_AI_OPERATION_NAME] as string} ${attributes[ATTR_GEN_AI_REQUEST_MODEL] as string}`,\n {\n kind: SpanKind.CLIENT,\n attributes,\n },\n getParentContext(config?.carrier),\n );\n const spanContext: Context = trace.setSpan(context.active(), span);\n\n return { span, spanContext, commonAttributes, spanAttributes: attributes };\n}\n\nexport type StartChatCompletionsSpanParameters = {\n tracer: Tracer;\n request: ChatCompletionCreateParams;\n provider: Provider;\n openAiBaseURL?: string;\n config?: OtelConfig;\n};\n\nexport type StartChatCompletionsSpanResult = {\n span: Span;\n spanContext: Context;\n commonAttributes: Attributes;\n spanAttributes: Attributes;\n};\n","import { metrics, trace } from '@opentelemetry/api';\nimport type { Meter, Tracer } from '@opentelemetry/api';\nimport { logs } from '@opentelemetry/api-logs';\nimport type { Logger } from '@opentelemetry/api-logs';\nimport type { Stream } from 'openai/core/streaming.js';\nimport type { ChatCompletion, ChatCompletionChunk } from 'openai/resources.js';\nimport { Memoize } from 'typescript-memoize';\n\nimport { OpenAIRequestService } from './openai-request.ts';\nimport { Provider } from './otel-helpers/attributes.ts';\nimport { getInferenceDetailsEmitter } from './otel-helpers/events.ts';\nimport { getOperationDurationRecorder } from './otel-helpers/metrics/operation-duration.ts';\nimport { getTimePerOutputChunkRecorder } from './otel-helpers/metrics/time-per-output-chunk.ts';\nimport { getTimeToFirstChunkRecorder } from './otel-helpers/metrics/time-to-first-chunk.ts';\nimport { getTokenUsageRecorder } from './otel-helpers/metrics/token-usage.ts';\nimport {\n wrapResponseStreamWithSpan,\n startChatCompletionsSpan,\n StartChatCompletionsSpanResult,\n wrapResponseWithSpan,\n} from './otel-helpers/traces.ts';\n\n/**\n * OpenAIRequestOtelService is a service that wraps the OpenAIRequestService and adds OpenTelemetry tracing, metrics and logging.\n */\nexport class OpenAIRequestOtelService extends OpenAIRequestService {\n @Memoize()\n private get tracer(): Tracer {\n return trace.getTracer('create-llm-chat-completion-step');\n }\n\n @Memoize()\n private get meter(): Meter {\n return metrics.getMeter('create-llm-chat-completion-step');\n }\n\n @Memoize()\n private get logger(): Logger {\n return logs.getLogger('create-llm-chat-completion-step');\n }\n\n protected async doChatCompletionRequest(\n ...arguments_: Parameters<OpenAIRequestService['doChatCompletionRequest']>\n ): Promise<ChatCompletion | Stream<ChatCompletionChunk>> {\n const request = structuredClone(arguments_[0]);\n\n let startInfo: StartChatCompletionsSpanResult | undefined;\n // TODO: make this configurable in this.data\n const otelConfig = this.data.otel ?? {};\n\n try {\n startInfo = startChatCompletionsSpan({\n tracer: this.tracer,\n request,\n // TODO: better map provider in data to a type\n provider: this.data.provider as Provider,\n openAiBaseURL: this.openAiBaseUrl,\n config: otelConfig,\n });\n } catch (error) {\n this.log.WARN?.('Unexpected error starting OpenTelemetry span:', error);\n return super.doChatCompletionRequest(...arguments_);\n }\n const { span, spanContext, commonAttributes, spanAttributes } = startInfo;\n\n this.log.DEBUG?.('OpenTelemetry span started', {\n spanAttributes,\n });\n\n const emitInferenceOperationDetails = getInferenceDetailsEmitter({\n logger: this.logger,\n context: spanContext,\n spanAttributes,\n config: otelConfig,\n request,\n });\n const recordOperationDuration = getOperationDurationRecorder({\n meter: this.meter,\n attributes: commonAttributes,\n context: spanContext,\n });\n const recordTokenUsage = getTokenUsageRecorder({\n meter: this.meter,\n attributes: commonAttributes,\n context: spanContext,\n });\n\n const responsePromise = super.doChatCompletionRequest(...arguments_);\n\n if (request.stream) {\n const recordTimeToFirstChunk = getTimeToFirstChunkRecorder({\n meter: this.meter,\n attributes: commonAttributes,\n context: spanContext,\n });\n const recordTimePerOutputChunk = getTimePerOutputChunkRecorder({\n meter: this.meter,\n attributes: commonAttributes,\n context: spanContext,\n });\n\n const wrappedStream = wrapResponseStreamWithSpan(\n responsePromise as Promise<Stream<ChatCompletionChunk>>,\n span,\n emitInferenceOperationDetails,\n recordOperationDuration,\n recordTokenUsage,\n recordTimeToFirstChunk,\n recordTimePerOutputChunk,\n ) as unknown as Stream<ChatCompletionChunk>;\n\n return wrappedStream;\n }\n\n return wrapResponseWithSpan(\n responsePromise as Promise<ChatCompletion>,\n span,\n emitInferenceOperationDetails,\n recordOperationDuration,\n recordTokenUsage,\n );\n }\n}\n","import type { IStepId, IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageParam } from 'openai/resources.js';\nimport { clear, Memoize } from 'typescript-memoize';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { createAbortController, deleteAbortController } from '../../utils/process-abort-controller.ts';\nimport { runChildThread } from '../../utils/thread-utilities.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { ContentContextConfig } from '../content/types.ts';\nimport { HistoryContext } from '../history/history-context.ts';\n\nimport { requestContextClassId } from './constants.ts';\nimport { responseHandlerFactory } from './factories/response-handler.ts';\nimport type { AbstractResponseHandler } from './response-handlers/abstract-response-handler.ts';\nimport { OpenAIRequestOtelService } from './services/openai-request-otel.ts';\nimport type { OpenAIRequestService } from './services/openai-request.ts';\nimport type { RequestContextConfig, RequestContextResult } from './types.ts';\n\nconst memoizeTag = ['requestInit'];\n\nexport class RequestContext extends BaseStep<RequestContextConfig> {\n public static readonly class = requestContextClassId;\n\n public static async start<T extends ContentContextConfig>(thread: IThread<T>): Promise<RequestContextResult> {\n return await runChildThread<RequestContextConfig, T>(thread, {\n id: this.getThreadId(thread.step.id),\n state: {\n step: thread.step.id,\n class: this.class,\n },\n background: true,\n });\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ---------------------------------------\n\n private cancel() {\n this.end({ status: 'cancel' } satisfies RequestContextResult);\n }\n\n private complete() {\n this.end({ status: 'ok' });\n }\n\n private async getHistory(): Promise<ChatCompletionMessageParam[]> {\n const history = HistoryContext.getHistory(this.thread);\n const { useState } = this.data;\n\n return useState ? await this.getHistoryWithStateMessage(history) : history;\n }\n\n private async getHistoryWithStateMessage(\n history: ChatCompletionMessageParam[],\n ): Promise<ChatCompletionMessageParam[]> {\n const {\n stateFunction,\n stateMessageType = 'developer',\n stateMessagePosition = 'top',\n } = this.data.stateSettings ?? {};\n\n if (typeof stateFunction !== 'function') return history;\n\n const historyClone = [...history];\n const content = (await stateFunction()) as string;\n const stateMessage: ChatCompletionMessageParam = {\n role: stateMessageType,\n content,\n };\n\n if (stateMessagePosition === 'top') {\n if (history.at(0)?.role === 'system') {\n // insert right after system message\n historyClone.splice(1, 0, stateMessage);\n } else {\n historyClone.unshift(stateMessage);\n }\n } else {\n if (history.at(-1)?.role === 'user') {\n const insertionIndex = Math.max(historyClone.length - 1, 0);\n historyClone.splice(insertionIndex, 0, stateMessage);\n } else {\n historyClone.push(stateMessage);\n }\n }\n\n return historyClone;\n }\n\n @Memoize()\n private get openAiService(): OpenAIRequestService {\n return new OpenAIRequestOtelService(this.thread, this.data);\n }\n\n @Memoize({ tags: memoizeTag })\n private get responseHandler(): AbstractResponseHandler {\n const isStreaming = this.data.streamResponse;\n return responseHandlerFactory({\n thread: this.thread,\n isStreaming,\n });\n }\n\n @BackgroundThreadErrorFilter\n public async runStep(): Promise<void> {\n clear(memoizeTag);\n const abortController = createAbortController({ thread: this.thread });\n try {\n const response = await this.openAiService.makeChatCompletionRequest(\n await this.getHistory(),\n abortController.signal,\n );\n await this.responseHandler.handle(response);\n this.complete();\n } catch (error) {\n if (abortController?.signal.aborted) return this.cancel();\n throw error;\n } finally {\n deleteAbortController({\n thread: this.thread,\n });\n }\n }\n}\n","export const toolsContextWorkerClassId = 'tl_wrk';\n","import type { IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageFunctionToolCall } from 'openai/resources.js';\n\nimport { ErrorFilter } from '../../../decorators/error-filter.ts';\nimport { runChildThread } from '../../../utils/thread-utilities.ts';\nimport { BaseStep } from '../../base/base.ts';\nimport { baseClassIdPrefix } from '../../base/constants.ts';\nimport type { ToolsContextConfig } from '../context/types.ts';\n\nimport { toolsContextWorkerClassId } from './constants.ts';\nimport type { ToolsContextWorkerConfig, ToolsContextParsedArguments } from './types.ts';\n\nexport class ToolsContextWorker extends BaseStep<ToolsContextWorkerConfig> {\n public static readonly class = toolsContextWorkerClassId;\n\n public static async start(\n thread: IThread<ToolsContextConfig>,\n toolCall: ChatCompletionMessageFunctionToolCall,\n ): Promise<void> {\n // parse tool call arguments if they are in string format\n const parsedArguments = JSON.parse(toolCall.function?.arguments) as ToolsContextParsedArguments;\n\n await runChildThread<ToolsContextWorkerConfig, ToolsContextConfig>(thread, {\n id: this.getThreadId(toolCall),\n state: {\n step: thread.step.id,\n class: this.class,\n },\n local: {\n toolCall,\n parsedArguments,\n\n // TODO: figure out how to remove these params without breaking typing\n parent: thread.id,\n active: true,\n },\n });\n }\n\n public static getThreadId(toolCall: ChatCompletionMessageFunctionToolCall): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${toolCall.id}`;\n }\n\n // -----------------------------------------------------------------------------------\n\n /**\n * Initializes the tool worker thread to handle processing of repackaged content chunks.\n */\n @ErrorFilter\n public runStep(): void {\n const { toolCall, parsedArguments } = this.local;\n\n this.log.DEBUG?.('Initializing tool worker thread', toolCall);\n this.exitStep(this.getExitName(/*toolCall*/), {\n function: {\n name: toolCall.function.name,\n arguments: parsedArguments, // use parsed arguments\n },\n });\n }\n\n protected getExitName(/*toolCall: ChatCompletionMessageFunctionToolCall*/): string {\n // TODO: add support for exits based on individual functions\n return 'function';\n }\n}\n","export const toolsContextClassId = 'tl_ctrl';\n\nexport const toolContextEvents = {\n callTool: 'tl_run_call',\n lastToolCallReceived: 'tl_rsp_end',\n} as const;\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { IActionEvent, IStepId, IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageFunctionToolCall, ChatCompletionToolMessageParam } from 'openai/resources.js';\n\nimport { BackgroundThreadErrorFilter } from '../../../decorators/background-thread-error-filter.ts';\nimport { errorFilter } from '../../../errors/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../../errors/step-error.ts';\nimport { runChildThread } from '../../../utils/thread-utilities.ts';\nimport { BaseStep } from '../../base/base.ts';\nimport { baseClassIdPrefix } from '../../base/constants.ts';\nimport type { ContentContextConfig } from '../../content/types.ts';\nimport { ToolsContextWorker } from '../worker/tools-context-worker.ts';\nimport type { ToolsContextWorkerConfig } from '../worker/types.ts';\n\nimport { toolContextEvents, toolsContextClassId } from './constants.ts';\nimport type {\n ToolsContextConfig,\n ToolContextEventName,\n CallToolParameters,\n ToolsContextEventCallTool,\n} from './types.ts';\n\nexport class ToolsContext extends BaseStep<ToolsContextConfig> {\n public static readonly class = toolsContextClassId;\n\n public static async start<T extends ContentContextConfig>(thread: IThread<T>): Promise<void> {\n const threadId = this.getThreadId(thread.step.id);\n await runChildThread<ToolsContextConfig, T>(thread, {\n id: threadId,\n state: {\n step: thread.step.id,\n class: this.class,\n\n /** tool calls from LLM response */\n tasks: {},\n\n /** flag to indicate if there are more tasks to process */\n expectMoreTasks: true,\n },\n background: true,\n });\n }\n\n public static async callTool<T extends ContentContextConfig>(\n thread: IThread<T>,\n toolCall: ChatCompletionMessageFunctionToolCall,\n ): Promise<void> {\n await thread.process.enqueueAndRun<ToolContextEventName['callTool'], CallToolParameters>({\n thread: this.getThreadId(thread.step.id),\n name: toolContextEvents.callTool,\n params: { toolCall },\n });\n }\n\n /**\n * Notify tools context thread that no more tool calls are expected\n */\n public static async lastToolCallReceived<T extends ContentContextConfig>(thread: IThread<T>): Promise<void> {\n await thread.process.enqueueAndRun<ToolContextEventName['lastToolCallReceived']>({\n thread: this.getThreadId(thread.step.id),\n name: toolContextEvents.lastToolCallReceived,\n });\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ---------------------------------------\n\n @BackgroundThreadErrorFilter\n public runStep(): void {\n this.triggers\n .local(toolContextEvents.callTool, this.onCallTool)\n .local(toolContextEvents.lastToolCallReceived, this.onLastToolCallReceived)\n .otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n public initialize(): void {\n this.log.DEBUG?.(`Initializing ${ToolsContext.name} thread`);\n }\n\n @BackgroundThreadErrorFilter\n public onCallTool(event: ToolsContextEventCallTool): void {\n const { toolCall } = event.params;\n\n // TODO: support other tool types\n if (toolCall.type !== 'function') {\n throw new CreateChatCompletionStepError('Only function tools are supported at the moment', {\n code: ErrorCode.UNSUPPORTED,\n });\n }\n\n this.state.tasks[toolCall.id] = {\n call: toolCall,\n status: 'pending',\n };\n\n this.startToolWorkerThread(toolCall);\n }\n\n @BackgroundThreadErrorFilter\n public onLastToolCallReceived(): void {\n this.log.DEBUG?.('No more tool calls expected', this.state.tasks);\n this.state.expectMoreTasks = false; // set flag to indicate no more tasks expected\n this.tryEndToolsContextThread();\n }\n\n @BackgroundThreadErrorFilter\n public onWorkerThreadEnd(event: IActionEvent<ToolsContextWorkerConfig, ACTION.end>): void {\n this.log.DEBUG?.('Tool caller worker thread has ended', event);\n\n const { result } = event.params.thread;\n\n if (result == undefined) {\n throw new CreateChatCompletionStepError(`${ToolsContextWorker.name} thread ended unexpectedly`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${ToolsContextWorker.name} thread ended with an error`,\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n\n // if thread was cancelled do nothing\n if (result.status === 'cancel') return;\n\n // TODO: validate structure of the result (zod?)\n this.log.DEBUG?.(`Tool worker thread completed successfully`, {\n toolCallId: result.toolCallId,\n result: result.data,\n });\n this.setToolCallResult(result.toolCallId, result.data);\n\n this.tryEndToolsContextThread();\n }\n\n /**\n * Starts the tool worker thread to process the tool call.\n */\n protected startToolWorkerThread(toolCall: ChatCompletionMessageFunctionToolCall): void {\n this.triggers.hook<ToolsContextWorkerConfig, ACTION.end>(\n { name: ACTION.end, thread: ToolsContextWorker.getThreadId(toolCall) },\n this.onWorkerThreadEnd,\n );\n\n void ToolsContextWorker.start(this.thread, toolCall);\n }\n\n protected setToolCallResult(toolCallId: string, result: unknown): void {\n const toolCall = this.state.tasks[toolCallId];\n\n if (toolCall == undefined) {\n throw new CreateChatCompletionStepError(`Unknown tool call with id '${toolCallId}'`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n toolCall.status = 'completed';\n toolCall.result = result;\n }\n\n protected tryEndToolsContextThread(): void {\n if (this.state.expectMoreTasks) return;\n\n // TODO: handle errored out tool calls\n\n // check if all tool calls are completed\n const hasActiveTasks = Object.values(this.state.tasks).some((task) => task.status === 'pending');\n if (hasActiveTasks) return;\n\n this.log.DEBUG?.('All tool calls completed or failed', this.state.tasks);\n this.end({\n status: 'ok',\n messages: this.messages,\n });\n }\n\n protected get messages(): ChatCompletionToolMessageParam[] {\n return Object.values(this.state.tasks).map((task) => ({\n role: 'tool',\n tool_call_id: task.call.id,\n content: JSON.stringify(task.result),\n }));\n }\n}\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { IActionEvent, STATE } from '@onereach/flow-sdk/types/index.js';\nimport { setImmediate } from 'node:timers/promises';\nimport type { ChatCompletionMessageFunctionToolCall } from 'openai/resources.js';\nimport { clear, Memoize } from 'typescript-memoize';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { errorFilter } from '../../errors/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../errors/step-error.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { RequestContext } from '../request/request-context.ts';\nimport type { RequestContextConfig } from '../request/types.ts';\nimport { ToolsContext } from '../tools/context/tools-context.ts';\nimport type { ToolsContextConfig } from '../tools/context/types.ts';\n\nimport { contentContextEvents } from './constants.ts';\nimport type { ContentContextConfig, ContentContextHandleContentEvent, ContentContextResult } from './types.ts';\n\nconst memoizeTag = ['toolsInit'];\n\nexport abstract class AbstractContentContext<T extends ContentContextConfig> extends BaseStep<T> {\n public static get class(): string {\n throw new Error('Define \"class\" static field');\n }\n\n public static getInitialState<T extends ContentContextConfig>(): STATE<T> {\n throw new Error('Define \"getInitialState\" static method');\n }\n\n // ----------------------------------------------\n\n @BackgroundThreadErrorFilter\n public runStep(): void | Promise<void> {\n // reset init of tools thread on a fresh start\n clear(memoizeTag);\n\n // TODO: add hook for end of ToolsContext thread\n this.triggers\n .local(contentContextEvents.handleContent, this.onHandleContent)\n .hook<RequestContextConfig, ACTION.end>(\n { name: ACTION.end, thread: RequestContext.getThreadId(this.thread.step.id) },\n this.onRequestContextEnd,\n )\n .otherwise(this.initialize);\n }\n\n @BackgroundThreadErrorFilter\n public initialize() {\n this.log.DEBUG?.(`Initializing ${this.constructor.name} thread`);\n\n void RequestContext.start(this.thread);\n }\n\n public abstract onHandleContent(event: ContentContextHandleContentEvent): void | Promise<void>;\n protected abstract onAllContentReceived(): void | Promise<void>;\n protected abstract tryToComplete(): void | Promise<void>;\n\n @BackgroundThreadErrorFilter\n public async onRequestContextEnd(event: IActionEvent<RequestContextConfig, ACTION.end>): Promise<void> {\n const { result } = event.params.thread;\n this.log.DEBUG?.(`${RequestContext.name} thread ended with result`, result);\n\n if (result == undefined) {\n throw new CreateChatCompletionStepError(`${RequestContext.name} thread ended unexpectedly`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${RequestContext.name} thread ended with an error`,\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n\n // TODO: figure out better way to check for correct structure of the event (zod?)\n\n // do nothing on cancel\n if (result.status === 'cancel') return this.cancel();\n\n if (result.status !== 'ok') {\n throw new CreateChatCompletionStepError(`Unexpected end of the ${RequestContext.name} thread`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n data: event.params.result,\n });\n }\n\n this.state.requestComplete = true;\n await this.onAllContentReceived();\n\n if (this.state.toolsReady != undefined) {\n await setImmediate();\n // notify ToolsContext no more tool calls will be made\n await ToolsContext.lastToolCallReceived(this.thread);\n }\n\n await this.tryToComplete();\n }\n\n @BackgroundThreadErrorFilter\n public async onToolsContextEnd(event: IActionEvent<ToolsContextConfig, ACTION.end>): Promise<void> {\n const { result } = event.params.thread;\n\n this.log.DEBUG?.(`${ToolsContext.name} thread ended`, result);\n\n if (result == undefined) {\n throw new CreateChatCompletionStepError(`${ToolsContext.name} thread ended unexpectedly`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${ToolsContext.name} thread ended with an error`,\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n\n // TODO: validate result with zod schema\n\n // do nothing on cancel\n if (result.status === 'cancel') return;\n\n const { status, messages } = result;\n\n if (status !== 'ok' || !Array.isArray(messages)) {\n throw new CreateChatCompletionStepError(`Unexpected end of the ${ToolsContext.name} thread`, {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n data: event.params.result,\n });\n }\n\n this.state.toolsResults = messages;\n this.state.toolsReady = true;\n\n await this.tryToComplete();\n }\n\n protected async callFunction(toolCall: ChatCompletionMessageFunctionToolCall) {\n // wait for ToolController needed\n this.state.toolsReady = false;\n await this.initToolsContextThread();\n await ToolsContext.callTool(this.thread, toolCall);\n }\n\n protected handleMultipleChoices(): void {\n const { chatCompletion } = this.state;\n\n const choices = chatCompletion?.choices ?? [];\n if (choices?.length > 1) {\n this.log.WARN?.('Multiple choices received from LLM, but only the first one will be processed', {\n choices: choices.length,\n });\n }\n }\n\n @Memoize({ tags: memoizeTag })\n protected async initToolsContextThread() {\n // wait for the end of ToolsContext thread\n this.triggers.hook<ToolsContextConfig, ACTION.end>(\n { name: ACTION.end, thread: ToolsContext.getThreadId(this.thread.step.id) },\n this.onToolsContextEnd,\n );\n\n await ToolsContext.start(this.thread);\n }\n\n protected cancel(): void {\n this.end({ status: 'cancel' } as ContentContextResult);\n }\n\n protected complete() {\n const { chatCompletion } = this.state;\n\n // TODO: add validation for ChatCompletion structure\n if (chatCompletion == undefined) {\n throw new CreateChatCompletionStepError('Missing chat completion content to return value', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n this.end({\n status: 'ok',\n chatCompletion,\n toolsResults: this.state.toolsResults ?? [],\n } as ContentContextResult);\n }\n}\n","export const simpleContentContextClassId = 'cnt_cxt_smp';\n","import type { STATE } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletionMessageFunctionToolCall } from 'openai/resources';\n\nimport { BackgroundThreadErrorFilter } from '../../../decorators/background-thread-error-filter.ts';\nimport { AbstractContentContext } from '../abstract-content-context.ts';\n\nimport { simpleContentContextClassId } from './constants.ts';\nimport type { SimpleContentContextConfig, SimpleContentContextHandleContentEvent } from './types.ts';\n\nexport class SimpleContentContext extends AbstractContentContext<SimpleContentContextConfig> {\n public static readonly class = simpleContentContextClassId;\n\n public static getInitialState(): STATE<SimpleContentContextConfig> {\n return {\n class: this.class,\n\n requestComplete: false,\n };\n }\n\n // ----------------------------------------------\n\n @BackgroundThreadErrorFilter\n public async onHandleContent(event: SimpleContentContextHandleContentEvent) {\n const { content } = event.params;\n\n this.state.chatCompletion = content;\n\n // Process tool calls if any\n const toolCalls = content.choices[0]?.message.tool_calls;\n if (toolCalls != undefined) {\n for (const toolCall of toolCalls) {\n // TODO: throw an error if tool call is not a function\n await this.callFunction(toolCall as ChatCompletionMessageFunctionToolCall);\n }\n }\n }\n\n @BackgroundThreadErrorFilter\n public onAllContentReceived() {\n this.handleMultipleChoices();\n }\n\n protected tryToComplete() {\n const { requestComplete, toolsReady } = this.state;\n\n // need to wait for request and tools to finish processing\n if (!requestComplete || toolsReady === false) return;\n\n this.complete();\n }\n}\n","export type ExtractTtsPhrasesOptions = {\n /** Hard ceiling for a single emitted phrase. */\n maxLength: number;\n /** Minimum characters before a boundary is eligible to flush. */\n minLength: number;\n};\n\nexport type ExtractTtsPhrasesResult = {\n phrases: string[];\n remainder: string;\n};\n\n/** Common abbreviations that should not end a sentence on `.`. */\nconst ABBREVIATIONS = new Set([\n 'mr',\n 'mrs',\n 'ms',\n 'dr',\n 'prof',\n 'sr',\n 'jr',\n 'vs',\n 'etc',\n 'eg',\n 'ie',\n 'us',\n 'uk',\n 'st',\n 'approx',\n 'dept',\n 'est',\n]);\n\n/** Sentence-ending punctuation, optional closing quotes/brackets, then space or end. */\nconst STRONG_BOUNDARY = /[.!?][\"')\\]]*(?=\\s|$)/g;\n\n/** Clause / line breaks suitable for TTS pauses. */\nconst SOFT_BOUNDARY = /[;:\\u{2014}\\u{2013}][\"')\\]]*(?=\\s|$)|(?:\\r?\\n)/gu;\n\n/** Comma breaks — only used once the buffer is already reasonably long. */\nconst WEAK_BOUNDARY = /,[\"')\\]]*(?=\\s|$)/g;\n\n/**\n * Extracts complete TTS-friendly phrases from a streaming text buffer.\n * Incomplete text stays in `remainder` until a boundary, max-length force-split, or flush.\n */\nexport function extractTtsPhrases(buffer: string, options: ExtractTtsPhrasesOptions): ExtractTtsPhrasesResult {\n const { maxLength, minLength } = options;\n if (maxLength < 1) {\n throw new Error('maxLength must be >= 1');\n }\n\n const effectiveMinLength = Math.max(1, Math.min(minLength, maxLength));\n const weakMinLength = Math.min(maxLength, Math.max(effectiveMinLength * 2, effectiveMinLength));\n\n const phrases: string[] = [];\n let start = 0;\n\n while (start < buffer.length) {\n const slice = buffer.slice(start);\n\n const strongCut = findFirstBoundary(slice, STRONG_BOUNDARY, effectiveMinLength, isValidSentenceEnd);\n if (strongCut != undefined) {\n phrases.push(slice.slice(0, strongCut));\n start += strongCut;\n continue;\n }\n\n const softCut = findFirstBoundary(slice, SOFT_BOUNDARY, effectiveMinLength);\n if (softCut != undefined) {\n phrases.push(slice.slice(0, softCut));\n start += softCut;\n continue;\n }\n\n const weakCut = findFirstBoundary(slice, WEAK_BOUNDARY, weakMinLength);\n if (weakCut != undefined) {\n phrases.push(slice.slice(0, weakCut));\n start += weakCut;\n continue;\n }\n\n if (slice.length >= maxLength) {\n const afterWhitespace = lastWhitespaceBefore(slice, maxLength);\n // Keep the separating whitespace with the remainder so joining chunks preserves text.\n let cut = afterWhitespace ?? maxLength;\n if (afterWhitespace != undefined) {\n while (cut > 0 && /\\s/.test(slice[cut - 1]!)) {\n cut -= 1;\n }\n }\n if (cut < 1) {\n cut = maxLength;\n }\n phrases.push(slice.slice(0, cut));\n start += cut;\n continue;\n }\n\n break;\n }\n\n return {\n phrases: phrases.filter((phrase) => phrase.length > 0),\n remainder: buffer.slice(start),\n };\n}\n\n/**\n * Returns the index after the last whitespace at or before `maxLength`,\n * or `undefined` if there is no whitespace in that window.\n */\nexport function lastWhitespaceBefore(text: string, maxLength: number): number | undefined {\n const limit = Math.min(text.length, maxLength);\n for (let index = limit - 1; index >= 1; index -= 1) {\n if (/\\s/.test(text[index]!)) {\n return index + 1;\n }\n }\n return undefined;\n}\n\nfunction findFirstBoundary(\n slice: string,\n pattern: RegExp,\n minCut: number,\n isValid?: (match: RegExpExecArray, slice: string) => boolean,\n): number | undefined {\n const regex = new RegExp(pattern.source, pattern.flags);\n let match: RegExpExecArray | null;\n while ((match = regex.exec(slice)) != undefined) {\n const cut = match.index + match[0].length;\n if (cut < minCut) continue;\n if (isValid != undefined && !isValid(match, slice)) continue;\n return cut;\n }\n return undefined;\n}\n\nfunction isValidSentenceEnd(match: RegExpExecArray, slice: string): boolean {\n const punctuation = match[0]?.at(0);\n if (punctuation !== '.') return true;\n\n const before = slice[match.index - 1];\n const afterPeriod = slice[match.index + 1];\n if (before != undefined && /\\d/.test(before) && afterPeriod != undefined && /\\d/.test(afterPeriod)) {\n return false;\n }\n\n const prefix = slice.slice(0, match.index);\n const tokenMatch = prefix.match(/((?:[A-Za-z]\\.)+[A-Za-z]|[A-Za-z]+)$/);\n if (tokenMatch == undefined) return true;\n\n const token = tokenMatch[1]!.toLowerCase().replaceAll('.', '');\n if (ABBREVIATIONS.has(token)) return false;\n\n // Single-letter initials (e.g. \"U.S.\", \"A.\") are treated as abbreviations.\n if (/^[A-Za-z]$/.test(tokenMatch[1]!)) return false;\n\n return true;\n}\n","/* eslint-disable unicorn/max-nested-calls */\nimport type { ChatCompletionChunk } from 'openai/resources';\nimport * as z from 'zod/mini';\n\n// eslint-disable-next-line unicorn/no-top-level-side-effects\nz.config(z.locales.en());\n\nexport const streamChunkEventSchema = z.looseObject({\n name: z.string(),\n params: z.looseObject({\n content: z.looseObject({\n id: z.string(),\n object: z.literal('chat.completion.chunk'),\n created: z.number(),\n model: z.string(),\n service_tier: z.nullish(z.enum(['default', 'auto', 'flex', 'scale', 'priority'])),\n choices: z.array(\n z.looseObject({\n index: z.number().check(z.int(), z.gte(0)),\n delta: z.looseObject({\n role: z.optional(z.enum(['developer', 'system', 'user', 'assistant', 'tool'])),\n content: z.nullish(z.string()),\n refusal: z.nullish(z.string()),\n tool_calls: z.optional(\n z.array(\n z.looseObject({\n index: z.number().check(z.int(), z.gte(0)),\n id: z.optional(z.string()),\n type: z.optional(z.literal('function')),\n function: z.looseObject({\n name: z.optional(z.string()),\n arguments: z.optional(z.string()),\n }),\n }) satisfies z.core.$ZodType<ChatCompletionChunk.Choice.Delta.ToolCall>,\n ),\n ),\n }),\n logprobs: z.nullish(z.any()), // logprobs may be null or omitted\n finish_reason: z.nullable(z.enum(['stop', 'length', 'tool_calls', 'content_filter'])),\n }),\n ),\n\n logprobs: z.nullish(\n z.looseObject({\n content: z.nullable(z.array(z.looseObject({}))),\n refusal: z.nullable(z.array(z.looseObject({}))),\n }),\n ),\n\n usage: z.nullish(\n z.looseObject({\n prompt_tokens: z.number(),\n completion_tokens: z.number(),\n total_tokens: z.number(),\n completion_tokens_details: z.optional(\n z.looseObject({\n accepted_prediction_tokens: z.optional(z.number()),\n audio_tokens: z.optional(z.number()),\n reasoning_tokens: z.optional(z.number()),\n rejected_prediction_tokens: z.optional(z.number()),\n }),\n ),\n prompt_tokens_details: z.optional(\n z.looseObject({\n audio_tokens: z.optional(z.number()),\n cached_tokens: z.optional(z.number()),\n }),\n ),\n }),\n ),\n }) satisfies z.core.$ZodType<ChatCompletionChunk>,\n }),\n});\n\nexport type StreamChunkEvent = z.infer<typeof streamChunkEventSchema>;\n","export const streamContentContextWorkerClassId = 'str_wrk';\n\nexport const streamWorkerExits = {\n chunk: 'chunk',\n} as const;\n","import type { IStepId, IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\n\nimport { ErrorFilter } from '../../../../decorators/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../../../errors/step-error.ts';\nimport { isThreadBusy, runChildThread } from '../../../../utils/thread-utilities.ts';\nimport { BaseStep } from '../../../base/base.ts';\nimport { baseClassIdPrefix } from '../../../base/constants.ts';\nimport type { StreamContentContextConfig } from '../context/types.ts';\n\nimport { streamContentContextWorkerClassId, streamWorkerExits } from './constants.ts';\nimport type { StreamContentContextWorkerConfig, ContentChunkEvent } from './types.ts';\n\nexport class StreamContentContextWorker extends BaseStep<StreamContentContextWorkerConfig> {\n public static readonly class = streamContentContextWorkerClassId;\n\n public static async start(thread: IThread<StreamContentContextConfig>, event: ContentChunkEvent): Promise<void> {\n await runChildThread<StreamContentContextWorkerConfig, StreamContentContextConfig>(thread, {\n id: this.getThreadId(thread.step.id),\n state: {\n step: thread.step.id,\n class: this.class,\n\n event,\n },\n });\n }\n\n public static isBusy(thread: IThread<StreamContentContextConfig>): boolean {\n return isThreadBusy<StreamContentContextConfig, StreamContentContextWorkerConfig>(\n thread,\n this.getThreadId(thread.step.id),\n );\n }\n\n public static getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.class}_${stepId}`;\n }\n\n // ----------------------------------------------\n\n @ErrorFilter\n public runStep(): void {\n if ('event' in this.state === false || this.state.event == undefined) {\n throw new CreateChatCompletionStepError('Stream worker thread state must contain an event to process', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n const chunk = this.state.event;\n this.log.DEBUG?.('Executing stream worker thread', chunk);\n this.exitStep(streamWorkerExits.chunk, { chunk });\n }\n}\n","export const streamContentContextClassId = 'cnt_cxt_str';\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { IActionEvent, STATE } from '@onereach/flow-sdk/types/index.js';\nimport type { ChatCompletion, ChatCompletionChunk, ChatCompletionMessageFunctionToolCall } from 'openai/resources.js';\nimport { clear, Memoize } from 'typescript-memoize';\n\nimport { BackgroundThreadErrorFilter } from '../../../../decorators/background-thread-error-filter.ts';\nimport { errorFilter } from '../../../../errors/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../../../errors/step-error.ts';\nimport { extractTtsPhrases, lastWhitespaceBefore } from '../../../../utils/extract-tts-phrases.ts';\nimport { OpenAiStreamReducer } from '../../../../utils/openai-stream-reducer.ts';\nimport { AbstractContentContext } from '../../abstract-content-context.ts';\nimport { streamChunkEventSchema } from '../schemas/stream-chunk.ts';\nimport { StreamContentContextWorker } from '../worker/stream-content-context-worker.ts';\nimport type { StreamContentContextWorkerConfig, ContentChunkEvent } from '../worker/types.ts';\n\nimport { streamContentContextClassId } from './constants.ts';\nimport type { StreamContentContextConfig, StreamContentContextHandleContentEvent, ContentEvent } from './types.ts';\n\nconst memoizeTag = ['streamInit'];\n\nexport class StreamContentContext extends AbstractContentContext<StreamContentContextConfig> {\n public static readonly class = streamContentContextClassId;\n\n public static getInitialState(): STATE<StreamContentContextConfig> {\n return {\n class: this.class,\n\n requestComplete: false,\n workerComplete: false,\n\n partialChatCompletion: {},\n events: [],\n lastChunkReceived: false,\n index: -1,\n holdback: '',\n };\n }\n\n // ---------------------------------------\n\n private onToolCall(toolCall: ChatCompletionMessageFunctionToolCall): void {\n this.log.DEBUG?.('Tool call received', toolCall);\n void this.callFunction(toolCall);\n }\n\n /**\n * Tries to flush the queue of response chunks to the controller thread.\n * If the first event in the queue is not full, it waits for a debounce duration before flushing.\n * If the first event is full, it flushes it immediately.\n */\n private scheduleNextContentEvent(): void {\n this.promoteDebouncedHoldback();\n\n const firstEvent = this.state.events[0];\n\n if (firstEvent == undefined || !this.isEventReady(firstEvent) || 'lastChunkReceived' in firstEvent) return;\n\n this.tryRunWorker();\n }\n\n /**\n * Compacts the content into the controller thread's events queue.\n * Length mode splits by `maxChunkContentLength`.\n * Phrase mode holds text until TTS-friendly punctuation boundaries.\n */\n private addContentToQueue(content: string): void {\n if (this.isPhraseChunkMode) {\n this.addPhraseContentToQueue(content);\n return;\n }\n\n this.addLengthContentToQueue(content);\n }\n\n private addLengthContentToQueue(content: string): void {\n // extend content chunk in the last event to max event size\n const lastEvent: ContentEvent | undefined = this.state.events.at(-1);\n\n if (lastEvent != undefined) {\n if ('lastChunkReceived' in lastEvent) {\n this.log.WARN?.('A new chunk received after the `lastChunkReceived` event. Ignoring it.');\n return;\n }\n\n if (lastEvent.content.length < this.maxChunkContentLength) {\n const mergedChunk = `${lastEvent.content}${content}`;\n lastEvent.content = mergedChunk.slice(0, this.maxChunkContentLength);\n\n content = mergedChunk.slice(this.maxChunkContentLength);\n }\n }\n\n // split chunk into max socket size events\n while (content) {\n this.enqueueChunk(content.slice(0, this.maxChunkContentLength));\n content = content.slice(this.maxChunkContentLength);\n }\n }\n\n private addPhraseContentToQueue(content: string): void {\n const lastEvent: ContentEvent | undefined = this.state.events.at(-1);\n if (lastEvent != undefined && 'lastChunkReceived' in lastEvent) {\n this.log.WARN?.('A new chunk received after the `lastChunkReceived` event. Ignoring it.');\n return;\n }\n\n this.promoteDebouncedHoldback();\n\n this.state.holdback = `${this.state.holdback}${content}`;\n this.state.holdbackTs ??= Date.now();\n\n const { phrases, remainder } = extractTtsPhrases(this.state.holdback, {\n maxLength: this.maxChunkContentLength,\n minLength: this.minPhraseLength,\n });\n\n for (const phrase of phrases) {\n this.enqueueChunk(phrase);\n }\n\n this.state.holdback = remainder;\n if (!remainder) this.state.holdbackTs = undefined;\n }\n\n /**\n * Promotes aged holdback text into the event queue when debounce has elapsed.\n */\n private promoteDebouncedHoldback(): void {\n if (!this.isPhraseChunkMode) return;\n if (!this.state.holdback || this.state.holdbackTs == undefined) return;\n if (Date.now() - this.state.holdbackTs < this.debounceDuration) return;\n\n this.flushHoldback();\n }\n\n /**\n * Flushes any remaining holdback into the queue (end of stream or debounce).\n * Still respects max length, preferring whitespace cuts.\n */\n private flushHoldback(): void {\n let content = this.state.holdback;\n if (!content) return;\n\n this.state.holdback = '';\n this.state.holdbackTs = undefined;\n\n // Prefer phrase boundaries even on force flush; allow short final phrases.\n const { phrases, remainder } = extractTtsPhrases(content, {\n maxLength: this.maxChunkContentLength,\n minLength: 1,\n });\n\n for (const phrase of phrases) {\n this.enqueueChunk(phrase);\n }\n\n content = remainder;\n while (content) {\n let cut =\n content.length > this.maxChunkContentLength\n ? (lastWhitespaceBefore(content, this.maxChunkContentLength) ?? this.maxChunkContentLength)\n : content.length;\n if (cut < content.length) {\n // Keep separating whitespace with the remainder.\n let trimmedCut = cut;\n while (trimmedCut > 0 && /\\s/.test(content[trimmedCut - 1]!)) {\n trimmedCut -= 1;\n }\n if (trimmedCut >= 1) cut = trimmedCut;\n }\n this.enqueueChunk(content.slice(0, cut));\n content = content.slice(cut);\n }\n }\n\n private enqueueChunk(content: string): void {\n if (!content) return;\n\n this.state.index += 1;\n\n const event: ContentChunkEvent = {\n content,\n index: this.state.index,\n ts: Date.now(),\n };\n this.log.DEBUG?.('Add new event into the queue', event);\n this.state.events.push(event);\n }\n\n /**\n * Processes the next event in the controller thread's queue.\n * If the worker thread is busy, it skips processing.\n * If the event is the termination marker, it notifies the end of the controller thread.\n * If the event is ready for processing, it starts the worker thread to handle it.\n */\n private tryRunWorker(): void {\n this.promoteDebouncedHoldback();\n\n // skip if worker thread is busy\n if (StreamContentContextWorker.isBusy(this.thread)) {\n this.log.DEBUG?.('Skip event processing. Worker thread is busy');\n return;\n }\n\n const event: ContentEvent | undefined = this.getEventToProcess();\n\n if (event == undefined) return;\n\n if ('lastChunkReceived' in event) {\n // if last chunk received, stop ContentContext thread with aggregated response\n this.log.DEBUG?.(\n `Stopping ${StreamContentContext.name} thread. All response content chunks were processed and no new chunks are coming`,\n );\n\n this.state.workerComplete = true;\n\n this.tryToComplete();\n return;\n }\n\n this.log.DEBUG?.('Notify stream worker thread about response chunk to process', event);\n\n void StreamContentContextWorker.start(this.thread, event);\n }\n\n private isEventReady(event: ContentEvent): boolean {\n if (event == undefined) return false;\n if ('lastChunkReceived' in event) return true;\n if (event.content == undefined) return false; // TODO: is it even possible? add test for this use-case\n\n // Phrase-mode events are sealed when enqueued — flush immediately.\n if (this.isPhraseChunkMode) return true;\n\n const eventDelay = Date.now() - event.ts;\n return (\n this.state.lastChunkReceived ||\n eventDelay >= this.debounceDuration ||\n event.content.length >= this.maxChunkContentLength\n );\n }\n\n private getEventToProcess(): ContentEvent | undefined {\n const firstEvent = this.state.events[0];\n\n if (firstEvent == undefined) return undefined;\n if (!this.isEventReady(firstEvent)) return undefined;\n if ('lastChunkReceived' in firstEvent) return firstEvent;\n\n this.state.events.shift();\n return firstEvent;\n }\n\n protected tryToComplete(): void {\n const { chatCompletion, toolsReady, requestComplete, workerComplete } = this.state;\n if (!workerComplete || !requestComplete || toolsReady === false || chatCompletion == undefined) return;\n\n const completionMessage = chatCompletion.choices?.[0]?.message;\n if (completionMessage == undefined) {\n throw new CreateChatCompletionStepError('Missing completion message in chat completion result', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n this.complete();\n }\n\n /**\n * Handles the notification that all response chunks were received from the OpenAI API.\n */\n @BackgroundThreadErrorFilter\n protected onAllContentReceived(): void {\n this.log.DEBUG?.('All LLM response chunks were received. No more response chunks expected');\n\n // TODO: maybe validate that completionResult is correct?\n this.state.chatCompletion = this.state.partialChatCompletion as ChatCompletion;\n\n this.handleMultipleChoices();\n\n // flush any incomplete phrase holdback before the end marker\n this.flushHoldback();\n\n // mark chunk as last in the stream, so it worker thread will have it in its data out\n if (this.state.events.length > 0) {\n const lastEvent = this.state.events.at(-1)! as ContentChunkEvent;\n lastEvent.last = true;\n }\n\n // add fake event as marker for end of stream\n // in rare cases when processing of last chunk already started and we need to mark that all chunks were processed\n this.state.events.push({ lastChunkReceived: true });\n\n // mark last chunk was received in stream content context thread state\n this.state.lastChunkReceived = true;\n\n // force processing of the top chunk in the content queue\n this.tryRunWorker();\n }\n\n @Memoize({ tags: memoizeTag })\n protected get maxChunkContentLength(): number {\n return this.data.streamSettings?.maxBufferLength ?? 100;\n }\n\n @Memoize({ tags: memoizeTag })\n protected get debounceDuration(): number {\n return this.data.streamSettings?.debounceDuration ?? 200;\n }\n\n @Memoize({ tags: memoizeTag })\n protected get isPhraseChunkMode(): boolean {\n return this.data.streamSettings?.chunkMode === 'phrase';\n }\n\n @Memoize({ tags: memoizeTag })\n protected get minPhraseLength(): number {\n return this.data.streamSettings?.minPhraseLength ?? 20;\n }\n\n @BackgroundThreadErrorFilter\n public async runStep(): Promise<void> {\n await super.runStep();\n\n clear(memoizeTag);\n\n this.triggers.hook<StreamContentContextWorkerConfig, ACTION.end>(\n { name: ACTION.end, thread: StreamContentContextWorker.getThreadId(this.thread.step.id) },\n this.onWorkerThreadEnd,\n );\n }\n\n /**\n * Handler of the worker thread end event.\n */\n @BackgroundThreadErrorFilter\n public onWorkerThreadEnd(event: IActionEvent<StreamContentContextWorkerConfig, ACTION.end>): void {\n const { result } = event.params.thread;\n\n this.log.DEBUG?.(`${StreamContentContextWorker.name} thread finished processing chunk`, result);\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${StreamContentContextWorker.name} thread ended with an error`,\n });\n throw resultError;\n }\n\n if (result?.status === 'cancel') return;\n\n // check if there are more tool calls or content chunks to process\n this.tryRunWorker();\n }\n\n /**\n * Handles a single chunk of the streaming response from the OpenAI API.\n */\n @BackgroundThreadErrorFilter\n public onHandleContent(event: StreamContentContextHandleContentEvent): void {\n const parsedEvent = streamChunkEventSchema.parse(event);\n const chunk = parsedEvent.params.content satisfies ChatCompletionChunk;\n\n const streamReducer = new OpenAiStreamReducer(this.state.partialChatCompletion, this.onToolCall.bind(this));\n streamReducer.reduceChunk(chunk);\n\n for (const chunkChoice of chunk.choices) {\n // this.log.DEBUG?.('LLM stream response chunk', chunkChoice);\n\n // skip streaming additional choices (if n > 1)\n if (chunkChoice.index > 0) continue;\n\n // aggregate content\n const content = chunkChoice.delta?.content;\n if (content != undefined && content.length > 0) {\n this.addContentToQueue(content);\n this.scheduleNextContentEvent();\n }\n }\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\nexport async function validateFlowSdkVersion(minVersion: string): Promise<void> {\n if (typeof minVersion !== 'string' || !/^\\d+\\.\\d+\\.\\d+$/.test(minVersion)) {\n throw new Error(`Invalid minimum version format: ${minVersion}`);\n }\n\n const packageJsonPath = require.resolve('@onereach/flow-sdk/package.json');\n if (!packageJsonPath) {\n throw new Error(`Could not find package.json for @onereach/flow-sdk`);\n }\n // Read the package.json file to get the version\n const packageJsonContent = await readFile(packageJsonPath, 'utf8');\n\n const { version } = JSON.parse(packageJsonContent) as { version: string };\n const { groups } = /^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)/.exec(version) || {};\n\n if (!groups) throw new Error(`Invalid Flow SDK version format: ${version}`);\n\n const major = Math.trunc(Number(groups.major ?? '0'));\n const minor = Math.trunc(Number(groups.minor ?? '0'));\n const patch = Math.trunc(Number(groups.patch ?? '0'));\n\n if (\n major == undefined ||\n minor == undefined ||\n patch == undefined ||\n Number.isNaN(major) ||\n Number.isNaN(minor) ||\n Number.isNaN(patch)\n ) {\n throw new Error(`Invalid version format: ${version}`);\n }\n\n const [minMajor, minMinor, minPatch] = minVersion.split('.').map((x) => Math.trunc(Number(x)));\n\n if (\n minMajor == undefined ||\n minMinor == undefined ||\n minPatch == undefined ||\n Number.isNaN(minMajor) ||\n Number.isNaN(minMinor) ||\n Number.isNaN(minPatch)\n ) {\n throw new Error(`Invalid minimum version format: ${minVersion}`);\n }\n\n if (\n major < minMajor ||\n (major === minMajor && minor < minMinor) ||\n (major === minMajor && minor === minMinor && patch < minPatch)\n ) {\n throw new Error(\n `Flow SDK version '${version}' is lower than required minimum version '${minVersion}' for the step`,\n );\n }\n}\n","import type { IStepId, IThread, IThreadId } from '@onereach/flow-sdk/types/index.js';\nimport { Memoize } from 'typescript-memoize';\n\nimport { runChildThread, stopThread } from '../../utils/thread-utilities.ts';\nimport { baseClassIdPrefix } from '../base/constants.ts';\nimport type { ChatCompletionConfig } from '../main/types.ts';\n\nimport { SimpleContentContext } from './simple/simple-content-context.ts';\nimport { StreamContentContext } from './stream/context/stream-content-context.ts';\nimport type { ContentContextConfig } from './types.ts';\n\nexport class ContentContextUtilities {\n private Constructor: ContentContextConstructor;\n\n private constructor(Constructor: ContentContextConstructor) {\n this.Constructor = Constructor;\n }\n\n @Memoize()\n static factory(isStreaming: boolean): ContentContextUtilities {\n const Constructor: ContentContextConstructor = isStreaming ? StreamContentContext : SimpleContentContext;\n return new ContentContextUtilities(Constructor);\n }\n\n public async start(thread: IThread<ChatCompletionConfig>): Promise<void> {\n const initialState = this.Constructor.getInitialState();\n await runChildThread<ContentContextConfig, ChatCompletionConfig>(thread, {\n id: this.getThreadId(thread.step.id),\n state: {\n ...initialState,\n requestComplete: false,\n step: thread.step.id,\n class: this.Constructor.class,\n },\n background: true,\n });\n }\n\n public async cancel(thread: IThread<ChatCompletionConfig>): Promise<void> {\n await stopThread<ContentContextConfig, ChatCompletionConfig>(thread, this.getThreadId(thread.step.id), {\n result: { status: 'cancel' },\n stopChildThreads: true,\n });\n }\n\n public getThreadId(stepId: IStepId): IThreadId {\n return `${baseClassIdPrefix}_${this.Constructor.class}_${stepId}`;\n }\n}\n\nexport type ContentContextConstructor = typeof SimpleContentContext | typeof StreamContentContext;\n","/* eslint-disable @typescript-eslint/unbound-method */\n\nimport { ACTION } from '@onereach/flow-sdk/types/index.js';\nimport type { IActionEvent } from '@onereach/flow-sdk/types/index.js';\n\nimport { BackgroundThreadErrorFilter } from '../../decorators/background-thread-error-filter.ts';\nimport { ErrorFilter } from '../../decorators/error-filter.ts';\nimport { errorFilter } from '../../errors/error-filter.ts';\nimport { CreateChatCompletionStepError, ErrorCode } from '../../errors/step-error.ts';\nimport { endChildThreads } from '../../utils/thread-utilities.ts';\nimport { validateFlowSdkVersion } from '../../utils/validate-flow-sdk-version.ts';\nimport { BaseStep } from '../base/base.ts';\nimport { CancelContext } from '../cancel/cancel-context.ts';\nimport { parentEvents as stepEvents } from '../cancel/constants.ts';\nimport { ContentContextUtilities } from '../content/content-context-utilities.ts';\nimport type { ContentContextConfig } from '../content/types.ts';\nimport { HistoryContext } from '../history/history-context.ts';\nimport { HistoryContextConfig } from '../history/types.ts';\n\nimport { ChatCompletionConfig } from './types.ts';\n\nconst MINIMAL_FLOW_SDK_VERSION = '8.0.72';\n\nexport class CreateChatCompletionStep extends BaseStep<ChatCompletionConfig> {\n private async tryToExitStep(): Promise<void> {\n const { cancelled, contentReady, chatCompletion, toolsResults } = this.state;\n\n if (cancelled) {\n // TODO: cleanup history with tool responses from it if \"second\" response was cancelled\n this.resetState();\n return;\n }\n\n if (!contentReady) return;\n\n if (chatCompletion == undefined) {\n throw new CreateChatCompletionStepError('Missing chat completion result, but request is marked as processed', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n const completionMessage = chatCompletion.choices?.[0]?.message;\n if (completionMessage == undefined) {\n throw new CreateChatCompletionStepError('Missing completion message in chat completion result', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n await Promise.all([\n // add completion message and possible tool results to history\n HistoryContext.appendToHistory(this.thread, [completionMessage, ...toolsResults]),\n // at this point there's nothing to cancel, so CancelContext thread is not needed anymore\n CancelContext.stop(this.thread),\n ]);\n\n const finishReason = chatCompletion.choices[0]?.finish_reason;\n if (finishReason === 'length') {\n // TODO: allow to proceed with partial data?\n throw new CreateChatCompletionStepError('Reached limit of tokens for LLM completion response', {\n code: ErrorCode.LLM_FINISH_LENGTH,\n });\n }\n if (finishReason === 'tool_calls') {\n // reset the step and run request again\n this.thread.jumpTo(this.currentStepId);\n return;\n }\n\n // both tools and content are ready, we can exit the step\n this.log.DEBUG?.('Exiting step with collected data', chatCompletion);\n this.exitStep('next', chatCompletion);\n }\n\n /**\n * Reset the step so it can handle new request\n *\n * - Reset state of initial thread (e.g. main) to original state;\n * - End CancelContext thread;\n * - End ContentController (with child thread);\n *\n * @throws if there any issues with stopping threads\n */\n private async resetStep(): Promise<void> {\n this.resetState();\n this.state.cancelled = true;\n\n const resetResults = await Promise.allSettled([\n endChildThreads(this.thread, { status: 'cancel' }),\n HistoryContext.adjustOnCancel(this.thread),\n ]);\n const failedTask = resetResults.find((task) => task.status === 'rejected');\n if (failedTask) throw failedTask.reason;\n }\n\n private resetState(): void {\n this.state.contentReady = false;\n this.state.chatCompletion = undefined;\n this.state.toolsResults = [];\n }\n\n private validateMergeFieldType(): void {\n const { functionsList } = this.data;\n if (!Array.isArray(functionsList) || functionsList.length === 0) return; // no functions used\n\n if (this.dataOut == undefined || this.getMergeField(this.dataOut).type !== 'thread') {\n throw new CreateChatCompletionStepError('Merge-field type has to be \"Thread\" if you are using functions', {\n code: ErrorCode.VALIDATION,\n });\n }\n }\n\n private get contentContext(): ContentContextUtilities {\n const isStreaming = this.data.streamResponse;\n return ContentContextUtilities.factory(isStreaming);\n }\n\n @ErrorFilter\n public runStep(): void {\n this.triggers.hook<ContentContextConfig, ACTION.end>(\n { name: ACTION.end, thread: this.contentContext.getThreadId(this.thread.step.id) },\n this.onContentContextEnd,\n );\n this.triggers.hook<HistoryContextConfig, ACTION.end>(\n { name: ACTION.end, thread: HistoryContext.getThreadId(this.thread.step.id) },\n this.onHistoryContextEnd,\n );\n this.triggers.local(stepEvents.cancel, this.onCancel);\n this.triggers.otherwise(this.initialize);\n }\n\n @ErrorFilter\n public async initialize(): Promise<void> {\n await validateFlowSdkVersion(MINIMAL_FLOW_SDK_VERSION);\n this.validateMergeFieldType();\n\n this.resetState();\n this.state.cancelled = false;\n\n await Promise.all([HistoryContext.start(this.thread), CancelContext.start(this.thread)]);\n\n // prepare messages history for the request\n await HistoryContext.prepareHistory(this.thread);\n\n // starting ContentContext thread will initiate the request to LLM\n await this.contentContext.start(this.thread);\n }\n\n @BackgroundThreadErrorFilter({ allowHandleError: true })\n public async onContentContextEnd(event: IActionEvent<ContentContextConfig, ACTION.end>): Promise<void> {\n try {\n const { result } = event.params.thread;\n this.log.DEBUG?.('ContentContext thread ended with result', result);\n\n if (result == undefined) {\n throw new CreateChatCompletionStepError('ContentContext thread ended unexpectedly', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n });\n }\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: 'ContentContext thread ended with an error',\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n\n if (result.status === 'cancel') {\n await this.resetStep();\n return;\n }\n\n // TODO: figure out better way to check for correct structure of the event (zod?)\n const { status, chatCompletion, toolsResults } = result;\n\n if (status !== 'ok' || chatCompletion == undefined || toolsResults == undefined) {\n throw new CreateChatCompletionStepError('Unexpected end of the ContentContext thread', {\n code: ErrorCode.STEP_LOGIC_ISSUE,\n data: event.params.result,\n });\n }\n\n this.log.DEBUG?.('Create Chat Completion result', chatCompletion);\n\n this.state.contentReady = true;\n this.state.chatCompletion = chatCompletion;\n this.state.toolsResults = toolsResults;\n\n await this.tryToExitStep();\n } catch (error) {\n try {\n await this.resetStep();\n } catch (resetError) {\n this.log.WARN?.('Failed to reset step', resetError);\n }\n throw error;\n }\n }\n\n @BackgroundThreadErrorFilter({ allowHandleError: true })\n public async onHistoryContextEnd(event: IActionEvent<HistoryContextConfig, ACTION.end>): Promise<void> {\n try {\n const { result } = event.params.thread;\n this.log.DEBUG?.(`${HistoryContext.name} thread ended with result`, result);\n\n if (result instanceof Error) {\n const resultError = errorFilter(result, {\n unknownMessage: `${HistoryContext.name} thread ended with an error`,\n unknownCode: ErrorCode.STEP_LOGIC_ISSUE,\n });\n throw resultError;\n }\n } catch (error) {\n try {\n await CancelContext.stop(this.thread);\n } catch (stopError) {\n this.log.WARN?.('Failed to stop CancelContext thread', stopError);\n }\n throw error;\n }\n }\n\n @ErrorFilter\n public async onCancel(): Promise<void> {\n await this.resetStep();\n }\n}\n","import { install } from 'source-map-support';\n\nimport { CancelContext } from './threads/cancel/cancel-context.ts';\nimport { SimpleContentContext } from './threads/content/simple/simple-content-context.ts';\nimport { StreamContentContext } from './threads/content/stream/context/stream-content-context.ts';\nimport { StreamContentContextWorker } from './threads/content/stream/worker/stream-content-context-worker.ts';\nimport { HistoryContext } from './threads/history/history-context.ts';\nimport { RequestContext } from './threads/request/request-context.ts';\nimport { ToolsContext } from './threads/tools/context/tools-context.ts';\nimport { ToolsContextWorker } from './threads/tools/worker/tools-context-worker.ts';\n\n// enable source map support for better error stack traces\n// eslint-disable-next-line unicorn/no-top-level-side-effects\ninstall();\n\nexport const states = {\n [HistoryContext.class]: HistoryContext,\n [RequestContext.class]: RequestContext,\n [ToolsContext.class]: ToolsContext,\n [ToolsContextWorker.class]: ToolsContextWorker,\n [SimpleContentContext.class]: SimpleContentContext,\n [StreamContentContext.class]: StreamContentContext,\n [StreamContentContextWorker.class]: StreamContentContextWorker,\n [CancelContext.class]: CancelContext,\n};\n\nexport { CreateChatCompletionStep as step } from './threads/main/step.ts';\n\nexport type * from './types.ts';\n"],"mappings":"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"}
|