@chat-js/cli 0.6.1 → 0.6.3

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 (154) hide show
  1. package/dist/index.js +17065 -16667
  2. package/package.json +1 -1
  3. package/templates/chat-app/app/(auth)/login/page.tsx +3 -3
  4. package/templates/chat-app/app/(chat)/api/chat/route.ts +4 -60
  5. package/templates/chat-app/app/not-found.tsx +2 -2
  6. package/templates/chat-app/chat.config.ts +3 -0
  7. package/templates/chat-app/components/ai-elements/actions.tsx +44 -44
  8. package/templates/chat-app/components/ai-elements/artifact.tsx +92 -92
  9. package/templates/chat-app/components/ai-elements/code-block.tsx +143 -143
  10. package/templates/chat-app/components/ai-elements/context.tsx +313 -313
  11. package/templates/chat-app/components/ai-elements/conversation.tsx +65 -65
  12. package/templates/chat-app/components/ai-elements/extra/conversation-content-scroll-area.tsx +29 -29
  13. package/templates/chat-app/components/ai-elements/extra/mcp-tool-header.tsx +27 -27
  14. package/templates/chat-app/components/ai-elements/message.tsx +341 -344
  15. package/templates/chat-app/components/ai-elements/parseIncompleteMarkdown.tsx +122 -122
  16. package/templates/chat-app/components/ai-elements/prompt-input.tsx +1059 -1059
  17. package/templates/chat-app/components/ai-elements/reasoning.tsx +131 -131
  18. package/templates/chat-app/components/ai-elements/response.tsx +15 -12
  19. package/templates/chat-app/components/ai-elements/sandbox.tsx +84 -84
  20. package/templates/chat-app/components/ai-elements/shimmer.tsx +47 -47
  21. package/templates/chat-app/components/ai-elements/suggestion.tsx +33 -33
  22. package/templates/chat-app/components/ai-elements/tool.tsx +118 -118
  23. package/templates/chat-app/components/app-sidebar-history-conditional.tsx +3 -3
  24. package/templates/chat-app/components/app-sidebar.tsx +3 -3
  25. package/templates/chat-app/components/connectors-dropdown.tsx +6 -3
  26. package/templates/chat-app/components/deep-research-progress.tsx +1 -1
  27. package/templates/chat-app/components/header-breadcrumb.tsx +14 -11
  28. package/templates/chat-app/components/internal-link.tsx +73 -0
  29. package/templates/chat-app/components/login-form.tsx +5 -5
  30. package/templates/chat-app/components/message-parts.tsx +1 -71
  31. package/templates/chat-app/components/model-selector.tsx +3 -3
  32. package/templates/chat-app/components/new-chat-button.tsx +4 -4
  33. package/templates/chat-app/components/part/document-common.tsx +3 -3
  34. package/templates/chat-app/components/part/document-tool.tsx +3 -3
  35. package/templates/chat-app/components/part/message-annotations.tsx +2 -2
  36. package/templates/chat-app/components/part/tool-part.tsx +92 -0
  37. package/templates/chat-app/components/project-chat-item.tsx +2 -2
  38. package/templates/chat-app/components/research-progress.tsx +2 -2
  39. package/templates/chat-app/components/research-task.tsx +1 -1
  40. package/templates/chat-app/components/research-tasks.tsx +1 -1
  41. package/templates/chat-app/components/settings/connectors-settings.tsx +4 -4
  42. package/templates/chat-app/components/settings/mcp-details-page.tsx +5 -5
  43. package/templates/chat-app/components/settings/settings-nav.tsx +3 -3
  44. package/templates/chat-app/components/sidebar-chat-item.tsx +4 -12
  45. package/templates/chat-app/components/sidebar-project-item.tsx +4 -11
  46. package/templates/chat-app/components/sidebar-top-row.tsx +7 -7
  47. package/templates/chat-app/components/sidebar-user-nav.tsx +3 -3
  48. package/templates/chat-app/components/signup-form.tsx +8 -5
  49. package/templates/chat-app/components/source-badge.tsx +3 -9
  50. package/templates/chat-app/components/sources.tsx +1 -1
  51. package/templates/chat-app/components/ui/accordion.tsx +32 -32
  52. package/templates/chat-app/components/ui/alert-dialog.tsx +103 -103
  53. package/templates/chat-app/components/ui/alert.tsx +36 -36
  54. package/templates/chat-app/components/ui/avatar.tsx +28 -28
  55. package/templates/chat-app/components/ui/badge.tsx +22 -22
  56. package/templates/chat-app/components/ui/breadcrumb.tsx +72 -72
  57. package/templates/chat-app/components/ui/button-group.tsx +58 -58
  58. package/templates/chat-app/components/ui/button.tsx +45 -45
  59. package/templates/chat-app/components/ui/card.tsx +65 -65
  60. package/templates/chat-app/components/ui/checkbox.tsx +16 -16
  61. package/templates/chat-app/components/ui/collapsible.tsx +1 -1
  62. package/templates/chat-app/components/ui/command.tsx +137 -137
  63. package/templates/chat-app/components/ui/dialog.tsx +94 -94
  64. package/templates/chat-app/components/ui/drawer.tsx +68 -68
  65. package/templates/chat-app/components/ui/dropdown-menu.tsx +184 -184
  66. package/templates/chat-app/components/ui/empty.tsx +76 -76
  67. package/templates/chat-app/components/ui/extra/action-container.tsx +3 -3
  68. package/templates/chat-app/components/ui/extra/scroll-area-viewport-ref.tsx +24 -24
  69. package/templates/chat-app/components/ui/form.tsx +112 -112
  70. package/templates/chat-app/components/ui/hover-card.tsx +25 -25
  71. package/templates/chat-app/components/ui/input-group.tsx +126 -126
  72. package/templates/chat-app/components/ui/input.tsx +13 -13
  73. package/templates/chat-app/components/ui/label.tsx +12 -12
  74. package/templates/chat-app/components/ui/popover.tsx +25 -25
  75. package/templates/chat-app/components/ui/progress.tsx +19 -19
  76. package/templates/chat-app/components/ui/resizable.tsx +27 -27
  77. package/templates/chat-app/components/ui/scroll-area.tsx +30 -30
  78. package/templates/chat-app/components/ui/select.tsx +108 -108
  79. package/templates/chat-app/components/ui/separator.tsx +16 -16
  80. package/templates/chat-app/components/ui/sheet.tsx +91 -91
  81. package/templates/chat-app/components/ui/sidebar.tsx +615 -615
  82. package/templates/chat-app/components/ui/skeleton.tsx +7 -7
  83. package/templates/chat-app/components/ui/slider.tsx +50 -50
  84. package/templates/chat-app/components/ui/spinner.tsx +8 -8
  85. package/templates/chat-app/components/ui/switch.tsx +16 -16
  86. package/templates/chat-app/components/ui/table.tsx +71 -71
  87. package/templates/chat-app/components/ui/tabs.tsx +31 -31
  88. package/templates/chat-app/components/ui/textarea.tsx +10 -10
  89. package/templates/chat-app/components/ui/toggle.tsx +31 -31
  90. package/templates/chat-app/components/ui/tooltip.tsx +48 -48
  91. package/templates/chat-app/components/upgrade-cta/limit-display.tsx +7 -7
  92. package/templates/chat-app/components/upgrade-cta/login-cta-banner.tsx +3 -3
  93. package/templates/chat-app/components/upgrade-cta/login-prompt.tsx +3 -3
  94. package/templates/chat-app/hooks/use-mobile.ts +13 -13
  95. package/templates/chat-app/lib/ai/core-chat-agent.ts +25 -14
  96. package/templates/chat-app/lib/ai/eval-agent.ts +4 -5
  97. package/templates/chat-app/lib/ai/gateway-model-defaults.ts +24 -0
  98. package/templates/chat-app/lib/ai/installed-tools.ts +12 -0
  99. package/templates/chat-app/lib/ai/mcp/mcp-client.ts +2 -2
  100. package/templates/chat-app/lib/ai/models.generated.ts +4236 -4585
  101. package/templates/chat-app/lib/ai/tool-renderer-registry.ts +31 -0
  102. package/templates/chat-app/lib/ai/types.ts +15 -20
  103. package/templates/chat-app/lib/config-requirements.ts +11 -6
  104. package/templates/chat-app/lib/config-schema.ts +24 -0
  105. package/templates/chat-app/lib/stores/hooks-message-parts.ts +1 -1
  106. package/templates/chat-app/lib/utils.ts +157 -157
  107. package/templates/chat-app/package.json +1 -1
  108. package/templates/chat-app/scripts/check-env.ts +229 -2
  109. package/templates/chat-app/tools/chatjs/_shared/lib/tool-part.ts +5 -0
  110. package/templates/chat-app/{components/part/weather.tsx → tools/chatjs/get-weather/renderer.tsx} +24 -38
  111. package/templates/chat-app/{components/part/retrieve-url.tsx → tools/chatjs/retrieve-url/renderer.tsx} +20 -15
  112. package/templates/chat-app/{lib/ai/tools/retrieve-url.ts → tools/chatjs/retrieve-url/tool.ts} +46 -7
  113. package/templates/chat-app/tools/chatjs/tools.ts +16 -0
  114. package/templates/chat-app/tools/chatjs/ui.ts +17 -0
  115. package/templates/chat-app/tools/chatjs/word-count/renderer.tsx +50 -0
  116. package/templates/chat-app/tools/chatjs/word-count/tool.ts +30 -0
  117. package/templates/chat-app/{lib/ai/tools → tools/platform}/code-execution.ts +3 -5
  118. package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/deep-research.ts +2 -3
  119. package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/pipeline.ts +1 -1
  120. package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/types.ts +1 -1
  121. package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/utils.ts +7 -7
  122. package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/types.ts +1 -1
  123. package/templates/chat-app/{lib/ai/tools → tools/platform}/generate-video.ts +4 -6
  124. package/templates/chat-app/{lib/ai/tools → tools/platform}/read-document.ts +2 -2
  125. package/templates/chat-app/{lib/ai/tools → tools/platform}/steps/multi-query-web-search.ts +1 -1
  126. package/templates/chat-app/{lib/ai/tools → tools/platform}/steps/web-search.ts +1 -1
  127. package/templates/chat-app/{lib/ai/tools → tools/platform}/tools.ts +54 -30
  128. package/templates/chat-app/{lib/ai/tools → tools/platform}/web-search.ts +7 -5
  129. package/templates/electron/CHANGELOG.md +16 -2
  130. package/templates/electron/package.json +1 -1
  131. package/templates/chat-app/lib/ai/tools/tools-definitions.ts +0 -83
  132. /package/templates/chat-app/{lib/ai/tools/get-weather.ts → tools/chatjs/get-weather/tool.ts} +0 -0
  133. /package/templates/chat-app/{lib/ai/tools → tools/platform}/code-execution.javascript.ts +0 -0
  134. /package/templates/chat-app/{lib/ai/tools → tools/platform}/code-execution.python.ts +0 -0
  135. /package/templates/chat-app/{lib/ai/tools → tools/platform}/code-execution.shared.test.ts +0 -0
  136. /package/templates/chat-app/{lib/ai/tools → tools/platform}/code-execution.shared.ts +0 -0
  137. /package/templates/chat-app/{lib/ai/tools → tools/platform}/code-execution.types.ts +0 -0
  138. /package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/configuration.ts +0 -0
  139. /package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/prompts.ts +0 -0
  140. /package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/researcher-agent.ts +0 -0
  141. /package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/supervisor-agent.ts +0 -0
  142. /package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/code-guidelines.ts +0 -0
  143. /package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/create-code-document.ts +0 -0
  144. /package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/create-sheet-document.ts +0 -0
  145. /package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/create-text-document.ts +0 -0
  146. /package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/edit-code-document.ts +0 -0
  147. /package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/edit-sheet-document.ts +0 -0
  148. /package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/edit-text-document.ts +0 -0
  149. /package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/sheet-guidelines.ts +0 -0
  150. /package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/text-guidelines.ts +0 -0
  151. /package/templates/chat-app/{lib/ai/tools → tools/platform}/generate-image.ts +0 -0
  152. /package/templates/chat-app/{lib/ai/tools → tools/platform}/research-updates-schema.ts +0 -0
  153. /package/templates/chat-app/{lib/ai/tools → tools/platform}/steps/search-utils.ts +0 -0
  154. /package/templates/chat-app/{lib/ai/tools → tools/platform}/types.ts +0 -0
