1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { generateMerchantTransactionData } from "https://esm.town/v/mjweaver01/generateMerchantTransactionData";
import { prompt } from "https://esm.town/v/mjweaver01/merchantAnalysisPrompt";
import { Hono } from "npm:hono";
import { OpenAI } from "npm:openai";
const trendGPT = async (data, onData) => {
const openai = new OpenAI();
const chatStream = await openai.chat.completions.create({
messages: [
{ role: "system", content: prompt.replaceAll("\n", "") },
{ role: "user", content: JSON.stringify(data) },
],
model: "chatgpt-4o-latest",
max_tokens: 4000,
temperature: 0,
stream: true,
});
let result = "";
try {
for await (const chunk of chatStream) {
const content = chunk.choices?.[0]?.delta?.content || "";
result += content;
if (onData) onData(result);
}
} catch (err) {
console.error("Error during stream processing:", err);
throw new Error("An error occurred while streaming the response.");
}
return result;
};
const trendsData = generateMerchantTransactionData();
const app = new Hono();
app.get("/", async (c) => {
const { readable, writable } = new TransformStream();
const writer = writable.getWriter();
const encoder = new TextEncoder();
writer.write(encoder.encode(`
<!DOCTYPE html>
<html>
<head>
<style>
* { font-family: sans-serif; }
.mermaid { background-color: #f0f0f0; padding: 10px; margin: 10px 0; }
pre { white-space: pre-wrap; word-wrap: break-word; }
</style>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
</head>
<body>
<div id="content"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/14.1.0/marked.min.js"></script>
<script>
let fullContent = "";
const contentElement = document.getElementById('content');
let autoScroll = true;
window.addEventListener('scroll', () => {
const scrolledToBottom = (window.innerHeight + window.scrollY) >= document.documentElement.scrollHeight - 10;
autoScroll = scrolledToBottom;
});
function updateContent(newContent) {
fullContent += newContent;
const parsedContent = marked.parse(fullContent, {
mangle: false,
headerIds: false,
breaks: true
});
contentElement.innerHTML = parsedContent;
processMermaidCharts();
if (autoScroll) {
requestAnimationFrame(() => {
window.scrollTo(0, document.body.scrollHeight);
});
}
}
function processMermaidCharts(newContent) {
if (typeof mermaid === 'undefined') {
setTimeout(processMermaidCharts, 100);
return;
}
const codeBlocks = document.querySelectorAll('pre');
codeBlocks.forEach((block, index) => {
const code = block.textContent.trim();
if (code.startsWith('pie') || code.startsWith('xychart-beta')) {
const id = 'mermaid-diagram-' + index;
const mermaidDiv = document.createElement('div');
mermaidDiv.className = 'mermaid';
mermaidDiv.id = id;
mermaidDiv.textContent = code;
block.parentNode.replaceChild(mermaidDiv, block);
}