fix the session-list scan's line count, and pin both new paths with tests
The rewritten cst_agent_store_info() counted a transcript line that ran past a whole 64 KiB read block a second time, when the newline ending its tail arrived: a session with one very long line (a tool that read a file back) reported one message too many -- exactly what the sidebar shows the person. - src/agent_store.c: the tail's newline ends a line that was already counted. - tests/test_store.c: test_info_scan() holds the scan down -- a 70 KiB line is one line, the first user message comes from the head of the file, and a user line past the window is not called the first one. - tests/test_tools_ext.c: a byte budget stops the session_search walk, says so in the result, and never reports a match it did not reach; the same query without a budget finds it. make check and make asan are green.
This commit is contained in:
@@ -236,6 +236,50 @@ static void test_session_search(cst_tool_ctx_t *ctx) {
|
||||
c = mk("session_search", NULL);
|
||||
EXPECT(run(ctx, c, &r) == 1, "a query is required");
|
||||
cst_tool_result_free(&r);
|
||||
|
||||
/* A store is not read to the end on a whim: a byte budget stops the walk
|
||||
* and says so, and it never reports a match it did not get to. */
|
||||
{
|
||||
char path2[512];
|
||||
EXPECT(cst_agent_store_path_for_id(g_ws, "20260101-130000-big", path2,
|
||||
sizeof(path2)) == 0,
|
||||
"a second session path");
|
||||
cst_session_t *s2 = cst_session_open(path2);
|
||||
EXPECT(s2 != NULL, "its transcript opens");
|
||||
if (s2) {
|
||||
cst_message_t m2;
|
||||
memset(&m2, 0, sizeof(m2));
|
||||
m2.role = CST_ROLE_USER;
|
||||
m2.content = (char *)"the start of a long one";
|
||||
EXPECT(cst_session_append(s2, &m2) == 0, "a first line goes in");
|
||||
for (int i = 0; i < 600; i++) {
|
||||
memset(&m2, 0, sizeof(m2));
|
||||
m2.role = CST_ROLE_ASSISTANT;
|
||||
m2.content = (char *)"a line of tool output that says nothing special";
|
||||
if (cst_session_append(s2, &m2) != 0)
|
||||
break;
|
||||
}
|
||||
memset(&m2, 0, sizeof(m2));
|
||||
m2.role = CST_ROLE_ASSISTANT;
|
||||
m2.content = (char *)"the needle is only at the very end";
|
||||
EXPECT(cst_session_append(s2, &m2) == 0, "the needle goes in last");
|
||||
cst_session_close(s2);
|
||||
}
|
||||
/* Enough lines that a byte budget is spent before the end is reached. */
|
||||
c = mk("session_search", "query", "needle", "max_bytes", "4096", NULL);
|
||||
EXPECT(run(ctx, c, &r) == 0 && r.out != NULL, "a bounded search runs");
|
||||
EXPECT(r.out && strstr(r.out, "budget stopped the walk") != NULL,
|
||||
"the byte budget stops the walk and says so");
|
||||
EXPECT(r.out == NULL || strstr(r.out, "the needle is only") == NULL,
|
||||
"and it does not report a match it never got to");
|
||||
cst_tool_result_free(&r);
|
||||
/* The same query without a budget reaches the end and finds it. */
|
||||
c = mk("session_search", "query", "needle", NULL);
|
||||
EXPECT(run(ctx, c, &r) == 0 && r.out &&
|
||||
strstr(r.out, "the needle is only") != NULL,
|
||||
"the unbounded search finds it");
|
||||
cst_tool_result_free(&r);
|
||||
}
|
||||
}
|
||||
|
||||
/* --- device_info: the environment, without a shell ---------------------- */
|
||||
|
||||
Reference in New Issue
Block a user