@@ -0,0 +1,31 @@
1
+ import type { ToolUIPart } from "ai";
2
+ import type { ComponentType } from "react";
3
+ import { ui } from "@/tools/chatjs/ui";
4
+ import type { InstalledTools, installedTools } from "./installed-tools";
5
+
6
+ export type InstalledToolName = keyof typeof installedTools;
7
+ export type InstalledToolType = `tool-${InstalledToolName & string}`;
8
+ export type InstalledToolUIPart = ToolUIPart<InstalledTools>;
9
+
10
+ export type InstalledToolPart<T extends InstalledToolType> = Extract<
11
+ InstalledToolUIPart,
12
+ { type: T }
13
+ >;
14
+
15
+ export type ToolRendererProps<T extends InstalledToolType> = {
16
+ tool: InstalledToolPart<T>;
17
+ messageId: string;
18
+ isReadonly: boolean;
19
+ };
20
+
21
+ export type ToolRendererRegistry = {
22
+ [K in InstalledToolType]: ComponentType<ToolRendererProps<K>>;
23
+ };
24
+
25
+ export const toolRendererRegistry = ui satisfies ToolRendererRegistry;
26
+
27
+ export function isInstalledToolType(
28
+ type: string
29
+ ): type is keyof typeof toolRendererRegistry {
30
+ return Object.hasOwn(toolRendererRegistry, type);
31
+ }
@@ -5,22 +5,21 @@ import type {
5
5
  UIMessageStreamWriter,
6
6
  } from "ai";
