#define _POSIX_C_SOURCE 200809L #include "context_format.h" #include #include #include static int append_text(char** buf, size_t* cap, size_t* used, const char* s, size_t len) { if (!buf || !cap || !used || !s) return -1; if (*used + len + 1U > *cap) { size_t next = *cap; while (*used + len + 1U > next) { next = (next == 0U) ? 256U : (next * 2U); } char* grown = (char*)realloc(*buf, next); if (!grown) return -1; *buf = grown; *cap = next; } memcpy(*buf + *used, s, len); *used += len; (*buf)[*used] = '\0'; return 0; } char* context_bump_headings(const char* text) { if (!text) return NULL; size_t cap = strlen(text) + 256; // Initial guess size_t used = 0; char* buf = (char*)malloc(cap); if (!buf) return NULL; buf[0] = '\0'; const char* p = text; while (*p) { const char* eol = strchr(p, '\n'); size_t line_len = eol ? (size_t)(eol - p) : strlen(p); // Check if line starts with '#' if (line_len > 0 && p[0] == '#') { // Add an extra '#' if (append_text(&buf, &cap, &used, "#", 1) != 0) { free(buf); return NULL; } } // Append the rest of the line if (append_text(&buf, &cap, &used, p, line_len) != 0) { free(buf); return NULL; } if (eol) { if (append_text(&buf, &cap, &used, "\n", 1) != 0) { free(buf); return NULL; } p = eol + 1; } else { break; } } return buf; } char* context_build_title(tools_context_t* ctx) { if (!ctx || !ctx->cfg) return strdup("# Didactyl Agent\n\n"); const char* name = "Didactyl Agent"; // Try to get name from kind 0 profile if available if (ctx->template_skill_lookup) { // We don't have direct access to the parsed kind 0 here easily, // but we can try to extract it from the agent_profile tool output // if we really wanted to. For now, let's stick to a simple default // or use the config if it has a name field (it doesn't currently). // A more robust way would be to parse the kind 0 JSON here. } // For now, just use a generic title. The identity skill will provide the rest. char title[256]; snprintf(title, sizeof(title), "# %s\n\n", name); return strdup(title); }