@langchain/core 1.2.9 → 1.2.10
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/CHANGELOG.md +6 -0
- package/dist/_virtual/_rolldown/runtime.cjs +1 -1
- package/dist/callbacks/dispatch/index.cjs +2 -1
- package/dist/callbacks/dispatch/index.cjs.map +1 -1
- package/dist/callbacks/dispatch/index.js +2 -1
- package/dist/callbacks/dispatch/index.js.map +1 -1
- package/dist/indexing/base.cjs +10 -6
- package/dist/indexing/base.cjs.map +1 -1
- package/dist/indexing/base.js +10 -6
- package/dist/indexing/base.js.map +1 -1
- package/dist/language_models/base.cjs +1 -1
- package/dist/language_models/base.cjs.map +1 -1
- package/dist/language_models/base.js +1 -1
- package/dist/language_models/base.js.map +1 -1
- package/dist/language_models/chat_models.cjs +10 -5
- package/dist/language_models/chat_models.cjs.map +1 -1
- package/dist/language_models/chat_models.js +10 -5
- package/dist/language_models/chat_models.js.map +1 -1
- package/dist/language_models/stream.cjs +0 -2
- package/dist/language_models/stream.cjs.map +1 -1
- package/dist/language_models/stream.js +0 -2
- package/dist/language_models/stream.js.map +1 -1
- package/dist/load/index.cjs +7 -5
- package/dist/load/index.cjs.map +1 -1
- package/dist/load/index.js +7 -5
- package/dist/load/index.js.map +1 -1
- package/dist/load/serializable.cjs +2 -1
- package/dist/load/serializable.cjs.map +1 -1
- package/dist/load/serializable.js +2 -1
- package/dist/load/serializable.js.map +1 -1
- package/dist/load/validation.cjs +4 -3
- package/dist/load/validation.cjs.map +1 -1
- package/dist/load/validation.js +4 -3
- package/dist/load/validation.js.map +1 -1
- package/dist/messages/base.cjs +13 -18
- package/dist/messages/base.cjs.map +1 -1
- package/dist/messages/base.d.cts.map +1 -1
- package/dist/messages/base.d.ts.map +1 -1
- package/dist/messages/base.js +13 -18
- package/dist/messages/base.js.map +1 -1
- package/dist/messages/block_translators/anthropic.cjs.map +1 -1
- package/dist/messages/block_translators/anthropic.js.map +1 -1
- package/dist/messages/block_translators/google.cjs +10 -9
- package/dist/messages/block_translators/google.cjs.map +1 -1
- package/dist/messages/block_translators/google.js +10 -9
- package/dist/messages/block_translators/google.js.map +1 -1
- package/dist/messages/block_translators/google_vertexai.cjs +14 -12
- package/dist/messages/block_translators/google_vertexai.cjs.map +1 -1
- package/dist/messages/block_translators/google_vertexai.js +14 -12
- package/dist/messages/block_translators/google_vertexai.js.map +1 -1
- package/dist/messages/message.cjs.map +1 -1
- package/dist/messages/message.d.cts.map +1 -1
- package/dist/messages/message.d.ts.map +1 -1
- package/dist/messages/message.js.map +1 -1
- package/dist/messages/transformers.cjs +12 -8
- package/dist/messages/transformers.cjs.map +1 -1
- package/dist/messages/transformers.js +12 -8
- package/dist/messages/transformers.js.map +1 -1
- package/dist/output_parsers/transform.cjs.map +1 -1
- package/dist/prompts/chat.cjs +2 -1
- package/dist/prompts/chat.cjs.map +1 -1
- package/dist/prompts/chat.js +2 -1
- package/dist/prompts/chat.js.map +1 -1
- package/dist/prompts/few_shot.cjs +6 -4
- package/dist/prompts/few_shot.cjs.map +1 -1
- package/dist/prompts/few_shot.js +6 -4
- package/dist/prompts/few_shot.js.map +1 -1
- package/dist/prompts/image.cjs +2 -1
- package/dist/prompts/image.cjs.map +1 -1
- package/dist/prompts/image.js +2 -1
- package/dist/prompts/image.js.map +1 -1
- package/dist/prompts/prompt.cjs.map +1 -1
- package/dist/prompts/prompt.d.cts.map +1 -1
- package/dist/prompts/prompt.d.ts.map +1 -1
- package/dist/prompts/prompt.js.map +1 -1
- package/dist/prompts/string.cjs +2 -1
- package/dist/prompts/string.cjs.map +1 -1
- package/dist/prompts/string.js +2 -1
- package/dist/prompts/string.js.map +1 -1
- package/dist/prompts/template.cjs.map +1 -1
- package/dist/prompts/template.js.map +1 -1
- package/dist/runnables/base.cjs +60 -40
- package/dist/runnables/base.cjs.map +1 -1
- package/dist/runnables/base.js +60 -40
- package/dist/runnables/base.js.map +1 -1
- package/dist/runnables/branch.cjs +16 -12
- package/dist/runnables/branch.cjs.map +1 -1
- package/dist/runnables/branch.js +16 -12
- package/dist/runnables/branch.js.map +1 -1
- package/dist/runnables/config.cjs +28 -23
- package/dist/runnables/config.cjs.map +1 -1
- package/dist/runnables/config.js +28 -23
- package/dist/runnables/config.js.map +1 -1
- package/dist/runnables/graph.cjs +2 -1
- package/dist/runnables/graph.cjs.map +1 -1
- package/dist/runnables/graph.js +2 -1
- package/dist/runnables/graph.js.map +1 -1
- package/dist/runnables/passthrough.cjs +8 -6
- package/dist/runnables/passthrough.cjs.map +1 -1
- package/dist/runnables/passthrough.js +8 -6
- package/dist/runnables/passthrough.js.map +1 -1
- package/dist/singletons/async_local_storage/context.cjs.map +1 -1
- package/dist/singletons/tracer.cjs +4 -1
- package/dist/singletons/tracer.cjs.map +1 -1
- package/dist/singletons/tracer.js +4 -1
- package/dist/singletons/tracer.js.map +1 -1
- package/dist/tools/index.cjs +22 -20
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.js +22 -20
- package/dist/tools/index.js.map +1 -1
- package/dist/tracers/base.cjs +11 -10
- package/dist/tracers/base.cjs.map +1 -1
- package/dist/tracers/base.js +11 -10
- package/dist/tracers/base.js.map +1 -1
- package/dist/tracers/log_stream.cjs +7 -6
- package/dist/tracers/log_stream.cjs.map +1 -1
- package/dist/tracers/log_stream.js +7 -6
- package/dist/tracers/log_stream.js.map +1 -1
- package/dist/tracers/tracer_langchain.cjs.map +1 -1
- package/dist/utils/env.cjs.map +1 -1
- package/dist/utils/env.d.cts.map +1 -1
- package/dist/utils/env.d.ts.map +1 -1
- package/dist/utils/env.js.map +1 -1
- package/dist/utils/event_source_parse.cjs +1 -3
- package/dist/utils/event_source_parse.cjs.map +1 -1
- package/dist/utils/event_source_parse.js +1 -3
- package/dist/utils/event_source_parse.js.map +1 -1
- package/dist/utils/fast-json-patch/src/core.cjs +4 -2
- package/dist/utils/fast-json-patch/src/core.cjs.map +1 -1
- package/dist/utils/fast-json-patch/src/core.js +4 -2
- package/dist/utils/fast-json-patch/src/core.js.map +1 -1
- package/dist/utils/fast-json-patch/src/helpers.cjs.map +1 -1
- package/dist/utils/fast-json-patch/src/helpers.js.map +1 -1
- package/dist/utils/js-sha256/hash.cjs.map +1 -1
- package/dist/utils/js-sha256/hash.js.map +1 -1
- package/dist/utils/json_schema.cjs +4 -2
- package/dist/utils/json_schema.cjs.map +1 -1
- package/dist/utils/json_schema.js +4 -2
- package/dist/utils/json_schema.js.map +1 -1
- package/dist/utils/sax-js/sax.cjs +41 -35
- package/dist/utils/sax-js/sax.cjs.map +1 -1
- package/dist/utils/sax-js/sax.js +41 -35
- package/dist/utils/sax-js/sax.js.map +1 -1
- package/dist/utils/testing/chat_models.cjs +2 -1
- package/dist/utils/testing/chat_models.cjs.map +1 -1
- package/dist/utils/testing/chat_models.js +2 -1
- package/dist/utils/testing/chat_models.js.map +1 -1
- package/dist/utils/tiktoken.cjs.map +1 -1
- package/dist/utils/types/zod.cjs.map +1 -1
- package/dist/utils/types/zod.js.map +1 -1
- package/dist/utils/zod-to-json-schema/parsers/bigint.cjs +9 -9
- package/dist/utils/zod-to-json-schema/parsers/bigint.cjs.map +1 -1
- package/dist/utils/zod-to-json-schema/parsers/bigint.js +9 -9
- package/dist/utils/zod-to-json-schema/parsers/bigint.js.map +1 -1
- package/dist/utils/zod-to-json-schema/parsers/date.cjs +1 -3
- package/dist/utils/zod-to-json-schema/parsers/date.cjs.map +1 -1
- package/dist/utils/zod-to-json-schema/parsers/date.js +1 -3
- package/dist/utils/zod-to-json-schema/parsers/date.js.map +1 -1
- package/dist/utils/zod-to-json-schema/parsers/number.cjs +9 -9
- package/dist/utils/zod-to-json-schema/parsers/number.cjs.map +1 -1
- package/dist/utils/zod-to-json-schema/parsers/number.js +9 -9
- package/dist/utils/zod-to-json-schema/parsers/number.js.map +1 -1
- package/dist/utils/zod-to-json-schema/parsers/string.cjs +3 -13
- package/dist/utils/zod-to-json-schema/parsers/string.cjs.map +1 -1
- package/dist/utils/zod-to-json-schema/parsers/string.js +3 -13
- package/dist/utils/zod-to-json-schema/parsers/string.js.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log_stream.cjs","names":["applyPatch","BaseTracer","IterableReadableStream","AIMessageChunk"],"sources":["../../src/tracers/log_stream.ts"],"sourcesContent":["import {\n applyPatch,\n type Operation as JSONPatchOperation,\n} from \"../utils/fast-json-patch/index.js\";\nimport { BaseTracer, type Run } from \"./base.js\";\nimport {\n BaseCallbackHandler,\n BaseCallbackHandlerInput,\n CallbackHandlerPrefersStreaming,\n HandleLLMNewTokenCallbackFields,\n} from \"../callbacks/base.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { ChatGenerationChunk, GenerationChunk } from \"../outputs.js\";\nimport { AIMessageChunk } from \"../messages/ai.js\";\nimport type { StreamEvent, StreamEventData } from \"./event_stream.js\";\n\nexport type { StreamEvent, StreamEventData };\n\n/**\n * Interface that represents the structure of a log entry in the\n * `LogStreamCallbackHandler`.\n */\nexport type LogEntry = {\n /** ID of the sub-run. */\n id: string;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n /** List of tags for the run. */\n tags: string[];\n /** Key-value pairs of metadata for the run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n metadata: Record<string, any>;\n /** ISO-8601 timestamp of when the run started. */\n start_time: string;\n /** List of general output chunks streamed by this run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** List of LLM tokens streamed by this run, if applicable. */\n streamed_output_str: string[];\n /** Inputs to this run. Not available currently via streamLog. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n inputs?: any;\n /** Final output of this run. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /** ISO-8601 timestamp of when the run ended. Only available after the run has finished. */\n end_time?: string;\n};\n\nexport type RunState = {\n /** ID of the sub-run. */\n id: string;\n /** List of output chunks streamed by Runnable.stream() */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** Final output of the run, usually the result of aggregating streamed_output. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /**\n * List of sub-runs contained in this run, if any, in the order they were started.\n * If filters were supplied, this list will contain only the runs that matched the filters.\n */\n logs: Record<string, LogEntry>;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n};\n\n/**\n * List of jsonpatch JSONPatchOperations, which describe how to create the run state\n * from an empty dict. This is the minimal representation of the log, designed to\n * be serialized as JSON and sent over the wire to reconstruct the log on the other\n * side. Reconstruction of the state can be done with any jsonpatch-compliant library,\n * see https://jsonpatch.com for more information.\n */\nexport class RunLogPatch {\n ops: JSONPatchOperation[];\n\n constructor(fields: { ops?: JSONPatchOperation[] }) {\n this.ops = fields.ops ?? [];\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch({}, ops);\n // oxlint-disable-next-line @typescript-eslint/no-use-before-define\n return new RunLog({\n ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport class RunLog extends RunLogPatch {\n state: RunState;\n\n constructor(fields: { ops?: JSONPatchOperation[]; state: RunState }) {\n super(fields);\n this.state = fields.state;\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch(this.state, other.ops);\n return new RunLog({ ops, state: states[states.length - 1].newDocument });\n }\n\n static fromRunLogPatch(patch: RunLogPatch) {\n const states = applyPatch({}, patch.ops);\n return new RunLog({\n ops: patch.ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport type SchemaFormat = \"original\" | \"streaming_events\";\n\nexport interface LogStreamCallbackHandlerInput extends BaseCallbackHandlerInput {\n autoClose?: boolean;\n includeNames?: string[];\n includeTypes?: string[];\n includeTags?: string[];\n excludeNames?: string[];\n excludeTypes?: string[];\n excludeTags?: string[];\n _schemaFormat?: SchemaFormat;\n}\n\nexport const isLogStreamHandler = (\n handler: BaseCallbackHandler\n): handler is LogStreamCallbackHandler => handler.name === \"log_stream_tracer\";\n\n/**\n * Extract standardized inputs from a run.\n *\n * Standardizes the inputs based on the type of the runnable used.\n *\n * @param run - Run object\n * @param schemaFormat - The schema format to use.\n *\n * @returns Valid inputs are only dict. By conventions, inputs always represented\n * invocation using named arguments.\n * A null means that the input is not yet known!\n */\nasync function _getStandardizedInputs(run: Run, schemaFormat: SchemaFormat) {\n if (schemaFormat === \"original\") {\n throw new Error(\n \"Do not assign inputs with original schema drop the key for now. \" +\n \"When inputs are added to streamLog they should be added with \" +\n \"standardized schema for streaming events.\"\n );\n }\n\n const { inputs } = run;\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return inputs;\n }\n\n if (Object.keys(inputs).length === 1 && inputs?.input === \"\") {\n return undefined;\n }\n\n // new style chains\n // These nest an additional 'input' key inside the 'inputs' to make sure\n // the input is always a dict. We need to unpack and user the inner value.\n // We should try to fix this in Runnables and callbacks/tracers\n // Runnables should be using a null type here not a placeholder\n // dict.\n return inputs.input;\n}\n\nasync function _getStandardizedOutputs(run: Run, schemaFormat: SchemaFormat) {\n const { outputs } = run;\n if (schemaFormat === \"original\") {\n // Return the old schema, without standardizing anything\n return outputs;\n }\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return outputs;\n }\n\n // TODO: Remove this hacky check\n if (\n outputs !== undefined &&\n Object.keys(outputs).length === 1 &&\n outputs?.output !== undefined\n ) {\n return outputs.output;\n }\n\n return outputs;\n}\n\nfunction isChatGenerationChunk(\n x?: ChatGenerationChunk | GenerationChunk\n): x is ChatGenerationChunk {\n return x !== undefined && (x as ChatGenerationChunk).message !== undefined;\n}\n\n/**\n * Class that extends the `BaseTracer` class from the\n * `langchain.callbacks.tracers.base` module. It represents a callback\n * handler that logs the execution of runs and emits `RunLog` instances to a\n * `RunLogStream`.\n */\nexport class LogStreamCallbackHandler\n extends BaseTracer\n implements CallbackHandlerPrefersStreaming\n{\n protected autoClose = true;\n\n protected includeNames?: string[];\n\n protected includeTypes?: string[];\n\n protected includeTags?: string[];\n\n protected excludeNames?: string[];\n\n protected excludeTypes?: string[];\n\n protected excludeTags?: string[];\n\n protected _schemaFormat: SchemaFormat = \"original\";\n\n protected rootId?: string;\n\n private keyMapByRunId: Record<string, string> = {};\n\n private counterMapByRunName: Record<string, number> = {};\n\n protected transformStream: TransformStream;\n\n public writer: WritableStreamDefaultWriter;\n\n public receiveStream: IterableReadableStream<RunLogPatch>;\n\n name = \"log_stream_tracer\";\n\n lc_prefer_streaming = true;\n\n constructor(fields?: LogStreamCallbackHandlerInput) {\n super({ _awaitHandler: true, ...fields });\n this.autoClose = fields?.autoClose ?? true;\n this.includeNames = fields?.includeNames;\n this.includeTypes = fields?.includeTypes;\n this.includeTags = fields?.includeTags;\n this.excludeNames = fields?.excludeNames;\n this.excludeTypes = fields?.excludeTypes;\n this.excludeTags = fields?.excludeTags;\n this._schemaFormat = fields?._schemaFormat ?? this._schemaFormat;\n this.transformStream = new TransformStream();\n this.writer = this.transformStream.writable.getWriter();\n this.receiveStream = IterableReadableStream.fromReadableStream(\n this.transformStream.readable\n );\n }\n\n [Symbol.asyncIterator]() {\n return this.receiveStream;\n }\n\n protected async persistRun(_run: Run): Promise<void> {\n // This is a legacy method only called once for an entire run tree\n // and is therefore not useful here\n }\n\n _includeRun(run: Run): boolean {\n if (run.id === this.rootId) {\n return false;\n }\n const runTags = run.tags ?? [];\n let include =\n this.includeNames === undefined &&\n this.includeTags === undefined &&\n this.includeTypes === undefined;\n if (this.includeNames !== undefined) {\n include = include || this.includeNames.includes(run.name);\n }\n if (this.includeTypes !== undefined) {\n include = include || this.includeTypes.includes(run.run_type);\n }\n if (this.includeTags !== undefined) {\n include =\n include ||\n runTags.find((tag) => this.includeTags?.includes(tag)) !== undefined;\n }\n if (this.excludeNames !== undefined) {\n include = include && !this.excludeNames.includes(run.name);\n }\n if (this.excludeTypes !== undefined) {\n include = include && !this.excludeTypes.includes(run.run_type);\n }\n if (this.excludeTags !== undefined) {\n include =\n include && runTags.every((tag) => !this.excludeTags?.includes(tag));\n }\n return include;\n }\n\n async *tapOutputIterable<T>(\n runId: string,\n output: AsyncGenerator<T>\n ): AsyncGenerator<T> {\n // Tap an output async iterator to stream its values to the log.\n for await (const chunk of output) {\n // root run is handled in .streamLog()\n if (runId !== this.rootId) {\n // if we can't find the run silently ignore\n // eg. because this run wasn't included in the log\n const key = this.keyMapByRunId[runId];\n if (key) {\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${key}/streamed_output/-`,\n value: chunk,\n },\n ],\n })\n );\n }\n }\n yield chunk;\n }\n }\n\n async onRunCreate(run: Run): Promise<void> {\n if (this.rootId === undefined) {\n this.rootId = run.id;\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"\",\n value: {\n id: run.id,\n name: run.name,\n type: run.run_type,\n streamed_output: [],\n final_output: undefined,\n logs: {},\n },\n },\n ],\n })\n );\n }\n\n if (!this._includeRun(run)) {\n return;\n }\n\n if (this.counterMapByRunName[run.name] === undefined) {\n this.counterMapByRunName[run.name] = 0;\n }\n this.counterMapByRunName[run.name] += 1;\n const count = this.counterMapByRunName[run.name];\n this.keyMapByRunId[run.id] =\n count === 1 ? run.name : `${run.name}:${count}`;\n\n const logEntry: LogEntry = {\n id: run.id,\n name: run.name,\n type: run.run_type,\n tags: run.tags ?? [],\n metadata: run.extra?.metadata ?? {},\n start_time: new Date(run.start_time).toISOString(),\n streamed_output: [],\n streamed_output_str: [],\n final_output: undefined,\n end_time: undefined,\n };\n\n if (this._schemaFormat === \"streaming_events\") {\n logEntry.inputs = await _getStandardizedInputs(run, this._schemaFormat);\n }\n\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${this.keyMapByRunId[run.id]}`,\n value: logEntry,\n },\n ],\n })\n );\n }\n\n async onRunUpdate(run: Run): Promise<void> {\n try {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n const ops: JSONPatchOperation[] = [];\n if (this._schemaFormat === \"streaming_events\") {\n ops.push({\n op: \"replace\",\n path: `/logs/${runName}/inputs`,\n value: await _getStandardizedInputs(run, this._schemaFormat),\n });\n }\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/final_output`,\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n });\n if (run.end_time !== undefined) {\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/end_time`,\n value: new Date(run.end_time).toISOString(),\n });\n }\n const patch = new RunLogPatch({ ops });\n await this.writer.write(patch);\n } finally {\n if (run.id === this.rootId) {\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"/final_output\",\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n },\n ],\n });\n await this.writer.write(patch);\n if (this.autoClose) {\n await this.writer.close();\n }\n }\n }\n }\n\n async onLLMNewToken(\n run: Run,\n token: string,\n kwargs?: HandleLLMNewTokenCallbackFields\n ): Promise<void> {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n // TODO: Remove hack\n const isChatModel = run.inputs.messages !== undefined;\n let streamedOutputValue;\n if (isChatModel) {\n if (isChatGenerationChunk(kwargs?.chunk)) {\n streamedOutputValue = kwargs?.chunk;\n } else {\n streamedOutputValue = new AIMessageChunk({\n id: `run-${run.id}`,\n content: token,\n });\n }\n } else {\n streamedOutputValue = token;\n }\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output_str/-`,\n value: token,\n },\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output/-`,\n value: streamedOutputValue,\n },\n ],\n });\n await this.writer.write(patch);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"log_stream.cjs","names":["applyPatch","BaseTracer","IterableReadableStream","AIMessageChunk"],"sources":["../../src/tracers/log_stream.ts"],"sourcesContent":["import {\n applyPatch,\n type Operation as JSONPatchOperation,\n} from \"../utils/fast-json-patch/index.js\";\nimport { BaseTracer, type Run } from \"./base.js\";\nimport {\n BaseCallbackHandler,\n BaseCallbackHandlerInput,\n CallbackHandlerPrefersStreaming,\n HandleLLMNewTokenCallbackFields,\n} from \"../callbacks/base.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { ChatGenerationChunk, GenerationChunk } from \"../outputs.js\";\nimport { AIMessageChunk } from \"../messages/ai.js\";\nimport type { StreamEvent, StreamEventData } from \"./event_stream.js\";\n\nexport type { StreamEvent, StreamEventData };\n\n/**\n * Interface that represents the structure of a log entry in the\n * `LogStreamCallbackHandler`.\n */\nexport type LogEntry = {\n /** ID of the sub-run. */\n id: string;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n /** List of tags for the run. */\n tags: string[];\n /** Key-value pairs of metadata for the run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n metadata: Record<string, any>;\n /** ISO-8601 timestamp of when the run started. */\n start_time: string;\n /** List of general output chunks streamed by this run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** List of LLM tokens streamed by this run, if applicable. */\n streamed_output_str: string[];\n /** Inputs to this run. Not available currently via streamLog. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n inputs?: any;\n /** Final output of this run. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /** ISO-8601 timestamp of when the run ended. Only available after the run has finished. */\n end_time?: string;\n};\n\nexport type RunState = {\n /** ID of the sub-run. */\n id: string;\n /** List of output chunks streamed by Runnable.stream() */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** Final output of the run, usually the result of aggregating streamed_output. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /**\n * List of sub-runs contained in this run, if any, in the order they were started.\n * If filters were supplied, this list will contain only the runs that matched the filters.\n */\n logs: Record<string, LogEntry>;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n};\n\n/**\n * List of jsonpatch JSONPatchOperations, which describe how to create the run state\n * from an empty dict. This is the minimal representation of the log, designed to\n * be serialized as JSON and sent over the wire to reconstruct the log on the other\n * side. Reconstruction of the state can be done with any jsonpatch-compliant library,\n * see https://jsonpatch.com for more information.\n */\nexport class RunLogPatch {\n ops: JSONPatchOperation[];\n\n constructor(fields: { ops?: JSONPatchOperation[] }) {\n this.ops = fields.ops ?? [];\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch({}, ops);\n // oxlint-disable-next-line @typescript-eslint/no-use-before-define\n return new RunLog({\n ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport class RunLog extends RunLogPatch {\n state: RunState;\n\n constructor(fields: { ops?: JSONPatchOperation[]; state: RunState }) {\n super(fields);\n this.state = fields.state;\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch(this.state, other.ops);\n return new RunLog({ ops, state: states[states.length - 1].newDocument });\n }\n\n static fromRunLogPatch(patch: RunLogPatch) {\n const states = applyPatch({}, patch.ops);\n return new RunLog({\n ops: patch.ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport type SchemaFormat = \"original\" | \"streaming_events\";\n\nexport interface LogStreamCallbackHandlerInput extends BaseCallbackHandlerInput {\n autoClose?: boolean;\n includeNames?: string[];\n includeTypes?: string[];\n includeTags?: string[];\n excludeNames?: string[];\n excludeTypes?: string[];\n excludeTags?: string[];\n _schemaFormat?: SchemaFormat;\n}\n\nexport const isLogStreamHandler = (\n handler: BaseCallbackHandler\n): handler is LogStreamCallbackHandler => handler.name === \"log_stream_tracer\";\n\n/**\n * Extract standardized inputs from a run.\n *\n * Standardizes the inputs based on the type of the runnable used.\n *\n * @param run - Run object\n * @param schemaFormat - The schema format to use.\n *\n * @returns Valid inputs are only dict. By conventions, inputs always represented\n * invocation using named arguments.\n * A null means that the input is not yet known!\n */\nasync function _getStandardizedInputs(run: Run, schemaFormat: SchemaFormat) {\n if (schemaFormat === \"original\") {\n throw new Error(\n \"Do not assign inputs with original schema drop the key for now. \" +\n \"When inputs are added to streamLog they should be added with \" +\n \"standardized schema for streaming events.\"\n );\n }\n\n const { inputs } = run;\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return inputs;\n }\n\n if (Object.keys(inputs).length === 1 && inputs?.input === \"\") {\n return undefined;\n }\n\n // new style chains\n // These nest an additional 'input' key inside the 'inputs' to make sure\n // the input is always a dict. We need to unpack and user the inner value.\n // We should try to fix this in Runnables and callbacks/tracers\n // Runnables should be using a null type here not a placeholder\n // dict.\n return inputs.input;\n}\n\nasync function _getStandardizedOutputs(run: Run, schemaFormat: SchemaFormat) {\n const { outputs } = run;\n if (schemaFormat === \"original\") {\n // Return the old schema, without standardizing anything\n return outputs;\n }\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return outputs;\n }\n\n // TODO: Remove this hacky check\n if (\n outputs !== undefined &&\n Object.keys(outputs).length === 1 &&\n outputs?.output !== undefined\n ) {\n return outputs.output;\n }\n\n return outputs;\n}\n\nfunction isChatGenerationChunk(\n x?: ChatGenerationChunk | GenerationChunk\n): x is ChatGenerationChunk {\n return x !== undefined && (x as ChatGenerationChunk).message !== undefined;\n}\n\n/**\n * Class that extends the `BaseTracer` class from the\n * `langchain.callbacks.tracers.base` module. It represents a callback\n * handler that logs the execution of runs and emits `RunLog` instances to a\n * `RunLogStream`.\n */\nexport class LogStreamCallbackHandler\n extends BaseTracer\n implements CallbackHandlerPrefersStreaming\n{\n protected autoClose = true;\n\n protected includeNames?: string[];\n\n protected includeTypes?: string[];\n\n protected includeTags?: string[];\n\n protected excludeNames?: string[];\n\n protected excludeTypes?: string[];\n\n protected excludeTags?: string[];\n\n protected _schemaFormat: SchemaFormat = \"original\";\n\n protected rootId?: string;\n\n private keyMapByRunId: Record<string, string> = {};\n\n private counterMapByRunName: Record<string, number> = {};\n\n protected transformStream: TransformStream;\n\n public writer: WritableStreamDefaultWriter;\n\n public receiveStream: IterableReadableStream<RunLogPatch>;\n\n name = \"log_stream_tracer\";\n\n lc_prefer_streaming = true;\n\n constructor(fields?: LogStreamCallbackHandlerInput) {\n super({ _awaitHandler: true, ...fields });\n this.autoClose = fields?.autoClose ?? true;\n this.includeNames = fields?.includeNames;\n this.includeTypes = fields?.includeTypes;\n this.includeTags = fields?.includeTags;\n this.excludeNames = fields?.excludeNames;\n this.excludeTypes = fields?.excludeTypes;\n this.excludeTags = fields?.excludeTags;\n this._schemaFormat = fields?._schemaFormat ?? this._schemaFormat;\n this.transformStream = new TransformStream();\n this.writer = this.transformStream.writable.getWriter();\n this.receiveStream = IterableReadableStream.fromReadableStream(\n this.transformStream.readable\n );\n }\n\n [Symbol.asyncIterator]() {\n return this.receiveStream;\n }\n\n protected async persistRun(_run: Run): Promise<void> {\n // This is a legacy method only called once for an entire run tree\n // and is therefore not useful here\n }\n\n _includeRun(run: Run): boolean {\n if (run.id === this.rootId) {\n return false;\n }\n const runTags = run.tags ?? [];\n let include =\n this.includeNames === undefined &&\n this.includeTags === undefined &&\n this.includeTypes === undefined;\n if (this.includeNames !== undefined) {\n include = include || this.includeNames.includes(run.name);\n }\n if (this.includeTypes !== undefined) {\n include = include || this.includeTypes.includes(run.run_type);\n }\n if (this.includeTags !== undefined) {\n include =\n include ||\n runTags.find((tag) => this.includeTags?.includes(tag)) !== undefined;\n }\n if (this.excludeNames !== undefined) {\n include = include && !this.excludeNames.includes(run.name);\n }\n if (this.excludeTypes !== undefined) {\n include = include && !this.excludeTypes.includes(run.run_type);\n }\n if (this.excludeTags !== undefined) {\n include =\n include && runTags.every((tag) => !this.excludeTags?.includes(tag));\n }\n return include;\n }\n\n async *tapOutputIterable<T>(\n runId: string,\n output: AsyncGenerator<T>\n ): AsyncGenerator<T> {\n // Tap an output async iterator to stream its values to the log.\n for await (const chunk of output) {\n // root run is handled in .streamLog()\n if (runId !== this.rootId) {\n // if we can't find the run silently ignore\n // eg. because this run wasn't included in the log\n const key = this.keyMapByRunId[runId];\n if (key) {\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${key}/streamed_output/-`,\n value: chunk,\n },\n ],\n })\n );\n }\n }\n yield chunk;\n }\n }\n\n async onRunCreate(run: Run): Promise<void> {\n if (this.rootId === undefined) {\n this.rootId = run.id;\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"\",\n value: {\n id: run.id,\n name: run.name,\n type: run.run_type,\n streamed_output: [],\n final_output: undefined,\n logs: {},\n },\n },\n ],\n })\n );\n }\n\n if (!this._includeRun(run)) {\n return;\n }\n\n if (this.counterMapByRunName[run.name] === undefined) {\n this.counterMapByRunName[run.name] = 0;\n }\n this.counterMapByRunName[run.name] += 1;\n const count = this.counterMapByRunName[run.name];\n this.keyMapByRunId[run.id] =\n count === 1 ? run.name : `${run.name}:${count}`;\n\n const logEntry: LogEntry = {\n id: run.id,\n name: run.name,\n type: run.run_type,\n tags: run.tags ?? [],\n metadata: run.extra?.metadata ?? {},\n start_time: new Date(run.start_time).toISOString(),\n streamed_output: [],\n streamed_output_str: [],\n final_output: undefined,\n end_time: undefined,\n };\n\n if (this._schemaFormat === \"streaming_events\") {\n logEntry.inputs = await _getStandardizedInputs(run, this._schemaFormat);\n }\n\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${this.keyMapByRunId[run.id]}`,\n value: logEntry,\n },\n ],\n })\n );\n }\n\n async onRunUpdate(run: Run): Promise<void> {\n try {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n const ops: JSONPatchOperation[] = [];\n if (this._schemaFormat === \"streaming_events\") {\n ops.push({\n op: \"replace\",\n path: `/logs/${runName}/inputs`,\n value: await _getStandardizedInputs(run, this._schemaFormat),\n });\n }\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/final_output`,\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n });\n if (run.end_time !== undefined) {\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/end_time`,\n value: new Date(run.end_time).toISOString(),\n });\n }\n const patch = new RunLogPatch({ ops });\n await this.writer.write(patch);\n } finally {\n if (run.id === this.rootId) {\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"/final_output\",\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n },\n ],\n });\n await this.writer.write(patch);\n if (this.autoClose) {\n await this.writer.close();\n }\n }\n }\n }\n\n async onLLMNewToken(\n run: Run,\n token: string,\n kwargs?: HandleLLMNewTokenCallbackFields\n ): Promise<void> {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n // TODO: Remove hack\n const isChatModel = run.inputs.messages !== undefined;\n let streamedOutputValue;\n if (isChatModel) {\n if (isChatGenerationChunk(kwargs?.chunk)) {\n streamedOutputValue = kwargs?.chunk;\n } else {\n streamedOutputValue = new AIMessageChunk({\n id: `run-${run.id}`,\n content: token,\n });\n }\n } else {\n streamedOutputValue = token;\n }\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output_str/-`,\n value: token,\n },\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output/-`,\n value: streamedOutputValue,\n },\n ],\n });\n await this.writer.write(patch);\n }\n}\n"],"mappings":"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"}
|
|
@@ -240,12 +240,13 @@ var LogStreamCallbackHandler = class extends BaseTracer {
|
|
|
240
240
|
if (runName === void 0) return;
|
|
241
241
|
const isChatModel = run.inputs.messages !== void 0;
|
|
242
242
|
let streamedOutputValue;
|
|
243
|
-
if (isChatModel)
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
243
|
+
if (isChatModel) {
|
|
244
|
+
if (isChatGenerationChunk(kwargs?.chunk)) streamedOutputValue = kwargs?.chunk;
|
|
245
|
+
else streamedOutputValue = new AIMessageChunk({
|
|
246
|
+
id: `run-${run.id}`,
|
|
247
|
+
content: token
|
|
248
|
+
});
|
|
249
|
+
} else streamedOutputValue = token;
|
|
249
250
|
const patch = new RunLogPatch({ ops: [{
|
|
250
251
|
op: "add",
|
|
251
252
|
path: `/logs/${runName}/streamed_output_str/-`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log_stream.js","names":[],"sources":["../../src/tracers/log_stream.ts"],"sourcesContent":["import {\n applyPatch,\n type Operation as JSONPatchOperation,\n} from \"../utils/fast-json-patch/index.js\";\nimport { BaseTracer, type Run } from \"./base.js\";\nimport {\n BaseCallbackHandler,\n BaseCallbackHandlerInput,\n CallbackHandlerPrefersStreaming,\n HandleLLMNewTokenCallbackFields,\n} from \"../callbacks/base.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { ChatGenerationChunk, GenerationChunk } from \"../outputs.js\";\nimport { AIMessageChunk } from \"../messages/ai.js\";\nimport type { StreamEvent, StreamEventData } from \"./event_stream.js\";\n\nexport type { StreamEvent, StreamEventData };\n\n/**\n * Interface that represents the structure of a log entry in the\n * `LogStreamCallbackHandler`.\n */\nexport type LogEntry = {\n /** ID of the sub-run. */\n id: string;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n /** List of tags for the run. */\n tags: string[];\n /** Key-value pairs of metadata for the run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n metadata: Record<string, any>;\n /** ISO-8601 timestamp of when the run started. */\n start_time: string;\n /** List of general output chunks streamed by this run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** List of LLM tokens streamed by this run, if applicable. */\n streamed_output_str: string[];\n /** Inputs to this run. Not available currently via streamLog. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n inputs?: any;\n /** Final output of this run. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /** ISO-8601 timestamp of when the run ended. Only available after the run has finished. */\n end_time?: string;\n};\n\nexport type RunState = {\n /** ID of the sub-run. */\n id: string;\n /** List of output chunks streamed by Runnable.stream() */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** Final output of the run, usually the result of aggregating streamed_output. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /**\n * List of sub-runs contained in this run, if any, in the order they were started.\n * If filters were supplied, this list will contain only the runs that matched the filters.\n */\n logs: Record<string, LogEntry>;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n};\n\n/**\n * List of jsonpatch JSONPatchOperations, which describe how to create the run state\n * from an empty dict. This is the minimal representation of the log, designed to\n * be serialized as JSON and sent over the wire to reconstruct the log on the other\n * side. Reconstruction of the state can be done with any jsonpatch-compliant library,\n * see https://jsonpatch.com for more information.\n */\nexport class RunLogPatch {\n ops: JSONPatchOperation[];\n\n constructor(fields: { ops?: JSONPatchOperation[] }) {\n this.ops = fields.ops ?? [];\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch({}, ops);\n // oxlint-disable-next-line @typescript-eslint/no-use-before-define\n return new RunLog({\n ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport class RunLog extends RunLogPatch {\n state: RunState;\n\n constructor(fields: { ops?: JSONPatchOperation[]; state: RunState }) {\n super(fields);\n this.state = fields.state;\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch(this.state, other.ops);\n return new RunLog({ ops, state: states[states.length - 1].newDocument });\n }\n\n static fromRunLogPatch(patch: RunLogPatch) {\n const states = applyPatch({}, patch.ops);\n return new RunLog({\n ops: patch.ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport type SchemaFormat = \"original\" | \"streaming_events\";\n\nexport interface LogStreamCallbackHandlerInput extends BaseCallbackHandlerInput {\n autoClose?: boolean;\n includeNames?: string[];\n includeTypes?: string[];\n includeTags?: string[];\n excludeNames?: string[];\n excludeTypes?: string[];\n excludeTags?: string[];\n _schemaFormat?: SchemaFormat;\n}\n\nexport const isLogStreamHandler = (\n handler: BaseCallbackHandler\n): handler is LogStreamCallbackHandler => handler.name === \"log_stream_tracer\";\n\n/**\n * Extract standardized inputs from a run.\n *\n * Standardizes the inputs based on the type of the runnable used.\n *\n * @param run - Run object\n * @param schemaFormat - The schema format to use.\n *\n * @returns Valid inputs are only dict. By conventions, inputs always represented\n * invocation using named arguments.\n * A null means that the input is not yet known!\n */\nasync function _getStandardizedInputs(run: Run, schemaFormat: SchemaFormat) {\n if (schemaFormat === \"original\") {\n throw new Error(\n \"Do not assign inputs with original schema drop the key for now. \" +\n \"When inputs are added to streamLog they should be added with \" +\n \"standardized schema for streaming events.\"\n );\n }\n\n const { inputs } = run;\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return inputs;\n }\n\n if (Object.keys(inputs).length === 1 && inputs?.input === \"\") {\n return undefined;\n }\n\n // new style chains\n // These nest an additional 'input' key inside the 'inputs' to make sure\n // the input is always a dict. We need to unpack and user the inner value.\n // We should try to fix this in Runnables and callbacks/tracers\n // Runnables should be using a null type here not a placeholder\n // dict.\n return inputs.input;\n}\n\nasync function _getStandardizedOutputs(run: Run, schemaFormat: SchemaFormat) {\n const { outputs } = run;\n if (schemaFormat === \"original\") {\n // Return the old schema, without standardizing anything\n return outputs;\n }\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return outputs;\n }\n\n // TODO: Remove this hacky check\n if (\n outputs !== undefined &&\n Object.keys(outputs).length === 1 &&\n outputs?.output !== undefined\n ) {\n return outputs.output;\n }\n\n return outputs;\n}\n\nfunction isChatGenerationChunk(\n x?: ChatGenerationChunk | GenerationChunk\n): x is ChatGenerationChunk {\n return x !== undefined && (x as ChatGenerationChunk).message !== undefined;\n}\n\n/**\n * Class that extends the `BaseTracer` class from the\n * `langchain.callbacks.tracers.base` module. It represents a callback\n * handler that logs the execution of runs and emits `RunLog` instances to a\n * `RunLogStream`.\n */\nexport class LogStreamCallbackHandler\n extends BaseTracer\n implements CallbackHandlerPrefersStreaming\n{\n protected autoClose = true;\n\n protected includeNames?: string[];\n\n protected includeTypes?: string[];\n\n protected includeTags?: string[];\n\n protected excludeNames?: string[];\n\n protected excludeTypes?: string[];\n\n protected excludeTags?: string[];\n\n protected _schemaFormat: SchemaFormat = \"original\";\n\n protected rootId?: string;\n\n private keyMapByRunId: Record<string, string> = {};\n\n private counterMapByRunName: Record<string, number> = {};\n\n protected transformStream: TransformStream;\n\n public writer: WritableStreamDefaultWriter;\n\n public receiveStream: IterableReadableStream<RunLogPatch>;\n\n name = \"log_stream_tracer\";\n\n lc_prefer_streaming = true;\n\n constructor(fields?: LogStreamCallbackHandlerInput) {\n super({ _awaitHandler: true, ...fields });\n this.autoClose = fields?.autoClose ?? true;\n this.includeNames = fields?.includeNames;\n this.includeTypes = fields?.includeTypes;\n this.includeTags = fields?.includeTags;\n this.excludeNames = fields?.excludeNames;\n this.excludeTypes = fields?.excludeTypes;\n this.excludeTags = fields?.excludeTags;\n this._schemaFormat = fields?._schemaFormat ?? this._schemaFormat;\n this.transformStream = new TransformStream();\n this.writer = this.transformStream.writable.getWriter();\n this.receiveStream = IterableReadableStream.fromReadableStream(\n this.transformStream.readable\n );\n }\n\n [Symbol.asyncIterator]() {\n return this.receiveStream;\n }\n\n protected async persistRun(_run: Run): Promise<void> {\n // This is a legacy method only called once for an entire run tree\n // and is therefore not useful here\n }\n\n _includeRun(run: Run): boolean {\n if (run.id === this.rootId) {\n return false;\n }\n const runTags = run.tags ?? [];\n let include =\n this.includeNames === undefined &&\n this.includeTags === undefined &&\n this.includeTypes === undefined;\n if (this.includeNames !== undefined) {\n include = include || this.includeNames.includes(run.name);\n }\n if (this.includeTypes !== undefined) {\n include = include || this.includeTypes.includes(run.run_type);\n }\n if (this.includeTags !== undefined) {\n include =\n include ||\n runTags.find((tag) => this.includeTags?.includes(tag)) !== undefined;\n }\n if (this.excludeNames !== undefined) {\n include = include && !this.excludeNames.includes(run.name);\n }\n if (this.excludeTypes !== undefined) {\n include = include && !this.excludeTypes.includes(run.run_type);\n }\n if (this.excludeTags !== undefined) {\n include =\n include && runTags.every((tag) => !this.excludeTags?.includes(tag));\n }\n return include;\n }\n\n async *tapOutputIterable<T>(\n runId: string,\n output: AsyncGenerator<T>\n ): AsyncGenerator<T> {\n // Tap an output async iterator to stream its values to the log.\n for await (const chunk of output) {\n // root run is handled in .streamLog()\n if (runId !== this.rootId) {\n // if we can't find the run silently ignore\n // eg. because this run wasn't included in the log\n const key = this.keyMapByRunId[runId];\n if (key) {\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${key}/streamed_output/-`,\n value: chunk,\n },\n ],\n })\n );\n }\n }\n yield chunk;\n }\n }\n\n async onRunCreate(run: Run): Promise<void> {\n if (this.rootId === undefined) {\n this.rootId = run.id;\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"\",\n value: {\n id: run.id,\n name: run.name,\n type: run.run_type,\n streamed_output: [],\n final_output: undefined,\n logs: {},\n },\n },\n ],\n })\n );\n }\n\n if (!this._includeRun(run)) {\n return;\n }\n\n if (this.counterMapByRunName[run.name] === undefined) {\n this.counterMapByRunName[run.name] = 0;\n }\n this.counterMapByRunName[run.name] += 1;\n const count = this.counterMapByRunName[run.name];\n this.keyMapByRunId[run.id] =\n count === 1 ? run.name : `${run.name}:${count}`;\n\n const logEntry: LogEntry = {\n id: run.id,\n name: run.name,\n type: run.run_type,\n tags: run.tags ?? [],\n metadata: run.extra?.metadata ?? {},\n start_time: new Date(run.start_time).toISOString(),\n streamed_output: [],\n streamed_output_str: [],\n final_output: undefined,\n end_time: undefined,\n };\n\n if (this._schemaFormat === \"streaming_events\") {\n logEntry.inputs = await _getStandardizedInputs(run, this._schemaFormat);\n }\n\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${this.keyMapByRunId[run.id]}`,\n value: logEntry,\n },\n ],\n })\n );\n }\n\n async onRunUpdate(run: Run): Promise<void> {\n try {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n const ops: JSONPatchOperation[] = [];\n if (this._schemaFormat === \"streaming_events\") {\n ops.push({\n op: \"replace\",\n path: `/logs/${runName}/inputs`,\n value: await _getStandardizedInputs(run, this._schemaFormat),\n });\n }\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/final_output`,\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n });\n if (run.end_time !== undefined) {\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/end_time`,\n value: new Date(run.end_time).toISOString(),\n });\n }\n const patch = new RunLogPatch({ ops });\n await this.writer.write(patch);\n } finally {\n if (run.id === this.rootId) {\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"/final_output\",\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n },\n ],\n });\n await this.writer.write(patch);\n if (this.autoClose) {\n await this.writer.close();\n }\n }\n }\n }\n\n async onLLMNewToken(\n run: Run,\n token: string,\n kwargs?: HandleLLMNewTokenCallbackFields\n ): Promise<void> {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n // TODO: Remove hack\n const isChatModel = run.inputs.messages !== undefined;\n let streamedOutputValue;\n if (isChatModel) {\n if (isChatGenerationChunk(kwargs?.chunk)) {\n streamedOutputValue = kwargs?.chunk;\n } else {\n streamedOutputValue = new AIMessageChunk({\n id: `run-${run.id}`,\n content: token,\n });\n }\n } else {\n streamedOutputValue = token;\n }\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output_str/-`,\n value: token,\n },\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output/-`,\n value: streamedOutputValue,\n },\n ],\n });\n await this.writer.write(patch);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"log_stream.js","names":[],"sources":["../../src/tracers/log_stream.ts"],"sourcesContent":["import {\n applyPatch,\n type Operation as JSONPatchOperation,\n} from \"../utils/fast-json-patch/index.js\";\nimport { BaseTracer, type Run } from \"./base.js\";\nimport {\n BaseCallbackHandler,\n BaseCallbackHandlerInput,\n CallbackHandlerPrefersStreaming,\n HandleLLMNewTokenCallbackFields,\n} from \"../callbacks/base.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { ChatGenerationChunk, GenerationChunk } from \"../outputs.js\";\nimport { AIMessageChunk } from \"../messages/ai.js\";\nimport type { StreamEvent, StreamEventData } from \"./event_stream.js\";\n\nexport type { StreamEvent, StreamEventData };\n\n/**\n * Interface that represents the structure of a log entry in the\n * `LogStreamCallbackHandler`.\n */\nexport type LogEntry = {\n /** ID of the sub-run. */\n id: string;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n /** List of tags for the run. */\n tags: string[];\n /** Key-value pairs of metadata for the run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n metadata: Record<string, any>;\n /** ISO-8601 timestamp of when the run started. */\n start_time: string;\n /** List of general output chunks streamed by this run. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** List of LLM tokens streamed by this run, if applicable. */\n streamed_output_str: string[];\n /** Inputs to this run. Not available currently via streamLog. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n inputs?: any;\n /** Final output of this run. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /** ISO-8601 timestamp of when the run ended. Only available after the run has finished. */\n end_time?: string;\n};\n\nexport type RunState = {\n /** ID of the sub-run. */\n id: string;\n /** List of output chunks streamed by Runnable.stream() */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n streamed_output: any[];\n /** Final output of the run, usually the result of aggregating streamed_output. Only available after the run has finished successfully. */\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n final_output?: any;\n /**\n * List of sub-runs contained in this run, if any, in the order they were started.\n * If filters were supplied, this list will contain only the runs that matched the filters.\n */\n logs: Record<string, LogEntry>;\n /** Name of the object being run. */\n name: string;\n /** Type of the object being run, eg. prompt, chain, llm, etc. */\n type: string;\n};\n\n/**\n * List of jsonpatch JSONPatchOperations, which describe how to create the run state\n * from an empty dict. This is the minimal representation of the log, designed to\n * be serialized as JSON and sent over the wire to reconstruct the log on the other\n * side. Reconstruction of the state can be done with any jsonpatch-compliant library,\n * see https://jsonpatch.com for more information.\n */\nexport class RunLogPatch {\n ops: JSONPatchOperation[];\n\n constructor(fields: { ops?: JSONPatchOperation[] }) {\n this.ops = fields.ops ?? [];\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch({}, ops);\n // oxlint-disable-next-line @typescript-eslint/no-use-before-define\n return new RunLog({\n ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport class RunLog extends RunLogPatch {\n state: RunState;\n\n constructor(fields: { ops?: JSONPatchOperation[]; state: RunState }) {\n super(fields);\n this.state = fields.state;\n }\n\n concat(other: RunLogPatch) {\n const ops = this.ops.concat(other.ops);\n const states = applyPatch(this.state, other.ops);\n return new RunLog({ ops, state: states[states.length - 1].newDocument });\n }\n\n static fromRunLogPatch(patch: RunLogPatch) {\n const states = applyPatch({}, patch.ops);\n return new RunLog({\n ops: patch.ops,\n state: states[states.length - 1].newDocument as RunState,\n });\n }\n}\n\nexport type SchemaFormat = \"original\" | \"streaming_events\";\n\nexport interface LogStreamCallbackHandlerInput extends BaseCallbackHandlerInput {\n autoClose?: boolean;\n includeNames?: string[];\n includeTypes?: string[];\n includeTags?: string[];\n excludeNames?: string[];\n excludeTypes?: string[];\n excludeTags?: string[];\n _schemaFormat?: SchemaFormat;\n}\n\nexport const isLogStreamHandler = (\n handler: BaseCallbackHandler\n): handler is LogStreamCallbackHandler => handler.name === \"log_stream_tracer\";\n\n/**\n * Extract standardized inputs from a run.\n *\n * Standardizes the inputs based on the type of the runnable used.\n *\n * @param run - Run object\n * @param schemaFormat - The schema format to use.\n *\n * @returns Valid inputs are only dict. By conventions, inputs always represented\n * invocation using named arguments.\n * A null means that the input is not yet known!\n */\nasync function _getStandardizedInputs(run: Run, schemaFormat: SchemaFormat) {\n if (schemaFormat === \"original\") {\n throw new Error(\n \"Do not assign inputs with original schema drop the key for now. \" +\n \"When inputs are added to streamLog they should be added with \" +\n \"standardized schema for streaming events.\"\n );\n }\n\n const { inputs } = run;\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return inputs;\n }\n\n if (Object.keys(inputs).length === 1 && inputs?.input === \"\") {\n return undefined;\n }\n\n // new style chains\n // These nest an additional 'input' key inside the 'inputs' to make sure\n // the input is always a dict. We need to unpack and user the inner value.\n // We should try to fix this in Runnables and callbacks/tracers\n // Runnables should be using a null type here not a placeholder\n // dict.\n return inputs.input;\n}\n\nasync function _getStandardizedOutputs(run: Run, schemaFormat: SchemaFormat) {\n const { outputs } = run;\n if (schemaFormat === \"original\") {\n // Return the old schema, without standardizing anything\n return outputs;\n }\n\n if ([\"retriever\", \"llm\", \"prompt\"].includes(run.run_type)) {\n return outputs;\n }\n\n // TODO: Remove this hacky check\n if (\n outputs !== undefined &&\n Object.keys(outputs).length === 1 &&\n outputs?.output !== undefined\n ) {\n return outputs.output;\n }\n\n return outputs;\n}\n\nfunction isChatGenerationChunk(\n x?: ChatGenerationChunk | GenerationChunk\n): x is ChatGenerationChunk {\n return x !== undefined && (x as ChatGenerationChunk).message !== undefined;\n}\n\n/**\n * Class that extends the `BaseTracer` class from the\n * `langchain.callbacks.tracers.base` module. It represents a callback\n * handler that logs the execution of runs and emits `RunLog` instances to a\n * `RunLogStream`.\n */\nexport class LogStreamCallbackHandler\n extends BaseTracer\n implements CallbackHandlerPrefersStreaming\n{\n protected autoClose = true;\n\n protected includeNames?: string[];\n\n protected includeTypes?: string[];\n\n protected includeTags?: string[];\n\n protected excludeNames?: string[];\n\n protected excludeTypes?: string[];\n\n protected excludeTags?: string[];\n\n protected _schemaFormat: SchemaFormat = \"original\";\n\n protected rootId?: string;\n\n private keyMapByRunId: Record<string, string> = {};\n\n private counterMapByRunName: Record<string, number> = {};\n\n protected transformStream: TransformStream;\n\n public writer: WritableStreamDefaultWriter;\n\n public receiveStream: IterableReadableStream<RunLogPatch>;\n\n name = \"log_stream_tracer\";\n\n lc_prefer_streaming = true;\n\n constructor(fields?: LogStreamCallbackHandlerInput) {\n super({ _awaitHandler: true, ...fields });\n this.autoClose = fields?.autoClose ?? true;\n this.includeNames = fields?.includeNames;\n this.includeTypes = fields?.includeTypes;\n this.includeTags = fields?.includeTags;\n this.excludeNames = fields?.excludeNames;\n this.excludeTypes = fields?.excludeTypes;\n this.excludeTags = fields?.excludeTags;\n this._schemaFormat = fields?._schemaFormat ?? this._schemaFormat;\n this.transformStream = new TransformStream();\n this.writer = this.transformStream.writable.getWriter();\n this.receiveStream = IterableReadableStream.fromReadableStream(\n this.transformStream.readable\n );\n }\n\n [Symbol.asyncIterator]() {\n return this.receiveStream;\n }\n\n protected async persistRun(_run: Run): Promise<void> {\n // This is a legacy method only called once for an entire run tree\n // and is therefore not useful here\n }\n\n _includeRun(run: Run): boolean {\n if (run.id === this.rootId) {\n return false;\n }\n const runTags = run.tags ?? [];\n let include =\n this.includeNames === undefined &&\n this.includeTags === undefined &&\n this.includeTypes === undefined;\n if (this.includeNames !== undefined) {\n include = include || this.includeNames.includes(run.name);\n }\n if (this.includeTypes !== undefined) {\n include = include || this.includeTypes.includes(run.run_type);\n }\n if (this.includeTags !== undefined) {\n include =\n include ||\n runTags.find((tag) => this.includeTags?.includes(tag)) !== undefined;\n }\n if (this.excludeNames !== undefined) {\n include = include && !this.excludeNames.includes(run.name);\n }\n if (this.excludeTypes !== undefined) {\n include = include && !this.excludeTypes.includes(run.run_type);\n }\n if (this.excludeTags !== undefined) {\n include =\n include && runTags.every((tag) => !this.excludeTags?.includes(tag));\n }\n return include;\n }\n\n async *tapOutputIterable<T>(\n runId: string,\n output: AsyncGenerator<T>\n ): AsyncGenerator<T> {\n // Tap an output async iterator to stream its values to the log.\n for await (const chunk of output) {\n // root run is handled in .streamLog()\n if (runId !== this.rootId) {\n // if we can't find the run silently ignore\n // eg. because this run wasn't included in the log\n const key = this.keyMapByRunId[runId];\n if (key) {\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${key}/streamed_output/-`,\n value: chunk,\n },\n ],\n })\n );\n }\n }\n yield chunk;\n }\n }\n\n async onRunCreate(run: Run): Promise<void> {\n if (this.rootId === undefined) {\n this.rootId = run.id;\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"\",\n value: {\n id: run.id,\n name: run.name,\n type: run.run_type,\n streamed_output: [],\n final_output: undefined,\n logs: {},\n },\n },\n ],\n })\n );\n }\n\n if (!this._includeRun(run)) {\n return;\n }\n\n if (this.counterMapByRunName[run.name] === undefined) {\n this.counterMapByRunName[run.name] = 0;\n }\n this.counterMapByRunName[run.name] += 1;\n const count = this.counterMapByRunName[run.name];\n this.keyMapByRunId[run.id] =\n count === 1 ? run.name : `${run.name}:${count}`;\n\n const logEntry: LogEntry = {\n id: run.id,\n name: run.name,\n type: run.run_type,\n tags: run.tags ?? [],\n metadata: run.extra?.metadata ?? {},\n start_time: new Date(run.start_time).toISOString(),\n streamed_output: [],\n streamed_output_str: [],\n final_output: undefined,\n end_time: undefined,\n };\n\n if (this._schemaFormat === \"streaming_events\") {\n logEntry.inputs = await _getStandardizedInputs(run, this._schemaFormat);\n }\n\n await this.writer.write(\n new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${this.keyMapByRunId[run.id]}`,\n value: logEntry,\n },\n ],\n })\n );\n }\n\n async onRunUpdate(run: Run): Promise<void> {\n try {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n const ops: JSONPatchOperation[] = [];\n if (this._schemaFormat === \"streaming_events\") {\n ops.push({\n op: \"replace\",\n path: `/logs/${runName}/inputs`,\n value: await _getStandardizedInputs(run, this._schemaFormat),\n });\n }\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/final_output`,\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n });\n if (run.end_time !== undefined) {\n ops.push({\n op: \"add\",\n path: `/logs/${runName}/end_time`,\n value: new Date(run.end_time).toISOString(),\n });\n }\n const patch = new RunLogPatch({ ops });\n await this.writer.write(patch);\n } finally {\n if (run.id === this.rootId) {\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"replace\",\n path: \"/final_output\",\n value: await _getStandardizedOutputs(run, this._schemaFormat),\n },\n ],\n });\n await this.writer.write(patch);\n if (this.autoClose) {\n await this.writer.close();\n }\n }\n }\n }\n\n async onLLMNewToken(\n run: Run,\n token: string,\n kwargs?: HandleLLMNewTokenCallbackFields\n ): Promise<void> {\n const runName = this.keyMapByRunId[run.id];\n if (runName === undefined) {\n return;\n }\n // TODO: Remove hack\n const isChatModel = run.inputs.messages !== undefined;\n let streamedOutputValue;\n if (isChatModel) {\n if (isChatGenerationChunk(kwargs?.chunk)) {\n streamedOutputValue = kwargs?.chunk;\n } else {\n streamedOutputValue = new AIMessageChunk({\n id: `run-${run.id}`,\n content: token,\n });\n }\n } else {\n streamedOutputValue = token;\n }\n const patch = new RunLogPatch({\n ops: [\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output_str/-`,\n value: token,\n },\n {\n op: \"add\",\n path: `/logs/${runName}/streamed_output/-`,\n value: streamedOutputValue,\n },\n ],\n });\n await this.writer.write(patch);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA8EA,IAAa,cAAb,MAAyB;CACvB;CAEA,YAAY,QAAwC;EAClD,KAAK,MAAM,OAAO,OAAO,CAAC;CAC5B;CAEA,OAAO,OAAoB;EACzB,MAAM,MAAM,KAAK,IAAI,OAAO,MAAM,GAAG;EACrC,MAAM,SAAS,WAAW,CAAC,GAAG,GAAG;EAEjC,OAAO,IAAI,OAAO;GAChB;GACA,OAAO,OAAO,OAAO,SAAS,EAAE,CAAC;EACnC,CAAC;CACH;AACF;AAEA,IAAa,SAAb,MAAa,eAAe,YAAY;CACtC;CAEA,YAAY,QAAyD;EACnE,MAAM,MAAM;EACZ,KAAK,QAAQ,OAAO;CACtB;CAEA,OAAO,OAAoB;EACzB,MAAM,MAAM,KAAK,IAAI,OAAO,MAAM,GAAG;EACrC,MAAM,SAAS,WAAW,KAAK,OAAO,MAAM,GAAG;EAC/C,OAAO,IAAI,OAAO;GAAE;GAAK,OAAO,OAAO,OAAO,SAAS,EAAE,CAAC;EAAY,CAAC;CACzE;CAEA,OAAO,gBAAgB,OAAoB;EACzC,MAAM,SAAS,WAAW,CAAC,GAAG,MAAM,GAAG;EACvC,OAAO,IAAI,OAAO;GAChB,KAAK,MAAM;GACX,OAAO,OAAO,OAAO,SAAS,EAAE,CAAC;EACnC,CAAC;CACH;AACF;AAeA,MAAa,sBACX,YACwC,QAAQ,SAAS;;;;;;;;;;;;;AAc3D,eAAe,uBAAuB,KAAU,cAA4B;CAC1E,IAAI,iBAAiB,YACnB,MAAM,IAAI,MACR,wKAGF;CAGF,MAAM,EAAE,WAAW;CAEnB,IAAI;EAAC;EAAa;EAAO;CAAQ,CAAC,CAAC,SAAS,IAAI,QAAQ,GACtD,OAAO;CAGT,IAAI,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,KAAK,QAAQ,UAAU,IACxD;CASF,OAAO,OAAO;AAChB;AAEA,eAAe,wBAAwB,KAAU,cAA4B;CAC3E,MAAM,EAAE,YAAY;CACpB,IAAI,iBAAiB,YAEnB,OAAO;CAGT,IAAI;EAAC;EAAa;EAAO;CAAQ,CAAC,CAAC,SAAS,IAAI,QAAQ,GACtD,OAAO;CAIT,IACE,YAAY,KAAA,KACZ,OAAO,KAAK,OAAO,CAAC,CAAC,WAAW,KAChC,SAAS,WAAW,KAAA,GAEpB,OAAO,QAAQ;CAGjB,OAAO;AACT;AAEA,SAAS,sBACP,GAC0B;CAC1B,OAAO,MAAM,KAAA,KAAc,EAA0B,YAAY,KAAA;AACnE;;;;;;;AAQA,IAAa,2BAAb,cACU,WAEV;CACE,YAAsB;CAEtB;CAEA;CAEA;CAEA;CAEA;CAEA;CAEA,gBAAwC;CAExC;CAEA,gBAAgD,CAAC;CAEjD,sBAAsD,CAAC;CAEvD;CAEA;CAEA;CAEA,OAAO;CAEP,sBAAsB;CAEtB,YAAY,QAAwC;EAClD,MAAM;GAAE,eAAe;GAAM,GAAG;EAAO,CAAC;EACxC,KAAK,YAAY,QAAQ,aAAa;EACtC,KAAK,eAAe,QAAQ;EAC5B,KAAK,eAAe,QAAQ;EAC5B,KAAK,cAAc,QAAQ;EAC3B,KAAK,eAAe,QAAQ;EAC5B,KAAK,eAAe,QAAQ;EAC5B,KAAK,cAAc,QAAQ;EAC3B,KAAK,gBAAgB,QAAQ,iBAAiB,KAAK;EACnD,KAAK,kBAAkB,IAAI,gBAAgB;EAC3C,KAAK,SAAS,KAAK,gBAAgB,SAAS,UAAU;EACtD,KAAK,gBAAgB,uBAAuB,mBAC1C,KAAK,gBAAgB,QACvB;CACF;CAEA,CAAC,OAAO,iBAAiB;EACvB,OAAO,KAAK;CACd;CAEA,MAAgB,WAAW,MAA0B,CAGrD;CAEA,YAAY,KAAmB;EAC7B,IAAI,IAAI,OAAO,KAAK,QAClB,OAAO;EAET,MAAM,UAAU,IAAI,QAAQ,CAAC;EAC7B,IAAI,UACF,KAAK,iBAAiB,KAAA,KACtB,KAAK,gBAAgB,KAAA,KACrB,KAAK,iBAAiB,KAAA;EACxB,IAAI,KAAK,iBAAiB,KAAA,GACxB,UAAU,WAAW,KAAK,aAAa,SAAS,IAAI,IAAI;EAE1D,IAAI,KAAK,iBAAiB,KAAA,GACxB,UAAU,WAAW,KAAK,aAAa,SAAS,IAAI,QAAQ;EAE9D,IAAI,KAAK,gBAAgB,KAAA,GACvB,UACE,WACA,QAAQ,MAAM,QAAQ,KAAK,aAAa,SAAS,GAAG,CAAC,MAAM,KAAA;EAE/D,IAAI,KAAK,iBAAiB,KAAA,GACxB,UAAU,WAAW,CAAC,KAAK,aAAa,SAAS,IAAI,IAAI;EAE3D,IAAI,KAAK,iBAAiB,KAAA,GACxB,UAAU,WAAW,CAAC,KAAK,aAAa,SAAS,IAAI,QAAQ;EAE/D,IAAI,KAAK,gBAAgB,KAAA,GACvB,UACE,WAAW,QAAQ,OAAO,QAAQ,CAAC,KAAK,aAAa,SAAS,GAAG,CAAC;EAEtE,OAAO;CACT;CAEA,OAAO,kBACL,OACA,QACmB;EAEnB,WAAW,MAAM,SAAS,QAAQ;GAEhC,IAAI,UAAU,KAAK,QAAQ;IAGzB,MAAM,MAAM,KAAK,cAAc;IAC/B,IAAI,KACF,MAAM,KAAK,OAAO,MAChB,IAAI,YAAY,EACd,KAAK,CACH;KACE,IAAI;KACJ,MAAM,SAAS,IAAI;KACnB,OAAO;IACT,CACF,EACF,CAAC,CACH;GAEJ;GACA,MAAM;EACR;CACF;CAEA,MAAM,YAAY,KAAyB;EACzC,IAAI,KAAK,WAAW,KAAA,GAAW;GAC7B,KAAK,SAAS,IAAI;GAClB,MAAM,KAAK,OAAO,MAChB,IAAI,YAAY,EACd,KAAK,CACH;IACE,IAAI;IACJ,MAAM;IACN,OAAO;KACL,IAAI,IAAI;KACR,MAAM,IAAI;KACV,MAAM,IAAI;KACV,iBAAiB,CAAC;KAClB,cAAc,KAAA;KACd,MAAM,CAAC;IACT;GACF,CACF,EACF,CAAC,CACH;EACF;EAEA,IAAI,CAAC,KAAK,YAAY,GAAG,GACvB;EAGF,IAAI,KAAK,oBAAoB,IAAI,UAAU,KAAA,GACzC,KAAK,oBAAoB,IAAI,QAAQ;EAEvC,KAAK,oBAAoB,IAAI,SAAS;EACtC,MAAM,QAAQ,KAAK,oBAAoB,IAAI;EAC3C,KAAK,cAAc,IAAI,MACrB,UAAU,IAAI,IAAI,OAAO,GAAG,IAAI,KAAK,GAAG;EAE1C,MAAM,WAAqB;GACzB,IAAI,IAAI;GACR,MAAM,IAAI;GACV,MAAM,IAAI;GACV,MAAM,IAAI,QAAQ,CAAC;GACnB,UAAU,IAAI,OAAO,YAAY,CAAC;GAClC,YAAY,IAAI,KAAK,IAAI,UAAU,CAAC,CAAC,YAAY;GACjD,iBAAiB,CAAC;GAClB,qBAAqB,CAAC;GACtB,cAAc,KAAA;GACd,UAAU,KAAA;EACZ;EAEA,IAAI,KAAK,kBAAkB,oBACzB,SAAS,SAAS,MAAM,uBAAuB,KAAK,KAAK,aAAa;EAGxE,MAAM,KAAK,OAAO,MAChB,IAAI,YAAY,EACd,KAAK,CACH;GACE,IAAI;GACJ,MAAM,SAAS,KAAK,cAAc,IAAI;GACtC,OAAO;EACT,CACF,EACF,CAAC,CACH;CACF;CAEA,MAAM,YAAY,KAAyB;EACzC,IAAI;GACF,MAAM,UAAU,KAAK,cAAc,IAAI;GACvC,IAAI,YAAY,KAAA,GACd;GAEF,MAAM,MAA4B,CAAC;GACnC,IAAI,KAAK,kBAAkB,oBACzB,IAAI,KAAK;IACP,IAAI;IACJ,MAAM,SAAS,QAAQ;IACvB,OAAO,MAAM,uBAAuB,KAAK,KAAK,aAAa;GAC7D,CAAC;GAEH,IAAI,KAAK;IACP,IAAI;IACJ,MAAM,SAAS,QAAQ;IACvB,OAAO,MAAM,wBAAwB,KAAK,KAAK,aAAa;GAC9D,CAAC;GACD,IAAI,IAAI,aAAa,KAAA,GACnB,IAAI,KAAK;IACP,IAAI;IACJ,MAAM,SAAS,QAAQ;IACvB,OAAO,IAAI,KAAK,IAAI,QAAQ,CAAC,CAAC,YAAY;GAC5C,CAAC;GAEH,MAAM,QAAQ,IAAI,YAAY,EAAE,IAAI,CAAC;GACrC,MAAM,KAAK,OAAO,MAAM,KAAK;EAC/B,UAAU;GACR,IAAI,IAAI,OAAO,KAAK,QAAQ;IAC1B,MAAM,QAAQ,IAAI,YAAY,EAC5B,KAAK,CACH;KACE,IAAI;KACJ,MAAM;KACN,OAAO,MAAM,wBAAwB,KAAK,KAAK,aAAa;IAC9D,CACF,EACF,CAAC;IACD,MAAM,KAAK,OAAO,MAAM,KAAK;IAC7B,IAAI,KAAK,WACP,MAAM,KAAK,OAAO,MAAM;GAE5B;EACF;CACF;CAEA,MAAM,cACJ,KACA,OACA,QACe;EACf,MAAM,UAAU,KAAK,cAAc,IAAI;EACvC,IAAI,YAAY,KAAA,GACd;EAGF,MAAM,cAAc,IAAI,OAAO,aAAa,KAAA;EAC5C,IAAI;EACJ,IAAI,aAAa;GACf,IAAI,sBAAsB,QAAQ,KAAK,GACrC,sBAAsB,QAAQ;QAE9B,sBAAsB,IAAI,eAAe;IACvC,IAAI,OAAO,IAAI;IACf,SAAS;GACX,CAAC;EAEL,OACE,sBAAsB;EAExB,MAAM,QAAQ,IAAI,YAAY,EAC5B,KAAK,CACH;GACE,IAAI;GACJ,MAAM,SAAS,QAAQ;GACvB,OAAO;EACT,GACA;GACE,IAAI;GACJ,MAAM,SAAS,QAAQ;GACvB,OAAO;EACT,CACF,EACF,CAAC;EACD,MAAM,KAAK,OAAO,MAAM,KAAK;CAC/B;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracer_langchain.cjs","names":["AIMessage","mergeUsageMetadata","BaseTracer","getDefaultLangChainClientSingleton","RunTree"],"sources":["../../src/tracers/tracer_langchain.ts"],"sourcesContent":["import {\n type Client,\n type LangSmithTracingClientInterface,\n getDefaultProjectName,\n} from \"langsmith\";\nimport { RunTree, type RunTreeConfig } from \"langsmith/run_trees\";\nimport { getCurrentRunTree } from \"langsmith/singletons/traceable\";\n\nimport {\n BaseRun,\n RunCreate,\n RunUpdate as BaseRunUpdate,\n KVMap,\n} from \"langsmith/schemas\";\nimport { BaseTracer, Run as BaseTracerRun } from \"./base.js\";\nimport { BaseCallbackHandlerInput } from \"../callbacks/base.js\";\nimport { getDefaultLangChainClientSingleton } from \"../singletons/tracer.js\";\nimport { ChatGeneration } from \"../outputs.js\";\nimport { AIMessage } from \"../messages/ai.js\";\nimport { mergeUsageMetadata, UsageMetadata } from \"../messages/metadata.js\";\n\nexport interface Run extends BaseRun {\n id: string;\n child_runs: this[];\n child_execution_order: number;\n dotted_order?: string;\n trace_id?: string;\n}\n\nexport interface RunCreate2 extends RunCreate {\n trace_id?: string;\n dotted_order?: string;\n}\n\nexport interface RunUpdate extends BaseRunUpdate {\n events: BaseRun[\"events\"];\n inputs: KVMap;\n trace_id?: string;\n dotted_order?: string;\n}\n\nexport interface LangChainTracerFields extends BaseCallbackHandlerInput {\n exampleId?: string;\n projectName?: string;\n client?: LangSmithTracingClientInterface;\n replicas?: RunTreeConfig[\"replicas\"];\n metadata?: Record<string, unknown>;\n tags?: string[];\n}\n\n/**\n * Keys that should be inherited from `tracerInheritableMetadata` even when\n * the run already has a value for them. This lets nested contexts\n * (e.g. a subagent invoked from inside a parent agent) override a\n * LangSmith-only tracing metadata value that was set by an ancestor.\n *\n * Keep this list very small: every key here loses the default\n * \"first wins\" protection and is always clobbered by the nearest\n * enclosing tracer config. Only keys that are strictly for LangSmith\n * tracing bookkeeping should be added.\n */\nexport const OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS = new Set<string>([\n \"ls_agent_type\",\n]);\n\n/**\n * Extract usage_metadata from chat generations.\n *\n * Iterates through generations to find and aggregates all usage_metadata\n * found in chat messages. This is typically present in chat model outputs.\n */\nfunction _getUsageMetadataFromGenerations(\n generations: ChatGeneration[][]\n): UsageMetadata | undefined {\n let output: UsageMetadata | undefined = undefined;\n for (const generationBatch of generations) {\n for (const generation of generationBatch) {\n if (\n AIMessage.isInstance(generation.message) &&\n generation.message.usage_metadata !== undefined\n ) {\n output = mergeUsageMetadata(output, generation.message.usage_metadata);\n }\n }\n }\n return output;\n}\n\nexport class LangChainTracer\n extends BaseTracer\n implements LangChainTracerFields\n{\n name = \"langchain_tracer\";\n\n projectName?: string;\n\n exampleId?: string;\n\n client: LangSmithTracingClientInterface;\n\n replicas?: RunTreeConfig[\"replicas\"];\n\n usesRunTreeMap = true;\n\n tracingMetadata?: Record<string, unknown>;\n\n tracingTags: string[] = [];\n\n constructor(protected fields: LangChainTracerFields = {}) {\n super(fields);\n const { exampleId, projectName, client, replicas, metadata, tags } = fields;\n\n this.projectName = projectName ?? getDefaultProjectName();\n this.replicas = replicas;\n this.exampleId = exampleId;\n this.client = client ?? getDefaultLangChainClientSingleton();\n this.tracingMetadata = metadata ? { ...metadata } : undefined;\n this.tracingTags = tags ?? [];\n\n const traceableTree = LangChainTracer.getTraceableRunTree();\n if (traceableTree) {\n this.updateFromRunTree(traceableTree);\n }\n }\n\n protected async persistRun(_run: Run): Promise<void> {\n // empty\n }\n\n async onRunCreate(run: Run): Promise<void> {\n _patchMissingTracingDefaults(this, run);\n if (!run.extra?.lc_defers_inputs) {\n const runTree = this.getRunTreeWithTracingConfig(run.id);\n await runTree?.postRun();\n }\n }\n\n async onRunUpdate(run: Run): Promise<void> {\n _patchMissingTracingDefaults(this, run);\n const runTree = this.getRunTreeWithTracingConfig(run.id);\n if (run.extra?.lc_defers_inputs) {\n await runTree?.postRun();\n } else {\n await runTree?.patchRun();\n }\n }\n\n onLLMEnd(run: BaseTracerRun): void {\n // Extract usage_metadata from outputs and store in extra.metadata\n const outputs = run.outputs as\n | { generations?: ChatGeneration[][] }\n | undefined;\n if (outputs?.generations) {\n const usageMetadata = _getUsageMetadataFromGenerations(\n outputs.generations\n );\n if (usageMetadata !== undefined) {\n run.extra = run.extra ?? {};\n const metadata =\n (run.extra.metadata as Record<string, unknown> | undefined) ?? {};\n metadata.usage_metadata = usageMetadata;\n run.extra.metadata = metadata;\n }\n }\n }\n\n copyWithTracingConfig({\n metadata,\n tags,\n }: {\n metadata?: Record<string, unknown>;\n tags?: string[];\n }): LangChainTracer {\n let mergedMetadata: Record<string, unknown> | undefined;\n if (metadata === undefined) {\n mergedMetadata = this.tracingMetadata\n ? { ...this.tracingMetadata }\n : undefined;\n } else if (this.tracingMetadata === undefined) {\n mergedMetadata = { ...metadata };\n } else {\n mergedMetadata = { ...this.tracingMetadata };\n for (const [key, value] of Object.entries(metadata)) {\n // For allowlisted LangSmith-only inheritable metadata keys (e.g.\n // `ls_agent_type`), nested callers are allowed to OVERRIDE the\n // value inherited from an ancestor. For all other keys we keep\n // the existing \"first wins\" behavior so that ancestor-provided\n // tracing metadata is not accidentally clobbered by child runs.\n if (\n !Object.prototype.hasOwnProperty.call(mergedMetadata, key) ||\n OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS.has(key)\n ) {\n mergedMetadata[key] = value;\n }\n }\n }\n\n const mergedTags = tags\n ? Array.from(new Set([...this.tracingTags, ...tags]))\n : [...this.tracingTags];\n\n const copied = new LangChainTracer({\n ...this.fields,\n metadata: mergedMetadata,\n tags: mergedTags,\n });\n copied.runMap = this.runMap;\n copied.runTreeMap = this.runTreeMap;\n return copied;\n }\n\n /** @internal */\n _getRunStoreKey(): object {\n return this.runTreeMap;\n }\n\n getRun(id: string): Run | undefined {\n return this.runTreeMap.get(id);\n }\n\n updateFromRunTree(runTree: RunTree) {\n this.runTreeMap.set(runTree.id, runTree);\n let rootRun: RunTree = runTree;\n const visited = new Set<string>();\n while (rootRun.parent_run) {\n if (visited.has(rootRun.id)) break;\n visited.add(rootRun.id);\n\n if (!rootRun.parent_run) break;\n rootRun = rootRun.parent_run as RunTree;\n }\n visited.clear();\n\n const queue = [rootRun];\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current || visited.has(current.id)) continue;\n visited.add(current.id);\n\n this.runTreeMap.set(current.id, current);\n if (current.child_runs) {\n queue.push(...current.child_runs);\n }\n }\n\n this.client = runTree.client ?? this.client;\n this.replicas = runTree.replicas ?? this.replicas;\n this.projectName = runTree.project_name ?? this.projectName;\n this.exampleId = runTree.reference_example_id ?? this.exampleId;\n this.fields = {\n ...this.fields,\n client: this.client,\n replicas: this.replicas,\n projectName: this.projectName,\n exampleId: this.exampleId,\n };\n }\n\n getRunTreeWithTracingConfig(id: string): RunTree | undefined {\n const runTree = this.runTreeMap.get(id);\n if (!runTree) return undefined;\n\n return new RunTree({\n ...runTree,\n client: this.client as Client,\n project_name: this.projectName,\n replicas: this.replicas,\n reference_example_id: this.exampleId,\n tracingEnabled: true,\n });\n }\n\n static getTraceableRunTree(): RunTree | undefined {\n try {\n return (\n // The type cast here provides forward compatibility. Old versions of LangSmith will just\n // ignore the permitAbsentRunTree arg.\n (\n getCurrentRunTree as (\n permitAbsentRunTree: boolean\n ) => ReturnType<typeof getCurrentRunTree> | undefined\n )(true)\n );\n } catch {\n return undefined;\n }\n }\n\n static [Symbol.hasInstance](instance: unknown): boolean {\n if (typeof instance !== \"object\" || instance === null) {\n return false;\n }\n const candidate = instance as Record<string, unknown>;\n return (\n \"name\" in candidate &&\n candidate.name === \"langchain_tracer\" &&\n \"copyWithTracingConfig\" in candidate &&\n typeof candidate.copyWithTracingConfig === \"function\" &&\n \"getRunTreeWithTracingConfig\" in candidate &&\n typeof candidate.getRunTreeWithTracingConfig === \"function\"\n );\n }\n}\n\nfunction _patchMissingTracingDefaults(tracer: LangChainTracer, run: Run): void {\n if (tracer.tracingMetadata) {\n run.extra ??= {};\n const metadata: Record<string, unknown> =\n (run.extra.metadata as Record<string, unknown> | undefined) ?? {};\n let didPatchMetadata = false;\n for (const [key, value] of Object.entries(tracer.tracingMetadata)) {\n // `OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS` are a small, LangSmith-only\n // allowlist that bypasses the \"first wins\" merge so a nested caller\n // (e.g. a subagent) can override a parent-set value.\n if (\n !Object.prototype.hasOwnProperty.call(metadata, key) ||\n OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS.has(key)\n ) {\n if (metadata[key] !== value) {\n metadata[key] = value;\n didPatchMetadata = true;\n }\n }\n }\n if (didPatchMetadata) {\n run.extra.metadata = metadata;\n }\n }\n\n if (tracer.tracingTags.length > 0) {\n run.tags = Array.from(\n new Set([...(run.tags ?? []), ...tracer.tracingTags])\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tracer_langchain.cjs","names":["AIMessage","mergeUsageMetadata","BaseTracer","getDefaultProjectName","getDefaultLangChainClientSingleton","RunTree","getCurrentRunTree"],"sources":["../../src/tracers/tracer_langchain.ts"],"sourcesContent":["import {\n type Client,\n type LangSmithTracingClientInterface,\n getDefaultProjectName,\n} from \"langsmith\";\nimport { RunTree, type RunTreeConfig } from \"langsmith/run_trees\";\nimport { getCurrentRunTree } from \"langsmith/singletons/traceable\";\n\nimport {\n BaseRun,\n RunCreate,\n RunUpdate as BaseRunUpdate,\n KVMap,\n} from \"langsmith/schemas\";\nimport { BaseTracer, Run as BaseTracerRun } from \"./base.js\";\nimport { BaseCallbackHandlerInput } from \"../callbacks/base.js\";\nimport { getDefaultLangChainClientSingleton } from \"../singletons/tracer.js\";\nimport { ChatGeneration } from \"../outputs.js\";\nimport { AIMessage } from \"../messages/ai.js\";\nimport { mergeUsageMetadata, UsageMetadata } from \"../messages/metadata.js\";\n\nexport interface Run extends BaseRun {\n id: string;\n child_runs: this[];\n child_execution_order: number;\n dotted_order?: string;\n trace_id?: string;\n}\n\nexport interface RunCreate2 extends RunCreate {\n trace_id?: string;\n dotted_order?: string;\n}\n\nexport interface RunUpdate extends BaseRunUpdate {\n events: BaseRun[\"events\"];\n inputs: KVMap;\n trace_id?: string;\n dotted_order?: string;\n}\n\nexport interface LangChainTracerFields extends BaseCallbackHandlerInput {\n exampleId?: string;\n projectName?: string;\n client?: LangSmithTracingClientInterface;\n replicas?: RunTreeConfig[\"replicas\"];\n metadata?: Record<string, unknown>;\n tags?: string[];\n}\n\n/**\n * Keys that should be inherited from `tracerInheritableMetadata` even when\n * the run already has a value for them. This lets nested contexts\n * (e.g. a subagent invoked from inside a parent agent) override a\n * LangSmith-only tracing metadata value that was set by an ancestor.\n *\n * Keep this list very small: every key here loses the default\n * \"first wins\" protection and is always clobbered by the nearest\n * enclosing tracer config. Only keys that are strictly for LangSmith\n * tracing bookkeeping should be added.\n */\nexport const OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS = new Set<string>([\n \"ls_agent_type\",\n]);\n\n/**\n * Extract usage_metadata from chat generations.\n *\n * Iterates through generations to find and aggregates all usage_metadata\n * found in chat messages. This is typically present in chat model outputs.\n */\nfunction _getUsageMetadataFromGenerations(\n generations: ChatGeneration[][]\n): UsageMetadata | undefined {\n let output: UsageMetadata | undefined = undefined;\n for (const generationBatch of generations) {\n for (const generation of generationBatch) {\n if (\n AIMessage.isInstance(generation.message) &&\n generation.message.usage_metadata !== undefined\n ) {\n output = mergeUsageMetadata(output, generation.message.usage_metadata);\n }\n }\n }\n return output;\n}\n\nexport class LangChainTracer\n extends BaseTracer\n implements LangChainTracerFields\n{\n name = \"langchain_tracer\";\n\n projectName?: string;\n\n exampleId?: string;\n\n client: LangSmithTracingClientInterface;\n\n replicas?: RunTreeConfig[\"replicas\"];\n\n usesRunTreeMap = true;\n\n tracingMetadata?: Record<string, unknown>;\n\n tracingTags: string[] = [];\n\n constructor(protected fields: LangChainTracerFields = {}) {\n super(fields);\n const { exampleId, projectName, client, replicas, metadata, tags } = fields;\n\n this.projectName = projectName ?? getDefaultProjectName();\n this.replicas = replicas;\n this.exampleId = exampleId;\n this.client = client ?? getDefaultLangChainClientSingleton();\n this.tracingMetadata = metadata ? { ...metadata } : undefined;\n this.tracingTags = tags ?? [];\n\n const traceableTree = LangChainTracer.getTraceableRunTree();\n if (traceableTree) {\n this.updateFromRunTree(traceableTree);\n }\n }\n\n protected async persistRun(_run: Run): Promise<void> {\n // empty\n }\n\n async onRunCreate(run: Run): Promise<void> {\n _patchMissingTracingDefaults(this, run);\n if (!run.extra?.lc_defers_inputs) {\n const runTree = this.getRunTreeWithTracingConfig(run.id);\n await runTree?.postRun();\n }\n }\n\n async onRunUpdate(run: Run): Promise<void> {\n _patchMissingTracingDefaults(this, run);\n const runTree = this.getRunTreeWithTracingConfig(run.id);\n if (run.extra?.lc_defers_inputs) {\n await runTree?.postRun();\n } else {\n await runTree?.patchRun();\n }\n }\n\n onLLMEnd(run: BaseTracerRun): void {\n // Extract usage_metadata from outputs and store in extra.metadata\n const outputs = run.outputs as\n | { generations?: ChatGeneration[][] }\n | undefined;\n if (outputs?.generations) {\n const usageMetadata = _getUsageMetadataFromGenerations(\n outputs.generations\n );\n if (usageMetadata !== undefined) {\n run.extra = run.extra ?? {};\n const metadata =\n (run.extra.metadata as Record<string, unknown> | undefined) ?? {};\n metadata.usage_metadata = usageMetadata;\n run.extra.metadata = metadata;\n }\n }\n }\n\n copyWithTracingConfig({\n metadata,\n tags,\n }: {\n metadata?: Record<string, unknown>;\n tags?: string[];\n }): LangChainTracer {\n let mergedMetadata: Record<string, unknown> | undefined;\n if (metadata === undefined) {\n mergedMetadata = this.tracingMetadata\n ? { ...this.tracingMetadata }\n : undefined;\n } else if (this.tracingMetadata === undefined) {\n mergedMetadata = { ...metadata };\n } else {\n mergedMetadata = { ...this.tracingMetadata };\n for (const [key, value] of Object.entries(metadata)) {\n // For allowlisted LangSmith-only inheritable metadata keys (e.g.\n // `ls_agent_type`), nested callers are allowed to OVERRIDE the\n // value inherited from an ancestor. For all other keys we keep\n // the existing \"first wins\" behavior so that ancestor-provided\n // tracing metadata is not accidentally clobbered by child runs.\n if (\n !Object.prototype.hasOwnProperty.call(mergedMetadata, key) ||\n OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS.has(key)\n ) {\n mergedMetadata[key] = value;\n }\n }\n }\n\n const mergedTags = tags\n ? Array.from(new Set([...this.tracingTags, ...tags]))\n : [...this.tracingTags];\n\n const copied = new LangChainTracer({\n ...this.fields,\n metadata: mergedMetadata,\n tags: mergedTags,\n });\n copied.runMap = this.runMap;\n copied.runTreeMap = this.runTreeMap;\n return copied;\n }\n\n /** @internal */\n _getRunStoreKey(): object {\n return this.runTreeMap;\n }\n\n getRun(id: string): Run | undefined {\n return this.runTreeMap.get(id);\n }\n\n updateFromRunTree(runTree: RunTree) {\n this.runTreeMap.set(runTree.id, runTree);\n let rootRun: RunTree = runTree;\n const visited = new Set<string>();\n while (rootRun.parent_run) {\n if (visited.has(rootRun.id)) break;\n visited.add(rootRun.id);\n\n if (!rootRun.parent_run) break;\n rootRun = rootRun.parent_run as RunTree;\n }\n visited.clear();\n\n const queue = [rootRun];\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current || visited.has(current.id)) continue;\n visited.add(current.id);\n\n this.runTreeMap.set(current.id, current);\n if (current.child_runs) {\n queue.push(...current.child_runs);\n }\n }\n\n this.client = runTree.client ?? this.client;\n this.replicas = runTree.replicas ?? this.replicas;\n this.projectName = runTree.project_name ?? this.projectName;\n this.exampleId = runTree.reference_example_id ?? this.exampleId;\n this.fields = {\n ...this.fields,\n client: this.client,\n replicas: this.replicas,\n projectName: this.projectName,\n exampleId: this.exampleId,\n };\n }\n\n getRunTreeWithTracingConfig(id: string): RunTree | undefined {\n const runTree = this.runTreeMap.get(id);\n if (!runTree) return undefined;\n\n return new RunTree({\n ...runTree,\n client: this.client as Client,\n project_name: this.projectName,\n replicas: this.replicas,\n reference_example_id: this.exampleId,\n tracingEnabled: true,\n });\n }\n\n static getTraceableRunTree(): RunTree | undefined {\n try {\n return (\n // The type cast here provides forward compatibility. Old versions of LangSmith will just\n // ignore the permitAbsentRunTree arg.\n (\n getCurrentRunTree as (\n permitAbsentRunTree: boolean\n ) => ReturnType<typeof getCurrentRunTree> | undefined\n )(true)\n );\n } catch {\n return undefined;\n }\n }\n\n static [Symbol.hasInstance](instance: unknown): boolean {\n if (typeof instance !== \"object\" || instance === null) {\n return false;\n }\n const candidate = instance as Record<string, unknown>;\n return (\n \"name\" in candidate &&\n candidate.name === \"langchain_tracer\" &&\n \"copyWithTracingConfig\" in candidate &&\n typeof candidate.copyWithTracingConfig === \"function\" &&\n \"getRunTreeWithTracingConfig\" in candidate &&\n typeof candidate.getRunTreeWithTracingConfig === \"function\"\n );\n }\n}\n\nfunction _patchMissingTracingDefaults(tracer: LangChainTracer, run: Run): void {\n if (tracer.tracingMetadata) {\n run.extra ??= {};\n const metadata: Record<string, unknown> =\n (run.extra.metadata as Record<string, unknown> | undefined) ?? {};\n let didPatchMetadata = false;\n for (const [key, value] of Object.entries(tracer.tracingMetadata)) {\n // `OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS` are a small, LangSmith-only\n // allowlist that bypasses the \"first wins\" merge so a nested caller\n // (e.g. a subagent) can override a parent-set value.\n if (\n !Object.prototype.hasOwnProperty.call(metadata, key) ||\n OVERRIDABLE_LANGSMITH_INHERITABLE_METADATA_KEYS.has(key)\n ) {\n if (metadata[key] !== value) {\n metadata[key] = value;\n didPatchMetadata = true;\n }\n }\n }\n if (didPatchMetadata) {\n run.extra.metadata = metadata;\n }\n }\n\n if (tracer.tracingTags.length > 0) {\n run.tags = Array.from(\n new Set([...(run.tags ?? []), ...tracer.tracingTags])\n );\n }\n}\n"],"mappings":"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"}
|
package/dist/utils/env.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.cjs","names":[],"sources":["../../src/utils/env.ts"],"sourcesContent":["// Inlined from https://github.com/flexdinesh/browser-or-node\ndeclare global {\n
|
|
1
|
+
{"version":3,"file":"env.cjs","names":[],"sources":["../../src/utils/env.ts"],"sourcesContent":["// Inlined from https://github.com/flexdinesh/browser-or-node\ndeclare global {\n const Deno:\n | {\n version: {\n deno: string;\n };\n env: {\n get: (name: string) => string | undefined;\n };\n }\n | undefined;\n}\n\nexport const isBrowser = () =>\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isWebWorker = () =>\n typeof globalThis === \"object\" &&\n globalThis.constructor &&\n globalThis.constructor.name === \"DedicatedWorkerGlobalScope\";\n\nexport const isJsDom = () =>\n (typeof window !== \"undefined\" && window.name === \"nodejs\") ||\n (typeof navigator !== \"undefined\" && navigator.userAgent.includes(\"jsdom\"));\n\n// Supabase Edge Function provides a `Deno` global object\n// without `version` property\nexport const isDeno = () => typeof Deno !== \"undefined\";\n\n// Mark not-as-node if in Supabase Edge Function\nexport const isNode = () =>\n typeof process !== \"undefined\" &&\n typeof process.versions !== \"undefined\" &&\n typeof process.versions.node !== \"undefined\" &&\n !isDeno();\n\nexport const getEnv = () => {\n let env: string;\n if (isBrowser()) {\n env = \"browser\";\n } else if (isNode()) {\n env = \"node\";\n } else if (isWebWorker()) {\n env = \"webworker\";\n } else if (isJsDom()) {\n env = \"jsdom\";\n } else if (isDeno()) {\n env = \"deno\";\n } else {\n env = \"other\";\n }\n\n return env;\n};\n\nexport type RuntimeEnvironment = {\n library: string;\n libraryVersion?: string;\n runtime: string;\n runtimeVersion?: string;\n};\n\nlet runtimeEnvironment: RuntimeEnvironment | undefined;\n\nexport function getRuntimeEnvironment(): RuntimeEnvironment {\n if (runtimeEnvironment === undefined) {\n const env = getEnv();\n\n runtimeEnvironment = {\n library: \"langchain-js\",\n runtime: env,\n };\n }\n return runtimeEnvironment;\n}\n\nexport function getEnvironmentVariable(name: string): string | undefined {\n // Certain Deno setups will throw an error if you try to access environment variables\n // https://github.com/langchain-ai/langchainjs/issues/1412\n try {\n if (typeof process !== \"undefined\") {\n // oxlint-disable-next-line no-process-env\n return process.env?.[name];\n } else if (isDeno()) {\n return Deno?.env.get(name);\n } else {\n return undefined;\n }\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAa,kBACX,OAAO,WAAW,eAAe,OAAO,OAAO,aAAa;AAE9D,MAAa,oBACX,OAAO,eAAe,YACtB,WAAW,eACX,WAAW,YAAY,SAAS;AAElC,MAAa,gBACV,OAAO,WAAW,eAAe,OAAO,SAAS,YACjD,OAAO,cAAc,eAAe,UAAU,UAAU,SAAS,OAAO;AAI3E,MAAa,eAAe,OAAO,SAAS;AAG5C,MAAa,eACX,OAAO,YAAY,eACnB,OAAO,QAAQ,aAAa,eAC5B,OAAO,QAAQ,SAAS,SAAS,eACjC,CAAC,OAAO;AAEV,MAAa,eAAe;CAC1B,IAAI;CACJ,IAAI,UAAU,GACZ,MAAM;MACD,IAAI,OAAO,GAChB,MAAM;MACD,IAAI,YAAY,GACrB,MAAM;MACD,IAAI,QAAQ,GACjB,MAAM;MACD,IAAI,OAAO,GAChB,MAAM;MAEN,MAAM;CAGR,OAAO;AACT;AASA,IAAI;AAEJ,SAAgB,wBAA4C;CAC1D,IAAI,uBAAuB,KAAA,GAGzB,qBAAqB;EACnB,SAAS;EACT,SAJU,OAIC;CACb;CAEF,OAAO;AACT;AAEA,SAAgB,uBAAuB,MAAkC;CAGvE,IAAI;EACF,IAAI,OAAO,YAAY,aAErB,OAAO,QAAQ,MAAM;OAChB,IAAI,OAAO,GAChB,OAAO,MAAM,IAAI,IAAI,IAAI;OAEzB;CAEJ,QAAQ;EACN;CACF;AACF"}
|
package/dist/utils/env.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.cts","names":[],"sources":["../../src/utils/env.ts"],"mappings":";QACQ;
|
|
1
|
+
{"version":3,"file":"env.d.cts","names":[],"sources":["../../src/utils/env.ts"],"mappings":";QACQ;QACA;IAEA;MACE;;IAEF;MACE,MAAM;;;;cAMH;cAGA;cAKA;cAMA;cAGA;cAMA;KAmBD;EACV;EACA;EACA;EACA;;iBAKc,yBAAyB;iBAYzB,uBAAuB"}
|
package/dist/utils/env.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","names":[],"sources":["../../src/utils/env.ts"],"mappings":";QACQ;
|
|
1
|
+
{"version":3,"file":"env.d.ts","names":[],"sources":["../../src/utils/env.ts"],"mappings":";QACQ;QACA;IAEA;MACE;;IAEF;MACE,MAAM;;;;cAMH;cAGA;cAKA;cAMA;cAGA;cAMA;KAmBD;EACV;EACA;EACA;EACA;;iBAKc,yBAAyB;iBAYzB,uBAAuB"}
|
package/dist/utils/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","names":[],"sources":["../../src/utils/env.ts"],"sourcesContent":["// Inlined from https://github.com/flexdinesh/browser-or-node\ndeclare global {\n
|
|
1
|
+
{"version":3,"file":"env.js","names":[],"sources":["../../src/utils/env.ts"],"sourcesContent":["// Inlined from https://github.com/flexdinesh/browser-or-node\ndeclare global {\n const Deno:\n | {\n version: {\n deno: string;\n };\n env: {\n get: (name: string) => string | undefined;\n };\n }\n | undefined;\n}\n\nexport const isBrowser = () =>\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isWebWorker = () =>\n typeof globalThis === \"object\" &&\n globalThis.constructor &&\n globalThis.constructor.name === \"DedicatedWorkerGlobalScope\";\n\nexport const isJsDom = () =>\n (typeof window !== \"undefined\" && window.name === \"nodejs\") ||\n (typeof navigator !== \"undefined\" && navigator.userAgent.includes(\"jsdom\"));\n\n// Supabase Edge Function provides a `Deno` global object\n// without `version` property\nexport const isDeno = () => typeof Deno !== \"undefined\";\n\n// Mark not-as-node if in Supabase Edge Function\nexport const isNode = () =>\n typeof process !== \"undefined\" &&\n typeof process.versions !== \"undefined\" &&\n typeof process.versions.node !== \"undefined\" &&\n !isDeno();\n\nexport const getEnv = () => {\n let env: string;\n if (isBrowser()) {\n env = \"browser\";\n } else if (isNode()) {\n env = \"node\";\n } else if (isWebWorker()) {\n env = \"webworker\";\n } else if (isJsDom()) {\n env = \"jsdom\";\n } else if (isDeno()) {\n env = \"deno\";\n } else {\n env = \"other\";\n }\n\n return env;\n};\n\nexport type RuntimeEnvironment = {\n library: string;\n libraryVersion?: string;\n runtime: string;\n runtimeVersion?: string;\n};\n\nlet runtimeEnvironment: RuntimeEnvironment | undefined;\n\nexport function getRuntimeEnvironment(): RuntimeEnvironment {\n if (runtimeEnvironment === undefined) {\n const env = getEnv();\n\n runtimeEnvironment = {\n library: \"langchain-js\",\n runtime: env,\n };\n }\n return runtimeEnvironment;\n}\n\nexport function getEnvironmentVariable(name: string): string | undefined {\n // Certain Deno setups will throw an error if you try to access environment variables\n // https://github.com/langchain-ai/langchainjs/issues/1412\n try {\n if (typeof process !== \"undefined\") {\n // oxlint-disable-next-line no-process-env\n return process.env?.[name];\n } else if (isDeno()) {\n return Deno?.env.get(name);\n } else {\n return undefined;\n }\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAa,kBACX,OAAO,WAAW,eAAe,OAAO,OAAO,aAAa;AAE9D,MAAa,oBACX,OAAO,eAAe,YACtB,WAAW,eACX,WAAW,YAAY,SAAS;AAElC,MAAa,gBACV,OAAO,WAAW,eAAe,OAAO,SAAS,YACjD,OAAO,cAAc,eAAe,UAAU,UAAU,SAAS,OAAO;AAI3E,MAAa,eAAe,OAAO,SAAS;AAG5C,MAAa,eACX,OAAO,YAAY,eACnB,OAAO,QAAQ,aAAa,eAC5B,OAAO,QAAQ,SAAS,SAAS,eACjC,CAAC,OAAO;AAEV,MAAa,eAAe;CAC1B,IAAI;CACJ,IAAI,UAAU,GACZ,MAAM;MACD,IAAI,OAAO,GAChB,MAAM;MACD,IAAI,YAAY,GACrB,MAAM;MACD,IAAI,QAAQ,GACjB,MAAM;MACD,IAAI,OAAO,GAChB,MAAM;MAEN,MAAM;CAGR,OAAO;AACT;AASA,IAAI;AAEJ,SAAgB,wBAA4C;CAC1D,IAAI,uBAAuB,KAAA,GAGzB,qBAAqB;EACnB,SAAS;EACT,SAJU,OAIC;CACb;CAEF,OAAO;AACT;AAEA,SAAgB,uBAAuB,MAAkC;CAGvE,IAAI;EACF,IAAI,OAAO,YAAY,aAErB,OAAO,QAAQ,MAAM;OAChB,IAAI,OAAO,GAChB,OAAO,MAAM,IAAI,IAAI,IAAI;OAEzB;CAEJ,QAAQ;EACN;CACF;AACF"}
|
|
@@ -72,9 +72,7 @@ function getLines(onLine) {
|
|
|
72
72
|
if (fieldLength === -1) fieldLength = position - lineStart;
|
|
73
73
|
break;
|
|
74
74
|
case 13: discardTrailingNewline = true;
|
|
75
|
-
case 10:
|
|
76
|
-
lineEnd = position;
|
|
77
|
-
break;
|
|
75
|
+
case 10: lineEnd = position;
|
|
78
76
|
}
|
|
79
77
|
if (lineEnd === -1) break;
|
|
80
78
|
onLine(buffer.subarray(lineStart, lineEnd), fieldLength);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event_source_parse.cjs","names":["IterableReadableStream"],"sources":["../../src/utils/event_source_parse.ts"],"sourcesContent":["/* oxlint-disable prefer-template */\n/* oxlint-disable default-case */\n// Adapted from https://github.com/gfortaine/fetch-event-source/blob/main/src/parse.ts\n// due to a packaging issue in the original.\n// MIT License\nimport { IterableReadableStream } from \"./stream.js\";\n\nexport const EventStreamContentType = \"text/event-stream\";\n\n/**\n * Represents a message sent in an event stream\n * https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format\n */\nexport interface EventSourceMessage {\n /** The event ID to set the EventSource object's last event ID value. */\n id: string;\n /** A string identifying the type of event described. */\n event: string;\n /** The event data */\n data: string;\n /** The reconnection interval (in milliseconds) to wait before retrying the connection */\n retry?: number;\n}\n\n/**\n * Converts a ReadableStream into a callback pattern.\n * @param stream The input ReadableStream.\n * @param onChunk A function that will be called on each new byte chunk in the stream.\n * @returns {Promise<void>} A promise that will be resolved when the stream closes.\n */\nexport async function getBytes(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n stream: ReadableStream<Uint8Array> | AsyncIterable<any>,\n onChunk: (arr: Uint8Array, flush?: boolean) => void\n) {\n // TODO: Use Async iteration for both cases?\n // oxlint-disable-next-line no-instanceof/no-instanceof\n if (stream instanceof ReadableStream) {\n const reader = stream.getReader();\n // CHANGED: Introduced a \"flush\" mechanism to process potential pending messages when the stream ends.\n // This change is essential to ensure that we capture every last piece of information from streams,\n // such as those from Azure OpenAI, which may not terminate with a blank line. Without this\n // mechanism, we risk ignoring a possibly significant last message.\n // See https://github.com/langchain-ai/langchainjs/issues/1299 for details.\n while (true) {\n const result = await reader.read();\n if (result.done) {\n onChunk(new Uint8Array(), true);\n break;\n }\n onChunk(result.value);\n }\n } else {\n try {\n // Handle Node.js Readable streams with async iteration\n for await (const chunk of stream) {\n onChunk(new Uint8Array(chunk));\n }\n onChunk(new Uint8Array(), true);\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n throw new Error(\n [\n \"Parsing event source stream failed.\",\n \"Ensure your implementation of fetch returns a web or Node readable stream.\",\n `Error: ${e.message}`,\n ].join(\"\\n\")\n );\n }\n }\n}\n\nconst enum ControlChars {\n NewLine = 10,\n CarriageReturn = 13,\n Space = 32,\n Colon = 58,\n}\n\n/**\n * Parses arbitary byte chunks into EventSource line buffers.\n * Each line should be of the format \"field: value\" and ends with \\r, \\n, or \\r\\n.\n * @param onLine A function that will be called on each new EventSource line.\n * @returns A function that should be called for each incoming byte chunk.\n */\nexport function getLines(\n onLine: (line: Uint8Array, fieldLength: number, flush?: boolean) => void\n) {\n let buffer: Uint8Array | undefined;\n let position: number; // current read position\n let fieldLength: number; // length of the `field` portion of the line\n let discardTrailingNewline = false;\n\n // return a function that can process each incoming byte chunk:\n return function onChunk(arr: Uint8Array, flush?: boolean) {\n if (flush) {\n onLine(arr, 0, true);\n return;\n }\n\n if (buffer === undefined) {\n buffer = arr;\n position = 0;\n fieldLength = -1;\n } else {\n // we're still parsing the old line. Append the new bytes into buffer:\n buffer = concat(buffer, arr);\n }\n\n const bufLength = buffer.length;\n let lineStart = 0; // index where the current line starts\n while (position < bufLength) {\n if (discardTrailingNewline) {\n if (buffer[position] === ControlChars.NewLine) {\n lineStart = ++position; // skip to next char\n }\n\n discardTrailingNewline = false;\n }\n\n // start looking forward till the end of line:\n let lineEnd = -1; // index of the \\r or \\n char\n for (; position < bufLength && lineEnd === -1; ++position) {\n switch (buffer[position]) {\n case ControlChars.Colon:\n if (fieldLength === -1) {\n // first colon in line\n fieldLength = position - lineStart;\n }\n break;\n // @ts-expect-error \\r case below should fallthrough to \\n:\n case ControlChars.CarriageReturn:\n discardTrailingNewline = true;\n // oxlint-disable-next-line no-fallthrough\n case ControlChars.NewLine:\n lineEnd = position;\n break;\n }\n }\n\n if (lineEnd === -1) {\n // We reached the end of the buffer but the line hasn't ended.\n // Wait for the next arr and then continue parsing:\n break;\n }\n\n // we've reached the line end, send it out:\n onLine(buffer.subarray(lineStart, lineEnd), fieldLength);\n lineStart = position; // we're now on the next line\n fieldLength = -1;\n }\n\n if (lineStart === bufLength) {\n buffer = undefined; // we've finished reading it\n } else if (lineStart !== 0) {\n // Create a new view into buffer beginning at lineStart so we don't\n // need to copy over the previous lines when we get the new arr:\n buffer = buffer.subarray(lineStart);\n position -= lineStart;\n }\n };\n}\n\n/**\n * Parses line buffers into EventSourceMessages.\n * @param onId A function that will be called on each `id` field.\n * @param onRetry A function that will be called on each `retry` field.\n * @param onMessage A function that will be called on each message.\n * @returns A function that should be called for each incoming line buffer.\n */\nexport function getMessages(\n onMessage?: (msg: EventSourceMessage) => void,\n onId?: (id: string) => void,\n onRetry?: (retry: number) => void\n) {\n let message = newMessage();\n const decoder = new TextDecoder();\n\n // return a function that can process each incoming line buffer:\n return function onLine(\n line: Uint8Array,\n fieldLength: number,\n flush?: boolean\n ) {\n if (flush) {\n if (!isEmpty(message)) {\n onMessage?.(message);\n message = newMessage();\n }\n return;\n }\n\n if (line.length === 0) {\n // empty line denotes end of message. Trigger the callback and start a new message:\n onMessage?.(message);\n message = newMessage();\n } else if (fieldLength > 0) {\n // exclude comments and lines with no values\n // line is of format \"<field>:<value>\" or \"<field>: <value>\"\n // https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation\n const field = decoder.decode(line.subarray(0, fieldLength));\n const valueOffset =\n fieldLength + (line[fieldLength + 1] === ControlChars.Space ? 2 : 1);\n const value = decoder.decode(line.subarray(valueOffset));\n\n switch (field) {\n case \"data\":\n // if this message already has data, append the new value to the old.\n // otherwise, just set to the new value:\n message.data = message.data ? message.data + \"\\n\" + value : value; // otherwise,\n break;\n case \"event\":\n message.event = value;\n break;\n case \"id\":\n onId?.((message.id = value));\n break;\n case \"retry\": {\n const retry = parseInt(value, 10);\n if (!Number.isNaN(retry)) {\n // per spec, ignore non-integers\n onRetry?.((message.retry = retry));\n }\n break;\n }\n }\n }\n };\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array) {\n const res = new Uint8Array(a.length + b.length);\n res.set(a);\n res.set(b, a.length);\n return res;\n}\n\nfunction newMessage(): EventSourceMessage {\n // data, event, and id must be initialized to empty strings:\n // https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation\n // retry should be initialized to undefined so we return a consistent shape\n // to the js engine all the time: https://mathiasbynens.be/notes/shapes-ics#takeaways\n return {\n data: \"\",\n event: \"\",\n id: \"\",\n retry: undefined,\n };\n}\n\nexport function convertEventStreamToIterableReadableDataStream(\n stream: ReadableStream,\n onMetadataEvent?: (e: unknown) => unknown\n) {\n const dataStream = new ReadableStream({\n async start(controller) {\n const enqueueLine = getMessages((msg) => {\n if (msg.event === \"error\") {\n throw new Error(msg.data ?? \"Unspecified event streaming error.\");\n } else if (msg.event === \"metadata\") {\n onMetadataEvent?.(msg);\n } else {\n if (msg.data) controller.enqueue(msg.data);\n }\n });\n const onLine = (\n line: Uint8Array,\n fieldLength: number,\n flush?: boolean\n ) => {\n enqueueLine(line, fieldLength, flush);\n if (flush) controller.close();\n };\n await getBytes(stream, getLines(onLine));\n },\n });\n return IterableReadableStream.fromReadableStream(dataStream);\n}\n\nfunction isEmpty(message: EventSourceMessage): boolean {\n return (\n message.data === \"\" &&\n message.event === \"\" &&\n message.id === \"\" &&\n message.retry === undefined\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"event_source_parse.cjs","names":["IterableReadableStream"],"sources":["../../src/utils/event_source_parse.ts"],"sourcesContent":["/* oxlint-disable prefer-template */\n/* oxlint-disable default-case */\n// Adapted from https://github.com/gfortaine/fetch-event-source/blob/main/src/parse.ts\n// due to a packaging issue in the original.\n// MIT License\nimport { IterableReadableStream } from \"./stream.js\";\n\nexport const EventStreamContentType = \"text/event-stream\";\n\n/**\n * Represents a message sent in an event stream\n * https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format\n */\nexport interface EventSourceMessage {\n /** The event ID to set the EventSource object's last event ID value. */\n id: string;\n /** A string identifying the type of event described. */\n event: string;\n /** The event data */\n data: string;\n /** The reconnection interval (in milliseconds) to wait before retrying the connection */\n retry?: number;\n}\n\n/**\n * Converts a ReadableStream into a callback pattern.\n * @param stream The input ReadableStream.\n * @param onChunk A function that will be called on each new byte chunk in the stream.\n * @returns {Promise<void>} A promise that will be resolved when the stream closes.\n */\nexport async function getBytes(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n stream: ReadableStream<Uint8Array> | AsyncIterable<any>,\n onChunk: (arr: Uint8Array, flush?: boolean) => void\n) {\n // TODO: Use Async iteration for both cases?\n // oxlint-disable-next-line no-instanceof/no-instanceof\n if (stream instanceof ReadableStream) {\n const reader = stream.getReader();\n // CHANGED: Introduced a \"flush\" mechanism to process potential pending messages when the stream ends.\n // This change is essential to ensure that we capture every last piece of information from streams,\n // such as those from Azure OpenAI, which may not terminate with a blank line. Without this\n // mechanism, we risk ignoring a possibly significant last message.\n // See https://github.com/langchain-ai/langchainjs/issues/1299 for details.\n while (true) {\n const result = await reader.read();\n if (result.done) {\n onChunk(new Uint8Array(), true);\n break;\n }\n onChunk(result.value);\n }\n } else {\n try {\n // Handle Node.js Readable streams with async iteration\n for await (const chunk of stream) {\n onChunk(new Uint8Array(chunk));\n }\n onChunk(new Uint8Array(), true);\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n throw new Error(\n [\n \"Parsing event source stream failed.\",\n \"Ensure your implementation of fetch returns a web or Node readable stream.\",\n `Error: ${e.message}`,\n ].join(\"\\n\")\n );\n }\n }\n}\n\nconst enum ControlChars {\n NewLine = 10,\n CarriageReturn = 13,\n Space = 32,\n Colon = 58,\n}\n\n/**\n * Parses arbitary byte chunks into EventSource line buffers.\n * Each line should be of the format \"field: value\" and ends with \\r, \\n, or \\r\\n.\n * @param onLine A function that will be called on each new EventSource line.\n * @returns A function that should be called for each incoming byte chunk.\n */\nexport function getLines(\n onLine: (line: Uint8Array, fieldLength: number, flush?: boolean) => void\n) {\n let buffer: Uint8Array | undefined;\n let position: number; // current read position\n let fieldLength: number; // length of the `field` portion of the line\n let discardTrailingNewline = false;\n\n // return a function that can process each incoming byte chunk:\n return function onChunk(arr: Uint8Array, flush?: boolean) {\n if (flush) {\n onLine(arr, 0, true);\n return;\n }\n\n if (buffer === undefined) {\n buffer = arr;\n position = 0;\n fieldLength = -1;\n } else {\n // we're still parsing the old line. Append the new bytes into buffer:\n buffer = concat(buffer, arr);\n }\n\n const bufLength = buffer.length;\n let lineStart = 0; // index where the current line starts\n while (position < bufLength) {\n if (discardTrailingNewline) {\n if (buffer[position] === ControlChars.NewLine) {\n lineStart = ++position; // skip to next char\n }\n\n discardTrailingNewline = false;\n }\n\n // start looking forward till the end of line:\n let lineEnd = -1; // index of the \\r or \\n char\n for (; position < bufLength && lineEnd === -1; ++position) {\n switch (buffer[position]) {\n case ControlChars.Colon:\n if (fieldLength === -1) {\n // first colon in line\n fieldLength = position - lineStart;\n }\n break;\n // @ts-expect-error \\r case below should fallthrough to \\n:\n case ControlChars.CarriageReturn:\n discardTrailingNewline = true;\n // oxlint-disable-next-line no-fallthrough\n case ControlChars.NewLine:\n lineEnd = position;\n break;\n }\n }\n\n if (lineEnd === -1) {\n // We reached the end of the buffer but the line hasn't ended.\n // Wait for the next arr and then continue parsing:\n break;\n }\n\n // we've reached the line end, send it out:\n onLine(buffer.subarray(lineStart, lineEnd), fieldLength);\n lineStart = position; // we're now on the next line\n fieldLength = -1;\n }\n\n if (lineStart === bufLength) {\n buffer = undefined; // we've finished reading it\n } else if (lineStart !== 0) {\n // Create a new view into buffer beginning at lineStart so we don't\n // need to copy over the previous lines when we get the new arr:\n buffer = buffer.subarray(lineStart);\n position -= lineStart;\n }\n };\n}\n\n/**\n * Parses line buffers into EventSourceMessages.\n * @param onId A function that will be called on each `id` field.\n * @param onRetry A function that will be called on each `retry` field.\n * @param onMessage A function that will be called on each message.\n * @returns A function that should be called for each incoming line buffer.\n */\nexport function getMessages(\n onMessage?: (msg: EventSourceMessage) => void,\n onId?: (id: string) => void,\n onRetry?: (retry: number) => void\n) {\n let message = newMessage();\n const decoder = new TextDecoder();\n\n // return a function that can process each incoming line buffer:\n return function onLine(\n line: Uint8Array,\n fieldLength: number,\n flush?: boolean\n ) {\n if (flush) {\n if (!isEmpty(message)) {\n onMessage?.(message);\n message = newMessage();\n }\n return;\n }\n\n if (line.length === 0) {\n // empty line denotes end of message. Trigger the callback and start a new message:\n onMessage?.(message);\n message = newMessage();\n } else if (fieldLength > 0) {\n // exclude comments and lines with no values\n // line is of format \"<field>:<value>\" or \"<field>: <value>\"\n // https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation\n const field = decoder.decode(line.subarray(0, fieldLength));\n const valueOffset =\n fieldLength + (line[fieldLength + 1] === ControlChars.Space ? 2 : 1);\n const value = decoder.decode(line.subarray(valueOffset));\n\n switch (field) {\n case \"data\":\n // if this message already has data, append the new value to the old.\n // otherwise, just set to the new value:\n message.data = message.data ? message.data + \"\\n\" + value : value; // otherwise,\n break;\n case \"event\":\n message.event = value;\n break;\n case \"id\":\n onId?.((message.id = value));\n break;\n case \"retry\": {\n const retry = parseInt(value, 10);\n if (!Number.isNaN(retry)) {\n // per spec, ignore non-integers\n onRetry?.((message.retry = retry));\n }\n break;\n }\n }\n }\n };\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array) {\n const res = new Uint8Array(a.length + b.length);\n res.set(a);\n res.set(b, a.length);\n return res;\n}\n\nfunction newMessage(): EventSourceMessage {\n // data, event, and id must be initialized to empty strings:\n // https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation\n // retry should be initialized to undefined so we return a consistent shape\n // to the js engine all the time: https://mathiasbynens.be/notes/shapes-ics#takeaways\n return {\n data: \"\",\n event: \"\",\n id: \"\",\n retry: undefined,\n };\n}\n\nexport function convertEventStreamToIterableReadableDataStream(\n stream: ReadableStream,\n onMetadataEvent?: (e: unknown) => unknown\n) {\n const dataStream = new ReadableStream({\n async start(controller) {\n const enqueueLine = getMessages((msg) => {\n if (msg.event === \"error\") {\n throw new Error(msg.data ?? \"Unspecified event streaming error.\");\n } else if (msg.event === \"metadata\") {\n onMetadataEvent?.(msg);\n } else {\n if (msg.data) controller.enqueue(msg.data);\n }\n });\n const onLine = (\n line: Uint8Array,\n fieldLength: number,\n flush?: boolean\n ) => {\n enqueueLine(line, fieldLength, flush);\n if (flush) controller.close();\n };\n await getBytes(stream, getLines(onLine));\n },\n });\n return IterableReadableStream.fromReadableStream(dataStream);\n}\n\nfunction isEmpty(message: EventSourceMessage): boolean {\n return (\n message.data === \"\" &&\n message.event === \"\" &&\n message.id === \"\" &&\n message.retry === undefined\n );\n}\n"],"mappings":"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"}
|
|
@@ -71,9 +71,7 @@ function getLines(onLine) {
|
|
|
71
71
|
if (fieldLength === -1) fieldLength = position - lineStart;
|
|
72
72
|
break;
|
|
73
73
|
case 13: discardTrailingNewline = true;
|
|
74
|
-
case 10:
|
|
75
|
-
lineEnd = position;
|
|
76
|
-
break;
|
|
74
|
+
case 10: lineEnd = position;
|
|
77
75
|
}
|
|
78
76
|
if (lineEnd === -1) break;
|
|
79
77
|
onLine(buffer.subarray(lineStart, lineEnd), fieldLength);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event_source_parse.js","names":[],"sources":["../../src/utils/event_source_parse.ts"],"sourcesContent":["/* oxlint-disable prefer-template */\n/* oxlint-disable default-case */\n// Adapted from https://github.com/gfortaine/fetch-event-source/blob/main/src/parse.ts\n// due to a packaging issue in the original.\n// MIT License\nimport { IterableReadableStream } from \"./stream.js\";\n\nexport const EventStreamContentType = \"text/event-stream\";\n\n/**\n * Represents a message sent in an event stream\n * https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format\n */\nexport interface EventSourceMessage {\n /** The event ID to set the EventSource object's last event ID value. */\n id: string;\n /** A string identifying the type of event described. */\n event: string;\n /** The event data */\n data: string;\n /** The reconnection interval (in milliseconds) to wait before retrying the connection */\n retry?: number;\n}\n\n/**\n * Converts a ReadableStream into a callback pattern.\n * @param stream The input ReadableStream.\n * @param onChunk A function that will be called on each new byte chunk in the stream.\n * @returns {Promise<void>} A promise that will be resolved when the stream closes.\n */\nexport async function getBytes(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n stream: ReadableStream<Uint8Array> | AsyncIterable<any>,\n onChunk: (arr: Uint8Array, flush?: boolean) => void\n) {\n // TODO: Use Async iteration for both cases?\n // oxlint-disable-next-line no-instanceof/no-instanceof\n if (stream instanceof ReadableStream) {\n const reader = stream.getReader();\n // CHANGED: Introduced a \"flush\" mechanism to process potential pending messages when the stream ends.\n // This change is essential to ensure that we capture every last piece of information from streams,\n // such as those from Azure OpenAI, which may not terminate with a blank line. Without this\n // mechanism, we risk ignoring a possibly significant last message.\n // See https://github.com/langchain-ai/langchainjs/issues/1299 for details.\n while (true) {\n const result = await reader.read();\n if (result.done) {\n onChunk(new Uint8Array(), true);\n break;\n }\n onChunk(result.value);\n }\n } else {\n try {\n // Handle Node.js Readable streams with async iteration\n for await (const chunk of stream) {\n onChunk(new Uint8Array(chunk));\n }\n onChunk(new Uint8Array(), true);\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n throw new Error(\n [\n \"Parsing event source stream failed.\",\n \"Ensure your implementation of fetch returns a web or Node readable stream.\",\n `Error: ${e.message}`,\n ].join(\"\\n\")\n );\n }\n }\n}\n\nconst enum ControlChars {\n NewLine = 10,\n CarriageReturn = 13,\n Space = 32,\n Colon = 58,\n}\n\n/**\n * Parses arbitary byte chunks into EventSource line buffers.\n * Each line should be of the format \"field: value\" and ends with \\r, \\n, or \\r\\n.\n * @param onLine A function that will be called on each new EventSource line.\n * @returns A function that should be called for each incoming byte chunk.\n */\nexport function getLines(\n onLine: (line: Uint8Array, fieldLength: number, flush?: boolean) => void\n) {\n let buffer: Uint8Array | undefined;\n let position: number; // current read position\n let fieldLength: number; // length of the `field` portion of the line\n let discardTrailingNewline = false;\n\n // return a function that can process each incoming byte chunk:\n return function onChunk(arr: Uint8Array, flush?: boolean) {\n if (flush) {\n onLine(arr, 0, true);\n return;\n }\n\n if (buffer === undefined) {\n buffer = arr;\n position = 0;\n fieldLength = -1;\n } else {\n // we're still parsing the old line. Append the new bytes into buffer:\n buffer = concat(buffer, arr);\n }\n\n const bufLength = buffer.length;\n let lineStart = 0; // index where the current line starts\n while (position < bufLength) {\n if (discardTrailingNewline) {\n if (buffer[position] === ControlChars.NewLine) {\n lineStart = ++position; // skip to next char\n }\n\n discardTrailingNewline = false;\n }\n\n // start looking forward till the end of line:\n let lineEnd = -1; // index of the \\r or \\n char\n for (; position < bufLength && lineEnd === -1; ++position) {\n switch (buffer[position]) {\n case ControlChars.Colon:\n if (fieldLength === -1) {\n // first colon in line\n fieldLength = position - lineStart;\n }\n break;\n // @ts-expect-error \\r case below should fallthrough to \\n:\n case ControlChars.CarriageReturn:\n discardTrailingNewline = true;\n // oxlint-disable-next-line no-fallthrough\n case ControlChars.NewLine:\n lineEnd = position;\n break;\n }\n }\n\n if (lineEnd === -1) {\n // We reached the end of the buffer but the line hasn't ended.\n // Wait for the next arr and then continue parsing:\n break;\n }\n\n // we've reached the line end, send it out:\n onLine(buffer.subarray(lineStart, lineEnd), fieldLength);\n lineStart = position; // we're now on the next line\n fieldLength = -1;\n }\n\n if (lineStart === bufLength) {\n buffer = undefined; // we've finished reading it\n } else if (lineStart !== 0) {\n // Create a new view into buffer beginning at lineStart so we don't\n // need to copy over the previous lines when we get the new arr:\n buffer = buffer.subarray(lineStart);\n position -= lineStart;\n }\n };\n}\n\n/**\n * Parses line buffers into EventSourceMessages.\n * @param onId A function that will be called on each `id` field.\n * @param onRetry A function that will be called on each `retry` field.\n * @param onMessage A function that will be called on each message.\n * @returns A function that should be called for each incoming line buffer.\n */\nexport function getMessages(\n onMessage?: (msg: EventSourceMessage) => void,\n onId?: (id: string) => void,\n onRetry?: (retry: number) => void\n) {\n let message = newMessage();\n const decoder = new TextDecoder();\n\n // return a function that can process each incoming line buffer:\n return function onLine(\n line: Uint8Array,\n fieldLength: number,\n flush?: boolean\n ) {\n if (flush) {\n if (!isEmpty(message)) {\n onMessage?.(message);\n message = newMessage();\n }\n return;\n }\n\n if (line.length === 0) {\n // empty line denotes end of message. Trigger the callback and start a new message:\n onMessage?.(message);\n message = newMessage();\n } else if (fieldLength > 0) {\n // exclude comments and lines with no values\n // line is of format \"<field>:<value>\" or \"<field>: <value>\"\n // https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation\n const field = decoder.decode(line.subarray(0, fieldLength));\n const valueOffset =\n fieldLength + (line[fieldLength + 1] === ControlChars.Space ? 2 : 1);\n const value = decoder.decode(line.subarray(valueOffset));\n\n switch (field) {\n case \"data\":\n // if this message already has data, append the new value to the old.\n // otherwise, just set to the new value:\n message.data = message.data ? message.data + \"\\n\" + value : value; // otherwise,\n break;\n case \"event\":\n message.event = value;\n break;\n case \"id\":\n onId?.((message.id = value));\n break;\n case \"retry\": {\n const retry = parseInt(value, 10);\n if (!Number.isNaN(retry)) {\n // per spec, ignore non-integers\n onRetry?.((message.retry = retry));\n }\n break;\n }\n }\n }\n };\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array) {\n const res = new Uint8Array(a.length + b.length);\n res.set(a);\n res.set(b, a.length);\n return res;\n}\n\nfunction newMessage(): EventSourceMessage {\n // data, event, and id must be initialized to empty strings:\n // https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation\n // retry should be initialized to undefined so we return a consistent shape\n // to the js engine all the time: https://mathiasbynens.be/notes/shapes-ics#takeaways\n return {\n data: \"\",\n event: \"\",\n id: \"\",\n retry: undefined,\n };\n}\n\nexport function convertEventStreamToIterableReadableDataStream(\n stream: ReadableStream,\n onMetadataEvent?: (e: unknown) => unknown\n) {\n const dataStream = new ReadableStream({\n async start(controller) {\n const enqueueLine = getMessages((msg) => {\n if (msg.event === \"error\") {\n throw new Error(msg.data ?? \"Unspecified event streaming error.\");\n } else if (msg.event === \"metadata\") {\n onMetadataEvent?.(msg);\n } else {\n if (msg.data) controller.enqueue(msg.data);\n }\n });\n const onLine = (\n line: Uint8Array,\n fieldLength: number,\n flush?: boolean\n ) => {\n enqueueLine(line, fieldLength, flush);\n if (flush) controller.close();\n };\n await getBytes(stream, getLines(onLine));\n },\n });\n return IterableReadableStream.fromReadableStream(dataStream);\n}\n\nfunction isEmpty(message: EventSourceMessage): boolean {\n return (\n message.data === \"\" &&\n message.event === \"\" &&\n message.id === \"\" &&\n message.retry === undefined\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"event_source_parse.js","names":[],"sources":["../../src/utils/event_source_parse.ts"],"sourcesContent":["/* oxlint-disable prefer-template */\n/* oxlint-disable default-case */\n// Adapted from https://github.com/gfortaine/fetch-event-source/blob/main/src/parse.ts\n// due to a packaging issue in the original.\n// MIT License\nimport { IterableReadableStream } from \"./stream.js\";\n\nexport const EventStreamContentType = \"text/event-stream\";\n\n/**\n * Represents a message sent in an event stream\n * https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format\n */\nexport interface EventSourceMessage {\n /** The event ID to set the EventSource object's last event ID value. */\n id: string;\n /** A string identifying the type of event described. */\n event: string;\n /** The event data */\n data: string;\n /** The reconnection interval (in milliseconds) to wait before retrying the connection */\n retry?: number;\n}\n\n/**\n * Converts a ReadableStream into a callback pattern.\n * @param stream The input ReadableStream.\n * @param onChunk A function that will be called on each new byte chunk in the stream.\n * @returns {Promise<void>} A promise that will be resolved when the stream closes.\n */\nexport async function getBytes(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n stream: ReadableStream<Uint8Array> | AsyncIterable<any>,\n onChunk: (arr: Uint8Array, flush?: boolean) => void\n) {\n // TODO: Use Async iteration for both cases?\n // oxlint-disable-next-line no-instanceof/no-instanceof\n if (stream instanceof ReadableStream) {\n const reader = stream.getReader();\n // CHANGED: Introduced a \"flush\" mechanism to process potential pending messages when the stream ends.\n // This change is essential to ensure that we capture every last piece of information from streams,\n // such as those from Azure OpenAI, which may not terminate with a blank line. Without this\n // mechanism, we risk ignoring a possibly significant last message.\n // See https://github.com/langchain-ai/langchainjs/issues/1299 for details.\n while (true) {\n const result = await reader.read();\n if (result.done) {\n onChunk(new Uint8Array(), true);\n break;\n }\n onChunk(result.value);\n }\n } else {\n try {\n // Handle Node.js Readable streams with async iteration\n for await (const chunk of stream) {\n onChunk(new Uint8Array(chunk));\n }\n onChunk(new Uint8Array(), true);\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n throw new Error(\n [\n \"Parsing event source stream failed.\",\n \"Ensure your implementation of fetch returns a web or Node readable stream.\",\n `Error: ${e.message}`,\n ].join(\"\\n\")\n );\n }\n }\n}\n\nconst enum ControlChars {\n NewLine = 10,\n CarriageReturn = 13,\n Space = 32,\n Colon = 58,\n}\n\n/**\n * Parses arbitary byte chunks into EventSource line buffers.\n * Each line should be of the format \"field: value\" and ends with \\r, \\n, or \\r\\n.\n * @param onLine A function that will be called on each new EventSource line.\n * @returns A function that should be called for each incoming byte chunk.\n */\nexport function getLines(\n onLine: (line: Uint8Array, fieldLength: number, flush?: boolean) => void\n) {\n let buffer: Uint8Array | undefined;\n let position: number; // current read position\n let fieldLength: number; // length of the `field` portion of the line\n let discardTrailingNewline = false;\n\n // return a function that can process each incoming byte chunk:\n return function onChunk(arr: Uint8Array, flush?: boolean) {\n if (flush) {\n onLine(arr, 0, true);\n return;\n }\n\n if (buffer === undefined) {\n buffer = arr;\n position = 0;\n fieldLength = -1;\n } else {\n // we're still parsing the old line. Append the new bytes into buffer:\n buffer = concat(buffer, arr);\n }\n\n const bufLength = buffer.length;\n let lineStart = 0; // index where the current line starts\n while (position < bufLength) {\n if (discardTrailingNewline) {\n if (buffer[position] === ControlChars.NewLine) {\n lineStart = ++position; // skip to next char\n }\n\n discardTrailingNewline = false;\n }\n\n // start looking forward till the end of line:\n let lineEnd = -1; // index of the \\r or \\n char\n for (; position < bufLength && lineEnd === -1; ++position) {\n switch (buffer[position]) {\n case ControlChars.Colon:\n if (fieldLength === -1) {\n // first colon in line\n fieldLength = position - lineStart;\n }\n break;\n // @ts-expect-error \\r case below should fallthrough to \\n:\n case ControlChars.CarriageReturn:\n discardTrailingNewline = true;\n // oxlint-disable-next-line no-fallthrough\n case ControlChars.NewLine:\n lineEnd = position;\n break;\n }\n }\n\n if (lineEnd === -1) {\n // We reached the end of the buffer but the line hasn't ended.\n // Wait for the next arr and then continue parsing:\n break;\n }\n\n // we've reached the line end, send it out:\n onLine(buffer.subarray(lineStart, lineEnd), fieldLength);\n lineStart = position; // we're now on the next line\n fieldLength = -1;\n }\n\n if (lineStart === bufLength) {\n buffer = undefined; // we've finished reading it\n } else if (lineStart !== 0) {\n // Create a new view into buffer beginning at lineStart so we don't\n // need to copy over the previous lines when we get the new arr:\n buffer = buffer.subarray(lineStart);\n position -= lineStart;\n }\n };\n}\n\n/**\n * Parses line buffers into EventSourceMessages.\n * @param onId A function that will be called on each `id` field.\n * @param onRetry A function that will be called on each `retry` field.\n * @param onMessage A function that will be called on each message.\n * @returns A function that should be called for each incoming line buffer.\n */\nexport function getMessages(\n onMessage?: (msg: EventSourceMessage) => void,\n onId?: (id: string) => void,\n onRetry?: (retry: number) => void\n) {\n let message = newMessage();\n const decoder = new TextDecoder();\n\n // return a function that can process each incoming line buffer:\n return function onLine(\n line: Uint8Array,\n fieldLength: number,\n flush?: boolean\n ) {\n if (flush) {\n if (!isEmpty(message)) {\n onMessage?.(message);\n message = newMessage();\n }\n return;\n }\n\n if (line.length === 0) {\n // empty line denotes end of message. Trigger the callback and start a new message:\n onMessage?.(message);\n message = newMessage();\n } else if (fieldLength > 0) {\n // exclude comments and lines with no values\n // line is of format \"<field>:<value>\" or \"<field>: <value>\"\n // https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation\n const field = decoder.decode(line.subarray(0, fieldLength));\n const valueOffset =\n fieldLength + (line[fieldLength + 1] === ControlChars.Space ? 2 : 1);\n const value = decoder.decode(line.subarray(valueOffset));\n\n switch (field) {\n case \"data\":\n // if this message already has data, append the new value to the old.\n // otherwise, just set to the new value:\n message.data = message.data ? message.data + \"\\n\" + value : value; // otherwise,\n break;\n case \"event\":\n message.event = value;\n break;\n case \"id\":\n onId?.((message.id = value));\n break;\n case \"retry\": {\n const retry = parseInt(value, 10);\n if (!Number.isNaN(retry)) {\n // per spec, ignore non-integers\n onRetry?.((message.retry = retry));\n }\n break;\n }\n }\n }\n };\n}\n\nfunction concat(a: Uint8Array, b: Uint8Array) {\n const res = new Uint8Array(a.length + b.length);\n res.set(a);\n res.set(b, a.length);\n return res;\n}\n\nfunction newMessage(): EventSourceMessage {\n // data, event, and id must be initialized to empty strings:\n // https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation\n // retry should be initialized to undefined so we return a consistent shape\n // to the js engine all the time: https://mathiasbynens.be/notes/shapes-ics#takeaways\n return {\n data: \"\",\n event: \"\",\n id: \"\",\n retry: undefined,\n };\n}\n\nexport function convertEventStreamToIterableReadableDataStream(\n stream: ReadableStream,\n onMetadataEvent?: (e: unknown) => unknown\n) {\n const dataStream = new ReadableStream({\n async start(controller) {\n const enqueueLine = getMessages((msg) => {\n if (msg.event === \"error\") {\n throw new Error(msg.data ?? \"Unspecified event streaming error.\");\n } else if (msg.event === \"metadata\") {\n onMetadataEvent?.(msg);\n } else {\n if (msg.data) controller.enqueue(msg.data);\n }\n });\n const onLine = (\n line: Uint8Array,\n fieldLength: number,\n flush?: boolean\n ) => {\n enqueueLine(line, fieldLength, flush);\n if (flush) controller.close();\n };\n await getBytes(stream, getLines(onLine));\n },\n });\n return IterableReadableStream.fromReadableStream(dataStream);\n}\n\nfunction isEmpty(message: EventSourceMessage): boolean {\n return (\n message.data === \"\" &&\n message.event === \"\" &&\n message.id === \"\" &&\n message.retry === undefined\n );\n}\n"],"mappings":"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"}
|
|
@@ -140,8 +140,10 @@ function getValueByPointer(document, pointer) {
|
|
|
140
140
|
* @return `{newDocument, result}` after the operation
|
|
141
141
|
*/
|
|
142
142
|
function applyOperation(document, operation, validateOperation = false, mutateDocument = true, banPrototypeModifications = true, index = 0) {
|
|
143
|
-
if (validateOperation)
|
|
144
|
-
|
|
143
|
+
if (validateOperation) {
|
|
144
|
+
if (typeof validateOperation == "function") validateOperation(operation, 0, document, operation.path);
|
|
145
|
+
else validator(operation, 0);
|
|
146
|
+
}
|
|
145
147
|
if (operation.path === "") {
|
|
146
148
|
let returnValue = { newDocument: document };
|
|
147
149
|
if (operation.op === "add") {
|