7
7
  import { z } from "zod";
8
- import type { codeExecution } from "@/lib/ai/tools/code-execution";
9
- import type { deepResearch } from "@/lib/ai/tools/deep-research/deep-research";
10
- import type { generateImageTool as generateImageToolFactory } from "@/lib/ai/tools/generate-image";
11
- import type { generateVideoTool as generateVideoToolFactory } from "@/lib/ai/tools/generate-video";
12
- import type { getWeather } from "@/lib/ai/tools/get-weather";
13
- import type { readDocument } from "@/lib/ai/tools/read-document";
14
- import type { retrieveUrl } from "@/lib/ai/tools/retrieve-url";
15
- import type { tavilyWebSearch } from "@/lib/ai/tools/web-search";
8
+ import type { codeExecution } from "@/tools/platform/code-execution";
9
+ import type { deepResearch } from "@/tools/platform/deep-research/deep-research";
10
+ import type { createCodeDocumentTool } from "@/tools/platform/documents/create-code-document";
11
+ import type { createSheetDocumentTool } from "@/tools/platform/documents/create-sheet-document";
12
+ import type { createTextDocumentTool } from "@/tools/platform/documents/create-text-document";
13
+ import type { editCodeDocumentTool } from "@/tools/platform/documents/edit-code-document";
14
+ import type { editSheetDocumentTool } from "@/tools/platform/documents/edit-sheet-document";
15
+ import type { editTextDocumentTool } from "@/tools/platform/documents/edit-text-document";
16
+ import type { generateImageTool as generateImageToolFactory } from "@/tools/platform/generate-image";
17
+ import type { generateVideoTool as generateVideoToolFactory } from "@/tools/platform/generate-video";
18
+ import type { readDocument } from "@/tools/platform/read-document";
19
+ import type { ResearchUpdate } from "@/tools/platform/research-updates-schema";
20
+ import type { tavilyWebSearch } from "@/tools/platform/web-search";
16
21
  import type { AppModelId } from "./app-models";
