(port = 5000, localhostOnly = false)
| 547 | } |
| 548 | |
| 549 | let args; |
| 550 | if (imageUrl && typeof imageUrl === 'string') { |
| 551 | const isVideo = /\.(mp4|webm|mov|avi|mkv)(\?|$)/i.test(imageUrl) || imageUrl.startsWith('data:video/'); |
| 552 | const mediaBlock = isVideo ? { video_url: { url: imageUrl } } : { image_url: { url: imageUrl } }; |
| 553 | args = { |
| 554 | vision: true, |
| 555 | messages: [{ content: [prompt, mediaBlock] }], |
| 556 | model: model || 'gpt-5-nano' |
| 557 | }; |
| 558 | } else { |
| 559 | args = { |
| 560 | messages: [{ content: prompt }], |
| 561 | model: model || 'gpt-5-nano' |
| 562 | }; |
| 563 | } |
| 564 | |
| 565 | const puterBody = JSON.stringify({ |
| 566 | interface: 'puter-chat-completion', |
| 567 | driver: 'ai-chat', |
| 568 | test_mode: false, |
| 569 | method: 'complete', |
| 570 | args, |
| 571 | auth_token: authToken || undefined |
| 572 | }); |
| 573 | |
| 574 | const puterResponse = await fetch('https://api.puter.com/drivers/call', { |
| 575 | method: 'POST', |
| 576 | headers: { |
| 577 | 'Content-Type': 'text/plain;actually=json', |
| 578 | 'Origin': 'https://puter.com', |
| 579 | 'Referer': 'https://puter.com/' |
| 580 | }, |
| 581 | body: puterBody |
| 582 | }); |
| 583 | |
| 584 | let data; |
| 585 | const puterRawBody = await puterResponse.text(); |
| 586 | try { |
| 587 | data = puterRawBody ? JSON.parse(puterRawBody) : {}; |
| 588 | } catch (parseErr) { |
| 589 | res.status(502).json({ error: `Invalid response from Puter API (${puterResponse.status})`, details: puterRawBody.slice(0, 500) }); |
| 590 | return; |
| 591 | } |
| 592 | |
| 593 | if (!puterResponse.ok || data.success === false) { |
| 594 | const errMsg = data?.error?.message || data?.message || `Puter API error (${puterResponse.status})`; |
| 595 | const code = data?.error?.code || data?.code; |
| 596 | res.status(puterResponse.status >= 400 ? puterResponse.status : 500).json({ error: errMsg, code, details: data }); |
| 597 | return; |
| 598 | } |
| 599 | |
| 600 | const result = data.result; |
| 601 | let chatText; |
| 602 | if (typeof result === 'string') { |
| 603 | chatText = result; |
| 604 | } else if (result?.message?.content) { |
| 605 | chatText = result.message.content; |
| 606 | } else if (typeof result?.text === 'string') { |
no test coverage detected