Pepguy commited on
Commit
f02017a
·
verified ·
1 Parent(s): 8d23bfe

Update app.js

Browse files
Files changed (1) hide show
  1. app.js +108 -65
app.js CHANGED
@@ -10,24 +10,34 @@ const PORT = 7860;
10
 
11
  app.use(express.json());
12
 
 
 
 
 
 
 
 
 
 
 
 
13
  // --- 1. SYSTEM PROMPTS ---
14
  const SYSTEM_PROMPT_PRO = "You are a pro";
15
  const SYSTEM_PROMPT_WORKER = "You are a worker";
16
 
17
  // --- 2. CLIENT INITIALIZATION ---
18
 
19
- // Bedrock Client (Uses SDK credential chain)
 
20
  const bedrockClient = new BedrockRuntimeClient({
21
  region: process.env.AWS_REGION || "us-east-1",
22
  maxAttempts: 1,
23
- credentials: {
24
- accessKeyId: "AKIARRXB77NRTRLNWEBT",
25
- secretAccessKey: "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",
26
- // sessionToken: "..." // Only if using temporary credentials
27
- }
28
  });
29
 
30
- // Azure OpenAI Client
31
  const AZURE_API_KEY = "7U3m9NRkE38ThSWTr92hMgQ4hDCUFI9MAnFNrCgRL7MhdvckfTXwJQQJ99CBACHYHv6XJ3w3AAAAACOGV22P";
32
  const AZURE_DEPLOY = process.env.AZURE_OPENAI_DEPLOYMENT || "gpt-5-mini";
33
  const AZURE_BASE_URL = `https://hollowpad-resource.cognitiveservices.azure.com/openai/deployments/${AZURE_DEPLOY}`;
