diff options
| author | t <t@tjp.lol> | 2026-06-02 15:00:44 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-06-02 16:37:32 -0600 |
| commit | 8b88b886346460b1ab29edb03ad85bc3bb565a45 (patch) | |
| tree | 13b9ab56061a722641389b5fc8ac1113d09b66e5 /src/system_prompt.zig | |
| parent | 7268c0b8e8bcf4b325581fabe7476a394f167738 (diff) | |
compaction
Diffstat (limited to 'src/system_prompt.zig')
| -rw-r--r-- | src/system_prompt.zig | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/system_prompt.zig b/src/system_prompt.zig index b796394..0b449dc 100644 --- a/src/system_prompt.zig +++ b/src/system_prompt.zig @@ -37,6 +37,31 @@ pub const default_seed = "You are a helpful assistant."; const seed_filename = "SYSTEM.md"; const append_filename = "APPEND_SYSTEM.md"; +const compaction_filename = "COMPACTION.md"; + +/// Last-resort fallback compaction prompt when no `COMPACTION.md` exists at +/// any layer. In normal operation the base layer ships a bundled +/// `agent/COMPACTION.md`, so this is only used if that staged file is +/// missing or unreadable. +pub const default_compaction_prompt = + \\You are compacting a long conversation to reduce its context size. + \\ + \\You will be given a transcript of an earlier portion of a + \\conversation between a user and an AI coding assistant, and possibly a + \\previous summary of even older history. Produce a single, dense + \\summary that preserves everything needed to continue the work + \\coherently: + \\ + \\- the user's goals, decisions, and stated preferences + \\- the current state of the task and what remains to be done + \\- key facts discovered about the codebase or problem + \\- important file paths, identifiers, and code structures + \\- unresolved questions, bugs, and their understanding + \\ + \\Write the summary as factual notes, not as a chat reply. Do not + \\address the user. Do not include pleasantries. Be comprehensive about + \\specifics but omit redundant back-and-forth. +; /// A resolved set of system blocks for a fresh session: the seed followed /// by zero or more appends, already in emission order. All slices @@ -185,6 +210,39 @@ pub fn reconcileResumeLayers( } } +/// Resolve the compaction system prompt across the three config layers. +/// Like `SYSTEM.md` (not `APPEND_SYSTEM.md`): the highest layer present +/// wins (project > user > base); falls back to a built-in default if no +/// `COMPACTION.md` exists anywhere. The result is owned by `arena`. +pub fn resolveCompaction( + arena: Allocator, + io: Io, + environ_map: *const std.process.Environ.Map, + base_dir: []const u8, +) ![]const u8 { + const user_dir = try userLayerDir(arena, environ_map); + const project_dir = try projectLayerDir(arena, io); + return resolveCompactionLayers(arena, io, base_dir, user_dir, project_dir); +} + +/// Layer-explicit variant of `resolveCompaction` (see `resolveLayers`). +pub fn resolveCompactionLayers( + arena: Allocator, + io: Io, + base_dir: ?[]const u8, + user_dir: ?[]const u8, + project_dir: ?[]const u8, +) ![]const u8 { + var prompt: []const u8 = default_compaction_prompt; + for ([_]?[]const u8{ base_dir, user_dir, project_dir }) |maybe_dir| { + const dir = maybe_dir orelse continue; + if (try readLayerFile(arena, io, dir, compaction_filename)) |text| { + prompt = text; + } + } + return prompt; +} + // --------------------------------------------------------------------------- // Internals // --------------------------------------------------------------------------- @@ -539,3 +597,34 @@ test "Resolved.blocks - seed leads appends" { try testing.expectEqualStrings("U", blocks[2]); try testing.expectEqualStrings("B", blocks[3]); } + +test "resolveCompactionLayers - highest COMPACTION.md wins, default otherwise" { + var tmp = testing.tmpDir(.{ .iterate = true }); + defer tmp.cleanup(); + + var arena_state = std.heap.ArenaAllocator.init(testing.allocator); + defer arena_state.deinit(); + const arena = arena_state.allocator(); + + var buf: [std.fs.max_path_bytes]u8 = undefined; + const root_len = try tmp.dir.realPathFile(testing.io, ".", &buf); + const root = buf[0..root_len]; + + // No files anywhere -> default. + { + const p = try resolveCompactionLayers(arena, testing.io, root, null, null); + try testing.expectEqualStrings(default_compaction_prompt, p); + } + + // base + project; project wins. + try tmp.dir.createDirPath(testing.io, "base"); + try tmp.dir.createDirPath(testing.io, "project"); + try writeTmpFile(tmp.dir, "base/COMPACTION.md", "base compaction"); + try writeTmpFile(tmp.dir, "project/COMPACTION.md", "project compaction"); + const base_dir = try std.fs.path.join(arena, &.{ root, "base" }); + const project_dir = try std.fs.path.join(arena, &.{ root, "project" }); + { + const p = try resolveCompactionLayers(arena, testing.io, base_dir, null, project_dir); + try testing.expectEqualStrings("project compaction", p); + } +} |
