veryfront 0.1.197 → 0.1.199

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.
Files changed (36) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/agent/react/use-voice-input.js +3 -4
  3. package/esm/src/chat/index.d.ts +0 -1
  4. package/esm/src/chat/index.js +0 -1
  5. package/esm/src/markdown/index.d.ts +0 -1
  6. package/esm/src/markdown/index.js +0 -1
  7. package/esm/src/mdx/index.d.ts +0 -1
  8. package/esm/src/mdx/index.js +0 -1
  9. package/esm/src/platform/compat/runtime.js +10 -11
  10. package/esm/src/provider/runtime-loader.d.ts.map +1 -1
  11. package/esm/src/provider/runtime-loader.js +171 -57
  12. package/esm/src/react/components/Head.d.ts +0 -1
  13. package/esm/src/react/components/Head.js +0 -1
  14. package/esm/src/react/components/chat/chat/components/code-block.js +1 -2
  15. package/esm/src/react/components/chat/chat/components/inline-citation.js +2 -3
  16. package/esm/src/react/components/chat/chat/components/message-actions.js +1 -2
  17. package/esm/src/react/components/chat/chat/components/reasoning.js +1 -2
  18. package/esm/src/react/components/chat/chat/hooks/use-threads.js +1 -2
  19. package/esm/src/react/components/chat/markdown.js +2 -2
  20. package/esm/src/react/context/index.d.ts +0 -1
  21. package/esm/src/react/context/index.js +0 -1
  22. package/esm/src/react/fonts/index.d.ts +0 -1
  23. package/esm/src/react/fonts/index.js +0 -1
  24. package/esm/src/react/router/index.d.ts +0 -1
  25. package/esm/src/react/router/index.js +0 -1
  26. package/esm/src/security/client/html-sanitizer.js +1 -2
  27. package/esm/src/server/handlers/dev/framework-candidates.generated.d.ts.map +1 -1
  28. package/esm/src/server/handlers/dev/framework-candidates.generated.js +5 -3
  29. package/esm/src/utils/version-constant.d.ts +1 -1
  30. package/esm/src/utils/version-constant.js +1 -1
  31. package/package.json +1 -1
  32. package/src/deno.js +1 -1
  33. package/src/src/provider/runtime-loader.ts +194 -54
  34. package/src/src/react/components/chat/markdown.tsx +2 -2
  35. package/src/src/server/handlers/dev/framework-candidates.generated.ts +5 -3
  36. package/src/src/utils/version-constant.ts +1 -1
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.197",
3
+ "version": "0.1.199",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -1,4 +1,3 @@
1
- import * as dntShim from "../../../_dnt.shims.js";
2
1
  import * as React from "react";