@@ -42,67 +52,85 @@ const azureOpenAI = new OpenAI({
42
  // --- 3. EXECUTION LOGIC ---
43
 
44
  async function callClaude(userPrompt) {
45
- const command = new ConverseCommand({
46
- // Full ARN required for global inference profiles
47
- modelId: "arn:aws:bedrock:us-east-1:106774395747:inference-profile/global.anthropic.claude-sonnet-4-6",
48
- system: [{ text: SYSTEM_PROMPT_PRO }],
49
- messages: [{ role: "user", content: [{ text: userPrompt }] }],
50
- inferenceConfig: {
51
- maxTokens: 49752,
52
- stopSequences: [],
53
- temperature: 1
54
- },
55
- additionalModelRequestFields: {
56
- thinking: { type: "adaptive" },
57
- output_config: { effort: "high" }
58
- },
59
- performanceConfig: { latency: "standard" }
60
- });
61
-
62
- const response = await bedrockClient.send(command);
63
-
64
- console.log(response);
65
-
66
- // Find text block in response (skips reasoning blocks)
67
- const textBlock = response.output.message.content.find(
68
- block => typeof block.text === 'string'
69
- );
70
-
71
- console.log(response);
72
- console.log(textBlock);
73
-
74
- return textBlock?.text ?? "No text response was generated.";
 
 
 
 
 
75
  }
76
 
77
  async function callGptMini(userPrompt) {
78
- const response = await azureOpenAI.chat.completions.create({
79
- model: AZURE_DEPLOY,
80
- messages: [
81
- { role: "system", content: SYSTEM_PROMPT_WORKER },
82
- { role: "user", content: userPrompt }
83
- ],
84
- reasoning_effort: "high",
85
- max_completion_tokens: 56069,
86
- store: true
87
- });
88
- return response.choices[0].message.content;
 
 
 
 
 
 
 
 
 
89
  }
90
 
91
  // --- 4. API ENDPOINT ---
92
 
93
  app.post('/api/generate', async (req, res) => {
94
  const { model, prompt } = req.body;
 
95
 
96
  if (!prompt || typeof prompt !== 'string') {
 
97
  return res.status(400).json({ success: false, error: "Missing or invalid 'prompt' field." });
98
  }
99
 
100
  try {
101
  const result = (model === "claude") ? await callClaude(prompt) : await callGptMini(prompt);
 
102
  res.json({ success: true, data: result });
103
  } catch (err) {
104
  const errorMsg = (err instanceof Error) ? err.message : String(err);
105
- console.error(`[${model ?? 'unknown'}] Error:`, errorMsg);
 
106
  if (!res.headersSent) {
107
  res.status(500).json({ success: false, error: errorMsg });
108
  }
@@ -112,6 +140,7 @@ app.post('/api/generate', async (req, res) => {
112
  // --- 5. HTML DEMO PAGE ---
113
 
114
  app.get('/', (req, res) => {
 
115
  res.send(`
116
  <!DOCTYPE html>
117
  <html>
@@ -122,31 +151,23 @@ app.get('/', (req, res) => {
122
  .box { max-width: 900px; margin: auto; background: #1a1a1a; padding: 30px; border-radius: 10px; border: 1px solid #333; }
123
  textarea { width: 100%; height: 180px; background: #222; color: #00ff00; border: 1px solid #333; padding: 15px; box-sizing: border-box; font-family: monospace; font-size: 14px; }
124
  select, button { background: #333; color: white; padding: 12px; border: 1px solid #444; border-radius: 5px; margin-top: 10px; width: 100%; cursor: pointer; }
125
- button { background: #0078d4; font-weight: bold; transition: background 0.2s; }
126
- button:hover { background: #0086f0; }
127
  button:disabled { background: #444; cursor: not-allowed; }
128
  #output { margin-top: 25px; white-space: pre-wrap; background: #000; padding: 20px; border-radius: 5px; border: 1px solid #222; color: #adadad; min-height: 50px; }
129
- .header { margin-bottom: 20px; }
130
  .badge { font-size: 11px; background: #444; padding: 2px 6px; border-radius: 3px; color: #ccc; }
131
  </style>
132
  </head>
133
  <body>
134
  <div class="box">
135
- <div class="header">
136
- <h1>Hollowpad Battle Arena</h1>
137
- <p><span class="badge">Thinking: Adaptive</span> <span class="badge">Effort: High</span></p>
138
- </div>
139
-
140
- <textarea id="prompt" placeholder="Enter your prompt here..."></textarea>
141
-
142
  <select id="model">
143
  <option value="gpt">GPT-5 Mini (Worker Prompt)</option>
144
  <option value="claude">Claude Sonnet 4.6 (Pro Prompt)</option>
145
  </select>
146
-
147
- <button id="runBtn" onclick="execute()">Run High Reasoning Test</button>
148
-
149
- <div id="output">Output will appear here...</div>
150
  </div>
151
 
152
  <script>
@@ -157,7 +178,7 @@ app.get('/', (req, res) => {
157
  const prompt = document.getElementById('prompt').value;
158
 
159
  btn.disabled = true;
160
- out.innerText = "Thinking (Adaptive Reasoning)...";
161
 
162
  try {
163
  const res = await fetch('/api/generate', {
@@ -165,6 +186,15 @@ app.get('/', (req, res) => {
165
  headers: { 'Content-Type': 'application/json' },
166
  body: JSON.stringify({ model, prompt })
167
  });
 
 
 
 
 
 
 
 
 
168
  const result = await res.json();
169
  out.innerText = result.success ? result.data : "Error: " + result.error;
170
  } catch (e) {
@@ -179,4 +209,17 @@ app.get('/', (req, res) => {
179
  `);
180
  });
181
 
182
- app.listen(PORT, () => console.log(`Server started: http://localhost:${PORT}`));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  app.use(express.json());
12
 
13
+ // --- 0. ROBUST LOGGER HELPER ---
14
+ const log = (level, context, message, data = null) => {
15
+ const timestamp = new Date().toISOString();
16
+ const color = level === 'ERROR' ? '\x1b[31m' : level === 'WARN' ? '\x1b[33m' : '\x1b[32m';
17
+ const reset = '\x1b[0m';
18
+ console.log(`${color}[${timestamp}] [${level}] [${context}] ${message}${reset}`);
19
+ if (data) {
20
+ console.dir(data, { depth: null, colors: true });
21
+ }
22
+ };
23
+
24
  // --- 1. SYSTEM PROMPTS ---
25
  const SYSTEM_PROMPT_PRO = "You are a pro";
26
  const SYSTEM_PROMPT_WORKER = "You are a worker";
27
 
28
  // --- 2. CLIENT INITIALIZATION ---
29
 
30
+ log('INFO', 'INIT', 'Initializing clients...');
31
+
32
  const bedrockClient = new BedrockRuntimeClient({
33
  region: process.env.AWS_REGION || "us-east-1",
34
  maxAttempts: 1,
35
+ credentials: {
36
+ accessKeyId: "AKIARRXB77NRTRLNWEBT",
37
+ secretAccessKey: "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",
38
+ }
 
39
  });
40
 
 
41
  const AZURE_API_KEY = "7U3m9NRkE38ThSWTr92hMgQ4hDCUFI9MAnFNrCgRL7MhdvckfTXwJQQJ99CBACHYHv6XJ3w3AAAAACOGV22P";
42
  const AZURE_DEPLOY = process.env.AZURE_OPENAI_DEPLOYMENT || "gpt-5-mini";
43
  const AZURE_BASE_URL = `https://hollowpad-resource.cognitiveservices.azure.com/openai/deployments/${AZURE_DEPLOY}`;
 
52
  // --- 3. EXECUTION LOGIC ---
53
 
54
  async function callClaude(userPrompt) {
55
+ log('INFO', 'CLAUDE', 'Starting Bedrock ConverseCommand...', { prompt: userPrompt.substring(0, 50) + "..." });
56
+
57
+ try {
58
+ const command = new ConverseCommand({
59
+ modelId: "arn:aws:bedrock:us-east-1:106774395747:inference-profile/global.anthropic.claude-sonnet-4-6",
60
+ system: [{ text: SYSTEM_PROMPT_PRO }],
61
+ messages: [{ role: "user", content: [{ text: userPrompt }] }],
62
+ inferenceConfig: {
63
+ maxTokens: 49752,
64
+ stopSequences: [],
65
+ temperature: 1
66
+ },
67
+ additionalModelRequestFields: {
68
+ thinking: { type: "adaptive" },
69
+ output_config: { effort: "high" }
70
+ },
71
+ performanceConfig: { latency: "standard" }
72
+ });
73
+
74
+ const response = await bedrockClient.send(command);
75
+ log('DEBUG', 'CLAUDE-RAW', 'Full Response from AWS:', response);
76
+
77
+ const textBlock = response.output.message.content.find(block => typeof block.text === 'string');
78
+
79
+ if (!textBlock) {
80
+ log('WARN', 'CLAUDE', 'No text block found in content array.');
81
+ } else {
82
+ log('INFO', 'CLAUDE', 'Successfully retrieved response.');
83
+ }
84
+
85
+ return textBlock?.text ?? "No text response was generated.";
86
+ } catch (err) {
87
+ log('ERROR', 'CLAUDE-SDK', 'AWS Bedrock call failed.', err);
88
+ throw err;
89
+ }
90
  }
91
 
92
  async function callGptMini(userPrompt) {
93
+ log('INFO', 'AZURE', 'Starting Azure OpenAI Request...', { deploy: AZURE_DEPLOY });
94
+
95
+ try {
96
+ const response = await azureOpenAI.chat.completions.create({
97
+ model: AZURE_DEPLOY,
98
+ messages: [
99
+ { role: "system", content: SYSTEM_PROMPT_WORKER },
100
+ { role: "user", content: userPrompt }
101
+ ],
102
+ reasoning_effort: "high",
103
+ max_completion_tokens: 56069,
104
+ store: true
105
+ });
106
+
107
+ log('INFO', 'AZURE', 'Successfully retrieved Azure response.');
108
+ return response.choices[0].message.content;
109
+ } catch (err) {
110
+ log('ERROR', 'AZURE-SDK', 'Azure call failed.', err);
111
+ throw err;
112
+ }
113
  }
114
 
115
  // --- 4. API ENDPOINT ---
116
 
117
  app.post('/api/generate', async (req, res) => {
118
  const { model, prompt } = req.body;
119
+ log('INFO', 'ENDPOINT', `Request received for model: ${model}`);
120
 
121
  if (!prompt || typeof prompt !== 'string') {
122
+ log('WARN', 'ENDPOINT', 'Invalid or missing prompt.');
123
  return res.status(400).json({ success: false, error: "Missing or invalid 'prompt' field." });
124
  }
125
 
126
  try {
127
  const result = (model === "claude") ? await callClaude(prompt) : await callGptMini(prompt);
128
+ log('INFO', 'ENDPOINT', 'Sending success response to client.');
129
  res.json({ success: true, data: result });
130
  } catch (err) {
131
  const errorMsg = (err instanceof Error) ? err.message : String(err);
132
+ log('ERROR', 'ENDPOINT-CATCH', `Failure in /api/generate`, { error: errorMsg });
133
+
134
  if (!res.headersSent) {
135
  res.status(500).json({ success: false, error: errorMsg });
136
  }
 
140
  // --- 5. HTML DEMO PAGE ---
141
 
142
  app.get('/', (req, res) => {
143
+ log('INFO', 'SERVER', 'Serving homepage...');
144
  res.send(`
145
  <!DOCTYPE html>
146
  <html>
 
151
  .box { max-width: 900px; margin: auto; background: #1a1a1a; padding: 30px; border-radius: 10px; border: 1px solid #333; }
152
  textarea { width: 100%; height: 180px; background: #222; color: #00ff00; border: 1px solid #333; padding: 15px; box-sizing: border-box; font-family: monospace; font-size: 14px; }
153
  select, button { background: #333; color: white; padding: 12px; border: 1px solid #444; border-radius: 5px; margin-top: 10px; width: 100%; cursor: pointer; }
154
+ button { background: #0078d4; font-weight: bold; }
 
155
  button:disabled { background: #444; cursor: not-allowed; }
156
  #output { margin-top: 25px; white-space: pre-wrap; background: #000; padding: 20px; border-radius: 5px; border: 1px solid #222; color: #adadad; min-height: 50px; }
 
157
  .badge { font-size: 11px; background: #444; padding: 2px 6px; border-radius: 3px; color: #ccc; }
158
  </style>
159
  </head>
160
  <body>
161
  <div class="box">
162
+ <h1>Hollowpad Battle Arena</h1>
163
+ <p><span class="badge">Robust Logging Enabled</span></p>
164
+ <textarea id="prompt" placeholder="Enter prompt..."></textarea>
 
 
 
 
165
  <select id="model">
166
  <option value="gpt">GPT-5 Mini (Worker Prompt)</option>
167
  <option value="claude">Claude Sonnet 4.6 (Pro Prompt)</option>
168
  </select>
169
+ <button id="runBtn" onclick="execute()">Run Test</button>
170
+ <div id="output">Ready. Check server console for logs.</div>
 
 
171
  </div>
172
 
173
  <script>
 
178
  const prompt = document.getElementById('prompt').value;
179
 
180
  btn.disabled = true;
181
+ out.innerText = "Processing request... check terminal.";
182
 
183
  try {
184
  const res = await fetch('/api/generate', {
 
186
  headers: { 'Content-Type': 'application/json' },
187
  body: JSON.stringify({ model, prompt })
188
  });
189
+
190
+ // If the response is not JSON (e.g., 404 HTML), this will catch it
191
+ const contentType = res.headers.get("content-type");
192
+ if (!contentType || !contentType.includes("application/json")) {
193
+ const text = await res.text();
194
+ out.innerHTML = "<b style='color:red'>SERVER RETURNED NON-JSON (HTML):</b><br>" + text.substring(0, 500);
195
+ return;
196
+ }
197
+
198
  const result = await res.json();
199
  out.innerText = result.success ? result.data : "Error: " + result.error;
200
  } catch (e) {
 
209
  `);
210
  });
211
 
212
+ // --- 6. EMERGENCY CATCH-ALLS ---
213
+ // This prevents the "Unexpected token <" error by ensuring 404s and errors are JSON
214
+
215
+ app.use((req, res) => {
216
+ log('WARN', 'SERVER', `404 Not Found: ${req.url}`);
217
+ res.status(404).json({ success: false, error: `Route ${req.url} not found on this server.` });
218
+ });
219
+
220
+ app.use((err, req, res, next) => {
221
+ log('ERROR', 'SERVER-CRASH', 'Uncaught middleware error!', err);
222
+ res.status(500).json({ success: false, error: "Internal Server Error", details: err.message });
223
+ });
224
+
225
+ app.listen(PORT, () => log('INFO', 'SERVER', `Server started: http://localhost:${PORT}`));