@mcowger/oh-my-pi-plexus 1.5.0 → 1.6.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 +23 -26
- package/dist/extension.js +46 -174
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Exposes models from a self-hosted [Plexus](https://github.com/mcowger/plexus) AI
|
|
|
12
12
|
## Prerequisites
|
|
13
13
|
|
|
14
14
|
- A running Plexus instance
|
|
15
|
-
- pi 0.
|
|
15
|
+
- pi 0.85.1 or later (for `plexus-pi`)
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
@@ -109,13 +109,14 @@ To force a model refresh:
|
|
|
109
109
|
/plexus refresh
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
Inspect the effective URL, authentication availability, and catalog source without exposing a credential:
|
|
113
113
|
|
|
114
114
|
```
|
|
115
|
-
/plexus
|
|
116
|
-
/plexus set-default-model claude-sonnet-4-5
|
|
115
|
+
/plexus status
|
|
117
116
|
```
|
|
118
117
|
|
|
118
|
+
Select a Plexus model in `/model`. Save its startup default with the host's normal model-picker action; Plexus does not maintain a separate default-model setting.
|
|
119
|
+
|
|
119
120
|
Use `/login plexus` for setup and `/logout plexus` to remove stored credentials.
|
|
120
121
|
|
|
121
122
|
### Oh My Pi
|
|
@@ -126,35 +127,32 @@ Run inside Oh My Pi using the native login flow:
|
|
|
126
127
|
/login plexus
|
|
127
128
|
```
|
|
128
129
|
|
|
129
|
-
Same prompts and `/plexus refresh` / `/plexus
|
|
130
|
+
Same prompts and `/plexus refresh` / `/plexus status` commands as pi (see above). Save the selected startup model through OMP's normal `/model` or `/models` flow.
|
|
130
131
|
|
|
131
132
|
## Configuration files
|
|
132
133
|
|
|
133
|
-
###
|
|
134
|
+
### Connection state
|
|
134
135
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
plexus-models-response.json # raw API response (diagnostics)
|
|
140
|
-
plexus.log # extension activity log
|
|
136
|
+
Each adapter stores only non-secret Plexus settings in its own `config.json`:
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
<agent-dir>/extensions/plexus/config.json # base URL and optional model suppression
|
|
141
140
|
```
|
|
142
141
|
|
|
143
|
-
|
|
142
|
+
Credentials stay in the host credential store (`auth.json` for Pi, `agent.db` for OMP). Model catalogs stay in the host model registry/store. The extension no longer writes a second model cache, ETag file, raw API response, or default-model preference.
|
|
144
143
|
|
|
145
|
-
|
|
144
|
+
At runtime, configuration resolves as follows:
|
|
146
145
|
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
plexus.log # extension activity log
|
|
146
|
+
```text
|
|
147
|
+
base URL: PLEXUS_API_URL → PLEXUS_BASE_URL → saved Plexus base URL
|
|
148
|
+
API key: host credential store → PLEXUS_API_KEY process fallback
|
|
149
|
+
catalog: host model store → live Plexus refresh
|
|
150
|
+
startup model: host model-picker preference
|
|
153
151
|
```
|
|
154
152
|
|
|
155
|
-
|
|
153
|
+
`PLEXUS_API_URL` and `PLEXUS_BASE_URL` are process-only URL overrides; `PLEXUS_API_KEY` is a process-only credential fallback. None are persisted. `/plexus status` reports the effective URL source, whether auth is available, and catalog state without exposing credentials.
|
|
156
154
|
|
|
157
|
-
|
|
155
|
+
Plexus accepts a root URL or a `/v1` API URL. The adapter normalizes that only for the Plexus discovery request. Each model then receives its own API-specific base URL: OpenAI stays on `/v1`, Anthropic uses the root, and Google uses `/v1beta`.
|
|
158
156
|
|
|
159
157
|
---
|
|
160
158
|
|
|
@@ -200,16 +198,15 @@ packages/
|
|
|
200
198
|
src/
|
|
201
199
|
extension.ts # entry point: commands, session refresh, auth flow
|
|
202
200
|
mapper.ts # PlexusModelDescriptor → pi ProviderModelConfig
|
|
203
|
-
config.ts # base URL /
|
|
204
|
-
cache.ts # model
|
|
201
|
+
config.ts # base URL / suppression config I/O
|
|
202
|
+
cache.ts # Pi native model-store restore
|
|
205
203
|
log.ts # append-only log
|
|
206
204
|
package.json # declares pi.extensions entry point
|
|
207
205
|
plexus-oh-my-pi/ # Oh My Pi host adapter (fork of pi; own runtime packages + catalog)
|
|
208
206
|
src/
|
|
209
207
|
extension.ts # entry point: commands, session refresh, auth flow
|
|
210
208
|
mapper.ts # PlexusModelDescriptor → Oh My Pi ProviderModelConfig
|
|
211
|
-
config.ts # base URL /
|
|
212
|
-
cache.ts # model cache I/O
|
|
209
|
+
config.ts # base URL / suppression config I/O
|
|
213
210
|
log.ts # append-only log
|
|
214
211
|
package.json # declares omp.extensions entry point
|
|
215
212
|
```
|
package/dist/extension.js
CHANGED
|
@@ -432682,43 +432682,6 @@ function getEnvSuppressedModels() {
|
|
|
432682
432682
|
const raw = env.PLEXUS_SUPPRESS_MODELS ?? env.PLEXUS_EXCLUDE_MODELS;
|
|
432683
432683
|
return parseSuppressionPatterns(raw);
|
|
432684
432684
|
}
|
|
432685
|
-
function isModelSuppressed(model, patterns) {
|
|
432686
|
-
const envPatterns = getEnvSuppressedModels();
|
|
432687
|
-
const explicitPatterns = parseSuppressionPatterns(patterns);
|
|
432688
|
-
const allPatterns = [...envPatterns, ...explicitPatterns];
|
|
432689
|
-
if (allPatterns.length === 0)
|
|
432690
|
-
return false;
|
|
432691
|
-
const id = model.id.toLowerCase();
|
|
432692
|
-
const name = (model.name ?? "").toLowerCase();
|
|
432693
|
-
const shortId = id.includes("/") ? id.split("/").pop() : id.includes(":") ? id.split(":").pop() : id;
|
|
432694
|
-
for (const pattern of allPatterns) {
|
|
432695
|
-
if (matchesPattern(id, name, shortId, pattern)) {
|
|
432696
|
-
return true;
|
|
432697
|
-
}
|
|
432698
|
-
}
|
|
432699
|
-
return false;
|
|
432700
|
-
}
|
|
432701
|
-
function matchesPattern(id, name, shortId, pattern) {
|
|
432702
|
-
const p = pattern.toLowerCase();
|
|
432703
|
-
if (p.startsWith("regex:")) {
|
|
432704
|
-
try {
|
|
432705
|
-
const re = new RegExp(pattern.slice(6), "i");
|
|
432706
|
-
return re.test(id) || re.test(name) || re.test(shortId);
|
|
432707
|
-
} catch {
|
|
432708
|
-
return false;
|
|
432709
|
-
}
|
|
432710
|
-
}
|
|
432711
|
-
if (p.includes("*") || p.includes("?")) {
|
|
432712
|
-
const regexStr = "^" + p.replace(/([.+^${}()|[\]\\])/g, "\\$1").replace(/\*/g, ".*").replace(/\?/g, ".") + "$";
|
|
432713
|
-
try {
|
|
432714
|
-
const re = new RegExp(regexStr, "i");
|
|
432715
|
-
return re.test(id) || re.test(name) || re.test(shortId);
|
|
432716
|
-
} catch {
|
|
432717
|
-
return false;
|
|
432718
|
-
}
|
|
432719
|
-
}
|
|
432720
|
-
return id === p || name === p || shortId === p;
|
|
432721
|
-
}
|
|
432722
432685
|
// ../plexus-models/src/convert.ts
|
|
432723
432686
|
var REASONING_PARAMS = new Set(["reasoning", "include_reasoning", "reasoning_effort"]);
|
|
432724
432687
|
var NON_CHAT_PATTERN = /(?:^|[\W_])(?:embed(?:ding|dings)?|transcri(?:be[ds]?|ptions?)|whisper|speech[\W_]*to[\W_]*text|stt|text[\W_]*to[\W_]*speech|tts|image(?:[\W_]*(?:gen(?:eration)?|\d+))?|diffusion|dall[\W_]*e|stable[\W_]*diffusion|sdxl|dream)(?:$|[\W_])/i;
|
|
@@ -433092,7 +433055,7 @@ var normalizeConfigBaseUrl = (raw) => {
|
|
|
433092
433055
|
const root = normalizeRoot(raw);
|
|
433093
433056
|
return root.endsWith("/v1") ? root.slice(0, -3) : root;
|
|
433094
433057
|
};
|
|
433095
|
-
var
|
|
433058
|
+
var toPlexusApiBase = (raw) => {
|
|
433096
433059
|
const root = normalizeConfigBaseUrl(raw);
|
|
433097
433060
|
return root ? `${root}/v1` : "";
|
|
433098
433061
|
};
|
|
@@ -433109,39 +433072,38 @@ function getConfigSync() {
|
|
|
433109
433072
|
cachedConfig = {};
|
|
433110
433073
|
return cachedConfig;
|
|
433111
433074
|
}
|
|
433112
|
-
async function saveBaseUrl(baseUrl
|
|
433075
|
+
async function saveBaseUrl(baseUrl) {
|
|
433113
433076
|
await mkdir(getConfigDir(), { recursive: true });
|
|
433114
|
-
const existing = getConfigSync();
|
|
433077
|
+
const { defaultModel: _defaultModel, ...existing } = getConfigSync();
|
|
433115
433078
|
const config = {
|
|
433116
433079
|
...existing,
|
|
433117
|
-
baseUrl: normalizeConfigBaseUrl(baseUrl)
|
|
433118
|
-
...defaultModel !== undefined && { defaultModel }
|
|
433080
|
+
baseUrl: normalizeConfigBaseUrl(baseUrl)
|
|
433119
433081
|
};
|
|
433120
433082
|
await writeFile(getConfigPath(), `${JSON.stringify(config, null, 2)}
|
|
433121
433083
|
`, "utf8");
|
|
433122
433084
|
cachedConfig = config;
|
|
433123
433085
|
}
|
|
433124
|
-
|
|
433125
|
-
await mkdir(getConfigDir(), { recursive: true });
|
|
433126
|
-
const config = { ...getConfigSync(), defaultModel };
|
|
433127
|
-
await writeFile(getConfigPath(), `${JSON.stringify(config, null, 2)}
|
|
433128
|
-
`, "utf8");
|
|
433129
|
-
cachedConfig = config;
|
|
433130
|
-
}
|
|
433131
|
-
function getRawBaseUrl() {
|
|
433086
|
+
function getBaseUrlResolution() {
|
|
433132
433087
|
const config = getConfigSync();
|
|
433133
|
-
|
|
433088
|
+
const apiUrl = resolveStringOption(process.env[ENV_API_URL]);
|
|
433089
|
+
if (apiUrl)
|
|
433090
|
+
return { baseUrl: apiUrl, source: ENV_API_URL };
|
|
433091
|
+
const baseUrl = resolveStringOption(process.env[ENV_BASE_URL]);
|
|
433092
|
+
if (baseUrl)
|
|
433093
|
+
return { baseUrl, source: ENV_BASE_URL };
|
|
433094
|
+
const saved = resolveStringOption(config.baseUrl);
|
|
433095
|
+
return { baseUrl: saved ?? null, source: saved ? "saved" : "none" };
|
|
433134
433096
|
}
|
|
433135
433097
|
function getEnvApiKey() {
|
|
433136
433098
|
return resolveStringOption(process.env[ENV_API_KEY]) ?? null;
|
|
433137
433099
|
}
|
|
433138
433100
|
function getModelsUrl() {
|
|
433139
|
-
const
|
|
433140
|
-
return
|
|
433101
|
+
const { baseUrl } = getBaseUrlResolution();
|
|
433102
|
+
return baseUrl ? `${toPlexusApiBase(baseUrl)}/models` : null;
|
|
433141
433103
|
}
|
|
433142
433104
|
function getBaseUrl() {
|
|
433143
|
-
const
|
|
433144
|
-
return
|
|
433105
|
+
const { baseUrl } = getBaseUrlResolution();
|
|
433106
|
+
return baseUrl ? toPlexusApiBase(baseUrl) : null;
|
|
433145
433107
|
}
|
|
433146
433108
|
function getSuppressedModels() {
|
|
433147
433109
|
const config = getConfigSync();
|
|
@@ -433150,59 +433112,12 @@ function getSuppressedModels() {
|
|
|
433150
433112
|
return [...envSuppressed, ...configSuppressed];
|
|
433151
433113
|
}
|
|
433152
433114
|
|
|
433153
|
-
// src/
|
|
433154
|
-
import {
|
|
433155
|
-
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
433115
|
+
// src/log.ts
|
|
433116
|
+
import { mkdir as mkdir2, appendFile } from "fs/promises";
|
|
433156
433117
|
import { join as join2 } from "path";
|
|
433157
433118
|
import { getAgentDir as getAgentDir2 } from "@oh-my-pi/pi-utils";
|
|
433158
433119
|
var getCacheDir = () => join2(getAgentDir2(), "extensions", "plexus");
|
|
433159
|
-
var
|
|
433160
|
-
var getRawResponsePath = () => join2(getCacheDir(), "plexus-models-response.json");
|
|
433161
|
-
function parseCacheData(raw) {
|
|
433162
|
-
try {
|
|
433163
|
-
const parsed = JSON.parse(raw);
|
|
433164
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
433165
|
-
return null;
|
|
433166
|
-
const obj = parsed;
|
|
433167
|
-
if (!Array.isArray(obj["models"]))
|
|
433168
|
-
return null;
|
|
433169
|
-
return {
|
|
433170
|
-
models: obj["models"],
|
|
433171
|
-
timestamp: typeof obj["timestamp"] === "number" ? obj["timestamp"] : 0,
|
|
433172
|
-
etag: typeof obj["etag"] === "string" ? obj["etag"] : undefined
|
|
433173
|
-
};
|
|
433174
|
-
} catch {
|
|
433175
|
-
return null;
|
|
433176
|
-
}
|
|
433177
|
-
}
|
|
433178
|
-
function readCachedModelsSync() {
|
|
433179
|
-
try {
|
|
433180
|
-
const p = getModelsCachePath();
|
|
433181
|
-
if (!existsSync2(p))
|
|
433182
|
-
return null;
|
|
433183
|
-
return parseCacheData(readFileSync2(p, "utf8"));
|
|
433184
|
-
} catch {
|
|
433185
|
-
return null;
|
|
433186
|
-
}
|
|
433187
|
-
}
|
|
433188
|
-
async function writeCachedModels(models, etag) {
|
|
433189
|
-
await mkdir2(getCacheDir(), { recursive: true });
|
|
433190
|
-
const payload = { models, timestamp: Date.now(), etag };
|
|
433191
|
-
await writeFile2(getModelsCachePath(), `${JSON.stringify(payload, null, 2)}
|
|
433192
|
-
`, "utf8");
|
|
433193
|
-
}
|
|
433194
|
-
async function writeRawResponse(data) {
|
|
433195
|
-
await mkdir2(getCacheDir(), { recursive: true });
|
|
433196
|
-
await writeFile2(getRawResponsePath(), `${JSON.stringify(data, null, 2)}
|
|
433197
|
-
`, "utf8");
|
|
433198
|
-
}
|
|
433199
|
-
|
|
433200
|
-
// src/log.ts
|
|
433201
|
-
import { mkdir as mkdir3, appendFile } from "fs/promises";
|
|
433202
|
-
import { join as join3 } from "path";
|
|
433203
|
-
import { getAgentDir as getAgentDir3 } from "@oh-my-pi/pi-utils";
|
|
433204
|
-
var getCacheDir2 = () => join3(getAgentDir3(), "extensions", "plexus");
|
|
433205
|
-
var getLogPath = () => join3(getCacheDir2(), "plexus.log");
|
|
433120
|
+
var getLogPath = () => join2(getCacheDir(), "plexus.log");
|
|
433206
433121
|
var dirEnsured = false;
|
|
433207
433122
|
function log(message, data) {
|
|
433208
433123
|
writeLogLine(message, data);
|
|
@@ -433210,7 +433125,7 @@ function log(message, data) {
|
|
|
433210
433125
|
async function writeLogLine(message, data) {
|
|
433211
433126
|
try {
|
|
433212
433127
|
if (!dirEnsured) {
|
|
433213
|
-
await
|
|
433128
|
+
await mkdir2(getCacheDir(), { recursive: true });
|
|
433214
433129
|
dirEnsured = true;
|
|
433215
433130
|
}
|
|
433216
433131
|
const ts = new Date().toISOString();
|
|
@@ -440221,22 +440136,16 @@ function getProviderApiKeyConfig() {
|
|
|
440221
440136
|
return Bun.env[ENV_API_KEY]?.trim() ? { apiKey: ENV_API_KEY, authHeader: true } : {};
|
|
440222
440137
|
}
|
|
440223
440138
|
var currentModels = [];
|
|
440139
|
+
var catalogSource = "none";
|
|
440224
440140
|
function plexusExtension(pi) {
|
|
440225
|
-
const
|
|
440226
|
-
|
|
440227
|
-
const startupBaseUrl = getBaseUrl() ?? "http://localhost/v1";
|
|
440228
|
-
const startupModels = (cached?.models ?? []).filter((m) => !isModelSuppressed({ id: m.id, name: m.name }, suppressPatterns)).map(descriptorToOhMyPiModel);
|
|
440229
|
-
log("startup", {
|
|
440230
|
-
cachedModelCount: startupModels.length,
|
|
440231
|
-
startupBaseUrl
|
|
440232
|
-
});
|
|
440141
|
+
const startupBaseUrl = getBaseUrl();
|
|
440142
|
+
log("startup", { catalogSource, startupBaseUrl });
|
|
440233
440143
|
pi.registerProvider(PROVIDER_NAME, {
|
|
440234
440144
|
api: "openai-completions",
|
|
440235
440145
|
...getProviderApiKeyConfig(),
|
|
440236
|
-
...
|
|
440146
|
+
...startupBaseUrl ? { baseUrl: startupBaseUrl } : {},
|
|
440237
440147
|
oauth: createPlexusLoginProvider(pi)
|
|
440238
440148
|
});
|
|
440239
|
-
currentModels = startupModels;
|
|
440240
440149
|
pi.on("message_end", (event) => {
|
|
440241
440150
|
normalizeProviderConnectionClosed(event.message, PROVIDER_NAME);
|
|
440242
440151
|
});
|
|
@@ -440251,38 +440160,21 @@ function plexusExtension(pi) {
|
|
|
440251
440160
|
await doRefresh(pi, apiKey, ctx);
|
|
440252
440161
|
});
|
|
440253
440162
|
pi.registerCommand("plexus", {
|
|
440254
|
-
description: "Plexus provider commands: refresh,
|
|
440163
|
+
description: "Plexus provider commands: refresh, status (setup: /login plexus)",
|
|
440255
440164
|
getArgumentCompletions: (prefix) => {
|
|
440256
440165
|
const subcommands = [
|
|
440257
440166
|
{ value: "refresh", label: "refresh", description: "Refresh Plexus models from the API" },
|
|
440258
|
-
{ value: "
|
|
440167
|
+
{ value: "status", label: "status", description: "Show Plexus configuration and catalog status" }
|
|
440259
440168
|
];
|
|
440260
|
-
|
|
440261
|
-
return subcommands.filter((command) => command.value.startsWith(prefix));
|
|
440262
|
-
}
|
|
440263
|
-
const [subcommand, ...rest] = prefix.split(/\s+/);
|
|
440264
|
-
if (subcommand !== "set-default-model")
|
|
440265
|
-
return null;
|
|
440266
|
-
const modelPrefix = rest.join(" ");
|
|
440267
|
-
const choices = currentModels.map((model) => ({
|
|
440268
|
-
value: model.id,
|
|
440269
|
-
label: model.name === model.id ? model.id : `${model.name} (${model.id})`
|
|
440270
|
-
}));
|
|
440271
|
-
const filtered = choices.filter((choice) => choice.value.toLowerCase().startsWith(modelPrefix.toLowerCase()));
|
|
440272
|
-
return filtered.length > 0 ? filtered : null;
|
|
440169
|
+
return prefix.includes(" ") ? null : subcommands.filter((command) => command.value.startsWith(prefix));
|
|
440273
440170
|
},
|
|
440274
440171
|
handler: async (args, ctx) => {
|
|
440275
|
-
const
|
|
440276
|
-
|
|
440277
|
-
|
|
440278
|
-
|
|
440279
|
-
return;
|
|
440280
|
-
}
|
|
440281
|
-
if (sub === "set-default-model" || sub.startsWith("set-default-model ")) {
|
|
440282
|
-
await handleSetDefaultModel(pi, ctx, trimmed.slice("set-default-model".length).trim());
|
|
440283
|
-
return;
|
|
440284
|
-
}
|
|
440285
|
-
ctx.ui.notify(`Unknown sub-command: "${args}". Use /login plexus, /plexus refresh, or /plexus set-default-model.`, "warning");
|
|
440172
|
+
const sub = args.trim().toLowerCase();
|
|
440173
|
+
if (sub === "refresh" || sub === "")
|
|
440174
|
+
return handleRefresh(pi, ctx);
|
|
440175
|
+
if (sub === "status")
|
|
440176
|
+
return handleStatus(ctx);
|
|
440177
|
+
ctx.ui.notify(`Unknown sub-command: "${args}". Use /login plexus, /plexus refresh, or /plexus status.`, "warning");
|
|
440286
440178
|
}
|
|
440287
440179
|
});
|
|
440288
440180
|
}
|
|
@@ -440315,29 +440207,16 @@ async function handleRefresh(pi, ctx) {
|
|
|
440315
440207
|
ctx.ui.notify("Refreshing Plexus models\u2026", "info");
|
|
440316
440208
|
await doRefresh(pi, apiKey, ctx);
|
|
440317
440209
|
}
|
|
440318
|
-
async function
|
|
440319
|
-
|
|
440320
|
-
|
|
440321
|
-
|
|
440322
|
-
|
|
440323
|
-
|
|
440324
|
-
}
|
|
440325
|
-
|
|
440326
|
-
|
|
440327
|
-
|
|
440328
|
-
return;
|
|
440329
|
-
const selectedIndex = choices.indexOf(selected);
|
|
440330
|
-
modelId = currentModels[selectedIndex]?.id ?? "";
|
|
440331
|
-
}
|
|
440332
|
-
const model = currentModels.find((candidate) => candidate.id === modelId);
|
|
440333
|
-
if (!model) {
|
|
440334
|
-
ctx.ui.notify(`Plexus model not found: "${modelId}". Run /plexus refresh and choose a model from the available list.`, "error");
|
|
440335
|
-
return;
|
|
440336
|
-
}
|
|
440337
|
-
await saveDefaultModel(model.id);
|
|
440338
|
-
const registryModel = ctx.modelRegistry.find(PROVIDER_NAME, model.id) ?? model;
|
|
440339
|
-
const active = await pi.setModel(registryModel);
|
|
440340
|
-
ctx.ui.notify(active ? `Plexus model selected: ${model.id}.` : `Plexus model ${model.id} was saved but could not be selected in this session.`, active ? "info" : "warning");
|
|
440210
|
+
async function handleStatus(ctx) {
|
|
440211
|
+
const baseUrl = getBaseUrlResolution();
|
|
440212
|
+
const apiKey = await ctx.modelRegistry.authStorage.getApiKey(PROVIDER_NAME);
|
|
440213
|
+
ctx.ui.notify([
|
|
440214
|
+
`Plexus base URL: ${baseUrl.baseUrl ?? "not configured"} (${baseUrl.source})`,
|
|
440215
|
+
`API key: ${apiKey ? getEnvApiKey() ? "host credential or PLEXUS_API_KEY fallback" : "host credential" : "not configured"}`,
|
|
440216
|
+
`Catalog: ${currentModels.length} models (${catalogSource})`,
|
|
440217
|
+
"Default model: managed by OMP. Use /model or /models to save the selection there."
|
|
440218
|
+
].join(`
|
|
440219
|
+
`), "info");
|
|
440341
440220
|
}
|
|
440342
440221
|
async function doRefresh(pi, apiKey, ctx) {
|
|
440343
440222
|
const modelsUrl = getModelsUrl();
|
|
@@ -440349,19 +440228,12 @@ async function doRefresh(pi, apiKey, ctx) {
|
|
|
440349
440228
|
return;
|
|
440350
440229
|
}
|
|
440351
440230
|
try {
|
|
440352
|
-
const
|
|
440353
|
-
const { models: apiModels, raw, etag, notModified } = await fetchPlexusModels(apiKey, modelsUrl, undefined, cached?.etag);
|
|
440354
|
-
if (notModified) {
|
|
440355
|
-
log("doRefresh: not modified", { etag: cached?.etag });
|
|
440356
|
-
if (ctx)
|
|
440357
|
-
ctx.ui.notify(`Refreshed ${currentModels.length} Plexus models (not modified)`, "info");
|
|
440358
|
-
return;
|
|
440359
|
-
}
|
|
440231
|
+
const { models: apiModels } = await fetchPlexusModels(apiKey, modelsUrl);
|
|
440360
440232
|
const suppressPatterns = getSuppressedModels();
|
|
440361
440233
|
const descriptors = convertDescriptors(apiModels, baseUrl, suppressPatterns);
|
|
440362
440234
|
const ohMyPiModels = descriptors.map(descriptorToOhMyPiModel);
|
|
440363
|
-
await Promise.all([writeCachedModels(descriptors, etag), raw ? writeRawResponse(raw) : Promise.resolve()]);
|
|
440364
440235
|
currentModels = ohMyPiModels;
|
|
440236
|
+
catalogSource = "live refresh";
|
|
440365
440237
|
pi.registerProvider(PROVIDER_NAME, {
|
|
440366
440238
|
api: "openai-completions",
|
|
440367
440239
|
...getProviderApiKeyConfig(),
|