@blogic-cz/agent-tools 0.8.11 → 0.8.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blogic-cz/agent-tools",
3
- "version": "0.8.11",
3
+ "version": "0.8.12",
4
4
  "description": "CLI tools for AI coding agent workflows — GitHub, database, Kubernetes, Azure DevOps, logs, sessions, and audit",
5
5
  "keywords": [
6
6
  "agent",
@@ -184,30 +184,65 @@ function parseDescribeSections(
184
184
  return sections;
185
185
  }
186
186
 
187
- function stripLowValueColumns(rows: Record<string, string>[]): Record<string, string>[] {
187
+ type KubectlTableResult = {
188
+ headers: string[];
189
+ rows: Record<string, string>[];
190
+ uniform?: Record<string, string>;
191
+ stripped?: string[];
192
+ };
193
+
194
+ const PLACEHOLDER_VALUES = new Set(["<none>", "<pending>", "<unknown>", "<unset>", ""]);
195
+ const ALWAYS_STRIP_COLUMNS = new Set(["SELECTOR", "LABELS", "NODE-SELECTORS", "NODE_SELECTORS"]);
196
+
197
+ function isSelectorLikeValue(value: string): boolean {
198
+ if (!value.includes("=")) return false;
199
+ return value.includes("kubernetes.io/") || value.includes("k8s.io/") || value.includes(",");
200
+ }
201
+
202
+ function stripLowValueColumns(rows: Record<string, string>[]): {
203
+ rows: Record<string, string>[];
204
+ stripped: string[];
205
+ } {
188
206
  if (rows.length === 0) {
189
- return rows;
207
+ return { rows, stripped: [] };
190
208
  }
191
209
 
192
210
  const keys = Object.keys(rows[0] ?? {});
193
211
  const keysToRemove = new Set<string>();
194
212
 
195
213
  for (const key of keys) {
196
- const allNone = rows.every((row) => {
197
- const value = (row[key] ?? "").trim().toLowerCase();
198
- return value === "<none>";
199
- });
214
+ if (ALWAYS_STRIP_COLUMNS.has(key.toUpperCase())) {
215
+ keysToRemove.add(key);
216
+ continue;
217
+ }
218
+
219
+ const values = rows.map((row) => (row[key] ?? "").trim());
200
220
 
201
- if (allNone) {
221
+ const allPlaceholder = values.every((v) => PLACEHOLDER_VALUES.has(v.toLowerCase()));
222
+ if (allPlaceholder) {
202
223
  keysToRemove.add(key);
224
+ continue;
225
+ }
226
+
227
+ const nonEmptyValues = values.filter(
228
+ (v) => v.length > 0 && !PLACEHOLDER_VALUES.has(v.toLowerCase()),
229
+ );
230
+ if (nonEmptyValues.length > 0) {
231
+ const avgLength =
232
+ nonEmptyValues.reduce((sum, v) => sum + v.length, 0) / nonEmptyValues.length;
233
+ const labelCount = nonEmptyValues.filter(isSelectorLikeValue).length;
234
+ if (avgLength > 50 && labelCount / nonEmptyValues.length > 0.5) {
235
+ keysToRemove.add(key);
236
+ }
203
237
  }
204
238
  }
205
239
 
206
240
  if (keysToRemove.size === 0) {
207
- return rows;
241
+ return { rows, stripped: [] };
208
242
  }
209
243
 
210
- return rows.map((row) => {
244
+ const stripped = keys.filter((k) => keysToRemove.has(k));
245
+ const filteredRows = rows.map((row) => {
211
246
  const filtered: Record<string, string> = {};
212
247
  for (const [key, value] of Object.entries(row)) {
213
248
  if (!keysToRemove.has(key)) {
@@ -216,6 +251,47 @@ function stripLowValueColumns(rows: Record<string, string>[]): Record<string, st
216
251
  }
217
252
  return filtered;
218
253
  });
254
+
255
+ return { rows: filteredRows, stripped };
256
+ }
257
+
258
+ function collapseUniformColumns(rows: Record<string, string>[]): {
259
+ rows: Record<string, string>[];
260
+ uniform: Record<string, string>;
261
+ } {
262
+ if (rows.length <= 1) {
263
+ return { rows, uniform: {} };
264
+ }
265
+
266
+ const keys = Object.keys(rows[0] ?? {});
267
+ const uniform: Record<string, string> = {};
268
+ const keysToCollapse = new Set<string>();
269
+
270
+ for (const key of keys) {
271
+ const values = rows.map((row) => (row[key] ?? "").trim());
272
+ const firstValue = values[0] ?? "";
273
+
274
+ if (firstValue.length > 0 && values.every((v) => v === firstValue)) {
275
+ uniform[key] = firstValue;
276
+ keysToCollapse.add(key);
277
+ }
278
+ }
279
+
280
+ if (keysToCollapse.size === 0) {
281
+ return { rows, uniform: {} };
282
+ }
283
+
284
+ const cleanedRows = rows.map((row) => {
285
+ const filtered: Record<string, string> = {};
286
+ for (const [key, value] of Object.entries(row)) {
287
+ if (!keysToCollapse.has(key)) {
288
+ filtered[key] = value;
289
+ }
290
+ }
291
+ return filtered;
292
+ });
293
+
294
+ return { rows: cleanedRows, uniform };
219
295
  }
220
296
 
221
297
  export function transformPods(jsonOutput: string): PodSummary | string {
@@ -487,11 +563,17 @@ export function transformGenericKubectl(
487
563
  parsedTable.headers.every((header) => /^[A-Z0-9_()\-/]+$/.test(header));
488
564
 
489
565
  if (looksLikeTable) {
490
- const rows = stripLowValueColumns(parsedTable.rows);
491
- const headers = parsedTable.headers.filter((headerName) =>
492
- rows.length === 0 ? true : rows.some((row) => headerName in row),
493
- );
494
- return { headers, rows };
566
+ const { rows: strippedRows, stripped } = stripLowValueColumns(parsedTable.rows);
567
+ const { rows: finalRows, uniform } = collapseUniformColumns(strippedRows);
568
+
569
+ const remainingKeys =
570
+ finalRows.length > 0 ? new Set(Object.keys(finalRows[0] ?? {})) : new Set<string>();
571
+ const headers = parsedTable.headers.filter((h) => remainingKeys.has(h));
572
+
573
+ const result: KubectlTableResult = { headers, rows: finalRows };
574
+ if (Object.keys(uniform).length > 0) result.uniform = uniform;
575
+ if (stripped.length > 0) result.stripped = stripped;
576
+ return result;
495
577
  }
496
578
 
497
579
  if (lines.length > 50) {