bedrock-wrapper 2.5.0 → 2.6.0

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.
@@ -7973,5 +7973,1111 @@
7973
7973
  }
7974
7974
  ]
7975
7975
  }
7976
+ },
7977
+ {
7978
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
7979
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
7980
+ "cwd": "C:\\git\\bedrock-wrapper",
7981
+ "hook_event_name": "PostToolUse",
7982
+ "tool_name": "LS",
7983
+ "tool_input": {
7984
+ "path": "C:\\git\\bedrock-proxy-endpoint"
7985
+ },
7986
+ "tool_response": "- C:\\git\\bedrock-wrapper\\\n - ..\\\n - bedrock-proxy-endpoint\\\n - CHANGELOG.md\n - CLAUDE.md\n - LICENSE\n - README.md\n - coverage\\\n - base.css\n - block-navigation.js\n - coverage-final.json\n - favicon.png\n - index.html\n - prettify.css\n - prettify.js\n - server.js.html\n - sort-arrow-sprite.png\n - sorter.js\n - utils.js.html\n - docs\\\n - bedrock-proxy-endpoint.png\n - console.png\n - example\\\n - example-stop-sequences.js\n - example-vision.js\n - example.js\n - lizard.jpg\n - node_modules\\\n - package-lock.json\n - package.json\n - test-stop-simple.js\n - icon.ico\n - logs\\\n - 21ede7f7-3f9b-4427-aa58-20468c546615\\\n - notification.json\n - post_tool_use.json\n - pre_tool_use.json\n - stop.json\n - user_prompt_submit.json\n - node_modules\\\n - package-lock.json\n - package.json\n - public\\\n - favicon.png\n - index.html\n - server.js\n - tests\\\n - fixtures\\\n - test-data.js\n - server.test.js\n - setup.js\n - utils.test.js\n - utils.js\n - vitest.config.js\n"
7987
+ },
7988
+ {
7989
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
7990
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
7991
+ "cwd": "C:\\git\\bedrock-wrapper",
7992
+ "hook_event_name": "PostToolUse",
7993
+ "tool_name": "Read",
7994
+ "tool_input": {
7995
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\server.js"
7996
+ },
7997
+ "tool_response": {
7998
+ "type": "text",
7999
+ "file": {
8000
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\server.js",
8001
+ "content": "// -------------------------------------------------\n// -- import environment variables from .env file --\n// -------------------------------------------------\nimport dotenv from 'dotenv';\ndotenv.config();\n\n// ------------------------------\n// -- import utility functions --\n// ------------------------------\nimport { toBoolean, extractAWSCreds } from \"./utils.js\";\n\nconst CONSOLE_LOGGING = toBoolean(process.env.CONSOLE_LOGGING);\nconst HTTP_ENABLED = toBoolean(process.env.HTTP_ENABLED);\nconst HTTP_PORT = process.env.HTTP_PORT;\nconst HTTPS_ENABLED = toBoolean(process.env.HTTPS_ENABLED);\nconst HTTPS_PORT = process.env.HTTPS_PORT;\nconst HTTPS_KEY_PATH = process.env.HTTPS_KEY_PATH;\nconst HTTPS_CERT_PATH = process.env.HTTPS_CERT_PATH;\nconst IP_RATE_LIMIT_ENABLED = toBoolean(process.env.IP_RATE_LIMIT_ENABLED);\nconst IP_RATE_LIMIT_WINDOW_MS = parseInt(process.env.IP_RATE_LIMIT_WINDOW_MS);\nconst IP_RATE_LIMIT_MAX_REQUESTS = parseInt(process.env.IP_RATE_LIMIT_MAX_REQUESTS);\nconst MAX_REQUEST_BODY_SIZE = process.env.MAX_REQUEST_BODY_SIZE || '1mb';\n\n// --------------------------------------------\n// -- import functions from bedrock-wrapper --\n// -- - bedrockWrapper --\n// -- - listBedrockWrapperSupportedModels --\n// --------------------------------------------\nimport { \n bedrockWrapper,\n listBedrockWrapperSupportedModels\n} from \"bedrock-wrapper\";\n\nconsole.log(\" ============================ PROXY ENDPOINT =============================\");\nconsole.log(\"\");\n\n// -----------------------------------\n// -- import server and its modules --\n// -----------------------------------\nimport express from 'express';\nimport bodyParser from 'body-parser';\nimport rateLimit from 'express-rate-limit';\nimport { fileURLToPath } from 'url';\nimport https from 'https';\nimport http from 'http';\nimport path from 'path';\nimport fs from 'fs';\nimport { stdout } from 'process';\n\nconst app = express();\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\napp.use(bodyParser.json({ limit: MAX_REQUEST_BODY_SIZE }));\n\n// ------------------------------------\n// -- setup rate limiting middleware --\n// ------------------------------------\nif (IP_RATE_LIMIT_ENABLED) {\n const limiter = rateLimit({\n windowMs: IP_RATE_LIMIT_WINDOW_MS,\n max: IP_RATE_LIMIT_MAX_REQUESTS\n });\n app.use(limiter);\n}\n\n// -------------------------------\n// -- error handling middleware --\n// -------------------------------\napp.use((err, req, res, next) => {\n if (err.code === 'ECONNRESET') {\n console.warn('Connection reset by peer');\n res.status(500).send('Connection reset by peer');\n } else if (err.headersSent) {\n return next(err);\n } else {\n console.error(err.stack);\n res.status(500).send('Something broke!');\n }\n});\n\n\n// -------------------\n// -- Info endpoint --\n// -------------------\napp.get('/', (req, res) => {\n res.sendFile(path.join(__dirname, 'public', 'index.html'));\n});\n\n// -------------------------------------\n// -- Endpoint: list supported models --\n// -------------------------------------\napp.get('/models', (req, res) => {\n listBedrockWrapperSupportedModels().then(supportedModels => {\n res.json(supportedModels);\n }).catch(err => {\n res.status(500).send('Failed to fetch models');\n });\n});\n\napp.post('/test/chat/completions', async (req, res) => {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n const data = {choices: [{delta: {\n content: \"(\u00e3\u0192\u201e) \u00e2\u2020\u2019 Test message from Bedrock Proxy Endpoint\"\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n\n res.end();\n});\n\n// --------------------------------------------------------\n// -- Endpoint: infer AWS Bedrock Proxy Chat Completions --\n// --------------------------------------------------------\napp.post('/chat/completions', async (req, res) => {\n if (CONSOLE_LOGGING) { console.log(\"\\n\\n--new '/chat/completions' request --------------------------------\"); }\n\n // Extract parameters from the incoming request\n const {\n messages = [],\n model = 'Llama-3-8b',\n max_tokens = 800,\n temperature = 0.1,\n top_p = 0.9,\n stream = true,\n include_thinking_data = false\n } = req.body;\n\n // validate messages array exists\n if (!messages.length) {\n res.status(400).send('Messages array is empty');\n return;\n }\n\n // extract AWS credentials from the request\n const bearerToken = req.rawHeaders.find(item => item.startsWith(\"Bearer \"));\n const token = bearerToken ? bearerToken.substring(7) : null;\n const tokenParts = extractAWSCreds(token);\n if (tokenParts.error) {\n res.status(401).send(tokenParts.message);\n return;\n } else {\n var { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = tokenParts.credentials;\n }\n \n // validate AWS credentials\n if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {\n res.status(401).send('Unauthorized');\n return;\n }\n\n // ---------------------------------------------------\n // -- create an object to hold your AWS credentials --\n // ---------------------------------------------------\n const awsCreds = {\n region: AWS_REGION,\n accessKeyId: AWS_ACCESS_KEY_ID,\n secretAccessKey: AWS_SECRET_ACCESS_KEY,\n };\n // ----------------------------------------------------------------------\n // -- create an object that copies your openai chat completions object --\n // ----------------------------------------------------------------------\n const openaiChatCompletionsCreateObject = {\n messages: messages,\n model: model,\n max_tokens: max_tokens,\n stream: stream,\n temperature: temperature,\n top_p: top_p,\n include_thinking_data: include_thinking_data,\n ...(req.body.stop && { stop: req.body.stop }),\n ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })\n };\n\n // set the response headers\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n // create a variable to hold the complete response\n let completeResponse = '';\n\n try {\n // check if the call is streamed\n if (openaiChatCompletionsCreateObject.stream) {\n // -------------------\n // -- streamed call --\n // -------------------\n for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING })) {\n // collect the response chunks\n completeResponse += chunk;\n // create a data object and send to the client\n const data = {choices: [{delta: {\n content: chunk\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n // log the response to the console\n if (CONSOLE_LOGGING) { stdout.write(chunk); }\n }\n res.end();\n } else {\n // ---------------------\n // -- unstreamed call --\n // ---------------------\n const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING });\n for await (const data of response) {\n // collect the response\n completeResponse += data;\n }\n // create a data object and send to the client\n const data = {choices: [{message: {\n content: completeResponse\n }}]};\n res.write(JSON.stringify(data));\n res.end();\n }\n } catch (error) {\n if (error.name === 'ThrottlingException') {\n console.error(\"Error during streaming:\", error);\n if (!res.headersSent) {\n res.status(429).send(\"Too many requests, please wait before trying again.\");\n }\n } else {\n console.error(\"Error during request processing:\", error);\n if (!res.headersSent) {\n res.status(500).send(\"Server error during request processing.\");\n }\n }\n }\n});\n\n\n// ----------------------\n// -- start the server --\n// ----------------------\nif (HTTP_ENABLED) {\n // start the HTTP server\n const httpServer = http.createServer(app);\n httpServer.listen(HTTP_PORT, () => {\n console.log(`HTTP Server listening on port ${HTTP_PORT}`);\n });\n}\nif (HTTPS_ENABLED) {\n // start the HTTPS server\n const httpsServer = https.createServer({\n key: fs.readFileSync(HTTPS_KEY_PATH, 'utf-8'),\n cert: fs.readFileSync(HTTPS_CERT_PATH, 'utf-8')\n }, app);\n httpsServer.listen(HTTPS_PORT, () => {\n console.log(`HTTPS Server listening on port ${HTTPS_PORT}`);\n });\n} \n",
8002
+ "numLines": 257,
8003
+ "startLine": 1,
8004
+ "totalLines": 257
8005
+ }
8006
+ }
8007
+ },
8008
+ {
8009
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8010
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8011
+ "cwd": "C:\\git\\bedrock-wrapper",
8012
+ "hook_event_name": "PostToolUse",
8013
+ "tool_name": "Read",
8014
+ "tool_input": {
8015
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\package.json"
8016
+ },
8017
+ "tool_response": {
8018
+ "type": "text",
8019
+ "file": {
8020
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\package.json",
8021
+ "content": "{\n \"name\": \"bedrock-proxy-endpoint\",\n \"version\": \"2.4.5\",\n \"description\": \"\u00f0\u0178\u201d\u20ac Bedrock Proxy Endpoint \u00e2\u2021\u00a2 Spin up your own custom OpenAI API server endpoint for easy AWS Bedrock inference (using standard `baseUrl`, and `apiKey` params)\",\n \"main\": \"server.js\",\n \"type\": \"module\",\n \"scripts\": {\n \"clean\": \"npx rimraf node_modules && npx rimraf package-lock.json && npm install\",\n \"server\": \"node --no-deprecation server.js\",\n \"start\": \"node --no-deprecation server.js\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\",\n \"test:watch\": \"vitest --watch\",\n \"test:coverage\": \"vitest run --coverage\",\n \"test:ui\": \"vitest --ui\",\n \"prepare\": \"husky\"\n },\n \"keywords\": [\n \"openai\",\n \"bedrock\",\n \"aws\",\n \"proxy\",\n \"wrapper\",\n \"serverless\",\n \"inference\",\n \"llm\"\n ],\n \"author\": \"\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"bedrock-wrapper\": \"^2.5.0\",\n \"body-parser\": \"^1.20.3\",\n \"dotenv\": \"^17.2.1\",\n \"express\": \"^4.21.2\",\n \"express-rate-limit\": \"^7.5.1\"\n },\n \"devDependencies\": {\n \"@vitest/coverage-v8\": \"^3.2.4\",\n \"@vitest/ui\": \"^3.2.4\",\n \"husky\": \"^9.1.7\",\n \"supertest\": \"^7.1.4\",\n \"vitest\": \"^3.2.4\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git@github.com-jparkerweb:jparkerweb/bedrock-proxy-endpoint.git\"\n }\n}\n",
8022
+ "numLines": 49,
8023
+ "startLine": 1,
8024
+ "totalLines": 49
8025
+ }
8026
+ }
8027
+ },
8028
+ {
8029
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8030
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8031
+ "cwd": "C:\\git\\bedrock-wrapper",
8032
+ "hook_event_name": "PostToolUse",
8033
+ "tool_name": "Read",
8034
+ "tool_input": {
8035
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\README.md"
8036
+ },
8037
+ "tool_response": {
8038
+ "type": "text",
8039
+ "file": {
8040
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\README.md",
8041
+ "content": "# \u00f0\u0178\u201d\u20ac Bedrock Proxy Endpoint\nSpin up your own custom OpenAI API server endpoint for easy AWS Bedrock LLM text inference (using standard `baseUrl`, and `apiKey` params)\n\n![bedrock-proxy-endpoint](https://raw.githubusercontent.com/jparkerweb/bedrock-proxy-endpoint/refs/heads/main/.readme/bedrock-proxy-endpoint.jpg)\n\n### Maintained by\n<a href=\"https://www.equilllabs.com\">\n <img src=\"https://raw.githubusercontent.com/jparkerweb/eQuill-Labs/refs/heads/main/src/static/images/logo-text-outline.png\" alt=\"eQuill Labs\" height=\"40\">\n</a>\n\n---\n\n### Why Bedrock Proxy Endpoint?\n\nAre you are stuck with using AWS Bedrock for all LLM text inference, but you want to keep your application platform agnostic? Are you tired of figuring out how to format your LLM inference calls to work with the Bedrock SDK? Are you going crazy with all the differences between configuration from model to model?\n\n- `Bedrock Proxy Endpoint` makes it easy to continue using the OpenAI API client that you are use to by standing up your own OpenAI text compatible endpoint that will proxy all your calls to Bedrock in a compatible way.\n\n- Great for getting existing OpenAI API compatible applications working with AWS Bedrock.\n\n\n### Prerequisites\n\nBefore getting started, make sure you have the following installed:\n\n- Node.js (version 12 or higher)\n- npm (Node Package Manager)\n\n### Installation\n\n1. Clone the repository:\n\n ```bash\n git clone https://github.com/jparkerweb/bedrock-proxy-endpoint.git\n ```\n\n2. Navigate to the project directory:\n\n ```bash\n cd bedrock-proxy-endpoint\n ```\n\n3. Install the dependencies:\n\n ```bash\n npm ci\n ```\n\n### Configuration\n\n* Update the `.env` file in the root directory of the project with the following\n environment variables based on your desired configuration:\n\n | key | value type | example | notes |\n |----------------------------|------------|---------------------------|--------------------------------|\n | CONSOLE_LOGGING | boolean | false | Show realtime logs |\n | HTTP_ENABLED | boolean | true | Start a HTTP server |\n | HTTP_PORT | integer | 80 | HTTP server port |\n | MAX_REQUEST_BODY_SIZE | string | 50mb | Maximum size for request body |\n | HTTPS_ENABLED | boolean | false | Start a HTTPS server |\n | HTTPS_PORT | integer | 443 | HTTPS server port |\n | HTTPS_KEY_PATH | string | ./path/mykey.key | Path to key file for HTTPS |\n | HTTPS_CERT_PATH | string | ./path/mycert.pem | Path to cert file for HTTPS |\n | IP_RATE_LIMIT_ENABLED | boolean | true | Enable rate limiting by IP |\n | IP_RATE_LIMIT_WINDOW_MS | integer | 60000 | Window in milliseconds |\n | IP_RATE_LIMIT_MAX_REQUESTS | integer | 100 | Max requests per IP per window |\n\n### Authentication\n\n`Bedrock Proxy` authenticates with AWS via `IAM`. Since the OpenAI API intance accpets an API Key we will utilize this value to hold your credentials. Construct your `apiKey` for inference in the next step following this format:\n\n- `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}`\n- example `apiKey` value: \n `us-west-2.AKIAWSXXXXXXXXXXX.YYYYYYYYYYYYYYYYYYYYYYYYY`\n\n### Usage\n\n- Start the server via: `node server` \n\n <img src=\"docs/console.png\"> \n\n You are now ready to make a standard chat completions to the server.\n\n- Important values\n - `baseUrl`: Root address of server based on your `.env` configuration.\n - `apiKey`: Descibed in the *Authentication* section above.\n - `messages`: Array of objects in role / content format.\n - `model`: This is the `modelName` from the list of supported models found on the `Bedrock Wrapper` README file [here](https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.\n - `include_thinking_data`: _Optional_ boolean parameter that when set to `true` will include the model's thinking process in the response (only used with thinking models such as `Claude-3-7-Sonnet-Thinking`).\n - `stop` or `stop_sequences`: _Optional_ parameter to specify text sequences that will cause the model to stop generating (e.g., `[\"STOP\", \"END\"]`).\n\n### Example OpenAI API Call\nLook at the example folder for complete examples of how to use the server:\n- `example.js` - Basic text completion example\n- `example-vision.js` - Vision model example with image processing (image can be passed as a base64 string or a URL)\n- `example-stop-sequences.js` - Stop sequences example demonstrating how to control where generation stops\n\n```javascript\nimport OpenAI from 'openai';\n\nconst messages = [\n {\n role: \"system\",\n content: \"You are a helpful AI assistant that follows instructions extremely well. Answer the user questions accurately.\",\n },\n {\n role: \"user\",\n content: \"Describe why the OpenAI API standard is so great. Limit your response to five sentences.\",\n },\n {\n role: \"assistant\",\n content: \"\",\n },\n];\n\nconst baseURL = \"http://localhost\"; // URL of the Bedrock Proxy Endpoint\nconst apiKey = `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}` // Your AWS Creds / API Key\n\nconst openai = new OpenAI({\n baseURL: baseURL,\n apiKey: apiKey,\n});\n\nasync function main() {\n try {\n const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-4-Sonnet\",\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: false, // Set to true for thinking models like \"Claude-4-Sonnet-Thinking\"\n });\n\n if (chatCompletion) {\n for await (const chunk of chatCompletion) {\n const response = chunk.choices[0]?.delta?.content || \"\";\n process.stdout.write(response);\n }\n }\n } catch (error) {\n console.error('Error:', error);\n } finally {\n process.exit(0);\n }\n}\n\nmain();\n```\n\n### Root Info Page\n\nPoint your browser to the root of your endpoint server to view the info page: (example: `http://localhost`) \n\n<img src=\"docs/bedrock-proxy-endpoint.png\" style=\"max-width:700px\">\n\n### Note\n\nAlternativly you can incorporate \u00f0\u0178\u00aa\u00a8 <a href=\"https://github.com/jparkerweb/bedrock-wrapper\" target=\"bedrockWrapper\">`Bedrock Wrapper`</a> core directly into your code base. If you would like to explore that option checkout the npm package here: https://www.npmjs.com/package/bedrock-wrapper\n\n---\n\nPlease consider sending me a tip to support my work \u00f0\u0178\u02dc\u20ac\n# [\u00f0\u0178\udc8d\u00b5 tip me here](https://ko-fi.com/jparkerweb)\n",
8042
+ "numLines": 166,
8043
+ "startLine": 1,
8044
+ "totalLines": 166
8045
+ }
8046
+ }
8047
+ },
8048
+ {
8049
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8050
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8051
+ "cwd": "C:\\git\\bedrock-wrapper",
8052
+ "hook_event_name": "PostToolUse",
8053
+ "tool_name": "Read",
8054
+ "tool_input": {
8055
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\example\\example.js"
8056
+ },
8057
+ "tool_response": {
8058
+ "type": "text",
8059
+ "file": {
8060
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\example\\example.js",
8061
+ "content": "import OpenAI from 'openai';\nimport dotenv from 'dotenv';\n\ndotenv.config();\nconst { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = process.env;\n\nconst messages = [\n {\n role: \"system\",\n content: \"You are a helpful AI assistant that follows instructions extremely well. Answer the user questions accurately.\",\n },\n {\n role: \"user\",\n content: \"Describe why the OpenAI API standard is so great. Limit your response to five sentences.\",\n },\n {\n role: \"assistant\",\n content: \"\",\n },\n];\n\nconst baseURL = \"http://localhost:88\"; // URL of the Bedrock Proxy Endpoint\nconst apiKey = `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}` // Your AWS Creds / API Key\n\nconst openai = new OpenAI({\n baseURL: baseURL,\n apiKey: apiKey,\n});\n\nasync function main() {\n try {\n const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-3-7-Sonnet-Thinking\", // Try: \"Claude-4-Sonnet\", \"Claude-4-Opus\", \"Claude-4-Sonnet-Thinking\", \"Claude-4-Opus-Thinking\"\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: true, // Works with thinking models\n });\n\n if (chatCompletion) {\n for await (const chunk of chatCompletion) {\n const response = chunk.choices[0]?.delta?.content || \"\";\n process.stdout.write(response);\n }\n // Add a newline at the end for cleaner output\n process.stdout.write('\\n');\n }\n } catch (error) {\n console.error('Error:', error);\n } finally {\n // Explicitly exit the process when done\n process.exit(0);\n }\n}\n\nmain();",
8062
+ "numLines": 58,
8063
+ "startLine": 1,
8064
+ "totalLines": 58
8065
+ }
8066
+ }
8067
+ },
8068
+ {
8069
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8070
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8071
+ "cwd": "C:\\git\\bedrock-wrapper",
8072
+ "hook_event_name": "PostToolUse",
8073
+ "tool_name": "Read",
8074
+ "tool_input": {
8075
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\CHANGELOG.md"
8076
+ },
8077
+ "tool_response": {
8078
+ "type": "text",
8079
+ "file": {
8080
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\CHANGELOG.md",
8081
+ "content": "# Changelog\nAll notable changes to this project will be documented in this file.\n\n## [2.4.5] - 2025-08-06\n### Added\n- Updated to use Bedrock Wrapper v2.4.5\n- Support for OpenAI GPT-OSS models on AWS Bedrock\n - GPT-OSS-120B (120B parameter open weight model)\n - GPT-OSS-20B (20B parameter open weight model)\n - GPT-OSS-120B-Thinking (with reasoning tag preservation)\n - GPT-OSS-20B-Thinking (with reasoning tag preservation)\n- `<reasoning>` tag processing for GPT-OSS thinking variants\n - Regular GPT-OSS models automatically strip `<reasoning>` tags\n - Thinking variants preserve `<reasoning>` tags (similar to Claude's `<think>` tags)\n\n## [2.4.4] - 2025-08-05\n### Added\n- Updated to use Bedrock Wrapper v2.4.4\n- Support for Claude Opus 4.1 models:\n - Claude-4-1-Opus (with image support)\n - Claude-4-1-Opus-Thinking (with image support)\n\n## [2.4.3] - 2025-07-31\n### Added\n- Updated to use Bedrock Wrapper v2.4.3\n- Refined stop sequences support with model-specific limitations:\n - Claude models: Full support (up to 8,191 sequences)\n - Nova models: Full support (up to 4 sequences) \n - Mistral models: Full support (up to 10 sequences)\n - Llama models: No stop sequences support (AWS Bedrock limitation)\n- Improved error handling for early response termination\n- Fixed Nova model configuration conflicts\n\n## [2.4.2] - 2025-07-31\n### Added\n- Updated to use Bedrock Wrapper v2.4.2\n- Support for Claude 4 models:\n - Claude-4-Opus (with image support)\n - Claude-4-Opus-Thinking (with image support)\n - Claude-4-Sonnet (with image support) \n - Claude-4-Sonnet-Thinking (with image support)\n- Stop sequences support (`stop_sequences` parameter)\n- Compatible with OpenAI's `stop` parameter for controlling generation stopping points\n\n## [2.4.1] - 2025-07-24\n### Added\n- Updated to use Bedrock Wrapper v2.4.1\\\n- Vision support for Claude 3 Haiku\n- Support for Amazon Nova models:\n - Amazon Nova Micro (text-only, ultra-low latency)\n - Amazon Nova Lite (multimodal, low-cost)\n - Amazon Nova Pro (multimodal, high capability)\n\n## [2.3.1] - 2025-05-28\n### Added\n- Updated to use Bedrock Wrapper v2.3.1\n - Support for Claude Sonnet 4\n - Support for Claude Opus 4\n\n## [2.3.0] - 2025-02-27 - Claude Sonnet 3.7 + Vision\n### Added\n- Support for Claude Sonnet 3.7\n- Support for Clause Sonnet 3.7 Thinking\n- Support for Claude Sonnet 3.x Vision\n\n## [2.2.0] - 2025-01-01 - Llama 3.3 70b\n### Added\n- Support for Llama 3.3 70b\n\n## [2.1.0] - 2024-11-21 - Claude Haiku 3.5\n### Added\n- Support for \"Anthropic Claude 3.5 Haiku\"\n\n## [2.0.0] - 2024-10-31 - Claude\n### Added\n- Updated to use Bedrock Wrapper v2.0.0\n- Model support for:\n - Claude 3.5 Sonnet V2\n - Claude 3.5 Sonnet\n - Claude 3 Haiku\n- Unstreamed response are returned as a string similar to streaming responses\n > Note: This could be a breaking change for any clients that are expecting a JSON response from unstreamed responses\n\n## [1.0.9] - 2024-09-25 - Lamma 3.2\n### Added\n- Model support for:\n - Llama 3.2 1b\n - Llama 3.2 3b\n - Llama 3.2 11b\n - Llama 3.2 90b\n\n\n## [1.0.7] - 2024-07-24 - Lamma 3.1\n### Added\n- Model support for:\n - Llama-3-1-8b\n - Llama-3-1-70b\n\n\n## [1.0.3] - 2024-05-06 - Initial Stable Release\n### Added\n- OpenAI API compatible proxy endpoint for AWS Bedrock\n- Support for HTTP and HTTPS servers\n- IP-based rate limiting\n- Environment variable configuration\n- AWS IAM authentication via API key\n- Streaming and non-streaming responses\n- `/models` endpoint to list supported models\n- Root info page with documentation\n- Endpoint type\n - `/chat/completions`\n- Model Support for:\n - Llama-3-8b\n - Llama-3-70b\n - Mistral-7b\n - Mixtral-8x7b\n - Mistral-Large\n- Error handling middleware\n- Console logging toggle\n\n### Security\n- HTTPS support with custom key and certificate paths\n- Rate limiting configuration options\n- AWS IAM authentication required for API access\n\n### Documentation\n- Installation instructions\n- Configuration guide\n- Authentication details\n- Usage examples\n- API endpoint documentation \n",
8082
+ "numLines": 132,
8083
+ "startLine": 1,
8084
+ "totalLines": 132
8085
+ }
8086
+ }
8087
+ },
8088
+ {
8089
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8090
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8091
+ "cwd": "C:\\git\\bedrock-wrapper",
8092
+ "hook_event_name": "PostToolUse",
8093
+ "tool_name": "ExitPlanMode",
8094
+ "tool_input": {
8095
+ "plan": "## Plan to Add `useConverseAPI` Parameter to Bedrock Proxy Endpoint\n\nI'll add the `useConverseAPI` optional parameter to the bedrock-proxy-endpoint project, following the same pattern as the existing `include_thinking_data` parameter.\n\n### Changes Required:\n\n#### 1. **server.js** (Main proxy server file)\n- **Line 128-129**: Add `use_converse_api = false` to the parameter extraction, right after `include_thinking_data`\n- **Line 172**: Add `use_converse_api` to the `openaiChatCompletionsCreateObject`\n- **Line 193**: Update the `bedrockWrapper` call to pass `useConverseAPI: use_converse_api` in the options object\n- **Line 209**: Update the non-streaming `bedrockWrapper` call similarly\n\n#### 2. **README.md** (Documentation)\n- Add documentation for the new `use_converse_api` parameter in the \"Important values\" section (around line 90)\n- Update the example code to show the new parameter (around line 134)\n- Add a note explaining the benefits of the Converse API\n\n#### 3. **example/example.js** (Example file)\n- Add the `use_converse_api` parameter to the example (around line 40)\n- Add a comment explaining when to use it\n\n#### 4. **package.json**\n- Update version from 2.4.5 to 2.5.0 to match the bedrock-wrapper version that includes Converse API support\n\n#### 5. **CHANGELOG.md**\n- Add a new entry for version 2.5.0 documenting the Converse API support\n\n### Implementation Details:\n\nThe parameter will:\n- Default to `false` to maintain backward compatibility (uses Invoke API by default)\n- When set to `true`, use AWS Bedrock's Converse API for unified request/response format\n- Work exactly like `include_thinking_data` - as an optional boolean parameter in the OpenAI chat completions request\n\n### Benefits of this addition:\n- Allows users to opt-in to the simpler, unified Converse API\n- Provides better consistency across different model families\n- Maintains full backward compatibility with existing implementations\n- Follows the established pattern for optional parameters in the codebase"
8096
+ },
8097
+ "tool_response": {
8098
+ "plan": "## Plan to Add `useConverseAPI` Parameter to Bedrock Proxy Endpoint\n\nI'll add the `useConverseAPI` optional parameter to the bedrock-proxy-endpoint project, following the same pattern as the existing `include_thinking_data` parameter.\n\n### Changes Required:\n\n#### 1. **server.js** (Main proxy server file)\n- **Line 128-129**: Add `use_converse_api = false` to the parameter extraction, right after `include_thinking_data`\n- **Line 172**: Add `use_converse_api` to the `openaiChatCompletionsCreateObject`\n- **Line 193**: Update the `bedrockWrapper` call to pass `useConverseAPI: use_converse_api` in the options object\n- **Line 209**: Update the non-streaming `bedrockWrapper` call similarly\n\n#### 2. **README.md** (Documentation)\n- Add documentation for the new `use_converse_api` parameter in the \"Important values\" section (around line 90)\n- Update the example code to show the new parameter (around line 134)\n- Add a note explaining the benefits of the Converse API\n\n#### 3. **example/example.js** (Example file)\n- Add the `use_converse_api` parameter to the example (around line 40)\n- Add a comment explaining when to use it\n\n#### 4. **package.json**\n- Update version from 2.4.5 to 2.5.0 to match the bedrock-wrapper version that includes Converse API support\n\n#### 5. **CHANGELOG.md**\n- Add a new entry for version 2.5.0 documenting the Converse API support\n\n### Implementation Details:\n\nThe parameter will:\n- Default to `false` to maintain backward compatibility (uses Invoke API by default)\n- When set to `true`, use AWS Bedrock's Converse API for unified request/response format\n- Work exactly like `include_thinking_data` - as an optional boolean parameter in the OpenAI chat completions request\n\n### Benefits of this addition:\n- Allows users to opt-in to the simpler, unified Converse API\n- Provides better consistency across different model families\n- Maintains full backward compatibility with existing implementations\n- Follows the established pattern for optional parameters in the codebase",
8099
+ "isAgent": false
8100
+ }
8101
+ },
8102
+ {
8103
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8104
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8105
+ "cwd": "C:\\git\\bedrock-wrapper",
8106
+ "hook_event_name": "PostToolUse",
8107
+ "tool_name": "TodoWrite",
8108
+ "tool_input": {
8109
+ "todos": [
8110
+ {
8111
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8112
+ "status": "pending",
8113
+ "id": "1"
8114
+ },
8115
+ {
8116
+ "content": "Update README.md to document the new use_converse_api parameter",
8117
+ "status": "pending",
8118
+ "id": "2"
8119
+ },
8120
+ {
8121
+ "content": "Update example/example.js to include use_converse_api in the example",
8122
+ "status": "pending",
8123
+ "id": "3"
8124
+ },
8125
+ {
8126
+ "content": "Update package.json version to 2.5.0",
8127
+ "status": "pending",
8128
+ "id": "4"
8129
+ },
8130
+ {
8131
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8132
+ "status": "pending",
8133
+ "id": "5"
8134
+ }
8135
+ ]
8136
+ },
8137
+ "tool_response": {
8138
+ "oldTodos": [
8139
+ {
8140
+ "content": "Integrate thinking support directly into bedrock-wrapper.js Converse API path",
8141
+ "status": "completed",
8142
+ "id": "13"
8143
+ }
8144
+ ],
8145
+ "newTodos": [
8146
+ {
8147
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8148
+ "status": "pending",
8149
+ "id": "1"
8150
+ },
8151
+ {
8152
+ "content": "Update README.md to document the new use_converse_api parameter",
8153
+ "status": "pending",
8154
+ "id": "2"
8155
+ },
8156
+ {
8157
+ "content": "Update example/example.js to include use_converse_api in the example",
8158
+ "status": "pending",
8159
+ "id": "3"
8160
+ },
8161
+ {
8162
+ "content": "Update package.json version to 2.5.0",
8163
+ "status": "pending",
8164
+ "id": "4"
8165
+ },
8166
+ {
8167
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8168
+ "status": "pending",
8169
+ "id": "5"
8170
+ }
8171
+ ]
8172
+ }
8173
+ },
8174
+ {
8175
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8176
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8177
+ "cwd": "C:\\git\\bedrock-wrapper",
8178
+ "hook_event_name": "PostToolUse",
8179
+ "tool_name": "TodoWrite",
8180
+ "tool_input": {
8181
+ "todos": [
8182
+ {
8183
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8184
+ "status": "in_progress",
8185
+ "id": "1"
8186
+ },
8187
+ {
8188
+ "content": "Update README.md to document the new use_converse_api parameter",
8189
+ "status": "pending",
8190
+ "id": "2"
8191
+ },
8192
+ {
8193
+ "content": "Update example/example.js to include use_converse_api in the example",
8194
+ "status": "pending",
8195
+ "id": "3"
8196
+ },
8197
+ {
8198
+ "content": "Update package.json version to 2.5.0",
8199
+ "status": "pending",
8200
+ "id": "4"
8201
+ },
8202
+ {
8203
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8204
+ "status": "pending",
8205
+ "id": "5"
8206
+ }
8207
+ ]
8208
+ },
8209
+ "tool_response": {
8210
+ "oldTodos": [
8211
+ {
8212
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8213
+ "status": "pending",
8214
+ "id": "1"
8215
+ },
8216
+ {
8217
+ "content": "Update README.md to document the new use_converse_api parameter",
8218
+ "status": "pending",
8219
+ "id": "2"
8220
+ },
8221
+ {
8222
+ "content": "Update example/example.js to include use_converse_api in the example",
8223
+ "status": "pending",
8224
+ "id": "3"
8225
+ },
8226
+ {
8227
+ "content": "Update package.json version to 2.5.0",
8228
+ "status": "pending",
8229
+ "id": "4"
8230
+ },
8231
+ {
8232
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8233
+ "status": "pending",
8234
+ "id": "5"
8235
+ }
8236
+ ],
8237
+ "newTodos": [
8238
+ {
8239
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8240
+ "status": "in_progress",
8241
+ "id": "1"
8242
+ },
8243
+ {
8244
+ "content": "Update README.md to document the new use_converse_api parameter",
8245
+ "status": "pending",
8246
+ "id": "2"
8247
+ },
8248
+ {
8249
+ "content": "Update example/example.js to include use_converse_api in the example",
8250
+ "status": "pending",
8251
+ "id": "3"
8252
+ },
8253
+ {
8254
+ "content": "Update package.json version to 2.5.0",
8255
+ "status": "pending",
8256
+ "id": "4"
8257
+ },
8258
+ {
8259
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8260
+ "status": "pending",
8261
+ "id": "5"
8262
+ }
8263
+ ]
8264
+ }
8265
+ },
8266
+ {
8267
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8268
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8269
+ "cwd": "C:\\git\\bedrock-wrapper",
8270
+ "hook_event_name": "PostToolUse",
8271
+ "tool_name": "Edit",
8272
+ "tool_input": {
8273
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\server.js",
8274
+ "old_string": " // Extract parameters from the incoming request\n const {\n messages = [],\n model = 'Llama-3-8b',\n max_tokens = 800,\n temperature = 0.1,\n top_p = 0.9,\n stream = true,\n include_thinking_data = false\n } = req.body;",
8275
+ "new_string": " // Extract parameters from the incoming request\n const {\n messages = [],\n model = 'Llama-3-8b',\n max_tokens = 800,\n temperature = 0.1,\n top_p = 0.9,\n stream = true,\n include_thinking_data = false,\n use_converse_api = false\n } = req.body;"
8276
+ },
8277
+ "tool_response": {
8278
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\server.js",
8279
+ "oldString": " // Extract parameters from the incoming request\n const {\n messages = [],\n model = 'Llama-3-8b',\n max_tokens = 800,\n temperature = 0.1,\n top_p = 0.9,\n stream = true,\n include_thinking_data = false\n } = req.body;",
8280
+ "newString": " // Extract parameters from the incoming request\n const {\n messages = [],\n model = 'Llama-3-8b',\n max_tokens = 800,\n temperature = 0.1,\n top_p = 0.9,\n stream = true,\n include_thinking_data = false,\n use_converse_api = false\n } = req.body;",
8281
+ "originalFile": "// -------------------------------------------------\n// -- import environment variables from .env file --\n// -------------------------------------------------\nimport dotenv from 'dotenv';\ndotenv.config();\n\n// ------------------------------\n// -- import utility functions --\n// ------------------------------\nimport { toBoolean, extractAWSCreds } from \"./utils.js\";\n\nconst CONSOLE_LOGGING = toBoolean(process.env.CONSOLE_LOGGING);\nconst HTTP_ENABLED = toBoolean(process.env.HTTP_ENABLED);\nconst HTTP_PORT = process.env.HTTP_PORT;\nconst HTTPS_ENABLED = toBoolean(process.env.HTTPS_ENABLED);\nconst HTTPS_PORT = process.env.HTTPS_PORT;\nconst HTTPS_KEY_PATH = process.env.HTTPS_KEY_PATH;\nconst HTTPS_CERT_PATH = process.env.HTTPS_CERT_PATH;\nconst IP_RATE_LIMIT_ENABLED = toBoolean(process.env.IP_RATE_LIMIT_ENABLED);\nconst IP_RATE_LIMIT_WINDOW_MS = parseInt(process.env.IP_RATE_LIMIT_WINDOW_MS);\nconst IP_RATE_LIMIT_MAX_REQUESTS = parseInt(process.env.IP_RATE_LIMIT_MAX_REQUESTS);\nconst MAX_REQUEST_BODY_SIZE = process.env.MAX_REQUEST_BODY_SIZE || '1mb';\n\n// --------------------------------------------\n// -- import functions from bedrock-wrapper --\n// -- - bedrockWrapper --\n// -- - listBedrockWrapperSupportedModels --\n// --------------------------------------------\nimport { \n bedrockWrapper,\n listBedrockWrapperSupportedModels\n} from \"bedrock-wrapper\";\n\nconsole.log(\" ============================ PROXY ENDPOINT =============================\");\nconsole.log(\"\");\n\n// -----------------------------------\n// -- import server and its modules --\n// -----------------------------------\nimport express from 'express';\nimport bodyParser from 'body-parser';\nimport rateLimit from 'express-rate-limit';\nimport { fileURLToPath } from 'url';\nimport https from 'https';\nimport http from 'http';\nimport path from 'path';\nimport fs from 'fs';\nimport { stdout } from 'process';\n\nconst app = express();\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\napp.use(bodyParser.json({ limit: MAX_REQUEST_BODY_SIZE }));\n\n// ------------------------------------\n// -- setup rate limiting middleware --\n// ------------------------------------\nif (IP_RATE_LIMIT_ENABLED) {\n const limiter = rateLimit({\n windowMs: IP_RATE_LIMIT_WINDOW_MS,\n max: IP_RATE_LIMIT_MAX_REQUESTS\n });\n app.use(limiter);\n}\n\n// -------------------------------\n// -- error handling middleware --\n// -------------------------------\napp.use((err, req, res, next) => {\n if (err.code === 'ECONNRESET') {\n console.warn('Connection reset by peer');\n res.status(500).send('Connection reset by peer');\n } else if (err.headersSent) {\n return next(err);\n } else {\n console.error(err.stack);\n res.status(500).send('Something broke!');\n }\n});\n\n\n// -------------------\n// -- Info endpoint --\n// -------------------\napp.get('/', (req, res) => {\n res.sendFile(path.join(__dirname, 'public', 'index.html'));\n});\n\n// -------------------------------------\n// -- Endpoint: list supported models --\n// -------------------------------------\napp.get('/models', (req, res) => {\n listBedrockWrapperSupportedModels().then(supportedModels => {\n res.json(supportedModels);\n }).catch(err => {\n res.status(500).send('Failed to fetch models');\n });\n});\n\napp.post('/test/chat/completions', async (req, res) => {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n const data = {choices: [{delta: {\n content: \"(\u00e3\u0192\u201e) \u00e2\u2020\u2019 Test message from Bedrock Proxy Endpoint\"\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n\n res.end();\n});\n\n// --------------------------------------------------------\n// -- Endpoint: infer AWS Bedrock Proxy Chat Completions --\n// --------------------------------------------------------\napp.post('/chat/completions', async (req, res) => {\n if (CONSOLE_LOGGING) { console.log(\"\\n\\n--new '/chat/completions' request --------------------------------\"); }\n\n // Extract parameters from the incoming request\n const {\n messages = [],\n model = 'Llama-3-8b',\n max_tokens = 800,\n temperature = 0.1,\n top_p = 0.9,\n stream = true,\n include_thinking_data = false\n } = req.body;\n\n // validate messages array exists\n if (!messages.length) {\n res.status(400).send('Messages array is empty');\n return;\n }\n\n // extract AWS credentials from the request\n const bearerToken = req.rawHeaders.find(item => item.startsWith(\"Bearer \"));\n const token = bearerToken ? bearerToken.substring(7) : null;\n const tokenParts = extractAWSCreds(token);\n if (tokenParts.error) {\n res.status(401).send(tokenParts.message);\n return;\n } else {\n var { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = tokenParts.credentials;\n }\n \n // validate AWS credentials\n if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {\n res.status(401).send('Unauthorized');\n return;\n }\n\n // ---------------------------------------------------\n // -- create an object to hold your AWS credentials --\n // ---------------------------------------------------\n const awsCreds = {\n region: AWS_REGION,\n accessKeyId: AWS_ACCESS_KEY_ID,\n secretAccessKey: AWS_SECRET_ACCESS_KEY,\n };\n // ----------------------------------------------------------------------\n // -- create an object that copies your openai chat completions object --\n // ----------------------------------------------------------------------\n const openaiChatCompletionsCreateObject = {\n messages: messages,\n model: model,\n max_tokens: max_tokens,\n stream: stream,\n temperature: temperature,\n top_p: top_p,\n include_thinking_data: include_thinking_data,\n ...(req.body.stop && { stop: req.body.stop }),\n ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })\n };\n\n // set the response headers\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n // create a variable to hold the complete response\n let completeResponse = '';\n\n try {\n // check if the call is streamed\n if (openaiChatCompletionsCreateObject.stream) {\n // -------------------\n // -- streamed call --\n // -------------------\n for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING })) {\n // collect the response chunks\n completeResponse += chunk;\n // create a data object and send to the client\n const data = {choices: [{delta: {\n content: chunk\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n // log the response to the console\n if (CONSOLE_LOGGING) { stdout.write(chunk); }\n }\n res.end();\n } else {\n // ---------------------\n // -- unstreamed call --\n // ---------------------\n const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING });\n for await (const data of response) {\n // collect the response\n completeResponse += data;\n }\n // create a data object and send to the client\n const data = {choices: [{message: {\n content: completeResponse\n }}]};\n res.write(JSON.stringify(data));\n res.end();\n }\n } catch (error) {\n if (error.name === 'ThrottlingException') {\n console.error(\"Error during streaming:\", error);\n if (!res.headersSent) {\n res.status(429).send(\"Too many requests, please wait before trying again.\");\n }\n } else {\n console.error(\"Error during request processing:\", error);\n if (!res.headersSent) {\n res.status(500).send(\"Server error during request processing.\");\n }\n }\n }\n});\n\n\n// ----------------------\n// -- start the server --\n// ----------------------\nif (HTTP_ENABLED) {\n // start the HTTP server\n const httpServer = http.createServer(app);\n httpServer.listen(HTTP_PORT, () => {\n console.log(`HTTP Server listening on port ${HTTP_PORT}`);\n });\n}\nif (HTTPS_ENABLED) {\n // start the HTTPS server\n const httpsServer = https.createServer({\n key: fs.readFileSync(HTTPS_KEY_PATH, 'utf-8'),\n cert: fs.readFileSync(HTTPS_CERT_PATH, 'utf-8')\n }, app);\n httpsServer.listen(HTTPS_PORT, () => {\n console.log(`HTTPS Server listening on port ${HTTPS_PORT}`);\n });\n} \n",
8282
+ "structuredPatch": [
8283
+ {
8284
+ "oldStart": 125,
8285
+ "oldLines": 7,
8286
+ "newStart": 125,
8287
+ "newLines": 8,
8288
+ "lines": [
8289
+ " temperature = 0.1,",
8290
+ " top_p = 0.9,",
8291
+ " stream = true,",
8292
+ "- include_thinking_data = false",
8293
+ "+ include_thinking_data = false,",
8294
+ "+ use_converse_api = false",
8295
+ " } = req.body;",
8296
+ " ",
8297
+ " // validate messages array exists"
8298
+ ]
8299
+ }
8300
+ ],
8301
+ "userModified": false,
8302
+ "replaceAll": false
8303
+ }
8304
+ },
8305
+ {
8306
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8307
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8308
+ "cwd": "C:\\git\\bedrock-wrapper",
8309
+ "hook_event_name": "PostToolUse",
8310
+ "tool_name": "Edit",
8311
+ "tool_input": {
8312
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\server.js",
8313
+ "old_string": " // ----------------------------------------------------------------------\n // -- create an object that copies your openai chat completions object --\n // ----------------------------------------------------------------------\n const openaiChatCompletionsCreateObject = {\n messages: messages,\n model: model,\n max_tokens: max_tokens,\n stream: stream,\n temperature: temperature,\n top_p: top_p,\n include_thinking_data: include_thinking_data,\n ...(req.body.stop && { stop: req.body.stop }),\n ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })\n };",
8314
+ "new_string": " // ----------------------------------------------------------------------\n // -- create an object that copies your openai chat completions object --\n // ----------------------------------------------------------------------\n const openaiChatCompletionsCreateObject = {\n messages: messages,\n model: model,\n max_tokens: max_tokens,\n stream: stream,\n temperature: temperature,\n top_p: top_p,\n include_thinking_data: include_thinking_data,\n use_converse_api: use_converse_api,\n ...(req.body.stop && { stop: req.body.stop }),\n ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })\n };"
8315
+ },
8316
+ "tool_response": {
8317
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\server.js",
8318
+ "oldString": " // ----------------------------------------------------------------------\n // -- create an object that copies your openai chat completions object --\n // ----------------------------------------------------------------------\n const openaiChatCompletionsCreateObject = {\n messages: messages,\n model: model,\n max_tokens: max_tokens,\n stream: stream,\n temperature: temperature,\n top_p: top_p,\n include_thinking_data: include_thinking_data,\n ...(req.body.stop && { stop: req.body.stop }),\n ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })\n };",
8319
+ "newString": " // ----------------------------------------------------------------------\n // -- create an object that copies your openai chat completions object --\n // ----------------------------------------------------------------------\n const openaiChatCompletionsCreateObject = {\n messages: messages,\n model: model,\n max_tokens: max_tokens,\n stream: stream,\n temperature: temperature,\n top_p: top_p,\n include_thinking_data: include_thinking_data,\n use_converse_api: use_converse_api,\n ...(req.body.stop && { stop: req.body.stop }),\n ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })\n };",
8320
+ "originalFile": "// -------------------------------------------------\n// -- import environment variables from .env file --\n// -------------------------------------------------\nimport dotenv from 'dotenv';\ndotenv.config();\n\n// ------------------------------\n// -- import utility functions --\n// ------------------------------\nimport { toBoolean, extractAWSCreds } from \"./utils.js\";\n\nconst CONSOLE_LOGGING = toBoolean(process.env.CONSOLE_LOGGING);\nconst HTTP_ENABLED = toBoolean(process.env.HTTP_ENABLED);\nconst HTTP_PORT = process.env.HTTP_PORT;\nconst HTTPS_ENABLED = toBoolean(process.env.HTTPS_ENABLED);\nconst HTTPS_PORT = process.env.HTTPS_PORT;\nconst HTTPS_KEY_PATH = process.env.HTTPS_KEY_PATH;\nconst HTTPS_CERT_PATH = process.env.HTTPS_CERT_PATH;\nconst IP_RATE_LIMIT_ENABLED = toBoolean(process.env.IP_RATE_LIMIT_ENABLED);\nconst IP_RATE_LIMIT_WINDOW_MS = parseInt(process.env.IP_RATE_LIMIT_WINDOW_MS);\nconst IP_RATE_LIMIT_MAX_REQUESTS = parseInt(process.env.IP_RATE_LIMIT_MAX_REQUESTS);\nconst MAX_REQUEST_BODY_SIZE = process.env.MAX_REQUEST_BODY_SIZE || '1mb';\n\n// --------------------------------------------\n// -- import functions from bedrock-wrapper --\n// -- - bedrockWrapper --\n// -- - listBedrockWrapperSupportedModels --\n// --------------------------------------------\nimport { \n bedrockWrapper,\n listBedrockWrapperSupportedModels\n} from \"bedrock-wrapper\";\n\nconsole.log(\" ============================ PROXY ENDPOINT =============================\");\nconsole.log(\"\");\n\n// -----------------------------------\n// -- import server and its modules --\n// -----------------------------------\nimport express from 'express';\nimport bodyParser from 'body-parser';\nimport rateLimit from 'express-rate-limit';\nimport { fileURLToPath } from 'url';\nimport https from 'https';\nimport http from 'http';\nimport path from 'path';\nimport fs from 'fs';\nimport { stdout } from 'process';\n\nconst app = express();\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\napp.use(bodyParser.json({ limit: MAX_REQUEST_BODY_SIZE }));\n\n// ------------------------------------\n// -- setup rate limiting middleware --\n// ------------------------------------\nif (IP_RATE_LIMIT_ENABLED) {\n const limiter = rateLimit({\n windowMs: IP_RATE_LIMIT_WINDOW_MS,\n max: IP_RATE_LIMIT_MAX_REQUESTS\n });\n app.use(limiter);\n}\n\n// -------------------------------\n// -- error handling middleware --\n// -------------------------------\napp.use((err, req, res, next) => {\n if (err.code === 'ECONNRESET') {\n console.warn('Connection reset by peer');\n res.status(500).send('Connection reset by peer');\n } else if (err.headersSent) {\n return next(err);\n } else {\n console.error(err.stack);\n res.status(500).send('Something broke!');\n }\n});\n\n\n// -------------------\n// -- Info endpoint --\n// -------------------\napp.get('/', (req, res) => {\n res.sendFile(path.join(__dirname, 'public', 'index.html'));\n});\n\n// -------------------------------------\n// -- Endpoint: list supported models --\n// -------------------------------------\napp.get('/models', (req, res) => {\n listBedrockWrapperSupportedModels().then(supportedModels => {\n res.json(supportedModels);\n }).catch(err => {\n res.status(500).send('Failed to fetch models');\n });\n});\n\napp.post('/test/chat/completions', async (req, res) => {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n const data = {choices: [{delta: {\n content: \"(\u00e3\u0192\u201e) \u00e2\u2020\u2019 Test message from Bedrock Proxy Endpoint\"\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n\n res.end();\n});\n\n// --------------------------------------------------------\n// -- Endpoint: infer AWS Bedrock Proxy Chat Completions --\n// --------------------------------------------------------\napp.post('/chat/completions', async (req, res) => {\n if (CONSOLE_LOGGING) { console.log(\"\\n\\n--new '/chat/completions' request --------------------------------\"); }\n\n // Extract parameters from the incoming request\n const {\n messages = [],\n model = 'Llama-3-8b',\n max_tokens = 800,\n temperature = 0.1,\n top_p = 0.9,\n stream = true,\n include_thinking_data = false,\n use_converse_api = false\n } = req.body;\n\n // validate messages array exists\n if (!messages.length) {\n res.status(400).send('Messages array is empty');\n return;\n }\n\n // extract AWS credentials from the request\n const bearerToken = req.rawHeaders.find(item => item.startsWith(\"Bearer \"));\n const token = bearerToken ? bearerToken.substring(7) : null;\n const tokenParts = extractAWSCreds(token);\n if (tokenParts.error) {\n res.status(401).send(tokenParts.message);\n return;\n } else {\n var { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = tokenParts.credentials;\n }\n \n // validate AWS credentials\n if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {\n res.status(401).send('Unauthorized');\n return;\n }\n\n // ---------------------------------------------------\n // -- create an object to hold your AWS credentials --\n // ---------------------------------------------------\n const awsCreds = {\n region: AWS_REGION,\n accessKeyId: AWS_ACCESS_KEY_ID,\n secretAccessKey: AWS_SECRET_ACCESS_KEY,\n };\n // ----------------------------------------------------------------------\n // -- create an object that copies your openai chat completions object --\n // ----------------------------------------------------------------------\n const openaiChatCompletionsCreateObject = {\n messages: messages,\n model: model,\n max_tokens: max_tokens,\n stream: stream,\n temperature: temperature,\n top_p: top_p,\n include_thinking_data: include_thinking_data,\n ...(req.body.stop && { stop: req.body.stop }),\n ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })\n };\n\n // set the response headers\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n // create a variable to hold the complete response\n let completeResponse = '';\n\n try {\n // check if the call is streamed\n if (openaiChatCompletionsCreateObject.stream) {\n // -------------------\n // -- streamed call --\n // -------------------\n for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING })) {\n // collect the response chunks\n completeResponse += chunk;\n // create a data object and send to the client\n const data = {choices: [{delta: {\n content: chunk\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n // log the response to the console\n if (CONSOLE_LOGGING) { stdout.write(chunk); }\n }\n res.end();\n } else {\n // ---------------------\n // -- unstreamed call --\n // ---------------------\n const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING });\n for await (const data of response) {\n // collect the response\n completeResponse += data;\n }\n // create a data object and send to the client\n const data = {choices: [{message: {\n content: completeResponse\n }}]};\n res.write(JSON.stringify(data));\n res.end();\n }\n } catch (error) {\n if (error.name === 'ThrottlingException') {\n console.error(\"Error during streaming:\", error);\n if (!res.headersSent) {\n res.status(429).send(\"Too many requests, please wait before trying again.\");\n }\n } else {\n console.error(\"Error during request processing:\", error);\n if (!res.headersSent) {\n res.status(500).send(\"Server error during request processing.\");\n }\n }\n }\n});\n\n\n// ----------------------\n// -- start the server --\n// ----------------------\nif (HTTP_ENABLED) {\n // start the HTTP server\n const httpServer = http.createServer(app);\n httpServer.listen(HTTP_PORT, () => {\n console.log(`HTTP Server listening on port ${HTTP_PORT}`);\n });\n}\nif (HTTPS_ENABLED) {\n // start the HTTPS server\n const httpsServer = https.createServer({\n key: fs.readFileSync(HTTPS_KEY_PATH, 'utf-8'),\n cert: fs.readFileSync(HTTPS_CERT_PATH, 'utf-8')\n }, app);\n httpsServer.listen(HTTPS_PORT, () => {\n console.log(`HTTPS Server listening on port ${HTTPS_PORT}`);\n });\n} \n",
8321
+ "structuredPatch": [
8322
+ {
8323
+ "oldStart": 171,
8324
+ "oldLines": 6,
8325
+ "newStart": 171,
8326
+ "newLines": 7,
8327
+ "lines": [
8328
+ " temperature: temperature,",
8329
+ " top_p: top_p,",
8330
+ " include_thinking_data: include_thinking_data,",
8331
+ "+ use_converse_api: use_converse_api,",
8332
+ " ...(req.body.stop && { stop: req.body.stop }),",
8333
+ " ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })",
8334
+ " };"
8335
+ ]
8336
+ }
8337
+ ],
8338
+ "userModified": false,
8339
+ "replaceAll": false
8340
+ }
8341
+ },
8342
+ {
8343
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8344
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8345
+ "cwd": "C:\\git\\bedrock-wrapper",
8346
+ "hook_event_name": "PostToolUse",
8347
+ "tool_name": "Edit",
8348
+ "tool_input": {
8349
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\server.js",
8350
+ "old_string": " // -------------------\n // -- streamed call --\n // -------------------\n for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING })) {",
8351
+ "new_string": " // -------------------\n // -- streamed call --\n // -------------------\n for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING, useConverseAPI: use_converse_api })) {"
8352
+ },
8353
+ "tool_response": {
8354
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\server.js",
8355
+ "oldString": " // -------------------\n // -- streamed call --\n // -------------------\n for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING })) {",
8356
+ "newString": " // -------------------\n // -- streamed call --\n // -------------------\n for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING, useConverseAPI: use_converse_api })) {",
8357
+ "originalFile": "// -------------------------------------------------\n// -- import environment variables from .env file --\n// -------------------------------------------------\nimport dotenv from 'dotenv';\ndotenv.config();\n\n// ------------------------------\n// -- import utility functions --\n// ------------------------------\nimport { toBoolean, extractAWSCreds } from \"./utils.js\";\n\nconst CONSOLE_LOGGING = toBoolean(process.env.CONSOLE_LOGGING);\nconst HTTP_ENABLED = toBoolean(process.env.HTTP_ENABLED);\nconst HTTP_PORT = process.env.HTTP_PORT;\nconst HTTPS_ENABLED = toBoolean(process.env.HTTPS_ENABLED);\nconst HTTPS_PORT = process.env.HTTPS_PORT;\nconst HTTPS_KEY_PATH = process.env.HTTPS_KEY_PATH;\nconst HTTPS_CERT_PATH = process.env.HTTPS_CERT_PATH;\nconst IP_RATE_LIMIT_ENABLED = toBoolean(process.env.IP_RATE_LIMIT_ENABLED);\nconst IP_RATE_LIMIT_WINDOW_MS = parseInt(process.env.IP_RATE_LIMIT_WINDOW_MS);\nconst IP_RATE_LIMIT_MAX_REQUESTS = parseInt(process.env.IP_RATE_LIMIT_MAX_REQUESTS);\nconst MAX_REQUEST_BODY_SIZE = process.env.MAX_REQUEST_BODY_SIZE || '1mb';\n\n// --------------------------------------------\n// -- import functions from bedrock-wrapper --\n// -- - bedrockWrapper --\n// -- - listBedrockWrapperSupportedModels --\n// --------------------------------------------\nimport { \n bedrockWrapper,\n listBedrockWrapperSupportedModels\n} from \"bedrock-wrapper\";\n\nconsole.log(\" ============================ PROXY ENDPOINT =============================\");\nconsole.log(\"\");\n\n// -----------------------------------\n// -- import server and its modules --\n// -----------------------------------\nimport express from 'express';\nimport bodyParser from 'body-parser';\nimport rateLimit from 'express-rate-limit';\nimport { fileURLToPath } from 'url';\nimport https from 'https';\nimport http from 'http';\nimport path from 'path';\nimport fs from 'fs';\nimport { stdout } from 'process';\n\nconst app = express();\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\napp.use(bodyParser.json({ limit: MAX_REQUEST_BODY_SIZE }));\n\n// ------------------------------------\n// -- setup rate limiting middleware --\n// ------------------------------------\nif (IP_RATE_LIMIT_ENABLED) {\n const limiter = rateLimit({\n windowMs: IP_RATE_LIMIT_WINDOW_MS,\n max: IP_RATE_LIMIT_MAX_REQUESTS\n });\n app.use(limiter);\n}\n\n// -------------------------------\n// -- error handling middleware --\n// -------------------------------\napp.use((err, req, res, next) => {\n if (err.code === 'ECONNRESET') {\n console.warn('Connection reset by peer');\n res.status(500).send('Connection reset by peer');\n } else if (err.headersSent) {\n return next(err);\n } else {\n console.error(err.stack);\n res.status(500).send('Something broke!');\n }\n});\n\n\n// -------------------\n// -- Info endpoint --\n// -------------------\napp.get('/', (req, res) => {\n res.sendFile(path.join(__dirname, 'public', 'index.html'));\n});\n\n// -------------------------------------\n// -- Endpoint: list supported models --\n// -------------------------------------\napp.get('/models', (req, res) => {\n listBedrockWrapperSupportedModels().then(supportedModels => {\n res.json(supportedModels);\n }).catch(err => {\n res.status(500).send('Failed to fetch models');\n });\n});\n\napp.post('/test/chat/completions', async (req, res) => {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n const data = {choices: [{delta: {\n content: \"(\u00e3\u0192\u201e) \u00e2\u2020\u2019 Test message from Bedrock Proxy Endpoint\"\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n\n res.end();\n});\n\n// --------------------------------------------------------\n// -- Endpoint: infer AWS Bedrock Proxy Chat Completions --\n// --------------------------------------------------------\napp.post('/chat/completions', async (req, res) => {\n if (CONSOLE_LOGGING) { console.log(\"\\n\\n--new '/chat/completions' request --------------------------------\"); }\n\n // Extract parameters from the incoming request\n const {\n messages = [],\n model = 'Llama-3-8b',\n max_tokens = 800,\n temperature = 0.1,\n top_p = 0.9,\n stream = true,\n include_thinking_data = false,\n use_converse_api = false\n } = req.body;\n\n // validate messages array exists\n if (!messages.length) {\n res.status(400).send('Messages array is empty');\n return;\n }\n\n // extract AWS credentials from the request\n const bearerToken = req.rawHeaders.find(item => item.startsWith(\"Bearer \"));\n const token = bearerToken ? bearerToken.substring(7) : null;\n const tokenParts = extractAWSCreds(token);\n if (tokenParts.error) {\n res.status(401).send(tokenParts.message);\n return;\n } else {\n var { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = tokenParts.credentials;\n }\n \n // validate AWS credentials\n if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {\n res.status(401).send('Unauthorized');\n return;\n }\n\n // ---------------------------------------------------\n // -- create an object to hold your AWS credentials --\n // ---------------------------------------------------\n const awsCreds = {\n region: AWS_REGION,\n accessKeyId: AWS_ACCESS_KEY_ID,\n secretAccessKey: AWS_SECRET_ACCESS_KEY,\n };\n // ----------------------------------------------------------------------\n // -- create an object that copies your openai chat completions object --\n // ----------------------------------------------------------------------\n const openaiChatCompletionsCreateObject = {\n messages: messages,\n model: model,\n max_tokens: max_tokens,\n stream: stream,\n temperature: temperature,\n top_p: top_p,\n include_thinking_data: include_thinking_data,\n use_converse_api: use_converse_api,\n ...(req.body.stop && { stop: req.body.stop }),\n ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })\n };\n\n // set the response headers\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n // create a variable to hold the complete response\n let completeResponse = '';\n\n try {\n // check if the call is streamed\n if (openaiChatCompletionsCreateObject.stream) {\n // -------------------\n // -- streamed call --\n // -------------------\n for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING })) {\n // collect the response chunks\n completeResponse += chunk;\n // create a data object and send to the client\n const data = {choices: [{delta: {\n content: chunk\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n // log the response to the console\n if (CONSOLE_LOGGING) { stdout.write(chunk); }\n }\n res.end();\n } else {\n // ---------------------\n // -- unstreamed call --\n // ---------------------\n const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING });\n for await (const data of response) {\n // collect the response\n completeResponse += data;\n }\n // create a data object and send to the client\n const data = {choices: [{message: {\n content: completeResponse\n }}]};\n res.write(JSON.stringify(data));\n res.end();\n }\n } catch (error) {\n if (error.name === 'ThrottlingException') {\n console.error(\"Error during streaming:\", error);\n if (!res.headersSent) {\n res.status(429).send(\"Too many requests, please wait before trying again.\");\n }\n } else {\n console.error(\"Error during request processing:\", error);\n if (!res.headersSent) {\n res.status(500).send(\"Server error during request processing.\");\n }\n }\n }\n});\n\n\n// ----------------------\n// -- start the server --\n// ----------------------\nif (HTTP_ENABLED) {\n // start the HTTP server\n const httpServer = http.createServer(app);\n httpServer.listen(HTTP_PORT, () => {\n console.log(`HTTP Server listening on port ${HTTP_PORT}`);\n });\n}\nif (HTTPS_ENABLED) {\n // start the HTTPS server\n const httpsServer = https.createServer({\n key: fs.readFileSync(HTTPS_KEY_PATH, 'utf-8'),\n cert: fs.readFileSync(HTTPS_CERT_PATH, 'utf-8')\n }, app);\n httpsServer.listen(HTTPS_PORT, () => {\n console.log(`HTTPS Server listening on port ${HTTPS_PORT}`);\n });\n} \n",
8358
+ "structuredPatch": [
8359
+ {
8360
+ "oldStart": 192,
8361
+ "oldLines": 7,
8362
+ "newStart": 192,
8363
+ "newLines": 7,
8364
+ "lines": [
8365
+ " // -------------------",
8366
+ " // -- streamed call --",
8367
+ " // -------------------",
8368
+ "- for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING })) {",
8369
+ "+ for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING, useConverseAPI: use_converse_api })) {",
8370
+ " // collect the response chunks",
8371
+ " completeResponse += chunk;",
8372
+ " // create a data object and send to the client"
8373
+ ]
8374
+ }
8375
+ ],
8376
+ "userModified": false,
8377
+ "replaceAll": false
8378
+ }
8379
+ },
8380
+ {
8381
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8382
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8383
+ "cwd": "C:\\git\\bedrock-wrapper",
8384
+ "hook_event_name": "PostToolUse",
8385
+ "tool_name": "Edit",
8386
+ "tool_input": {
8387
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\server.js",
8388
+ "old_string": " // ---------------------\n // -- unstreamed call --\n // ---------------------\n const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING });",
8389
+ "new_string": " // ---------------------\n // -- unstreamed call --\n // ---------------------\n const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING, useConverseAPI: use_converse_api });"
8390
+ },
8391
+ "tool_response": {
8392
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\server.js",
8393
+ "oldString": " // ---------------------\n // -- unstreamed call --\n // ---------------------\n const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING });",
8394
+ "newString": " // ---------------------\n // -- unstreamed call --\n // ---------------------\n const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING, useConverseAPI: use_converse_api });",
8395
+ "originalFile": "// -------------------------------------------------\n// -- import environment variables from .env file --\n// -------------------------------------------------\nimport dotenv from 'dotenv';\ndotenv.config();\n\n// ------------------------------\n// -- import utility functions --\n// ------------------------------\nimport { toBoolean, extractAWSCreds } from \"./utils.js\";\n\nconst CONSOLE_LOGGING = toBoolean(process.env.CONSOLE_LOGGING);\nconst HTTP_ENABLED = toBoolean(process.env.HTTP_ENABLED);\nconst HTTP_PORT = process.env.HTTP_PORT;\nconst HTTPS_ENABLED = toBoolean(process.env.HTTPS_ENABLED);\nconst HTTPS_PORT = process.env.HTTPS_PORT;\nconst HTTPS_KEY_PATH = process.env.HTTPS_KEY_PATH;\nconst HTTPS_CERT_PATH = process.env.HTTPS_CERT_PATH;\nconst IP_RATE_LIMIT_ENABLED = toBoolean(process.env.IP_RATE_LIMIT_ENABLED);\nconst IP_RATE_LIMIT_WINDOW_MS = parseInt(process.env.IP_RATE_LIMIT_WINDOW_MS);\nconst IP_RATE_LIMIT_MAX_REQUESTS = parseInt(process.env.IP_RATE_LIMIT_MAX_REQUESTS);\nconst MAX_REQUEST_BODY_SIZE = process.env.MAX_REQUEST_BODY_SIZE || '1mb';\n\n// --------------------------------------------\n// -- import functions from bedrock-wrapper --\n// -- - bedrockWrapper --\n// -- - listBedrockWrapperSupportedModels --\n// --------------------------------------------\nimport { \n bedrockWrapper,\n listBedrockWrapperSupportedModels\n} from \"bedrock-wrapper\";\n\nconsole.log(\" ============================ PROXY ENDPOINT =============================\");\nconsole.log(\"\");\n\n// -----------------------------------\n// -- import server and its modules --\n// -----------------------------------\nimport express from 'express';\nimport bodyParser from 'body-parser';\nimport rateLimit from 'express-rate-limit';\nimport { fileURLToPath } from 'url';\nimport https from 'https';\nimport http from 'http';\nimport path from 'path';\nimport fs from 'fs';\nimport { stdout } from 'process';\n\nconst app = express();\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\napp.use(bodyParser.json({ limit: MAX_REQUEST_BODY_SIZE }));\n\n// ------------------------------------\n// -- setup rate limiting middleware --\n// ------------------------------------\nif (IP_RATE_LIMIT_ENABLED) {\n const limiter = rateLimit({\n windowMs: IP_RATE_LIMIT_WINDOW_MS,\n max: IP_RATE_LIMIT_MAX_REQUESTS\n });\n app.use(limiter);\n}\n\n// -------------------------------\n// -- error handling middleware --\n// -------------------------------\napp.use((err, req, res, next) => {\n if (err.code === 'ECONNRESET') {\n console.warn('Connection reset by peer');\n res.status(500).send('Connection reset by peer');\n } else if (err.headersSent) {\n return next(err);\n } else {\n console.error(err.stack);\n res.status(500).send('Something broke!');\n }\n});\n\n\n// -------------------\n// -- Info endpoint --\n// -------------------\napp.get('/', (req, res) => {\n res.sendFile(path.join(__dirname, 'public', 'index.html'));\n});\n\n// -------------------------------------\n// -- Endpoint: list supported models --\n// -------------------------------------\napp.get('/models', (req, res) => {\n listBedrockWrapperSupportedModels().then(supportedModels => {\n res.json(supportedModels);\n }).catch(err => {\n res.status(500).send('Failed to fetch models');\n });\n});\n\napp.post('/test/chat/completions', async (req, res) => {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n const data = {choices: [{delta: {\n content: \"(\u00e3\u0192\u201e) \u00e2\u2020\u2019 Test message from Bedrock Proxy Endpoint\"\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n\n res.end();\n});\n\n// --------------------------------------------------------\n// -- Endpoint: infer AWS Bedrock Proxy Chat Completions --\n// --------------------------------------------------------\napp.post('/chat/completions', async (req, res) => {\n if (CONSOLE_LOGGING) { console.log(\"\\n\\n--new '/chat/completions' request --------------------------------\"); }\n\n // Extract parameters from the incoming request\n const {\n messages = [],\n model = 'Llama-3-8b',\n max_tokens = 800,\n temperature = 0.1,\n top_p = 0.9,\n stream = true,\n include_thinking_data = false,\n use_converse_api = false\n } = req.body;\n\n // validate messages array exists\n if (!messages.length) {\n res.status(400).send('Messages array is empty');\n return;\n }\n\n // extract AWS credentials from the request\n const bearerToken = req.rawHeaders.find(item => item.startsWith(\"Bearer \"));\n const token = bearerToken ? bearerToken.substring(7) : null;\n const tokenParts = extractAWSCreds(token);\n if (tokenParts.error) {\n res.status(401).send(tokenParts.message);\n return;\n } else {\n var { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = tokenParts.credentials;\n }\n \n // validate AWS credentials\n if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {\n res.status(401).send('Unauthorized');\n return;\n }\n\n // ---------------------------------------------------\n // -- create an object to hold your AWS credentials --\n // ---------------------------------------------------\n const awsCreds = {\n region: AWS_REGION,\n accessKeyId: AWS_ACCESS_KEY_ID,\n secretAccessKey: AWS_SECRET_ACCESS_KEY,\n };\n // ----------------------------------------------------------------------\n // -- create an object that copies your openai chat completions object --\n // ----------------------------------------------------------------------\n const openaiChatCompletionsCreateObject = {\n messages: messages,\n model: model,\n max_tokens: max_tokens,\n stream: stream,\n temperature: temperature,\n top_p: top_p,\n include_thinking_data: include_thinking_data,\n use_converse_api: use_converse_api,\n ...(req.body.stop && { stop: req.body.stop }),\n ...(req.body.stop_sequences && { stop_sequences: req.body.stop_sequences })\n };\n\n // set the response headers\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive'\n });\n\n // create a variable to hold the complete response\n let completeResponse = '';\n\n try {\n // check if the call is streamed\n if (openaiChatCompletionsCreateObject.stream) {\n // -------------------\n // -- streamed call --\n // -------------------\n for await (const chunk of bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING, useConverseAPI: use_converse_api })) {\n // collect the response chunks\n completeResponse += chunk;\n // create a data object and send to the client\n const data = {choices: [{delta: {\n content: chunk\n }}]};\n res.write(`data: ${JSON.stringify(data)}\\n\\n`);\n // log the response to the console\n if (CONSOLE_LOGGING) { stdout.write(chunk); }\n }\n res.end();\n } else {\n // ---------------------\n // -- unstreamed call --\n // ---------------------\n const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING });\n for await (const data of response) {\n // collect the response\n completeResponse += data;\n }\n // create a data object and send to the client\n const data = {choices: [{message: {\n content: completeResponse\n }}]};\n res.write(JSON.stringify(data));\n res.end();\n }\n } catch (error) {\n if (error.name === 'ThrottlingException') {\n console.error(\"Error during streaming:\", error);\n if (!res.headersSent) {\n res.status(429).send(\"Too many requests, please wait before trying again.\");\n }\n } else {\n console.error(\"Error during request processing:\", error);\n if (!res.headersSent) {\n res.status(500).send(\"Server error during request processing.\");\n }\n }\n }\n});\n\n\n// ----------------------\n// -- start the server --\n// ----------------------\nif (HTTP_ENABLED) {\n // start the HTTP server\n const httpServer = http.createServer(app);\n httpServer.listen(HTTP_PORT, () => {\n console.log(`HTTP Server listening on port ${HTTP_PORT}`);\n });\n}\nif (HTTPS_ENABLED) {\n // start the HTTPS server\n const httpsServer = https.createServer({\n key: fs.readFileSync(HTTPS_KEY_PATH, 'utf-8'),\n cert: fs.readFileSync(HTTPS_CERT_PATH, 'utf-8')\n }, app);\n httpsServer.listen(HTTPS_PORT, () => {\n console.log(`HTTPS Server listening on port ${HTTPS_PORT}`);\n });\n} \n",
8396
+ "structuredPatch": [
8397
+ {
8398
+ "oldStart": 208,
8399
+ "oldLines": 7,
8400
+ "newStart": 208,
8401
+ "newLines": 7,
8402
+ "lines": [
8403
+ " // ---------------------",
8404
+ " // -- unstreamed call --",
8405
+ " // ---------------------",
8406
+ "- const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING });",
8407
+ "+ const response = await bedrockWrapper(awsCreds, openaiChatCompletionsCreateObject, { logging: CONSOLE_LOGGING, useConverseAPI: use_converse_api });",
8408
+ " for await (const data of response) {",
8409
+ " // collect the response",
8410
+ " completeResponse += data;"
8411
+ ]
8412
+ }
8413
+ ],
8414
+ "userModified": false,
8415
+ "replaceAll": false
8416
+ }
8417
+ },
8418
+ {
8419
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8420
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8421
+ "cwd": "C:\\git\\bedrock-wrapper",
8422
+ "hook_event_name": "PostToolUse",
8423
+ "tool_name": "TodoWrite",
8424
+ "tool_input": {
8425
+ "todos": [
8426
+ {
8427
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8428
+ "status": "completed",
8429
+ "id": "1"
8430
+ },
8431
+ {
8432
+ "content": "Update README.md to document the new use_converse_api parameter",
8433
+ "status": "in_progress",
8434
+ "id": "2"
8435
+ },
8436
+ {
8437
+ "content": "Update example/example.js to include use_converse_api in the example",
8438
+ "status": "pending",
8439
+ "id": "3"
8440
+ },
8441
+ {
8442
+ "content": "Update package.json version to 2.5.0",
8443
+ "status": "pending",
8444
+ "id": "4"
8445
+ },
8446
+ {
8447
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8448
+ "status": "pending",
8449
+ "id": "5"
8450
+ }
8451
+ ]
8452
+ },
8453
+ "tool_response": {
8454
+ "oldTodos": [
8455
+ {
8456
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8457
+ "status": "in_progress",
8458
+ "id": "1"
8459
+ },
8460
+ {
8461
+ "content": "Update README.md to document the new use_converse_api parameter",
8462
+ "status": "pending",
8463
+ "id": "2"
8464
+ },
8465
+ {
8466
+ "content": "Update example/example.js to include use_converse_api in the example",
8467
+ "status": "pending",
8468
+ "id": "3"
8469
+ },
8470
+ {
8471
+ "content": "Update package.json version to 2.5.0",
8472
+ "status": "pending",
8473
+ "id": "4"
8474
+ },
8475
+ {
8476
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8477
+ "status": "pending",
8478
+ "id": "5"
8479
+ }
8480
+ ],
8481
+ "newTodos": [
8482
+ {
8483
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8484
+ "status": "completed",
8485
+ "id": "1"
8486
+ },
8487
+ {
8488
+ "content": "Update README.md to document the new use_converse_api parameter",
8489
+ "status": "in_progress",
8490
+ "id": "2"
8491
+ },
8492
+ {
8493
+ "content": "Update example/example.js to include use_converse_api in the example",
8494
+ "status": "pending",
8495
+ "id": "3"
8496
+ },
8497
+ {
8498
+ "content": "Update package.json version to 2.5.0",
8499
+ "status": "pending",
8500
+ "id": "4"
8501
+ },
8502
+ {
8503
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8504
+ "status": "pending",
8505
+ "id": "5"
8506
+ }
8507
+ ]
8508
+ }
8509
+ },
8510
+ {
8511
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8512
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8513
+ "cwd": "C:\\git\\bedrock-wrapper",
8514
+ "hook_event_name": "PostToolUse",
8515
+ "tool_name": "Edit",
8516
+ "tool_input": {
8517
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\README.md",
8518
+ "old_string": "- Important values\n - `baseUrl`: Root address of server based on your `.env` configuration.\n - `apiKey`: Descibed in the *Authentication* section above.\n - `messages`: Array of objects in role / content format.\n - `model`: This is the `modelName` from the list of supported models found on the `Bedrock Wrapper` README file [here](https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.\n - `include_thinking_data`: _Optional_ boolean parameter that when set to `true` will include the model's thinking process in the response (only used with thinking models such as `Claude-3-7-Sonnet-Thinking`).\n - `stop` or `stop_sequences`: _Optional_ parameter to specify text sequences that will cause the model to stop generating (e.g., `[\"STOP\", \"END\"]`).",
8519
+ "new_string": "- Important values\n - `baseUrl`: Root address of server based on your `.env` configuration.\n - `apiKey`: Descibed in the *Authentication* section above.\n - `messages`: Array of objects in role / content format.\n - `model`: This is the `modelName` from the list of supported models found on the `Bedrock Wrapper` README file [here](https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.\n - `include_thinking_data`: _Optional_ boolean parameter that when set to `true` will include the model's thinking process in the response (only used with thinking models such as `Claude-3-7-Sonnet-Thinking`).\n - `use_converse_api`: _Optional_ boolean parameter that when set to `true` will use AWS Bedrock's Converse API instead of the Invoke API. The Converse API provides a unified request/response format across all models, better conversation management, and cleaner multimodal handling. Defaults to `false` for backward compatibility.\n - `stop` or `stop_sequences`: _Optional_ parameter to specify text sequences that will cause the model to stop generating (e.g., `[\"STOP\", \"END\"]`)."
8520
+ },
8521
+ "tool_response": {
8522
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\README.md",
8523
+ "oldString": "- Important values\n - `baseUrl`: Root address of server based on your `.env` configuration.\n - `apiKey`: Descibed in the *Authentication* section above.\n - `messages`: Array of objects in role / content format.\n - `model`: This is the `modelName` from the list of supported models found on the `Bedrock Wrapper` README file [here](https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.\n - `include_thinking_data`: _Optional_ boolean parameter that when set to `true` will include the model's thinking process in the response (only used with thinking models such as `Claude-3-7-Sonnet-Thinking`).\n - `stop` or `stop_sequences`: _Optional_ parameter to specify text sequences that will cause the model to stop generating (e.g., `[\"STOP\", \"END\"]`).",
8524
+ "newString": "- Important values\n - `baseUrl`: Root address of server based on your `.env` configuration.\n - `apiKey`: Descibed in the *Authentication* section above.\n - `messages`: Array of objects in role / content format.\n - `model`: This is the `modelName` from the list of supported models found on the `Bedrock Wrapper` README file [here](https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.\n - `include_thinking_data`: _Optional_ boolean parameter that when set to `true` will include the model's thinking process in the response (only used with thinking models such as `Claude-3-7-Sonnet-Thinking`).\n - `use_converse_api`: _Optional_ boolean parameter that when set to `true` will use AWS Bedrock's Converse API instead of the Invoke API. The Converse API provides a unified request/response format across all models, better conversation management, and cleaner multimodal handling. Defaults to `false` for backward compatibility.\n - `stop` or `stop_sequences`: _Optional_ parameter to specify text sequences that will cause the model to stop generating (e.g., `[\"STOP\", \"END\"]`).",
8525
+ "originalFile": "# \u00f0\u0178\u201d\u20ac Bedrock Proxy Endpoint\nSpin up your own custom OpenAI API server endpoint for easy AWS Bedrock LLM text inference (using standard `baseUrl`, and `apiKey` params)\n\n![bedrock-proxy-endpoint](https://raw.githubusercontent.com/jparkerweb/bedrock-proxy-endpoint/refs/heads/main/.readme/bedrock-proxy-endpoint.jpg)\n\n### Maintained by\n<a href=\"https://www.equilllabs.com\">\n <img src=\"https://raw.githubusercontent.com/jparkerweb/eQuill-Labs/refs/heads/main/src/static/images/logo-text-outline.png\" alt=\"eQuill Labs\" height=\"40\">\n</a>\n\n---\n\n### Why Bedrock Proxy Endpoint?\n\nAre you are stuck with using AWS Bedrock for all LLM text inference, but you want to keep your application platform agnostic? Are you tired of figuring out how to format your LLM inference calls to work with the Bedrock SDK? Are you going crazy with all the differences between configuration from model to model?\n\n- `Bedrock Proxy Endpoint` makes it easy to continue using the OpenAI API client that you are use to by standing up your own OpenAI text compatible endpoint that will proxy all your calls to Bedrock in a compatible way.\n\n- Great for getting existing OpenAI API compatible applications working with AWS Bedrock.\n\n\n### Prerequisites\n\nBefore getting started, make sure you have the following installed:\n\n- Node.js (version 12 or higher)\n- npm (Node Package Manager)\n\n### Installation\n\n1. Clone the repository:\n\n ```bash\n git clone https://github.com/jparkerweb/bedrock-proxy-endpoint.git\n ```\n\n2. Navigate to the project directory:\n\n ```bash\n cd bedrock-proxy-endpoint\n ```\n\n3. Install the dependencies:\n\n ```bash\n npm ci\n ```\n\n### Configuration\n\n* Update the `.env` file in the root directory of the project with the following\n environment variables based on your desired configuration:\n\n | key | value type | example | notes |\n |----------------------------|------------|---------------------------|--------------------------------|\n | CONSOLE_LOGGING | boolean | false | Show realtime logs |\n | HTTP_ENABLED | boolean | true | Start a HTTP server |\n | HTTP_PORT | integer | 80 | HTTP server port |\n | MAX_REQUEST_BODY_SIZE | string | 50mb | Maximum size for request body |\n | HTTPS_ENABLED | boolean | false | Start a HTTPS server |\n | HTTPS_PORT | integer | 443 | HTTPS server port |\n | HTTPS_KEY_PATH | string | ./path/mykey.key | Path to key file for HTTPS |\n | HTTPS_CERT_PATH | string | ./path/mycert.pem | Path to cert file for HTTPS |\n | IP_RATE_LIMIT_ENABLED | boolean | true | Enable rate limiting by IP |\n | IP_RATE_LIMIT_WINDOW_MS | integer | 60000 | Window in milliseconds |\n | IP_RATE_LIMIT_MAX_REQUESTS | integer | 100 | Max requests per IP per window |\n\n### Authentication\n\n`Bedrock Proxy` authenticates with AWS via `IAM`. Since the OpenAI API intance accpets an API Key we will utilize this value to hold your credentials. Construct your `apiKey` for inference in the next step following this format:\n\n- `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}`\n- example `apiKey` value: \n `us-west-2.AKIAWSXXXXXXXXXXX.YYYYYYYYYYYYYYYYYYYYYYYYY`\n\n### Usage\n\n- Start the server via: `node server` \n\n <img src=\"docs/console.png\"> \n\n You are now ready to make a standard chat completions to the server.\n\n- Important values\n - `baseUrl`: Root address of server based on your `.env` configuration.\n - `apiKey`: Descibed in the *Authentication* section above.\n - `messages`: Array of objects in role / content format.\n - `model`: This is the `modelName` from the list of supported models found on the `Bedrock Wrapper` README file [here](https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.\n - `include_thinking_data`: _Optional_ boolean parameter that when set to `true` will include the model's thinking process in the response (only used with thinking models such as `Claude-3-7-Sonnet-Thinking`).\n - `stop` or `stop_sequences`: _Optional_ parameter to specify text sequences that will cause the model to stop generating (e.g., `[\"STOP\", \"END\"]`).\n\n### Example OpenAI API Call\nLook at the example folder for complete examples of how to use the server:\n- `example.js` - Basic text completion example\n- `example-vision.js` - Vision model example with image processing (image can be passed as a base64 string or a URL)\n- `example-stop-sequences.js` - Stop sequences example demonstrating how to control where generation stops\n\n```javascript\nimport OpenAI from 'openai';\n\nconst messages = [\n {\n role: \"system\",\n content: \"You are a helpful AI assistant that follows instructions extremely well. Answer the user questions accurately.\",\n },\n {\n role: \"user\",\n content: \"Describe why the OpenAI API standard is so great. Limit your response to five sentences.\",\n },\n {\n role: \"assistant\",\n content: \"\",\n },\n];\n\nconst baseURL = \"http://localhost\"; // URL of the Bedrock Proxy Endpoint\nconst apiKey = `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}` // Your AWS Creds / API Key\n\nconst openai = new OpenAI({\n baseURL: baseURL,\n apiKey: apiKey,\n});\n\nasync function main() {\n try {\n const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-4-Sonnet\",\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: false, // Set to true for thinking models like \"Claude-4-Sonnet-Thinking\"\n });\n\n if (chatCompletion) {\n for await (const chunk of chatCompletion) {\n const response = chunk.choices[0]?.delta?.content || \"\";\n process.stdout.write(response);\n }\n }\n } catch (error) {\n console.error('Error:', error);\n } finally {\n process.exit(0);\n }\n}\n\nmain();\n```\n\n### Root Info Page\n\nPoint your browser to the root of your endpoint server to view the info page: (example: `http://localhost`) \n\n<img src=\"docs/bedrock-proxy-endpoint.png\" style=\"max-width:700px\">\n\n### Note\n\nAlternativly you can incorporate \u00f0\u0178\u00aa\u00a8 <a href=\"https://github.com/jparkerweb/bedrock-wrapper\" target=\"bedrockWrapper\">`Bedrock Wrapper`</a> core directly into your code base. If you would like to explore that option checkout the npm package here: https://www.npmjs.com/package/bedrock-wrapper\n\n---\n\nPlease consider sending me a tip to support my work \u00f0\u0178\u02dc\u20ac\n# [\u00f0\u0178\udc8d\u00b5 tip me here](https://ko-fi.com/jparkerweb)\n",
8526
+ "structuredPatch": [
8527
+ {
8528
+ "oldStart": 87,
8529
+ "oldLines": 6,
8530
+ "newStart": 87,
8531
+ "newLines": 7,
8532
+ "lines": [
8533
+ " - `messages`: Array of objects in role / content format.",
8534
+ " - `model`: This is the `modelName` from the list of supported models found on the `Bedrock Wrapper` README file [here](https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.",
8535
+ " - `include_thinking_data`: _Optional_ boolean parameter that when set to `true` will include the model's thinking process in the response (only used with thinking models such as `Claude-3-7-Sonnet-Thinking`).",
8536
+ "+ - `use_converse_api`: _Optional_ boolean parameter that when set to `true` will use AWS Bedrock's Converse API instead of the Invoke API. The Converse API provides a unified request/response format across all models, better conversation management, and cleaner multimodal handling. Defaults to `false` for backward compatibility.",
8537
+ " - `stop` or `stop_sequences`: _Optional_ parameter to specify text sequences that will cause the model to stop generating (e.g., `[\"STOP\", \"END\"]`).",
8538
+ " ",
8539
+ " ### Example OpenAI API Call"
8540
+ ]
8541
+ }
8542
+ ],
8543
+ "userModified": false,
8544
+ "replaceAll": false
8545
+ }
8546
+ },
8547
+ {
8548
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8549
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8550
+ "cwd": "C:\\git\\bedrock-wrapper",
8551
+ "hook_event_name": "PostToolUse",
8552
+ "tool_name": "Edit",
8553
+ "tool_input": {
8554
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\README.md",
8555
+ "old_string": " const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-4-Sonnet\",\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: false, // Set to true for thinking models like \"Claude-4-Sonnet-Thinking\"\n });",
8556
+ "new_string": " const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-4-Sonnet\",\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: false, // Set to true for thinking models like \"Claude-4-Sonnet-Thinking\"\n use_converse_api: false, // Set to true to use the unified Converse API instead of Invoke API\n });"
8557
+ },
8558
+ "tool_response": {
8559
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\README.md",
8560
+ "oldString": " const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-4-Sonnet\",\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: false, // Set to true for thinking models like \"Claude-4-Sonnet-Thinking\"\n });",
8561
+ "newString": " const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-4-Sonnet\",\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: false, // Set to true for thinking models like \"Claude-4-Sonnet-Thinking\"\n use_converse_api: false, // Set to true to use the unified Converse API instead of Invoke API\n });",
8562
+ "originalFile": "# \u00f0\u0178\u201d\u20ac Bedrock Proxy Endpoint\nSpin up your own custom OpenAI API server endpoint for easy AWS Bedrock LLM text inference (using standard `baseUrl`, and `apiKey` params)\n\n![bedrock-proxy-endpoint](https://raw.githubusercontent.com/jparkerweb/bedrock-proxy-endpoint/refs/heads/main/.readme/bedrock-proxy-endpoint.jpg)\n\n### Maintained by\n<a href=\"https://www.equilllabs.com\">\n <img src=\"https://raw.githubusercontent.com/jparkerweb/eQuill-Labs/refs/heads/main/src/static/images/logo-text-outline.png\" alt=\"eQuill Labs\" height=\"40\">\n</a>\n\n---\n\n### Why Bedrock Proxy Endpoint?\n\nAre you are stuck with using AWS Bedrock for all LLM text inference, but you want to keep your application platform agnostic? Are you tired of figuring out how to format your LLM inference calls to work with the Bedrock SDK? Are you going crazy with all the differences between configuration from model to model?\n\n- `Bedrock Proxy Endpoint` makes it easy to continue using the OpenAI API client that you are use to by standing up your own OpenAI text compatible endpoint that will proxy all your calls to Bedrock in a compatible way.\n\n- Great for getting existing OpenAI API compatible applications working with AWS Bedrock.\n\n\n### Prerequisites\n\nBefore getting started, make sure you have the following installed:\n\n- Node.js (version 12 or higher)\n- npm (Node Package Manager)\n\n### Installation\n\n1. Clone the repository:\n\n ```bash\n git clone https://github.com/jparkerweb/bedrock-proxy-endpoint.git\n ```\n\n2. Navigate to the project directory:\n\n ```bash\n cd bedrock-proxy-endpoint\n ```\n\n3. Install the dependencies:\n\n ```bash\n npm ci\n ```\n\n### Configuration\n\n* Update the `.env` file in the root directory of the project with the following\n environment variables based on your desired configuration:\n\n | key | value type | example | notes |\n |----------------------------|------------|---------------------------|--------------------------------|\n | CONSOLE_LOGGING | boolean | false | Show realtime logs |\n | HTTP_ENABLED | boolean | true | Start a HTTP server |\n | HTTP_PORT | integer | 80 | HTTP server port |\n | MAX_REQUEST_BODY_SIZE | string | 50mb | Maximum size for request body |\n | HTTPS_ENABLED | boolean | false | Start a HTTPS server |\n | HTTPS_PORT | integer | 443 | HTTPS server port |\n | HTTPS_KEY_PATH | string | ./path/mykey.key | Path to key file for HTTPS |\n | HTTPS_CERT_PATH | string | ./path/mycert.pem | Path to cert file for HTTPS |\n | IP_RATE_LIMIT_ENABLED | boolean | true | Enable rate limiting by IP |\n | IP_RATE_LIMIT_WINDOW_MS | integer | 60000 | Window in milliseconds |\n | IP_RATE_LIMIT_MAX_REQUESTS | integer | 100 | Max requests per IP per window |\n\n### Authentication\n\n`Bedrock Proxy` authenticates with AWS via `IAM`. Since the OpenAI API intance accpets an API Key we will utilize this value to hold your credentials. Construct your `apiKey` for inference in the next step following this format:\n\n- `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}`\n- example `apiKey` value: \n `us-west-2.AKIAWSXXXXXXXXXXX.YYYYYYYYYYYYYYYYYYYYYYYYY`\n\n### Usage\n\n- Start the server via: `node server` \n\n <img src=\"docs/console.png\"> \n\n You are now ready to make a standard chat completions to the server.\n\n- Important values\n - `baseUrl`: Root address of server based on your `.env` configuration.\n - `apiKey`: Descibed in the *Authentication* section above.\n - `messages`: Array of objects in role / content format.\n - `model`: This is the `modelName` from the list of supported models found on the `Bedrock Wrapper` README file [here](https://github.com/jparkerweb/bedrock-wrapper?tab=readme-ov-file#supported-models); The `/models` enpoint of this server will also return a list of supported models.\n - `include_thinking_data`: _Optional_ boolean parameter that when set to `true` will include the model's thinking process in the response (only used with thinking models such as `Claude-3-7-Sonnet-Thinking`).\n - `use_converse_api`: _Optional_ boolean parameter that when set to `true` will use AWS Bedrock's Converse API instead of the Invoke API. The Converse API provides a unified request/response format across all models, better conversation management, and cleaner multimodal handling. Defaults to `false` for backward compatibility.\n - `stop` or `stop_sequences`: _Optional_ parameter to specify text sequences that will cause the model to stop generating (e.g., `[\"STOP\", \"END\"]`).\n\n### Example OpenAI API Call\nLook at the example folder for complete examples of how to use the server:\n- `example.js` - Basic text completion example\n- `example-vision.js` - Vision model example with image processing (image can be passed as a base64 string or a URL)\n- `example-stop-sequences.js` - Stop sequences example demonstrating how to control where generation stops\n\n```javascript\nimport OpenAI from 'openai';\n\nconst messages = [\n {\n role: \"system\",\n content: \"You are a helpful AI assistant that follows instructions extremely well. Answer the user questions accurately.\",\n },\n {\n role: \"user\",\n content: \"Describe why the OpenAI API standard is so great. Limit your response to five sentences.\",\n },\n {\n role: \"assistant\",\n content: \"\",\n },\n];\n\nconst baseURL = \"http://localhost\"; // URL of the Bedrock Proxy Endpoint\nconst apiKey = `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}` // Your AWS Creds / API Key\n\nconst openai = new OpenAI({\n baseURL: baseURL,\n apiKey: apiKey,\n});\n\nasync function main() {\n try {\n const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-4-Sonnet\",\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: false, // Set to true for thinking models like \"Claude-4-Sonnet-Thinking\"\n });\n\n if (chatCompletion) {\n for await (const chunk of chatCompletion) {\n const response = chunk.choices[0]?.delta?.content || \"\";\n process.stdout.write(response);\n }\n }\n } catch (error) {\n console.error('Error:', error);\n } finally {\n process.exit(0);\n }\n}\n\nmain();\n```\n\n### Root Info Page\n\nPoint your browser to the root of your endpoint server to view the info page: (example: `http://localhost`) \n\n<img src=\"docs/bedrock-proxy-endpoint.png\" style=\"max-width:700px\">\n\n### Note\n\nAlternativly you can incorporate \u00f0\u0178\u00aa\u00a8 <a href=\"https://github.com/jparkerweb/bedrock-wrapper\" target=\"bedrockWrapper\">`Bedrock Wrapper`</a> core directly into your code base. If you would like to explore that option checkout the npm package here: https://www.npmjs.com/package/bedrock-wrapper\n\n---\n\nPlease consider sending me a tip to support my work \u00f0\u0178\u02dc\u20ac\n# [\u00f0\u0178\udc8d\u00b5 tip me here](https://ko-fi.com/jparkerweb)\n",
8563
+ "structuredPatch": [
8564
+ {
8565
+ "oldStart": 132,
8566
+ "oldLines": 6,
8567
+ "newStart": 132,
8568
+ "newLines": 7,
8569
+ "lines": [
8570
+ " top_p: 0.7,",
8571
+ " stream: true,",
8572
+ " include_thinking_data: false, // Set to true for thinking models like \"Claude-4-Sonnet-Thinking\"",
8573
+ "+ use_converse_api: false, // Set to true to use the unified Converse API instead of Invoke API",
8574
+ " });",
8575
+ " ",
8576
+ " if (chatCompletion) {"
8577
+ ]
8578
+ }
8579
+ ],
8580
+ "userModified": false,
8581
+ "replaceAll": false
8582
+ }
8583
+ },
8584
+ {
8585
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8586
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8587
+ "cwd": "C:\\git\\bedrock-wrapper",
8588
+ "hook_event_name": "PostToolUse",
8589
+ "tool_name": "TodoWrite",
8590
+ "tool_input": {
8591
+ "todos": [
8592
+ {
8593
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8594
+ "status": "completed",
8595
+ "id": "1"
8596
+ },
8597
+ {
8598
+ "content": "Update README.md to document the new use_converse_api parameter",
8599
+ "status": "completed",
8600
+ "id": "2"
8601
+ },
8602
+ {
8603
+ "content": "Update example/example.js to include use_converse_api in the example",
8604
+ "status": "in_progress",
8605
+ "id": "3"
8606
+ },
8607
+ {
8608
+ "content": "Update package.json version to 2.5.0",
8609
+ "status": "pending",
8610
+ "id": "4"
8611
+ },
8612
+ {
8613
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8614
+ "status": "pending",
8615
+ "id": "5"
8616
+ }
8617
+ ]
8618
+ },
8619
+ "tool_response": {
8620
+ "oldTodos": [
8621
+ {
8622
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8623
+ "status": "completed",
8624
+ "id": "1"
8625
+ },
8626
+ {
8627
+ "content": "Update README.md to document the new use_converse_api parameter",
8628
+ "status": "in_progress",
8629
+ "id": "2"
8630
+ },
8631
+ {
8632
+ "content": "Update example/example.js to include use_converse_api in the example",
8633
+ "status": "pending",
8634
+ "id": "3"
8635
+ },
8636
+ {
8637
+ "content": "Update package.json version to 2.5.0",
8638
+ "status": "pending",
8639
+ "id": "4"
8640
+ },
8641
+ {
8642
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8643
+ "status": "pending",
8644
+ "id": "5"
8645
+ }
8646
+ ],
8647
+ "newTodos": [
8648
+ {
8649
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8650
+ "status": "completed",
8651
+ "id": "1"
8652
+ },
8653
+ {
8654
+ "content": "Update README.md to document the new use_converse_api parameter",
8655
+ "status": "completed",
8656
+ "id": "2"
8657
+ },
8658
+ {
8659
+ "content": "Update example/example.js to include use_converse_api in the example",
8660
+ "status": "in_progress",
8661
+ "id": "3"
8662
+ },
8663
+ {
8664
+ "content": "Update package.json version to 2.5.0",
8665
+ "status": "pending",
8666
+ "id": "4"
8667
+ },
8668
+ {
8669
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8670
+ "status": "pending",
8671
+ "id": "5"
8672
+ }
8673
+ ]
8674
+ }
8675
+ },
8676
+ {
8677
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8678
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8679
+ "cwd": "C:\\git\\bedrock-wrapper",
8680
+ "hook_event_name": "PostToolUse",
8681
+ "tool_name": "Edit",
8682
+ "tool_input": {
8683
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\example\\example.js",
8684
+ "old_string": " const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-3-7-Sonnet-Thinking\", // Try: \"Claude-4-Sonnet\", \"Claude-4-Opus\", \"Claude-4-Sonnet-Thinking\", \"Claude-4-Opus-Thinking\"\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: true, // Works with thinking models\n });",
8685
+ "new_string": " const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-3-7-Sonnet-Thinking\", // Try: \"Claude-4-Sonnet\", \"Claude-4-Opus\", \"Claude-4-Sonnet-Thinking\", \"Claude-4-Opus-Thinking\"\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: true, // Works with thinking models\n use_converse_api: false, // Set to true to use the unified Converse API (better consistency across models)\n });"
8686
+ },
8687
+ "tool_response": {
8688
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\example\\example.js",
8689
+ "oldString": " const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-3-7-Sonnet-Thinking\", // Try: \"Claude-4-Sonnet\", \"Claude-4-Opus\", \"Claude-4-Sonnet-Thinking\", \"Claude-4-Opus-Thinking\"\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: true, // Works with thinking models\n });",
8690
+ "newString": " const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-3-7-Sonnet-Thinking\", // Try: \"Claude-4-Sonnet\", \"Claude-4-Opus\", \"Claude-4-Sonnet-Thinking\", \"Claude-4-Opus-Thinking\"\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: true, // Works with thinking models\n use_converse_api: false, // Set to true to use the unified Converse API (better consistency across models)\n });",
8691
+ "originalFile": "import OpenAI from 'openai';\nimport dotenv from 'dotenv';\n\ndotenv.config();\nconst { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY } = process.env;\n\nconst messages = [\n {\n role: \"system\",\n content: \"You are a helpful AI assistant that follows instructions extremely well. Answer the user questions accurately.\",\n },\n {\n role: \"user\",\n content: \"Describe why the OpenAI API standard is so great. Limit your response to five sentences.\",\n },\n {\n role: \"assistant\",\n content: \"\",\n },\n];\n\nconst baseURL = \"http://localhost:88\"; // URL of the Bedrock Proxy Endpoint\nconst apiKey = `${AWS_REGION}.${AWS_ACCESS_KEY_ID}.${AWS_SECRET_ACCESS_KEY}` // Your AWS Creds / API Key\n\nconst openai = new OpenAI({\n baseURL: baseURL,\n apiKey: apiKey,\n});\n\nasync function main() {\n try {\n const chatCompletion = await openai.chat.completions.create({\n messages: messages,\n model: \"Claude-3-7-Sonnet-Thinking\", // Try: \"Claude-4-Sonnet\", \"Claude-4-Opus\", \"Claude-4-Sonnet-Thinking\", \"Claude-4-Opus-Thinking\"\n max_tokens: 2048,\n temperature: 0.4,\n top_p: 0.7,\n stream: true,\n include_thinking_data: true, // Works with thinking models\n });\n\n if (chatCompletion) {\n for await (const chunk of chatCompletion) {\n const response = chunk.choices[0]?.delta?.content || \"\";\n process.stdout.write(response);\n }\n // Add a newline at the end for cleaner output\n process.stdout.write('\\n');\n }\n } catch (error) {\n console.error('Error:', error);\n } finally {\n // Explicitly exit the process when done\n process.exit(0);\n }\n}\n\nmain();",
8692
+ "structuredPatch": [
8693
+ {
8694
+ "oldStart": 37,
8695
+ "oldLines": 6,
8696
+ "newStart": 37,
8697
+ "newLines": 7,
8698
+ "lines": [
8699
+ " top_p: 0.7,",
8700
+ " stream: true,",
8701
+ " include_thinking_data: true, // Works with thinking models",
8702
+ "+ use_converse_api: false, // Set to true to use the unified Converse API (better consistency across models)",
8703
+ " });",
8704
+ " ",
8705
+ " if (chatCompletion) {"
8706
+ ]
8707
+ }
8708
+ ],
8709
+ "userModified": false,
8710
+ "replaceAll": false
8711
+ }
8712
+ },
8713
+ {
8714
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8715
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8716
+ "cwd": "C:\\git\\bedrock-wrapper",
8717
+ "hook_event_name": "PostToolUse",
8718
+ "tool_name": "TodoWrite",
8719
+ "tool_input": {
8720
+ "todos": [
8721
+ {
8722
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8723
+ "status": "completed",
8724
+ "id": "1"
8725
+ },
8726
+ {
8727
+ "content": "Update README.md to document the new use_converse_api parameter",
8728
+ "status": "completed",
8729
+ "id": "2"
8730
+ },
8731
+ {
8732
+ "content": "Update example/example.js to include use_converse_api in the example",
8733
+ "status": "completed",
8734
+ "id": "3"
8735
+ },
8736
+ {
8737
+ "content": "Update package.json version to 2.5.0",
8738
+ "status": "in_progress",
8739
+ "id": "4"
8740
+ },
8741
+ {
8742
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8743
+ "status": "pending",
8744
+ "id": "5"
8745
+ }
8746
+ ]
8747
+ },
8748
+ "tool_response": {
8749
+ "oldTodos": [
8750
+ {
8751
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8752
+ "status": "completed",
8753
+ "id": "1"
8754
+ },
8755
+ {
8756
+ "content": "Update README.md to document the new use_converse_api parameter",
8757
+ "status": "completed",
8758
+ "id": "2"
8759
+ },
8760
+ {
8761
+ "content": "Update example/example.js to include use_converse_api in the example",
8762
+ "status": "in_progress",
8763
+ "id": "3"
8764
+ },
8765
+ {
8766
+ "content": "Update package.json version to 2.5.0",
8767
+ "status": "pending",
8768
+ "id": "4"
8769
+ },
8770
+ {
8771
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8772
+ "status": "pending",
8773
+ "id": "5"
8774
+ }
8775
+ ],
8776
+ "newTodos": [
8777
+ {
8778
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8779
+ "status": "completed",
8780
+ "id": "1"
8781
+ },
8782
+ {
8783
+ "content": "Update README.md to document the new use_converse_api parameter",
8784
+ "status": "completed",
8785
+ "id": "2"
8786
+ },
8787
+ {
8788
+ "content": "Update example/example.js to include use_converse_api in the example",
8789
+ "status": "completed",
8790
+ "id": "3"
8791
+ },
8792
+ {
8793
+ "content": "Update package.json version to 2.5.0",
8794
+ "status": "in_progress",
8795
+ "id": "4"
8796
+ },
8797
+ {
8798
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8799
+ "status": "pending",
8800
+ "id": "5"
8801
+ }
8802
+ ]
8803
+ }
8804
+ },
8805
+ {
8806
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8807
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8808
+ "cwd": "C:\\git\\bedrock-wrapper",
8809
+ "hook_event_name": "PostToolUse",
8810
+ "tool_name": "Edit",
8811
+ "tool_input": {
8812
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\package.json",
8813
+ "old_string": " \"version\": \"2.4.5\",",
8814
+ "new_string": " \"version\": \"2.5.0\","
8815
+ },
8816
+ "tool_response": {
8817
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\package.json",
8818
+ "oldString": " \"version\": \"2.4.5\",",
8819
+ "newString": " \"version\": \"2.5.0\",",
8820
+ "originalFile": "{\n \"name\": \"bedrock-proxy-endpoint\",\n \"version\": \"2.4.5\",\n \"description\": \"\u00f0\u0178\u201d\u20ac Bedrock Proxy Endpoint \u00e2\u2021\u00a2 Spin up your own custom OpenAI API server endpoint for easy AWS Bedrock inference (using standard `baseUrl`, and `apiKey` params)\",\n \"main\": \"server.js\",\n \"type\": \"module\",\n \"scripts\": {\n \"clean\": \"npx rimraf node_modules && npx rimraf package-lock.json && npm install\",\n \"server\": \"node --no-deprecation server.js\",\n \"start\": \"node --no-deprecation server.js\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\",\n \"test:watch\": \"vitest --watch\",\n \"test:coverage\": \"vitest run --coverage\",\n \"test:ui\": \"vitest --ui\",\n \"prepare\": \"husky\"\n },\n \"keywords\": [\n \"openai\",\n \"bedrock\",\n \"aws\",\n \"proxy\",\n \"wrapper\",\n \"serverless\",\n \"inference\",\n \"llm\"\n ],\n \"author\": \"\",\n \"license\": \"ISC\",\n \"dependencies\": {\n \"bedrock-wrapper\": \"^2.5.0\",\n \"body-parser\": \"^1.20.3\",\n \"dotenv\": \"^17.2.1\",\n \"express\": \"^4.21.2\",\n \"express-rate-limit\": \"^7.5.1\"\n },\n \"devDependencies\": {\n \"@vitest/coverage-v8\": \"^3.2.4\",\n \"@vitest/ui\": \"^3.2.4\",\n \"husky\": \"^9.1.7\",\n \"supertest\": \"^7.1.4\",\n \"vitest\": \"^3.2.4\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git@github.com-jparkerweb:jparkerweb/bedrock-proxy-endpoint.git\"\n }\n}\n",
8821
+ "structuredPatch": [
8822
+ {
8823
+ "oldStart": 1,
8824
+ "oldLines": 6,
8825
+ "newStart": 1,
8826
+ "newLines": 6,
8827
+ "lines": [
8828
+ " {",
8829
+ " \"name\": \"bedrock-proxy-endpoint\",",
8830
+ "- \"version\": \"2.4.5\",",
8831
+ "+ \"version\": \"2.5.0\",",
8832
+ " \"description\": \"\u00f0\u0178\u201d\u20ac Bedrock Proxy Endpoint \u00e2\u2021\u00a2 Spin up your own custom OpenAI API server endpoint for easy AWS Bedrock inference (using standard `baseUrl`, and `apiKey` params)\",",
8833
+ " \"main\": \"server.js\",",
8834
+ " \"type\": \"module\","
8835
+ ]
8836
+ }
8837
+ ],
8838
+ "userModified": false,
8839
+ "replaceAll": false
8840
+ }
8841
+ },
8842
+ {
8843
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8844
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8845
+ "cwd": "C:\\git\\bedrock-wrapper",
8846
+ "hook_event_name": "PostToolUse",
8847
+ "tool_name": "TodoWrite",
8848
+ "tool_input": {
8849
+ "todos": [
8850
+ {
8851
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8852
+ "status": "completed",
8853
+ "id": "1"
8854
+ },
8855
+ {
8856
+ "content": "Update README.md to document the new use_converse_api parameter",
8857
+ "status": "completed",
8858
+ "id": "2"
8859
+ },
8860
+ {
8861
+ "content": "Update example/example.js to include use_converse_api in the example",
8862
+ "status": "completed",
8863
+ "id": "3"
8864
+ },
8865
+ {
8866
+ "content": "Update package.json version to 2.5.0",
8867
+ "status": "completed",
8868
+ "id": "4"
8869
+ },
8870
+ {
8871
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8872
+ "status": "in_progress",
8873
+ "id": "5"
8874
+ }
8875
+ ]
8876
+ },
8877
+ "tool_response": {
8878
+ "oldTodos": [
8879
+ {
8880
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8881
+ "status": "completed",
8882
+ "id": "1"
8883
+ },
8884
+ {
8885
+ "content": "Update README.md to document the new use_converse_api parameter",
8886
+ "status": "completed",
8887
+ "id": "2"
8888
+ },
8889
+ {
8890
+ "content": "Update example/example.js to include use_converse_api in the example",
8891
+ "status": "completed",
8892
+ "id": "3"
8893
+ },
8894
+ {
8895
+ "content": "Update package.json version to 2.5.0",
8896
+ "status": "in_progress",
8897
+ "id": "4"
8898
+ },
8899
+ {
8900
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8901
+ "status": "pending",
8902
+ "id": "5"
8903
+ }
8904
+ ],
8905
+ "newTodos": [
8906
+ {
8907
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
8908
+ "status": "completed",
8909
+ "id": "1"
8910
+ },
8911
+ {
8912
+ "content": "Update README.md to document the new use_converse_api parameter",
8913
+ "status": "completed",
8914
+ "id": "2"
8915
+ },
8916
+ {
8917
+ "content": "Update example/example.js to include use_converse_api in the example",
8918
+ "status": "completed",
8919
+ "id": "3"
8920
+ },
8921
+ {
8922
+ "content": "Update package.json version to 2.5.0",
8923
+ "status": "completed",
8924
+ "id": "4"
8925
+ },
8926
+ {
8927
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
8928
+ "status": "in_progress",
8929
+ "id": "5"
8930
+ }
8931
+ ]
8932
+ }
8933
+ },
8934
+ {
8935
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8936
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8937
+ "cwd": "C:\\git\\bedrock-wrapper",
8938
+ "hook_event_name": "PostToolUse",
8939
+ "tool_name": "Edit",
8940
+ "tool_input": {
8941
+ "file_path": "C:\\git\\bedrock-proxy-endpoint\\CHANGELOG.md",
8942
+ "old_string": "# Changelog\nAll notable changes to this project will be documented in this file.\n\n## [2.4.5] - 2025-08-06",
8943
+ "new_string": "# Changelog\nAll notable changes to this project will be documented in this file.\n\n## [2.5.0] - 2025-08-12\n### Added\n- Updated to use Bedrock Wrapper v2.5.0\n- Support for AWS Bedrock Converse API via `use_converse_api` parameter\n - Optional boolean parameter that defaults to `false` for backward compatibility\n - When set to `true`, uses the unified Converse API instead of Invoke API\n - Provides consistent request/response format across all model families\n - Simplifies conversation management and multimodal handling\n - Better support for system prompts and tool use (where applicable)\n- Converse API benefits include:\n - Unified API format across Claude, Nova, GPT-OSS, Llama, and Mistral models\n - Cleaner handling of thinking models with proper `reasoningContent` extraction\n - Simplified message format without model-specific prompt construction\n - Native support for system prompts as a separate field\n\n### Technical Details\n- The `use_converse_api` parameter follows the same pattern as `include_thinking_data`\n- Passes through to bedrock-wrapper's `useConverseAPI` option\n- Works with both streaming and non-streaming responses\n- Maintains full backward compatibility when not specified or set to `false`\n\n## [2.4.5] - 2025-08-06"
8944
+ },
8945
+ "tool_response": {
8946
+ "filePath": "C:\\git\\bedrock-proxy-endpoint\\CHANGELOG.md",
8947
+ "oldString": "# Changelog\nAll notable changes to this project will be documented in this file.\n\n## [2.4.5] - 2025-08-06",
8948
+ "newString": "# Changelog\nAll notable changes to this project will be documented in this file.\n\n## [2.5.0] - 2025-08-12\n### Added\n- Updated to use Bedrock Wrapper v2.5.0\n- Support for AWS Bedrock Converse API via `use_converse_api` parameter\n - Optional boolean parameter that defaults to `false` for backward compatibility\n - When set to `true`, uses the unified Converse API instead of Invoke API\n - Provides consistent request/response format across all model families\n - Simplifies conversation management and multimodal handling\n - Better support for system prompts and tool use (where applicable)\n- Converse API benefits include:\n - Unified API format across Claude, Nova, GPT-OSS, Llama, and Mistral models\n - Cleaner handling of thinking models with proper `reasoningContent` extraction\n - Simplified message format without model-specific prompt construction\n - Native support for system prompts as a separate field\n\n### Technical Details\n- The `use_converse_api` parameter follows the same pattern as `include_thinking_data`\n- Passes through to bedrock-wrapper's `useConverseAPI` option\n- Works with both streaming and non-streaming responses\n- Maintains full backward compatibility when not specified or set to `false`\n\n## [2.4.5] - 2025-08-06",
8949
+ "originalFile": "# Changelog\nAll notable changes to this project will be documented in this file.\n\n## [2.4.5] - 2025-08-06\n### Added\n- Updated to use Bedrock Wrapper v2.4.5\n- Support for OpenAI GPT-OSS models on AWS Bedrock\n - GPT-OSS-120B (120B parameter open weight model)\n - GPT-OSS-20B (20B parameter open weight model)\n - GPT-OSS-120B-Thinking (with reasoning tag preservation)\n - GPT-OSS-20B-Thinking (with reasoning tag preservation)\n- `<reasoning>` tag processing for GPT-OSS thinking variants\n - Regular GPT-OSS models automatically strip `<reasoning>` tags\n - Thinking variants preserve `<reasoning>` tags (similar to Claude's `<think>` tags)\n\n## [2.4.4] - 2025-08-05\n### Added\n- Updated to use Bedrock Wrapper v2.4.4\n- Support for Claude Opus 4.1 models:\n - Claude-4-1-Opus (with image support)\n - Claude-4-1-Opus-Thinking (with image support)\n\n## [2.4.3] - 2025-07-31\n### Added\n- Updated to use Bedrock Wrapper v2.4.3\n- Refined stop sequences support with model-specific limitations:\n - Claude models: Full support (up to 8,191 sequences)\n - Nova models: Full support (up to 4 sequences) \n - Mistral models: Full support (up to 10 sequences)\n - Llama models: No stop sequences support (AWS Bedrock limitation)\n- Improved error handling for early response termination\n- Fixed Nova model configuration conflicts\n\n## [2.4.2] - 2025-07-31\n### Added\n- Updated to use Bedrock Wrapper v2.4.2\n- Support for Claude 4 models:\n - Claude-4-Opus (with image support)\n - Claude-4-Opus-Thinking (with image support)\n - Claude-4-Sonnet (with image support) \n - Claude-4-Sonnet-Thinking (with image support)\n- Stop sequences support (`stop_sequences` parameter)\n- Compatible with OpenAI's `stop` parameter for controlling generation stopping points\n\n## [2.4.1] - 2025-07-24\n### Added\n- Updated to use Bedrock Wrapper v2.4.1\\\n- Vision support for Claude 3 Haiku\n- Support for Amazon Nova models:\n - Amazon Nova Micro (text-only, ultra-low latency)\n - Amazon Nova Lite (multimodal, low-cost)\n - Amazon Nova Pro (multimodal, high capability)\n\n## [2.3.1] - 2025-05-28\n### Added\n- Updated to use Bedrock Wrapper v2.3.1\n - Support for Claude Sonnet 4\n - Support for Claude Opus 4\n\n## [2.3.0] - 2025-02-27 - Claude Sonnet 3.7 + Vision\n### Added\n- Support for Claude Sonnet 3.7\n- Support for Clause Sonnet 3.7 Thinking\n- Support for Claude Sonnet 3.x Vision\n\n## [2.2.0] - 2025-01-01 - Llama 3.3 70b\n### Added\n- Support for Llama 3.3 70b\n\n## [2.1.0] - 2024-11-21 - Claude Haiku 3.5\n### Added\n- Support for \"Anthropic Claude 3.5 Haiku\"\n\n## [2.0.0] - 2024-10-31 - Claude\n### Added\n- Updated to use Bedrock Wrapper v2.0.0\n- Model support for:\n - Claude 3.5 Sonnet V2\n - Claude 3.5 Sonnet\n - Claude 3 Haiku\n- Unstreamed response are returned as a string similar to streaming responses\n > Note: This could be a breaking change for any clients that are expecting a JSON response from unstreamed responses\n\n## [1.0.9] - 2024-09-25 - Lamma 3.2\n### Added\n- Model support for:\n - Llama 3.2 1b\n - Llama 3.2 3b\n - Llama 3.2 11b\n - Llama 3.2 90b\n\n\n## [1.0.7] - 2024-07-24 - Lamma 3.1\n### Added\n- Model support for:\n - Llama-3-1-8b\n - Llama-3-1-70b\n\n\n## [1.0.3] - 2024-05-06 - Initial Stable Release\n### Added\n- OpenAI API compatible proxy endpoint for AWS Bedrock\n- Support for HTTP and HTTPS servers\n- IP-based rate limiting\n- Environment variable configuration\n- AWS IAM authentication via API key\n- Streaming and non-streaming responses\n- `/models` endpoint to list supported models\n- Root info page with documentation\n- Endpoint type\n - `/chat/completions`\n- Model Support for:\n - Llama-3-8b\n - Llama-3-70b\n - Mistral-7b\n - Mixtral-8x7b\n - Mistral-Large\n- Error handling middleware\n- Console logging toggle\n\n### Security\n- HTTPS support with custom key and certificate paths\n- Rate limiting configuration options\n- AWS IAM authentication required for API access\n\n### Documentation\n- Installation instructions\n- Configuration guide\n- Authentication details\n- Usage examples\n- API endpoint documentation \n",
8950
+ "structuredPatch": [
8951
+ {
8952
+ "oldStart": 1,
8953
+ "oldLines": 6,
8954
+ "newStart": 1,
8955
+ "newLines": 27,
8956
+ "lines": [
8957
+ " # Changelog",
8958
+ " All notable changes to this project will be documented in this file.",
8959
+ " ",
8960
+ "+## [2.5.0] - 2025-08-12",
8961
+ "+### Added",
8962
+ "+- Updated to use Bedrock Wrapper v2.5.0",
8963
+ "+- Support for AWS Bedrock Converse API via `use_converse_api` parameter",
8964
+ "+ - Optional boolean parameter that defaults to `false` for backward compatibility",
8965
+ "+ - When set to `true`, uses the unified Converse API instead of Invoke API",
8966
+ "+ - Provides consistent request/response format across all model families",
8967
+ "+ - Simplifies conversation management and multimodal handling",
8968
+ "+ - Better support for system prompts and tool use (where applicable)",
8969
+ "+- Converse API benefits include:",
8970
+ "+ - Unified API format across Claude, Nova, GPT-OSS, Llama, and Mistral models",
8971
+ "+ - Cleaner handling of thinking models with proper `reasoningContent` extraction",
8972
+ "+ - Simplified message format without model-specific prompt construction",
8973
+ "+ - Native support for system prompts as a separate field",
8974
+ "+",
8975
+ "+### Technical Details",
8976
+ "+- The `use_converse_api` parameter follows the same pattern as `include_thinking_data`",
8977
+ "+- Passes through to bedrock-wrapper's `useConverseAPI` option",
8978
+ "+- Works with both streaming and non-streaming responses",
8979
+ "+- Maintains full backward compatibility when not specified or set to `false`",
8980
+ "+",
8981
+ " ## [2.4.5] - 2025-08-06",
8982
+ " ### Added",
8983
+ " - Updated to use Bedrock Wrapper v2.4.5"
8984
+ ]
8985
+ }
8986
+ ],
8987
+ "userModified": false,
8988
+ "replaceAll": false
8989
+ }
8990
+ },
8991
+ {
8992
+ "session_id": "e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3",
8993
+ "transcript_path": "C:\\Users\\Justin.Parker\\.claude\\projects\\C--git-bedrock-wrapper\\e4cf59ef-9d22-45bf-9c6c-53e3cb9efda3.jsonl",
8994
+ "cwd": "C:\\git\\bedrock-wrapper",
8995
+ "hook_event_name": "PostToolUse",
8996
+ "tool_name": "TodoWrite",
8997
+ "tool_input": {
8998
+ "todos": [
8999
+ {
9000
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
9001
+ "status": "completed",
9002
+ "id": "1"
9003
+ },
9004
+ {
9005
+ "content": "Update README.md to document the new use_converse_api parameter",
9006
+ "status": "completed",
9007
+ "id": "2"
9008
+ },
9009
+ {
9010
+ "content": "Update example/example.js to include use_converse_api in the example",
9011
+ "status": "completed",
9012
+ "id": "3"
9013
+ },
9014
+ {
9015
+ "content": "Update package.json version to 2.5.0",
9016
+ "status": "completed",
9017
+ "id": "4"
9018
+ },
9019
+ {
9020
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
9021
+ "status": "completed",
9022
+ "id": "5"
9023
+ }
9024
+ ]
9025
+ },
9026
+ "tool_response": {
9027
+ "oldTodos": [
9028
+ {
9029
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
9030
+ "status": "completed",
9031
+ "id": "1"
9032
+ },
9033
+ {
9034
+ "content": "Update README.md to document the new use_converse_api parameter",
9035
+ "status": "completed",
9036
+ "id": "2"
9037
+ },
9038
+ {
9039
+ "content": "Update example/example.js to include use_converse_api in the example",
9040
+ "status": "completed",
9041
+ "id": "3"
9042
+ },
9043
+ {
9044
+ "content": "Update package.json version to 2.5.0",
9045
+ "status": "completed",
9046
+ "id": "4"
9047
+ },
9048
+ {
9049
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
9050
+ "status": "in_progress",
9051
+ "id": "5"
9052
+ }
9053
+ ],
9054
+ "newTodos": [
9055
+ {
9056
+ "content": "Update server.js to add use_converse_api parameter extraction and pass to bedrockWrapper",
9057
+ "status": "completed",
9058
+ "id": "1"
9059
+ },
9060
+ {
9061
+ "content": "Update README.md to document the new use_converse_api parameter",
9062
+ "status": "completed",
9063
+ "id": "2"
9064
+ },
9065
+ {
9066
+ "content": "Update example/example.js to include use_converse_api in the example",
9067
+ "status": "completed",
9068
+ "id": "3"
9069
+ },
9070
+ {
9071
+ "content": "Update package.json version to 2.5.0",
9072
+ "status": "completed",
9073
+ "id": "4"
9074
+ },
9075
+ {
9076
+ "content": "Update CHANGELOG.md to document version 2.5.0 with Converse API support",
9077
+ "status": "completed",
9078
+ "id": "5"
9079
+ }
9080
+ ]
9081
+ }
7976
9082
  }
7977
9083
  ]