@chat-js/cli 0.6.0 → 0.6.2

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 +17007 -16480
  2. package/package.json +4 -3
  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/installed-tools.ts +12 -0
  98. package/templates/chat-app/lib/ai/mcp/mcp-client.ts +2 -2
  99. package/templates/chat-app/lib/ai/models.generated.ts +4236 -4585
  100. package/templates/chat-app/lib/ai/tool-renderer-registry.ts +31 -0
  101. package/templates/chat-app/lib/ai/types.ts +15 -20
  102. package/templates/chat-app/lib/config-requirements.ts +11 -6
  103. package/templates/chat-app/lib/config-schema.ts +13 -0
  104. package/templates/chat-app/lib/stores/hooks-message-parts.ts +1 -1
  105. package/templates/chat-app/lib/utils.ts +157 -157
  106. package/templates/chat-app/package.json +3 -2
  107. package/templates/chat-app/scripts/check-env.ts +229 -2
  108. package/templates/chat-app/tools/chatjs/_shared/lib/tool-part.ts +5 -0
  109. package/templates/chat-app/{components/part/weather.tsx → tools/chatjs/get-weather/renderer.tsx} +24 -38
  110. package/templates/chat-app/{components/part/retrieve-url.tsx → tools/chatjs/retrieve-url/renderer.tsx} +20 -15
  111. package/templates/chat-app/{lib/ai/tools/retrieve-url.ts → tools/chatjs/retrieve-url/tool.ts} +46 -7
  112. package/templates/chat-app/tools/chatjs/tools.ts +16 -0
  113. package/templates/chat-app/tools/chatjs/ui.ts +17 -0
  114. package/templates/chat-app/tools/chatjs/word-count/renderer.tsx +50 -0
  115. package/templates/chat-app/tools/chatjs/word-count/tool.ts +30 -0
  116. package/templates/chat-app/{lib/ai/tools → tools/platform}/code-execution.ts +3 -5
  117. package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/deep-research.ts +2 -3
  118. package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/pipeline.ts +1 -1
  119. package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/types.ts +1 -1
  120. package/templates/chat-app/{lib/ai/tools → tools/platform}/deep-research/utils.ts +7 -7
  121. package/templates/chat-app/{lib/ai/tools → tools/platform}/documents/types.ts +1 -1
  122. package/templates/chat-app/{lib/ai/tools → tools/platform}/generate-video.ts +4 -6
  123. package/templates/chat-app/{lib/ai/tools → tools/platform}/read-document.ts +2 -2
  124. package/templates/chat-app/{lib/ai/tools → tools/platform}/steps/multi-query-web-search.ts +1 -1
  125. package/templates/chat-app/{lib/ai/tools → tools/platform}/steps/web-search.ts +1 -1
  126. package/templates/chat-app/{lib/ai/tools → tools/platform}/tools.ts +20 -20
  127. package/templates/chat-app/{lib/ai/tools → tools/platform}/web-search.ts +7 -5
  128. package/templates/electron/CHANGELOG.md +7 -1
  129. package/templates/electron/forge.config.ts +1 -6
  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
@@ -5,9 +5,9 @@ import { type ComponentProps, createContext, useContext } from "react";
5
5
  import { getUsage } from "tokenlens";
6
6
  import { Button } from "@/components/ui/button";
7
7
  import {
8
- HoverCard,
9
- HoverCardContent,
10
- HoverCardTrigger,
8
+ HoverCard,
9
+ HoverCardContent,
10
+ HoverCardTrigger,
11
11
  } from "@/components/ui/hover-card";
12
12
  import { Progress } from "@/components/ui/progress";
13
13
  import { cn } from "@/lib/utils";
@@ -21,388 +21,388 @@ const ICON_STROKE_WIDTH = 2;
21
21
  type ModelId = string;
22
22
 
23
23
  type ContextSchema = {
24
- usedTokens: number;
25
- maxTokens: number;
26
- usage?: LanguageModelUsage;
27
- modelId?: ModelId;
24
+ usedTokens: number;
25
+ maxTokens: number;
26
+ usage?: LanguageModelUsage;
27
+ modelId?: ModelId;
28
28
  };
29
29
 
30
30
  const ContextContext = createContext<ContextSchema | null>(null);
31
31
 