17
- import type { createCodeDocumentTool } from "./tools/documents/create-code-document";
18
- import type { createSheetDocumentTool } from "./tools/documents/create-sheet-document";
19
- import type { createTextDocumentTool } from "./tools/documents/create-text-document";
20
- import type { editCodeDocumentTool } from "./tools/documents/edit-code-document";
21
- import type { editSheetDocumentTool } from "./tools/documents/edit-sheet-document";
22
- import type { editTextDocumentTool } from "./tools/documents/edit-text-document";
23
- import type { ResearchUpdate } from "./tools/research-updates-schema";
22
+ import type { InstalledTools } from "./installed-tools";
24
23
 
25
24
  export const toolNameSchema = z.enum([
26
25
  "getWeather",
@@ -143,7 +142,6 @@ const messageMetadataSchema = z.object({
143
142
 
144
143
  export type MessageMetadata = z.infer<typeof messageMetadataSchema>;
145
144
 
146
- type weatherTool = InferUITool<typeof getWeather>;
147
145
  type createTextDocumentToolType = InferUITool<
148
146
  ReturnType<typeof createTextDocumentTool>
149
147
  >;
@@ -172,7 +170,6 @@ type generateVideoTool = InferUITool<
172
170
  >;
173
171
  type webSearchTool = InferUITool<ReturnType<typeof tavilyWebSearch>>;
174
172
  type codeExecutionTool = InferUITool<ReturnType<typeof codeExecution>>;
175
- type retrieveUrlTool = InferUITool<typeof retrieveUrl>;
176
173
 
177
174
  export type ChatTools = {
178
175
  codeExecution: codeExecutionTool;
@@ -185,11 +182,9 @@ export type ChatTools = {
185
182
  editTextDocument: editTextDocumentToolType;
186
183
  generateImage: generateImageTool;
187
184
  generateVideo: generateVideoTool;
188
- getWeather: weatherTool;
189
185
  readDocument: readDocumentTool;
190
- retrieveUrl: retrieveUrlTool;
191
186
  webSearch: webSearchTool;
192
- };
187
+ } & InstalledTools;
193
188
 
194
189
  interface FollowupSuggestions {
195
190
  suggestions: string[];
@@ -8,10 +8,19 @@ import type {
8
8
  type EnvVarName = keyof NodeJS.ProcessEnv;
9
9
 
10
10
  export interface EnvRequirement {
11
- description: string;
11
+ description?: string;
12
12
  options: EnvVarName[][];
13
13
  }
14
14
 
15
+ export function formatRequirementDescription(
16
+ requirement: EnvRequirement
17
+ ): string {
18
+ return (
19
+ requirement.description ??
20
+ requirement.options.map((option) => option.join(" + ")).join(" or ")
21
+ );
22
+ }
23
+
15
24
  export const gatewayEnvRequirements: Record<GatewayType, EnvRequirement> = {
16
25
  openrouter: {
17
26
  options: [["OPENROUTER_API_KEY"]],
@@ -51,10 +60,6 @@ export const aiToolEnvRequirements: Partial<
51
60
  options: [["TAVILY_API_KEY"], ["FIRECRAWL_API_KEY"]],
52
61
  description: "TAVILY_API_KEY or FIRECRAWL_API_KEY",
53
62
  },
54
- urlRetrieval: {
55
- options: [["FIRECRAWL_API_KEY"]],
56
- description: "FIRECRAWL_API_KEY",
57
- },
58
63
  mcp: {
59
64
  options: [["MCP_ENCRYPTION_KEY"]],
60
65
  description: "MCP_ENCRYPTION_KEY",
@@ -106,5 +111,5 @@ export function getMissingRequirement(
106
111
  ): string | null {
107
112
  return isRequirementSatisfied(requirement, env)
108
113
  ? null
109
- : requirement.description;
114
+ : formatRequirementDescription(requirement);
110
115
  }
@@ -92,6 +92,14 @@ function createAiSchema<G extends GatewayType>(g: G) {
92
92
  mcp: z.object({
93
93
  enabled: z.boolean(),
94
94
  }),
95
+ documents: z.object({
96
+ enabled: z.boolean(),
97
+ types: z.object({
98
+ text: z.boolean(),
99
+ code: z.boolean(),
100
+ sheet: z.boolean(),
101
+ }),
102
+ }),
95
103
  followupSuggestions: z.object({
96
104
  enabled: z.boolean(),
97
105
  default: gatewayModelId<G>(),
@@ -253,6 +261,16 @@ export const authenticationConfigSchema = z
253
261
  github: true,
254
262
  vercel: false,
255
263
  });
264
+ export const pathsConfigSchema = z
265
+ .object({
266
+ tools: z
267
+ .string()
268
+ .describe(
269
+ "Import alias for the installable tools registry index and tool files"
270
+ )
271
+ .default("@/tools/chatjs"),
272
+ })
273
+ .default({ tools: "@/tools/chatjs" });
256
274
 
257
275
  export const desktopAppConfigSchema = z
258
276
  .object({
@@ -343,6 +361,8 @@ export const configSchema = z.object({
343
361
  anonymous: anonymousConfigSchema,
344
362
 
345
363
  attachments: attachmentsConfigSchema,
364
+
365
+ paths: pathsConfigSchema,
346
366
  });
347
367
 
348
368
  // Output types (after defaults applied)
@@ -352,6 +372,7 @@ export type AiConfig = z.infer<typeof aiConfigSchema>;
352
372
  export type AnonymousConfig = z.infer<typeof anonymousConfigSchema>;
353
373
  export type AttachmentsConfig = z.infer<typeof attachmentsConfigSchema>;
354
374
  export type FeaturesConfig = z.infer<typeof featuresConfigSchema>;
375
+ export type PathsConfig = z.infer<typeof pathsConfigSchema>;
355
376
  export type AuthenticationConfig = z.infer<typeof authenticationConfigSchema>;
356
377
  export type DesktopAppConfig = z.infer<typeof desktopAppConfigSchema>;
357
378
 
@@ -391,6 +412,9 @@ interface AiToolsInputFor<G extends GatewayType> {
391
412
  code?: Partial<{ [P in keyof AiToolsShape["code"]]: GatewayModelIdMap[G] }>;
392
413
  codeExecution?: Partial<AiToolsShape["codeExecution"]>;
393
414
  deepResearch?: DeepResearchToolInputFor<G>;
415
+ documents?: Partial<Omit<AiToolsShape["documents"], "types">> & {
416
+ types?: AiToolsShape["documents"]["types"];
417
+ };
394
418
  followupSuggestions?: FollowupSuggestionsToolInputFor<G>;
395
419
  image?: ImageToolInputFor<G>;
396
420
  mcp?: Partial<AiToolsShape["mcp"]>;
@@ -3,7 +3,7 @@
3
3
  import equal from "fast-deep-equal";
4
4
  import { shallow } from "zustand/shallow";
5
5
  import { useStoreWithEqualityFn } from "zustand/traditional";
6
- import { documentToolTypes } from "../ai/tools/documents/types";
6
+ import { documentToolTypes } from "@/tools/platform/documents/types";
7
7
  import type { ChatMessage } from "../ai/types";
8
8
  import {
9
9
  type CustomChatStoreState,
@@ -8,212 +8,212 @@ import { ChatSDKError, type ErrorCode } from "./ai/errors";
8
8
  import type { Attachment, ChatMessage } from "./ai/types";
9
9
 
10
10
  export function cn(...inputs: ClassValue[]) {
11
- return twMerge(clsx(inputs));
11
+ return twMerge(clsx(inputs));
12
12
  }
13
13
 
14
14
  interface ApplicationError extends Error {
15
- info: string;
16
- status: number;
15
+ info: string;
16
+ status: number;
17
17
  }
18
18
 
19
19
  export async function fetchWithErrorHandlers(
20
- input: RequestInfo | URL,
21
- init?: RequestInit
20
+ input: RequestInfo | URL,
21
+ init?: RequestInit,
22
22
  ) {
23
- try {
24
- const response = await fetch(input, init);
25
-
26
- if (!response.ok) {
27
- const { code, cause } = await response.json();
28
- throw new ChatSDKError(code as ErrorCode, cause);
29
- }
30
-
31
- return response;
32
- } catch (error: unknown) {
33
- if (typeof navigator !== "undefined" && !navigator.onLine) {
34
- throw new ChatSDKError("offline:chat");
35
- }
36
-
37
- throw error;
38
- }
23
+ try {
24
+ const response = await fetch(input, init);
25
+
26
+ if (!response.ok) {
27
+ const { code, cause } = await response.json();
28
+ throw new ChatSDKError(code as ErrorCode, cause);
29
+ }
30
+
31
+ return response;
32
+ } catch (error: unknown) {
33
+ if (typeof navigator !== "undefined" && !navigator.onLine) {
34
+ throw new ChatSDKError("offline:chat");
35
+ }
36
+
37
+ throw error;
38
+ }
39
39
  }
40
40
 
41
41
  function findLastArtifact(
42
- messages: Array<ChatMessage>
42
+ messages: Array<ChatMessage>,
43
43
  ): { messageIndex: number; toolCallId: string } | null {
44
- const allArtifacts: Array<{ messageIndex: number; toolCallId: string }> = [];
45
-
46
- messages.forEach((msg, messageIndex) => {
47
- msg.parts?.forEach((part) => {
48
- if (
49
- (part.type === "tool-createTextDocument" ||
50
- part.type === "tool-createCodeDocument" ||
51
- part.type === "tool-createSheetDocument" ||
52
- part.type === "tool-editTextDocument" ||
53
- part.type === "tool-editCodeDocument" ||
54
- part.type === "tool-editSheetDocument" ||
55
- part.type === "tool-deepResearch") &&
56
- part.state === "output-available"
57
- ) {
58
- allArtifacts.push({
59
- messageIndex,
60
- toolCallId: part.toolCallId,
61
- });
62
- }
63
- });
64
- });
65
-
66
- return allArtifacts[allArtifacts.length - 1] || null;
44
+ const allArtifacts: Array<{ messageIndex: number; toolCallId: string }> = [];
45
+
46
+ messages.forEach((msg, messageIndex) => {
47
+ msg.parts?.forEach((part) => {
48
+ if (
49
+ (part.type === "tool-createTextDocument" ||
50
+ part.type === "tool-createCodeDocument" ||
51
+ part.type === "tool-createSheetDocument" ||
52
+ part.type === "tool-editTextDocument" ||
53
+ part.type === "tool-editCodeDocument" ||
54
+ part.type === "tool-editSheetDocument" ||
55
+ part.type === "tool-deepResearch") &&
56
+ part.state === "output-available"
57
+ ) {
58
+ allArtifacts.push({
59
+ messageIndex,
60
+ toolCallId: part.toolCallId,
61
+ });
62
+ }
63
+ });
64
+ });
65
+
66
+ return allArtifacts[allArtifacts.length - 1] || null;
67
67
  }
68
68
 
69
69
  const fetcher = async (url: string) => {
70
- const res = await fetch(url);
70
+ const res = await fetch(url);
71
71
 
72
- if (!res.ok) {
73
- const error = new Error(
74
- "An error occurred while fetching the data."
75
- ) as ApplicationError;
72
+ if (!res.ok) {
73
+ const error = new Error(
74
+ "An error occurred while fetching the data.",
75
+ ) as ApplicationError;
76
76
 
77
- error.info = await res.json();
78
- error.status = res.status;
77
+ error.info = await res.json();
78
+ error.status = res.status;
79
79
 
80
- throw error;
81
- }
80
+ throw error;
81
+ }
82
82
 
83
- return res.json();
83
+ return res.json();
84
84
  };
85
85
 
86
86
  function getLocalStorage(key: string) {
87
- if (typeof window !== "undefined") {
88
- return JSON.parse(localStorage.getItem(key) || "[]");
89
- }
90
- return [];
87
+ if (typeof window !== "undefined") {
88
+ return JSON.parse(localStorage.getItem(key) || "[]");
89
+ }
90
+ return [];
91
91
  }
92
92
 
93
93
  export function generateUUID(): string {
94
- return uuidv7();
94
+ return uuidv7();
95
95
  }
96
96
 
97
97
  function getMostRecentUserMessage(messages: Array<ChatMessage>) {
98
- const userMessages = messages.filter((message) => message.role === "user");
99
- return userMessages.at(-1);
98
+ const userMessages = messages.filter((message) => message.role === "user");
99
+ return userMessages.at(-1);
100
100
  }
101
101
 
102
102
  function getDocumentTimestampByIndex(
103
- documents: Array<Document>,
104
- index: number
103
+ documents: Array<Document>,
104
+ index: number,
105
105
  ) {
106
- if (!documents) return new Date();
107
- if (index > documents.length) return new Date();
106
+ if (!documents) return new Date();
107
+ if (index > documents.length) return new Date();
108
108
 
109
- return documents[index].createdAt;
109
+ return documents[index].createdAt;
110
110
  }
111
111
 
112
112
  function getTrailingMessageId({
113
- messages,
113
+ messages,
114
114
  }: {
115
- messages: Array<ChatMessage>;
115
+ messages: Array<ChatMessage>;
116
116
  }): string | null {
117
- const trailingMessage = messages.at(-1);
117
+ const trailingMessage = messages.at(-1);
118
118
 
119
- if (!trailingMessage) return null;
119
+ if (!trailingMessage) return null;
120
120
 
121
- return trailingMessage.id;
121
+ return trailingMessage.id;
122
122
  }
123
123
 
124
124
  export function getLanguageFromFileName(fileName: string): string {
125
- const extension = fileName.split(".").pop()?.toLowerCase() || "";
126
-
127
- const extensionToLanguage: Record<string, string> = {
128
- // JavaScript/TypeScript
129
- js: "javascript",
130
- jsx: "jsx",
131
- ts: "typescript",
132
- tsx: "tsx",
133
- mjs: "javascript",
134
- cjs: "javascript",
135
-
136
- // Python
137
- py: "python",
138
- pyw: "python",
139
- pyi: "python",
140
-
141
- // Web
142
- html: "html",
143
- htm: "html",
144
- css: "css",
145
- scss: "css",
146
- sass: "css",
147
- less: "css",
148
-
149
- // Data formats
150
- json: "json",
151
- xml: "xml",
152
- yaml: "yaml",
153
- yml: "yaml",
154
- toml: "toml",
155
-
156
- // Shell
157
- sh: "shell",
158
- bash: "shell",
159
- zsh: "shell",
160
- fish: "shell",
161
-
162
- // Other languages
163
- sql: "sql",
164
- md: "markdown",
165
- mdx: "markdown",
166
- java: "java",
167
- c: "c",
168
- cpp: "cpp",
169
- cc: "cpp",
170
- cxx: "cpp",
171
- h: "c",
172
- hpp: "cpp",
173
- cs: "csharp",
174
- php: "php",
175
- rb: "ruby",
176
- go: "go",
177
- rs: "rust",
178
- swift: "swift",
179
- kt: "kotlin",
180
- r: "r",
181
- R: "r",
182
- };
183
-
184
- return extensionToLanguage[extension] || "python"; // Default to python
125
+ const extension = fileName.split(".").pop()?.toLowerCase() || "";
126
+
127
+ const extensionToLanguage: Record<string, string> = {
128
+ // JavaScript/TypeScript
129
+ js: "javascript",
130
+ jsx: "jsx",
131
+ ts: "typescript",
132
+ tsx: "tsx",
133
+ mjs: "javascript",
134
+ cjs: "javascript",
135
+
136
+ // Python
137
+ py: "python",
138
+ pyw: "python",
139
+ pyi: "python",
140
+
141
+ // Web
142
+ html: "html",
143
+ htm: "html",
144
+ css: "css",
145
+ scss: "css",
146
+ sass: "css",
147
+ less: "css",
148
+
149
+ // Data formats
150
+ json: "json",
151
+ xml: "xml",
152
+ yaml: "yaml",
153
+ yml: "yaml",
154
+ toml: "toml",
155
+
156
+ // Shell
157
+ sh: "shell",
158
+ bash: "shell",
159
+ zsh: "shell",
160
+ fish: "shell",
161
+
162
+ // Other languages
163
+ sql: "sql",
164
+ md: "markdown",
165
+ mdx: "markdown",
166
+ java: "java",
167
+ c: "c",
168
+ cpp: "cpp",
169
+ cc: "cpp",
170
+ cxx: "cpp",
171
+ h: "c",
172
+ hpp: "cpp",
173
+ cs: "csharp",
174
+ php: "php",
175
+ rb: "ruby",
176
+ go: "go",
177
+ rs: "rust",
178
+ swift: "swift",
179
+ kt: "kotlin",
180
+ r: "r",
181
+ R: "r",
182
+ };
183
+
184
+ return extensionToLanguage[extension] || "python"; // Default to python
185
185
  }
186
186
 
187
187
  export function getAttachmentsFromMessage(message: ChatMessage): Attachment[] {
188
- return message.parts
189
- .filter<FileUIPart>((part) => part.type === "file")
190
- .map((part) => ({
191
- name: part.filename || "",
192
- url: part.url,
193
- contentType: part.mediaType,
194
- }));
188
+ return message.parts
189
+ .filter<FileUIPart>((part) => part.type === "file")
190
+ .map((part) => ({
191
+ name: part.filename || "",
192
+ url: part.url,
193
+ contentType: part.mediaType,
194
+ }));
195
195
  }
196
196
 
197
197
  export function getTextContentFromMessage(message: ChatMessage): string {
198
- return message.parts
199
- .filter<TextPart>((part) => part.type === "text")
200
- .map((part) => part.text)
201
- .join("");
198
+ return message.parts
199
+ .filter<TextPart>((part) => part.type === "text")
200
+ .map((part) => part.text)
201
+ .join("");
202
202
  }
203
203
 
204
204
  export function getTextContentFromModelMessage(message: ModelMessage): string {
205
- const content = message.content;
206
-
207
- if (typeof content === "string") {
208
- return content;
209
- }
210
-
211
- return content
212
- .map((part) => {
213
- if (part.type === "text") {
214
- return part.text;
215
- }
216
- return "";
217
- })
218
- .join("\n");
205
+ const content = message.content;
206
+
207
+ if (typeof content === "string") {
208
+ return content;
209
+ }
210
+
211
+ return content
212
+ .map((part) => {
213
+ if (part.type === "text") {
214
+ return part.text;
215
+ }
216
+ return "";
217
+ })
218
+ .join("\n");
219
219
  }
@@ -153,7 +153,7 @@
153
153
  "usehooks-ts": "^3.1.0",
154
154
  "uuid": "^11.1.0",
155
155
  "vaul": "^1.1.2",
156
- "zod": "^4.1.4",
156
+ "zod": "^4.3.6",
157
157
  "zustand": "^5.0.6"
158
158
  },
159
159
  "overrides": {