@mcowger/oh-my-pi-plexus 1.6.1 → 1.7.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 +45 -1
- package/dist/extension.js +17 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,11 +8,13 @@ Exposes models from a self-hosted [Plexus](https://github.com/mcowger/plexus) AI
|
|
|
8
8
|
|---|---|---|
|
|
9
9
|
| `plexus-pi` | [pi](https://github.com/earendil-works/pi) | `@mcowger/pi-plexus` |
|
|
10
10
|
| `plexus-oh-my-pi` | [Oh My Pi](https://github.com/can1357/oh-my-pi) | `@mcowger/oh-my-pi-plexus` |
|
|
11
|
+
| `plexus-opencode-v2` | [OpenCode](https://github.com/anomalyco/opencode) V2 | `@mcowger/opencode-plexus` |
|
|
11
12
|
|
|
12
13
|
## Prerequisites
|
|
13
14
|
|
|
14
15
|
- A running Plexus instance
|
|
15
16
|
- pi 0.85.1 or later (for `plexus-pi`)
|
|
17
|
+
- OpenCode V2 (for `plexus-opencode-v2`)
|
|
16
18
|
|
|
17
19
|
## Installation
|
|
18
20
|
|
|
@@ -86,6 +88,28 @@ Then register the path in `~/.omp/agent/settings.json`:
|
|
|
86
88
|
}
|
|
87
89
|
```
|
|
88
90
|
|
|
91
|
+
### OpenCode (V2)
|
|
92
|
+
|
|
93
|
+
Add the plugin to `~/.config/opencode/opencode.jsonc`, either from npm or from a local clone (local plugins must point at the package directory, not a file):
|
|
94
|
+
|
|
95
|
+
```jsonc
|
|
96
|
+
{
|
|
97
|
+
"plugins": ["@mcowger/opencode-plexus"]
|
|
98
|
+
// or: ["file:///home/you/code/plexus-agent-plugins/packages/plexus-opencode-v2"]
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
If you use `experimental.policies` to restrict providers, policies are last-match-wins — put the `plexus` allow **after** any `"*"` deny:
|
|
103
|
+
|
|
104
|
+
```jsonc
|
|
105
|
+
"policies": [
|
|
106
|
+
{ "action": "provider.use", "resource": "*", "effect": "deny" },
|
|
107
|
+
{ "action": "provider.use", "resource": "plexus", "effect": "allow" }
|
|
108
|
+
]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Restart the service (`opencode service stop && opencode service start`) after changing plugins.
|
|
112
|
+
|
|
89
113
|
---
|
|
90
114
|
|
|
91
115
|
## First-time setup
|
|
@@ -129,6 +153,18 @@ Run inside Oh My Pi using the native login flow:
|
|
|
129
153
|
|
|
130
154
|
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.
|
|
131
155
|
|
|
156
|
+
### OpenCode (V2)
|
|
157
|
+
|
|
158
|
+
Run `/connect` and pick **Plexus**. You will be prompted for the Plexus base URL and API key; models load immediately — no restart needed. Disconnecting, reconnecting, or rotating the key also reloads the model list.
|
|
159
|
+
|
|
160
|
+
To force a model refresh:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
/plexus-refresh
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`PLEXUS_API_URL` / `PLEXUS_BASE_URL` / `PLEXUS_API_KEY` env vars and plugin options (`plexusBaseURL`, `suppressModels`) are also honored. Until a URL is configured, the provider shows a single `plexus-unconfigured` placeholder. Plugin logs are written to `~/.local/share/opencode/plugins/plexus/plugin.log` (the OpenCode service discards plugin stdout).
|
|
167
|
+
|
|
132
168
|
## Configuration files
|
|
133
169
|
|
|
134
170
|
### Connection state
|
|
@@ -209,6 +245,14 @@ packages/
|
|
|
209
245
|
config.ts # base URL / suppression config I/O
|
|
210
246
|
log.ts # append-only log
|
|
211
247
|
package.json # declares omp.extensions entry point
|
|
248
|
+
plexus-opencode-v2/ # OpenCode V2 provider plugin
|
|
249
|
+
src/
|
|
250
|
+
plugin.ts # entry point: provider/integration transforms, /plexus-refresh, credential watcher
|
|
251
|
+
mapper.ts # PlexusModelDescriptor → OpenCode Model.Info
|
|
252
|
+
config-store.ts # base URL / API key / suppression resolution
|
|
253
|
+
cache.ts # model cache I/O
|
|
254
|
+
log.ts # console + file log
|
|
255
|
+
server.js # root entrypoint required by OpenCode for directory plugins
|
|
212
256
|
```
|
|
213
257
|
|
|
214
258
|
`plexus-models` has zero imports from any agent framework. Each host adapter imports it via a relative path.
|
|
@@ -247,6 +291,6 @@ The pre-commit hook (via lefthook) rebuilds the active dist artifacts automatica
|
|
|
247
291
|
|
|
248
292
|
## Archived adapters
|
|
249
293
|
|
|
250
|
-
`packages/deprecated/plexus-opencode` is preserved for reference but is archived. It is private and excluded from builds, tests, hooks, version sync, and publishing.
|
|
294
|
+
`packages/deprecated/plexus-opencode` (the OpenCode V1 adapter) is preserved for reference but is archived. It is private and excluded from builds, tests, hooks, version sync, and publishing. It is superseded by `plexus-opencode-v2`.
|
|
251
295
|
|
|
252
296
|
To add support for a new host agent, see [AGENTS.md](AGENTS.md).
|
package/dist/extension.js
CHANGED
|
@@ -16156,6 +16156,8 @@ function convertToDescriptor(raw, baseUrl) {
|
|
|
16156
16156
|
function isChatModel(model) {
|
|
16157
16157
|
if (!model.id)
|
|
16158
16158
|
return false;
|
|
16159
|
+
if (model.type !== undefined && model.type !== "text")
|
|
16160
|
+
return false;
|
|
16159
16161
|
const inputModalities = model.architecture?.input_modalities;
|
|
16160
16162
|
if (inputModalities !== undefined && inputModalities.length > 0 && !inputModalities.includes("text")) {
|
|
16161
16163
|
return false;
|
|
@@ -23202,6 +23204,7 @@ function plexusExtension(pi) {
|
|
|
23202
23204
|
api: "openai-completions",
|
|
23203
23205
|
...getProviderApiKeyConfig(),
|
|
23204
23206
|
...startupBaseUrl ? { baseUrl: startupBaseUrl } : {},
|
|
23207
|
+
fetchDynamicModels: fetchPlexusModelConfigs,
|
|
23205
23208
|
oauth: createPlexusLoginProvider(pi)
|
|
23206
23209
|
});
|
|
23207
23210
|
pi.on("message_end", (event) => {
|
|
@@ -23276,6 +23279,19 @@ async function handleStatus(ctx) {
|
|
|
23276
23279
|
].join(`
|
|
23277
23280
|
`), "info");
|
|
23278
23281
|
}
|
|
23282
|
+
async function fetchPlexusModelConfigs(apiKey) {
|
|
23283
|
+
const key = apiKey ?? getEnvApiKey();
|
|
23284
|
+
const modelsUrl = getModelsUrl();
|
|
23285
|
+
const baseUrl = getBaseUrl();
|
|
23286
|
+
if (!key || !modelsUrl || !baseUrl)
|
|
23287
|
+
return [];
|
|
23288
|
+
const { models: apiModels } = await fetchPlexusModels(key, modelsUrl);
|
|
23289
|
+
const descriptors = convertDescriptors(apiModels, baseUrl, getSuppressedModels());
|
|
23290
|
+
const models = descriptors.map(descriptorToOhMyPiModel);
|
|
23291
|
+
currentModels = [...models];
|
|
23292
|
+
catalogSource = "live refresh";
|
|
23293
|
+
return models;
|
|
23294
|
+
}
|
|
23279
23295
|
async function doRefresh(pi, apiKey, ctx) {
|
|
23280
23296
|
const modelsUrl = getModelsUrl();
|
|
23281
23297
|
const baseUrl = getBaseUrl();
|
|
@@ -23297,6 +23313,7 @@ async function doRefresh(pi, apiKey, ctx) {
|
|
|
23297
23313
|
...getProviderApiKeyConfig(),
|
|
23298
23314
|
baseUrl,
|
|
23299
23315
|
models: ohMyPiModels,
|
|
23316
|
+
fetchDynamicModels: fetchPlexusModelConfigs,
|
|
23300
23317
|
oauth: createPlexusLoginProvider(pi)
|
|
23301
23318
|
});
|
|
23302
23319
|
log("doRefresh: registered", { count: ohMyPiModels.length });
|