Skip to content

Fix edit docs link #675

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ export default defineConfig({
'./src/styles/index.css',
],
editLink: {
baseUrl: 'https://github.com/smallcloudai/web_docs_refact_ai/edit/main/',
baseUrl: 'https://github.com/smallcloudai/refact/edit/main/docs/',
},
lastUpdated: true,
}),
Expand Down
2 changes: 1 addition & 1 deletion refact-agent/engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ lto = true

[package]
name = "refact-lsp"
version = "0.10.16"
version = "0.10.17"
edition = "2021"
build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
16 changes: 13 additions & 3 deletions refact-agent/engine/src/http/routers/v1/at_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ pub async fn handle_v1_tools_check_if_confirmation_needed(
let tool = match all_tools.get(&tool_call.function.name) {
Some(x) => x,
None => {
return Err(ScratchError::new(StatusCode::UNPROCESSABLE_ENTITY, format!("Unknown tool: {}", tool_call.function.name)))
tracing::error!("Unknown tool: {}", tool_call.function.name);
// Not returning error here, because we don't want to stop the chat, it will fail later
// in `/chat` and provide error to the model
continue;
}
};

Expand All @@ -172,8 +175,15 @@ pub async fn handle_v1_tools_check_if_confirmation_needed(
}
};

let should_confirm = tool.match_against_confirm_deny(ccx.clone(), &args).await
.map_err(|e| { ScratchError::new(StatusCode::UNPROCESSABLE_ENTITY, e)})?;
let should_confirm = match tool.match_against_confirm_deny(ccx.clone(), &args).await {
Ok(should_confirm) => should_confirm,
Err(e) => {
tracing::error!("Error getting tool command to match: {e}");
// Not returning error here, because we don't want to stop the chat, it will fail later
// in `/chat` and provide error to the model
continue;
}
};

