Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
104 changes: 19 additions & 85 deletions src/clice.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,30 @@
#include <print>
#include <string>

#include "server/master_server.h"
#include "server/stateful_worker.h"
#include "server/stateless_worker.h"
#include "server/service/master_server.h"
#include "server/worker/stateful_worker.h"
#include "server/worker/stateless_worker.h"
#include "support/logging.h"

#include "kota/async/async.h"
#include "kota/deco/deco.h"
#include "kota/ipc/codec/json.h"
#include "kota/ipc/peer.h"
#include "kota/ipc/recording_transport.h"
#include "kota/ipc/transport.h"

namespace clice {

using kota::deco::decl::KVStyle;

struct Options {
DecoKV(style = KVStyle::JoinedOrSeparate,
help = "Running mode: pipe, socket, stateless-worker, stateful-worker",
help = "Running mode: pipe, socket, agentic, stateless-worker, stateful-worker",
required = false)
<std::string> mode;

DecoKV(style = KVStyle::JoinedOrSeparate, help = "Socket mode address", required = false)
<std::string> host = "127.0.0.1";

DecoKV(style = KVStyle::JoinedOrSeparate, help = "Socket mode port", required = false)
<int> port = 50051;
DecoKV(style = KVStyle::JoinedOrSeparate,
help = "Agentic TCP port (0 = disabled)",
required = false)
<int> port = 0;

DecoKV(style = KVStyle::JoinedOrSeparate,
names = {"--log-level", "--log-level="},
Expand Down Expand Up @@ -68,9 +65,6 @@ struct Options {

int main(int argc, const char** argv) {
#ifndef _WIN32
// On POSIX systems, ignore SIGPIPE so that writing to a closed pipe
// (e.g. when the LSP client disconnects) returns EPIPE instead of
// killing the process. This is standard practice for pipe-based servers.
signal(SIGPIPE, SIG_IGN);
#endif

Expand Down Expand Up @@ -110,8 +104,6 @@ int main(int argc, const char** argv) {
return 1;
}

std::string self_path = argv[0];

auto& mode = *opts.mode;

auto worker_name = opts.worker_name.value_or("");
Expand All @@ -131,77 +123,19 @@ int main(int argc, const char** argv) {
log_dir);
}

if(mode == "pipe") {
clice::logging::stderr_logger("master", clice::logging::options);

kota::event_loop loop;

auto transport = kota::ipc::StreamTransport::open_stdio(loop);
if(!transport) {
LOG_ERROR("failed to open stdio transport");
return 1;
}

std::unique_ptr<kota::ipc::Transport> final_transport = std::move(*transport);
if(opts.record.has_value()) {
final_transport =
std::make_unique<kota::ipc::RecordingTransport>(std::move(final_transport),
*opts.record);
}

kota::ipc::JsonPeer peer(loop, std::move(final_transport));
clice::MasterServer server(loop, peer, std::move(self_path));
server.register_handlers();

loop.schedule(peer.run());
loop.run();
return 0;
if(mode == "pipe" || mode == "socket") {
clice::ServerOptions server_opts;
server_opts.mode = mode;
server_opts.host = opts.host.value_or("127.0.0.1");
server_opts.port = opts.port.value_or(0);
server_opts.self_path = argv[0];
server_opts.record = opts.record.value_or("");
return clice::run_server_mode(server_opts);
}

if(mode == "socket") {
clice::logging::stderr_logger("master", clice::logging::options);

kota::event_loop loop;

auto host = opts.host.value_or("127.0.0.1");
auto port = opts.port.value_or(50051);

auto acceptor = kota::tcp::listen(host, port, {}, loop);
if(!acceptor) {
LOG_ERROR("failed to listen on {}:{}", host, port);
return 1;
}

LOG_INFO("Listening on {}:{} ...", host, port);

auto task = [&]() -> kota::task<> {
auto client = co_await acceptor->accept();
if(!client.has_value()) {
LOG_ERROR("failed to accept connection");
loop.stop();
co_return;
}

LOG_INFO("Client connected");

std::unique_ptr<kota::ipc::Transport> transport =
std::make_unique<kota::ipc::StreamTransport>(std::move(client.value()));
if(opts.record.has_value()) {
transport = std::make_unique<kota::ipc::RecordingTransport>(std::move(transport),
*opts.record);
}
kota::ipc::JsonPeer peer(loop, std::move(transport));
clice::MasterServer server(loop, peer, std::string(self_path));
server.register_handlers();

co_await peer.run();
peer.close();
loop.stop();
};

loop.schedule(task());
loop.run();
return 0;
if(mode == "agentic") {
LOG_ERROR("agentic client mode is not yet implemented");
return 1;
}

LOG_ERROR("unknown mode '{}'", mode);
Expand Down
30 changes: 30 additions & 0 deletions src/protocol/agentic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <string>
#include <vector>

#include "kota/ipc/protocol.h"

namespace clice::agentic {

struct CompileCommandParams {
std::string path;
};

struct CompileCommandResult {
std::string file;
std::string directory;
std::vector<std::string> arguments;
};

} // namespace clice::agentic

namespace kota::ipc::protocol {

template <>
struct RequestTraits<clice::agentic::CompileCommandParams> {
using Result = clice::agentic::CompileCommandResult;
constexpr inline static std::string_view method = "agentic/compileCommand";
};

} // namespace kota::ipc::protocol
42 changes: 42 additions & 0 deletions src/protocol/extension.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include <optional>
#include <string>
#include <vector>

namespace clice::ext {

struct ContextItem {
std::string label;
std::string description;
std::string uri;
};

struct QueryContextParams {
std::string uri;
std::optional<int> offset;
};

struct QueryContextResult {
std::vector<ContextItem> contexts;
int total = 0;
};

struct CurrentContextParams {
std::string uri;
};

struct CurrentContextResult {
std::optional<ContextItem> context;
};

struct SwitchContextParams {
std::string uri;
std::string context_uri;
};

struct SwitchContextResult {
bool success = false;
};

} // namespace clice::ext
39 changes: 0 additions & 39 deletions src/server/protocol.h → src/protocol/worker.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once

#include <cstdint>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
Expand All @@ -10,7 +9,6 @@
#include "syntax/token.h"

#include "kota/codec/json/json.h"
#include "kota/ipc/lsp/protocol.h"
#include "kota/ipc/protocol.h"

namespace clice::worker {
Expand Down Expand Up @@ -122,43 +120,6 @@ struct EvictedParams {

} // namespace clice::worker

namespace clice::ext {

struct ContextItem {
std::string label;
std::string description;
std::string uri;
};

struct QueryContextParams {
std::string uri;
std::optional<int> offset;
};

struct QueryContextResult {
std::vector<ContextItem> contexts;
int total;
};

struct CurrentContextParams {
std::string uri;
};

struct CurrentContextResult {
std::optional<ContextItem> context;
};

struct SwitchContextParams {
std::string uri;
std::string context_uri;
};

struct SwitchContextResult {
bool success;
};

} // namespace clice::ext

namespace kota::ipc::protocol {

template <>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "server/compile_graph.h"
#include "server/compiler/compile_graph.h"

#include <algorithm>

Expand Down
File renamed without changes.
15 changes: 9 additions & 6 deletions src/server/compiler.cpp → src/server/compiler/compiler.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#include "server/compiler.h"
#include "server/compiler/compiler.h"

#include <format>
#include <ranges>
#include <string>

#include "command/search_config.h"
#include "index/tu_index.h"
#include "server/protocol.h"
#include "protocol/worker.h"
#include "support/filesystem.h"
#include "support/logging.h"
#include "syntax/include_resolver.h"
Expand All @@ -28,11 +28,10 @@ using serde_raw = kota::codec::RawValue;
/// Detect whether the cursor is inside a preamble directive (include/import).

Compiler::Compiler(kota::event_loop& loop,
kota::ipc::JsonPeer& peer,
Workspace& workspace,
WorkerPool& pool,
llvm::DenseMap<std::uint32_t, Session>& sessions) :
loop(loop), peer(peer), workspace(workspace), pool(pool), sessions(sessions) {}
loop(loop), workspace(workspace), pool(pool), sessions(sessions) {}

Compiler::~Compiler() {
workspace.cancel_all();
Expand Down Expand Up @@ -410,6 +409,8 @@ std::string uri_to_path(const std::string& uri) {
void Compiler::publish_diagnostics(const std::string& uri,
int version,
const kota::codec::RawValue& diagnostics_json) {
if(!peer)
return;
std::vector<protocol::Diagnostic> diagnostics;
if(!diagnostics_json.empty()) {
auto status = kota::codec::json::from_json(diagnostics_json.data, diagnostics);
Expand All @@ -421,14 +422,16 @@ void Compiler::publish_diagnostics(const std::string& uri,
params.uri = uri;
params.version = version;
params.diagnostics = std::move(diagnostics);
peer.send_notification(params);
peer->send_notification(params);
}

void Compiler::clear_diagnostics(const std::string& uri) {
if(!peer)
return;
protocol::PublishDiagnosticsParams params;
params.uri = uri;
params.diagnostics = {};
peer.send_notification(params);
peer->send_notification(params);
}

kota::task<bool> Compiler::ensure_pch(Session& session,
Expand Down
14 changes: 9 additions & 5 deletions src/server/compiler.h → src/server/compiler/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
#include <vector>

#include "command/command.h"
#include "server/session.h"
#include "server/worker_pool.h"
#include "server/workspace.h"
#include "server/service/session.h"
#include "server/worker/worker_pool.h"
#include "server/workspace/workspace.h"
#include "syntax/completion.h"

#include "kota/async/async.h"
Expand Down Expand Up @@ -50,10 +50,14 @@ std::string uri_to_path(const std::string& uri);
class Compiler {
public:
Compiler(kota::event_loop& loop,
kota::ipc::JsonPeer& peer,
Workspace& workspace,
WorkerPool& pool,
llvm::DenseMap<std::uint32_t, Session>& sessions);

void set_peer(kota::ipc::JsonPeer* p) {
peer = p;
}

~Compiler();

void init_compile_graph();
Expand Down Expand Up @@ -125,7 +129,7 @@ class Compiler {

private:
kota::event_loop& loop;
kota::ipc::JsonPeer& peer;
kota::ipc::JsonPeer* peer = nullptr;
Workspace& workspace;
WorkerPool& pool;
llvm::DenseMap<std::uint32_t, Session>& sessions;
Expand Down
Loading
Loading