@hawtio/ai-plugin 0.1.1 → 0.1.6

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/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
4
4
 
5
+ ## [0.1.6](///compare/v0.1.5...v0.1.6) (2026-05-01)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * make attribute modal open automatically after diagnosis finished 06725b6
11
+
12
+ ## [0.1.5](///compare/v0.1.1...v0.1.5) (2026-05-01)
13
+
14
+
15
+ ### Features
16
+
17
+ * add support for OpenAI & Anthropic models 306638d, closes #10
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * exclude test app from releasing 5c107bd
23
+ * skip publishing test app (finally) 2bb437e
24
+ * skip test app deployment (again) 2209659
25
+
5
26
  ## [0.1.1](///compare/v0.1.0...v0.1.1) (2026-04-23)
6
27
 
7
28
 
package/dist/index.js CHANGED
@@ -2055,8 +2055,9 @@ function extractMethod(request, params) {
2055
2055
  method = "get";
2056
2056
  } else if (methodGiven !== "post") {
2057
2057
  throw new Error('Illegal method "' + methodGiven + '"');
2058
+ } else {
2059
+ method = "post";
2058
2060
  }
2059
- method = "post";
2060
2061
  } else {
2061
2062
  if (Array.isArray(request) || "config" in request || request.type?.toLowerCase() === "read" && "attribute" in request && Array.isArray(request.attribute) || "target" in request) {
2062
2063
  method = "post";
@@ -2145,7 +2146,7 @@ var CLIENT_VERSION, DEFAULT_FETCH_PARAMS, PROCESSING_PARAMS, Jolokia, GET_URL_EX
2145
2146
  var init_jolokia = __esm({
2146
2147
  "node_modules/jolokia.js/dist/jolokia.mjs"() {
2147
2148
  "use strict";
2148
- CLIENT_VERSION = "2.5.0";
2149
+ CLIENT_VERSION = "2.6.0";
2149
2150
  DEFAULT_FETCH_PARAMS = {
2150
2151
  cache: "no-store",
2151
2152
  credentials: "same-origin",
@@ -2549,21 +2550,33 @@ var init_jolokia = __esm({
2549
2550
  });
2550
2551
 
2551
2552
  // src/ai-plugin/common/ai-model.ts
2552
- var MODELS;
2553
+ var PROVIDERS, MODELS;
2553
2554
  var init_ai_model = __esm({
2554
2555
  "src/ai-plugin/common/ai-model.ts"() {
2555
2556
  "use strict";
2557
+ PROVIDERS = ["openai", "anthropic", "google-genai", "ollama"];
2556
2558
  MODELS = [
2557
- { id: "gemini-2.5-flash", name: "Gemini 2.5 Flash", tool: true, type: "google-genai" },
2558
- { id: "gemini-2.5-pro", name: "Gemini 2.5 Pro", tool: true, type: "google-genai" },
2559
- { id: "granite3.1-moe:latest", name: "Granite 3.1 Moe", tool: true, type: "ollama" },
2560
- { id: "granite3.1-dense:latest", name: "Granite 3.1 Dense", tool: true, type: "ollama" },
2561
- { id: "llama3:latest", name: "Llama 3", tool: false, type: "ollama" },
2562
- { id: "llama3.2:latest", name: "Llama 3.2", tool: true, type: "ollama" },
2563
- { id: "phi4:latest", name: "Phi 4", tool: false, type: "ollama" },
2564
- { id: "phi3.5:latest", name: "Phi 3.5", tool: false, type: "ollama" },
2565
- { id: "qwen3:4b", name: "Qwen 3 4B", tool: true, type: "ollama" },
2566
- { id: "qwen3:latest", name: "Qwen 3", tool: true, type: "ollama" }
2559
+ // OpenAI models
2560
+ { id: "gpt-5.5", name: "GPT-5.5", tool: true, provider: "openai" },
2561
+ { id: "gpt-5.4", name: "GPT-5.4", tool: true, provider: "openai" },
2562
+ { id: "gpt-5.4-mini", name: "GPT-5.4 mini", tool: true, provider: "openai" },
2563
+ // Anthropic Claude models
2564
+ { id: "claude-opus-4-7", name: "Claude Opus 4.7", tool: true, provider: "anthropic" },
2565
+ { id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6", tool: true, provider: "anthropic" },
2566
+ { id: "claude-haiku-4-5", name: "Claude Haiku 4.5", tool: true, provider: "anthropic" },
2567
+ // Google Gemini models
2568
+ { id: "gemini-2.5-flash", name: "Gemini 2.5 Flash", tool: true, provider: "google-genai" },
2569
+ { id: "gemini-2.5-flash-lite", name: "Gemini 2.5 Flash-Lite", tool: true, provider: "google-genai" },
2570
+ { id: "gemini-2.5-pro", name: "Gemini 2.5 Pro", tool: true, provider: "google-genai" },
2571
+ // Ollama models
2572
+ { id: "granite3.1-moe:latest", name: "Granite 3.1 Moe", tool: true, provider: "ollama" },
2573
+ { id: "granite3.1-dense:latest", name: "Granite 3.1 Dense", tool: true, provider: "ollama" },
2574
+ { id: "llama3:latest", name: "Llama 3", tool: false, provider: "ollama" },
2575
+ { id: "llama3.2:latest", name: "Llama 3.2", tool: true, provider: "ollama" },
2576
+ { id: "phi4:latest", name: "Phi 4", tool: false, provider: "ollama" },
2577
+ { id: "phi3.5:latest", name: "Phi 3.5", tool: false, provider: "ollama" },
2578
+ { id: "qwen3:4b", name: "Qwen 3 4B", tool: true, provider: "ollama" },
2579
+ { id: "qwen3:latest", name: "Qwen 3", tool: true, provider: "ollama" }
2567
2580
  ];
2568
2581
  }
2569
2582
  });
@@ -2577,7 +2590,7 @@ var init_ai_preferences_service = __esm({
2577
2590
  init_ai_service();
2578
2591
  STORAGE_KEY_PREFERENCES = "ai.preferences";
2579
2592
  DEFAULT_OPTIONS = {
2580
- model: MODELS[0].id
2593
+ model: MODELS[0]
2581
2594
  };
2582
2595
  AiPreferencesService = class {
2583
2596
  loadOptions() {
@@ -2589,10 +2602,7 @@ var init_ai_preferences_service = __esm({
2589
2602
  const updated = { ...this.loadOptions(), ...options };
2590
2603
  localStorage.setItem(STORAGE_KEY_PREFERENCES, JSON.stringify(updated));
2591
2604
  if (options.model) {
2592
- const modelObj = MODELS.find((m) => m.id === options.model);
2593
- if (modelObj) {
2594
- aiService.reset(modelObj);
2595
- }
2605
+ aiService.reset(options.model);
2596
2606
  }
2597
2607
  }
2598
2608
  };
@@ -2601,15 +2611,16 @@ var init_ai_preferences_service = __esm({
2601
2611
  });
2602
2612
 
2603
2613
  // src/ai-plugin/common/ai-service.ts
2604
- var import_messages, import_google_genai, import_ollama, TOOLS, TOOLS_BY_NAME, AiService, aiService;
2614
+ var import_anthropic, import_messages, import_google_genai, import_ollama, import_openai, TOOLS, TOOLS_BY_NAME, AiService, aiService;
2605
2615
  var init_ai_service = __esm({
2606
2616
  "src/ai-plugin/common/ai-service.ts"() {
2607
2617
  "use strict";
2618
+ import_anthropic = require("@langchain/anthropic");
2608
2619
  import_messages = require("@langchain/core/messages");
2609
2620
  import_google_genai = require("@langchain/google-genai");
2610
2621
  import_ollama = require("@langchain/ollama");
2622
+ import_openai = require("@langchain/openai");
2611
2623
  init_globals();
2612
- init_ai_model();
2613
2624
  init_ai_preferences_service();
2614
2625
  TOOLS = [];
2615
2626
  TOOLS_BY_NAME = TOOLS.reduce(
@@ -2632,7 +2643,23 @@ var init_ai_service = __esm({
2632
2643
  const { token } = aiPreferencesService.loadOptions();
2633
2644
  this.model = model;
2634
2645
  try {
2635
- switch (this.model.type) {
2646
+ switch (this.model.provider) {
2647
+ case "openai":
2648
+ this.llm = new import_openai.ChatOpenAI({
2649
+ model: this.model.id,
2650
+ apiKey: token,
2651
+ temperature: 0,
2652
+ streaming: false
2653
+ });
2654
+ break;
2655
+ case "anthropic":
2656
+ this.llm = new import_anthropic.ChatAnthropic({
2657
+ model: this.model.id,
2658
+ apiKey: token,
2659
+ temperature: 0,
2660
+ streaming: false
2661
+ });
2662
+ break;
2636
2663
  case "google-genai":
2637
2664
  this.llm = new import_google_genai.ChatGoogleGenerativeAI({
2638
2665
  model: this.model.id,
@@ -2650,7 +2677,9 @@ var init_ai_service = __esm({
2650
2677
  }
2651
2678
  } catch (error) {
2652
2679
  log.warn("Error initialising AI model:", error);
2680
+ this.llm = void 0;
2653
2681
  }
2682
+ this.llmWithTools = void 0;
2654
2683
  if (TOOLS.length !== 0 && this.model.tool) {
2655
2684
  this.llmWithTools = this.llm?.bindTools(TOOLS);
2656
2685
  }
@@ -2658,13 +2687,9 @@ var init_ai_service = __esm({
2658
2687
  getLlm() {
2659
2688
  if (!this.model || !this.llm) {
2660
2689
  const { model } = aiPreferencesService.loadOptions();
2661
- const modelObj = MODELS.find((m) => m.id === model) ?? MODELS[0];
2662
- this.reset(modelObj);
2663
- }
2664
- if (this.llmWithTools) {
2665
- return this.llmWithTools;
2690
+ this.reset(model);
2666
2691
  }
2667
- return this.llm;
2692
+ return this.llmWithTools ?? this.llm;
2668
2693
  }
2669
2694
  async invoke(messages) {
2670
2695
  const llm = this.getLlm();
@@ -15900,12 +15925,15 @@ var init_Attributes = __esm({
15900
15925
  setAttributes(attrs);
15901
15926
  setIsReading(false);
15902
15927
  });
15903
- attributeService.register({ type: "read", mbean: objectName }, (response) => {
15904
- if (!Jolokia.isError(response)) {
15905
- log.debug("Scheduler - Attributes:", response.value);
15906
- setAttributes(response.value);
15928
+ attributeService.register(
15929
+ { type: "read", mbean: objectName },
15930
+ (response) => {
15931
+ if (response && !Jolokia.isError(response)) {
15932
+ log.debug("Scheduler - Attributes:", response.value);
15933
+ setAttributes(response.value);
15934
+ }
15907
15935
  }
15908
- });
15936
+ );
15909
15937
  return () => attributeService.unregisterAll();
15910
15938
  }, [selectedNode]);
15911
15939
  (0, import_react10.useEffect)(() => {
@@ -15940,6 +15968,16 @@ var init_Attributes = __esm({
15940
15968
  setIsModalOpen(true);
15941
15969
  }
15942
15970
  };
15971
+ const showDiagnosisResult = () => {
15972
+ if (!isModalOpen && Object.keys(attributes).length > 0) {
15973
+ if (!isAttributeSelected) {
15974
+ const name2 = Object.keys(attributes).sort((a, b) => a > b ? 1 : -1)[0];
15975
+ setSelected({ name: name2, value: String(attributes[name2]) });
15976
+ setIsAttributeSelected(true);
15977
+ }
15978
+ setIsModalOpen(true);
15979
+ }
15980
+ };
15943
15981
  const getSortParams = () => ({
15944
15982
  sortBy: {
15945
15983
  index: 0,
@@ -15966,14 +16004,7 @@ var init_Attributes = __esm({
15966
16004
  }
15967
16005
  );
15968
16006
  const attributesTable = /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { id: "attribute-table-with-panel", children: [
15969
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
15970
- AiJmxToolbar,
15971
- {
15972
- attributes,
15973
- setAiMessage,
15974
- onDiagnosisFinished: () => setIsModalOpen(true)
15975
- }
15976
- ),
16007
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(AiJmxToolbar, { attributes, setAiMessage, onDiagnosisFinished: showDiagnosisResult }),
15977
16008
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_table.Table, { "aria-label": "Attributes", variant: "compact", children: [
15978
16009
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_table.Thead, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_table.Tr, { children: [
15979
16010
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_table.Th, { sort: getSortParams(), children: "Attribute" }),
@@ -16078,14 +16109,17 @@ var init_AttributeTable2 = __esm({
16078
16109
  const setJobForSpecificNode = async (node2) => {
16079
16110
  if (!node2 || !node2?.objectName) return;
16080
16111
  const mbean = node2.objectName;
16081
- attributeService.register({ type: "read", mbean }, (response) => {
16082
- if ("value" in response) {
16083
- setAttributesList((attributesList2) => {
16084
- attributesList2[mbean] = response.value;
16085
- return { ...attributesList2 };
16086
- });
16112
+ attributeService.register(
16113
+ { type: "read", mbean },
16114
+ (response) => {
16115
+ if (response && typeof response === "object" && "value" in response) {
16116
+ setAttributesList((attributesList2) => {
16117
+ attributesList2[mbean] = response.value;
16118
+ return { ...attributesList2 };
16119
+ });
16120
+ }
16087
16121
  }
16088
- });
16122
+ );
16089
16123
  };
16090
16124
  const setReadingJobs = async (currentSelection) => {
16091
16125
  if (!currentSelection) return;
@@ -16363,23 +16397,46 @@ init_ai_preferences_service();
16363
16397
  var import_jsx_runtime8 = require("react/jsx-runtime");
16364
16398
  var AiPreferences = () => {
16365
16399
  const [options, setOptions] = (0, import_react18.useState)(aiPreferencesService.loadOptions());
16400
+ const [provider, setProvider] = (0, import_react18.useState)(options.model.provider);
16401
+ const [models, setModels] = (0, import_react18.useState)(MODELS.filter((m) => m.provider === provider));
16366
16402
  const [passwordHidden, setPasswordHidden] = (0, import_react18.useState)(true);
16367
- const updateOptions = (updated) => {
16368
- aiPreferencesService.saveOptions(updated);
16369
- setOptions({ ...options, ...updated });
16403
+ const updateProvider = (provider2) => {
16404
+ setProvider(provider2);
16405
+ setModels(MODELS.filter((m) => m.provider === provider2));
16406
+ };
16407
+ const updateModel = (updated) => {
16408
+ const model = MODELS.find((m) => m.id === updated);
16409
+ if (model) {
16410
+ aiPreferencesService.saveOptions({ model });
16411
+ setOptions({ ...options, model });
16412
+ }
16413
+ };
16414
+ const updateToken = (updated) => {
16415
+ aiPreferencesService.saveOptions({ token: updated });
16416
+ setOptions({ ...options, token: updated });
16370
16417
  };
16371
16418
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.CardBody, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.Form, { isHorizontal: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_core7.FormSection, { title: "AI", titleElement: "h2", children: [
16372
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.FormGroup, { fieldId: "ai-prefs-form-model", label: "Model to use", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
16419
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.FormGroup, { fieldId: "ai-prefs-form-provider", label: "Provider", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
16420
+ import_react_core7.FormSelect,
16421
+ {
16422
+ id: "ai-prefs-form-provider-input",
16423
+ "aria-label": "Form Select Provider",
16424
+ value: provider,
16425
+ onChange: (_, provider2) => updateProvider(provider2),
16426
+ children: PROVIDERS.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.FormSelectOption, { value: p, label: p }, i))
16427
+ }
16428
+ ) }),
16429
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.FormGroup, { fieldId: "ai-prefs-form-model", label: "Model", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
16373
16430
  import_react_core7.FormSelect,
16374
16431
  {
16375
16432
  id: "ai-prefs-form-model-input",
16376
16433
  "aria-label": "Form Select Model",
16377
- value: options.model,
16378
- onChange: (_, model) => updateOptions({ model }),
16379
- children: MODELS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.FormSelectOption, { value: m.id, label: `${m.name} (${m.type})` }, m.id))
16434
+ value: options.model.id,
16435
+ onChange: (_, id) => updateModel(id),
16436
+ children: models.map((m) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.FormSelectOption, { value: m.id, label: m.name }, m.id))
16380
16437
  }
16381
16438
  ) }),
16382
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.FormGroup, { fieldId: "ai-prefs-form-token", label: "Token for the model (optional)", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_core7.InputGroup, { children: [
16439
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.FormGroup, { fieldId: "ai-prefs-form-token", label: "API Key / Token (optional)", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_react_core7.InputGroup, { children: [
16383
16440
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.InputGroupItem, { isFill: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
16384
16441
  import_react_core7.TextInput,
16385
16442
  {
@@ -16387,7 +16444,7 @@ var AiPreferences = () => {
16387
16444
  "aria-label": "Form Select Token",
16388
16445
  type: passwordHidden ? "password" : "text",
16389
16446
  value: options.token,
16390
- onChange: (_, token) => updateOptions({ token })
16447
+ onChange: (_, token) => updateToken(token)
16391
16448
  }
16392
16449
  ) }),
16393
16450
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_react_core7.InputGroupItem, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
@@ -16420,7 +16477,7 @@ var plugin = () => {
16420
16477
  aiCommon();
16421
16478
  jmxAi();
16422
16479
  };
16423
- import_react21.configManager.addProductInfo("Hawtio AI Plugin", "0.1.1");
16480
+ import_react21.configManager.addProductInfo("Hawtio AI Plugin", "0.1.6");
16424
16481
  // Annotate the CommonJS export names for ESM import in node:
16425
16482
  0 && (module.exports = {
16426
16483
  plugin