From 7ed779bbf384a2a559b642c553ec2c0e0de02ada Mon Sep 17 00:00:00 2001 From: Ntwari Bruce <107446340+ntwari-bruce@users.noreply.github.com> Date: Sat, 8 Mar 2025 16:47:53 -0600 Subject: [PATCH] feat: enhanced ai command to perfom other commands (#1156) * Enhanced ai command to perfom other commands * Enhance AI Command in Puter's shell --- package-lock.json | 1 + package.json | 1 + src/phoenix/src/puter-shell/coreutils/ai.js | 56 ++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 67b31e4b..0544b076 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "experiments/js-parse-and-output" ], "dependencies": { + "@heyputer/putility": "^1.0.2", "dedent": "^1.5.3", "javascript-time-ago": "^2.5.11", "json-colorizer": "^3.0.1", diff --git a/package.json b/package.json index 6ccee391..817be965 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ ] }, "dependencies": { + "@heyputer/putility": "^1.0.2", "dedent": "^1.5.3", "javascript-time-ago": "^2.5.11", "json-colorizer": "^3.0.1", diff --git a/src/phoenix/src/puter-shell/coreutils/ai.js b/src/phoenix/src/puter-shell/coreutils/ai.js index 83152c4a..e0537eca 100644 --- a/src/phoenix/src/puter-shell/coreutils/ai.js +++ b/src/phoenix/src/puter-shell/coreutils/ai.js @@ -26,6 +26,9 @@ export default { $: 'simple-parser', allowPositionals: true, }, + input: { + synchLines: true, + }, execute: async ctx => { const { positionals } = ctx.locals; const [ prompt ] = positionals; @@ -49,6 +52,18 @@ export default { a_args = { messages: [ ...chatHistory.get_messages(), + { + role: 'system', + content: `You are a helpful AI assistant that helps users with shell commands. + When a user asks to perform an action: + 1. If the action requires a command, wrap ONLY the command between %%% markers + 2. Keep the command simple and on a single line + 3. Do not ask for confirmation + Example: + User: "create a directory named test" + You: "Creating directory 'test' + %%%mkdir test%%%"` + }, { role: 'user', content: prompt, @@ -80,8 +95,47 @@ export default { return; } + chatHistory.add_message(resobj?.result?.message); - await ctx.externs.out.write(message + '\n'); + const commandMatch = message.match(/%%%(.*?)%%%/); + + if (commandMatch) { + const commandToExecute = commandMatch[1].trim(); + const cleanMessage = message.replace(/%%%(.*?)%%%/, ''); + + await ctx.externs.out.write(cleanMessage + '\n'); + + await ctx.externs.out.write(`Execute command: '${commandToExecute}' (y/n): `); + + try { + let line, done; + const next_line = async () => { + ({ value: line, done } = await ctx.externs.in_.read()); + } + + await next_line(); + + const inputString = new TextDecoder().decode(line); + const response = (inputString ?? '').trim().toLowerCase(); + + console.log('processed response', {response}); + + if (!response.startsWith('y')) { + await ctx.externs.out.write('\nCommand execution cancelled\n'); + return; + } + + await ctx.externs.out.write('\n'); + await ctx.shell.runPipeline(commandToExecute); + await ctx.externs.out.write(`Command executed: ${commandToExecute}\n`); + } catch (error) { + await ctx.externs.err.write(`Error executing command: ${error.message}\n`); + return; + } + } else { + await ctx.externs.out.write(message + '\n'); + } + } }