opencode-ufr 0.2.3 → 0.2.5
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 +20 -3
- package/package.json +1 -1
- package/src/plugin/connect.ts +17 -1
- package/src/plugin/index.ts +6 -0
package/README.md
CHANGED
|
@@ -23,6 +23,23 @@ opencode plugin add opencode-ufr # registers the plugin
|
|
|
23
23
|
|
|
24
24
|
(or add `"plugins": ["opencode-ufr"]` to your `opencode.json` manually.)
|
|
25
25
|
|
|
26
|
+
## Updating
|
|
27
|
+
|
|
28
|
+
opencode loads plugins inside a background server (`opencode serve --service`)
|
|
29
|
+
that keeps running after you close the TUI, and it keeps using the plugin
|
|
30
|
+
version it loaded when it started — a new release only arrives once that server
|
|
31
|
+
restarts:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bun add -g opencode-ufr@latest # update the `ufr` CLI
|
|
35
|
+
pkill -f "opencode serve --service" # stop opencode's background server
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The next opencode start installs the latest plugin. If it still loads the old
|
|
39
|
+
one, delete opencode's cached copy (`~/.cache/opencode/npm/opencode-ufr@latest`)
|
|
40
|
+
and start opencode again. On Windows, end the `opencode` server process in Task
|
|
41
|
+
Manager instead of `pkill`.
|
|
42
|
+
|
|
26
43
|
## Setup
|
|
27
44
|
|
|
28
45
|
**Inside opencode — the normal way:** open `/connect`, pick **Uni Freiburg**,
|
|
@@ -66,9 +83,9 @@ ufr disconnect # remove everything: keys, uni login, config, gateway
|
|
|
66
83
|
Removing the **unifreiburg** integration in opencode's `/connect` panel does the
|
|
67
84
|
same as `ufr disconnect`: the stored keys and uni login are wiped, the gateway
|
|
68
85
|
stops, and the models disappear from the picker on the next opencode start.
|
|
69
|
-
While opencode runs,
|
|
70
|
-
closed when you removed the integration, run `ufr disconnect` once
|
|
71
|
-
is left.
|
|
86
|
+
While opencode runs, connecting and removing are noticed within seconds. If
|
|
87
|
+
opencode was closed when you removed the integration, run `ufr disconnect` once
|
|
88
|
+
to wipe what is left.
|
|
72
89
|
|
|
73
90
|
## The built-in VPN
|
|
74
91
|
|
package/package.json
CHANGED
package/src/plugin/connect.ts
CHANGED
|
@@ -13,6 +13,9 @@ import { applyKeyChange, disconnectAll } from "../cli/keys"
|
|
|
13
13
|
|
|
14
14
|
export const UFR_INTEGRATION_ID = "unifreiburg"
|
|
15
15
|
|
|
16
|
+
/** opencode has no connection events for plugins, so the watcher polls; seconds keep /connect feeling immediate. */
|
|
17
|
+
export const CONNECT_POLL_MS = 5_000
|
|
18
|
+
|
|
16
19
|
export type ConnectDeps = {
|
|
17
20
|
ctx: any // opencode plugin context (integration + storage domains)
|
|
18
21
|
paths: Paths
|
|
@@ -23,6 +26,8 @@ export type ConnectDeps = {
|
|
|
23
26
|
register?: () => Promise<boolean | void> | boolean | void
|
|
24
27
|
/** Whether setup() already registered the provider (it does when a connection exists at startup). */
|
|
25
28
|
providerRegistered?: boolean
|
|
29
|
+
/** Poll interval override (tests). */
|
|
30
|
+
pollMs?: number
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
type CredentialValue = { type?: string; key?: string; configuration?: Record<string, unknown> } | undefined
|
|
@@ -131,7 +136,18 @@ export async function registerConnect(d: ConnectDeps): Promise<ConnectRegistrati
|
|
|
131
136
|
}
|
|
132
137
|
|
|
133
138
|
await applyOnce()
|
|
134
|
-
|
|
139
|
+
// A registration can take ~40 s (gateway boot) — never start a second one while it runs.
|
|
140
|
+
let busy = false
|
|
141
|
+
const tick = async () => {
|
|
142
|
+
if (busy) return
|
|
143
|
+
busy = true
|
|
144
|
+
try {
|
|
145
|
+
await applyOnce()
|
|
146
|
+
} finally {
|
|
147
|
+
busy = false
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const timer = setInterval(() => void tick(), d.pollMs ?? CONNECT_POLL_MS)
|
|
135
151
|
;(timer as { unref?: () => void }).unref?.()
|
|
136
152
|
return {
|
|
137
153
|
stop: () => clearInterval(timer),
|
package/src/plugin/index.ts
CHANGED
|
@@ -10,6 +10,11 @@ import { toModelInfo } from "./model-info"
|
|
|
10
10
|
|
|
11
11
|
const DAEMON_ENTRY = fileURLToPath(new URL("../daemon/main.ts", import.meta.url))
|
|
12
12
|
|
|
13
|
+
// opencode takes a request's key from the provider's integration (default: the one with the provider's
|
|
14
|
+
// id), and a key credential there replaces settings.apiKey. The /connect credential on "unifreiburg"
|
|
15
|
+
// holds the UFR keys, not the gateway token — so link the provider to an integration with no credential.
|
|
16
|
+
const GATEWAY_INTEGRATION_ID = "opencode-ufr-gateway"
|
|
17
|
+
|
|
13
18
|
function log(msg: string): void {
|
|
14
19
|
console.warn(`[opencode-ufr] ${msg}`)
|
|
15
20
|
}
|
|
@@ -58,6 +63,7 @@ async function registerProvider(
|
|
|
58
63
|
info: {
|
|
59
64
|
id: providerId,
|
|
60
65
|
name: providerName,
|
|
66
|
+
integrationID: GATEWAY_INTEGRATION_ID,
|
|
61
67
|
activation: "enabled",
|
|
62
68
|
package: "@opencode/ai/providers/openai-compatible",
|
|
63
69
|
settings: { baseURL: `http://127.0.0.1:${conn.port}/v1`, apiKey: conn.token },
|