Skip to content

Commit 1f075ef

Browse files
committed
fix(corpus): camelCase dateStart/dateEnd dual-accept + obs_type key routing
Two defects in build_corpus path silently narrowed result sets: 1. CorpusRoutes destructured only snake_case (date_start, date_end) from the request body, but the MCP tool surface advertises camelCase (dateStart, dateEnd). Zod's .passthrough() let the unknown keys through but the handler never read them — date filters were silently dropped. Fix: declare both casings in the Zod schema and read either at the destructure site. 2. CorpusBuilder set searchArgs.type = filter.types.join(',') — but `type` is the search-router discriminator (observations|sessions|prompts), NOT the observation-type filter. Passing 'bugfix,decision' to that key matched zero rows; a downstream array hydrate masked the failure and returned only entries that survived a different filter pass. Fix: route the joined types through searchArgs.obs_type (the correct observation-type filter key).
1 parent 8463689 commit 1f075ef

2 files changed

Lines changed: 17 additions & 5 deletions

File tree

src/services/worker/http/routes/CorpusRoutes.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ const buildCorpusSchema = z.object({
4949
query: z.string().optional(),
5050
date_start: z.string().optional(),
5151
date_end: z.string().optional(),
52+
// Dual-accept: the MCP tool surface advertises camelCase (dateStart/dateEnd).
53+
// Without these declarations Zod's .passthrough() keeps the camelCase keys on
54+
// the body but the snake_case destructure below never reads them.
55+
dateStart: z.string().optional(),
56+
dateEnd: z.string().optional(),
5257
limit: positiveIntegerLike,
5358
}).passthrough();
5459

@@ -79,17 +84,20 @@ export class CorpusRoutes extends BaseRouteHandler {
7984
}
8085

8186
private handleBuildCorpus = this.wrapHandler(async (req: Request, res: Response): Promise<void> => {
82-
const { name, description, project, types, concepts, files, query, date_start, date_end, limit } =
83-
req.body as z.infer<typeof buildCorpusSchema>;
87+
const body = req.body as z.infer<typeof buildCorpusSchema>;
88+
const { name, description, project, types, concepts, files, query, limit } = body;
89+
// Accept either casing — internal filter stays snake_case.
90+
const dateStart = body.date_start ?? body.dateStart;
91+
const dateEnd = body.date_end ?? body.dateEnd;
8492

8593
const filter: CorpusFilter = {};
8694
if (project) filter.project = project;
8795
if (types && types.length > 0) filter.types = types as CorpusFilter['types'];
8896
if (concepts && concepts.length > 0) filter.concepts = concepts;
8997
if (files && files.length > 0) filter.files = files;
9098
if (query) filter.query = query;
91-
if (date_start) filter.date_start = date_start;
92-
if (date_end) filter.date_end = date_end;
99+
if (dateStart) filter.date_start = dateStart;
100+
if (dateEnd) filter.date_end = dateEnd;
93101
if (limit !== undefined) filter.limit = limit;
94102

95103
logger.info('SEARCH', 'Building corpus', { name, project, filterKeys: Object.keys(filter) });

src/services/worker/knowledge/CorpusBuilder.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ export class CorpusBuilder {
3939

4040
const searchArgs: Record<string, unknown> = {};
4141
if (filter.project) searchArgs.project = filter.project;
42-
if (filter.types && filter.types.length > 0) searchArgs.type = filter.types.join(',');
42+
// `type` is the search-router discriminator (observations|sessions|prompts).
43+
// For observation-type filtering use `obs_type`. Passing the comma-joined
44+
// observation types to `type` silently collapses the result set (only the
45+
// first type survives the downstream WHERE).
46+
if (filter.types && filter.types.length > 0) searchArgs.obs_type = filter.types.join(',');
4347
if (filter.concepts && filter.concepts.length > 0) searchArgs.concepts = filter.concepts.join(',');
4448
if (filter.files && filter.files.length > 0) searchArgs.files = filter.files.join(',');
4549
if (filter.query) searchArgs.query = filter.query;

0 commit comments

Comments
 (0)