diff --git a/llm_client/src/bin/o1_prompting.rs b/llm_client/src/bin/o1_prompting.rs new file mode 100644 index 00000000..f6656c37 --- /dev/null +++ b/llm_client/src/bin/o1_prompting.rs @@ -0,0 +1,179 @@ +use llm_client::{ + clients::{ + openai::OpenAIClient, + types::{LLMClient, LLMClientCompletionRequest, LLMClientMessage, LLMType}, + }, + provider::{LLMProviderAPIKeys, OpenAIProvider}, +}; + +#[tokio::main] +async fn main() { + let developer_message = format!( + r#"You have to assign tasks to a junior engineer to solve a user problem. The user problem could be of various forms: + +- Adding a feature +- Debugging a failing test case +- Understanding a feature in the codebase +- A GitHub issue raised on the codebase + +## Additional Instructions + +### Junior Engineer Visibility +You are not supposed to solve the user query yourself. Instead, you will provide instructions to a junior engineer who will do the actual work. +The junior engineer does not see the original user query. They only see and follow your instructions. +The junior engineer always starts with zero context on the problem, so your instructions must stand on their own. + +### Instruction Content +Be explicit in what files to edit or create, which lines to change, and any code or commands they should run. +Include sample code snippets or test code for clarity and to avoid ambiguity. +Provide context and justification for each task so the junior engineer understands why they are doing it. +Consider any edge cases or complexities in your instructions. + +### Task Format +You maintain a high-level plan consisting of sequential steps. +For each step, you will provide a clear instruction to the junior engineer. +You can refine the plan as the engineer reports back with progress or any discoveries. + +## Workflow + +- **Identify the Problem**: Describe the user problem in your own words (since the junior engineer won’t see it). +- **Break Down the Task**: Outline the tasks needed to address the problem. +- **Assign Tasks**: Provide instructions with enough detail that the junior engineer can carry them out without additional context. +- **Track Progress**: After the engineer executes a step, use their feedback to update or refine your plan. +- **Iterate**: Continue until the user’s issue is resolved or the requested feature is implemented. +- **Completion**: Confirm that all steps are done and the issue is fully addressed. + +## Notes and Reminders +- Keep any additional insights or references in sections so they’re easy to refer back to later. +- The junior engineer is hardworking and will follow your instructions to the letter. +- The junior engineer never sees the user’s original problem statement, so restating important details is crucial. + +## Output Format Requirements + +When you produce an output in response to the junior engineer's progress, include the following sections in this order: + +### Plan Section + + + + {{High-level step-by-step plan}} + + +This is the updated plan, reflecting the overall strategy and steps to address the user problem. + +### Notes Section (if needed) + + + {{Any helpful references, code snippets, or insights for future steps}} + +This can contain extra details or code for future use. + +### Current Task Section + + + + {{The specific instruction the engineer should execute next}} + + + +Direct, specific task instructions for the junior engineer to execute immediately. + +### Junior Engineer's Tools +They have access to: + +- Bash commands (Terminal) +- A local editor to modify or create files +- Python environment to install and test Astropy locally + +### Repository Information + +Repository Name: astropy +Working Directory: /testbed/astropy + +The junior engineer will communicate their progress in the following format: + + +{{the instruction they are working on}} + +And the steps they took to work on the instruction: + + + + {{engineer’s reasoning or approach}} + + + {{commands or code they ran}} + + + {{results, errors, or logs}} + + +"# + ); + let user_message = format!( + r#" +Modeling's `separability_matrix` does not compute separability correctly for nested CompoundModels +Consider the following model: + +```python +from astropy.modeling import models as m +from astropy.modeling.separable import separability_matrix + +cm = m.Linear1D(10) & m.Linear1D(5) +``` + +It's separability matrix as you might expect is a diagonal: + +```python +>>> separability_matrix(cm) +array([[ True, False], + [False, True]]) +``` + +If I make the model more complex: +```python +>>> separability_matrix(m.Pix2Sky_TAN() & m.Linear1D(10) & m.Linear1D(5)) +array([[ True, True, False, False], + [ True, True, False, False], + [False, False, True, False], + [False, False, False, True]]) +``` + +The output matrix is again, as expected, the outputs and inputs to the linear models are separable and independent of each other. + +If however, I nest these compound models: +```python +>>> separability_matrix(m.Pix2Sky_TAN() & cm) +array([[ True, True, False, False], + [ True, True, False, False], + [False, False, True, True], + [False, False, True, True]]) +``` +Suddenly the inputs and outputs are no longer separable? + +This feels like a bug to me, but I might be missing something? +"# + ); + + let llm_client = OpenAIClient::new(); + let completion_request = LLMClientCompletionRequest::new( + LLMType::O1, + vec![ + LLMClientMessage::system(developer_message), + LLMClientMessage::user(user_message), + ], + 0.2, + None, + ); + let (sender, _receiver) = tokio::sync::mpsc::unbounded_channel(); + let response = llm_client + .stream_completion( + LLMProviderAPIKeys::OpenAI(OpenAIProvider::new("".to_owned())), + completion_request, + sender, + ) + .await + .expect("to work"); + + println!("response:\n{}", response.answer_up_until_now()); +} diff --git a/llm_client/src/clients/openai.rs b/llm_client/src/clients/openai.rs index 90a048ea..413abed8 100644 --- a/llm_client/src/clients/openai.rs +++ b/llm_client/src/clients/openai.rs @@ -6,7 +6,7 @@ use async_openai::{ ChatCompletionRequestAssistantMessageArgs, ChatCompletionRequestDeveloperMessageArgs, ChatCompletionRequestMessage, ChatCompletionRequestSystemMessageArgs, ChatCompletionRequestUserMessageArgs, CreateChatCompletionRequestArgs, FunctionCall, - ReasoningEffort, + ReasoningEffort, ResponseFormat, }, Client, }; @@ -227,9 +227,18 @@ impl LLMClient for OpenAIClient { let mut request_builder = request_builder_args .model(model.to_owned()) .messages(messages); - request_builder = request_builder - .temperature(request.temperature()) - .stream(true); + + // o1 does not support streaming on the api + if llm_model != &LLMType::O1 { + request_builder = request_builder.stream(true); + } + // set response format to text + request_builder.response_format(ResponseFormat::Text); + + // we cannot set temperature for o1 + if llm_model != &LLMType::O1 { + request_builder = request_builder.temperature(request.temperature()); + } // if its o1 we should set reasoning_effort to high if llm_model == &LLMType::O1 { @@ -283,7 +292,7 @@ impl LLMClient for OpenAIClient { } } OpenAIClientType::OpenAIClient(client) => { - if false { + if true { let completion = client.chat().create(request).await?; let response = completion .choices @@ -303,6 +312,7 @@ impl LLMClient for OpenAIClient { } else { let mut stream = client.chat().create_stream(request).await?; while let Some(response) = stream.next().await { + println!("{:?}", &response); match response { Ok(response) => { let response = response diff --git a/sidecar/src/agentic/tool/session/service.rs b/sidecar/src/agentic/tool/session/service.rs index b8437854..f0133717 100644 --- a/sidecar/src/agentic/tool/session/service.rs +++ b/sidecar/src/agentic/tool/session/service.rs @@ -626,6 +626,9 @@ impl SessionService { session = session.accept_open_exchanges_if_any(message_properties.clone()); let mut previous_failure = false; + // we want something here which is giving tasks to the agent so we can run the loop below + // for the agent and hard cut it after some steps + // now that we have saved it we can start the loop over here and look out for the cancellation // token which will imply that we should end the current loop loop { diff --git a/sidecar/src/agentic/tool/session/session.rs b/sidecar/src/agentic/tool/session/session.rs index 80f2a779..164804b8 100644 --- a/sidecar/src/agentic/tool/session/session.rs +++ b/sidecar/src/agentic/tool/session/session.rs @@ -1234,6 +1234,17 @@ impl Session { } } + pub async fn reasoning( + mut self, + tool_box: Arc, + exchange_id: &str, + parent_exchange_id: String, + tool_use_agent: ToolUseAgent, + message_properties: SymbolEventMessageProperties, + ) { + // the goal of reasoning is to use o1 to better steer sonnet to success + } + pub async fn get_tool_to_use( mut self, tool_box: Arc, diff --git a/sidecar/src/agentic/tool/session/something.json b/sidecar/src/agentic/tool/session/something.json deleted file mode 100644 index 27eb2b1c..00000000 --- a/sidecar/src/agentic/tool/session/something.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "model": "anthropic/claude-3.5-sonnet:beta", - "temperature": 0.2, - "messages": [ - { - "role": "system", - "content": [ - { - "type": "text", - "text": "You are an expert software engineer taked with helping the developer.\nYou know in detail everything about this repository and all the different code structures which are present in it source code for it.\n\n\n/Users/skcd/test_repo/sidecar\n\nI've uploaded a code repository in the directory /Users/skcd/test_repo/sidecar (not in /tmp/inputs).\n\nCan you help me implement the necessary changes to the repository so that the requirements specified by the user are met?\nI've also setup the developer environment in /Users/skcd/test_repo/sidecar.\n\nYour task is to make the minimal changes to files in the /Users/skcd/test_repo/sidecar directory to ensure the developer is satisfied.\n\nTool capabilities:\n- You have access to tools that let you execute CLI commands on the local checkout, list files, view source code definitions, regex search, read and write files. These tools help you effectively accomplish a wide range of tasks, such as writing code, making edits or improvements to existing files, understanding the current state of a project, and much more.\n- You can use search_files to perform regex searches across files in a specified directory, outputting context-rich results that include surrounding lines. This is particularly useful for understanding code patterns, finding specific implementations, or identifying areas that need refactoring.\n- When using the search_files tool, craft your regex patterns carefully to balance specificity and flexibility. Based on the developer needs you may use it to find code patterns, function definitions, or any text-based information across the project. The results include context, so analyze the surrounding code to better understand the matches. Leverage the search_files tool in combination with other tools for more comprehensive analysis.\n- Once a file has been created using `create` on `str_replace_editor` tool, you should not keep creating the same file again and again. Focus on editing the file after it has been created.\n- You can run long running terminal commands which can run in the background, we will present you with the updated logs. This can be useful if the user wants you to start a debug server in the terminal and then look at the logs or other long running processes.\n\n====\n\nSYSTEM INFORMATION\n\nOperating System: macos\nDefault Shell: /bin/zsh\nCurrent Working Directory: /Users/skcd/test_repo/sidecar\n\n====\n\nFOLLOW these steps to resolve the issue:\n1. As a first step, it might be a good idea to explore the repo to familiarize yourself with its structure.\n2. Once you have understood the repository structure being by making minimal edits to make sure that the user request is answered. The user request could also be about understanding the codebase in which case you don't need to make any edits.\n3. Once you have made the edits it is important that you look at the diagnostic messages which might be present so you can fix any errors or bugs which you have introduced.\n4. You also have access to the terminal, you should ALWAYS run commands from the /Users/skcd/test_repo/sidecar (any command run outside this directory will lead to errors)\n5. Once you have done everything to help the user out, use attempt_completion to summarise what you have done and end the task assigned to you by the user.\n\nYour thinking should be thorough and so it's fine if it's very long.", - "cache_control": null - } - ] - }, - { - "role": "user", - "content": [ - { - "type": "text", - "text": "\n\n/Users/skcd/test_repo/sidecar/sidecar/src/agentic/tool/terminal/mod.rs\ngit/scm0/input\n/Users/skcd/.vscode-oss-dev/User/modelSelection.json\n\n\n\n\n\n\ncan you make a bin file which shows how we can use the terminal command\n", - "cache_control": null - } - ] - }, - { - "role": "assistant", - "content": [ - { - "type": "text", - "text": "I'll help you create a binary example that demonstrates how to use the terminal command functionality. First, let's explore the repository structure to understand where we should create this example.", - "cache_control": null - } - ], - "tool_calls": [ - { - "id": "toolu_01FguFFkkUEQBpcbwPkAfhyK", - "type": "function", - "function": { - "name": "list_files", - "arguments": "{\"directory_path\":\"/Users/skcd/test_repo/sidecar\",\"recursive\":false}" - } - } - ] - }, - { - "role": "user", - "content": [ - { - "type": "text", - "text": "Content for directory /Users/skcd/test_repo/sidecar\n/Users/skcd/test_repo/sidecar/CODE_OF_CONDUCT.md\n/Users/skcd/test_repo/sidecar/Cargo.toml\n/Users/skcd/test_repo/sidecar/LICENSE.md\n/Users/skcd/test_repo/sidecar/llm_client\n/Users/skcd/test_repo/sidecar/package_windows_bin.sh\n/Users/skcd/test_repo/sidecar/dataset\n/Users/skcd/test_repo/sidecar/llm_prompts\n/Users/skcd/test_repo/sidecar/Cargo.lock\n/Users/skcd/test_repo/sidecar/vllm\n/Users/skcd/test_repo/sidecar/README.md\n/Users/skcd/test_repo/sidecar/update_version.sh\n/Users/skcd/test_repo/sidecar/.gitignore\n/Users/skcd/test_repo/sidecar/CONTRIBUTING.md\n/Users/skcd/test_repo/sidecar/sidecar\n/Users/skcd/test_repo/sidecar/HOW_TO_CONTRIBUTE.md\n/Users/skcd/test_repo/sidecar/huggingface\n/Users/skcd/test_repo/sidecar/rust-toolchain.toml\n/Users/skcd/test_repo/sidecar/package_windows_zip.sh\n/Users/skcd/test_repo/sidecar/logging\n/Users/skcd/test_repo/sidecar/SECURITY.md\n/Users/skcd/test_repo/sidecar/media", - "cache_control": null - } - ], - "tool_call_id": "toolu_01FguFFkkUEQBpcbwPkAfhyK", - "name": "list_files" - }, - { - "role": "user", - "content": [ - { - "type": "text", - "text": "Here's the full content of the file:\n\n/Users/skcd/test_repo/sidecar/sidecar/src/agentic/tool/terminal/mod.rs\n\n\n```rust\npub mod terminal;\n\n", - "cache_control": null - } - ], - "tool_call_id": "toolu_014fTNiagBFSA2Bj1kAu4NTH", - "name": "read_file" - }, - { - "role": "user", - "content": [ - { - "type": "text", - "text": "Here's the full content of the file:\n\n/Users/skcd/test_repo/sidecar/sidecar/src/agentic/tool/terminal/terminal.rs\n\n\n```rust\nuse async_trait::async_trait;\n\nuse crate::agentic::tool::{\n errors::ToolError,\n input::ToolInput,\n output::ToolOutput,\n r#type::{Tool, ToolRewardScale},\n};\n\npub struct TerminalTool {\n client: reqwest::Client,\n}\n\n#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]\npub struct TerminalInputPartial {\n command: String,\n}\n\nimpl TerminalInputPartial {\n pub fn new(command: String) -> Self {\n Self { command }\n }\n\n pub fn command(&self) -> &str {\n &self.command\n }\n\n pub fn sanitise_for_repro_script(self) -> Self {\n if self.command.contains(\"reproduce_error.py\") && self.command.contains(\"python\") {\n Self {\n command: \"python reproduce_error.py\".to_owned(),\n }\n } else {\n self\n }\n }\n\n pub fn to_string(&self) -> String {\n format!(\n r#\"\n...\n\n\n\n{}\n\n\"#,\n self.command\n )\n }\n\n pub fn to_json() -> serde_json::Value {\n serde_json::json!({\n \"name\": \"execute_command\",\n \"description\": r#\"Request to execute a CLI command on the system. Commands will be executed in the current working directory.\"#,\n \"input_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"command\": {\n \"type\": \"string\",\n \"description\": \"(required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.\",\n }\n },\n \"required\": [\"command\"],\n },\n })\n }\n}\n\n#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]\npub struct TerminalInput {\n command: String,\n editor_url: String,\n}\n\nimpl TerminalInput {\n pub fn new(command: String, editor_url: String) -> Self {\n Self {\n command,\n editor_url,\n }\n }\n}\n\n#[derive(Debug, serde::Deserialize, serde::Serialize)]\npub struct TerminalOutput {\n output: String,\n}\n\nimpl TerminalOutput {\n pub fn output(&self) -> &str {\n &self.output\n }\n}\n\nimpl TerminalTool {\n pub fn new() -> Self {\n Self {\n client: reqwest::Client::new(),\n }\n }\n}\n\n#[async_trait]\nimpl Tool for TerminalTool {\n async fn invoke(&self, input: ToolInput) -> Result {\n let context = input.is_terminal_command()?;\n let editor_endpoint = context.editor_url.to_owned() + \"/execute_terminal_command\";\n\n let response = self\n .client\n .post(editor_endpoint)\n .body(serde_json::to_string(&context).map_err(|_e| ToolError::SerdeConversionFailed)?)\n .send()\n .await\n .map_err(|_e| ToolError::ErrorCommunicatingWithEditor)?;\n\n let terminal_response: TerminalOutput = response\n .json()\n .await\n .map_err(|_e| ToolError::SerdeConversionFailed)?;\n\n Ok(ToolOutput::TerminalCommand(terminal_response))\n }\n\n // credit Cline.\n // Current working directory will be known to LLM from higher level context\n fn tool_description(&self) -> String {\n format!(\n r#\"### execute_command\nRequest to execute a CLI command on the system.\nUse this when you need to perform system operations or run specific commands to accomplish any step in the user's task.\nYou must tailor your command to the user's system and provide a clear explanation of what the command does.\nPrefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run.\nCommands will be executed in the current working directory.\nNote: You MUST append a `sleep 0.05` to the end of the command for commands that will complete in under 50ms, as this will circumvent a known issue with the terminal tool where it will sometimes not return the output when the command completes too quickly.\n\"#\n )\n }\n\n fn tool_input_format(&self) -> String {\n format!(\n r#\"Parameters:\n- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.\n\nUsage:\n\n\nYour command here\n\n\n\"#\n )\n }\n\n fn get_evaluation_criteria(&self, trajectory_length: usize) -> Vec {\n let evaluation_criteria = if trajectory_length < 3 {\n vec![\n \"Exploratory Actions: Recognize that initial searches and information-gathering steps are essential and should not be heavily penalized if they don't yield immediate results.\",\n \"Appropriateness of Action: Evaluate if the action is logical given the agent's current knowledge and the early stage of problem-solving.\",\n ]\n } else {\n vec![\n \"Solution Quality: Assess the logical changes, contextual fit, and overall improvement without introducing new issues.\",\n \"Progress Assessment: Evaluate the agent's awareness of solution history, detection of repetitive actions, and planned next steps.\",\n \"Repetitive or Redundant Actions: Detect if the agent is repeating the same unsuccessful or redundant actions without making progress. Pay close attention to the agent's history and outputs indicating lack of progress.\",\n ]\n };\n evaluation_criteria\n .into_iter()\n .map(|evaluation_criteria| evaluation_criteria.to_owned())\n .collect()\n }\n\n fn get_reward_scale(&self, _trajectory_length: usize) -> Vec {\n vec![\n ToolRewardScale::new(\n 75,\n 100,\n \"The action significantly advances the solution.\",\n ),\n ToolRewardScale::new(\n 50,\n 74,\n \"The action contributes positively towards solving the problem.\",\n ),\n ToolRewardScale::new(\n 25,\n 49,\n \"The action is acceptable but may have some issues.\",\n ),\n ToolRewardScale::new(\n 0,\n 24,\n \"The action has minimal impact or minor negative consequences.\",\n ),\n ToolRewardScale::new(\n -49,\n -1,\n \"The code change is inappropriate, unhelpful, introduces new issues, or redundantly repeats previous changes without making further progress. The Git diff does not align with instructions or is unnecessary.\",\n ),\n ToolRewardScale::new(\n -100,\n -50,\n \"The code change is counterproductive, causing significant setbacks or demonstrating persistent repetition without learning. The agent fails to recognize completed tasks and continues to attempt redundant actions.\",\n ),\n ]\n }\n}\n\n", - "cache_control": null - } - ], - "tool_call_id": "toolu_017nBwMSaKfZ6rX3U22xuJs6", - "name": "read_file" - }, - { - "role": "assistant", - "content": [ - { - "type": "text", - "text": "I'll help you create a binary example that demonstrates how to use the terminal command functionality. Let's create a new binary file in the sidecar project. First, let's check the project structure to see where we should place our binary example.", - "cache_control": null - } - ], - "tool_calls": [ - { - "id": "toolu_016f7zN12JaMuiqnMv8z78zr", - "type": "function", - "function": { - "name": "list_files", - "arguments": "{\"directory_path\":\"/Users/skcd/test_repo/sidecar/sidecar/src/bin\",\"recursive\":false}" - } - } - ] - }, - { - "role": "user", - "content": [ - { - "type": "text", - "text": "Content for directory /Users/skcd/test_repo/sidecar/sidecar/src/bin\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/get_diagnostics.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/git_ignore_walk.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/git_diff_generator.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/cohere_rerank.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/swe_bench.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/diff_rendering.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/serde_xml.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/try_repomap.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/midwit_tool_use.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/swe_bench_test_agent.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/mistral.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/test_agent.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/webserver.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/terminal.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/tool_box_git_diff.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/sys_info.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/find_code_section.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/git_diff_trace.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/db_loading.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/code_selection_editing.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/state.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/stream_thinking.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/shared_future.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/simd_page_rank.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/axflow_ingest.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/git_walking.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/parea.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/openai_test.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/fireworks.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/read_folder.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/swe_bench_mcts.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/code_editing_flow.rs\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/git_log.rs", - "cache_control": null - } - ], - "tool_call_id": "toolu_016f7zN12JaMuiqnMv8z78zr", - "name": "list_files" - }, - { - "role": "user", - "content": [ - { - "type": "text", - "text": "Here's the full content of the file:\n\n/Users/skcd/test_repo/sidecar/sidecar/src/bin/terminal.rs\n\n\n```rust\nuse std::{path::PathBuf, sync::Arc};\n\nuse llm_client::{\n broker::LLMBroker,\n clients::types::LLMType,\n config::LLMBrokerConfiguration,\n provider::{\n AnthropicAPIKey, FireworksAPIKey, GoogleAIStudioKey, LLMProvider, LLMProviderAPIKeys,\n OpenAIProvider,\n },\n};\nuse sidecar::agentic::symbol::ui_event::UIEventWithID;\nuse sidecar::{\n agentic::{\n symbol::{identifier::LLMProperties, manager::SymbolManager},\n tool::{\n broker::{ToolBroker, ToolBrokerConfiguration},\n code_edit::models::broker::CodeEditBroker,\n },\n },\n chunking::{editor_parsing::EditorParsing, languages::TSLanguageParsing},\n inline_completion::symbols_tracker::SymbolTrackerInline,\n user_context::types::UserContext,\n};\n\nfn default_index_dir() -> PathBuf {\n match directories::ProjectDirs::from(\"ai\", \"codestory\", \"sidecar\") {\n Some(dirs) => dirs.data_dir().to_owned(),\n None => \"codestory_sidecar\".into(),\n }\n}\n\n#[tokio::main]\nasync fn main() {\n let request_id = uuid::Uuid::new_v4();\n let request_id_str = request_id.to_string();\n let parea_url = format!(\n r#\"https://app.parea.ai/logs?colViz=%7B%220%22%3Afalse%2C%221%22%3Afalse%2C%222%22%3Afalse%2C%223%22%3Afalse%2C%22error%22%3Afalse%2C%22deployment_id%22%3Afalse%2C%22feedback_score%22%3Afalse%2C%22time_to_first_token%22%3Afalse%2C%22scores%22%3Afalse%2C%22start_timestamp%22%3Afalse%2C%22user%22%3Afalse%2C%22session_id%22%3Afalse%2C%22target%22%3Afalse%2C%22experiment_uuid%22%3Afalse%2C%22dataset_references%22%3Afalse%2C%22in_dataset%22%3Afalse%2C%22event_type%22%3Afalse%2C%22request_type%22%3Afalse%2C%22evaluation_metric_names%22%3Afalse%2C%22request%22%3Afalse%2C%22calling_node%22%3Afalse%2C%22edges%22%3Afalse%2C%22metadata_evaluation_metric_names%22%3Afalse%2C%22metadata_event_type%22%3Afalse%2C%22metadata_0%22%3Afalse%2C%22metadata_calling_node%22%3Afalse%2C%22metadata_edges%22%3Afalse%2C%22metadata_root_id%22%3Afalse%7D&filter=%7B%22filter_field%22%3A%22meta_data%22%2C%22filter_operator%22%3A%22equals%22%2C%22filter_key%22%3A%22root_id%22%2C%22filter_value%22%3A%22{request_id_str}%22%7D&page=1&page_size=50&time_filter=1m\"#\n );\n println!(\"===========================================\\nRequest ID: {}\\nParea AI: {}\\n===========================================\", request_id.to_string(), parea_url);\n\n // check this\n let _editor_url = \"http://localhost:42427\".to_owned();\n let anthropic_api_keys = LLMProviderAPIKeys::Anthropic(AnthropicAPIKey::new(\"\".to_owned()));\n let anthropic_llm_properties = LLMProperties::new(\n LLMType::ClaudeSonnet,\n LLMProvider::Anthropic,\n anthropic_api_keys.clone(),\n );\n let _llama_70b_properties = LLMProperties::new(\n LLMType::Llama3_1_70bInstruct,\n LLMProvider::FireworksAI,\n LLMProviderAPIKeys::FireworksAI(FireworksAPIKey::new(\"\".to_owned())),\n );\n let _google_ai_studio_api_keys =\n LLMProviderAPIKeys::GoogleAIStudio(GoogleAIStudioKey::new(\"\".to_owned()));\n let editor_parsing = Arc::new(EditorParsing::default());\n let symbol_broker = Arc::new(SymbolTrackerInline::new(editor_parsing.clone()));\n let llm_broker = LLMBroker::new(LLMBrokerConfiguration::new(default_index_dir()))\n .await\n .expect(\"to initialize properly\");\n\n let _llm_broker_clone = LLMBroker::new(LLMBrokerConfiguration::new(default_index_dir()))\n .await\n .expect(\"to initialize properly\");\n\n let tool_broker = Arc::new(ToolBroker::new(\n Arc::new(llm_broker),\n Arc::new(CodeEditBroker::new()),\n symbol_broker.clone(),\n Arc::new(TSLanguageParsing::init()),\n // for our testing workflow we want to apply the edits directly\n ToolBrokerConfiguration::new(None, true),\n LLMProperties::new(\n LLMType::Gpt4O,\n LLMProvider::OpenAI,\n LLMProviderAPIKeys::OpenAI(OpenAIProvider::new(\"\".to_owned())),\n ), // LLMProperties::new(\n // LLMType::GeminiPro,\n // LLMProvider::GoogleAIStudio,\n // LLMProviderAPIKeys::GoogleAIStudio(GoogleAIStudioKey::new(\n // \"\".to_owned(),\n // )),\n // ),\n ));\n\n let _user_context = UserContext::new(vec![], vec![], None, vec![]);\n\n let (sender, mut _receiver) = tokio::sync::mpsc::unbounded_channel();\n\n // fill this\n let _access_token = String::from(\"\");\n\n // let message_properties = SymbolEventMessageProperties::new(\n // SymbolEventRequestId::new(\"\".to_owned(), \"\".to_owned()),\n // sender.clone(),\n // editor_url.to_owned(),\n // tokio_util::sync::CancellationToken::new(),\n // access_token,\n // );\n\n let test_command = \"ls\".to_owned();\n\n let session_id = \"14b55c44-fab8-4a23-a598-94b3295dc574\".to_owned();\n let exchange_id = \"14b55c44-fab8-4a23-a598-94b3295dc574\".to_owned();\n\n let ui_event_with_id = UIEventWithID::terminal_command(\n session_id.clone(),\n exchange_id.clone(),\n test_command.clone(),\n );\n // Send the event\n let res = sender.send(ui_event_with_id);\n\n dbg!(&res);\n\n let _ = _receiver.recv().await;\n\n // Process received events from the receiver\n // while let Some(event) = _receiver.recv().await {\n // match event {\n // UIEventWithID::TerminalCommand {\n // session_id: _,\n // exchange_id: _,\n // command,\n // } => {\n // println!(\"Received terminal command: {}\", command);\n // // Handle the terminal command here\n // }\n // _ => {\n // // Handle other event types if needed\n // }\n // }\n // }\n\n let _symbol_manager = SymbolManager::new(\n tool_broker.clone(),\n symbol_broker.clone(),\n editor_parsing,\n anthropic_llm_properties.clone(),\n );\n}\n\n", - "cache_control": null - } - ], - "tool_call_id": "toolu_01HUzZRuHzSNF6GztEzi2LDF", - "name": "read_file" - } - ], - "tools": [ - { - "type": "function", - "function": { - "description": "Request to list files and directories within the specified directory.\nIf recursive is true, it will list all files and directories recursively.\nIf recursive is false, it will only list the top-level contents.\nDo not use this tool to confirm the existence of files you may have created, as the user will let you know if the files were created successfully or not.", - "name": "list_files", - "parameters": { - "properties": { - "directory_path": { - "description": "(required) The absolute path of the directory to list contents for.", - "type": "string" - }, - "recursive": { - "description": "(required) Whether to list files recursively. Use true for recursive listing, false for top-level only.", - "type": "boolean" - } - }, - "required": [ - "directory_path", - "recursive" - ], - "type": "object" - } - } - }, - { - "type": "function", - "function": { - "description": "Request to perform a regex search across files in a specified directory, providing context-rich results.\nThis tool searches for patterns or specific content across multiple files, displaying each match with encapsulating context.", - "name": "search_files", - "parameters": { - "properties": { - "directory_path": { - "description": "(required) The absolute path of the directory to search in. This directory will be recursively searched.", - "type": "string" - }, - "file_pattern": { - "description": "(optional) Glob pattern to filter files (e.g., '*.ts' for TypeScript files). If not provided, it will search all files (*).", - "type": "string" - }, - "regex_pattern": { - "description": "(required) The regular expression pattern to search for. Uses Rust regex syntax.", - "type": "string" - } - }, - "required": [ - "directory_path", - "regex_pattern" - ], - "type": "object" - } - } - }, - { - "type": "function", - "function": { - "description": "Request to read the full contents of a file at the specified path.\nUse this when you need to examine the full content of an existing file you do not know the contents of, for example to analyze code, review text files, or extract information from configuration files.\nMay not be suitable for other types of binary files, as it returns the raw content as a string", - "name": "read_file", - "parameters": { - "properties": { - "fs_file_path": { - "description": "(required) The relative path of the file to read.", - "type": "string" - } - }, - "required": [ - "fs_file_path" - ], - "type": "object" - } - } - }, - { - "type": "function", - "function": { - "description": "Use this when you have resolved the Github Issue and solved it completely or you have enough evidence to suggest that the Github Issue has been resolved after your changes.", - "name": "attempt_completion", - "parameters": { - "properties": { - "result": { - "description": "(required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance.", - "type": "string" - } - }, - "required": [ - "result" - ], - "type": "object" - } - } - }, - { - "type": "function", - "function": { - "description": "Request to execute a CLI command on the system. Commands will be executed in the current working directory.", - "name": "execute_command", - "parameters": { - "properties": { - "command": { - "description": "(required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.", - "type": "string" - } - }, - "required": [ - "command" - ], - "type": "object" - } - } - } - ], - "stream": true -} \ No newline at end of file