32
32
  const useContextValue = () => {
33
- const context = useContext(ContextContext);
33
+ const context = useContext(ContextContext);
34
34
 
35
- if (!context) {
36
- throw new Error("Context components must be used within Context");
37
- }
35
+ if (!context) {
36
+ throw new Error("Context components must be used within Context");
37
+ }
38
38
 
39
- return context;
39
+ return context;
40
40
  };
41
41
 
42
42
  export type ContextProps = ComponentProps<typeof HoverCard> & ContextSchema;
43
43
 
44
44
  export const Context = ({
45
- usedTokens,
46
- maxTokens,
47
- usage,
48
- modelId,
49
- ...props
45
+ usedTokens,
46
+ maxTokens,
47
+ usage,
48
+ modelId,
49
+ ...props
50
50
  }: ContextProps) => (
51
- <ContextContext.Provider
52
- value={{
53
- usedTokens,
54
- maxTokens,
55
- usage,
56
- modelId,
57
- }}
58
- >
59
- <HoverCard closeDelay={0} openDelay={0} {...props} />
60
- </ContextContext.Provider>
51
+ <ContextContext.Provider
52
+ value={{
53
+ usedTokens,
54
+ maxTokens,
55
+ usage,
56
+ modelId,
57
+ }}
58
+ >
59
+ <HoverCard closeDelay={0} openDelay={0} {...props} />
60
+ </ContextContext.Provider>
61
61
  );
62
62
 
63
63
  const ContextIcon = () => {
64
- const { usedTokens, maxTokens } = useContextValue();
65
- const circumference = 2 * Math.PI * ICON_RADIUS;
66
- const usedPercent = usedTokens / maxTokens;
67
- const dashOffset = circumference * (1 - usedPercent);
68
-
69
- return (
70
- <svg
71
- aria-label="Model context usage"
72
- height="20"
73
- role="img"
74
- style={{ color: "currentcolor" }}
75
- viewBox={`0 0 ${ICON_VIEWBOX} ${ICON_VIEWBOX}`}
76
- width="20"
77
- >
78
- <circle
79
- cx={ICON_CENTER}
80
- cy={ICON_CENTER}
81
- fill="none"
82
- opacity="0.25"
83
- r={ICON_RADIUS}
84
- stroke="currentColor"
85
- strokeWidth={ICON_STROKE_WIDTH}
86
- />
87
- <circle
88
- cx={ICON_CENTER}
89
- cy={ICON_CENTER}
90
- fill="none"
91
- opacity="0.7"
92
- r={ICON_RADIUS}
93
- stroke="currentColor"
94
- strokeDasharray={`${circumference} ${circumference}`}
95
- strokeDashoffset={dashOffset}
96
- strokeLinecap="round"
97
- strokeWidth={ICON_STROKE_WIDTH}
98
- style={{ transformOrigin: "center", transform: "rotate(-90deg)" }}
99
- />
100
- </svg>
101
- );
64
+ const { usedTokens, maxTokens } = useContextValue();
65
+ const circumference = 2 * Math.PI * ICON_RADIUS;
66
+ const usedPercent = usedTokens / maxTokens;
67
+ const dashOffset = circumference * (1 - usedPercent);
68
+
69
+ return (
70
+ <svg
71
+ aria-label="Model context usage"
72
+ height="20"
73
+ role="img"
74
+ style={{ color: "currentcolor" }}
75
+ viewBox={`0 0 ${ICON_VIEWBOX} ${ICON_VIEWBOX}`}
76
+ width="20"
77
+ >
78
+ <circle
79
+ cx={ICON_CENTER}
80
+ cy={ICON_CENTER}
81
+ fill="none"
82
+ opacity="0.25"
83
+ r={ICON_RADIUS}
84
+ stroke="currentColor"
85
+ strokeWidth={ICON_STROKE_WIDTH}
86
+ />
87
+ <circle
88
+ cx={ICON_CENTER}
89
+ cy={ICON_CENTER}
90
+ fill="none"
91
+ opacity="0.7"
92
+ r={ICON_RADIUS}
93
+ stroke="currentColor"
94
+ strokeDasharray={`${circumference} ${circumference}`}
95
+ strokeDashoffset={dashOffset}
96
+ strokeLinecap="round"
97
+ strokeWidth={ICON_STROKE_WIDTH}
98
+ style={{ transformOrigin: "center", transform: "rotate(-90deg)" }}
99
+ />
100
+ </svg>
101
+ );
102
102
  };
103
103
 
104
104
  export type ContextTriggerProps = ComponentProps<typeof Button>;
105
105
 
