Skip to content

Commit

Permalink
called claude api and execute the return code
Browse files Browse the repository at this point in the history
  • Loading branch information
Ancss committed Aug 9, 2024
1 parent ffddb9c commit a50cadc
Show file tree
Hide file tree
Showing 13 changed files with 525 additions and 332 deletions.
12 changes: 10 additions & 2 deletions src-tauri/src/ai/claude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ use tauri::command;
use tokio::sync::Mutex;
use uuid::Uuid;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct MessageContent {
#[serde(rename = "type")]
pub content_type: String,
pub text: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Message {
pub role: String,
pub content: String,
pub content: Vec<MessageContent>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
Expand Down Expand Up @@ -82,9 +88,10 @@ pub async fn send_message_to_anthropic(
"model": model,
"system": system_prompt,
"tools": tools,
"tool_choice": { "type": "tool", "name": "format_response" },
"tool_choice": { "type": "auto" },
"max_tokens": max_tokens.unwrap_or(8192),
"messages": messages,
"temperature":0,
"stream": false
});
println!("Request body: {}", body.to_string());
Expand All @@ -99,6 +106,7 @@ pub async fn send_message_to_anthropic(
.header("Content-Type", "application/json")
.header("x-api-key", api_key)
.header("anthropic-version", "2023-06-01")
.header("anthropic-beta", "max-tokens-3-5-sonnet-2024-07-15")
.json(&body)
.send();

Expand Down
28 changes: 28 additions & 0 deletions src-tauri/src/commands/execute_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use std::process::Command;
use tauri::command;

#[command]
pub fn execute_code(code: String) -> Result<String, String> {
let output = if cfg!(target_os = "windows") {
Command::new("powershell")
.arg("-Command")
.arg(&code)
.output()
} else if cfg!(target_os = "macos") {
Command::new("sh").arg("-c").arg(&code).output()
} else {
// Assuming Linux or other Unix-like systems
Command::new("bash").arg("-c").arg(&code).output()
};

match output {
Ok(output) => {
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Err(String::from_utf8_lossy(&output.stderr).to_string())
}
}
Err(e) => Err(format!("Failed to execute command: {}", e)),
}
}
5 changes: 3 additions & 2 deletions src-tauri/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod file_operations;
pub mod ai_operations;
// pub mod file_operations;
// pub mod ai_operations;
pub mod execute_code;
4 changes: 3 additions & 1 deletion src-tauri/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod ai;
mod commands;
mod prompts;
use tauri::Manager;

Expand All @@ -15,7 +16,8 @@ fn main() {
.invoke_handler(tauri::generate_handler![
ai::claude::send_message_to_anthropic,
ai::claude::cancel_request,
ai::claude::create_cancel_flag
ai::claude::create_cancel_flag,
commands::execute_code::execute_code,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
Expand Down
72 changes: 24 additions & 48 deletions src-tauri/src/prompts.rs
Original file line number Diff line number Diff line change
@@ -1,61 +1,37 @@
use sysinfo::{System, SystemExt};

pub const SYSTEM_PROMPT_TEMPLATE: &str = r#"
You are OsaiAI, the central AI assistant integrated into the Osai desktop application. As the sole intermediary between the user and their operating system, you have the capability to perform any operation on the OS that the user requests, subject to user confirmation for sensitive actions.
You are an intelligent operating system assistant (OS AI) capable of performing tasks on the user's behalf. Your primary function is to understand user requests and execute them using available system resources.
Guidelines:
1. Provide concise and accurate responses for general queries.
2. For actionable requests, take initiative to perform tasks without asking for permission, unless it involves system changes or sensitive operations.
3. Utilize system resources efficiently to fulfill user requests.
4. Break down tasks into the simplest, most atomic steps possible.
5. Generate actual, executable system commands for each step.
6. Only set user_confirmation_required to true for operations that modify system settings or access sensitive data.
7. If a task cannot be completed, explain why and suggest alternatives.
8. Do not invent or assume any information not explicitly provided or directly obtainable through the executed commands.
9. For web searches, use general search engines like Google or Bing unless a specific, verified website is needed.
10. When dealing with applications:
a. Do not assume default installation paths.
b. Use system commands to search for the application in multiple potential locations.
c. Verify the existence of the application before attempting to launch it.
d. Provide clear feedback on whether the application was found and launched successfully.
11. Combine interdependent steps into a single executable step when necessary.
12. The 'code' field in the execution array must contain only executable commands. Do not include comments or pseudocode.
13. Be aware of and utilize appropriate system commands for different operating systems (Windows, macOS, Linux).
14. Always provide a clear and informative response to the user about the actions taken and their results.
Always structure your response using the specified AIResponse format.
Key Capabilities:
1. Universal Language Processing: Understand and respond in the language of the user's input.
2. Comprehensive OS Control: Execute any operation on the user's operating system through appropriate commands and APIs.
3. Task Decomposition and Execution: Break down complex requests into actionable steps and execute them sequentially.
4. Dynamic Code Generation: Create and execute OS-specific code (PowerShell, Bash, AppleScript, etc.) as needed.
5. Intelligent Application and File Management: Handle application launching, file operations, and system settings adjustments.
6. Web Integration: Perform web searches and interact with online services when necessary.
7. Adaptive Conversation: Engage in both task-oriented and casual conversations, answering questions and providing information.
Operational Guidelines:
1. User Confirmation:
- Always ask for explicit user confirmation before executing any system operation, except for opening applications or web browsers.
- Clearly explain the potential impact of sensitive operations.
2. Task Execution:
- Generate a detailed, step-by-step plan for complex tasks before execution.
- Use the appropriate system commands based on the user's OS (Windows, macOS, or Linux).
- Provide real-time feedback on task progress and results.
3. Application and File Handling:
- Verify the existence of applications and files before attempting operations.
- For partial or ambiguous names, suggest the most likely matches and confirm with the user.
4. Web Integration:
- Seamlessly integrate web searches and online services when local resources are insufficient.
5. Safety and Privacy:
- Prioritize system security and user privacy in all operations.
- Warn users about potential risks associated with their requests.
6. Language Adaptation:
- Detect the language of the user's input and respond in the same language.
- Maintain consistency in language use throughout the conversation.
Response Structure:
Always structure your responses in the following JSON format:
When responding to a user request:
1. Analyze the input to determine the nature of the request (task, question, or conversation).
2. For tasks, create a detailed plan and populate the JSON structure accordingly.
3. For questions or conversation, focus on the 'thought_process' and 'response' fields.
4. Always use the language of the user's input in the 'response' field.
5. Ensure all sensitive operations are flagged for user confirmation.
====
Operating System Information
- Type: {OS_TYPE}
- Version: {OS_VERSION}
- Architecture: {ARCH}
Remember, as OsaiAI, you are the user's primary interface with their operating system. Strive to be helpful, efficient, and security-conscious in all interactions.`;
`;
"#;

pub fn format_system_prompt() -> String {
Expand Down
114 changes: 114 additions & 0 deletions src/components/BottomInputContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import React, { useState, useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
import { Button } from "@/components/ui/button";
import { useSpeechRecognition } from "@/hooks/useSpeechRecognition";
import {
MAX_CHARS,
MIN_TEXTAREA_HEIGHT,
MAX_TEXTAREA_HEIGHT,
} from "@/utils/constants";
import { Textarea } from "@chakra-ui/react";
import { cn } from "@/lib/utils";
import { Send, StopCircle } from "lucide-react";

const BottomInputContainer = ({
isLoading,
input,
// stopListening,
// startListening,
handleSend,
setInput,
abortRequest,
}: {
input: string;
isLoading: boolean;
// stopListening: () => void;
// startListening: () => void;
handleSend: () => void;
setInput: (s: string) => void;
abortRequest: () => void;
}) => {
const { t } = useTranslation();
const { transcript } = useSpeechRecognition();
const textareaRef = useRef<HTMLTextAreaElement>(null);

// const handleVoiceInput = () => {
// if (transcript) {
// stopListening();
// } else {
// startListening();
// }
// };

const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const value = e.target.value;
if (value.length <= MAX_CHARS) {
setInput(value);
}
};

const adjustHeight = () => {
const textarea = textareaRef.current;
if (!textarea) return;

textarea.style.height = "auto";
const scrollHeight = input === "" ? 45 : textarea.scrollHeight;
const lines = scrollHeight / 45;
const newRows = Math.max(1, Math.min(10, Math.floor(lines)));

textarea.style.height = `${newRows * 45}px`;
};

useEffect(adjustHeight, [input]);

return (
<div className="bg-gray-50 dark:bg-gray-800">
<div className="flex p-2 items-end space-x-2 bg-white dark:bg-gray-700 rounded-2 overflow-hidden shadow-inner">
{/* <Button
variant="ghost"
className="rounded-full min-w-10 p-2"
onClick={handleVoiceInput}
>
<Mic size={16} className={transcript ? "text-red-500" : ""} />
</Button> */}
<Textarea
ref={textareaRef}
value={input}
onChange={handleInputChange}
placeholder={t("typeMessage")!}
className={cn(
"flex-grow border-none bg-transparent focus:ring-0 focus:outline-none resize-none",
"min-h-[2.5rem] py-2 px-3 text-base leading-relaxed",
"scrollbar scrollbar-thumb-gray-300 dark:scrollbar-thumb-gray-600",
"scrollbar-track-transparent scrollbar-thin hover:scrollbar-thumb-gray-400 dark:hover:scrollbar-thumb-gray-500",
"!border-none focus-visible:ring-0 focus-visible:outline-none"
)}
style={{
minHeight: `${MIN_TEXTAREA_HEIGHT}px`,
maxHeight: `${MAX_TEXTAREA_HEIGHT}px`,
overflowY: "auto",
boxSizing: "border-box",
}}
onKeyPress={(e) => {
if (e.key === "Enter" && !e.shiftKey && !isLoading) {
e.preventDefault();
handleSend();
}
}}
/>
<Button
className="rounded-full min-w-10 p-2"
onClick={isLoading ? abortRequest : handleSend}
>
{isLoading ? (
<StopCircle size={16} className="text-red-500" />
) : (
<Send size={16} />
)}
</Button>
</div>
</div>
);
};

export default BottomInputContainer;
38 changes: 38 additions & 0 deletions src/components/ExecutionStepComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from "react";
import { CheckCircle, XCircle, Clock } from "lucide-react";
import { ExecutionStep } from "@/type";

const ExecutionStepComponent: React.FC<{ step: ExecutionStep }> = ({
step,
}) => {
const getStatusIcon = () => {
switch (step.status) {
case "success":
return <CheckCircle className="text-green-500" />;
case "failure":
return <XCircle className="text-red-500" />;
default:
return <Clock className="text-gray-500" />;
}
};

return (
<div className="border rounded p-2 mb-2">
<div className="flex items-center">
{getStatusIcon()}
<span className="ml-2 font-bold">{step.step}</span>
</div>
<pre className="bg-gray-100 p-2 mt-2 rounded text-sm overflow-x-auto">
<code>{step.code}</code>
</pre>
{step.result && (
<div className="mt-2">
<strong>Result:</strong>
<p>{step.result}</p>
</div>
)}
</div>
);
};

export default ExecutionStepComponent;
Loading

0 comments on commit a50cadc

Please sign in to comment.