3
2
  export function useVoiceInput(options = {}) {
4
3
  const { language, continuous = false, interimResults = true, onTranscript, onError, onStart, onEnd, } = options;
@@ -7,15 +6,15 @@ export function useVoiceInput(options = {}) {
7
6
  const [error, setError] = React.useState(null);
8
7
  const recognitionRef = React.useRef(null);
9
8
  const isSupported = React.useMemo(() => {
10
- if (typeof dntShim.dntGlobalThis === "undefined")
9
+ if (typeof globalThis === "undefined")
11
10
  return false;
12
- const g = dntShim.dntGlobalThis;
11
+ const g = globalThis;
13
12
  return Boolean(g.SpeechRecognition ?? g.webkitSpeechRecognition);
14
13
  }, []);
15
14
  React.useEffect(() => {
16
15
  if (!isSupported)
17
16
  return;
18
- const g = dntShim.dntGlobalThis;
17
+ const g = globalThis;
19
18
  const SpeechRecognitionAPI = g.SpeechRecognition ?? g.webkitSpeechRecognition;
20
19
  if (!SpeechRecognitionAPI)
21
20
  return;
@@ -47,7 +47,6 @@
47
47
  * </Message.Root>
48
48
  * ```
49
49
  */
50
- import "../../_dnt.polyfills.js";
51
50
  export { Chat, ChatComponents, type ChatProps } from "../react/components/chat/chat.js";
52
51
  export { ChatComposer, type ChatComposerProps, ChatEmpty, type ChatEmptyProps, ChatIf, type ChatIfProps, ChatMessageList, type ChatMessageListProps, ChatRoot, type ChatRootProps, ErrorBanner, type ErrorBannerProps, Message, type MessageRootProps, ModelAvatar, type ModelAvatarProps, } from "../react/components/chat/chat.js";
53
52
  export { ChatContextProvider, type ChatContextValue, ComposerContextProvider, type ComposerContextValue, MessageContextProvider, type MessageContextValue, ThreadListContextProvider, type ThreadListContextValue, useChatContext, useChatContextOptional, useComposerContext, useComposerContextOptional, useMessageContext, useMessageContextOptional, useThreadListContext, useThreadListContextOptional, } from "../react/components/chat/chat.js";
@@ -47,7 +47,6 @@
47
47
  * </Message.Root>
48
48
  * ```
49
49
  */
50
- import "../../_dnt.polyfills.js";
51
50
  export { Chat, ChatComponents } from "../react/components/chat/chat.js";
52
51
  export { ChatComposer, ChatEmpty, ChatIf, ChatMessageList, ChatRoot, ErrorBanner, Message, ModelAvatar, } from "../react/components/chat/chat.js";
53
52
  export { ChatContextProvider, ComposerContextProvider, MessageContextProvider, ThreadListContextProvider, useChatContext, useChatContextOptional, useComposerContext, useComposerContextOptional, useMessageContext, useMessageContextOptional, useThreadListContext, useThreadListContextOptional, } from "../react/components/chat/chat.js";
@@ -10,6 +10,5 @@
10
10
  * <Markdown># Hello{"\n\n"}Some **bold** text with `code`.</Markdown>
11
11
  * ```
12
12
  */
13
- import "../../_dnt.polyfills.js";
14
13
  export { type CodeBlockProps, Markdown, type MarkdownProps, } from "../react/components/chat/markdown.js";
15
14
  //# sourceMappingURL=index.d.ts.map
@@ -10,5 +10,4 @@
10
10
  * <Markdown># Hello{"\n\n"}Some **bold** text with `code`.</Markdown>
11
11
  * ```
12
12
  */
13
- import "../../_dnt.polyfills.js";
14
13
  export { Markdown, } from "../react/components/chat/markdown.js";
@@ -14,6 +14,5 @@
14
14
  *
15
15
  * For runtime markdown string rendering, use `veryfront/markdown` instead.
16
16
  */
17
- import "../../_dnt.polyfills.js";
18
17
  export { MDXProvider, type MDXProviderProps, useMDXComponents, } from "../react/components/MDXProvider.js";
19
18
  //# sourceMappingURL=index.d.ts.map
@@ -14,5 +14,4 @@
14
14
  *
15
15
  * For runtime markdown string rendering, use `veryfront/markdown` instead.
16
16
  */
17
- import "../../_dnt.polyfills.js";
18
17
  export { MDXProvider, useMDXComponents, } from "../react/components/MDXProvider.js";
@@ -1,16 +1,15 @@
1
- import * as dntShim from "../../../_dnt.shims.js";
2
1
  function hasNodeProcess() {
3
- const global = dntShim.dntGlobalThis;
2
+ const global = globalThis;
4
3
  return global.process?.versions?.node != null && !global.process?.versions?.deno;
5
4
  }
6
5
  function hasBunGlobal() {
7
- return dntShim.dntGlobalThis.Bun != null;
6
+ return globalThis.Bun != null;
8
7
  }
9
8
  function hasRealDeno() {
10
- return (typeof dntShim.Deno !== "undefined" &&
11
- typeof dntShim.Deno.version === "object" &&
12
- typeof dntShim.Deno.build === "object" &&
13
- typeof dntShim.Deno.build.os === "string");
9
+ return (typeof globalThis.Deno !== "undefined" &&
10
+ typeof globalThis.Deno.version === "object" &&
11
+ typeof globalThis.Deno.build === "object" &&
12
+ typeof globalThis.Deno.build.os === "string");
14
13
  }
15
14
  /**
16
15
  * Check if an executable path is a compiled Deno binary.
@@ -30,7 +29,7 @@ function isDenoCompiledBinary() {
30
29
  if (!hasRealDeno())
31
30
  return false;
32
31
  try {
33
- return testDenoCompiledDetection(dntShim.Deno.execPath());
32
+ return testDenoCompiledDetection(globalThis.Deno.execPath());
34
33
  }
35
34
  catch (_) {
36
35
  /* expected: Deno.execPath() may not be available in all environments */
@@ -38,7 +37,7 @@ function isDenoCompiledBinary() {
38
37
  }
39
38
  }
40
39
  function hasCloudflareGlobals() {
41
- return "caches" in dntShim.dntGlobalThis && "WebSocketPair" in dntShim.dntGlobalThis;
40
+ return "caches" in globalThis && "WebSocketPair" in globalThis;
42
41
  }
43
42
  /** True if running in Bun runtime (check first since Bun has process.versions.node) */
44
43
  export const isBun = hasBunGlobal();
@@ -77,10 +76,10 @@ export function isNodeRuntime() {
77
76
  * @see plans/architecture-audit/006.1-ssr-detection-inconsistencies.md
78
77
  */
79
78
  export function isServerEnvironment() {
80
- const ssrFlag = dntShim.dntGlobalThis.__VERYFRONT_SSR__;
79
+ const ssrFlag = globalThis.__VERYFRONT_SSR__;
81
80
  if (ssrFlag === true)
82
81
  return true;
83
- return typeof dntShim.dntGlobalThis === "undefined";
82
+ return typeof globalThis === "undefined";
84
83
  }
85
84
  /**
86
85
  * Detect if code is executing in a browser environment.
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-loader.d.ts","sourceRoot":"","sources":["../../../src/src/provider/runtime-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAkhDD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAkDd;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,MAAM,GACd,YAAY,CA4Dd;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAkDd;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,gBAAgB,CA0ClB;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,gBAAgB,CAgDlB"}
1
+ {"version":3,"file":"runtime-loader.d.ts","sourceRoot":"","sources":["../../../src/src/provider/runtime-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AA8pDD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAkDd;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,MAAM,GACd,YAAY,CA4Dd;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,YAAY,CAkDd;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,gBAAgB,CA0ClB;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,MAAM,GACd,gBAAgB,CAgDlB"}
@@ -258,6 +258,20 @@ function toSnakeCaseRecord(record) {
258
258
  value,
259
259
  ]));
260
260
  }
261
+ function pushAnthropicUserContent(messages, content) {
262
+ if (content.length === 0) {
263
+ return;
264
+ }
265
+ const lastMessage = messages.at(-1);
266
+ if (lastMessage?.role === "user") {
267
+ lastMessage.content.push(...content);
268
+ return;
269
+ }
270
+ messages.push({
271
+ role: "user",
272
+ content,
273
+ });
274
+ }
261
275
  function toAnthropicMessages(prompt) {
262
276
  const systemParts = [];
263
277
  const messages = [];
@@ -269,10 +283,10 @@ function toAnthropicMessages(prompt) {
269
283
  }
270
284
  break;
271
285
  case "user":
272
- messages.push({
273
- role: "user",
274
- content: [{ type: "text", text: readTextParts(message.content) }],
275
- });
286
+ pushAnthropicUserContent(messages, [{
287
+ type: "text",
288
+ text: readTextParts(message.content),
289
+ }]);
276
290
  break;
277
291
  case "assistant":
278
292
  messages.push({
@@ -286,14 +300,11 @@ function toAnthropicMessages(prompt) {
286
300
  });
287
301
  break;
288
302
  case "tool":
289
- messages.push({
290
- role: "user",
291
- content: message.content.map((part) => ({
292
- type: "tool_result",
293
- tool_use_id: part.toolCallId,
294
- content: stringifyJsonValue(part.output.value),
295
- })),
296
- });
303
+ pushAnthropicUserContent(messages, message.content.map((part) => ({
304
+ type: "tool_result",
305
+ tool_use_id: part.toolCallId,
306
+ content: stringifyJsonValue(part.output.value),
307
+ })));
297
308
  break;
298
309
  }
299
310
  }
@@ -440,6 +451,7 @@ async function* streamAnthropicCompatibleParts(stream) {
440
451
  const decoder = new TextDecoder();
441
452
  let buffer = "";
442
453
  const toolCalls = new Map();
454
+ const reasoningBlocks = new Map();
443
455
  let finishReason = null;
444
456
  let usage;
445
457
  for await (const chunk of stream) {
@@ -466,6 +478,22 @@ async function* streamAnthropicCompatibleParts(stream) {
466
478
  yield { type: "text-delta", delta: contentBlock.text };
467
479
  continue;
468
480
  }
481
+ if (blockType === "thinking") {
482
+ const reasoningId = `thinking-${index}`;
483
+ reasoningBlocks.set(index, { id: reasoningId });
484
+ yield {
485
+ type: "reasoning-start",
486
+ id: reasoningId,
487
+ };
488
+ if (typeof contentBlock?.thinking === "string" && contentBlock.thinking.length > 0) {
489
+ yield {
490
+ type: "reasoning-delta",
491
+ id: reasoningId,
492
+ delta: contentBlock.thinking,
493
+ };
494
+ }
495
+ continue;
496
+ }
469
497
  if ((blockType === "tool_use" || blockType === "server_tool_use") &&
470
498
  typeof contentBlock?.id === "string" &&
471
499
  typeof contentBlock?.name === "string") {
@@ -527,6 +555,19 @@ async function* streamAnthropicCompatibleParts(stream) {
527
555
  yield { type: "text-delta", delta: delta.text };
528
556
  continue;
529
557
  }
558
+ if (deltaType === "thinking_delta" && typeof delta?.thinking === "string" &&
559
+ delta.thinking.length > 0) {
560
+ const current = reasoningBlocks.get(index);
561
+ if (!current) {
562
+ continue;
563
+ }
564
+ yield {
565
+ type: "reasoning-delta",
566
+ id: current.id,
567
+ delta: delta.thinking,
568
+ };
569
+ continue;
570
+ }
530
571
  if (deltaType === "input_json_delta" && typeof delta?.partial_json === "string") {
531
572
  const current = toolCalls.get(index);
532
573
  if (!current) {
@@ -543,6 +584,15 @@ async function* streamAnthropicCompatibleParts(stream) {
543
584
  }
544
585
  if (eventType === "content_block_stop") {
545
586
  const index = typeof record?.index === "number" ? record.index : 0;
587
+ const reasoning = reasoningBlocks.get(index);
588
+ if (reasoning) {
589
+ yield {
590
+ type: "reasoning-end",
591
+ id: reasoning.id,
592
+ };
593
+ reasoningBlocks.delete(index);
594
+ continue;
595
+ }
546
596
  const current = toolCalls.get(index);
547
597
  if (!current) {
548
598
  continue;
@@ -871,6 +921,8 @@ async function* streamGoogleCompatibleParts(stream) {
871
921
  const decoder = new TextDecoder();
872
922
  let buffer = "";
873
923
  const seenToolCalls = new Set();
924
+ let reasoningId = null;
925
+ let reasoningIndex = 0;
874
926
  let finishReason = null;
875
927
  let usage;
876
928
  for await (const chunk of stream) {
@@ -888,6 +940,29 @@ async function* streamGoogleCompatibleParts(stream) {
888
940
  finishReason = normalizedFinishReason;
889
941
  }
890
942
  for (const [index, part] of extractGoogleCandidateParts(event).entries()) {
943
+ const isThought = part.thought === true;
944
+ if (isThought && typeof part.text === "string" && part.text.length > 0) {
945
+ if (!reasoningId) {
946
+ reasoningId = `reasoning-${reasoningIndex++}`;
947
+ yield {
948
+ type: "reasoning-start",
949
+ id: reasoningId,
950
+ };
951
+ }
952
+ yield {
953
+ type: "reasoning-delta",
954
+ id: reasoningId,
955
+ delta: part.text,
956
+ };
957
+ continue;
958
+ }
959
+ if (reasoningId) {
960
+ yield {
961
+ type: "reasoning-end",
962
+ id: reasoningId,
963
+ };
964
+ reasoningId = null;
965
+ }
891
966
  if (typeof part.text === "string" && part.text.length > 0) {
892
967
  yield { type: "text-delta", delta: part.text };
893
968
  continue;
@@ -930,6 +1005,12 @@ async function* streamGoogleCompatibleParts(stream) {
930
1005
  usage = extractGoogleUsage(event) ?? usage;
931
1006
  }
932
1007
  }
1008
+ if (reasoningId) {
1009
+ yield {
1010
+ type: "reasoning-end",
1011
+ id: reasoningId,
1012
+ };
1013
+ }
933
1014
  yield {
934
1015
  type: "finish",
935
1016
  finishReason,
@@ -971,6 +1052,8 @@ async function* streamOpenAICompatibleParts(stream) {
971
1052
  const decoder = new TextDecoder();
972
1053
  let buffer = "";
973
1054
  const toolCalls = new Map();
1055
+ let reasoningId = null;
1056
+ let reasoningIndex = 0;
974
1057
  let finishReason = null;
975
1058
  let usage;
976
1059
  for await (const chunk of stream) {
@@ -983,56 +1066,81 @@ async function* streamOpenAICompatibleParts(stream) {
983
1066
  }
984
1067
  const record = readRecord(event);
985
1068
  usage = extractOpenAIUsage(record) ?? usage;
986
- const choices = Array.isArray(record?.choices) ? record.choices : [];
987
- for (const choiceValue of choices) {
988
- const choice = readRecord(choiceValue);
989
- if (!choice) {
990
- continue;
1069
+ const choice = extractFirstChoice(record);
1070
+ if (!choice) {
1071
+ continue;
1072
+ }
1073
+ const delta = readRecord(choice.delta);
1074
+ if (typeof delta?.reasoning_content === "string" && delta.reasoning_content.length > 0) {
1075
+ if (!reasoningId) {
1076
+ reasoningId = `reasoning-${reasoningIndex++}`;
1077
+ yield {
1078
+ type: "reasoning-start",
1079
+ id: reasoningId,
1080
+ };
991
1081
  }
992
- const delta = readRecord(choice.delta);
993
- const textDelta = extractOpenAIContentText(delta?.content);
994
- if (textDelta.length > 0) {
995
- yield { type: "text-delta", delta: textDelta };
1082
+ yield {
1083
+ type: "reasoning-delta",
1084
+ id: reasoningId,
1085
+ delta: delta.reasoning_content,
1086
+ };
1087
+ }
1088
+ const textDelta = extractOpenAIContentText(delta?.content);
1089
+ if (textDelta.length > 0) {
1090
+ if (reasoningId) {
1091
+ yield {
1092
+ type: "reasoning-end",
1093
+ id: reasoningId,
1094
+ };
1095
+ reasoningId = null;
996
1096
  }
997
- const rawToolCalls = Array.isArray(delta?.tool_calls) ? delta.tool_calls : [];
998
- for (const rawToolCall of rawToolCalls) {
999
- const toolCallRecord = readRecord(rawToolCall);
1000
- const index = typeof toolCallRecord?.index === "number" ? toolCallRecord.index : 0;
1001
- const current = toolCalls.get(index) ?? {
1002
- id: typeof toolCallRecord?.id === "string" ? toolCallRecord.id : `tool-${index}`,
1003
- name: "",
1004
- arguments: "",
1005
- started: false,
1097
+ yield { type: "text-delta", delta: textDelta };
1098
+ }
1099
+ const rawToolCalls = Array.isArray(delta?.tool_calls) ? delta.tool_calls : [];
1100
+ for (const rawToolCall of rawToolCalls) {
1101
+ if (reasoningId) {
1102
+ yield {
1103
+ type: "reasoning-end",
1104
+ id: reasoningId,
1006
1105
  };
1007
- if (typeof toolCallRecord?.id === "string") {
1008
- current.id = toolCallRecord.id;
1009
- }
1010
- const fn = readRecord(toolCallRecord?.function);
1011
- if (typeof fn?.name === "string") {
1012
- current.name = fn.name;
1013
- }
1014
- if (!current.started && current.name.length > 0) {
1015
- current.started = true;
1016
- yield {
1017
- type: "tool-input-start",
1018
- id: current.id,
1019
- toolName: current.name,
1020
- };
1021
- }
1022
- if (typeof fn?.arguments === "string" && fn.arguments.length > 0) {
1023
- current.arguments += fn.arguments;
1024
- yield {
1025
- type: "tool-input-delta",
1026
- id: current.id,
1027
- delta: fn.arguments,
1028
- };
1029
- }
1030
- toolCalls.set(index, current);
1106
+ reasoningId = null;
1031
1107
  }
1032
- const normalizedFinishReason = normalizeOpenAIFinishReason(choice.finish_reason);
1033
- if (normalizedFinishReason) {
1034
- finishReason = normalizedFinishReason;
1108
+ const toolCallRecord = readRecord(rawToolCall);
1109
+ const index = typeof toolCallRecord?.index === "number" ? toolCallRecord.index : 0;
1110
+ const current = toolCalls.get(index) ?? {
1111
+ id: typeof toolCallRecord?.id === "string" ? toolCallRecord.id : `tool-${index}`,
1112
+ name: "",
1113
+ arguments: "",
1114
+ started: false,
1115
+ };
1116
+ if (typeof toolCallRecord?.id === "string") {
1117
+ current.id = toolCallRecord.id;
1118
+ }
1119
+ const fn = readRecord(toolCallRecord?.function);
1120
+ if (typeof fn?.name === "string") {
1121
+ current.name = fn.name;
1122
+ }
1123
+ if (!current.started && current.name.length > 0) {
1124
+ current.started = true;
1125
+ yield {
1126
+ type: "tool-input-start",
1127
+ id: current.id,
1128
+ toolName: current.name,
1129
+ };
1130
+ }
1131
+ if (typeof fn?.arguments === "string" && fn.arguments.length > 0) {
1132
+ current.arguments += fn.arguments;
1133
+ yield {
1134
+ type: "tool-input-delta",
1135
+ id: current.id,
1136
+ delta: fn.arguments,
1137
+ };
1035
1138
  }
1139
+ toolCalls.set(index, current);
1140
+ }
1141
+ const normalizedFinishReason = normalizeOpenAIFinishReason(choice.finish_reason);
1142
+ if (normalizedFinishReason) {
1143
+ finishReason = normalizedFinishReason;
1036
1144
  }
1037
1145
  }
1038
1146
  }
@@ -1046,6 +1154,12 @@ async function* streamOpenAICompatibleParts(stream) {
1046
1154
  usage = extractOpenAIUsage(record) ?? usage;
1047
1155
  }
1048
1156
  }
1157
+ if (reasoningId) {
1158
+ yield {
1159
+ type: "reasoning-end",
1160
+ id: reasoningId,
1161
+ };
1162
+ }
1049
1163
  if (finishReason &&
1050
1164
  typeof finishReason === "object" &&
1051
1165
  finishReason.unified === "tool-calls") {
@@ -7,6 +7,5 @@
7
7
  * import { Head } from "veryfront/head";
8
8
  * ```
9
9
  */
10
- import "../../../_dnt.polyfills.js";
11
10
  export { Head } from "../runtime/core.js";
12
11
  //# sourceMappingURL=Head.d.ts.map
@@ -7,5 +7,4 @@
7
7
  * import { Head } from "veryfront/head";
8
8
  * ```
9
9
  */
10
- import "../../../_dnt.polyfills.js";
11
10
  export { Head } from "../runtime/core.js";
@@ -1,4 +1,3 @@
1
- import * as dntShim from "../../../../../../_dnt.shims.js";
2
1
  import * as React from "react";
3
2
  import { cn } from "../../theme.js";
4
3
  import { CheckIcon, CopyIcon } from "../../icons/index.js";
@@ -18,7 +17,7 @@ export const RichCodeBlock = React.forwardRef(function RichCodeBlock({ language,
18
17
  document.body.removeChild(textarea);
19
18
  }
20
19
  setCopied(true);
21
- dntShim.setTimeout(() => setCopied(false), 2000);
20
+ globalThis.setTimeout(() => setCopied(false), 2000);
22
21
  }, [code]);
23
22
  if (inline) {
24
23
  return (React.createElement("code", { className: cn("bg-[var(--accent)] px-1.5 py-0.5 rounded text-sm font-mono", className) }, code));
@@ -1,4 +1,3 @@
1
- import * as dntShim from "../../../../../../_dnt.shims.js";
2
1
  import * as React from "react";
3
2
  import { cn } from "../../theme.js";
4
3
  export function InlineCitation({ index, source, className, onClick, }) {
@@ -8,7 +7,7 @@ export function InlineCitation({ index, source, className, onClick, }) {
8
7
  const [cardStyle, setCardStyle] = React.useState({});
9
8
  const show = React.useCallback(() => {
10
9
  clearTimeout(timerRef.current);
11
- timerRef.current = dntShim.setTimeout(() => {
10
+ timerRef.current = globalThis.setTimeout(() => {
12
11
  // Position the card using fixed positioning to prevent overflow clipping
13
12
  const el = buttonRef.current;
14
13
  if (el) {
@@ -25,7 +24,7 @@ export function InlineCitation({ index, source, className, onClick, }) {
25
24
  }, []);
26
25
  const hide = React.useCallback(() => {
27
26
  clearTimeout(timerRef.current);
28
- timerRef.current = dntShim.setTimeout(() => setShowCard(false), 100);
27
+ timerRef.current = globalThis.setTimeout(() => setShowCard(false), 100);
29
28
  }, []);
30
29
  React.useEffect(() => () => clearTimeout(timerRef.current), []);
31
30
  return (React.createElement(React.Fragment, null,
@@ -1,4 +1,3 @@
1
- import * as dntShim from "../../../../../../_dnt.shims.js";
2
1
  import * as React from "react";
3
2
  import { cn } from "../../theme.js";
4
3
  import { CheckIcon, CopyIcon } from "../../icons/index.js";
@@ -7,7 +6,7 @@ export const MessageActions = React.forwardRef(function MessageActions({ content
7
6
  const [copied, setCopied] = React.useState(false);
8
7
  const setCopiedWithTimeout = React.useCallback(() => {
9
8
  setCopied(true);
10
- dntShim.setTimeout(() => setCopied(false), 2000);
9
+ globalThis.setTimeout(() => setCopied(false), 2000);
11
10
  }, []);
12
11
  const fallbackCopy = React.useCallback(() => {
13
12
  const textarea = document.createElement("textarea");
@@ -1,4 +1,3 @@
1
- import * as dntShim from "../../../../../../_dnt.shims.js";
2
1
  import * as React from "react";
3
2
  import { cn } from "../../theme.js";
4
3
  import { Markdown } from "../../markdown.js";
@@ -10,7 +9,7 @@ export const ReasoningCard = React.forwardRef(function ReasoningCard({ text, isS
10
9
  React.useEffect(() => {
11
10
  if (isStreaming || !isOpen || userToggledRef.current)
12
11
  return;
13
- const timer = dntShim.setTimeout(() => setIsOpen(false), 1000);
12
+ const timer = globalThis.setTimeout(() => setIsOpen(false), 1000);
14
13
  return () => clearTimeout(timer);
15
14
  }, [isStreaming, isOpen]);
16
15
  const label = isStreaming ? React.createElement(Shimmer, null, "Thinking...") : React.createElement("span", null, "Thought process");
@@ -1,4 +1,3 @@
1
- import * as dntShim from "../../../../../../_dnt.shims.js";
2
1
  import * as React from "react";
3
2
  import { isBrowserEnvironment } from "../../../../../platform/compat/runtime.js";
4
3
  function generateId() {
@@ -85,7 +84,7 @@ export function useThreads(options) {
85
84
  React.useEffect(() => () => clearTimeout(saveTimerRef.current), []);
86
85
  const persistThreads = React.useCallback((updated) => {
87
86
  clearTimeout(saveTimerRef.current);
88
- saveTimerRef.current = dntShim.setTimeout(() => {
87
+ saveTimerRef.current = globalThis.setTimeout(() => {
89
88
  saveIndex(storageKey, { ids: updated.map((t) => t.id) });
90
89
  for (const thread of updated) {
91
90
  saveThread(storageKey, thread);
@@ -3,12 +3,12 @@ import { cn } from "./theme.js";
3
3
  import { isBrowserEnvironment } from "../../../platform/compat/runtime.js";
4
4
  import { validateTrustedHtml } from "../../../security/client/html-sanitizer.js";
5
5
  import { RichCodeBlock } from "./chat/components/code-block.js";
6
- const ESM_REACT_MARKDOWN = "https://esm.sh/react-markdown@9.0.3?external=react&target=es2022&pin=v135";
6
+ const ESM_REACT_MARKDOWN = "https://esm.sh/react-markdown@9.0.3?target=es2022&pin=v135&deps=react@19.2.4";
7
7
  const ESM_REMARK_GFM = "https://esm.sh/remark-gfm@4.0.1?target=es2022&pin=v135";
8
8
  const ESM_REHYPE_HIGHLIGHT = "https://esm.sh/rehype-highlight@7.0.2?target=es2022&pin=v135";
9
9
  const ESM_MERMAID = "https://esm.sh/mermaid@11.4.1?pin=v135";
10
10
  async function importFromUrl(url) {
11
- return await import(url);
11
+ return await import(/* @vite-ignore */ url);
12
12
  }
13
13
  // deno-lint-ignore no-explicit-any
14
14
  let ReactMarkdown = null;
@@ -7,7 +7,6 @@
7
7
  * import { PageContextProvider, usePageContext } from "veryfront/context";
8
8
  * ```
9
9
  */
10
- import "../../../_dnt.polyfills.js";
11
10
  export { PageContextProvider, usePageContext } from "../runtime/core.js";
12
11
  export type { MdxHeading, PageContextProviderProps, PageContextValue } from "../runtime/core.js";
13
12
  //# sourceMappingURL=index.d.ts.map
@@ -7,5 +7,4 @@
7
7
  * import { PageContextProvider, usePageContext } from "veryfront/context";
8
8
  * ```
9
9
  */
10
- import "../../../_dnt.polyfills.js";
11
10
  export { PageContextProvider, usePageContext } from "../runtime/core.js";
@@ -15,7 +15,6 @@
15
15
  * />
16
16
  * ```
17
17
  */
18
- import "../../../_dnt.polyfills.js";
19
18
  import React from "react";
20
19
  export interface Font {
21
20
  name: string;
@@ -15,7 +15,6 @@
15
15
  * />
16
16
  * ```
17
17
  */
18
- import "../../../_dnt.polyfills.js";
19
18
  import React from "react";
20
19
  import { Head } from "../components/Head.js";
21
20
  function sortMixedArray(arr) {
@@ -7,7 +7,6 @@
7
7
  * import { Link, RouterProvider, useRouter } from "veryfront/router";
8
8
  * ```
9
9
  */
10
- import "../../../_dnt.polyfills.js";
11
10
  export { Link, Router, RouterProvider, useRouter } from "../runtime/core.js";
12
11
  export type { LinkProps, RouterProviderProps, RouterValue } from "../runtime/core.js";
13
12
  //# sourceMappingURL=index.d.ts.map
@@ -7,5 +7,4 @@
7
7
  * import { Link, RouterProvider, useRouter } from "veryfront/router";
8
8
  * ```
9
9
  */
10
- import "../../../_dnt.polyfills.js";
11
10
  export { Link, Router, RouterProvider, useRouter } from "../runtime/core.js";
@@ -6,7 +6,6 @@
6
6
  * - Error messages and debug info are untrusted and must be escaped
7
7
  * - validateTrustedHtml() provides defense-in-depth for server HTML
8
8
  */
9
- import * as dntShim from "../../../_dnt.shims.js";
10
9
  import { escapeHtml } from "../../html/html-escape.js";
11
10
  import { SECURITY_VIOLATION } from "../../errors/error-registry.js";
12
11
  export { escapeHtml };
@@ -21,7 +20,7 @@ const SUSPICIOUS_PATTERNS = [
21
20
  { pattern: /data:\s*text\/html/gi, name: "data: HTML URL" },
22
21
  ];
23
22
  function isDevMode() {
24
- const g = dntShim.dntGlobalThis;
23
+ const g = globalThis;
25
24
  return g.__VERYFRONT_DEV__ === true || g.Deno?.env?.get?.("VERYFRONT_ENV") === "development";
26
25
  }
27
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"framework-candidates.generated.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/framework-candidates.generated.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAixKjD,CAAC"}
1
+ {"version":3,"file":"framework-candidates.generated.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/framework-candidates.generated.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAmxKjD,CAAC"}
@@ -528,6 +528,7 @@ export const FRAMEWORK_CANDIDATES = [
528
528
  "@internal",
529
529
  "@media(prefers-color-scheme:dark){[data-vf-chat]:not([data-vf-theme]){${dark}}}",
530
530
  "@module",
531
+ "@vite-ignore",
531
532
  "A",
532
533
  "ACTION_BUTTON",
533
534
  "AI",
@@ -2601,6 +2602,7 @@ export const FRAMEWORK_CANDIDATES = [
2601
2602
  "deno-lint-ignore",
2602
2603
  "dependency)",
2603
2604
  "deprecated,",
2605
+ "deps=react@19.2.4",
2604
2606
  "desc",
2605
2607
  "descendant",
2606
2608
  "describe(",
@@ -3142,7 +3144,7 @@ export const FRAMEWORK_CANDIDATES = [
3142
3144
  "html><html><head><style",
3143
3145
  "https://ai-sdk.dev/elements)",
3144
3146
  "https://esm.sh/mermaid@11.4.1?pin=v135",
3145
- "https://esm.sh/react-markdown@9.0.3?external=react",
3147
+ "https://esm.sh/react-markdown@9.0.3?target=es2022",
3146
3148
  "https://esm.sh/rehype-highlight@7.0.2?target=es2022",
3147
3149
  "https://esm.sh/remark-gfm@4.0.1?target=es2022",
3148
3150
  "https://example.com/",
@@ -3189,7 +3191,7 @@ export const FRAMEWORK_CANDIDATES = [
3189
3191
  "if",
3190
3192
  "ignores",
3191
3193
  "import",
3192
- "import(url)",
3194
+ "import(/*",
3193
3195
  "importFromUrl<DefaultModule<unknown>>(ESM_REACT_MARKDOWN),",
3194
3196
  "importFromUrl<DefaultModule<unknown>>(ESM_REHYPE_HIGHLIGHT),",
3195
3197
  "importFromUrl<DefaultModule<unknown>>(ESM_REMARK_GFM),",
@@ -4882,7 +4884,6 @@ export const FRAMEWORK_CANDIDATES = [
4882
4884
  "take",
4883
4885
  "target",
4884
4886
  "target=",
4885
- "target=es2022",
4886
4887
  "tbody>",
4887
4888
  "tc1",
4888
4889
  "td",
@@ -5205,6 +5206,7 @@ export const FRAMEWORK_CANDIDATES = [
5205
5206
  "upward",
5206
5207
  "url",
5207
5208
  "url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600",
5209
+ "url)",
5208
5210
  "url:",
5209
5211
  "url;",
5210
5212
  "url?:",
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.1.197";
1
+ export declare const VERSION = "0.1.199";
2
2
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.197";
3
+ export const VERSION = "0.1.199";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.197",
3
+ "version": "0.1.199",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.197",
3
+ "version": "0.1.199",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -156,6 +156,9 @@ type AnthropicStreamToolCallState = {
156
156
  input: string;
157
157
  providerExecuted?: boolean;
158
158
  };
159
+ type AnthropicStreamReasoningState = {
160
+ id: string;
161
+ };
159
162
  type GoogleCompatibleContent = {
160
163
  role: "user" | "model";
161
164
  parts: Array<Record<string, unknown>>;
@@ -535,6 +538,26 @@ function toSnakeCaseRecord(record: Record<string, unknown>): Record<string, unkn
535
538
  );
536
539
  }
537
540
 
541
+ function pushAnthropicUserContent(
542
+ messages: AnthropicCompatibleMessage[],
543
+ content: Array<Record<string, unknown>>,
544
+ ): void {
545
+ if (content.length === 0) {
546
+ return;
547
+ }
548
+
549
+ const lastMessage = messages.at(-1);
550
+ if (lastMessage?.role === "user") {
551
+ lastMessage.content.push(...content);
552
+ return;
553
+ }
554
+
555
+ messages.push({
556
+ role: "user",
557
+ content,
558
+ });
559
+ }
560
+
538
561
  function toAnthropicMessages(
539
562
  prompt: RuntimePromptMessage[],
540
563
  ): { system?: string; messages: AnthropicCompatibleMessage[] } {
@@ -549,10 +572,10 @@ function toAnthropicMessages(
549
572
  }
550
573
  break;
551
574
  case "user":
552
- messages.push({
553
- role: "user",
554
- content: [{ type: "text", text: readTextParts(message.content) }],
555
- });
575
+ pushAnthropicUserContent(messages, [{
576
+ type: "text",
577
+ text: readTextParts(message.content),
578
+ }]);
556
579
  break;
557
580
  case "assistant":
558
581
  messages.push({
@@ -568,14 +591,14 @@ function toAnthropicMessages(
568
591
  });
569
592
  break;
570
593
  case "tool":
571
- messages.push({
572
- role: "user",
573
- content: message.content.map((part) => ({
594
+ pushAnthropicUserContent(
595
+ messages,
596
+ message.content.map((part) => ({
574
597
  type: "tool_result",
575
598
  tool_use_id: part.toolCallId,
576
599
  content: stringifyJsonValue(part.output.value),
577
600
  })),
578
- });
601
+ );
579
602
  break;
580
603
  }
581
604
  }
@@ -780,6 +803,7 @@ async function* streamAnthropicCompatibleParts(
780
803
  const decoder = new TextDecoder();
781
804
  let buffer = "";
782
805
  const toolCalls = new Map<number, AnthropicStreamToolCallState>();
806
+ const reasoningBlocks = new Map<number, AnthropicStreamReasoningState>();
783
807
  let finishReason: string | { unified: string; raw: string } | null = null;
784
808
  let usage: { inputTokens?: number; outputTokens?: number; totalTokens?: number } | undefined;
785
809
 
@@ -815,6 +839,24 @@ async function* streamAnthropicCompatibleParts(
815
839
  continue;
816
840
  }
817
841
 
842
+ if (blockType === "thinking") {
843
+ const reasoningId = `thinking-${index}`;
844
+ reasoningBlocks.set(index, { id: reasoningId });
845
+ yield {
846
+ type: "reasoning-start",
847
+ id: reasoningId,
848
+ };
849
+
850
+ if (typeof contentBlock?.thinking === "string" && contentBlock.thinking.length > 0) {
851
+ yield {
852
+ type: "reasoning-delta",
853
+ id: reasoningId,
854
+ delta: contentBlock.thinking,
855
+ };
856
+ }
857
+ continue;
858
+ }
859
+
818
860
  if (
819
861
  (blockType === "tool_use" || blockType === "server_tool_use") &&
820
862
  typeof contentBlock?.id === "string" &&
@@ -892,6 +934,23 @@ async function* streamAnthropicCompatibleParts(
892
934
  continue;
893
935
  }
894
936
 
937
+ if (
938
+ deltaType === "thinking_delta" && typeof delta?.thinking === "string" &&
939
+ delta.thinking.length > 0
940
+ ) {
941
+ const current = reasoningBlocks.get(index);
942
+ if (!current) {
943
+ continue;
944
+ }
945
+
946
+ yield {
947
+ type: "reasoning-delta",
948
+ id: current.id,
949
+ delta: delta.thinking,
950
+ };
951
+ continue;
952
+ }
953
+
895
954
  if (deltaType === "input_json_delta" && typeof delta?.partial_json === "string") {
896
955
  const current = toolCalls.get(index);
897
956
  if (!current) {
@@ -911,6 +970,16 @@ async function* streamAnthropicCompatibleParts(
911
970
 
912
971
  if (eventType === "content_block_stop") {
913
972
  const index = typeof record?.index === "number" ? record.index : 0;
973
+ const reasoning = reasoningBlocks.get(index);
974
+ if (reasoning) {
975
+ yield {
976
+ type: "reasoning-end",
977
+ id: reasoning.id,
978
+ };
979
+ reasoningBlocks.delete(index);
980
+ continue;
981
+ }
982
+
914
983
  const current = toolCalls.get(index);
915
984
  if (!current) {
916
985
  continue;
@@ -1334,6 +1403,8 @@ async function* streamGoogleCompatibleParts(
1334
1403
  const decoder = new TextDecoder();
1335
1404
  let buffer = "";
1336
1405
  const seenToolCalls = new Set<string>();
1406
+ let reasoningId: string | null = null;
1407
+ let reasoningIndex = 0;
1337
1408
  let finishReason: string | { unified: string; raw: string } | null = null;
1338
1409
  let usage: { inputTokens?: number; outputTokens?: number; totalTokens?: number } | undefined;
1339
1410
 
@@ -1355,6 +1426,32 @@ async function* streamGoogleCompatibleParts(
1355
1426
  }
1356
1427
 
1357
1428
  for (const [index, part] of extractGoogleCandidateParts(event).entries()) {
1429
+ const isThought = part.thought === true;
1430
+ if (isThought && typeof part.text === "string" && part.text.length > 0) {
1431
+ if (!reasoningId) {
1432
+ reasoningId = `reasoning-${reasoningIndex++}`;
1433
+ yield {
1434
+ type: "reasoning-start",
1435
+ id: reasoningId,
1436
+ };
1437
+ }
1438
+
1439
+ yield {
1440
+ type: "reasoning-delta",
1441
+ id: reasoningId,
1442
+ delta: part.text,
1443
+ };
1444
+ continue;
1445
+ }
1446
+
1447
+ if (reasoningId) {
1448
+ yield {
1449
+ type: "reasoning-end",
1450
+ id: reasoningId,
1451
+ };
1452
+ reasoningId = null;
1453
+ }
1454
+
1358
1455
  if (typeof part.text === "string" && part.text.length > 0) {
1359
1456
  yield { type: "text-delta", delta: part.text };
1360
1457
  continue;
@@ -1402,6 +1499,13 @@ async function* streamGoogleCompatibleParts(
1402
1499
  }
1403
1500
  }
1404
1501
 
1502
+ if (reasoningId) {
1503
+ yield {
1504
+ type: "reasoning-end",
1505
+ id: reasoningId,
1506
+ };
1507
+ }
1508
+
1405
1509
  yield {
1406
1510
  type: "finish",
1407
1511
  finishReason,
@@ -1462,6 +1566,8 @@ async function* streamOpenAICompatibleParts(
1462
1566
  const decoder = new TextDecoder();
1463
1567
  let buffer = "";
1464
1568
  const toolCalls = new Map<number, OpenAIStreamToolCallState>();
1569
+ let reasoningId: string | null = null;
1570
+ let reasoningIndex = 0;
1465
1571
  let finishReason: string | { unified: string; raw: string } | null = null;
1466
1572
  let usage: { inputTokens?: number; outputTokens?: number; totalTokens?: number } | undefined;
1467
1573
 
@@ -1477,65 +1583,92 @@ async function* streamOpenAICompatibleParts(
1477
1583
 
1478
1584
  const record = readRecord(event);
1479
1585
  usage = extractOpenAIUsage(record) ?? usage;
1480
- const choices = Array.isArray(record?.choices) ? record.choices : [];
1586
+ const choice = extractFirstChoice(record);
1587
+ if (!choice) {
1588
+ continue;
1589
+ }
1481
1590
 
1482
- for (const choiceValue of choices) {
1483
- const choice = readRecord(choiceValue);
1484
- if (!choice) {
1485
- continue;
1591
+ const delta = readRecord(choice.delta);
1592
+ if (typeof delta?.reasoning_content === "string" && delta.reasoning_content.length > 0) {
1593
+ if (!reasoningId) {
1594
+ reasoningId = `reasoning-${reasoningIndex++}`;
1595
+ yield {
1596
+ type: "reasoning-start",
1597
+ id: reasoningId,
1598
+ };
1486
1599
  }
1487
1600
 
1488
- const delta = readRecord(choice.delta);
1489
- const textDelta = extractOpenAIContentText(delta?.content);
1490
- if (textDelta.length > 0) {
1491
- yield { type: "text-delta", delta: textDelta };
1492
- }
1601
+ yield {
1602
+ type: "reasoning-delta",
1603
+ id: reasoningId,
1604
+ delta: delta.reasoning_content,
1605
+ };
1606
+ }
1493
1607
 
1494
- const rawToolCalls = Array.isArray(delta?.tool_calls) ? delta.tool_calls : [];
1495
- for (const rawToolCall of rawToolCalls) {
1496
- const toolCallRecord = readRecord(rawToolCall);
1497
- const index = typeof toolCallRecord?.index === "number" ? toolCallRecord.index : 0;
1498
- const current = toolCalls.get(index) ?? {
1499
- id: typeof toolCallRecord?.id === "string" ? toolCallRecord.id : `tool-${index}`,
1500
- name: "",
1501
- arguments: "",
1502
- started: false,
1608
+ const textDelta = extractOpenAIContentText(delta?.content);
1609
+ if (textDelta.length > 0) {
1610
+ if (reasoningId) {
1611
+ yield {
1612
+ type: "reasoning-end",
1613
+ id: reasoningId,
1503
1614
  };
1615
+ reasoningId = null;
1616
+ }
1617
+ yield { type: "text-delta", delta: textDelta };
1618
+ }
1504
1619
 
1505
- if (typeof toolCallRecord?.id === "string") {
1506
- current.id = toolCallRecord.id;
1507
- }
1620
+ const rawToolCalls = Array.isArray(delta?.tool_calls) ? delta.tool_calls : [];
1621
+ for (const rawToolCall of rawToolCalls) {
1622
+ if (reasoningId) {
1623
+ yield {
1624
+ type: "reasoning-end",
1625
+ id: reasoningId,
1626
+ };
1627
+ reasoningId = null;
1628
+ }
1508
1629
 
1509
- const fn = readRecord(toolCallRecord?.function);
1510
- if (typeof fn?.name === "string") {
1511
- current.name = fn.name;
1512
- }
1630
+ const toolCallRecord = readRecord(rawToolCall);
1631
+ const index = typeof toolCallRecord?.index === "number" ? toolCallRecord.index : 0;
1632
+ const current = toolCalls.get(index) ?? {
1633
+ id: typeof toolCallRecord?.id === "string" ? toolCallRecord.id : `tool-${index}`,
1634
+ name: "",
1635
+ arguments: "",
1636
+ started: false,
1637
+ };
1513
1638
 
1514
- if (!current.started && current.name.length > 0) {
1515
- current.started = true;
1516
- yield {
1517
- type: "tool-input-start",
1518
- id: current.id,
1519
- toolName: current.name,
1520
- };
1521
- }
1639
+ if (typeof toolCallRecord?.id === "string") {
1640
+ current.id = toolCallRecord.id;
1641
+ }
1522
1642
 
1523
- if (typeof fn?.arguments === "string" && fn.arguments.length > 0) {
1524
- current.arguments += fn.arguments;
1525
- yield {
1526
- type: "tool-input-delta",
1527
- id: current.id,
1528
- delta: fn.arguments,
1529
- };
1530
- }
1643
+ const fn = readRecord(toolCallRecord?.function);
1644
+ if (typeof fn?.name === "string") {
1645
+ current.name = fn.name;
1646
+ }
1531
1647
 
1532
- toolCalls.set(index, current);
1648
+ if (!current.started && current.name.length > 0) {
1649
+ current.started = true;
1650
+ yield {
1651
+ type: "tool-input-start",
1652
+ id: current.id,
1653
+ toolName: current.name,
1654
+ };
1533
1655
  }
1534
1656
 
1535
- const normalizedFinishReason = normalizeOpenAIFinishReason(choice.finish_reason);
1536
- if (normalizedFinishReason) {
1537
- finishReason = normalizedFinishReason;
1657
+ if (typeof fn?.arguments === "string" && fn.arguments.length > 0) {
1658
+ current.arguments += fn.arguments;
1659
+ yield {
1660
+ type: "tool-input-delta",
1661
+ id: current.id,
1662
+ delta: fn.arguments,
1663
+ };
1538
1664
  }
1665
+
1666
+ toolCalls.set(index, current);
1667
+ }
1668
+
1669
+ const normalizedFinishReason = normalizeOpenAIFinishReason(choice.finish_reason);
1670
+ if (normalizedFinishReason) {
1671
+ finishReason = normalizedFinishReason;
1539
1672
  }
1540
1673
  }
1541
1674
  }
@@ -1552,6 +1685,13 @@ async function* streamOpenAICompatibleParts(
1552
1685
  }
1553
1686
  }
1554
1687
 
1688
+ if (reasoningId) {
1689
+ yield {
1690
+ type: "reasoning-end",
1691
+ id: reasoningId,
1692
+ };
1693
+ }
1694
+
1555
1695
  if (
1556
1696
  finishReason &&
1557
1697
  typeof finishReason === "object" &&
@@ -22,7 +22,7 @@ export interface CodeBlockProps {
22
22
  }
23
23
 
24
24
  const ESM_REACT_MARKDOWN =
25
- "https://esm.sh/react-markdown@9.0.3?external=react&target=es2022&pin=v135";
25
+ "https://esm.sh/react-markdown@9.0.3?target=es2022&pin=v135&deps=react@19.2.4";
26
26
  const ESM_REMARK_GFM = "https://esm.sh/remark-gfm@4.0.1?target=es2022&pin=v135";
27
27
  const ESM_REHYPE_HIGHLIGHT = "https://esm.sh/rehype-highlight@7.0.2?target=es2022&pin=v135";
28
28
  const ESM_MERMAID = "https://esm.sh/mermaid@11.4.1?pin=v135";
@@ -41,7 +41,7 @@ type MermaidModule = {
41
41
  };
42
42
 
43
43
  async function importFromUrl<T>(url: string): Promise<T> {
44
- return await import(url) as T;
44
+ return await import(/* @vite-ignore */ url) as T;
45
45
  }
46
46
 
47
47
  // deno-lint-ignore no-explicit-any
@@ -529,6 +529,7 @@ export const FRAMEWORK_CANDIDATES: readonly string[] = [
529
529
  "@internal",
530
530
  "@media(prefers-color-scheme:dark){[data-vf-chat]:not([data-vf-theme]){${dark}}}",
531
531
  "@module",
532
+ "@vite-ignore",
532
533
  "A",
533
534
  "ACTION_BUTTON",
534
535
  "AI",
@@ -2602,6 +2603,7 @@ export const FRAMEWORK_CANDIDATES: readonly string[] = [
2602
2603
  "deno-lint-ignore",
2603
2604
  "dependency)",
2604
2605
  "deprecated,",
2606
+ "deps=react@19.2.4",
2605
2607
  "desc",
2606
2608
  "descendant",
2607
2609
  "describe(",
@@ -3143,7 +3145,7 @@ export const FRAMEWORK_CANDIDATES: readonly string[] = [
3143
3145
  "html><html><head><style",
3144
3146
  "https://ai-sdk.dev/elements)",
3145
3147
  "https://esm.sh/mermaid@11.4.1?pin=v135",
3146
- "https://esm.sh/react-markdown@9.0.3?external=react",
3148
+ "https://esm.sh/react-markdown@9.0.3?target=es2022",
3147
3149
  "https://esm.sh/rehype-highlight@7.0.2?target=es2022",
3148
3150
  "https://esm.sh/remark-gfm@4.0.1?target=es2022",
3149
3151
  "https://example.com/",
@@ -3190,7 +3192,7 @@ export const FRAMEWORK_CANDIDATES: readonly string[] = [
3190
3192
  "if",
3191
3193
  "ignores",
3192
3194
  "import",
3193
- "import(url)",
3195
+ "import(/*",
3194
3196
  "importFromUrl<DefaultModule<unknown>>(ESM_REACT_MARKDOWN),",
3195
3197
  "importFromUrl<DefaultModule<unknown>>(ESM_REHYPE_HIGHLIGHT),",
3196
3198
  "importFromUrl<DefaultModule<unknown>>(ESM_REMARK_GFM),",
@@ -4883,7 +4885,6 @@ export const FRAMEWORK_CANDIDATES: readonly string[] = [
4883
4885
  "take",
4884
4886
  "target",
4885
4887
  "target=",
4886
- "target=es2022",
4887
4888
  "tbody>",
4888
4889
  "tc1",
4889
4890
  "td",
@@ -5206,6 +5207,7 @@ export const FRAMEWORK_CANDIDATES: readonly string[] = [
5206
5207
  "upward",
5207
5208
  "url",
5208
5209
  "url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600",
5210
+ "url)",
5209
5211
  "url:",
5210
5212
  "url;",
5211
5213
  "url?:",
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.197";
3
+ export const VERSION = "0.1.199";