match should_confirm.result {
MatchConfirmDenyResult::DENY => {
Expand Down
34 changes: 34 additions & 0 deletions refact-agent/engine/src/known_models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,33 @@ pub const KNOWN_MODELS: &str = r####"
"gpt-4o-mini-2024-07-18"
]
},
"gpt-4.1": {
"n_ctx": 200000,
"supports_tools": true,
"supports_multimodality": true,
"supports_agent": true,
"supports_scratchpads": {
"PASSTHROUGH": {
}
},
"similar_models": [
"gpt-4.1-2025-04-14"
]
},
"gpt-4.1-mini": {
"n_ctx": 200000,
"supports_tools": true,
"supports_multimodality": true,
"supports_scratchpads": {
"PASSTHROUGH": {
}
},
"similar_models": [
"gpt-4.1-nano",
"gpt-4.1-mini-2025-04-14",
"gpt-4.1-nano-2025-04-14"
]
},
"chatgpt-4o": {
"n_ctx": 128000,
"supports_tools": false,
Expand Down Expand Up @@ -831,6 +858,13 @@ pub const KNOWN_MODELS: &str = r####"
"openai/gpt-4o": "Xenova/gpt-4o",
"chatgpt-4o": "Xenova/gpt-4o",

"gpt-4.1": "Xenova/gpt-4o",
"gpt-4.1-2025-04-14": "Xenova/gpt-4o",
"gpt-4.1-mini": "Xenova/gpt-4o",
"gpt-4.1-mini-2025-04-14": "Xenova/gpt-4o",
"gpt-4.1-nano": "Xenova/gpt-4o",
"gpt-4.1-nano-2025-04-14": "Xenova/gpt-4o",

"claude-3-5-sonnet": "Xenova/claude-tokenizer",
"claude-3-5-haiku": "Xenova/claude-tokenizer",
"claude-3-5-haiku-20241022": "Xenova/claude-tokenizer",
Expand Down
71 changes: 36 additions & 35 deletions refact-agent/engine/src/tools/tool_cat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,32 @@ pub struct ToolCat;
const CAT_MAX_IMAGES_CNT: usize = 1;

fn parse_cat_args(args: &HashMap<String, Value>) -> Result<(Vec<String>, HashMap<String, Option<(usize, usize)>>, Vec<String>), String> {
fn try_parse_line_range(s: &str) -> Result<Option<(usize, usize)>, String> {
let s = s.trim();

// Try parsing as a single number (like "10")
if let Ok(n) = s.parse::<usize>() {
return Ok(Some((n, n)));
}

// Try parsing as a range (like "10-20")
if s.contains('-') {
let parts = s.split('-').collect::<Vec<_>>();
if parts.len() == 2 {
if let Ok(start) = parts[0].trim().parse::<usize>() {
if let Ok(end) = parts[1].trim().parse::<usize>() {
if start > end {
return Err(format!("Start line ({}) cannot be greater than end line ({})", start, end));
}
return Ok(Some((start, end)));
}
}
}
}

Ok(None) // Not a line range - likely a Windows path
}

let raw_paths = match args.get("paths") {
Some(Value::String(s)) => {
s.split(",").map(|x|x.trim().to_string()).collect::<Vec<_>>()
Expand All @@ -37,43 +63,18 @@ fn parse_cat_args(args: &HashMap<String, Value>) -> Result<(Vec<String>, HashMap
let mut path_line_ranges = HashMap::new();

for path_str in raw_paths {
if let Some(colon_pos) = path_str.find(':') {
let (file_path, range_str) = path_str.split_at(colon_pos);
let file_path = file_path.trim().to_string();
let range_str = range_str[1..].trim(); // Remove the colon

// Parse the line range
if range_str.contains('-') {
let range_parts: Vec<&str> = range_str.split('-').collect();
if range_parts.len() == 2 {
let start = match range_parts[0].trim().parse::<usize>() {
Ok(n) => n,
Err(_) => return Err(format!("Invalid start line: {}", range_parts[0]))
};
let end = match range_parts[1].trim().parse::<usize>() {
Ok(n) => n,
Err(_) => return Err(format!("Invalid end line: {}", range_parts[1]))
};
if start > end {
return Err(format!("Start line ({}) cannot be greater than end line ({})", start, end));
}
path_line_ranges.insert(file_path.clone(), Some((start, end)));
} else {
return Err(format!("Invalid line range format: {}", range_str));
}
} else {
// Single line case
match range_str.parse::<usize>() {
Ok(n) => path_line_ranges.insert(file_path.clone(), Some((n, n))),
Err(_) => return Err(format!("Invalid line number: {}", range_str))
};
let (file_path, range) = if let Some(colon_pos) = path_str.rfind(':') {
match try_parse_line_range(&path_str[colon_pos+1..])? {
Some((start, end)) => {
(path_str[..colon_pos].trim().to_string(), Some((start, end)))
},
None => (path_str, None),
}

paths.push(file_path);
} else {
paths.push(path_str.clone());
path_line_ranges.insert(path_str, None);
}
(path_str, None)
};
path_line_ranges.insert(file_path.clone(), range);
paths.push(file_path);
}

let symbols = match args.get("symbols") {
Expand Down
20 changes: 19 additions & 1 deletion refact-agent/gui/src/app/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
setIsWaitingForResponse,
upsertToolCall,
sendCurrentChatToLspAfterToolCallUpdate,
chatResponse,
} from "../features/Chat/Thread";
import { statisticsApi } from "../services/refact/statistics";
import { integrationsApi } from "../services/refact/integrations";
Expand All @@ -38,8 +39,12 @@ import {
updateConfirmationAfterIdeToolUse,
} from "../features/ToolConfirmation/confirmationSlice";
import { setInitialAgentUsage } from "../features/AgentUsage/agentUsageSlice";
import { ideToolCallResponse } from "../hooks/useEventBusForIDE";
import {
ideToolCallResponse,
ideForceReloadProjectTreeFiles,
} from "../hooks/useEventBusForIDE";
import { upsertToolCallIntoHistory } from "../features/History/historySlice";
import { isToolResponse } from "../events";

const AUTH_ERROR_MESSAGE =
"There is an issue with your API key. Check out your API Key or re-login";
Expand Down Expand Up @@ -536,3 +541,16 @@ startListening({
}
},
});

// JB file refresh
// TBD: this could include diff messages to
startListening({
actionCreator: chatResponse,
effect: (action, listenerApi) => {
const state = listenerApi.getState();
if (state.config.host !== "jetbrains") return;
if (!isToolResponse(action.payload)) return;
if (!window.postIntellijMessage) return;
window.postIntellijMessage(ideForceReloadProjectTreeFiles());
},
});
7 changes: 2 additions & 5 deletions refact-agent/gui/src/components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
useGetCapsQuery,
useCapsForToolUse,
useAgentUsage,
useLastSentCompressionStop,
} from "../../hooks";
import { type Config } from "../../features/Config/configSlice";
import {
Expand Down Expand Up @@ -54,7 +53,6 @@ export const Chat: React.FC<ChatProps> = ({
const { submit, abort, retryFromIndex } = useSendChatRequest();

const chatToolUse = useAppSelector(getSelectedToolUse);
const compressionStop = useLastSentCompressionStop();
const threadNewChatSuggested = useAppSelector(selectThreadNewChatSuggested);
const messages = useAppSelector(selectMessages);
const capsForToolUse = useCapsForToolUse();
Expand Down Expand Up @@ -106,9 +104,8 @@ export const Chat: React.FC<ChatProps> = ({
<AgentUsage />
<SuggestNewChat
shouldBeVisible={
compressionStop.stopped ||
(threadNewChatSuggested.wasSuggested &&
!threadNewChatSuggested.wasRejectedByUser)
threadNewChatSuggested.wasSuggested &&
!threadNewChatSuggested.wasRejectedByUser
}
/>
{!isStreaming && preventSend && unCalledTools && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { popBackTo, push } from "../../../features/Pages/pagesSlice";
import { telemetryApi } from "../../../services/refact";
import {
enableSend,
newChatAction,
selectChatId,
setIsNewChatSuggestionRejected,
Expand Down Expand Up @@ -64,6 +65,7 @@ export const SuggestNewChat = ({

const handleClose = () => {
dispatch(setIsNewChatSuggestionRejected({ chatId, value: true }));
dispatch(enableSend({ id: chatId }));

void sendTelemetryEvent({
scope: `dismissedNewChatSuggestionWarning`,
Expand Down
5 changes: 4 additions & 1 deletion refact-agent/gui/src/components/Tour/TourEnd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ export const TourEnd = () => {
<Text>
-{" "}
<Link
style={{ color: "black", textDecoration: "underline" }}
style={{
color: appearance === "light" ? "white" : "black",
textDecoration: "underline",
}}
onClick={() => openUrl("https://docs.refact.ai")}
>
Check out our documentation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
selectIsStreaming,
selectIsWaiting,
selectMessages,
// selectLastSentCompression,
} from "../../features/Chat";
import { useAppSelector, useLastSentCompressionStop } from "../../hooks";
import {
Expand Down Expand Up @@ -33,19 +32,17 @@ export function useUsageCounter() {
}, [currentThreadUsage]);

const isOverflown = useMemo(() => {
if (!compressionStop.stopped) return false;
if (compressionStop.strength === "low") return true;
if (compressionStop.strength === "medium") return true;
if (compressionStop.strength === "high") return true;
return false;
}, [compressionStop.stopped, compressionStop.strength]);
}, [compressionStop.strength]);

const isWarning = useMemo(() => {
if (!compressionStop.stopped) return false;
if (compressionStop.strength === "medium") return true;
if (compressionStop.strength === "high") return true;
return false;
}, [compressionStop.stopped, compressionStop.strength]);
}, [compressionStop.strength]);

const shouldShow = useMemo(() => {
return messages.length > 0 && !isStreaming && !isWaiting;
Expand Down
14 changes: 3 additions & 11 deletions refact-agent/gui/src/features/Chat/Thread/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import {
setIsNewChatSuggestionRejected,
upsertToolCall,
setIncreaseMaxTokens,
setThreadPaused,
} from "./actions";
import { formatChatResponse } from "./utils";
import {
Expand Down Expand Up @@ -79,7 +78,6 @@ const createChatThread = (
boost_reasoning: false,
automatic_patch: false,
increase_max_tokens: false,
paused: false,
};
return chat;
};
Expand Down Expand Up @@ -209,7 +207,7 @@ export const chatReducer = createReducer(initialState, (builder) => {
action.payload.compression_strength !== "absent"
) {
state.thread.new_chat_suggested = {
...state.thread.new_chat_suggested,
wasRejectedByUser: false,
wasSuggested: true,
};
}
Expand Down Expand Up @@ -243,15 +241,14 @@ export const chatReducer = createReducer(initialState, (builder) => {

builder.addCase(setIsNewChatSuggested, (state, action) => {
if (state.thread.id !== action.payload.chatId) return state;
state.thread.paused = true;
state.thread.new_chat_suggested = {
wasSuggested: action.payload.value,
};
});

builder.addCase(setIsNewChatSuggestionRejected, (state, action) => {
if (state.thread.id !== action.payload.chatId) return state;
state.thread.paused = false;
state.prevent_send = false;
state.thread.new_chat_suggested = {
...state.thread.new_chat_suggested,
wasRejectedByUser: action.payload.value,
Expand Down Expand Up @@ -279,7 +276,6 @@ export const chatReducer = createReducer(initialState, (builder) => {
state.streaming = true;
state.thread.read = false;
state.prevent_send = false;
state.thread.paused = false;
});

builder.addCase(removeChatFromCache, (state, action) => {
Expand Down Expand Up @@ -337,7 +333,7 @@ export const chatReducer = createReducer(initialState, (builder) => {
lastUserMessage.compression_strength !== "absent"
) {
state.thread.new_chat_suggested = {
...state.thread.new_chat_suggested,
wasRejectedByUser: false,
wasSuggested: true,
};
}
Expand Down Expand Up @@ -427,10 +423,6 @@ export const chatReducer = createReducer(initialState, (builder) => {
state.thread.increase_max_tokens = action.payload;
});

builder.addCase(setThreadPaused, (state, action) => {
state.thread.paused = action.payload;
});

builder.addMatcher(
capsApi.endpoints.getCaps.matchFulfilled,
(state, action) => {
Expand Down
5 changes: 0 additions & 5 deletions refact-agent/gui/src/features/Chat/Thread/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,3 @@ export const selectLastSentCompression = createSelector(
return lastCompression;
},
);

export const selectThreadPaused = createSelector(
selectThread,
(thread) => thread.paused ?? false,
);
1 change: 0 additions & 1 deletion refact-agent/gui/src/features/Chat/Thread/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export type ChatThread = {
currentMaximumContextTokens?: number;
currentMessageContextTokens?: number;
increase_max_tokens?: boolean;
paused?: boolean;
};

export type SuggestedChat = {
Expand Down
Loading