106
106
  export const ContextTrigger = ({ children, ...props }: ContextTriggerProps) => {
107
- const { usedTokens, maxTokens } = useContextValue();
108
- const usedPercent = usedTokens / maxTokens;
109
- const renderedPercent = new Intl.NumberFormat("en-US", {
110
- style: "percent",
111
- maximumFractionDigits: 1,
112
- }).format(usedPercent);
113
-
114
- return (
115
- <HoverCardTrigger asChild>
116
- {children ?? (
117
- <Button type="button" variant="ghost" {...props}>
118
- <span className="font-medium text-muted-foreground">
119
- {renderedPercent}
120
- </span>
121
- <ContextIcon />
122
- </Button>
123
- )}
124
- </HoverCardTrigger>
125
- );
107
+ const { usedTokens, maxTokens } = useContextValue();
108
+ const usedPercent = usedTokens / maxTokens;
109
+ const renderedPercent = new Intl.NumberFormat("en-US", {
110
+ style: "percent",
111
+ maximumFractionDigits: 1,
112
+ }).format(usedPercent);
113
+
114
+ return (
115
+ <HoverCardTrigger asChild>
116
+ {children ?? (
117
+ <Button type="button" variant="ghost" {...props}>
118
+ <span className="font-medium text-muted-foreground">
119
+ {renderedPercent}
120
+ </span>
121
+ <ContextIcon />
122
+ </Button>
123
+ )}
124
+ </HoverCardTrigger>
125
+ );
126
126
  };
127
127
 
128
128
  export type ContextContentProps = ComponentProps<typeof HoverCardContent>;
129
129
 
130
130
  export const ContextContent = ({
131
- className,
132
- ...props
131
+ className,
132
+ ...props
133
133
  }: ContextContentProps) => (
134
- <HoverCardContent
135
- className={cn("min-w-60 divide-y overflow-hidden p-0", className)}
136
- {...props}
137
- />
134
+ <HoverCardContent
135
+ className={cn("min-w-60 divide-y overflow-hidden p-0", className)}
136
+ {...props}
137
+ />
138
138
  );
139
139
 
140
140
  export type ContextContentHeaderProps = ComponentProps<"div">;
141
141
 
142
142
  export const ContextContentHeader = ({
143
- children,
144
- className,
145
- ...props
143
+ children,
144
+ className,
145
+ ...props
146
146
  }: ContextContentHeaderProps) => {
147
- const { usedTokens, maxTokens } = useContextValue();
148
- const usedPercent = usedTokens / maxTokens;
149
- const displayPct = new Intl.NumberFormat("en-US", {
150
- style: "percent",
151
- maximumFractionDigits: 1,
152
- }).format(usedPercent);
153
- const used = new Intl.NumberFormat("en-US", {
154
- notation: "compact",
155
- }).format(usedTokens);
156
- const total = new Intl.NumberFormat("en-US", {
157
- notation: "compact",
158
- }).format(maxTokens);
159
-
160
- return (
161
- <div className={cn("w-full space-y-2 p-3", className)} {...props}>
162
- {children ?? (
163
- <>
164
- <div className="flex items-center justify-between gap-3 text-xs">
165
- <p>{displayPct}</p>
166
- <p className="font-mono text-muted-foreground">
167
- {used} / {total}
168
- </p>
169
- </div>
170
- <div className="space-y-2">
171
- <Progress className="bg-muted" value={usedPercent * PERCENT_MAX} />
172
- </div>
173
- </>
174
- )}
175
- </div>
176
- );
147
+ const { usedTokens, maxTokens } = useContextValue();
148
+ const usedPercent = usedTokens / maxTokens;
149
+ const displayPct = new Intl.NumberFormat("en-US", {
150
+ style: "percent",
151
+ maximumFractionDigits: 1,
152
+ }).format(usedPercent);
153
+ const used = new Intl.NumberFormat("en-US", {
154
+ notation: "compact",
155
+ }).format(usedTokens);
156
+ const total = new Intl.NumberFormat("en-US", {
157
+ notation: "compact",
158
+ }).format(maxTokens);
159
+
160
+ return (
161
+ <div className={cn("w-full space-y-2 p-3", className)} {...props}>
162
+ {children ?? (
163
+ <>
164
+ <div className="flex items-center justify-between gap-3 text-xs">
165
+ <p>{displayPct}</p>
166
+ <p className="font-mono text-muted-foreground">
167
+ {used} / {total}
168
+ </p>
169
+ </div>
170
+ <div className="space-y-2">
171
+ <Progress className="bg-muted" value={usedPercent * PERCENT_MAX} />
172
+ </div>
173
+ </>
174
+ )}
175
+ </div>
176
+ );
177
177
  };
