Skip to content
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
26 changes: 26 additions & 0 deletions docs/bashrc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# What bashrc need to be for OSC 333

```

# --- OSC 333 marks for the multiplexer ---
_osc333_preexec() {
[[ -n "$_osc333_in_cmd" ]] && return
printf '\e]333;C\a'
_osc333_in_cmd=1
}

_osc333_postexec() {
local ec=$?
printf '\e]333;D;%d\a' "$ec"
unset _osc333_in_cmd
}

trap '_osc333_preexec' DEBUG # «pre‑exec»
PROMPT_COMMAND='_osc333_postexec' # «post‑exec»

PS1='\[\e]333;A\a\]\u@\h:\w\$ \[\e]333;B\a\]'
PS2='\[\e]333;A\a\]> \[\e]333;B\a\]'
PS3='\[\e]333;A\a\]#? \[\e]333;B\a\]'
```

description of a standart - https://gitlab.freedesktop.org/Per_Bothner/specifications/-/blob/master/proposals/semantic-prompts.md
12 changes: 12 additions & 0 deletions docs/terminal_multiplexer_handle_input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## How `bash` window is working in `terminal_multiplexer.cpp`

- Method `init` initialize two PTY's for agent and bash windows
- Methods from `refresh_cursor` to `resize` (lines 30-37 in `terminal_multiplexer.hpp`) are technical
- Method `run_terminal` creates an epoll instance and fill it with `STDIN`, screens PTY's and fd for window resize. After this it goes to infinite cycle for waiting this fd's.

### Then `STDIN` was called

- Symbols handles by `handle_input()` method for special symbols like `CTRL + B` and if it is just a letter, it writes this to fd of bash screen
- Then method `handle_screen_output(Screen &screen, const int fd)` starts working, because it handles everything that needs to print on a screen(including bash screen)
- Method `handle_screen_output(Screen &screen, const int fd)` also can be called from epolling cycle by bash command output
- This method reads all symbols from given `fd` and sends it to `screen's` method `handle_char(const TerminalChar &tch)` to show it on a screen
18 changes: 8 additions & 10 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,22 @@

PROJECT_DIR="tui-tux"
DEPENDENCIES=(
"libncurses5-dev"
"libncursesw5-dev"
"libreadline-dev"
"libcurl4-openssl-dev"
"ncurses"
"readline"
"curl"
)

JSON_DIR="tui-tux/nlohmann"
RUN_TESTS=false

is_package_installed() {
dpkg -s "$1" &> /dev/null
pacman -Qi "$1" &> /dev/null
return $?
}

install_package() {
echo "Installing $1..."
sudo apt-get update -qq
sudo apt-get install -y "$1"
sudo pacman -S --noconfirm --needed "$1"
}

if ! [ -f "$JSON_DIR/json.hpp" ]; then
Expand All @@ -39,9 +37,9 @@ fi
for arg in "$@"; do
case $arg in
-t|--test)
RUN_TESTS=true
shift
;;
RUN_TESTS=true
shift
;;
esac
done

Expand Down
6 changes: 3 additions & 3 deletions tui-tux/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ TARGET := ishell
TEST_TARGET := test_ishell

# Configurable
NO_MAIN_SOURCES := screen.cpp escape.cpp agency_manager.cpp command_manager.cpp bookmark_manager.cpp agent.cpp terminal_multiplexer.cpp agency_request_wrapper.cpp https_client.cpp utils.cpp
NO_MAIN_SOURCES := screen.cpp escape.cpp agency_manager.cpp command_manager.cpp bookmark_manager.cpp agent.cpp terminal_multiplexer.cpp agency_request_wrapper.cpp https_client.cpp utils.cpp session_tracker.cpp markdown_manager.cpp
SOURCES := $(NO_MAIN_SOURCES) main.cpp

TEST_SOURCES := test_bookmark_manager.cpp test_agency_request_wrapper.cpp test_https_client.cpp test_escape.cpp test_agency_manager.cpp test_terminal_multiplexer.cpp test_command_manager.cpp
FLAGS := -Wall
LIBS := -lncurses -lreadline -lcurl
LIBS := -lncurses -lreadline -lcurl -lsqlite3
TEST_EXTRA_LIBS := -lgtest -lgmock -L/usr/local/lib -lgtest_main -lpthread

NO_MAIN_OBJECTS := $(patsubst %.cpp,%.o,$(patsubst %, bin/%, $(NO_MAIN_SOURCES)))
Expand All @@ -20,7 +20,7 @@ TEST_SOURCES := $(patsubst %, test/%, $(TEST_SOURCES))

INCLUDE := -Iinclude

CXXFLAGS := $(FLAGS) -std=c++17 -g
CXXFLAGS := $(FLAGS) -std=c++17 -g3

