mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
fix(daemon): accept Unicode session roots on Windows
Signed-off-by: Ertan <ertan.kucukoglu@gmail.com>
This commit is contained in:
1 parent
5fbab7bb73
commit
9d4ac2b98b
3 files changed
+49
-7
No files matched your search
@@ -374,6 +374,11 @@ static bool application_regular_db_exists(const char *project) {
|
||||
return stat(path, &status) == 0 && S_ISREG(status.st_mode);
|
||||
}
|
||||
|
||||
static bool application_canonical_directory_exists(const char *path) {
|
||||
cbm_path_info_t info = {0};
|
||||
return cbm_path_info_utf8(path, &info) == 0 && info.is_directory;
|
||||
}
|
||||
|
||||
static cbm_daemon_application_watch_t *application_find_watch_locked(
|
||||
cbm_daemon_application_t *application, const char *project) {
|
||||
for (cbm_daemon_application_watch_t *watch = application->watches; watch; watch = watch->next) {
|
||||
@@ -2354,9 +2359,7 @@ static cbm_daemon_runtime_application_status_t application_set_context(
|
||||
if (canonical && allowed_present) {
|
||||
canonical = cbm_canonical_path(allowed, canonical_allowed, sizeof(canonical_allowed));
|
||||
}
|
||||
struct stat root_status;
|
||||
canonical =
|
||||
canonical && stat(canonical_root, &root_status) == 0 && S_ISDIR(root_status.st_mode);
|
||||
canonical = canonical && application_canonical_directory_exists(canonical_root);
|
||||
bool set =
|
||||
canonical && cbm_mcp_server_set_session_context(session->mcp, canonical_root,
|
||||
allowed_present ? canonical_allowed : NULL);
|
||||
@@ -3369,9 +3372,8 @@ static int application_background_index(cbm_daemon_application_t *application,
|
||||
return -1;
|
||||
}
|
||||
char canonical_root[APPLICATION_PATH_CAP];
|
||||
struct stat root_status;
|
||||
if (!cbm_canonical_path(root_path, canonical_root, sizeof(canonical_root)) ||
|
||||
stat(canonical_root, &root_status) != 0 || !S_ISDIR(root_status.st_mode)) {
|
||||
!application_canonical_directory_exists(canonical_root)) {
|
||||
return -1;
|
||||
}
|
||||
yyjson_mut_doc *document = yyjson_mut_doc_new(NULL);
|
||||
|
||||
@@ -714,6 +714,45 @@ TEST(daemon_application_requires_immutable_explicit_context) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(daemon_application_accepts_utf8_session_context_root) {
|
||||
char root[APP_TEST_PATH_CAP];
|
||||
snprintf(root, sizeof(root), "%s/cbm-app-context-caf\xC3\xA9-XXXXXX", cbm_tmpdir());
|
||||
bool root_ok = cbm_mkdtemp(root) != NULL;
|
||||
cbm_daemon_application_t *application = cbm_daemon_application_new(NULL);
|
||||
cbm_daemon_runtime_application_callbacks_t callbacks =
|
||||
cbm_daemon_application_runtime_callbacks(application);
|
||||
cbm_daemon_runtime_application_session_t *session = app_test_open(&callbacks, 311);
|
||||
uint8_t *context = NULL;
|
||||
uint32_t context_length = 0;
|
||||
uint8_t *response = NULL;
|
||||
uint32_t response_length = 0;
|
||||
bool context_ok = root_ok && app_test_context_request(root, root, &context, &context_length);
|
||||
cbm_daemon_runtime_application_status_t status =
|
||||
context_ok ? app_test_request(&callbacks, session, context, context_length, &response,
|
||||
&response_length)
|
||||
: CBM_DAEMON_RUNTIME_APPLICATION_TRANSPORT_ERROR;
|
||||
|
||||
free(context);
|
||||
free(response);
|
||||
if (session) {
|
||||
callbacks.session_close(callbacks.context, session);
|
||||
}
|
||||
bool stopped = application && cbm_daemon_application_shutdown(application, APP_TEST_TIMEOUT_MS);
|
||||
cbm_daemon_application_free(application);
|
||||
if (root_ok) {
|
||||
(void)cbm_rmdir(root);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(root_ok);
|
||||
ASSERT_NOT_NULL(application);
|
||||
ASSERT_NOT_NULL(session);
|
||||
ASSERT_TRUE(context_ok);
|
||||
ASSERT_EQ(status, CBM_DAEMON_RUNTIME_APPLICATION_OK);
|
||||
ASSERT_EQ(response_length, 0);
|
||||
ASSERT_TRUE(stopped);
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(daemon_application_mcp_notification_has_no_response) {
|
||||
cbm_daemon_application_t *application = cbm_daemon_application_new(NULL);
|
||||
cbm_daemon_runtime_application_callbacks_t callbacks =
|
||||
@@ -5348,6 +5387,7 @@ SUITE(daemon_application) {
|
||||
RUN_TEST(daemon_application_new_session_does_not_retain_initial_store);
|
||||
RUN_TEST(daemon_application_request_cancel_is_scoped_to_exact_token);
|
||||
RUN_TEST(daemon_application_requires_immutable_explicit_context);
|
||||
RUN_TEST(daemon_application_accepts_utf8_session_context_root);
|
||||
RUN_TEST(daemon_application_ui_config_updates_are_masked_and_serialized);
|
||||
RUN_TEST(daemon_application_ui_config_rejects_noncanonical_frames);
|
||||
RUN_TEST(daemon_application_ui_readiness_proof_is_generation_bound_before_context);
|
||||
|
||||
@@ -358,9 +358,9 @@ def no_project_error(index_txt, repo, cache):
|
||||
|
||||
|
||||
def index_and_count(binary, repo, cache):
|
||||
"""Index `repo` into an isolated cache and return label-resolved counts."""
|
||||
"""Start in and index `repo`, then return label-resolved counts."""
|
||||
os.makedirs(cache, exist_ok=True)
|
||||
with McpServer(binary, cache_dir=cache) as s:
|
||||
with McpServer(binary, cache_dir=cache, cwd=repo) as s:
|
||||
s.initialize()
|
||||
resp = s.call_tool("index_repository", {"repo_path": repo}, timeout=180)
|
||||
index_txt, err = s.tool_text(resp)
|
||||
|
||||
Reference in new issue
Block a user