178
178
 
179
179
  export type ContextContentBodyProps = ComponentProps<"div">;
180
180
 
181
181
  export const ContextContentBody = ({
182
- children,
183
- className,
184
- ...props
182
+ children,
183
+ className,
184
+ ...props
185
185
  }: ContextContentBodyProps) => (
186
- <div className={cn("w-full p-3", className)} {...props}>
187
- {children}
188
- </div>
186
+ <div className={cn("w-full p-3", className)} {...props}>
187
+ {children}
188
+ </div>
189
189
  );
190
190
 
191
191
  export type ContextContentFooterProps = ComponentProps<"div">;
192
192
 
193
193
  export const ContextContentFooter = ({
194
- children,
195
- className,
196
- ...props
194
+ children,
195
+ className,
196
+ ...props
197
197
  }: ContextContentFooterProps) => {
198
- const { modelId, usage } = useContextValue();
199
- const costUSD = modelId
200
- ? getUsage({
201
- modelId,
202
- usage: {
203
- input: usage?.inputTokens ?? 0,
204
- output: usage?.outputTokens ?? 0,
205
- },
206
- }).costUSD?.totalUSD
207
- : undefined;
208
- const totalCost = new Intl.NumberFormat("en-US", {
209
- style: "currency",
210
- currency: "USD",
211
- }).format(costUSD ?? 0);
212
-
213
- return (
214
- <div
215
- className={cn(
216
- "flex w-full items-center justify-between gap-3 bg-secondary p-3 text-xs",
217
- className
218
- )}
219
- {...props}
220
- >
221
- {children ?? (
222
- <>
223
- <span className="text-muted-foreground">Total cost</span>
224
- <span>{totalCost}</span>
225
- </>
226
- )}
227
- </div>
228
- );
198
+ const { modelId, usage } = useContextValue();
199
+ const costUSD = modelId
200
+ ? getUsage({
201
+ modelId,
202
+ usage: {
203
+ input: usage?.inputTokens ?? 0,
204
+ output: usage?.outputTokens ?? 0,
205
+ },
206
+ }).costUSD?.totalUSD
207
+ : undefined;
208
+ const totalCost = new Intl.NumberFormat("en-US", {
209
+ style: "currency",
210
+ currency: "USD",
211
+ }).format(costUSD ?? 0);
212
+
213
+ return (
214
+ <div
215
+ className={cn(
216
+ "flex w-full items-center justify-between gap-3 bg-secondary p-3 text-xs",
217
+ className,
218
+ )}
219
+ {...props}
220
+ >
221
+ {children ?? (
222
+ <>
223
+ <span className="text-muted-foreground">Total cost</span>
224
+ <span>{totalCost}</span>
225
+ </>
226
+ )}
227
+ </div>
228
+ );
229
229
  };
230
230
 
231
231
  export type ContextInputUsageProps = ComponentProps<"div">;
232
232
 
233
233
  export const ContextInputUsage = ({
234
- className,
235
- children,
236
- ...props
234
+ className,
235
+ children,
236
+ ...props
237
237
  }: ContextInputUsageProps) => {
238
- const { usage, modelId } = useContextValue();
239
- const inputTokens = usage?.inputTokens ?? 0;
240
-
241
- if (children) {
242
- return children;
243
- }
244
-
245
- if (!inputTokens) {
246
- return null;
247
- }
248
-
249
- const inputCost = modelId
250
- ? getUsage({
251
- modelId,
252
- usage: { input: inputTokens, output: 0 },
253
- }).costUSD?.totalUSD
254
- : undefined;
255
- const inputCostText = new Intl.NumberFormat("en-US", {
256
- style: "currency",
257
- currency: "USD",
258
- }).format(inputCost ?? 0);
259
-
260
- return (
261
- <div
262
- className={cn("flex items-center justify-between text-xs", className)}
263
- {...props}
264
- >
265
- <span className="text-muted-foreground">Input</span>
266
- <TokensWithCost costText={inputCostText} tokens={inputTokens} />
267
- </div>
268
- );
238
+ const { usage, modelId } = useContextValue();
239
+ const inputTokens = usage?.inputTokens ?? 0;
240
+
241
+ if (children) {
242
+ return children;
243
+ }
244
+
245
+ if (!inputTokens) {
246
+ return null;
247
+ }
248
+
249
+ const inputCost = modelId
250
+ ? getUsage({
251
+ modelId,
252
+ usage: { input: inputTokens, output: 0 },
253
+ }).costUSD?.totalUSD
254
+ : undefined;
255
+ const inputCostText = new Intl.NumberFormat("en-US", {
256
+ style: "currency",
257
+ currency: "USD",
258
+ }).format(inputCost ?? 0);
259
+
260
+ return (
261
+ <div
262
+ className={cn("flex items-center justify-between text-xs", className)}
263
+ {...props}
264
+ >
265
+ <span className="text-muted-foreground">Input</span>
266
+ <TokensWithCost costText={inputCostText} tokens={inputTokens} />
267
+ </div>
268
+ );
269
269
  };
