fix(cli): add list filtering/pagination, fix double-close in container ncl

- genericList now accepts column filters (--flag value) and LIMIT (default 200)
- Remove early inDb.close() in container pollResponse to avoid double-close
- Document filtering and --limit in cli.instructions.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-05-08 21:02:23 +03:00
parent ed571d1f66
commit 6caad0757a
3 changed files with 18 additions and 6 deletions
+1 -3
View File
@@ -102,8 +102,6 @@ function pollResponse(requestId: string, timeoutMs: number): ResponseFrame | nul
.get(`%"requestId":"${requestId}"%`) as { id: string; content: string } | null;
if (row) {
inDb.close();
// Mark as completed via processing_ack so agent-runner skips it
const outDb = new Database(OUTBOUND_DB);
outDb.exec('PRAGMA journal_mode = DELETE');
@@ -119,7 +117,7 @@ function pollResponse(requestId: string, timeoutMs: number): ResponseFrame | nul
return parsed.frame as ResponseFrame;
}
} finally {
try { inDb.close(); } catch {}
inDb.close();
}
Bun.sleepSync(500);
@@ -73,5 +73,6 @@ ncl destinations add --agent-group-id abc123 --messaging-group-id mg_xyz
- Use `ncl <resource> help` to see all available fields, types, enums, and which fields are required or updatable.
- Flags use `--hyphen-case` (e.g. `--agent-group-id`), mapped to `underscore_case` DB columns automatically.
- `list` supports filtering by any non-auto column (e.g. `ncl wirings list --messaging-group-id mg_xyz`). Default limit is 200 rows; override with `--limit N`.
- For composite-key resources (roles, members, destinations), use the custom verbs (grant/revoke, add/remove) instead of create/delete.
- Write commands return `approval-pending` immediately — don't treat this as an error. Wait for the system message with the result.
+16 -3
View File
@@ -89,8 +89,21 @@ function visibleColumns(def: ResourceDef): string[] {
function genericList(def: ResourceDef) {
const cols = visibleColumns(def).join(', ');
return async () => {
return getDb().prepare(`SELECT ${cols} FROM ${def.table}`).all();
const filterableNames = new Set(def.columns.filter((c) => !c.generated).map((c) => c.name));
return async (args: Record<string, unknown>) => {
const limit = args.limit !== undefined ? Math.max(1, Number(args.limit)) : 200;
const filters: string[] = [];
const params: unknown[] = [];
for (const [k, v] of Object.entries(args)) {
if (k === 'id' || k === 'limit') continue;
if (filterableNames.has(k)) {
filters.push(`${k} = ?`);
params.push(v);
}
}
const where = filters.length > 0 ? ` WHERE ${filters.join(' AND ')}` : '';
params.push(limit);
return getDb().prepare(`SELECT ${cols} FROM ${def.table}${where} LIMIT ?`).all(...params);
};
}
@@ -211,7 +224,7 @@ export function registerResource(def: ResourceDef): void {
description: `List all ${def.plural}.`,
access: def.operations.list,
resource: def.plural,
parseArgs: () => ({}),
parseArgs: (raw) => normalizeArgs(raw),
handler: genericList(def),
});
}