From 70fe6fccdb58528d6d2c4729e5beb04e091461d4 Mon Sep 17 00:00:00 2001 From: sebseb7 Date: Tue, 12 Aug 2025 03:38:23 +0000 Subject: [PATCH] Refactor CLI input handling to ensure userText is passed correctly and improve output formatting in cli.js. Update package.json and package-lock.json to include 'exa-js' dependency for enhanced functionality. Revise systemprompt.txt to clarify tool usage and streamline instructions. --- .devcontainer.json | 3 ++ cli.js | 6 ++-- package-lock.json | 74 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + systemprompt.txt | 18 ++++------- tools/websearch.js | 29 ++++++++++++++++++ 6 files changed, 116 insertions(+), 15 deletions(-) create mode 100644 .devcontainer.json create mode 100644 tools/websearch.js diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 0000000..4d87578 --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,3 @@ +{ + "image": "mcr.microsoft.com/devcontainers/javascript-node" +} \ No newline at end of file diff --git a/cli.js b/cli.js index b65667b..dcd1f9f 100644 --- a/cli.js +++ b/cli.js @@ -71,7 +71,7 @@ while(true){ let counter = 0; // Block for user input before kicking off the LLM loop const userText = await askUserForInput(); - await streamOnce(new OpenAI({ apiKey: process.env.OPENAI_API_KEY }), userText || ''); + await streamOnce(new OpenAI({ apiKey: process.env.OPENAI_API_KEY }), userText ); async function streamOnce(openai, userText) { const toolsByFile = await loadTools(); let previousResponseId; @@ -142,7 +142,7 @@ while(true){ stream.on('response.completed', async (event) => { printIndented(10,renderUsage(event.response.usage)); - if (event.response.output.filter(i => i.type === 'message').length > 0) printIndented(10, "Textresult:",event.response.output.filter(i => i.type === 'message').map(i => i.content[0].text)); + if (event.response.output.filter(i => i.type === 'message').length > 0) printIndented(10,event.response.output.filter(i => i.type === 'message').map(i => i.content[0].text).join('\n')); }); await Array.fromAsync(stream); @@ -165,4 +165,4 @@ while(true){ //console.log('OPENAI STREAM FINISHED'); } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 8edc9bc..a6f3cf9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "es-set-tostringtag": "^2.1.0", "esbuild": "^0.25.8", "event-target-shim": "^5.0.1", + "exa-js": "^1.8.27", "form-data": "^4.0.4", "form-data-encoder": "^1.7.2", "formdata-node": "^4.4.1", @@ -723,6 +724,15 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/cross-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, "node_modules/cwise-compiler": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", @@ -899,6 +909,52 @@ "node": ">=6" } }, + "node_modules/exa-js": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/exa-js/-/exa-js-1.8.27.tgz", + "integrity": "sha512-C0vsC3r5B1vhibXAxtJ9OlCwXTp+AaWFPk3ozLoUBV2VH+Xd+WhkKp8/30i9mkBVJopK/8+lDMv8MyRjkOWm5g==", + "license": "MIT", + "dependencies": { + "cross-fetch": "~4.1.0", + "dotenv": "~16.4.7", + "openai": "^5.0.1", + "zod": "^3.22.0", + "zod-to-json-schema": "^3.20.0" + } + }, + "node_modules/exa-js/node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/exa-js/node_modules/openai": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/openai/-/openai-5.12.2.tgz", + "integrity": "sha512-xqzHHQch5Tws5PcKR2xsZGX9xtch+JQFz5zb14dGqlshmmDAFBFEWmeIpf7wVqWV+w7Emj7jRgkNJakyKE0tYQ==", + "license": "Apache-2.0", + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, "node_modules/form-data": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", @@ -1780,6 +1836,24 @@ "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz", "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==", "license": "MIT" + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } } } } diff --git a/package.json b/package.json index bbcd79a..bd71499 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "es-set-tostringtag": "^2.1.0", "esbuild": "^0.25.8", "event-target-shim": "^5.0.1", + "exa-js": "^1.8.27", "form-data": "^4.0.4", "form-data-encoder": "^1.7.2", "formdata-node": "^4.4.1", diff --git a/systemprompt.txt b/systemprompt.txt index 8efcf29..9ae9029 100644 --- a/systemprompt.txt +++ b/systemprompt.txt @@ -1,16 +1,10 @@ You are an interactive CLI AI assistant. Follow the user's instructions. If a tool is available and relevant, plan to use it. -Be explicit when information is undefined. -Do not silently fall back: surface errors. -Prefer concise answers. - -Developer rules: -- Null tells the truth. If data is missing/undefined, say so; do not invent values. -- In development, never hide errors; include warnings if using fallbacks. - -Behavior: -- Answer succinctly. -- Ask for clarification when the user input is ambiguous. -- Output plain text suitable for a terminal. +Tools: +list_files - (no/empty path means root) +patch_files - (zum anlegen, ändern und löschen von Dateien) +read_file - (nach zeilen) +ripgrep - suchmusater und dateimuster +websearch - eine Google Suche machen mit Schlüsselwörtern diff --git a/tools/websearch.js b/tools/websearch.js new file mode 100644 index 0000000..583f751 --- /dev/null +++ b/tools/websearch.js @@ -0,0 +1,29 @@ +import Exa from "exa-js"; +const exa = new Exa("1513ba88-5280-402b-9da3-e060d38f96d8"); + +export default { + type: 'function', + name: 'websearch', + description: 'Perform a google web search.', + strict: true, + parameters: { + type: 'object', + required: ['query'], + additionalProperties: false, + properties: { + query: { type: 'string', description: 'The search query.' } + } + } +}; + +export async function run(args) { + try + { + console.log('Google search: ', args.query); + const result = await exa.search( args.query,{ type: "auto", userLocation: "DE", numResults: 20} ); + console.log('Google search result: ', result.results[0]); + return result; + } catch (error) { + return `websearch error: ${error?.message || String(error)}`; + } +}