@64mb/freelens-power 1.2.2 → 1.3.0
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/README.md +3 -1
- package/out/main/common/store/monitoring-preferences-store.js +5 -0
- package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
- package/out/renderer/ai-diagnostic-handoff.js +52 -0
- package/out/renderer/ai-diagnostic-handoff.js.map +1 -0
- package/out/renderer/ai-extras.js +40 -4
- package/out/renderer/ai-extras.js.map +1 -1
- package/out/renderer/ai.js +48 -56
- package/out/renderer/ai.js.map +1 -1
- package/out/renderer/details/hpa-diagnostics-details.js +46 -0
- package/out/renderer/details/hpa-diagnostics-details.js.map +1 -0
- package/out/renderer/details/namespace-health-details.js +91 -0
- package/out/renderer/details/namespace-health-details.js.map +1 -0
- package/out/renderer/details/resource-health-details.js +131 -0
- package/out/renderer/details/resource-health-details.js.map +1 -0
- package/out/renderer/details/service-diagnostics-details.js +163 -0
- package/out/renderer/details/service-diagnostics-details.js.map +1 -0
- package/out/renderer/diagnostic-explain-button.js +16 -0
- package/out/renderer/diagnostic-explain-button.js.map +1 -0
- package/out/renderer/diagnostics-state.js +51 -0
- package/out/renderer/diagnostics-state.js.map +1 -0
- package/out/renderer/diagnostics.css.js +9 -0
- package/out/renderer/diagnostics.css.js.map +1 -1
- package/out/renderer/diagnostics.js +369 -73
- package/out/renderer/diagnostics.js.map +1 -1
- package/out/renderer/incident-copy-button.js +50 -0
- package/out/renderer/incident-copy-button.js.map +1 -0
- package/out/renderer/index.js +91 -19
- package/out/renderer/index.js.map +1 -1
- package/out/renderer/monitoring-history-collection.js +1 -1
- package/out/renderer/preferences/monitoring-preferences.js +10 -0
- package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
- package/out/renderer/preferences/preferences.js +88 -0
- package/out/renderer/preferences/preferences.js.map +1 -1
- package/out/renderer/resource-relationships.css.js +7 -0
- package/out/renderer/resource-relationships.css.js.map +1 -0
- package/out/renderer/resource-relationships.js +556 -0
- package/out/renderer/resource-relationships.js.map +1 -0
- package/out/renderer/resource-search-distance.js +24 -0
- package/out/renderer/resource-search-distance.js.map +1 -0
- package/out/renderer/resource-search-fields.js +55 -0
- package/out/renderer/resource-search-fields.js.map +1 -0
- package/out/renderer/resource-search-model.js +193 -0
- package/out/renderer/resource-search-model.js.map +1 -0
- package/out/renderer/resource-search.js +365 -0
- package/out/renderer/resource-search.js.map +1 -0
- package/out/renderer/src/common/hpa-diagnostics.js +24 -0
- package/out/renderer/src/common/hpa-diagnostics.js.map +1 -0
- package/out/renderer/src/common/incident-summary.js +73 -0
- package/out/renderer/src/common/incident-summary.js.map +1 -0
- package/out/renderer/src/common/resource-health.js +92 -0
- package/out/renderer/src/common/resource-health.js.map +1 -0
- package/out/renderer/src/common/resource-relationships.js +155 -0
- package/out/renderer/src/common/resource-relationships.js.map +1 -0
- package/out/renderer/src/common/service-diagnostics.js +50 -0
- package/out/renderer/src/common/service-diagnostics.js.map +1 -0
- package/out/renderer/src/common/store/monitoring-preferences-store.js +5 -0
- package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
- package/out/renderer/src/common/timeline-groups.js +36 -0
- package/out/renderer/src/common/timeline-groups.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-search-distance.js","names":[],"sources":["../../src/renderer/resource-search-distance.ts"],"sourcesContent":["export function boundedNameDistance(left: string, right: string, limit: number): number {\n if (left.length > 64 || right.length > 64 || Math.abs(left.length - right.length) > limit) return limit + 1;\n let previous = Array.from({ length: right.length + 1 }, (_, index) => index);\n let beforePrevious = previous;\n for (let row = 1; row <= left.length; row++) {\n const current = Array<number>(right.length + 1).fill(limit + 1);\n current[0] = row;\n let minimum = limit + 1;\n for (let column = Math.max(1, row - limit); column <= Math.min(right.length, row + limit); column++) {\n current[column] = Math.min(\n previous[column] + 1,\n current[column - 1] + 1,\n previous[column - 1] + (left[row - 1] === right[column - 1] ? 0 : 1),\n );\n if (row > 1 && column > 1 && left[row - 1] === right[column - 2] && left[row - 2] === right[column - 1])\n current[column] = Math.min(current[column], beforePrevious[column - 2] + 1);\n minimum = Math.min(minimum, current[column]);\n }\n if (minimum > limit) return limit + 1;\n beforePrevious = previous;\n previous = current;\n }\n return previous[right.length];\n}\n"],"mappings":";AAAA,SAAgB,oBAAoB,MAAc,OAAe,OAAuB;CACtF,IAAI,KAAK,SAAS,MAAM,MAAM,SAAS,MAAM,KAAK,IAAI,KAAK,SAAS,MAAM,MAAM,IAAI,OAAO,OAAO,QAAQ;CAC1G,IAAI,WAAW,MAAM,KAAK,EAAE,QAAQ,MAAM,SAAS,EAAE,IAAI,GAAG,UAAU,KAAK;CAC3E,IAAI,iBAAiB;CACrB,KAAK,IAAI,MAAM,GAAG,OAAO,KAAK,QAAQ,OAAO;EAC3C,MAAM,UAAU,MAAc,MAAM,SAAS,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;EAC9D,QAAQ,KAAK;EACb,IAAI,UAAU,QAAQ;EACtB,KAAK,IAAI,SAAS,KAAK,IAAI,GAAG,MAAM,KAAK,GAAG,UAAU,KAAK,IAAI,MAAM,QAAQ,MAAM,KAAK,GAAG,UAAU;GACnG,QAAQ,UAAU,KAAK,IACrB,SAAS,UAAU,GACnB,QAAQ,SAAS,KAAK,GACtB,SAAS,SAAS,MAAM,KAAK,MAAM,OAAO,MAAM,SAAS,KAAK,IAAI,EACpE;GACA,IAAI,MAAM,KAAK,SAAS,KAAK,KAAK,MAAM,OAAO,MAAM,SAAS,MAAM,KAAK,MAAM,OAAO,MAAM,SAAS,IACnG,QAAQ,UAAU,KAAK,IAAI,QAAQ,SAAS,eAAe,SAAS,KAAK,CAAC;GAC5E,UAAU,KAAK,IAAI,SAAS,QAAQ,OAAO;EAC7C;EACA,IAAI,UAAU,OAAO,OAAO,QAAQ;EACpC,iBAAiB;EACjB,WAAW;CACb;CACA,OAAO,SAAS,MAAM;AACxB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const require_ai_terminal_context = require("./src/common/ai-terminal-context.js");
|
|
2
|
+
//#region src/renderer/resource-search-fields.ts
|
|
3
|
+
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
4
|
+
var array = (value) => Array.isArray(value) ? value.slice(0, 32) : [];
|
|
5
|
+
function projectSearchFields(kind, value) {
|
|
6
|
+
if (kind === "Secret" || kind === "ConfigMap") return [];
|
|
7
|
+
const object = record(value);
|
|
8
|
+
const status = record(object.status);
|
|
9
|
+
const spec = record(object.spec);
|
|
10
|
+
const metadata = record(object.metadata);
|
|
11
|
+
const fields = [];
|
|
12
|
+
let remaining = 4096;
|
|
13
|
+
const add = (label, value, redact = false) => {
|
|
14
|
+
if (typeof value !== "string" || !remaining || fields.length >= 32) return;
|
|
15
|
+
const bounded = value.slice(0, 4096);
|
|
16
|
+
const text = (redact ? require_ai_terminal_context.redactAiTerminalText(bounded) : bounded).slice(0, Math.min(512, remaining));
|
|
17
|
+
if (text) {
|
|
18
|
+
fields.push({
|
|
19
|
+
label,
|
|
20
|
+
text
|
|
21
|
+
});
|
|
22
|
+
remaining -= text.length;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
add("Phase", status.phase);
|
|
26
|
+
for (const condition of array(status.conditions)) {
|
|
27
|
+
const item = record(condition);
|
|
28
|
+
add("Condition", item.type);
|
|
29
|
+
add("Reason", item.reason, true);
|
|
30
|
+
add("Message", item.message, true);
|
|
31
|
+
}
|
|
32
|
+
const template = record(record(spec.template).spec);
|
|
33
|
+
for (const container of [...array(spec.containers), ...array(template.containers)]) {
|
|
34
|
+
const item = record(container);
|
|
35
|
+
add("Container", item.name);
|
|
36
|
+
add("Image", item.image);
|
|
37
|
+
}
|
|
38
|
+
const selector = record(spec.selector);
|
|
39
|
+
for (const [key, value] of Object.entries({
|
|
40
|
+
...selector,
|
|
41
|
+
...record(selector.matchLabels)
|
|
42
|
+
}).slice(0, 32)) if (typeof value === "string") add("Selector", `${key}=${value}`);
|
|
43
|
+
const target = record(spec.scaleTargetRef);
|
|
44
|
+
add("Scale target", target.kind);
|
|
45
|
+
add("Scale target", target.name);
|
|
46
|
+
for (const owner of array(metadata.ownerReferences)) {
|
|
47
|
+
add("Owner kind", record(owner).kind);
|
|
48
|
+
add("Owner", record(owner).name);
|
|
49
|
+
}
|
|
50
|
+
return fields;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
exports.projectSearchFields = projectSearchFields;
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=resource-search-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-search-fields.js","names":[],"sources":["../../src/renderer/resource-search-fields.ts"],"sourcesContent":["import { redactAiTerminalText } from \"../common/ai-terminal-context\";\n\nexport interface SearchField {\n label: string;\n text: string;\n}\nconst record = (value: unknown): Record<string, unknown> =>\n value && typeof value === \"object\" && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\nconst array = (value: unknown): unknown[] => (Array.isArray(value) ? value.slice(0, 32) : []);\nexport function projectSearchFields(kind: string, value: unknown): SearchField[] {\n if (kind === \"Secret\" || kind === \"ConfigMap\") return [];\n const object = record(value);\n const status = record(object.status);\n const spec = record(object.spec);\n const metadata = record(object.metadata);\n const fields: SearchField[] = [];\n let remaining = 4096;\n const add = (label: string, value: unknown, redact = false) => {\n if (typeof value !== \"string\" || !remaining || fields.length >= 32) return;\n const bounded = value.slice(0, 4096);\n const text = (redact ? redactAiTerminalText(bounded) : bounded).slice(0, Math.min(512, remaining));\n if (text) {\n fields.push({ label, text });\n remaining -= text.length;\n }\n };\n add(\"Phase\", status.phase);\n for (const condition of array(status.conditions)) {\n const item = record(condition);\n add(\"Condition\", item.type);\n add(\"Reason\", item.reason, true);\n add(\"Message\", item.message, true);\n }\n const template = record(record(spec.template).spec);\n for (const container of [...array(spec.containers), ...array(template.containers)]) {\n const item = record(container);\n add(\"Container\", item.name);\n add(\"Image\", item.image);\n }\n const selector = record(spec.selector);\n for (const [key, value] of Object.entries({ ...selector, ...record(selector.matchLabels) }).slice(0, 32)) {\n if (typeof value === \"string\") add(\"Selector\", `${key}=${value}`);\n }\n const target = record(spec.scaleTargetRef);\n add(\"Scale target\", target.kind);\n add(\"Scale target\", target.name);\n for (const owner of array(metadata.ownerReferences)) {\n add(\"Owner kind\", record(owner).kind);\n add(\"Owner\", record(owner).name);\n }\n return fields;\n}\n"],"mappings":";;AAMA,IAAM,UAAU,UACd,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAK,QAAoC,CAAC;AACtG,IAAM,SAAS,UAA+B,MAAM,QAAQ,KAAK,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC;AAC3F,SAAgB,oBAAoB,MAAc,OAA+B;CAC/E,IAAI,SAAS,YAAY,SAAS,aAAa,OAAO,CAAC;CACvD,MAAM,SAAS,OAAO,KAAK;CAC3B,MAAM,SAAS,OAAO,OAAO,MAAM;CACnC,MAAM,OAAO,OAAO,OAAO,IAAI;CAC/B,MAAM,WAAW,OAAO,OAAO,QAAQ;CACvC,MAAM,SAAwB,CAAC;CAC/B,IAAI,YAAY;CAChB,MAAM,OAAO,OAAe,OAAgB,SAAS,UAAU;EAC7D,IAAI,OAAO,UAAU,YAAY,CAAC,aAAa,OAAO,UAAU,IAAI;EACpE,MAAM,UAAU,MAAM,MAAM,GAAG,IAAI;EACnC,MAAM,QAAQ,SAAS,4BAAA,qBAAqB,OAAO,IAAI,QAAA,CAAS,MAAM,GAAG,KAAK,IAAI,KAAK,SAAS,CAAC;EACjG,IAAI,MAAM;GACR,OAAO,KAAK;IAAE;IAAO;GAAK,CAAC;GAC3B,aAAa,KAAK;EACpB;CACF;CACA,IAAI,SAAS,OAAO,KAAK;CACzB,KAAK,MAAM,aAAa,MAAM,OAAO,UAAU,GAAG;EAChD,MAAM,OAAO,OAAO,SAAS;EAC7B,IAAI,aAAa,KAAK,IAAI;EAC1B,IAAI,UAAU,KAAK,QAAQ,IAAI;EAC/B,IAAI,WAAW,KAAK,SAAS,IAAI;CACnC;CACA,MAAM,WAAW,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,IAAI;CAClD,KAAK,MAAM,aAAa,CAAC,GAAG,MAAM,KAAK,UAAU,GAAG,GAAG,MAAM,SAAS,UAAU,CAAC,GAAG;EAClF,MAAM,OAAO,OAAO,SAAS;EAC7B,IAAI,aAAa,KAAK,IAAI;EAC1B,IAAI,SAAS,KAAK,KAAK;CACzB;CACA,MAAM,WAAW,OAAO,KAAK,QAAQ;CACrC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ;EAAE,GAAG;EAAU,GAAG,OAAO,SAAS,WAAW;CAAE,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,GACrG,IAAI,OAAO,UAAU,UAAU,IAAI,YAAY,GAAG,IAAI,GAAG,OAAO;CAElE,MAAM,SAAS,OAAO,KAAK,cAAc;CACzC,IAAI,gBAAgB,OAAO,IAAI;CAC/B,IAAI,gBAAgB,OAAO,IAAI;CAC/B,KAAK,MAAM,SAAS,MAAM,SAAS,eAAe,GAAG;EACnD,IAAI,cAAc,OAAO,KAAK,CAAC,CAAC,IAAI;EACpC,IAAI,SAAS,OAAO,KAAK,CAAC,CAAC,IAAI;CACjC;CACA,OAAO;AACT"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
const require_resource_search_distance = require("./resource-search-distance.js");
|
|
2
|
+
//#region src/renderer/resource-search-model.ts
|
|
3
|
+
var RESOURCE_SEARCH_MAX_DOCUMENT_CHARS = 4096;
|
|
4
|
+
var queryTokens = (query) => query.slice(0, 300).toLocaleLowerCase().trim().split(/\s+/).filter(Boolean);
|
|
5
|
+
var metadataText = (resource) => [
|
|
6
|
+
resource.kind,
|
|
7
|
+
resource.name,
|
|
8
|
+
resource.namespace ?? "",
|
|
9
|
+
...Object.entries(resource.labels).map(([key, value]) => `${key}=${value}`)
|
|
10
|
+
].join(" ");
|
|
11
|
+
function rankResources(resources, tokens) {
|
|
12
|
+
const score = (resource) => tokens.reduce((total, token) => {
|
|
13
|
+
const name = resource.name.toLocaleLowerCase();
|
|
14
|
+
const kind = resource.kind.toLocaleLowerCase();
|
|
15
|
+
const namespace = (resource.namespace ?? "").toLocaleLowerCase();
|
|
16
|
+
return total + (name === token ? 0 : name.startsWith(token) ? 1 : kind === token ? 2 : name.includes(token) ? 3 : kind.includes(token) ? 4 : namespace.includes(token) ? 5 : 6);
|
|
17
|
+
}, 0);
|
|
18
|
+
return resources.sort((a, b) => score(a) - score(b) || a.kind.localeCompare(b.kind) || a.name.localeCompare(b.name));
|
|
19
|
+
}
|
|
20
|
+
function createResourceSearchIndex(resources) {
|
|
21
|
+
const documents = resources.filter((resource) => resource.kind !== "Secret" && resource.kind !== "ConfigMap");
|
|
22
|
+
const vocabulary = /* @__PURE__ */ new Map();
|
|
23
|
+
const names = /* @__PURE__ */ new Map();
|
|
24
|
+
let lastQuery;
|
|
25
|
+
let lastResults = [];
|
|
26
|
+
let similarPaths = /* @__PURE__ */ new Set();
|
|
27
|
+
let partsPaths = /* @__PURE__ */ new Set();
|
|
28
|
+
const nameParts = /* @__PURE__ */ new Map();
|
|
29
|
+
const partVocabulary = /* @__PURE__ */ new Map();
|
|
30
|
+
const snippets = /* @__PURE__ */ new Map();
|
|
31
|
+
const metadata = /* @__PURE__ */ new Map();
|
|
32
|
+
documents.forEach((resource, id) => {
|
|
33
|
+
const parts = resource.name.toLocaleLowerCase().split(/[-._]/).filter(Boolean).slice(0, 16);
|
|
34
|
+
nameParts.set(id, parts);
|
|
35
|
+
for (const part of parts) {
|
|
36
|
+
let ids = partVocabulary.get(part);
|
|
37
|
+
if (!ids) {
|
|
38
|
+
ids = /* @__PURE__ */ new Set();
|
|
39
|
+
partVocabulary.set(part, ids);
|
|
40
|
+
}
|
|
41
|
+
ids.add(id);
|
|
42
|
+
}
|
|
43
|
+
for (const name of new Set([resource.name, ...resource.name.split(/[-.]/)].map((name) => name.toLocaleLowerCase()))) {
|
|
44
|
+
if (name.length < 3 || name.length > 64) continue;
|
|
45
|
+
let bucket = names.get(name.length);
|
|
46
|
+
if (!bucket) {
|
|
47
|
+
bucket = /* @__PURE__ */ new Map();
|
|
48
|
+
names.set(name.length, bucket);
|
|
49
|
+
}
|
|
50
|
+
let ids = bucket.get(name);
|
|
51
|
+
if (!ids) {
|
|
52
|
+
ids = /* @__PURE__ */ new Set();
|
|
53
|
+
bucket.set(name, ids);
|
|
54
|
+
}
|
|
55
|
+
ids.add(id);
|
|
56
|
+
}
|
|
57
|
+
const identity = metadataText(resource).slice(0, RESOURCE_SEARCH_MAX_DOCUMENT_CHARS);
|
|
58
|
+
metadata.set(resource.path, identity.toLocaleLowerCase());
|
|
59
|
+
let remaining = RESOURCE_SEARCH_MAX_DOCUMENT_CHARS - identity.length;
|
|
60
|
+
const fields = [];
|
|
61
|
+
for (const field of resource.fields ?? []) {
|
|
62
|
+
if (remaining <= 1) break;
|
|
63
|
+
const text = field.text.slice(0, remaining - 1);
|
|
64
|
+
fields.push({
|
|
65
|
+
label: field.label,
|
|
66
|
+
text
|
|
67
|
+
});
|
|
68
|
+
remaining -= text.length + 1;
|
|
69
|
+
}
|
|
70
|
+
snippets.set(resource.path, fields);
|
|
71
|
+
for (const word of new Set([identity, ...fields.map((field) => field.text)].join(" ").toLocaleLowerCase().split(/\s+/))) {
|
|
72
|
+
if (!word) continue;
|
|
73
|
+
let ids = vocabulary.get(word);
|
|
74
|
+
if (!ids) {
|
|
75
|
+
ids = /* @__PURE__ */ new Set();
|
|
76
|
+
vocabulary.set(word, ids);
|
|
77
|
+
}
|
|
78
|
+
ids.add(id);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
search(query) {
|
|
83
|
+
query = query.slice(0, 300);
|
|
84
|
+
if (lastQuery === query) return lastResults;
|
|
85
|
+
lastQuery = query;
|
|
86
|
+
similarPaths = /* @__PURE__ */ new Set();
|
|
87
|
+
partsPaths = /* @__PURE__ */ new Set();
|
|
88
|
+
lastResults = [];
|
|
89
|
+
const tokens = queryTokens(query);
|
|
90
|
+
const penalties = /* @__PURE__ */ new Map();
|
|
91
|
+
let candidates;
|
|
92
|
+
for (const token of tokens) {
|
|
93
|
+
const found = /* @__PURE__ */ new Set();
|
|
94
|
+
for (const [word, ids] of vocabulary) if (word.includes(token)) for (const id of ids) found.add(id);
|
|
95
|
+
if (/^[a-z0-9]+(?:[-._][a-z0-9]+)+$/.test(token)) {
|
|
96
|
+
const parts = token.split(/[-._]/);
|
|
97
|
+
if (parts.length <= 16) {
|
|
98
|
+
let possible;
|
|
99
|
+
for (const part of parts) {
|
|
100
|
+
const ids = partVocabulary.get(part) ?? /* @__PURE__ */ new Set();
|
|
101
|
+
possible = possible === void 0 ? ids : new Set([...possible].filter((id) => ids.has(id)));
|
|
102
|
+
}
|
|
103
|
+
for (const id of possible ?? []) {
|
|
104
|
+
if (found.has(id)) continue;
|
|
105
|
+
let offset = 0;
|
|
106
|
+
for (const part of nameParts.get(id) ?? []) if (part === parts[offset]) offset++;
|
|
107
|
+
if (offset === parts.length) {
|
|
108
|
+
found.add(id);
|
|
109
|
+
penalties.set(id, (penalties.get(id) ?? 0) + 1);
|
|
110
|
+
partsPaths.add(documents[id].path);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const exact = new Set(found);
|
|
116
|
+
const limit = token.length >= 7 && token.length <= 64 ? 2 : token.length >= 4 && token.length <= 6 ? 1 : 0;
|
|
117
|
+
if (limit) {
|
|
118
|
+
const distances = /* @__PURE__ */ new Map();
|
|
119
|
+
for (let length = token.length - limit; length <= token.length + limit; length++) for (const [name, ids] of names.get(length) ?? []) {
|
|
120
|
+
const distance = require_resource_search_distance.boundedNameDistance(token, name, limit);
|
|
121
|
+
if (distance > limit) continue;
|
|
122
|
+
for (const id of ids) if (!exact.has(id)) distances.set(id, Math.min(distances.get(id) ?? Infinity, distance));
|
|
123
|
+
}
|
|
124
|
+
for (const [id, distance] of distances) {
|
|
125
|
+
found.add(id);
|
|
126
|
+
penalties.set(id, (penalties.get(id) ?? 0) + 10 * distance);
|
|
127
|
+
similarPaths.add(documents[id].path);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
candidates = candidates === void 0 ? found : new Set([...candidates].filter((id) => found.has(id)));
|
|
131
|
+
if (!candidates.size) return [];
|
|
132
|
+
}
|
|
133
|
+
lastResults = rankResources(candidates === void 0 ? [...documents] : [...candidates].map((id) => documents[id]), tokens);
|
|
134
|
+
const penaltyByPath = new Map([...penalties].map(([id, penalty]) => [documents[id].path, penalty]));
|
|
135
|
+
lastResults.sort((left, right) => (penaltyByPath.get(left.path) ?? 0) - (penaltyByPath.get(right.path) ?? 0));
|
|
136
|
+
return lastResults;
|
|
137
|
+
},
|
|
138
|
+
nameParts(resource) {
|
|
139
|
+
return partsPaths.has(resource.path);
|
|
140
|
+
},
|
|
141
|
+
similarName(resource) {
|
|
142
|
+
return similarPaths.has(resource.path);
|
|
143
|
+
},
|
|
144
|
+
snippet(resource, query) {
|
|
145
|
+
const tokens = queryTokens(query);
|
|
146
|
+
const identity = metadata.get(resource.path) ?? "";
|
|
147
|
+
const bodyTokens = tokens.filter((token) => !identity.includes(token));
|
|
148
|
+
if (!bodyTokens.length) return;
|
|
149
|
+
const field = snippets.get(resource.path)?.find((item) => bodyTokens.some((token) => item.text.toLocaleLowerCase().includes(token)));
|
|
150
|
+
if (!field) return;
|
|
151
|
+
const offset = Math.max(0, Math.min(...bodyTokens.map((token) => field.text.toLocaleLowerCase().indexOf(token)).filter((index) => index >= 0)) - 35);
|
|
152
|
+
return {
|
|
153
|
+
label: field.label,
|
|
154
|
+
text: (offset ? "…" : "") + field.text.slice(offset, offset + 150) + (field.text.length > offset + 150 ? "…" : "")
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function createDoubleShift() {
|
|
160
|
+
let last = 0;
|
|
161
|
+
let held = false;
|
|
162
|
+
const otherKeys = /* @__PURE__ */ new Set();
|
|
163
|
+
return (event, now) => {
|
|
164
|
+
const physicalKey = event.code || event.key;
|
|
165
|
+
if (event.type === "keyup") {
|
|
166
|
+
if (event.key === "Shift") held = false;
|
|
167
|
+
else otherKeys.delete(physicalKey);
|
|
168
|
+
if (event.key === "Meta") {
|
|
169
|
+
otherKeys.clear();
|
|
170
|
+
held = false;
|
|
171
|
+
last = 0;
|
|
172
|
+
}
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
if (event.key !== "Shift") otherKeys.add(physicalKey);
|
|
176
|
+
if (event.key !== "Shift" || otherKeys.size > 0 || event.altKey || event.ctrlKey || event.metaKey) {
|
|
177
|
+
last = 0;
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
if (event.repeat || held) return false;
|
|
181
|
+
held = true;
|
|
182
|
+
const hit = last > 0 && now - last <= 400;
|
|
183
|
+
last = hit ? 0 : now;
|
|
184
|
+
return hit;
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
//#endregion
|
|
188
|
+
exports.RESOURCE_SEARCH_MAX_DOCUMENT_CHARS = RESOURCE_SEARCH_MAX_DOCUMENT_CHARS;
|
|
189
|
+
exports.createDoubleShift = createDoubleShift;
|
|
190
|
+
exports.createResourceSearchIndex = createResourceSearchIndex;
|
|
191
|
+
exports.queryTokens = queryTokens;
|
|
192
|
+
|
|
193
|
+
//# sourceMappingURL=resource-search-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-search-model.js","names":[],"sources":["../../src/renderer/resource-search-model.ts"],"sourcesContent":["import { boundedNameDistance } from \"./resource-search-distance\";\n\nimport type { SearchField } from \"./resource-search-fields\";\nexport interface SearchResource {\n kind: string;\n name: string;\n namespace?: string;\n labels: Record<string, string>;\n path: string;\n fields?: SearchField[];\n}\n\nexport const RESOURCE_SEARCH_MAX_DOCUMENT_CHARS = 4096;\nexport const queryTokens = (query: string) =>\n query.slice(0, 300).toLocaleLowerCase().trim().split(/\\s+/).filter(Boolean);\nconst metadataText = (resource: SearchResource) =>\n [\n resource.kind,\n resource.name,\n resource.namespace ?? \"\",\n ...Object.entries(resource.labels).map(([key, value]) => `${key}=${value}`),\n ].join(\" \");\nfunction rankResources(resources: SearchResource[], tokens: string[]) {\n const score = (resource: SearchResource) =>\n tokens.reduce((total, token) => {\n const name = resource.name.toLocaleLowerCase();\n const kind = resource.kind.toLocaleLowerCase();\n const namespace = (resource.namespace ?? \"\").toLocaleLowerCase();\n return (\n total +\n (name === token\n ? 0\n : name.startsWith(token)\n ? 1\n : kind === token\n ? 2\n : name.includes(token)\n ? 3\n : kind.includes(token)\n ? 4\n : namespace.includes(token)\n ? 5\n : 6)\n );\n }, 0);\n\n return resources.sort((a, b) => score(a) - score(b) || a.kind.localeCompare(b.kind) || a.name.localeCompare(b.name));\n}\n\nexport function createResourceSearchIndex(resources: SearchResource[]) {\n const documents = resources.filter((resource) => resource.kind !== \"Secret\" && resource.kind !== \"ConfigMap\");\n const vocabulary = new Map<string, Set<number>>();\n const names = new Map<number, Map<string, Set<number>>>();\n let lastQuery: string | undefined;\n let lastResults: SearchResource[] = [];\n let similarPaths = new Set<string>();\n let partsPaths = new Set<string>();\n const nameParts = new Map<number, string[]>();\n const partVocabulary = new Map<string, Set<number>>();\n const snippets = new Map<string, SearchField[]>();\n const metadata = new Map<string, string>();\n documents.forEach((resource, id) => {\n const parts = resource.name.toLocaleLowerCase().split(/[-._]/).filter(Boolean).slice(0, 16);\n nameParts.set(id, parts);\n for (const part of parts) {\n let ids = partVocabulary.get(part);\n if (!ids) {\n ids = new Set();\n partVocabulary.set(part, ids);\n }\n ids.add(id);\n }\n for (const name of new Set(\n [resource.name, ...resource.name.split(/[-.]/)].map((name) => name.toLocaleLowerCase()),\n )) {\n if (name.length < 3 || name.length > 64) continue;\n let bucket = names.get(name.length);\n if (!bucket) {\n bucket = new Map();\n names.set(name.length, bucket);\n }\n let ids = bucket.get(name);\n if (!ids) {\n ids = new Set();\n bucket.set(name, ids);\n }\n ids.add(id);\n }\n const identity = metadataText(resource).slice(0, RESOURCE_SEARCH_MAX_DOCUMENT_CHARS);\n metadata.set(resource.path, identity.toLocaleLowerCase());\n let remaining = RESOURCE_SEARCH_MAX_DOCUMENT_CHARS - identity.length;\n const fields: SearchField[] = [];\n for (const field of resource.fields ?? []) {\n if (remaining <= 1) break;\n const text = field.text.slice(0, remaining - 1);\n fields.push({ label: field.label, text });\n remaining -= text.length + 1;\n }\n snippets.set(resource.path, fields);\n for (const word of new Set(\n [identity, ...fields.map((field) => field.text)].join(\" \").toLocaleLowerCase().split(/\\s+/),\n )) {\n if (!word) continue;\n let ids = vocabulary.get(word);\n if (!ids) {\n ids = new Set();\n vocabulary.set(word, ids);\n }\n ids.add(id);\n }\n });\n return {\n search(query: string): SearchResource[] {\n query = query.slice(0, 300);\n if (lastQuery === query) return lastResults;\n lastQuery = query;\n similarPaths = new Set();\n partsPaths = new Set();\n lastResults = [];\n const tokens = queryTokens(query);\n const penalties = new Map<number, number>();\n let candidates: Set<number> | undefined;\n for (const token of tokens) {\n const found = new Set<number>();\n for (const [word, ids] of vocabulary) if (word.includes(token)) for (const id of ids) found.add(id);\n if (/^[a-z0-9]+(?:[-._][a-z0-9]+)+$/.test(token)) {\n const parts = token.split(/[-._]/);\n if (parts.length <= 16) {\n let possible: Set<number> | undefined;\n for (const part of parts) {\n const ids = partVocabulary.get(part) ?? new Set<number>();\n possible = possible === undefined ? ids : new Set([...possible].filter((id) => ids.has(id)));\n }\n for (const id of possible ?? []) {\n if (found.has(id)) continue;\n let offset = 0;\n for (const part of nameParts.get(id) ?? []) if (part === parts[offset]) offset++;\n if (offset === parts.length) {\n found.add(id);\n penalties.set(id, (penalties.get(id) ?? 0) + 1);\n partsPaths.add(documents[id].path);\n }\n }\n }\n }\n const exact = new Set(found);\n const limit = token.length >= 7 && token.length <= 64 ? 2 : token.length >= 4 && token.length <= 6 ? 1 : 0;\n if (limit) {\n const distances = new Map<number, number>();\n for (let length = token.length - limit; length <= token.length + limit; length++) {\n for (const [name, ids] of names.get(length) ?? []) {\n const distance = boundedNameDistance(token, name, limit);\n if (distance > limit) continue;\n for (const id of ids)\n if (!exact.has(id)) distances.set(id, Math.min(distances.get(id) ?? Infinity, distance));\n }\n }\n for (const [id, distance] of distances) {\n found.add(id);\n penalties.set(id, (penalties.get(id) ?? 0) + 10 * distance);\n similarPaths.add(documents[id].path);\n }\n }\n candidates = candidates === undefined ? found : new Set([...candidates].filter((id) => found.has(id)));\n if (!candidates.size) return [];\n }\n lastResults = rankResources(\n candidates === undefined ? [...documents] : [...candidates].map((id) => documents[id]),\n tokens,\n );\n const penaltyByPath = new Map([...penalties].map(([id, penalty]) => [documents[id].path, penalty]));\n lastResults.sort((left, right) => (penaltyByPath.get(left.path) ?? 0) - (penaltyByPath.get(right.path) ?? 0));\n return lastResults;\n },\n nameParts(resource: SearchResource): boolean {\n return partsPaths.has(resource.path);\n },\n similarName(resource: SearchResource): boolean {\n return similarPaths.has(resource.path);\n },\n snippet(resource: SearchResource, query: string): SearchField | undefined {\n const tokens = queryTokens(query);\n const identity = metadata.get(resource.path) ?? \"\";\n const bodyTokens = tokens.filter((token) => !identity.includes(token));\n if (!bodyTokens.length) return;\n const field = snippets\n .get(resource.path)\n ?.find((item) => bodyTokens.some((token) => item.text.toLocaleLowerCase().includes(token)));\n if (!field) return;\n const offset = Math.max(\n 0,\n Math.min(\n ...bodyTokens.map((token) => field.text.toLocaleLowerCase().indexOf(token)).filter((index) => index >= 0),\n ) - 35,\n );\n return {\n label: field.label,\n text:\n (offset ? \"…\" : \"\") + field.text.slice(offset, offset + 150) + (field.text.length > offset + 150 ? \"…\" : \"\"),\n };\n },\n };\n}\n\nexport function matchResources(resources: SearchResource[], query: string): SearchResource[] {\n return createResourceSearchIndex(resources).search(query);\n}\n\nexport function createDoubleShift() {\n let last = 0;\n let held = false;\n const otherKeys = new Set<string>();\n return (\n event: Pick<KeyboardEvent, \"key\" | \"type\" | \"repeat\" | \"altKey\" | \"ctrlKey\" | \"metaKey\"> &\n Partial<Pick<KeyboardEvent, \"code\">>,\n now: number,\n ) => {\n const physicalKey = event.code || event.key;\n if (event.type === \"keyup\") {\n if (event.key === \"Shift\") held = false;\n else otherKeys.delete(physicalKey);\n if (event.key === \"Meta\") {\n otherKeys.clear();\n held = false;\n last = 0;\n }\n return false;\n }\n if (event.key !== \"Shift\") otherKeys.add(physicalKey);\n if (event.key !== \"Shift\" || otherKeys.size > 0 || event.altKey || event.ctrlKey || event.metaKey) {\n last = 0;\n return false;\n }\n if (event.repeat || held) return false;\n held = true;\n const hit = last > 0 && now - last <= 400;\n last = hit ? 0 : now;\n return hit;\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
const require_extensions = require("./_virtual/_global-external_@freelensapp/extensions.js");
|
|
2
|
+
const require__global_external_mobx = require("./_virtual/_global-external_mobx.js");
|
|
3
|
+
const require__global_external_react = require("./_virtual/_global-external_react.js");
|
|
4
|
+
const require__global_external_react_dom = require("./_virtual/_global-external_react-dom.js");
|
|
5
|
+
const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
|
|
6
|
+
const require_ai_icon = require("./ai-icon.js");
|
|
7
|
+
const require_ai_diagnostic_handoff = require("./ai-diagnostic-handoff.js");
|
|
8
|
+
const require_diagnostic_explain_button = require("./diagnostic-explain-button.js");
|
|
9
|
+
const require_resource_search_fields = require("./resource-search-fields.js");
|
|
10
|
+
const require_resource_search_model = require("./resource-search-model.js");
|
|
11
|
+
//#region src/renderer/resource-search.tsx
|
|
12
|
+
var OPEN = "power-resource-search";
|
|
13
|
+
var activeId = () => require_extensions.Renderer.Catalog.activeCluster.get()?.metadata.uid;
|
|
14
|
+
var inventory = () => [
|
|
15
|
+
[
|
|
16
|
+
"Pod",
|
|
17
|
+
require_extensions.Renderer.K8sApi.podsStore,
|
|
18
|
+
"view_in_ar"
|
|
19
|
+
],
|
|
20
|
+
[
|
|
21
|
+
"Node",
|
|
22
|
+
require_extensions.Renderer.K8sApi.nodesStore,
|
|
23
|
+
"dns"
|
|
24
|
+
],
|
|
25
|
+
[
|
|
26
|
+
"Deployment",
|
|
27
|
+
require_extensions.Renderer.K8sApi.deploymentStore,
|
|
28
|
+
"layers"
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
"StatefulSet",
|
|
32
|
+
require_extensions.Renderer.K8sApi.statefulSetStore,
|
|
33
|
+
"layers"
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
"DaemonSet",
|
|
37
|
+
require_extensions.Renderer.K8sApi.daemonSetStore,
|
|
38
|
+
"layers"
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
"ReplicaSet",
|
|
42
|
+
require_extensions.Renderer.K8sApi.replicaSetStore,
|
|
43
|
+
"layers"
|
|
44
|
+
],
|
|
45
|
+
[
|
|
46
|
+
"Job",
|
|
47
|
+
require_extensions.Renderer.K8sApi.jobStore,
|
|
48
|
+
"work"
|
|
49
|
+
],
|
|
50
|
+
[
|
|
51
|
+
"CronJob",
|
|
52
|
+
require_extensions.Renderer.K8sApi.cronJobStore,
|
|
53
|
+
"schedule"
|
|
54
|
+
],
|
|
55
|
+
[
|
|
56
|
+
"Service",
|
|
57
|
+
require_extensions.Renderer.K8sApi.serviceStore,
|
|
58
|
+
"settings_ethernet"
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
"Ingress",
|
|
62
|
+
require_extensions.Renderer.K8sApi.ingressStore,
|
|
63
|
+
"alt_route"
|
|
64
|
+
],
|
|
65
|
+
[
|
|
66
|
+
"Namespace",
|
|
67
|
+
require_extensions.Renderer.K8sApi.namespaceStore,
|
|
68
|
+
"folder"
|
|
69
|
+
],
|
|
70
|
+
[
|
|
71
|
+
"HorizontalPodAutoscaler",
|
|
72
|
+
require_extensions.Renderer.K8sApi.hpaStore,
|
|
73
|
+
"swap_vert"
|
|
74
|
+
]
|
|
75
|
+
];
|
|
76
|
+
var icons = new Map(inventory().map(([kind, , icon]) => [kind, icon]));
|
|
77
|
+
function project(kind, objects) {
|
|
78
|
+
return objects.slice(0, 500).flatMap((object) => object.metadata.name ? [{
|
|
79
|
+
kind,
|
|
80
|
+
name: object.metadata.name,
|
|
81
|
+
namespace: object.metadata.namespace,
|
|
82
|
+
labels: Object.fromEntries(Object.entries(object.metadata.labels ?? {}).filter((entry) => typeof entry[1] === "string")),
|
|
83
|
+
path: object.selfLink,
|
|
84
|
+
fields: require_resource_search_fields.projectSearchFields(kind, object)
|
|
85
|
+
}] : []);
|
|
86
|
+
}
|
|
87
|
+
function SearchSnippet({ field, query }) {
|
|
88
|
+
if (!field) return null;
|
|
89
|
+
const token = require_resource_search_model.queryTokens(query).find((token) => field.text.toLocaleLowerCase().includes(token));
|
|
90
|
+
const offset = token ? field.text.toLocaleLowerCase().indexOf(token) : -1;
|
|
91
|
+
return /* @__PURE__ */ require_jsx_runtime.jsxs("small", {
|
|
92
|
+
className: "power-resource-search-snippet",
|
|
93
|
+
children: [
|
|
94
|
+
field.label,
|
|
95
|
+
":",
|
|
96
|
+
" ",
|
|
97
|
+
offset < 0 || !token ? field.text : /* @__PURE__ */ require_jsx_runtime.jsxs(require_jsx_runtime.Fragment, { children: [
|
|
98
|
+
field.text.slice(0, offset),
|
|
99
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("mark", { children: field.text.slice(offset, offset + token.length) }),
|
|
100
|
+
field.text.slice(offset + token.length)
|
|
101
|
+
] })
|
|
102
|
+
]
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function SearchDialog({ close, clusterId }) {
|
|
106
|
+
const [query, setQuery] = require__global_external_react.useState("");
|
|
107
|
+
const [resources, setResources] = require__global_external_react.useState([]);
|
|
108
|
+
const [loading, setLoading] = require__global_external_react.useState(true);
|
|
109
|
+
const [failed, setFailed] = require__global_external_react.useState(0);
|
|
110
|
+
const [selectedPath, setSelectedPath] = require__global_external_react.useState();
|
|
111
|
+
const [error, setError] = require__global_external_react.useState("");
|
|
112
|
+
const dialog = require__global_external_react.useRef(null);
|
|
113
|
+
const input = require__global_external_react.useRef(null);
|
|
114
|
+
const searchIndex = require__global_external_react.useMemo(() => require_resource_search_model.createResourceSearchIndex(resources), [resources]);
|
|
115
|
+
const matches = searchIndex.search(query);
|
|
116
|
+
const selectedResource = matches.find((resource) => resource.path === selectedPath) ?? matches[0];
|
|
117
|
+
const results = matches.slice(0, 100);
|
|
118
|
+
if (selectedResource && !results.includes(selectedResource)) results[results.length - 1] = selectedResource;
|
|
119
|
+
const selected = results.findIndex((resource) => resource.path === selectedResource?.path);
|
|
120
|
+
require__global_external_react.useEffect(() => {
|
|
121
|
+
if (selectedPath !== void 0 && selectedPath !== selectedResource?.path) setSelectedPath(void 0);
|
|
122
|
+
}, [selectedPath, selectedResource?.path]);
|
|
123
|
+
require__global_external_react.useEffect(() => {
|
|
124
|
+
const previous = document.activeElement;
|
|
125
|
+
input.current?.focus();
|
|
126
|
+
const controller = new AbortController();
|
|
127
|
+
const timeout = window.setTimeout(() => controller.abort(), 15e3);
|
|
128
|
+
let live = true;
|
|
129
|
+
const sources = inventory();
|
|
130
|
+
const parts = sources.map(([kind, store]) => project(kind, store.items));
|
|
131
|
+
setResources(parts.flat());
|
|
132
|
+
let next = 0;
|
|
133
|
+
const worker = async () => {
|
|
134
|
+
while (next < sources.length && live && activeId() === clusterId) {
|
|
135
|
+
const index = next++;
|
|
136
|
+
const [kind, store] = sources[index];
|
|
137
|
+
try {
|
|
138
|
+
const objects = await store.api.list({
|
|
139
|
+
namespace: "",
|
|
140
|
+
reqInit: { signal: controller.signal }
|
|
141
|
+
}, { limit: 500 });
|
|
142
|
+
if (!live || activeId() !== clusterId) return;
|
|
143
|
+
parts[index] = project(kind, objects ?? []);
|
|
144
|
+
setResources(parts.flat());
|
|
145
|
+
} catch {
|
|
146
|
+
if (live && activeId() === clusterId) setFailed((count) => count + 1);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
Promise.all([worker(), worker()]).then(() => {
|
|
151
|
+
if (live) setLoading(false);
|
|
152
|
+
});
|
|
153
|
+
return () => {
|
|
154
|
+
live = false;
|
|
155
|
+
window.clearTimeout(timeout);
|
|
156
|
+
controller.abort();
|
|
157
|
+
if (previous?.isConnected) previous.focus();
|
|
158
|
+
};
|
|
159
|
+
}, [clusterId]);
|
|
160
|
+
require__global_external_react.useEffect(() => {
|
|
161
|
+
document.getElementById(`power-resource-result-${selected}`)?.scrollIntoView?.({ block: "nearest" });
|
|
162
|
+
}, [selected, selectedResource?.path]);
|
|
163
|
+
const open = (resource) => {
|
|
164
|
+
if (activeId() !== clusterId) return;
|
|
165
|
+
Promise.resolve().then(() => require_extensions.Renderer.Navigation.showDetails(resource.path)).then(() => {
|
|
166
|
+
if (activeId() === clusterId) close();
|
|
167
|
+
}).catch(() => setError("Could not open this resource. Try again or refresh the inventory."));
|
|
168
|
+
};
|
|
169
|
+
return /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
170
|
+
className: "power-resource-search-backdrop",
|
|
171
|
+
"data-freelens-power-ai-overlay": "",
|
|
172
|
+
onClick: (event) => event.stopPropagation(),
|
|
173
|
+
onMouseDown: (event) => {
|
|
174
|
+
event.stopPropagation();
|
|
175
|
+
if (event.target === event.currentTarget) close();
|
|
176
|
+
},
|
|
177
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
178
|
+
ref: dialog,
|
|
179
|
+
role: "dialog",
|
|
180
|
+
"aria-modal": "true",
|
|
181
|
+
"aria-labelledby": "power-resource-search-title",
|
|
182
|
+
className: "power-resource-search-dialog",
|
|
183
|
+
onKeyDown: (event) => {
|
|
184
|
+
if (event.key === "Escape") {
|
|
185
|
+
event.stopPropagation();
|
|
186
|
+
close();
|
|
187
|
+
}
|
|
188
|
+
if (event.key === "Tab") {
|
|
189
|
+
const controls = Array.from(dialog.current?.querySelectorAll("input, button:not(:disabled)") ?? []);
|
|
190
|
+
const index = controls.indexOf(document.activeElement);
|
|
191
|
+
if (event.shiftKey && index <= 0) {
|
|
192
|
+
event.preventDefault();
|
|
193
|
+
controls.at(-1)?.focus();
|
|
194
|
+
} else if (!event.shiftKey && index === controls.length - 1) {
|
|
195
|
+
event.preventDefault();
|
|
196
|
+
controls[0]?.focus();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
children: [
|
|
201
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
202
|
+
className: "power-resource-search-heading",
|
|
203
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsxs("strong", {
|
|
204
|
+
id: "power-resource-search-title",
|
|
205
|
+
style: {
|
|
206
|
+
display: "flex",
|
|
207
|
+
alignItems: "center",
|
|
208
|
+
gap: 8
|
|
209
|
+
},
|
|
210
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsx(require_ai_icon.AiIcon, {
|
|
211
|
+
material: "search",
|
|
212
|
+
size: 18
|
|
213
|
+
}), "Search resources"]
|
|
214
|
+
}), /* @__PURE__ */ require_jsx_runtime.jsx("button", {
|
|
215
|
+
type: "button",
|
|
216
|
+
"aria-label": "Close resource search",
|
|
217
|
+
onClick: close,
|
|
218
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx(require_ai_icon.AiIcon, { material: "close" })
|
|
219
|
+
})]
|
|
220
|
+
}),
|
|
221
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("input", {
|
|
222
|
+
ref: input,
|
|
223
|
+
"aria-label": "Resource name, namespace, kind, label or indexed text",
|
|
224
|
+
"aria-controls": "power-resource-search-results",
|
|
225
|
+
placeholder: "Name, namespace, label, image, condition…",
|
|
226
|
+
maxLength: 300,
|
|
227
|
+
value: query,
|
|
228
|
+
onChange: (event) => {
|
|
229
|
+
setQuery(event.target.value);
|
|
230
|
+
setSelectedPath(void 0);
|
|
231
|
+
},
|
|
232
|
+
onKeyDown: (event) => {
|
|
233
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
234
|
+
event.preventDefault();
|
|
235
|
+
setSelectedPath(results[results.length ? (selected + (event.key === "ArrowDown" ? 1 : -1) + results.length) % results.length : 0]?.path);
|
|
236
|
+
}
|
|
237
|
+
if (event.key === "Enter" && !event.nativeEvent.isComposing && results[selected]) {
|
|
238
|
+
event.preventDefault();
|
|
239
|
+
open(results[selected]);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}),
|
|
243
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("p", {
|
|
244
|
+
role: "status",
|
|
245
|
+
children: [
|
|
246
|
+
loading ? "Loading supported kinds; cached results are available. " : "Supported kinds loaded. ",
|
|
247
|
+
"Partial inventory: up to 500 objects per kind, subject to permissions. Secrets, ConfigMaps and custom resources are excluded. Full-text index covers safe metadata, images, selectors and status only.",
|
|
248
|
+
failed > 0 && ` ${failed} kinds unavailable; cached results retained.`
|
|
249
|
+
]
|
|
250
|
+
}),
|
|
251
|
+
error && /* @__PURE__ */ require_jsx_runtime.jsx("p", {
|
|
252
|
+
role: "alert",
|
|
253
|
+
children: error
|
|
254
|
+
}),
|
|
255
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
256
|
+
id: "power-resource-search-results",
|
|
257
|
+
role: "list",
|
|
258
|
+
"aria-label": "Matching resources",
|
|
259
|
+
className: "power-resource-search-results",
|
|
260
|
+
children: [results.map((resource, index) => /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
261
|
+
id: `power-resource-result-${index}`,
|
|
262
|
+
role: "listitem",
|
|
263
|
+
className: `power-resource-search-row ${selected === index ? "selected" : ""}`,
|
|
264
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsxs("button", {
|
|
265
|
+
className: "power-resource-search-open",
|
|
266
|
+
type: "button",
|
|
267
|
+
onClick: () => open(resource),
|
|
268
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsx(require_ai_icon.AiIcon, { material: icons.get(resource.kind) ?? "view_in_ar" }), /* @__PURE__ */ require_jsx_runtime.jsxs("span", { children: [
|
|
269
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("strong", { children: resource.name }),
|
|
270
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("small", { children: [
|
|
271
|
+
resource.kind,
|
|
272
|
+
" · ",
|
|
273
|
+
resource.namespace ?? "cluster scoped"
|
|
274
|
+
] }),
|
|
275
|
+
searchIndex.nameParts(resource) && /* @__PURE__ */ require_jsx_runtime.jsx("small", { children: "Name parts" }),
|
|
276
|
+
searchIndex.similarName(resource) && /* @__PURE__ */ require_jsx_runtime.jsx("small", { children: "Similar name" }),
|
|
277
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(SearchSnippet, {
|
|
278
|
+
field: searchIndex.snippet(resource, query),
|
|
279
|
+
query
|
|
280
|
+
})
|
|
281
|
+
] })]
|
|
282
|
+
}), /* @__PURE__ */ require_jsx_runtime.jsx(require_diagnostic_explain_button.DiagnosticExplainButton, {
|
|
283
|
+
className: "power-resource-search-ai",
|
|
284
|
+
"aria-label": `Ask AI about ${resource.kind} ${resource.name}`,
|
|
285
|
+
title: "Ask AI about this resource",
|
|
286
|
+
onClick: () => {
|
|
287
|
+
if (activeId() !== clusterId) return;
|
|
288
|
+
close();
|
|
289
|
+
require_ai_diagnostic_handoff.explainDiagnosticFinding({
|
|
290
|
+
clusterId,
|
|
291
|
+
title: `${resource.kind}: ${resource.name}`,
|
|
292
|
+
summary: `Resource selected from search. Kind: ${resource.kind}; namespace: ${resource.namespace ?? "cluster scoped"}; name: ${resource.name}. No live diagnostic data was collected.`,
|
|
293
|
+
resource: {
|
|
294
|
+
kind: resource.kind,
|
|
295
|
+
name: resource.name,
|
|
296
|
+
namespace: resource.namespace
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
},
|
|
300
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx(require_ai_icon.AiIcon, { material: "auto_awesome" })
|
|
301
|
+
})]
|
|
302
|
+
}, resource.path)), !results.length && /* @__PURE__ */ require_jsx_runtime.jsx("p", { children: loading ? "Searching…" : "No matching resources in the available inventory" })]
|
|
303
|
+
}),
|
|
304
|
+
matches.length > 100 && /* @__PURE__ */ require_jsx_runtime.jsx("p", { children: "Showing 100 matches. Refine your search." }),
|
|
305
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("p", {
|
|
306
|
+
className: "power-resource-search-shortcuts",
|
|
307
|
+
children: "↑↓ Navigate · Enter Open · Esc Close"
|
|
308
|
+
})
|
|
309
|
+
]
|
|
310
|
+
})
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
function startResourceSearch() {
|
|
314
|
+
const container = document.createElement("div");
|
|
315
|
+
const style = document.createElement("style");
|
|
316
|
+
style.textContent = `.power-resource-search-backdrop{position:fixed;inset:0;z-index:10000;background:#0007;display:flex;align-items:flex-start;justify-content:center;padding:12vh 20px}.power-resource-search-dialog{width:680px;max-width:100%;max-height:75vh;display:flex;flex-direction:column;padding:20px;gap:12px;background:var(--mainBackground,#222);color:var(--textColorPrimary,#eee);border:1px solid var(--borderColor,#555);border-radius:8px;box-shadow:0 16px 60px #0008}.power-resource-search-heading{display:flex;align-items:center;justify-content:space-between}.power-resource-search-dialog input{padding:12px;font-size:16px;background:var(--inputControlBackground,#333);color:inherit;border:1px solid var(--borderColor,#666);border-radius:4px}.power-resource-search-dialog p{margin:0;font-size:12px;color:var(--textColorSecondary,#bbb)}.power-resource-search-results{overflow:auto;min-height:60px}.power-resource-search-row{display:flex;align-items:center;gap:12px;padding:4px;border-radius:4px}.power-resource-search-row{border-left:3px solid transparent}.power-resource-search-row.selected{background:var(--tableSelectedBackground,#394b66);border-left-color:var(--primary,#668fff)}.power-resource-search-row.selected .Icon{color:var(--primary,#8daaff)}.power-resource-search-row:hover{background:var(--tableHoveredBackground,#ffffff0b)}.power-resource-search-dialog button:hover:not(:disabled){background:#ffffff12;border-radius:4px}.power-resource-search-row>button:last-child{border:1px solid var(--borderColor,#555);border-radius:4px}.power-resource-search-shortcuts{padding-top:8px;border-top:1px solid var(--borderColor,#555)}.power-resource-search-dialog button{min-width:32px;min-height:32px;padding:6px;color:inherit;background:transparent;border:0;cursor:pointer}.power-resource-search-dialog button:disabled{opacity:.45;cursor:default}.power-resource-search-open{display:flex;align-items:center;gap:12px;flex:1;text-align:left;min-width:0}.power-resource-search-open span{min-width:0}.power-resource-search-open strong,.power-resource-search-open small{display:block;overflow-wrap:anywhere}.power-resource-search-open small{opacity:.7}.power-resource-search-row>button.power-resource-search-ai{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:34px;height:34px;min-width:34px;padding:0;background:var(--contentColor,#292d32);border:1px solid var(--borderColor,#666)}.power-resource-search-row.selected>button.power-resource-search-ai{background:var(--mainBackground,#202326);border-color:color-mix(in srgb,var(--textColorPrimary,#ddd) 55%,var(--borderColor,#666));box-shadow:0 1px 3px #0002}.power-resource-search-row.selected>button.power-resource-search-ai .Icon{color:var(--textColorAccent,#eee)}.power-resource-search-row>button.power-resource-search-ai:hover:not(:disabled){background:var(--contentColor,#30343a);border-color:var(--primary,#8daaff);color:var(--primary,#8daaff)}.power-resource-search-row>button.power-resource-search-ai:hover:not(:disabled) .Icon{color:inherit}.power-resource-search-dialog button:focus-visible{outline:2px solid var(--primary,#668fff)}`;
|
|
317
|
+
document.head.append(style);
|
|
318
|
+
document.body.append(container);
|
|
319
|
+
let visible = false;
|
|
320
|
+
const close = () => {
|
|
321
|
+
if (visible) {
|
|
322
|
+
visible = false;
|
|
323
|
+
require__global_external_react_dom.default.unmountComponentAtNode(container);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
const show = () => {
|
|
327
|
+
const clusterId = activeId();
|
|
328
|
+
if (window.top === window || !clusterId || visible || document.querySelector("[aria-modal=\"true\"], .Dialog.is-opened")) return;
|
|
329
|
+
visible = true;
|
|
330
|
+
require__global_external_react_dom.default.render(/* @__PURE__ */ require_jsx_runtime.jsx(SearchDialog, {
|
|
331
|
+
close,
|
|
332
|
+
clusterId
|
|
333
|
+
}), container);
|
|
334
|
+
};
|
|
335
|
+
let shift = require_resource_search_model.createDoubleShift();
|
|
336
|
+
const resetShift = () => {
|
|
337
|
+
shift = require_resource_search_model.createDoubleShift();
|
|
338
|
+
};
|
|
339
|
+
const key = (event) => {
|
|
340
|
+
if (event.isComposing || event.key === "Process") {
|
|
341
|
+
resetShift();
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if (shift(event, performance.now())) show();
|
|
345
|
+
};
|
|
346
|
+
window.addEventListener("blur", resetShift);
|
|
347
|
+
window.addEventListener("keydown", key);
|
|
348
|
+
window.addEventListener("keyup", key);
|
|
349
|
+
window.addEventListener(OPEN, show);
|
|
350
|
+
const dispose = require__global_external_mobx.reaction(activeId, close);
|
|
351
|
+
return () => {
|
|
352
|
+
close();
|
|
353
|
+
dispose();
|
|
354
|
+
window.removeEventListener("blur", resetShift);
|
|
355
|
+
window.removeEventListener("keydown", key);
|
|
356
|
+
window.removeEventListener("keyup", key);
|
|
357
|
+
window.removeEventListener(OPEN, show);
|
|
358
|
+
container.remove();
|
|
359
|
+
style.remove();
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
//#endregion
|
|
363
|
+
exports.startResourceSearch = startResourceSearch;
|
|
364
|
+
|
|
365
|
+
//# sourceMappingURL=resource-search.js.map
|