270
270
 
271
271
  export type ContextOutputUsageProps = ComponentProps<"div">;
272
272
 
273
273
  export const ContextOutputUsage = ({
274
- className,
275
- children,
276
- ...props
274
+ className,
275
+ children,
276
+ ...props
277
277
  }: ContextOutputUsageProps) => {
278
- const { usage, modelId } = useContextValue();
279
- const outputTokens = usage?.outputTokens ?? 0;
280
-
281
- if (children) {
282
- return children;
283
- }
284
-
285
- if (!outputTokens) {
286
- return null;
287
- }
288
-
289
- const outputCost = modelId
290
- ? getUsage({
291
- modelId,
292
- usage: { input: 0, output: outputTokens },
293
- }).costUSD?.totalUSD
294
- : undefined;
295
- const outputCostText = new Intl.NumberFormat("en-US", {
296
- style: "currency",
297
- currency: "USD",
298
- }).format(outputCost ?? 0);
299
-
300
- return (
301
- <div
302
- className={cn("flex items-center justify-between text-xs", className)}
303
- {...props}
304
- >
305
- <span className="text-muted-foreground">Output</span>
306
- <TokensWithCost costText={outputCostText} tokens={outputTokens} />
307
- </div>
308
- );
278
+ const { usage, modelId } = useContextValue();
279
+ const outputTokens = usage?.outputTokens ?? 0;
280
+
281
+ if (children) {
282
+ return children;
283
+ }
284
+
285
+ if (!outputTokens) {
286
+ return null;
287
+ }
288
+
289
+ const outputCost = modelId
290
+ ? getUsage({
291
+ modelId,
292
+ usage: { input: 0, output: outputTokens },
293
+ }).costUSD?.totalUSD
294
+ : undefined;
295
+ const outputCostText = new Intl.NumberFormat("en-US", {
296
+ style: "currency",
297
+ currency: "USD",
298
+ }).format(outputCost ?? 0);
299
+
300
+ return (
301
+ <div
302
+ className={cn("flex items-center justify-between text-xs", className)}
303
+ {...props}
304
+ >
305
+ <span className="text-muted-foreground">Output</span>
306
+ <TokensWithCost costText={outputCostText} tokens={outputTokens} />
307
+ </div>
308
+ );
309
309
  };
310
310
 
311
311
  export type ContextReasoningUsageProps = ComponentProps<"div">;
312
312
 
313
313
  export const ContextReasoningUsage = ({
314
- className,
315
- children,
316
- ...props
314
+ className,
315
+ children,
316
+ ...props
317
317
  }: ContextReasoningUsageProps) => {
318
- const { usage, modelId } = useContextValue();
319
- const reasoningTokens = usage?.reasoningTokens ?? 0;
320
-
321
- if (children) {
322
- return children;
323
- }
324
-
325
- if (!reasoningTokens) {
326
- return null;
327
- }
328
-
329
- const reasoningCost = modelId
330
- ? getUsage({
331
- modelId,
332
- usage: { reasoningTokens },
333
- }).costUSD?.totalUSD
334
- : undefined;
335
- const reasoningCostText = new Intl.NumberFormat("en-US", {
336
- style: "currency",
337
- currency: "USD",
338
- }).format(reasoningCost ?? 0);
339
-
340
- return (
341
- <div
342
- className={cn("flex items-center justify-between text-xs", className)}
343
- {...props}
344
- >
345
- <span className="text-muted-foreground">Reasoning</span>
346
- <TokensWithCost costText={reasoningCostText} tokens={reasoningTokens} />
347
- </div>
348
- );
318
+ const { usage, modelId } = useContextValue();
319
+ const reasoningTokens = usage?.reasoningTokens ?? 0;
320
+
321
+ if (children) {
322
+ return children;
323
+ }
324
+
325
+ if (!reasoningTokens) {
326
+ return null;
327
+ }
328
+
329
+ const reasoningCost = modelId
330
+ ? getUsage({
331
+ modelId,
332
+ usage: { reasoningTokens },
333
+ }).costUSD?.totalUSD
334
+ : undefined;
335
+ const reasoningCostText = new Intl.NumberFormat("en-US", {
336
+ style: "currency",
337
+ currency: "USD",
338
+ }).format(reasoningCost ?? 0);
339
+
340
+ return (
341
+ <div
342
+ className={cn("flex items-center justify-between text-xs", className)}
343
+ {...props}
344
+ >
345
+ <span className="text-muted-foreground">Reasoning</span>
346
+ <TokensWithCost costText={reasoningCostText} tokens={reasoningTokens} />
347
+ </div>
348
+ );
349
349
  };
