@vymalo/opencode-lightbridge 0.16.1 → 0.18.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 +101 -38
- package/dist/config.d.ts +70 -4
- package/dist/config.js +76 -3
- package/dist/config.js.map +1 -1
- package/dist/lib.d.ts +4 -3
- package/dist/lib.js +4 -3
- package/dist/lib.js.map +1 -1
- package/dist/logging.d.ts +44 -0
- package/dist/logging.js +100 -0
- package/dist/logging.js.map +1 -0
- package/dist/migration.d.ts +31 -0
- package/dist/migration.js +91 -0
- package/dist/migration.js.map +1 -0
- package/dist/opencode.d.ts +33 -15
- package/dist/opencode.js +390 -194
- package/dist/opencode.js.map +1 -1
- package/dist/otel-adapter.d.ts +68 -0
- package/dist/otel-adapter.js +315 -0
- package/dist/otel-adapter.js.map +1 -0
- package/dist/plugin.d.ts +77 -23
- package/dist/plugin.js +157 -33
- package/dist/plugin.js.map +1 -1
- package/package.json +15 -9
package/dist/plugin.js
CHANGED
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { createJsonConsoleLogger, DEFAULT_TOKEN_EXPIRY_SKEW_MS, resolveCacheRoot, TokenRuntime } from "@vymalo/opencode-auth-core/lib";
|
|
3
|
+
import { FileCacheStore as SharedFileCacheStore } from "@vymalo/opencode-provider-sync/lib";
|
|
4
|
+
import { migrateRootTokenIfNeeded } from "./migration.js";
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
+
* Legacy identity for the exchanged project-token store (UNCHANGED by
|
|
7
|
+
* ADR-0017 — see `migration.ts`'s module doc for why only the ROOT token
|
|
8
|
+
* relocated). Kept as a constant, not `auth.id`, because the exchanged-token
|
|
9
|
+
* cache key has always been derived from this literal, independent of the
|
|
10
|
+
* configured IdP's `id`.
|
|
6
11
|
*/
|
|
7
12
|
export const LIGHTBRIDGE_IDENTITY = "lightbridge";
|
|
8
|
-
/** Own cache namespace — separate from oauth2/repo-auth/otel's
|
|
13
|
+
/** Own cache namespace for the exchanged-token store — separate from oauth2/repo-auth/otel's. */
|
|
9
14
|
export const DEFAULT_CACHE_NAMESPACE = "opencode-lightbridge";
|
|
10
15
|
/**
|
|
16
|
+
* ADR-0017: the human ROOT token now lives in the SAME cache file
|
|
17
|
+
* `@vymalo/opencode-oauth2` uses for a server of this id —
|
|
18
|
+
* `<cacheRoot>/opencode-oauth2/opencode-oauth2-model-sync/<id>.json`, a fused
|
|
19
|
+
* `CachedServerState` (token + discovered models). This is what lets a
|
|
20
|
+
* developer who configures the same IdP (`auth.id` == an oauth2 `servers[].id`,
|
|
21
|
+
* same issuer/clientId) log in ONCE and have both plugins read/write the same
|
|
22
|
+
* on-disk state. The literals are pinned here (not imported from
|
|
23
|
+
* `@vymalo/opencode-oauth2`, which lightbridge does not depend on) — see
|
|
24
|
+
* `docs/adr/0017-lightbridge-all-in-one.md` for the shared-contract rationale.
|
|
25
|
+
*/
|
|
26
|
+
export const ROOT_CACHE_SEGMENT = "opencode-oauth2";
|
|
27
|
+
export const ROOT_CACHE_NAMESPACE = "opencode-oauth2-model-sync";
|
|
28
|
+
/**
|
|
11
29
|
* Cache key for the default-project token — used when no `projectId` is
|
|
12
30
|
* configured, so the exchange sends no `project_id` and the backend mints a
|
|
13
31
|
* token for the caller's default project (ADR-0012). Distinct from any real
|
|
@@ -15,10 +33,9 @@ export const DEFAULT_CACHE_NAMESPACE = "opencode-lightbridge";
|
|
|
15
33
|
*/
|
|
16
34
|
export const DEFAULT_PROJECT_KEY = "__default__";
|
|
17
35
|
/**
|
|
18
|
-
* Whether a cached project token is usable.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* non-expiring.
|
|
36
|
+
* Whether a cached project token is usable. The project token carries no
|
|
37
|
+
* refresh token, so an undefined `expiresAt` must be treated as expired
|
|
38
|
+
* (re-exchange), never as non-expiring.
|
|
22
39
|
*/
|
|
23
40
|
function isProjectTokenUsable(token, skewMs) {
|
|
24
41
|
if (!token?.accessToken) {
|
|
@@ -30,59 +47,148 @@ function isProjectTokenUsable(token, skewMs) {
|
|
|
30
47
|
return Date.now() + skewMs < token.expiresAt;
|
|
31
48
|
}
|
|
32
49
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
50
|
+
* Build the ONE shared root `TokenRuntime` for `serverId`, persisting through
|
|
51
|
+
* the SAME fused `CachedServerState` shape+location `ProviderModelSyncEngine`
|
|
52
|
+
* uses (see `ROOT_CACHE_SEGMENT`/`ROOT_CACHE_NAMESPACE` above) — mirroring the
|
|
53
|
+
* override pattern in `@vymalo/opencode-provider-sync`'s
|
|
54
|
+
* `ProviderModelSyncEngine.buildTokenRuntime` (extract `.token`, preserve
|
|
55
|
+
* `.models`/`.rawModels` on write) but WITHOUT running that engine's
|
|
56
|
+
* scheduler/model-discovery — this is a read/refresh-only participant in the
|
|
57
|
+
* shared cache file, not a second poller (see ADR-0017's double-scheduling
|
|
58
|
+
* guard, enforced inside the engine itself for the `register` path).
|
|
59
|
+
*
|
|
60
|
+
* Unlike `ProviderModelSyncEngine`, this performs no cross-process
|
|
61
|
+
* "adopt-if-newer" reconciliation — every `getCached()` call here reads disk
|
|
62
|
+
* fresh and takes it as-is. That is deliberately simpler (no in-memory
|
|
63
|
+
* snapshot to reconcile against) and still safe: a momentarily unreadable/
|
|
64
|
+
* missing file degrades to "no cached token" (a safe, if suboptimal,
|
|
65
|
+
* fallback), and refreshes are still coordinated via `TokenRuntime`'s own
|
|
66
|
+
* cross-process file lock.
|
|
67
|
+
*/
|
|
68
|
+
function buildSharedRootTokenRuntime(serverId, auth, sharedStore, options) {
|
|
69
|
+
return new TokenRuntime(serverId, auth, {
|
|
70
|
+
logger: options.logger,
|
|
71
|
+
fetchImpl: options.fetchImpl,
|
|
72
|
+
onAuthorizationUrl: options.onAuthorizationUrl,
|
|
73
|
+
tokenExpirySkewMs: options.tokenExpirySkewMs,
|
|
74
|
+
serviceLabel: "opencode-lightbridge",
|
|
75
|
+
getCached: async () => {
|
|
76
|
+
const state = await sharedStore.loadServerState(serverId);
|
|
77
|
+
return state?.token;
|
|
78
|
+
},
|
|
79
|
+
setCached: async (token) => {
|
|
80
|
+
const existing = await sharedStore.loadServerState(serverId);
|
|
81
|
+
const next = {
|
|
82
|
+
serverId,
|
|
83
|
+
updatedAt: Date.now(),
|
|
84
|
+
lastSyncAt: existing?.lastSyncAt,
|
|
85
|
+
models: existing?.models ?? [],
|
|
86
|
+
rawModels: existing?.rawModels ?? [],
|
|
87
|
+
token
|
|
88
|
+
};
|
|
89
|
+
await sharedStore.saveServerState(next);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The ONE shared runtime the umbrella plugin builds (ADR-0012, amended by
|
|
95
|
+
* ADR-0017): a single human login, reused as the subject token for a
|
|
96
|
+
* project-scoped RFC 8693 exchange (when `gateway.exchange` is `true`) or
|
|
97
|
+
* used directly as the gateway/OTEL bearer (the new default) — consumed by
|
|
98
|
+
* BOTH the gateway (`chat.headers`) and OTEL (`TokenSource.headers()`).
|
|
99
|
+
*
|
|
100
|
+
* The human root token itself is no longer lightbridge-exclusive storage: it
|
|
101
|
+
* lives in the SAME cache file `@vymalo/opencode-oauth2` writes for a server
|
|
102
|
+
* of this id (`ROOT_CACHE_SEGMENT`/`ROOT_CACHE_NAMESPACE`), so configuring
|
|
103
|
+
* both plugins against the same IdP (`auth.id` matching an oauth2
|
|
104
|
+
* `servers[].id`, same issuer/clientId) means logging in once. An upgrading
|
|
105
|
+
* install's pre-existing root token is migrated in automatically — see
|
|
106
|
+
* `migration.ts`.
|
|
41
107
|
*/
|
|
42
108
|
export class LightbridgeRuntime {
|
|
43
109
|
projectId;
|
|
44
|
-
|
|
110
|
+
rootRuntime;
|
|
111
|
+
sharedStore;
|
|
112
|
+
exchangeRuntime;
|
|
45
113
|
logger;
|
|
46
114
|
tokenExpirySkewMs;
|
|
115
|
+
exchange;
|
|
116
|
+
cacheRoot;
|
|
117
|
+
serverId;
|
|
47
118
|
/** Token-cache key: the project id, or `DEFAULT_PROJECT_KEY` when unset. */
|
|
48
119
|
projectKey;
|
|
49
120
|
inFlightExchange;
|
|
121
|
+
migration;
|
|
50
122
|
constructor(auth, projectId, options = {}) {
|
|
51
123
|
this.projectId = projectId;
|
|
124
|
+
this.serverId = auth.id;
|
|
52
125
|
this.projectKey = projectId ?? DEFAULT_PROJECT_KEY;
|
|
53
126
|
this.logger = options.logger ?? createJsonConsoleLogger("info");
|
|
127
|
+
this.exchange = options.exchange ?? false;
|
|
128
|
+
this.cacheRoot = options.cacheDir ?? resolveCacheRoot();
|
|
54
129
|
this.tokenExpirySkewMs = typeof options.tokenExpirySkewMs === "number" && Number.isFinite(options.tokenExpirySkewMs) && options.tokenExpirySkewMs > 0 ? options.tokenExpirySkewMs : DEFAULT_TOKEN_EXPIRY_SKEW_MS;
|
|
55
|
-
this.
|
|
130
|
+
this.sharedStore = new SharedFileCacheStore(join(this.cacheRoot, ROOT_CACHE_SEGMENT, ROOT_CACHE_NAMESPACE), this.logger);
|
|
131
|
+
this.rootRuntime = buildSharedRootTokenRuntime(this.serverId, auth, this.sharedStore, options);
|
|
132
|
+
// The exchange-only runtime keeps its OWN dedicated, lightbridge-exclusive
|
|
133
|
+
// store (unchanged location/shape) — there is no oauth2 equivalent for a
|
|
134
|
+
// project-scoped exchanged token, so nothing to share here.
|
|
135
|
+
this.exchangeRuntime = new TokenRuntime(LIGHTBRIDGE_IDENTITY, auth, {
|
|
56
136
|
logger: this.logger,
|
|
57
137
|
fetchImpl: options.fetchImpl,
|
|
58
138
|
onAuthorizationUrl: options.onAuthorizationUrl,
|
|
59
|
-
cacheDir:
|
|
60
|
-
tokenExpirySkewMs: this.tokenExpirySkewMs
|
|
139
|
+
cacheDir: join(this.cacheRoot, DEFAULT_CACHE_NAMESPACE),
|
|
140
|
+
tokenExpirySkewMs: this.tokenExpirySkewMs,
|
|
141
|
+
serviceLabel: "opencode-lightbridge"
|
|
61
142
|
});
|
|
62
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* One-time (per instance) migration of a pre-ADR-0017 root token into the
|
|
146
|
+
* shared cache file — see `migration.ts`. Idempotent and cheap on every
|
|
147
|
+
* call after the first (the underlying function also short-circuits once
|
|
148
|
+
* the new location has ANY state).
|
|
149
|
+
*/
|
|
150
|
+
ensureMigrated() {
|
|
151
|
+
if (!this.migration) {
|
|
152
|
+
this.migration = migrateRootTokenIfNeeded(this.cacheRoot, ROOT_CACHE_SEGMENT, ROOT_CACHE_NAMESPACE, this.serverId, this.logger).catch((error) => {
|
|
153
|
+
// Never fatal: worst case is a fresh login, same as a first-ever
|
|
154
|
+
// install. Swallow so a migration hiccup can't break normal auth.
|
|
155
|
+
this.logger.debug("lightbridge_root_migration_error", { error: error instanceof Error ? error.message : String(error) });
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return this.migration;
|
|
159
|
+
}
|
|
63
160
|
/** Non-network read of the cached project token, if any. */
|
|
64
161
|
async getCachedProjectToken() {
|
|
65
|
-
return this.
|
|
162
|
+
return this.exchangeRuntime.getExchangedByKey(this.projectKey);
|
|
66
163
|
}
|
|
67
164
|
/**
|
|
68
|
-
* Resolve a usable
|
|
69
|
-
* `chat.headers`, OTEL `TokenSource.headers()`)
|
|
165
|
+
* Resolve a usable gateway/OTEL bearer, shared by every caller (gateway
|
|
166
|
+
* `chat.headers`, OTEL `TokenSource.headers()`).
|
|
167
|
+
*
|
|
168
|
+
* `gateway.exchange: false` (default, ADR-0017): the IdP access token IS
|
|
169
|
+
* the bearer — just `ensure()` the shared root token (refresh-only unless
|
|
170
|
+
* `interactive`).
|
|
171
|
+
*
|
|
172
|
+
* `gateway.exchange: true` (ADR-0012, unchanged):
|
|
70
173
|
*
|
|
71
|
-
* cached usable? ──yes──▶ return it
|
|
174
|
+
* cached exchanged token usable? ──yes──▶ return it
|
|
72
175
|
* │ no
|
|
73
176
|
* ▼
|
|
74
|
-
* ensure human root (refresh-only unless `interactive`)
|
|
177
|
+
* ensure shared human root (refresh-only unless `interactive`)
|
|
75
178
|
* ▼
|
|
76
179
|
* exchangeTo(projectKey, humanToken, projectId ? { project_id } : {})
|
|
77
180
|
* ▼ (no projectId → backend picks the default project)
|
|
78
181
|
* cache + return
|
|
79
182
|
*
|
|
80
|
-
* Concurrent callers
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* which is expected to fail closed (no header / empty `headers()`).
|
|
183
|
+
* Concurrent callers share the in-flight exchange in either mode. Never
|
|
184
|
+
* invents a token: a failure propagates to the caller, which is expected to
|
|
185
|
+
* fail closed (no header / empty `headers()`).
|
|
84
186
|
*/
|
|
85
187
|
async getProjectToken(options = {}) {
|
|
188
|
+
await this.ensureMigrated();
|
|
189
|
+
if (!this.exchange) {
|
|
190
|
+
return this.rootRuntime.ensure({ interactive: options.interactive });
|
|
191
|
+
}
|
|
86
192
|
const cached = await this.getCachedProjectToken();
|
|
87
193
|
if (isProjectTokenUsable(cached, this.tokenExpirySkewMs)) {
|
|
88
194
|
this.logger.trace("lightbridge_exchange_cache_hit", { projectId: this.projectId });
|
|
@@ -103,12 +209,12 @@ export class LightbridgeRuntime {
|
|
|
103
209
|
}
|
|
104
210
|
}
|
|
105
211
|
async performExchange(options) {
|
|
106
|
-
const human = await this.
|
|
212
|
+
const human = await this.rootRuntime.ensure({ interactive: options.interactive });
|
|
107
213
|
this.logger.info("lightbridge_exchange_started", { projectId: this.projectId ?? "(default)" });
|
|
108
214
|
try {
|
|
109
215
|
// No `projectId` → send no `project_id` param; the backend mints a token
|
|
110
216
|
// for the caller's default project (ADR-0012).
|
|
111
|
-
const exchanged = await this.
|
|
217
|
+
const exchanged = await this.exchangeRuntime.exchangeTo(this.projectKey, human.accessToken, this.projectId ? { project_id: this.projectId } : {});
|
|
112
218
|
this.logger.info("lightbridge_exchange_success", { projectId: this.projectId ?? "(default)" });
|
|
113
219
|
return exchanged;
|
|
114
220
|
} catch (error) {
|
|
@@ -119,14 +225,32 @@ export class LightbridgeRuntime {
|
|
|
119
225
|
throw error;
|
|
120
226
|
}
|
|
121
227
|
}
|
|
122
|
-
/**
|
|
228
|
+
/**
|
|
229
|
+
* Drop the cached tokens for this identity: the exchanged project token
|
|
230
|
+
* entirely (its own exclusive store), and the shared root token's `token`
|
|
231
|
+
* field only — NOT the whole shared cache file, which may also hold
|
|
232
|
+
* `@vymalo/opencode-oauth2`'s discovered models for this server id and must
|
|
233
|
+
* survive a lightbridge-side logout.
|
|
234
|
+
*/
|
|
123
235
|
async reset() {
|
|
124
|
-
await this.
|
|
236
|
+
await this.exchangeRuntime.reset();
|
|
237
|
+
const existing = await this.sharedStore.loadServerState(this.serverId);
|
|
238
|
+
if (existing?.token) {
|
|
239
|
+
await this.sharedStore.saveServerState({
|
|
240
|
+
...existing,
|
|
241
|
+
updatedAt: Date.now(),
|
|
242
|
+
token: undefined
|
|
243
|
+
});
|
|
244
|
+
}
|
|
125
245
|
}
|
|
126
246
|
}
|
|
127
|
-
/** Absolute path to the lightbridge cache directory
|
|
247
|
+
/** Absolute path to the lightbridge-exclusive (exchanged-token) cache directory. */
|
|
128
248
|
export function lightbridgeCacheDir(cacheRoot) {
|
|
129
249
|
return join(cacheRoot, DEFAULT_CACHE_NAMESPACE);
|
|
130
250
|
}
|
|
251
|
+
/** Absolute path to the SHARED root-token cache directory (ADR-0017). */
|
|
252
|
+
export function rootCacheDir(cacheRoot) {
|
|
253
|
+
return join(cacheRoot, ROOT_CACHE_SEGMENT, ROOT_CACHE_NAMESPACE);
|
|
254
|
+
}
|
|
131
255
|
|
|
132
256
|
//# sourceMappingURL=plugin.js.map
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAAA,SAAS,YAAY;AAErB,SACE,yBACA,8BACA,kBACA,oBAIK
|
|
1
|
+
{"mappings":"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","names":[],"sources":["../src/plugin.ts"],"version":3,"file":"plugin.js","sourceRoot":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vymalo/opencode-lightbridge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Umbrella OpenCode plugin for ADR-0012: one shared credential (TokenRuntime) drives both the LLM gateway bearer and OTEL export, so a developer authenticates once and every egress rides the same project-scoped token.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "vymalo contributors",
|
|
@@ -50,17 +50,23 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@opencode
|
|
53
|
+
"@opencode/plugin": "2.2.6",
|
|
54
54
|
"@opentelemetry/api": "^1.9.1",
|
|
55
|
-
"@opentelemetry/api-logs": "^0.
|
|
56
|
-
"@
|
|
57
|
-
"@vymalo/opencode-core
|
|
55
|
+
"@opentelemetry/api-logs": "^0.222.0",
|
|
56
|
+
"@opentelemetry/core": "^2.11.0",
|
|
57
|
+
"@vymalo/opencode-auth-core": "0.18.0",
|
|
58
|
+
"@vymalo/opencode-core-otel": "0.18.0",
|
|
59
|
+
"@vymalo/opencode-provider-sync": "0.18.0"
|
|
58
60
|
},
|
|
59
61
|
"devDependencies": {
|
|
60
|
-
"@opentelemetry/sdk-logs": "^0.
|
|
61
|
-
"@opentelemetry/sdk-trace": "^2.
|
|
62
|
-
"
|
|
63
|
-
"
|
|
62
|
+
"@opentelemetry/sdk-logs": "^0.222.0",
|
|
63
|
+
"@opentelemetry/sdk-trace": "^2.11.0",
|
|
64
|
+
"effect": "4.1.0",
|
|
65
|
+
"vite": "^8.3.0",
|
|
66
|
+
"vitest": "^5.0.1"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"effect": "^4.0.0"
|
|
64
70
|
},
|
|
65
71
|
"scripts": {
|
|
66
72
|
"build": "node ../../scripts/build-package.mjs",
|