fixed some bugs for romeo

This commit is contained in:
2026-07-22 17:12:08 -04:00
parent 840db1f804
commit f3747a7581
7 changed files with 177 additions and 33 deletions
+9 -9
View File
@@ -113,8 +113,8 @@ namespace Romeo
{
size_t bodyCap = modelName.Size + 64;
char* showBodyBuf = Juliet::ArenaPushArray<char>(arena, bodyCap JULIET_DEBUG_PARAM("ShowBody"));
snprintf(showBodyBuf, bodyCap, "{\"name\":\"%.*s\"}", static_cast<int>(modelName.Size), CStr(modelName));
Juliet::String showBody = Juliet::WrapString(showBodyBuf);
int showLen = snprintf(showBodyBuf, bodyCap, "{\"name\":\"%.*s\"}", static_cast<int>(modelName.Size), CStr(modelName));
Juliet::String showBody = { showBodyBuf, static_cast<size_t>(showLen > 0 ? showLen : 0) };
Juliet::String showResponse = {};
bool showSuccess = PostWithRetry(arena, host, port, ConstString("/api/show"), false, showBody, showResponse);
@@ -148,8 +148,8 @@ namespace Romeo
OutputDebugStringA("Romeo AI: Model not found. Pulling model...\n");
char* pullBodyBuf = Juliet::ArenaPushArray<char>(arena, bodyCap + 32 JULIET_DEBUG_PARAM("PullBody"));
snprintf(pullBodyBuf, bodyCap + 32, "{\"name\":\"%.*s\",\"stream\":false}", static_cast<int>(modelName.Size), CStr(modelName));
Juliet::String pullBody = Juliet::WrapString(pullBodyBuf);
int pullLen = snprintf(pullBodyBuf, bodyCap + 32, "{\"name\":\"%.*s\",\"stream\":false}", static_cast<int>(modelName.Size), CStr(modelName));
Juliet::String pullBody = { pullBodyBuf, static_cast<size_t>(pullLen > 0 ? pullLen : 0) };
Juliet::String pullResponse = {};
bool pullSuccess = PostWithRetry(arena, host, port, ConstString("/api/pull"), false, pullBody, pullResponse);
@@ -225,7 +225,7 @@ namespace Romeo
);
}
Juliet::String prompt = { promptBuf, static_cast<size_t>(written) };
Juliet::String prompt = { promptBuf, static_cast<size_t>(written > 0 ? written : 0) };
Juliet::String escapedPrompt = Json_EscapeString(arena, prompt);
// Try local Ollama
@@ -236,7 +236,7 @@ namespace Romeo
Juliet::String modelName = GetEnvironmentVar(arena, "ROMEO_LLM_MODEL");
if (modelName.Size == 0)
{
modelName = ConstString("qwen3.5:4b");
modelName = ConstString("qwen2.5-coder:1.5b");
}
// Check / pull model if needed
@@ -252,12 +252,12 @@ namespace Romeo
size_t bodyCap = modelName.Size + escapedPrompt.Size + 256;
char* bodyBuf = Juliet::ArenaPushArray<char>(arena, bodyCap JULIET_DEBUG_PARAM("OllamaBody"));
snprintf(bodyBuf, bodyCap,
"{\"model\":\"%.*s\",\"prompt\":\"%.*s\",\"stream\":false,\"think\":true}",
int bodyLen = snprintf(bodyBuf, bodyCap,
"{\"model\":\"%.*s\",\"prompt\":\"%.*s\",\"stream\":false}",
static_cast<int>(modelName.Size), CStr(modelName),
static_cast<int>(escapedPrompt.Size), CStr(escapedPrompt)
);
Juliet::String body = Juliet::WrapString(bodyBuf);
Juliet::String body = { bodyBuf, static_cast<size_t>(bodyLen > 0 ? bodyLen : 0) };
Juliet::String response = {};
+18 -7
View File
@@ -431,15 +431,19 @@ namespace Romeo
Assert(arena != nullptr);
size_t escLen = 0;
const char* p = CStr(str);
const char* end = p + str.Size;
const unsigned char* p = reinterpret_cast<const unsigned char*>(CStr(str));
const unsigned char* end = p + str.Size;
while (p < end)
{
char c = *p;
if (c == '"' || c == '\\' || c == '\n' || c == '\r' || c == '\t')
unsigned char c = *p;
if (c == '"' || c == '\\' || c == '\n' || c == '\r' || c == '\t' || c == '\b' || c == '\f')
{
escLen += 2;
}
else if (c < 32)
{
escLen += 6;
}
else
{
escLen += 1;
@@ -449,16 +453,23 @@ namespace Romeo
char* buf = Juliet::ArenaPushArray<char>(arena, escLen + 1 JULIET_DEBUG_PARAM("JsonEscapedStr"));
char* dst = buf;
p = CStr(str);
p = reinterpret_cast<const unsigned char*>(CStr(str));
while (p < end)
{
char c = *p;
unsigned char c = *p;
if (c == '"') { *dst++ = '\\'; *dst++ = '"'; }
else if (c == '\\') { *dst++ = '\\'; *dst++ = '\\'; }
else if (c == '\n') { *dst++ = '\\'; *dst++ = 'n'; }
else if (c == '\r') { *dst++ = '\\'; *dst++ = 'r'; }
else if (c == '\t') { *dst++ = '\\'; *dst++ = 't'; }
else { *dst++ = c; }
else if (c == '\b') { *dst++ = '\\'; *dst++ = 'b'; }
else if (c == '\f') { *dst++ = '\\'; *dst++ = 'f'; }
else if (c < 32)
{
snprintf(dst, 7, "\\u00%02x", static_cast<unsigned int>(c));
dst += 6;
}
else { *dst++ = static_cast<char>(c); }
p++;
}
*dst = '\0';
+49 -4
View File
@@ -110,11 +110,37 @@ namespace Romeo
{
const char* absPtr = CStr(absolutePath);
const char* rootPtr = CStr(workspaceRoot);
if (_strnicmp(absPtr, rootPtr, workspaceRoot.Size) == 0)
size_t rootSize = workspaceRoot.Size;
size_t matched = 0;
while (matched < rootSize && matched < absolutePath.Size)
{
const char* rel = absPtr + workspaceRoot.Size;
size_t newSize = absolutePath.Size - workspaceRoot.Size;
if (*rel == '\\' || *rel == '/') { rel++; newSize--; }
char c1 = absPtr[matched];
char c2 = rootPtr[matched];
if (c1 == '/')
{
c1 = '\\';
}
if (c2 == '/')
{
c2 = '\\';
}
if (tolower(static_cast<unsigned char>(c1)) != tolower(static_cast<unsigned char>(c2)))
{
break;
}
matched++;
}
if (matched == rootSize)
{
const char* rel = absPtr + rootSize;
size_t newSize = absolutePath.Size - rootSize;
if (*rel == '\\' || *rel == '/')
{
rel++;
newSize--;
}
return { const_cast<char*>(rel), newSize };
}
}
@@ -845,6 +871,25 @@ namespace Romeo
{
EnsureDirectoryExists(CStr(docsDir));
// Clean up any stale broken C__*.md files from prior runs
{
char searchPattern[512];
snprintf(searchPattern, sizeof(searchPattern), "%s\\C__*.md", CStr(docsDir));
WIN32_FIND_DATAA findData;
HANDLE hFind = FindFirstFileA(searchPattern, &findData);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
char filePath[512];
snprintf(filePath, sizeof(filePath), "%s\\%s", CStr(docsDir), findData.cFileName);
DeleteFileA(filePath);
} while (FindNextFileA(hFind, &findData) != 0);
FindClose(hFind);
}
}
char overviewPath[512];
snprintf(overviewPath, sizeof(overviewPath), "%s\\overview.md", CStr(docsDir));
+25 -6
View File
@@ -36,15 +36,32 @@ static Juliet::String GetWorkspaceRoot(Juliet::Arena* arena)
char* buf = Juliet::ArenaPushArray<char>(arena, base.Size + 1 JULIET_DEBUG_PARAM("WorkspaceRootPath"));
memcpy(buf, base.Data, base.Size);
buf[base.Size] = '\0';
// Normalize slashes
for (size_t i = 0; i < base.Size; ++i)
{
if (buf[i] == '/')
{
buf[i] = '\\';
}
}
// Search for \bin to find workspace root
char* binPtr = strstr(buf, "\\bin");
if (binPtr != nullptr)
{
*binPtr = '\0';
return { buf, static_cast<size_t>(binPtr - buf) };
}
size_t count = 0;
for (size_t i = base.Size; i > 0; --i)
{
size_t idx = i - 1;
if (buf[idx] == '\\' || buf[idx] == '/')
if (buf[idx] == '\\')
{
count++;
if (count == 3)
if (count == 2)
{
buf[idx] = '\0';
return { buf, idx };
@@ -332,15 +349,17 @@ int JulietMain(int argc, wchar_t** argv)
&jobInfo, sizeof(jobInfo));
}
// Build a mutable command line buffer (CreateProcessA requires mutable string)
// Build a command line for cmd.exe /k so the console window remains open
char cmdLine[600] = {};
snprintf(cmdLine, sizeof(cmdLine), "\"%s\" serve", ollamaPath);
snprintf(cmdLine, sizeof(cmdLine), "cmd.exe /k \"\"%s\" serve\"", ollamaPath);
STARTUPINFOA si = {};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
PROCESS_INFORMATION pi = {};
BOOL createRes = CreateProcessA(
ollamaPath,
nullptr,
cmdLine,
nullptr,
nullptr,