350
350
 
351
351
  export type ContextCacheUsageProps = ComponentProps<"div">;
352
352
 
353
353
  export const ContextCacheUsage = ({
354
- className,
355
- children,
356
- ...props
354
+ className,
355
+ children,
356
+ ...props
357
357
  }: ContextCacheUsageProps) => {
358
- const { usage, modelId } = useContextValue();
359
- const cacheTokens = usage?.cachedInputTokens ?? 0;
360
-
361
- if (children) {
362
- return children;
363
- }
364
-
365
- if (!cacheTokens) {
366
- return null;
367
- }
368
-
369
- const cacheCost = modelId
370
- ? getUsage({
371
- modelId,
372
- usage: { cacheReads: cacheTokens, input: 0, output: 0 },
373
- }).costUSD?.totalUSD
374
- : undefined;
375
- const cacheCostText = new Intl.NumberFormat("en-US", {
376
- style: "currency",
377
- currency: "USD",
378
- }).format(cacheCost ?? 0);
379
-
380
- return (
381
- <div
382
- className={cn("flex items-center justify-between text-xs", className)}
383
- {...props}
384
- >
385
- <span className="text-muted-foreground">Cache</span>
386
- <TokensWithCost costText={cacheCostText} tokens={cacheTokens} />
387
- </div>
388
- );
358
+ const { usage, modelId } = useContextValue();
359
+ const cacheTokens = usage?.cachedInputTokens ?? 0;
360
+
361
+ if (children) {
362
+ return children;
363
+ }
364
+
365
+ if (!cacheTokens) {
366
+ return null;
367
+ }
368
+
369
+ const cacheCost = modelId
370
+ ? getUsage({
371
+ modelId,
372
+ usage: { cacheReads: cacheTokens, input: 0, output: 0 },
373
+ }).costUSD?.totalUSD
374
+ : undefined;
375
+ const cacheCostText = new Intl.NumberFormat("en-US", {
376
+ style: "currency",
377
+ currency: "USD",
378
+ }).format(cacheCost ?? 0);
379
+
380
+ return (
381
+ <div
382
+ className={cn("flex items-center justify-between text-xs", className)}
383
+ {...props}
384
+ >
385
+ <span className="text-muted-foreground">Cache</span>
386
+ <TokensWithCost costText={cacheCostText} tokens={cacheTokens} />
387
+ </div>
388
+ );
389
389
  };
390
390
 
391
391
  const TokensWithCost = ({
392
- tokens,
393
- costText,
392
+ tokens,
393
+ costText,
394
394
  }: {
395
- tokens?: number;
396
- costText?: string;
395
+ tokens?: number;
396
+ costText?: string;
397
397
  }) => (
398
- <span>
399
- {tokens === undefined
400
- ? "—"
401
- : new Intl.NumberFormat("en-US", {
402
- notation: "compact",
403
- }).format(tokens)}
404
- {costText ? (
405
- <span className="ml-2 text-muted-foreground">• {costText}</span>
406
- ) : null}
407
- </span>
398
+ <span>
399
+ {tokens === undefined
400
+ ? "—"
401
+ : new Intl.NumberFormat("en-US", {
402
+ notation: "compact",
403
+ }).format(tokens)}
404
+ {costText ? (
405
+ <span className="ml-2 text-muted-foreground">• {costText}</span>
406
+ ) : null}
407
+ </span>
408
408
  );