@telefonica/ai-sdlc-opencode-plugin-v1 1.0.4 → 1.0.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.
@@ -310,8 +310,9 @@ function modelRows(payload) {
310
310
  return payload.data;
311
311
  }
312
312
  function infoRows(payload) {
313
- if (!isRecord(payload) || !Array.isArray(payload.data)) return [];
314
- return payload.data.filter(isRecord);
313
+ if (!isRecord(payload) || !Array.isArray(payload.data)) return void 0;
314
+ if (!payload.data.every((entry) => isRecord(entry) && typeof entry.model_name === "string" && entry.model_name.length > 0 && isRecord(entry.model_info) && (entry.litellm_params === void 0 || isRecord(entry.litellm_params)))) return void 0;
315
+ return payload.data;
315
316
  }
316
317
  function usableModel(model) {
317
318
  return !model.mode || model.mode === "chat";
@@ -322,22 +323,27 @@ async function discoverModelsResult(options) {
322
323
  const [modelsResponse, infoResponse] = await Promise.all([fetchJSON(`${baseURL}/v1/models`, options, "models.discover"), fetchJSON(`${baseURL}/v1/model/info`, options, "models.discover")]);
323
324
  let result;
324
325
  if (!modelsResponse.ok) result = modelsResponse;
326
+ else if (!infoResponse.ok) result = infoResponse;
325
327
  else {
326
328
  const rows = modelRows(modelsResponse.value);
329
+ const metadataPayload = infoResponse.value;
330
+ const metadataRows = infoRows(metadataPayload);
327
331
  if (!rows) result = invalid("Invalid or empty /v1/models response");
332
+ else if (!metadataRows) result = invalid("Invalid /v1/model/info response");
328
333
  else {
329
334
  const infos = /* @__PURE__ */ new Map();
330
- if (infoResponse.ok) {
331
- for (const row of infoRows(infoResponse.value)) if (typeof row.model_name === "string") infos.set(row.model_name, row);
335
+ for (const row of metadataRows) infos.set(row.model_name, row);
336
+ if (!rows.every((row) => infos.has(row.id))) result = invalid("Incomplete /v1/model/info response");
337
+ else {
338
+ const models = rows.map((row) => {
339
+ const metadata = infos.get(row.id);
340
+ return normalizeModel(row, metadata.model_info, metadata.litellm_params);
341
+ }).filter(usableModel);
342
+ result = models.length > 0 ? {
343
+ ok: true,
344
+ value: models
345
+ } : invalid("No usable chat models in /v1/models response");
332
346
  }
333
- const models = rows.map((row) => {
334
- const metadata = infos.get(row.id);
335
- return normalizeModel(row, metadata?.model_info, metadata?.litellm_params);
336
- }).filter(usableModel);
337
- result = models.length > 0 ? {
338
- ok: true,
339
- value: models
340
- } : invalid("No usable chat models in /v1/models response");
341
347
  }
342
348
  }
343
349
  emitGatewayLog(options, {
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { f as unsanitizeModelId, i as normalizeProviderURL, o as discoverModels, t as PROD, u as PLUGIN_COPY } from "./flavor-BsY4SlmY.js";
1
+ import { f as unsanitizeModelId, i as normalizeProviderURL, o as discoverModels, t as PROD, u as PLUGIN_COPY } from "./flavor-COZ5DAs4.js";
2
2
  import { createHash, randomUUID } from "node:crypto";
3
3
  import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
4
4
  import { homedir } from "node:os";
@@ -130,7 +130,7 @@ function createAuthHook(flavor) {
130
130
  provider: flavor.providerID,
131
131
  async loader(auth) {
132
132
  const creds = await auth();
133
- if (!creds || creds.type !== "api") return {};
133
+ if (creds?.type !== "api") return {};
134
134
  const url = creds.metadata?.["url"];
135
135
  return {
136
136
  baseURL: url ? normalizeProviderURL(url) : void 0,
@@ -163,7 +163,7 @@ async function fromAuthFile(providerID) {
163
163
  try {
164
164
  const raw = await readFile(authFilePath(), "utf8");
165
165
  const entry = JSON.parse(raw)[providerID];
166
- if (!entry || entry.type !== "api") return {};
166
+ if (entry?.type !== "api") return {};
167
167
  return {
168
168
  apiKey: entry.key,
169
169
  baseURL: entry.metadata?.["url"]
package/dist/tui.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as resolveUsagePercent, c as fetchJSON, d as PLUGIN_UI, l as isRecord, n as BUDGET_SOURCE_LABELS, r as monthlyUsageMetrics, s as emitGatewayLog, t as PROD, u as PLUGIN_COPY } from "./flavor-BsY4SlmY.js";
1
+ import { a as resolveUsagePercent, c as fetchJSON, d as PLUGIN_UI, l as isRecord, n as BUDGET_SOURCE_LABELS, r as monthlyUsageMetrics, s as emitGatewayLog, t as PROD, u as PLUGIN_COPY } from "./flavor-COZ5DAs4.js";
2
2
  import { For, createSignal } from "solid-js";
3
3
  import { createTextAttributes } from "@opentui/core";
4
4
  import { Fragment, jsx, jsxs } from "@opentui/solid/jsx-runtime";
@@ -84,14 +84,16 @@ function toEntry(providerName, result) {
84
84
  //#region src/components.tsx
85
85
  function barColor(entry, theme) {
86
86
  const pct = entry.thresholdPercent ?? 0;
87
- return pct >= PLUGIN_UI.exceededPercent ? theme.error : pct >= PLUGIN_UI.warningPercent ? theme.warning : theme.success;
87
+ if (pct >= PLUGIN_UI.exceededPercent) return theme.error;
88
+ if (pct >= PLUGIN_UI.warningPercent) return theme.warning;
89
+ return theme.success;
88
90
  }
89
91
  function valuesLine(entry) {
90
92
  if (entry.error != null) return PLUGIN_COPY.usageUnavailable(entry.error);
91
93
  return PLUGIN_COPY.usageValues(entry.spend ?? 0, entry.budget ?? null);
92
94
  }
93
95
  function UsagePanel(props) {
94
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(For, {
96
+ return /* @__PURE__ */ jsx(For, {
95
97
  each: props.entries,
96
98
  children: (entry) => /* @__PURE__ */ jsxs("box", {
97
99
  flexDirection: "column",
@@ -102,7 +104,7 @@ function UsagePanel(props) {
102
104
  }),
103
105
  /* @__PURE__ */ jsx("text", {
104
106
  fg: !entry.connected || entry.error != null ? props.theme.error : void 0,
105
- children: !entry.connected ? PLUGIN_COPY.notConnected(props.connectCommand) : valuesLine(entry)
107
+ children: entry.connected ? valuesLine(entry) : PLUGIN_COPY.notConnected(props.connectCommand)
106
108
  }),
107
109
  entry.connected && entry.error == null && entry.percent != null && /* @__PURE__ */ jsx("text", {
108
110
  fg: barColor(entry, props.theme),
@@ -121,7 +123,7 @@ function UsagePanel(props) {
121
123
  })] })
122
124
  ]
123
125
  })
124
- }) });
126
+ });
125
127
  }
126
128
  //#endregion
127
129
  //#region src/tui.tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telefonica/ai-sdlc-opencode-plugin-v1",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "OpenCode 1.x plugin: CDO.AI provider registration, model discovery, and budget panel",
5
5
  "type": "module",
6
6
  "exports": {