diff --git a/app/commit.json b/app/commit.json
index 46c97342..018af740 100644
--- a/app/commit.json
+++ b/app/commit.json
@@ -1 +1 @@
-{ "commit": "fcb61ba49990d1d0cc13d05a0958007b6e9c1c38" }
+{ "commit": "2e05270bab264d7ee83d7a1dd5408c969f648a68" }
diff --git a/app/components/chat/AssistantMessage.tsx b/app/components/chat/AssistantMessage.tsx
index a5698e97..7cdddda3 100644
--- a/app/components/chat/AssistantMessage.tsx
+++ b/app/components/chat/AssistantMessage.tsx
@@ -1,14 +1,24 @@
import { memo } from 'react';
import { Markdown } from './Markdown';
+import { USAGE_REGEX } from '~/utils/constants';
interface AssistantMessageProps {
content: string;
}
export const AssistantMessage = memo(({ content }: AssistantMessageProps) => {
+ const match = content.match(USAGE_REGEX);
+ const usage = match ? JSON.parse(match[1]) : null;
+ const cleanContent = content.replace(USAGE_REGEX, '').trim();
+
return (
-
-
- {textContent}
-
- {images.length > 0 && (
-
- {images.map((item, index) => (
-
-

-
- ))}
-
- )}
+
+ {textContent &&
{textContent}}
+ {images.map((item, index) => (
+

+ ))}
);
}
- const textContent = sanitizeUserMessage(content);
+ const textContent = stripMetadata(content);
return (
- {textContent}
+ {textContent}
);
}
-function sanitizeUserMessage(content: string) {
+function stripMetadata(content: string) {
return content.replace(MODEL_REGEX, '').replace(PROVIDER_REGEX, '');
}
diff --git a/app/lib/.server/llm/switchable-stream.ts b/app/lib/.server/llm/switchable-stream.ts
index 638db7a4..51f46ff2 100644
--- a/app/lib/.server/llm/switchable-stream.ts
+++ b/app/lib/.server/llm/switchable-stream.ts
@@ -1,5 +1,5 @@
export default class SwitchableStream extends TransformStream {
- private _controller: TransformStreamDefaultController | null = null;
+ _controller: TransformStreamDefaultController | null = null;
private _currentReader: ReadableStreamDefaultReader | null = null;
private _switches = 0;
diff --git a/app/routes/api.chat.ts b/app/routes/api.chat.ts
index 34dea349..c7d63839 100644
--- a/app/routes/api.chat.ts
+++ b/app/routes/api.chat.ts
@@ -41,12 +41,36 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
const stream = new SwitchableStream();
+ const cumulativeUsage = {
+ completionTokens: 0,
+ promptTokens: 0,
+ totalTokens: 0,
+ };
+
try {
const options: StreamingOptions = {
toolChoice: 'none',
onFinish: async ({ text: content, finishReason, usage }) => {
console.log('usage', usage);
+ if (usage && stream._controller) {
+ cumulativeUsage.completionTokens += usage.completionTokens || 0;
+ cumulativeUsage.promptTokens += usage.promptTokens || 0;
+ cumulativeUsage.totalTokens += usage.totalTokens || 0;
+
+ // Send usage info in message metadata for assistant messages
+ const usageMetadata = `0:"[Usage: ${JSON.stringify({
+ completionTokens: cumulativeUsage.completionTokens,
+ promptTokens: cumulativeUsage.promptTokens,
+ totalTokens: cumulativeUsage.totalTokens,
+ })}\n]"`;
+
+ console.log(usageMetadata);
+
+ const encodedData = new TextEncoder().encode(usageMetadata);
+ stream._controller.enqueue(encodedData);
+ }
+
if (finishReason !== 'length') {
return stream.close();
}
@@ -83,6 +107,7 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
files,
providerSettings,
});
+
stream.switchSource(result.toDataStream());
return new Response(stream.readable, {
diff --git a/app/utils/constants.ts b/app/utils/constants.ts
index cc2aafc9..2ab6cfbf 100644
--- a/app/utils/constants.ts
+++ b/app/utils/constants.ts
@@ -9,6 +9,7 @@ export const WORK_DIR = `/home/${WORK_DIR_NAME}`;
export const MODIFICATIONS_TAG_NAME = 'bolt_file_modifications';
export const MODEL_REGEX = /^\[Model: (.*?)\]\n\n/;
export const PROVIDER_REGEX = /\[Provider: (.*?)\]\n\n/;
+export const USAGE_REGEX = /\[Usage: ({.*?})\]/; // Keep this regex for assistant messages
export const DEFAULT_MODEL = 'claude-3-5-sonnet-latest';
export const PROMPT_COOKIE_KEY = 'cachedPrompt';