Skip to content
This repository was archived by the owner on Feb 21, 2025. It is now read-only.

Isolation for self configure #509

Merged
merged 20 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ece3c42
fix: only sync .config folder, no need to sync .cache anymore
humbertoyusta Dec 16, 2024
2ca2ed8
feat: reuse cache using cargo chef to build dev container
humbertoyusta Dec 17, 2024
9329a83
feat: add handler to prepend system prompt and maybe more initial mes…
humbertoyusta Dec 18, 2024
53c3a81
feat: prepend system prompt from remote if needed
humbertoyusta Dec 18, 2024
f6f0a40
fix: system prompt goes to the front when it is streamed (like chat-j…
humbertoyusta Dec 18, 2024
805b0e4
feat: add handler to run at commands, and rename run_at_commands to r…
humbertoyusta Dec 19, 2024
bdf35a3
feat: execute at commands remotely
humbertoyusta Dec 19, 2024
afcd142
revert: fixes of prepending system prompt manually
humbertoyusta Dec 19, 2024
63d04c9
fix: only load integrations in isolation when isolated is true
humbertoyusta Dec 23, 2024
cbc6637
feat: copy integrations yaml if specified, to the container, refactor…
humbertoyusta Dec 23, 2024
1eff6c1
feat: add network to isolation config to run container in a specific …
humbertoyusta Dec 23, 2024
bfb8f83
feat: allow variables yaml to be specified to lsp like integrations
humbertoyusta Dec 24, 2024
2875b4b
feat: add chrome dockerfile
humbertoyusta Dec 24, 2024
6a0969a
feat: add support to get dynamic ws_url in chrome
humbertoyusta Dec 26, 2024
de0e309
fix: increase waiting timeout for lsp to stop (docker containers may …
humbertoyusta Dec 26, 2024
a84d451
fix: chrome container using nginx for redirects and supervisord to ru…
humbertoyusta Dec 26, 2024
6a93ada
fix: update url to not be localhost, but container instead
humbertoyusta Dec 26, 2024
2d6b5c9
refactor: improve code to get ws url from chrome, adapting it for con…
humbertoyusta Dec 27, 2024
3c41c6e
fix: replace localhost with container name if needed to make chrome t…
humbertoyusta Dec 27, 2024
f3cb60d
fix: remove huge info messages from logs
humbertoyusta Jan 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions docker/chrome/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM debian:bookworm

RUN apt-get update && apt-get install -y \
wget \
gnupg \
apt-transport-https \
curl \
nginx \
supervisor \
&& rm -rf /var/lib/apt/lists/*

RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - && \
sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list' && \
apt-get update && apt-get install -y google-chrome-stable \
&& rm -rf /var/lib/apt/lists/*

ENV CHROME_BIN=/usr/bin/google-chrome \
CHROME_PATH=/opt/google/chrome/ \
XDG_RUNTIME_DIR=/tmp/xdg-runtime-dir

RUN mkdir -p /tmp/xdg-runtime-dir && chmod 700 /tmp/xdg-runtime-dir

EXPOSE 9222

COPY nginx.conf /etc/nginx/nginx.conf

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

ENTRYPOINT ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
24 changes: 24 additions & 0 deletions docker/chrome/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
worker_processes auto;

events {
worker_connections 4096;
}

http {
server {
listen 9222;

location / {
proxy_pass http://127.0.0.1:9223;
proxy_set_header Host 127.0.0.1:9223;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
}
16 changes: 16 additions & 0 deletions docker/chrome/supervisord.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[supervisord]
nodaemon=true

[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr

[program:chrome]
command=/opt/google/chrome/chrome --headless --no-sandbox --disable-gpu --disable-software-rasterizer --remote-debugging-port=9223
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr
30 changes: 12 additions & 18 deletions docker/lsp-debug.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,29 @@
# This dockerfile can be used to compile refact-lsp for development purposes,
# for example, to get refact-lsp to bind into docker containers to start threads in containers

FROM alpine:3.18
FROM lukemathwalker/cargo-chef:latest-rust-alpine3.21 AS chef

FROM chef AS planner
WORKDIR /refact-lsp
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS builder
WORKDIR /refact-lsp
COPY --from=planner /refact-lsp/recipe.json recipe.json

RUN apk add --no-cache \
build-base \
curl \
git \
openssl-dev \
openssl-libs-static \
pkgconfig \
protobuf-dev \
zlib-static

RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH=/root/.cargo/bin:$PATH

WORKDIR /refact-lsp

COPY Cargo.toml build.rs ./

RUN mkdir src && echo 'fn main() { println!("Dummy main to satisfy Cargo"); }' > src/main.rs

RUN cargo fetch
RUN cargo check

RUN rm -rf src
RUN cargo chef cook --recipe-path recipe.json

COPY . .

RUN cargo build

RUN mkdir -p /output && cp target/debug/refact-lsp /output/

RUN mkdir -p /output && cp target/debug/refact-lsp /output/
2 changes: 1 addition & 1 deletion python_binding_and_cmdline/refact/lsp_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ async def _stop_real(self):
try:
self._refact_lsp_process.terminate()
try:
await asyncio.wait_for(self._refact_lsp_process.wait(), timeout=5.0)
await asyncio.wait_for(self._refact_lsp_process.wait(), timeout=30.0)
except asyncio.TimeoutError:
print("LSP server did not terminate in time, forcefully killing")
self._refact_lsp_process.kill()
Expand Down
46 changes: 45 additions & 1 deletion src/at_commands/execute_at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ use tracing::{info, warn};

use crate::at_commands::at_commands::{AtCommandsContext, AtParam, filter_only_context_file_from_context_tool};
use crate::call_validation::{ChatContent, ChatMessage, ContextEnum};
use crate::http::http_post_json;
use crate::http::routers::v1::at_commands::{CommandExecutePost, CommandExecuteResponse};
use crate::integrations::docker::docker_container_manager::docker_container_get_host_lsp_port_to_connect;
use crate::postprocessing::pp_context_files::postprocess_context_files;
use crate::postprocessing::pp_plain_text::postprocess_plain_text;
use crate::scratchpads::scratchpad_utils::{HasRagResults, max_tokens_for_rag_chat};
Expand All @@ -15,7 +18,7 @@ use crate::scratchpads::scratchpad_utils::{HasRagResults, max_tokens_for_rag_cha
pub const MIN_RAG_CONTEXT_LIMIT: usize = 256;


pub async fn run_at_commands(
pub async fn run_at_commands_locally(
ccx: Arc<AMutex<AtCommandsContext>>,
tokenizer: Arc<RwLock<Tokenizer>>,
maxgen: usize,
Expand Down Expand Up @@ -162,6 +165,47 @@ pub async fn run_at_commands(
return (rebuilt_messages.clone(), user_msg_starts, any_context_produced)
}

pub async fn run_at_commands_remotely(
ccx: Arc<AMutex<AtCommandsContext>>,
model_name: &str,
maxgen: usize,
original_messages: &Vec<ChatMessage>,
stream_back_to_user: &mut HasRagResults,
) -> Result<(Vec<ChatMessage>, usize, bool), String> {
let (gcx, n_ctx, subchat_tool_parameters, postprocess_parameters, chat_id) = {
let ccx_locked = ccx.lock().await;
(
ccx_locked.global_context.clone(),
ccx_locked.n_ctx,
ccx_locked.subchat_tool_parameters.clone(),
ccx_locked.postprocess_parameters.clone(),
ccx_locked.chat_id.clone()
)
};

let post = CommandExecutePost {
messages: original_messages.clone(),
n_ctx,
maxgen,
subchat_tool_parameters,
postprocess_parameters,
model_name: model_name.to_string(),
chat_id: chat_id.clone(),
};

let port = docker_container_get_host_lsp_port_to_connect(gcx.clone(), &chat_id).await?;
tracing::info!("run_at_commands_remotely: connecting to port {}", port);

let url = format!("http://localhost:{port}/v1/at-command-execute");
let response: CommandExecuteResponse = http_post_json(&url, &post).await?;

for msg in response.messages_to_stream_back {
stream_back_to_user.push_in_json(msg);
}

Ok((response.messages, response.undroppable_msg_number, response.any_context_produced))
}

pub async fn correct_at_arg(
ccx: Arc<AMutex<AtCommandsContext>>,
param: Arc<AMutex<dyn AtParam>>,
Expand Down
3 changes: 3 additions & 0 deletions src/global_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ pub struct CommandLine {

#[structopt(long, default_value="", help="Specify the integrations.yaml, this also disables the global integrations.d")]
pub integrations_yaml: String,

#[structopt(long, default_value="", help="Specify the variables.yaml, this also disables the global variables.yaml")]
pub variables_yaml: String,
}

impl CommandLine {
Expand Down
12 changes: 7 additions & 5 deletions src/http/routers/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::global_context::SharedGlobalContext;
use crate::http::routers::v1::code_completion::{handle_v1_code_completion_web, handle_v1_code_completion_prompt};
use crate::http::routers::v1::code_lens::handle_v1_code_lens;
use crate::http::routers::v1::ast::{handle_v1_ast_file_dump, handle_v1_ast_file_symbols, handle_v1_ast_status};
use crate::http::routers::v1::at_commands::{handle_v1_command_completion, handle_v1_command_preview};
use crate::http::routers::v1::at_commands::{handle_v1_command_completion, handle_v1_command_preview, handle_v1_at_command_execute};
use crate::http::routers::v1::at_tools::{handle_v1_tools, handle_v1_tools_check_if_confirmation_needed, handle_v1_tools_execute};
use crate::http::routers::v1::caps::handle_v1_caps;
use crate::http::routers::v1::caps::handle_v1_ping;
Expand All @@ -37,7 +37,7 @@ use crate::http::routers::v1::gui_help_handlers::handle_v1_fullpath;
use crate::http::routers::v1::patch::{handle_v1_patch_apply_all, handle_v1_patch_single_file_from_ticket};
use crate::http::routers::v1::subchat::{handle_v1_subchat, handle_v1_subchat_single};
use crate::http::routers::v1::sync_files::handle_v1_sync_files_extract_tar;
use crate::http::routers::v1::system_prompt::handle_v1_system_prompt;
use crate::http::routers::v1::system_prompt::handle_v1_prepend_system_prompt_and_maybe_more_initial_messages;

#[cfg(feature="vecdb")]
use crate::http::routers::v1::vecdb::{handle_v1_vecdb_search, handle_v1_vecdb_status};
Expand All @@ -60,7 +60,7 @@ mod dashboard;
pub mod links;
pub mod lsp_like_handlers;
pub mod customization;
mod at_commands;
pub mod at_commands;
mod ast;
pub mod at_tools;
mod status;
Expand Down Expand Up @@ -97,7 +97,7 @@ pub fn make_v1_router() -> Router {

.route("/tools", telemetry_get!(handle_v1_tools))
.route("/tools-check-if-confirmation-needed", telemetry_post!(handle_v1_tools_check_if_confirmation_needed))
.route("/tools-execute", telemetry_post!(handle_v1_tools_execute))
.route("/tools-execute", telemetry_post!(handle_v1_tools_execute)) // because it works remotely

.route("/lsp-initialize", telemetry_post!(handle_v1_lsp_initialize))
.route("/lsp-did-changed", telemetry_post!(handle_v1_lsp_did_change))
Expand All @@ -118,10 +118,12 @@ pub fn make_v1_router() -> Router {

.route("/git-commit", telemetry_post!(handle_v1_git_commit))

.route("/system-prompt", telemetry_post!(handle_v1_system_prompt)) // because it works remotely
.route("/prepend-system-prompt-and-maybe-more-initial-messages",
telemetry_post!(handle_v1_prepend_system_prompt_and_maybe_more_initial_messages)) // because it works remotely

.route("/at-command-completion", telemetry_post!(handle_v1_command_completion))
.route("/at-command-preview", telemetry_post!(handle_v1_command_preview))
.route("/at-command-execute", telemetry_post!(handle_v1_at_command_execute)) // because it works remotely

.route("/fullpath", telemetry_post!(handle_v1_fullpath))

Expand Down
63 changes: 63 additions & 0 deletions src/http/routers/v1/at_commands.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use axum::response::Result;
use axum::Extension;
use hyper::{Body, Response, StatusCode};
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::sync::RwLock as StdRwLock;
Expand All @@ -12,15 +13,19 @@ use itertools::Itertools;
use tokenizers::Tokenizer;
use tracing::info;

use crate::at_commands::execute_at::run_at_commands_locally;
use crate::cached_tokenizers;
use crate::at_commands::at_commands::AtCommandsContext;
use crate::at_commands::execute_at::{execute_at_commands_in_query, parse_words_from_line};
use crate::call_validation::{PostprocessSettings, SubchatParameters};
use crate::custom_error::ScratchError;
use crate::global_context::try_load_caps_quickly_if_not_present;
use crate::global_context::GlobalContext;
use crate::call_validation::{ChatMessage, ChatContent, ContextEnum};
use crate::at_commands::at_commands::filter_only_context_file_from_context_tool;
use crate::postprocessing::pp_context_files::postprocess_context_files;
use crate::scratchpads::scratchpad_utils::max_tokens_for_rag_chat;
use crate::scratchpads::scratchpad_utils::HasRagResults;


#[derive(Serialize, Deserialize, Clone)]
Expand Down Expand Up @@ -52,6 +57,25 @@ struct Highlight {
reason: String,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct CommandExecutePost {
pub messages: Vec<ChatMessage>,
pub n_ctx: usize,
pub maxgen: usize,
pub subchat_tool_parameters: IndexMap<String, SubchatParameters>, // tool_name: {model, allowed_context, temperature}
pub postprocess_parameters: PostprocessSettings,
pub model_name: String,
pub chat_id: String,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct CommandExecuteResponse {
pub messages: Vec<ChatMessage>,
pub undroppable_msg_number: usize,
pub any_context_produced: bool,
pub messages_to_stream_back: Vec<serde_json::Value>,
}

pub async fn handle_v1_command_completion(
Extension(global_context): Extension<Arc<ARwLock<GlobalContext>>>,
body_bytes: hyper::body::Bytes,
Expand Down Expand Up @@ -203,6 +227,45 @@ pub async fn handle_v1_command_preview(
.unwrap())
}

pub async fn handle_v1_at_command_execute(
Extension(global_context): Extension<Arc<ARwLock<GlobalContext>>>,
body_bytes: hyper::body::Bytes,
) -> Result<Response<Body>, ScratchError> {
let post = serde_json::from_slice::<CommandExecutePost>(&body_bytes)
.map_err(|e| ScratchError::new(StatusCode::UNPROCESSABLE_ENTITY, format!("JSON problem: {}", e)))?;

let caps = try_load_caps_quickly_if_not_present(global_context.clone(), 0).await?;
let tokenizer = cached_tokenizers::cached_tokenizer(caps, global_context.clone(), post.model_name.clone()).await
.map_err(|e| ScratchError::new(StatusCode::INTERNAL_SERVER_ERROR, format!("Error loading tokenizer: {}", e)))?;

let mut ccx = AtCommandsContext::new(
global_context.clone(),
post.n_ctx,
crate::http::routers::v1::chat::CHAT_TOP_N,
true,
vec![],
"".to_string(),
false,
).await;
ccx.subchat_tool_parameters = post.subchat_tool_parameters.clone();
ccx.postprocess_parameters = post.postprocess_parameters.clone();
let ccx_arc = Arc::new(AMutex::new(ccx));

let mut has_rag_results = HasRagResults::new();
let (messages, undroppable_msg_number, any_context_produced) = run_at_commands_locally(
ccx_arc.clone(), tokenizer.clone(), post.maxgen, &post.messages, &mut has_rag_results).await;
let messages_to_stream_back = has_rag_results.in_json;

let response = CommandExecuteResponse {
messages, messages_to_stream_back, undroppable_msg_number, any_context_produced };

Ok(Response::builder()
.status(StatusCode::OK)
.header("Content-Type", "application/json")
.body(Body::from(serde_json::to_string_pretty(&response).unwrap()))
.unwrap())
}

fn get_line_with_cursor(query: &String, cursor: i64) -> Result<(String, i64, i64), ScratchError> {
let mut cursor_rel = cursor;
for line in query.lines() {
Expand Down
Loading