Cxx := g++

Expand Down
5 changes: 1 addition & 4 deletions tui-tux/include/agency_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class AgencyManager {
virtual ~AgencyManager();

std::string get_agency_url();
virtual std::string execute_query(const std::string &endpoint, const std::string &query);
virtual std::string execute_query(const std::string &endpoint, std::string query, bool include_session_history);

[[nodiscard]] virtual std::string get_agent_name() const;
virtual void set_agent_name(const std::string &agent_name);
Expand All @@ -21,9 +21,6 @@ class AgencyManager {
std::string agent_name = "assistant";

AgencyRequestWrapper* request_wrapper;

// <query, result>
std::vector<std::pair<std::string, std::string>> session_history;
};

#endif // AGENCY_HPP
10 changes: 7 additions & 3 deletions tui-tux/include/agency_request_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@ class AgencyRequestWrapper {
virtual std::string get_ssh_ip();
virtual int get_ssh_port();
virtual std::string get_ssh_user();
json send_request_to_agent_server(const std::string &url, const std::string &user_query, std::vector<std::pair<std::string, std::string>> &session_history);
json send_request_to_agent_server(const std::string &url, std::string user_query, bool include_session_history);

static std::string get_session_history_string();

virtual std::string ask_agent(const std::string &url, std::string user_query, bool include_session_history);

static std::string get_session_history_string(std::vector<std::pair<std::string, std::string>> &session_history);
virtual std::string ask_agent(const std::string &url, const std::string &user_query, std::vector<std::pair<std::string, std::string>> &session_history);
virtual json make_http_request(HttpRequestType request_type, const std::string& url,
const std::map<std::string, std::string>& query_params,
const json& body,
const std::map<std::string, std::string>& headers);
virtual char *getenv(const char *key);

std::vector<std::string> context;
};

#endif // AGENCY_REQUEST_WRAPPER_HPP
9 changes: 5 additions & 4 deletions tui-tux/include/bookmark_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <unordered_map>
#include <string>
#include <utility>
#include <optional>
#include "../nlohmann/json.hpp"
#include <agency_manager.hpp>

Expand All @@ -17,7 +18,9 @@ class BookmarkManager {
explicit BookmarkManager(AgencyManager *agency_manager);
virtual ~BookmarkManager();

virtual std::string get_bookmarks_file_path();
// virtual std::string get_bookmarks_file_path();

std::unordered_map<std::string, std::pair<std::string, std::string>> bookmarks;

virtual void load_bookmarks(const std::string &filename);
virtual void save_bookmarks(const std::string &filename);
Expand All @@ -27,9 +30,7 @@ class BookmarkManager {

virtual void list_bookmarks() const;
virtual void remove_bookmark(const std::string &alias);
virtual void bookmark(int index, const std::string &alias);

std::unordered_map<std::string, std::pair<std::string, std::string>> bookmarks;
virtual void bookmark(int first, int last, const std::string& alias);

virtual bool create_bookmarks_file(const std::string &filename);
virtual void parse_bookmark_json(const json &bookmark);
Expand Down
10 changes: 8 additions & 2 deletions tui-tux/include/command_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,34 @@
#include <string>

#include "bookmark_manager.hpp"
#include "markdown_manager.hpp"

using json = nlohmann::json;

class CommandManager {
public:
virtual ~CommandManager() = default;

explicit CommandManager(BookmarkManager *bookmark_manager);
explicit CommandManager(BookmarkManager *bookmark_manager, MarkdownManager *markdown_manager);

void run_command(std::string &command);
virtual void run_alias(std::string &alias);

void clear(const std::vector<std::string> &args);
void bookmark(const std::vector<std::string> &args);
void agent_switch(const std::vector<std::string> &args);
void markdown(const std::vector<std::string> &args);

virtual int read_from_file(std::string &filepath, std::string &output);

BookmarkManager *bookmark_manager;
MarkdownManager *markdown_manager;

std::unordered_map<std::string, void (CommandManager::*)(const std::vector<std::string>&)> command_map = {
{"bookmark", &CommandManager::bookmark},
{"clear", &CommandManager::clear},
{"switch", &CommandManager::agent_switch}
{"switch", &CommandManager::agent_switch},
{"markdown", &CommandManager::markdown}
};
};

Expand Down
6 changes: 6 additions & 0 deletions tui-tux/include/escape.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
// Insert character
#define E_KEY_ICH 266

// ────────── OSC 133 (semantic prompt marks) ──────────
#define E_OSC_PROMPT_START 512 // 333;A
#define E_OSC_PROMPT_END 513 // 333;B
#define E_OSC_PRE_EXEC 514 // 333;C
#define E_OSC_CMD_FINISH 515 // 333;D;<exit>

struct TerminalChar {
int ch;
std::vector<int> args;
Expand Down
42 changes: 42 additions & 0 deletions tui-tux/include/markdown_manager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef MARKDOWN_MANAGER_HPP
#define MARKDOWN_MANAGER_HPP

#include <unordered_map>
#include <string>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <cstdlib>
#include <sys/stat.h>
#include "../nlohmann/json.hpp"
#include "bookmark_manager.hpp"
#include "agency_manager.hpp"

using json = nlohmann::json;

class MarkdownManager {

public:
explicit MarkdownManager();
virtual ~MarkdownManager();

virtual bool create_markdowns_file(const std::string &filename);
virtual void parse_markdown_json(const json &markdown);

virtual void load_markdowns(const std::string &filename);
virtual void save_markdowns(const std::string &filename);

virtual bool is_markdown(const std::string &bookmark) const;
virtual std::pair<std::string, std::string> get_markdown(const std::string &bookmark) const;

virtual void markdown(const std::pair<std::string, std::string>& protocol); // create markdown from bookmark with "default" group
virtual void list_markdowns() const; // list markdowns "markdown -l"
virtual void remove_markdown(const std::string &bookmark); // remove markdown "markdown -r"
virtual void add_to_group(const std::string &group, const std::string &bookmark); // change markdown's group
virtual std::vector<std::string> get_by_group(const std::string &group); // give LLM context of this group
virtual bool save_as_file(const std::string& bookmark); // save markdown as <bookmark>.md

std::unordered_map<std::string, std::pair<std::string, std::string>> markdowns; // <bookmark> [<group, protocol>]
};

#endif //MARKDOWN_MANAGER_HPP
2 changes: 2 additions & 0 deletions tui-tux/include/screen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class Screen {
int waddch(WINDOW *window, chtype ch);
int winsch(WINDOW *window, chtype ch);
int wmove(WINDOW *window, int y, int x);

std::string get_line(int line_num);
};

#endif
63 changes: 63 additions & 0 deletions tui-tux/include/session_tracker.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#ifndef SESSION_TRACKER_HPP
#define SESSION_TRACKER_HPP

#include <string>
#include <vector>
#include <sqlite3.h>

class SessionTracker {
public:
enum class EventType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments?

ShellCommand,
SystemCommand,
Unknown
};

struct ShellCmd {
int interaction_id;
std::string command;
std::string output;
std::string execution_start;
std::string execution_end;
int exit_code;
};

struct Interaction {
int interaction_id;
std::string timestamp;
std::string question;
std::string answer;
std::vector<ShellCmd> shell;
};

static SessionTracker& get();

void startSession();
void endSession();

void logAgentInteraction(const std::string& question, const std::string& response);

void addNewCommand(EventType command_type);
void appendCommandText(const std::string& text);
void setCommandOutput(const std::string& output);
void setExitCode(int exit_code);

const std::vector<Interaction>& get_history() const;

private:
SessionTracker();
~SessionTracker();

SessionTracker(const SessionTracker&) = delete;
SessionTracker& operator=(const SessionTracker&) = delete;

void openLogFile();

sqlite3 *db;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to use some prefix for members

int sessionDbId;
int lastCommandId;

mutable std::vector<Interaction> history;
};

#endif // SESSION_TRACKER_HPP
9 changes: 8 additions & 1 deletion tui-tux/include/terminal_multiplexer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,20 @@ class TerminalMultiplexer {
void send_dims();
void resize();
void run_terminal();
int handle_screen_output(Screen &screen, int fd) const;
int handle_screen_output(Screen &screen, int fd);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done it because i want to call non-const method to collect command output and change variable last_command_finished

int handle_input();

static void handle_pty_input(int fd, char ch);
void zoom_in();
void zoom_out();
void toggle_manual_scroll();

/* ────────── OSC 133 state (bash‑экран) ────────── */
bool bash_capturing = false;
bool bash_waiting_for_prompt = true;
std::string bash_output;
int last_command_line = -10;
int first_command_line = -10;
};

#endif
5 changes: 3 additions & 2 deletions tui-tux/include/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
#include <string>
#include <vector>

std::vector<std::string> split(std::string &str, char delim, bool ignore_empty);
std::vector<std::string> split(const std::string &str, char delim, bool ignore_empty);
std::string join(std::vector<std::string> &words, char delim);
bool is_range_token(const std::string& s);

#define DEFAULT_AGENCY_URL "https://ishell-stage.csai.site/agents"
#define DEFAULT_AGENCY_URL "http://142.93.231.126:5000/agents"
#define DEFAULT_ISHELL_LOCAL_DIR "/etc/ishell"

#endif
Loading