Skip to content

Commit be0b490

Browse files
committed
ai-assistant: index: utils: Fix event types
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
1 parent 044c74e commit be0b490

File tree

3 files changed

+163
-25
lines changed

3 files changed

+163
-25
lines changed

ai-assistant/src/index.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {
55
registerPluginSettings,
66
registerUIPanel,
77
} from '@kinvolk/headlamp-plugin/lib';
8+
// @todo: this HeadlampEventType import is weird. Maybe fix in headlamp to be better.
9+
import { DefaultHeadlampEvents as HeadlampEventType } from '@kinvolk/headlamp-plugin/lib/plugin/registry';
810
import {
911
Box,
1012
Button,
@@ -262,32 +264,47 @@ registerAppBarAction(HeadlampAIPrompt);
262264

263265
registerAppBarAction(() => {
264266
const _pluginState = useGlobalState();
267+
268+
// @todo: these "any" casts are all suspicious and also bugs (at least in the types maybe more).
269+
// @todo: the data being used is not in the event type definitions. Check the definitions and this code.
265270
registerHeadlampEventCallback(event => {
271+
// @todo: headlamp.home-page-loaded does not exist in headlampEventSlice or anywhere in headlamp.
266272
if (event.type === 'headlamp.home-page-loaded') {
267273
_pluginState.setEvent({
268274
..._pluginState.event,
275+
type: 'headlamp.home-page-loaded',
269276
clusters: (event.data as any).clusters,
270277
errors: (event.data as any).errors,
271278
});
272279
}
273-
if (event.type === 'headlamp.object-events') {
280+
if (event.type === HeadlampEventType.OBJECT_EVENTS) {
274281
_pluginState.setEvent({
275282
..._pluginState.event,
276-
objectEvent: event.data,
283+
type: HeadlampEventType.OBJECT_EVENTS,
284+
objectEvent: (_pluginState?.event as any)?.objectEvent,
285+
resources: (event.data as any).resources,
286+
resourceKind: (event.data as any).resourceKind,
277287
});
278288
}
279289

280-
if (event.type === 'headlamp.details-view') {
290+
if (event.type === HeadlampEventType.DETAILS_VIEW) {
281291
_pluginState.setEvent({
292+
type: HeadlampEventType.DETAILS_VIEW,
282293
title: (event.data as any).title,
283294
resource: (event.data as any).resource,
284-
objectEvent: _pluginState?.event?.objectEvent,
295+
objectEvent: (_pluginState?.event as any)?.objectEvent,
296+
resources: (event.data as any).resources,
297+
resourceKind: (event.data as any).resourceKind,
285298
});
286299
}
287-
if (event.type === 'headlamp.list-view') {
300+
if (event.type === HeadlampEventType.LIST_VIEW) {
288301
_pluginState.setEvent({
289-
resources: event.data.resources,
290-
resourceKind: event.data.resourceKind,
302+
type: HeadlampEventType.LIST_VIEW,
303+
title: (event.data as any).title,
304+
resources: (event.data as any).resources,
305+
resourceKind: (event.data as any).resourceKind,
306+
resource: (event.data as any).resource,
307+
objectEvent: (_pluginState?.event as any)?.objectEvent,
291308
});
292309
}
293310
return null;

ai-assistant/src/utils.tsx

Lines changed: 137 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,149 @@
11
import { ConfigStore } from '@kinvolk/headlamp-plugin/lib';
2+
import type {
3+
EventListEvent,
4+
ResourceDetailsViewLoadedEvent,
5+
ResourceListViewLoadedEvent,
6+
} from '@kinvolk/headlamp-plugin/lib/plugin/registry';
27
import React from 'react';
38
import { useBetween } from 'use-between';
4-
import { StoredProviderConfig } from './utils/ProviderConfigManager';
9+
import type { StoredProviderConfig, SavedConfigurations } from './utils/ProviderConfigManager';
510

611
export const PLUGIN_NAME = '@headlamp-k8s/ai-assistant';
712
export const getSettingsURL = () => `/settings/plugins/${encodeURIComponent(PLUGIN_NAME)}`;
813

9-
export const pluginStore = new ConfigStore<{ isUIPanelOpen?: boolean }>(PLUGIN_NAME);
14+
//@todo: In index.tsx the setEvent uses things from event.data into the root of the event.
15+
// Why does it do this? Maybe it can just use event.data as is?
16+
// This would simplify things and avoid copying and casts/type gymnastics.
17+
18+
//@todo: Can we have these names be the same? It's confusing having three names.
19+
// EventListEvent, OBJECT_EVENTS and headlamp.object-events
20+
21+
// @todo: We can't just do something like this...
22+
// because these types actually copy from "data" to top level... and add other fields.
23+
// type HeadlampEventPayload =
24+
// | {
25+
// type: 'headlamp.home-page-loaded';
26+
// clusters: any;
27+
// errors: any;
28+
// }
29+
// | EventListEvent
30+
// | ResourceDetailsViewLoadedEvent
31+
// | ResourceListViewLoadedEvent;
32+
/**
33+
* Event fired when a resource is loaded in the details view.
34+
*/
35+
// export interface ResourceDetailsViewLoadedEvent {
36+
// type: HeadlampEventType.DETAILS_VIEW;
37+
// data: {
38+
// /** The resource that was loaded. */
39+
// resource: KubeObject;
40+
// /** The error, if an error has occurred */
41+
// error?: Error;
42+
// };
43+
// }
44+
// /**
45+
// * Event fired when a list view is loaded for a resource.
46+
// */
47+
// export interface ResourceListViewLoadedEvent {
48+
// type: HeadlampEventType.LIST_VIEW;
49+
// data: {
50+
// /** The list of resources that were loaded. */
51+
// resources: KubeObject[];
52+
// /** The kind of resource that was loaded. */
53+
// resourceKind: string;
54+
// /** The error, if an error has occurred */
55+
// error?: Error;
56+
// };
57+
// }
58+
// /**
59+
// * Event fired when kubernetes events are loaded (for a resource or not).
60+
// */
61+
// export interface EventListEvent {
62+
// type: HeadlampEventType.OBJECT_EVENTS;
63+
// data: {
64+
// /** The resource for which the events were loaded. */
65+
// resource?: KubeObject;
66+
// /** The list of events that were loaded. */
67+
// events: Event[];
68+
// };
69+
// }
70+
71+
// interface HeadlampEvent {
72+
// type?: string;
73+
// title?: string;
74+
// resource?: any;
75+
// items?: any[];
76+
// resources?: any[];
77+
// resourceKind?: string;
78+
// errors?: any[];
79+
// objectEvent?: {
80+
// events?: any[];
81+
// };
82+
// }
83+
84+
export type HeadlampEventPayload =
85+
| {
86+
type: 'headlamp.home-page-loaded';
87+
title?: string;
88+
items?: any[];
89+
clusters: any;
90+
errors: any;
91+
resource?: EventListEvent['data']['resource'];
92+
resources?: any;
93+
resourceKind?: string;
94+
objectEvent?: any;
95+
}
96+
| {
97+
type: EventListEvent['type'];
98+
title?: string;
99+
items?: any[];
100+
objectEvent: EventListEvent['data'];
101+
resource?: EventListEvent['data']['resource'];
102+
resources: any;
103+
// resourceKind: EventListEvent['data']['resourceKind'];
104+
resourceKind: string;
105+
}
106+
| {
107+
type: ResourceDetailsViewLoadedEvent['type'];
108+
title: string;
109+
items?: any[];
110+
resource: ResourceDetailsViewLoadedEvent['data']['resource'];
111+
resources: any;
112+
resourceKind: string;
113+
// resourceKind: ResourceDetailsViewLoadedEvent['data']['resourceKind'];
114+
objectEvent?: ResourceDetailsViewLoadedEvent['data'];
115+
}
116+
| {
117+
type: ResourceListViewLoadedEvent['type'];
118+
title?: string;
119+
items?: any[];
120+
//@todo: "resource" is not set in index.tsx with setEvent. Is this a bug?
121+
resource: any;
122+
resources: ResourceListViewLoadedEvent['data']['resources'];
123+
resourceKind: ResourceListViewLoadedEvent['data']['resourceKind'];
124+
objectEvent?: ResourceListViewLoadedEvent['data'];
125+
};
126+
127+
interface PluginConfig extends SavedConfigurations {
128+
/** Is the AI Assistant UI panel open? */
129+
isUIPanelOpen?: boolean;
130+
/** Is the config popover shown? */
131+
configPopoverShown?: boolean;
132+
/** Saved provider configurations */
133+
savedProviders?: StoredProviderConfig[];
134+
/** Currently active provider configuration */
135+
activeProvider?: StoredProviderConfig;
136+
/** Is the plugin in test mode? */
137+
testMode?: boolean;
138+
/** Latest Headlamp event payload */
139+
event?: HeadlampEventPayload | null; //@todo: should this be HeadlampEventPayload?
140+
}
141+
142+
export const pluginStore = new ConfigStore<PluginConfig>(PLUGIN_NAME);
10143
export const usePluginConfig = pluginStore.useConfig();
11144

12145
function usePluginSettings() {
13-
const [event, setEvent] = React.useState(null);
146+
const [event, setEvent] = React.useState<HeadlampEventPayload | null>(null);
14147
// Add states to track providers and active provider
15148
const [savedProviders, setSavedProviders] = React.useState<StoredProviderConfig[]>([]);
16149
const [activeProvider, setActiveProvider] = React.useState<StoredProviderConfig | null>(null);
@@ -41,6 +174,7 @@ function usePluginSettings() {
41174
setActiveProvider,
42175
isUIPanelOpen,
43176
setIsUIPanelOpen,
177+
// @todo: should testMode setTestMode be added here?
44178
};
45179
}
46180

ai-assistant/src/utils/contextGenerator.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Event from '@kinvolk/headlamp-plugin/lib/K8s/event';
2-
2+
import type { HeadlampEventPayload } from '../utils';
33
/**
44
* Context Generator - Creates human-readable context descriptions for the AI
55
* This replaces the complex JSON context system with simple, natural language descriptions
@@ -11,19 +11,6 @@ import Event from '@kinvolk/headlamp-plugin/lib/K8s/event';
1111
* - event.resourceKind: Type of resources in event.resources
1212
*/
1313

14-
interface HeadlampEvent {
15-
type?: string;
16-
title?: string;
17-
resource?: any;
18-
items?: any[];
19-
resources?: any[];
20-
resourceKind?: string;
21-
errors?: any[];
22-
objectEvent?: {
23-
events?: any[];
24-
};
25-
}
26-
2714
/**
2815
* Minimizes resource data to only include essential fields
2916
*/
@@ -51,7 +38,7 @@ export function minimizeResourceList(resources: any[]): any[] {
5138
}
5239

5340
export function generateContextDescription(
54-
event: HeadlampEvent,
41+
event: HeadlampEventPayload | null,
5542
currentCluster?: string,
5643
clusterWarnings?: Record<string, { warnings: Event[]; error?: Error | null }>,
5744
selectedClusters?: string[]

0 commit comments

Comments
 (0)