diff --git a/js/package.json b/js/package.json index 7b833e87c..2962995d5 100644 --- a/js/package.json +++ b/js/package.json @@ -109,20 +109,21 @@ "uuid": "^10.0.0" }, "devDependencies": { - "@ai-sdk/openai": "^0.0.68", + "@ai-sdk/openai": "^1.0.13", "@babel/preset-env": "^7.22.4", "@faker-js/faker": "^8.4.1", "@jest/globals": "^29.5.0", "@langchain/core": "^0.3.14", "@langchain/langgraph": "^0.2.20", "@langchain/openai": "^0.3.11", + "@opentelemetry/api": "^1.9.0", "@opentelemetry/sdk-trace-base": "^1.26.0", "@opentelemetry/sdk-trace-node": "^1.26.0", "@tsconfig/recommended": "^1.0.2", "@types/jest": "^29.5.1", "@typescript-eslint/eslint-plugin": "^5.59.8", "@typescript-eslint/parser": "^5.59.8", - "ai": "^3.4.17", + "ai": "^4.0.27", "babel-jest": "^29.5.0", "cross-env": "^7.0.3", "dotenv": "^16.1.3", diff --git a/js/src/tests/vercel.int.test.ts b/js/src/tests/vercel.int.test.ts index 28a2280be..f3232f1df 100644 --- a/js/src/tests/vercel.int.test.ts +++ b/js/src/tests/vercel.int.test.ts @@ -102,7 +102,7 @@ test("generateText with image", async () => { expect(storedRun.id).toEqual(runId); }); -test.skip("streamText", async () => { +test("streamText", async () => { const runId = uuid(); const result = await streamText({ model: openai("gpt-4o-mini"), @@ -234,9 +234,7 @@ test("traceable", async () => { async () => { return "bar"; }, - { - name: "foo", - } + { name: "foo" } ); await foo(); @@ -254,6 +252,64 @@ test("traceable", async () => { expect(storedRun.outputs).toEqual(result); }); +test("nested generateText", async () => { + const runId = uuid(); + const childRunId = uuid(); + + await generateText({ + model: openai("gpt-4o-mini"), + messages: [ + { + role: "user", + content: "What are my orders and where are they? My user ID is 123", + }, + ], + tools: { + listOrders: tool({ + description: "list all orders", + parameters: z.object({ userId: z.string() }), + execute: async ({ userId }) => + `User ${userId} has the following orders: 1`, + }), + viewTrackingInformation: tool({ + description: "view tracking information for a specific order", + parameters: z.object({ orderId: z.string() }), + execute: async ({ orderId }) => + await generateText({ + model: openai("gpt-4o-mini"), + experimental_telemetry: AISDKExporter.getSettings({ + isEnabled: true, + runId: childRunId, + }), + messages: [ + { + role: "user", + content: `Generate a random tracking information, include order ID ${orderId}`, + }, + ], + }), + }), + }, + experimental_telemetry: AISDKExporter.getSettings({ + isEnabled: true, + runId, + functionId: "functionId", + metadata: { userId: "123", language: "english" }, + }), + maxSteps: 10, + }); + + await provider.forceFlush(); + await waitUntilRunFound(client, runId, true); + + const storedRun = await client.readRun(runId); + expect(storedRun.id).toEqual(runId); + + await waitUntilRunFound(client, childRunId, true); + const storedChildRun = await client.readRun(childRunId); + expect(storedChildRun.id).toEqual(childRunId); +}); + afterAll(async () => { await provider.shutdown(); }); diff --git a/js/src/tests/vercel.test.ts b/js/src/tests/vercel.test.ts index 9c7c78fa0..2846af12e 100644 --- a/js/src/tests/vercel.test.ts +++ b/js/src/tests/vercel.test.ts @@ -1,6 +1,7 @@ import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node"; import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base"; - +import { context, trace } from "@opentelemetry/api"; +import { v4 as uuidv4 } from "uuid"; import { generateText, streamText, @@ -940,3 +941,117 @@ test("traceable", async () => { }, }); }); + +test("unrelated spans around", async () => { + const tracer = provider.getTracer("test"); + + const inner = async () => { + const span = tracer.startSpan("inner-unrelated"); + const ctx = trace.setSpan(context.active(), span); + + await context.with(ctx, async () => { + await generateText({ + model: new MockMultiStepLanguageModelV1({ + provider: "inner-model", + doGenerate: async () => { + return { + rawCall: { rawPrompt: null, rawSettings: {} }, + finishReason: "stop", + usage: { promptTokens: 10, completionTokens: 20 }, + text: `Hello, world!`, + }; + }, + }), + messages: [{ role: "user", content: "Hello" }], + experimental_telemetry: AISDKExporter.getSettings({ + isEnabled: true, + metadata: { userId: "123" }, + }), + }); + }); + + span.end(); + }; + + const rootRunId = uuidv4(); + + const outer = async () => { + const span = tracer.startSpan("outer-unrelated"); + const ctx = trace.setSpan(context.active(), span); + + const model = new MockMultiStepLanguageModelV1({ + provider: "outer-model", + doGenerate: async () => { + if (model.generateStep === 0) { + return { + rawCall: { rawPrompt: null, rawSettings: {} }, + finishReason: "stop", + usage: { promptTokens: 10, completionTokens: 20 }, + toolCalls: [ + { + toolCallType: "function", + toolName: "callInner", + toolCallId: "tool-id", + args: JSON.stringify({}), + }, + ], + }; + } + + return { + rawCall: { rawPrompt: null, rawSettings: {} }, + finishReason: "stop", + usage: { promptTokens: 10, completionTokens: 20 }, + text: `Hello, world!`, + }; + }, + }); + + await context.with(ctx, async () => { + await generateText({ + model, + tools: { + callInner: tool({ + description: "call inner", + parameters: z.object({}), + execute: inner, + }), + }, + messages: [{ role: "user", content: "Nested call" }], + experimental_telemetry: AISDKExporter.getSettings({ + isEnabled: true, + runName: "outer", + runId: rootRunId, + }), + maxSteps: 10, + }); + }); + + span.end(); + }; + + await outer(); + await provider.forceFlush(); + + const actual = getAssumedTreeFromCalls(callSpy.mock.calls); + expect(actual).toMatchObject({ + nodes: [ + "outer:0", + "outer-model:1", + "callInner:2", + "outer-model:3", + "inner-model:4", + "inner-model:5", + ], + edges: [ + ["outer:0", "outer-model:1"], + ["outer:0", "callInner:2"], + ["outer:0", "outer-model:3"], + ["callInner:2", "inner-model:4"], + ["inner-model:4", "inner-model:5"], + ], + data: { + "outer:0": { id: rootRunId }, + }, + }); +}); diff --git a/js/src/tests/wrapped_ai_sdk.int.test.ts b/js/src/tests/wrapped_ai_sdk.int.test.ts index fc97a44b7..5f32f3671 100644 --- a/js/src/tests/wrapped_ai_sdk.int.test.ts +++ b/js/src/tests/wrapped_ai_sdk.int.test.ts @@ -35,7 +35,7 @@ test("AI SDK generateText with a tool", async () => { JSON.stringify(["pasta", "tomato", "cheese", "onions"]), }), }, - maxToolRoundtrips: 2, + maxSteps: 2, }); DEBUG && console.log(text); }); diff --git a/js/src/vercel.ts b/js/src/vercel.ts index c5da1f950..18d6ce731 100644 --- a/js/src/vercel.ts +++ b/js/src/vercel.ts @@ -7,7 +7,7 @@ import type { import type { AISDKSpan } from "./vercel.types.js"; import { Client, RunTree } from "./index.js"; import { KVMap, RunCreate } from "./schemas.js"; -import { v5 as uuid5, v4 as uuid4 } from "uuid"; +import { v5 as uuid5 } from "uuid"; import { getCurrentRunTree } from "./singletons/traceable.js"; import { getLangSmithEnvironmentVariable, @@ -183,17 +183,25 @@ function stripNonAlphanumeric(input: string) { return input.replace(/[-:.]/g, ""); } -function convertToDottedOrderFormat( - [seconds, nanoseconds]: [seconds: number, nanoseconds: number], - runId: string, - executionOrder: number -) { +function getDotOrder(item: { + startTime: [seconds: number, nanoseconds: number]; + id: string; + executionOrder: number; +}): string { + const { + startTime: [seconds, nanoseconds], + id: runId, + executionOrder, + } = item; + // Date only has millisecond precision, so we use the microseconds to break // possible ties, avoiding incorrect run order - const ms = Number(String(nanoseconds).slice(0, 3)); - const ns = String(Number(String(nanoseconds).slice(3, 6)) + executionOrder) - .padStart(3, "0") - .slice(0, 3); + const nanosecondString = String(nanoseconds).padStart(9, "0"); + const msFull = Number(nanosecondString.slice(0, 6)) + executionOrder; + const msString = String(msFull).padStart(6, "0"); + + const ms = Number(msString.slice(0, -3)); + const ns = msString.slice(-3); return ( stripNonAlphanumeric( @@ -202,6 +210,59 @@ function convertToDottedOrderFormat( ); } +function joinDotOrder(...segments: (string | undefined | null)[]): string { + return segments.filter(Boolean).join("."); +} + +function removeDotOrder(dotOrder: string, ...ids: string[]): string { + return dotOrder + .split(".") + .filter((i) => !ids.some((id) => i.includes(id))) + .join("."); +} + +function reparentDotOrder( + dotOrder: string, + sourceRunId: string, + parentDotOrder: string +): string { + const segments = dotOrder.split("."); + const sourceIndex = segments.findIndex((i) => i.includes(sourceRunId)); + + if (sourceIndex === -1) return dotOrder; + return joinDotOrder( + ...parentDotOrder.split("."), + ...segments.slice(sourceIndex) + ); +} + +interface MutableRunCreate { + id: string; + trace_id: string; + dotted_order: string; + parent_run_id: string | undefined; +} + +function getMutableRunCreate(dotOrder: string): MutableRunCreate { + const segments = dotOrder.split(".").map((i) => { + const [startTime, runId] = i.split("Z"); + return { startTime, runId }; + }); + + const traceId = segments[0].runId; + const parentRunId = segments.at(-2)?.runId; + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const runId = segments.at(-1)!.runId; + + return { + id: runId, + trace_id: traceId, + dotted_order: dotOrder, + parent_run_id: parentRunId, + }; +} + function convertToTimestamp([seconds, nanoseconds]: [ seconds: number, nanoseconds: number @@ -248,18 +309,25 @@ const RESERVED_METADATA_KEYS = [ BAGGAGE_METADATA_KEY.output, ]; +type PostProcessAction = + | { type: "delete"; runId: string } + | { type: "reparent"; runId: string; parentDotOrder: string } + | { type: "rename"; sourceRunId: string; targetRunId: string }; + interface RunTask { id: string; - parentId: string | undefined; + executionOrder: number; startTime: [seconds: number, nanoseconds: number]; - run: RunCreate; + + run: RunCreate | undefined; + + interop: InteropType | undefined; sent: boolean; - executionOrder: number; } type InteropType = | { type: "traceable"; parentRunTree: RunTree } - | { type: "user"; userTraceId?: string } + | { type: "user"; userRunId: string } | undefined; /** @@ -310,7 +378,6 @@ export class AISDKExporter { childMap: Record; nodeMap: Record; relativeExecutionOrder: Record; - interop?: InteropType; } > = {}; @@ -372,6 +439,8 @@ export class AISDKExporter { /** @internal */ protected parseInteropFromMetadata(span: AISDKSpan): InteropType { + if (!this.isRootRun(span)) return undefined; + const userTraceId = this.getSpanAttributeKey( span, RUN_ID_METADATA_KEY.output @@ -399,17 +468,12 @@ export class AISDKExporter { return { type: "traceable", parentRunTree }; } - if (userTraceId) return { type: "user", userTraceId }; + if (userTraceId) return { type: "user", userRunId: userTraceId }; return undefined; } /** @internal */ protected getRunCreate(span: AISDKSpan): RunCreate | undefined { - const runId = uuid5(span.spanContext().spanId, RUN_ID_NAMESPACE); - const parentRunId = span.parentSpanId - ? uuid5(span.parentSpanId, RUN_ID_NAMESPACE) - : undefined; - const asRunCreate = (rawConfig: RunCreate) => { const aiMetadata = Object.keys(span.attributes) .filter( @@ -448,8 +512,6 @@ export class AISDKExporter { const config: RunCreate = { ...rawConfig, name, - id: runId, - parent_run_id: parentRunId, extra: { ...rawConfig.extra, metadata: { @@ -732,62 +794,41 @@ export class AISDKExporter { }; const runId = uuid5(spanId, RUN_ID_NAMESPACE); - let parentRunId = parentId + const parentRunId = parentId ? uuid5(parentId, RUN_ID_NAMESPACE) : undefined; - // in LangSmith we currently only support certain spans - // which may be deeply nested within other traces - if (this.isRootRun(span)) parentRunId = undefined; const traceMap = this.traceByMap[traceId]; - const run = this.getRunCreate(span); - if (!run) { - this.logDebug("skipping span", span); - continue; - } traceMap.relativeExecutionOrder[parentRunId ?? ROOT] ??= -1; traceMap.relativeExecutionOrder[parentRunId ?? ROOT] += 1; traceMap.nodeMap[runId] ??= { id: runId, - parentId: parentRunId, startTime: span.startTime, run, sent: false, + interop: this.parseInteropFromMetadata(span), executionOrder: traceMap.relativeExecutionOrder[parentRunId ?? ROOT], }; if (this.debug) console.log(`[${span.name}] ${runId}`, run); traceMap.childMap[parentRunId ?? ROOT] ??= []; traceMap.childMap[parentRunId ?? ROOT].push(traceMap.nodeMap[runId]); - traceMap.interop = this.parseInteropFromMetadata(span); } - type OverrideRunCreate = { - id: string; - trace_id: string; - dotted_order: string; - parent_run_id: string | undefined; - }; - - // We separate `id`, - const sampled: [OverrideRunCreate, RunCreate][] = []; + const sampled: RunCreate[] = []; + const actions: PostProcessAction[] = []; for (const traceId of Object.keys(this.traceByMap)) { - type QueueItem = { item: RunTask; dottedOrder: string; traceId: string }; + type QueueItem = { dotOrder: string; item: RunTask }; const traceMap = this.traceByMap[traceId]; const queue: QueueItem[] = traceMap.childMap[ROOT]?.map((item) => ({ item, - dottedOrder: convertToDottedOrderFormat( - item.startTime, - item.id, - item.executionOrder - ), - traceId: item.id, + dotOrder: getDotOrder(item), })) ?? []; const seen = new Set(); @@ -797,85 +838,68 @@ export class AISDKExporter { if (seen.has(task.item.id)) continue; if (!task.item.sent) { - let override: OverrideRunCreate = { - id: task.item.id, - parent_run_id: task.item.parentId, - dotted_order: task.dottedOrder, - trace_id: task.traceId, - }; + if (task.item.run != null) { + if (task.item.interop?.type === "user") { + actions.push({ + type: "rename", + sourceRunId: task.item.id, + targetRunId: task.item.interop.userRunId, + }); + } - if (traceMap.interop) { - // attach the run to a parent run tree - // - id: preserve - // - parent_run_id: use existing parent run id or hook to the provided run tree - // - dotted_order: append to the dotted_order of the parent run tree - // - trace_id: use from the existing run tree - if (traceMap.interop.type === "traceable") { - override = { - id: override.id, - parent_run_id: - override.parent_run_id ?? traceMap.interop.parentRunTree.id, - dotted_order: [ - traceMap.interop.parentRunTree.dotted_order, - override.dotted_order, - ] - .filter(Boolean) - .join("."), - trace_id: traceMap.interop.parentRunTree.trace_id, - }; - } else if (traceMap.interop.type === "user") { - // Allow user to specify custom trace ID = run ID of the root run - // - id: use user provided run ID if root run, otherwise preserve - // - parent_run_id: use user provided run ID if root run, otherwise preserve - // - dotted_order: replace the trace_id with the user provided run ID - // - trace_id: use user provided run ID - const userTraceId = traceMap.interop.userTraceId ?? uuid4(); - override = { - id: - override.id === override.trace_id ? userTraceId : override.id, - parent_run_id: - override.parent_run_id === override.trace_id - ? userTraceId - : override.parent_run_id, - dotted_order: override.dotted_order.replace( - override.trace_id, - userTraceId - ), - trace_id: userTraceId, - }; + if (task.item.interop?.type === "traceable") { + actions.push({ + type: "reparent", + runId: task.item.id, + parentDotOrder: task.item.interop.parentRunTree.dotted_order, + }); + } + + let dotOrder = task.dotOrder; + for (const action of actions) { + if (action.type === "delete") { + dotOrder = removeDotOrder(dotOrder, action.runId); + } + + if (action.type === "reparent") { + dotOrder = reparentDotOrder( + dotOrder, + action.runId, + action.parentDotOrder + ); + } + + if (action.type === "rename") { + dotOrder = dotOrder.replace( + action.sourceRunId, + action.targetRunId + ); + } } + + sampled.push({ + ...task.item.run, + ...getMutableRunCreate(dotOrder), + }); + } else { + actions.push({ type: "delete", runId: task.item.id }); } - sampled.push([override, task.item.run]); task.item.sent = true; } const children = traceMap.childMap[task.item.id] ?? []; queue.push( - ...children.map((child) => { - return { - item: child, - dottedOrder: [ - task.dottedOrder, - convertToDottedOrderFormat( - child.startTime, - child.id, - child.executionOrder - ), - ].join("."), - traceId: task.traceId, - }; - }) + ...children.map((item) => ({ + item, + dotOrder: joinDotOrder(task.dotOrder, getDotOrder(item)), + })) ); } } this.logDebug(`sampled runs to be sent to LangSmith`, sampled); - Promise.all( - sampled.map(([override, value]) => - this.client.createRun({ ...value, ...override }) - ) - ).then( + Promise.all(sampled.map((run) => this.client.createRun(run))).then( () => resultCallback({ code: 0 }), (error) => resultCallback({ code: 1, error }) ); @@ -884,9 +908,10 @@ export class AISDKExporter { async shutdown(): Promise { // find nodes which are incomplete const incompleteNodes = Object.values(this.traceByMap).flatMap((trace) => - Object.values(trace.nodeMap).filter((i) => !i.sent) + Object.values(trace.nodeMap).filter((i) => !i.sent && i.run != null) ); - this.logDebug("shutting down", { incompleteNodes: incompleteNodes.length }); + + this.logDebug("shutting down", { incompleteNodes }); if (incompleteNodes.length > 0) { console.warn( diff --git a/js/yarn.lock b/js/yarn.lock index 1c7b89807..a5e15453f 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -2,76 +2,49 @@ # yarn lockfile v1 -"@ai-sdk/openai@^0.0.68": - version "0.0.68" - resolved "https://registry.yarnpkg.com/@ai-sdk/openai/-/openai-0.0.68.tgz#7507534a217355273651ad2ea0fffd6e208587ea" - integrity sha512-WSzB7qpBTrnYvFbnBBmIsw1G8GM04JRMr+I7B5T7msgZfleG4cTvVrn9A1HeHHw9TmbKiaCKJrEZH4V0lb7jNQ== - dependencies: - "@ai-sdk/provider" "0.0.24" - "@ai-sdk/provider-utils" "1.0.20" - -"@ai-sdk/provider-utils@1.0.20": - version "1.0.20" - resolved "https://registry.yarnpkg.com/@ai-sdk/provider-utils/-/provider-utils-1.0.20.tgz#46175945dc32ad2d76cb5447738bcac3ad59dbcb" - integrity sha512-ngg/RGpnA00eNOWEtXHenpX1MsM2QshQh4QJFjUfwcqHpM5kTfG7je7Rc3HcEDP+OkRVv2GF+X4fC1Vfcnl8Ow== - dependencies: - "@ai-sdk/provider" "0.0.24" - eventsource-parser "1.1.2" - nanoid "3.3.6" - secure-json-parse "2.7.0" - -"@ai-sdk/provider@0.0.24": - version "0.0.24" - resolved "https://registry.yarnpkg.com/@ai-sdk/provider/-/provider-0.0.24.tgz#e794f4255a833c47aeffcd8f6808a79b2a6b1f06" - integrity sha512-XMsNGJdGO+L0cxhhegtqZ8+T6nn4EoShS819OvCgI2kLbYTIvk0GWFGD0AXJmxkxs3DrpsJxKAFukFR7bvTkgQ== - dependencies: - json-schema "0.4.0" - -"@ai-sdk/react@0.0.64": - version "0.0.64" - resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-0.0.64.tgz#921d1dc53c98b7c3488a2099d2b67f6573c83e92" - integrity sha512-4LN2vleyA6rYHZ4Rk9CdxnJgaVkNPJDD4Wx1brUhc5RvUxj3TODcm2UwGOR/mxv4pcydtZGELfQQs/i/tkAUCw== - dependencies: - "@ai-sdk/provider-utils" "1.0.20" - "@ai-sdk/ui-utils" "0.0.46" - swr "2.2.5" - -"@ai-sdk/solid@0.0.50": - version "0.0.50" - resolved "https://registry.yarnpkg.com/@ai-sdk/solid/-/solid-0.0.50.tgz#a7a30959a97c472a7bae38986958c5164aa2c487" - integrity sha512-JF+KKOgGAgcROgae6FU+hAtxMRhR896SzwI3H1h5hFOZrjqYeYzemJoKzA5MR5IBnPSK4FzEjunc8G5L67TyzQ== - dependencies: - "@ai-sdk/provider-utils" "1.0.20" - "@ai-sdk/ui-utils" "0.0.46" - -"@ai-sdk/svelte@0.0.52": - version "0.0.52" - resolved "https://registry.yarnpkg.com/@ai-sdk/svelte/-/svelte-0.0.52.tgz#3b1ee970ce870a5b565807d88b701185afabcd4b" - integrity sha512-ZGd81ruVuqpOh1Suma+HwBMBywcOV0IUzi96Q3knIoZIz99sVwebSKH8ExMofXm49bQdCTRa73Wn8sTs6QDIYg== - dependencies: - "@ai-sdk/provider-utils" "1.0.20" - "@ai-sdk/ui-utils" "0.0.46" - sswr "2.1.0" - -"@ai-sdk/ui-utils@0.0.46": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@ai-sdk/ui-utils/-/ui-utils-0.0.46.tgz#72311a1917a370074089cc6dd8c982d272f6b836" - integrity sha512-ZG/wneyJG+6w5Nm/hy1AKMuRgjPQToAxBsTk61c9sVPUTaxo+NNjM2MhXQMtmsja2N5evs8NmHie+ExEgpL3cA== - dependencies: - "@ai-sdk/provider" "0.0.24" - "@ai-sdk/provider-utils" "1.0.20" - json-schema "0.4.0" - secure-json-parse "2.7.0" - zod-to-json-schema "3.23.2" - -"@ai-sdk/vue@0.0.55": - version "0.0.55" - resolved "https://registry.yarnpkg.com/@ai-sdk/vue/-/vue-0.0.55.tgz#3da3466418a3e105dd96bdee7217bd2d94a5cb61" - integrity sha512-NZ89CeRPO3D9GjI7GmK3vC+YXjsaWi3iCIvxlGqfQYt0JFKcjgM6dfeq8Nkk+qWI9OoxoOhV/yQdqWQKPv3RRg== - dependencies: - "@ai-sdk/provider-utils" "1.0.20" - "@ai-sdk/ui-utils" "0.0.46" - swrv "1.0.4" +"@ai-sdk/openai@^1.0.13": + version "1.0.13" + resolved "https://registry.yarnpkg.com/@ai-sdk/openai/-/openai-1.0.13.tgz#03ce0cd6a3f1b3fb78ea3069320fba23c41ba71e" + integrity sha512-kuSLNM6nFy+lgEd6d0X9Bp4hXjPbEwtUbnIrI4jqa9uZZupHc9vh8rOF6XO8s6ZhrWYjnuYZmhvK0S4k+sHrsg== + dependencies: + "@ai-sdk/provider" "1.0.3" + "@ai-sdk/provider-utils" "2.0.5" + +"@ai-sdk/provider-utils@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@ai-sdk/provider-utils/-/provider-utils-2.0.5.tgz#7b200f535668e619b7dbc55619aadcc5c1a103f8" + integrity sha512-2M7vLhYN0ThGjNlzow7oO/lsL+DyMxvGMIYmVQvEYaCWhDzxH5dOp78VNjJIVwHzVLMbBDigX3rJuzAs853idw== + dependencies: + "@ai-sdk/provider" "1.0.3" + eventsource-parser "^3.0.0" + nanoid "^3.3.8" + secure-json-parse "^2.7.0" + +"@ai-sdk/provider@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@ai-sdk/provider/-/provider-1.0.3.tgz#cfc75e2d3932133712583c55992f4b209f8a5e77" + integrity sha512-WiuJEpHTrltOIzv3x2wx4gwksAHW0h6nK3SoDzjqCOJLu/2OJ1yASESTIX+f07ChFykHElVoP80Ol/fe9dw6tQ== + dependencies: + json-schema "^0.4.0" + +"@ai-sdk/react@1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@ai-sdk/react/-/react-1.0.7.tgz#012fd0d76f5a89b1dc87aa548e9666f311ae04fe" + integrity sha512-j2/of4iCNq+r2Bjx0O9vdRhn5C/02t2Esenis71YtnsoynPz74eQlJ3N0RYYPheThiJes50yHdfdVdH9ulxs1A== + dependencies: + "@ai-sdk/provider-utils" "2.0.5" + "@ai-sdk/ui-utils" "1.0.6" + swr "^2.2.5" + throttleit "2.1.0" + +"@ai-sdk/ui-utils@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@ai-sdk/ui-utils/-/ui-utils-1.0.6.tgz#9962b4db71675c79f7817f65813cdeebd4b6a23d" + integrity sha512-ZP6Vjj+VCnSPBIAvWAdKj2olQONJ/f4aZpkVCGkzprdhv8TjHwB6CTlXFS3zypuEGy4asg84dc1dvXKooQXFvg== + dependencies: + "@ai-sdk/provider" "1.0.3" + "@ai-sdk/provider-utils" "2.0.5" + zod-to-json-schema "^3.23.5" "@ampproject/remapping@^2.2.0": version "2.2.1" @@ -1463,7 +1436,7 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@opentelemetry/api@1.9.0": +"@opentelemetry/api@1.9.0", "@opentelemetry/api@^1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== @@ -1834,25 +1807,18 @@ agentkeepalive@^4.2.1: dependencies: humanize-ms "^1.2.1" -ai@^3.4.17: - version "3.4.17" - resolved "https://registry.yarnpkg.com/ai/-/ai-3.4.17.tgz#9c5bbce9a2a2fdb49058ded31f0d5ba9f8531bfd" - integrity sha512-QZc+NgNlzPT34ZTHaCGGXVJ+stbMLj98hwq+vJaIzD1lns6HlDatrmlFjJsYYf8FtnfqGV7yPNu8DrH8a274vA== - dependencies: - "@ai-sdk/provider" "0.0.24" - "@ai-sdk/provider-utils" "1.0.20" - "@ai-sdk/react" "0.0.64" - "@ai-sdk/solid" "0.0.50" - "@ai-sdk/svelte" "0.0.52" - "@ai-sdk/ui-utils" "0.0.46" - "@ai-sdk/vue" "0.0.55" +ai@^4.0.27: + version "4.0.27" + resolved "https://registry.yarnpkg.com/ai/-/ai-4.0.27.tgz#ef5ac59a749073989d9ce5673ba658b747793d90" + integrity sha512-3wMFXNAR6a269R7k4ZDQ9FfF3fb8gQlnlIE4kWaQfZDUTEM5aWgQdbzFhsr9Q5DULCyZg7l/bFpGd48cRfvLaA== + dependencies: + "@ai-sdk/provider" "1.0.3" + "@ai-sdk/provider-utils" "2.0.5" + "@ai-sdk/react" "1.0.7" + "@ai-sdk/ui-utils" "1.0.6" "@opentelemetry/api" "1.9.0" - eventsource-parser "1.1.2" - json-schema "0.4.0" jsondiffpatch "0.6.0" - nanoid "3.3.6" - secure-json-parse "2.7.0" - zod-to-json-schema "3.23.2" + zod-to-json-schema "^3.23.5" ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" @@ -2188,11 +2154,6 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz" integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== -client-only@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== - cliui@^8.0.1: version "8.0.1" resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" @@ -2347,6 +2308,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +dequal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" @@ -2685,10 +2651,10 @@ eventemitter3@^4.0.4: resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -eventsource-parser@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-1.1.2.tgz#ed6154a4e3dbe7cda9278e5e35d2ffc58b309f89" - integrity sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA== +eventsource-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.0.tgz#9303e303ef807d279ee210a17ce80f16300d9f57" + integrity sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA== execa@^5.0.0: version "5.1.1" @@ -3725,7 +3691,7 @@ json-schema-traverse@^0.4.1: resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema@0.4.0: +json-schema@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== @@ -3938,10 +3904,10 @@ mustache@^4.2.0: resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== -nanoid@3.3.6: - version "3.3.6" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" - integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== +nanoid@^3.3.8: + version "3.3.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== natural-compare-lite@^1.4.0: version "1.4.0" @@ -4400,7 +4366,7 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" -secure-json-parse@2.7.0: +secure-json-parse@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== @@ -4498,13 +4464,6 @@ sprintf-js@~1.0.2: resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -sswr@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sswr/-/sswr-2.1.0.tgz#1eb64cd647cc9e11f871e7f43554abd8c64e1103" - integrity sha512-Cqc355SYlTAaUt8iDPaC/4DPPXK925PePLMxyBKuWd5kKc5mwsG3nT9+Mq2tyguL5s7b4Jg+IRMpTRsNTAfpSQ== - dependencies: - swrev "^4.0.0" - stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" @@ -4609,23 +4568,13 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -swr@2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/swr/-/swr-2.2.5.tgz#063eea0e9939f947227d5ca760cc53696f46446b" - integrity sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg== +swr@^2.2.5: + version "2.3.0" + resolved "https://registry.yarnpkg.com/swr/-/swr-2.3.0.tgz#66fa45023efd4199f4e7ce608c255709a135943d" + integrity sha512-NyZ76wA4yElZWBHzSgEJc28a0u6QZvhb6w0azeL2k7+Q1gAzVK+IqQYXhVOC/mzi+HZIozrZvBVeSeOZNR2bqA== dependencies: - client-only "^0.0.1" - use-sync-external-store "^1.2.0" - -swrev@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/swrev/-/swrev-4.0.0.tgz#83da6983c7ef9d71ac984a9b169fc197cbf18ff8" - integrity sha512-LqVcOHSB4cPGgitD1riJ1Hh4vdmITOp+BkmfmXRh4hSF/t7EnS4iD+SOTmq7w5pPm/SiPeto4ADbKS6dHUDWFA== - -swrv@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/swrv/-/swrv-1.0.4.tgz#278b4811ed4acbb1ae46654972a482fd1847e480" - integrity sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g== + dequal "^2.0.3" + use-sync-external-store "^1.4.0" test-exclude@^6.0.0: version "6.0.0" @@ -4641,6 +4590,11 @@ text-table@^0.2.0: resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +throttleit@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-2.1.0.tgz#a7e4aa0bf4845a5bd10daa39ea0c783f631a07b4" + integrity sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw== + tmpl@1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" @@ -4807,10 +4761,10 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -use-sync-external-store@^1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9" - integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw== +use-sync-external-store@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" + integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== uuid@^10.0.0: version "10.0.0" @@ -4966,16 +4920,16 @@ yocto-queue@^0.1.0: resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zod-to-json-schema@3.23.2: - version "3.23.2" - resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.23.2.tgz#bc7e379c8050462538383e382964c03d8fe008f9" - integrity sha512-uSt90Gzc/tUfyNqxnjlfBs8W6WSGpNBv0rVsNxP/BVSMHMKGdthPYff4xtCHYloJGM0CFxFsb3NbC0eqPhfImw== - zod-to-json-schema@^3.22.3: version "3.22.4" resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.22.4.tgz#f8cc691f6043e9084375e85fb1f76ebafe253d70" integrity sha512-2Ed5dJ+n/O3cU383xSY28cuVi0BCQhF8nYqWU5paEpl7fVdqdAmiLdqLyfblbNdfOFwFfi/mqU4O1pwc60iBhQ== +zod-to-json-schema@^3.23.5: + version "3.24.1" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz#f08c6725091aadabffa820ba8d50c7ab527f227a" + integrity sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w== + zod@^3.22.4: version "3.22.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"