@vymalo/opencode-lightbridge 0.17.0 → 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 +59 -19
- package/dist/config.d.ts +18 -15
- package/dist/config.js +19 -38
- package/dist/config.js.map +1 -1
- package/dist/lib.d.ts +2 -2
- package/dist/lib.js +2 -2
- 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/opencode.d.ts +33 -15
- package/dist/opencode.js +328 -273
- 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/package.json +15 -10
package/README.md
CHANGED
|
@@ -31,30 +31,36 @@ npm install @vymalo/opencode-lightbridge
|
|
|
31
31
|
```jsonc
|
|
32
32
|
// opencode.json
|
|
33
33
|
{
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
34
|
+
"plugins": [
|
|
35
|
+
{
|
|
36
|
+
"package": "@vymalo/opencode-lightbridge",
|
|
37
|
+
"options": {
|
|
38
|
+
"auth": {
|
|
39
|
+
"id": "lightbridge",
|
|
40
|
+
"issuer": "https://authz.example.com/realms/lightbridge",
|
|
41
|
+
"clientId": "opencode-cli",
|
|
42
|
+
"scopes": ["openid", "offline_access"],
|
|
43
|
+
"authFlow": "device_code"
|
|
44
|
+
},
|
|
45
|
+
"gateway": {
|
|
46
|
+
"providers": ["gateway"],
|
|
47
|
+
"exchange": false
|
|
48
|
+
},
|
|
49
|
+
"otel": {
|
|
50
|
+
"endpoint": "http://localhost:4318"
|
|
51
|
+
},
|
|
52
|
+
"register": {
|
|
53
|
+
"baseURL": "https://gateway.example.com/v1"
|
|
54
|
+
}
|
|
52
55
|
}
|
|
53
|
-
}
|
|
56
|
+
}
|
|
54
57
|
]
|
|
55
58
|
}
|
|
56
59
|
```
|
|
57
60
|
|
|
61
|
+
If you also run `@vymalo/opencode-oauth2`, list it **before** lightbridge: lightbridge detects an
|
|
62
|
+
oauth2-managed provider id from the `settings.oauth2` marker oauth2 stamps on the provider record.
|
|
63
|
+
|
|
58
64
|
- **`auth`** (required) — the one IdP login, an `AuthServerConfigInput` (same shape as
|
|
59
65
|
`opencode-oauth2`/`opencode-repo-auth`'s per-provider auth block). `auth.id` also doubles as the
|
|
60
66
|
OpenCode provider id `register` uses and the shared cache identity (see below).
|
|
@@ -106,3 +112,37 @@ for the full reasoning.
|
|
|
106
112
|
## License
|
|
107
113
|
|
|
108
114
|
MIT
|
|
115
|
+
|
|
116
|
+
## Migrating from v1
|
|
117
|
+
|
|
118
|
+
`0.18.0` targets the OpenCode **v2** plugin API; `0.17.x` was the last v1 release. See
|
|
119
|
+
[ADR-0019](https://github.com/ADORSYS-GIS/lightbridge-opencode-toolbeit/blob/main/docs/adr/0019-opencode-v2-cutover.md)
|
|
120
|
+
for why there is no dual-support build.
|
|
121
|
+
|
|
122
|
+
| v1 | v2 |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| `"plugin": [["@vymalo/opencode-lightbridge", { ... }]]` | `"plugins": [{ "package": "@vymalo/opencode-lightbridge", "options": { ... } }]` |
|
|
125
|
+
| `config.provider[<auth.id>]` registered by `register` | provider editor: `package: "aisdk:@ai-sdk/openai-compatible"`, `settings.baseURL` |
|
|
126
|
+
| `chat.headers` (gateway bearer) | `session.hook("model.request")` |
|
|
127
|
+
| OTEL observers (`event`, `chat.message`, `tool.execute.*`, …) | `event.subscribe` + `prompt` / `context` / `tool` / `permission` hooks |
|
|
128
|
+
| trace propagation via `options.fetch` | `session.hook("http.request")` |
|
|
129
|
+
| host `config.logLevel` | `options.logLevel`, else `OPENCODE_LOG_LEVEL` |
|
|
130
|
+
| oauth2 collision via `pluginConfig` / `options.oauth2` | `settings.oauth2` marker on the provider record |
|
|
131
|
+
|
|
132
|
+
The `auth`, `gateway`, `otel` and `register` option blocks are unchanged, as is every event name
|
|
133
|
+
except where listed below.
|
|
134
|
+
|
|
135
|
+
### Behaviour changes in v2
|
|
136
|
+
|
|
137
|
+
- **Gateway failures now refuse the request.** A failed token resolution used to leave the request
|
|
138
|
+
to go out bearer-less (the gateway 401'd); it now dies the hook so a stale stamped `Authorization`
|
|
139
|
+
cannot ride along (`lightbridge_gateway_no_bearer`, now `warn`).
|
|
140
|
+
- **List oauth2 before lightbridge** so the oauth2 collision marker is visible on the first pass.
|
|
141
|
+
- **`session.diff`, `todo.updated` and `command.executed` are no longer observed** (no v2 mapping):
|
|
142
|
+
the lines-of-code metric and `opencode.file_edited` event stop being produced.
|
|
143
|
+
- `experimental.compaction.autocontinue` is gone with no v2 equivalent.
|
|
144
|
+
- `./lib` drops `oauth2ManagedProviderIds` and `OpenCodeConfigLike`; `hasOAuth2Conflict` now takes
|
|
145
|
+
a provider editor.
|
|
146
|
+
|
|
147
|
+
The full list is in
|
|
148
|
+
[`docs/lightbridge.md`](https://github.com/ADORSYS-GIS/lightbridge-opencode-toolbeit/blob/main/docs/lightbridge.md#behaviour-changes-in-v2).
|
package/dist/config.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export interface LightbridgeRegisterOptions {
|
|
|
47
47
|
syncIntervalMinutes?: number;
|
|
48
48
|
/**
|
|
49
49
|
* Route inference through the OpenAI Responses API instead of Chat
|
|
50
|
-
* Completions — see `@vymalo/opencode-provider-sync`'s `
|
|
50
|
+
* Completions — see `@vymalo/opencode-provider-sync`'s `resolveProviderPackage`.
|
|
51
51
|
*/
|
|
52
52
|
responseApi?: boolean;
|
|
53
53
|
}
|
|
@@ -99,20 +99,23 @@ export declare function parseLightbridgeOptions(raw: unknown): ParsedLightbridge
|
|
|
99
99
|
* `ProviderModelSyncEngine`, not `LightbridgeRuntime`.
|
|
100
100
|
*/
|
|
101
101
|
export declare function needsProjectToken(options: ParsedLightbridgeOptions): boolean;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
/** The slice of a `ProviderEditor` the collision guard reads. */
|
|
103
|
+
export interface ProviderLookup {
|
|
104
|
+
get(id: string): {
|
|
105
|
+
readonly provider: {
|
|
106
|
+
readonly settings?: unknown;
|
|
107
|
+
};
|
|
108
|
+
} | undefined;
|
|
105
109
|
}
|
|
106
110
|
/**
|
|
107
|
-
*
|
|
108
|
-
* `
|
|
111
|
+
* Whether `providerId` is (also) managed by `@vymalo/opencode-oauth2`, judged
|
|
112
|
+
* from the provider record's `settings.oauth2` / `settings.oauth2ModelSync`
|
|
113
|
+
* block. Used by lightbridge's `register` module to skip registering or owning
|
|
114
|
+
* a provider oauth2 already claims (logged at `debug`).
|
|
115
|
+
*
|
|
116
|
+
* Order-sensitive: oauth2 stamps its marker inside its own provider transform,
|
|
117
|
+
* so oauth2 must be listed BEFORE lightbridge in `plugin` for lightbridge to
|
|
118
|
+
* see it on the first pass. A later pass (oauth2's own `provider.reload()`)
|
|
119
|
+
* still detects it and lightbridge then stands its engine down.
|
|
109
120
|
*/
|
|
110
|
-
export declare function
|
|
111
|
-
/**
|
|
112
|
-
* Whether `providerId` is (also) managed by `@vymalo/opencode-oauth2` —
|
|
113
|
-
* either via that provider's own `options.oauth2` / `options.oauth2ModelSync`
|
|
114
|
-
* block, or via the `pluginConfig.oauth2ModelSync.servers` channel. Used by
|
|
115
|
-
* lightbridge's `register` module to skip registering/owning a provider
|
|
116
|
-
* oauth2 already claims (logged at `debug` — see `opencode.ts`).
|
|
117
|
-
*/
|
|
118
|
-
export declare function hasOAuth2Conflict(config: OpenCodeConfigLike, providerId: string): boolean;
|
|
121
|
+
export declare function hasOAuth2Conflict(editor: ProviderLookup, providerId: string): boolean;
|
package/dist/config.js
CHANGED
|
@@ -124,47 +124,28 @@ export function needsProjectToken(options) {
|
|
|
124
124
|
//
|
|
125
125
|
// If a developer configures BOTH `@vymalo/opencode-oauth2` and lightbridge's
|
|
126
126
|
// `register` block against the SAME OpenCode provider id, they must not both
|
|
127
|
-
// register/own it
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
127
|
+
// register/own it. v1 read oauth2's private `pluginConfig` off the shared
|
|
128
|
+
// config object; v2 plugins cannot see each other's options, so the signal is
|
|
129
|
+
// the provider RECORD: oauth2 stamps `settings.oauth2` (a user block, or the
|
|
130
|
+
// marker `{ managed: true, source: "options.servers" }`) on every provider it
|
|
131
|
+
// manages. Kept as a lightbridge-local literal rather than a shared import:
|
|
132
|
+
// each consumer's own settings-key literals are intentionally NOT centralized
|
|
131
133
|
// (see `@vymalo/opencode-provider-sync`'s `opencode-helpers.ts` module doc).
|
|
132
|
-
const
|
|
134
|
+
const OAUTH2_SETTINGS_KEYS = ["oauth2", "oauth2ModelSync"];
|
|
133
135
|
/**
|
|
134
|
-
*
|
|
135
|
-
* `
|
|
136
|
+
* Whether `providerId` is (also) managed by `@vymalo/opencode-oauth2`, judged
|
|
137
|
+
* from the provider record's `settings.oauth2` / `settings.oauth2ModelSync`
|
|
138
|
+
* block. Used by lightbridge's `register` module to skip registering or owning
|
|
139
|
+
* a provider oauth2 already claims (logged at `debug`).
|
|
140
|
+
*
|
|
141
|
+
* Order-sensitive: oauth2 stamps its marker inside its own provider transform,
|
|
142
|
+
* so oauth2 must be listed BEFORE lightbridge in `plugin` for lightbridge to
|
|
143
|
+
* see it on the first pass. A later pass (oauth2's own `provider.reload()`)
|
|
144
|
+
* still detects it and lightbridge then stands its engine down.
|
|
136
145
|
*/
|
|
137
|
-
export function
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
const oauth2ModelSync = isRecord(pluginConfig?.oauth2ModelSync) ? pluginConfig?.oauth2ModelSync : undefined;
|
|
141
|
-
const servers = oauth2ModelSync?.servers;
|
|
142
|
-
if (Array.isArray(servers)) {
|
|
143
|
-
for (const raw of servers) {
|
|
144
|
-
const entry = isRecord(raw) ? raw : undefined;
|
|
145
|
-
const id = typeof entry?.id === "string" ? entry.id : undefined;
|
|
146
|
-
if (id) {
|
|
147
|
-
ids.add(id);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return ids;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Whether `providerId` is (also) managed by `@vymalo/opencode-oauth2` —
|
|
155
|
-
* either via that provider's own `options.oauth2` / `options.oauth2ModelSync`
|
|
156
|
-
* block, or via the `pluginConfig.oauth2ModelSync.servers` channel. Used by
|
|
157
|
-
* lightbridge's `register` module to skip registering/owning a provider
|
|
158
|
-
* oauth2 already claims (logged at `debug` — see `opencode.ts`).
|
|
159
|
-
*/
|
|
160
|
-
export function hasOAuth2Conflict(config, providerId) {
|
|
161
|
-
const providers = isRecord(config.provider) ? config.provider : undefined;
|
|
162
|
-
const providerEntry = providers ? providers[providerId] : undefined;
|
|
163
|
-
const providerOptions = isRecord(providerEntry) && isRecord(providerEntry.options) ? providerEntry.options : undefined;
|
|
164
|
-
if (providerOptions && OAUTH2_OPTION_KEYS.some((key) => isRecord(providerOptions[key]))) {
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
return oauth2ManagedProviderIds(config).has(providerId);
|
|
146
|
+
export function hasOAuth2Conflict(editor, providerId) {
|
|
147
|
+
const settings = editor.get(providerId)?.provider.settings;
|
|
148
|
+
return isRecord(settings) && OAUTH2_SETTINGS_KEYS.some((key) => isRecord(settings[key]));
|
|
168
149
|
}
|
|
169
150
|
|
|
170
151
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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
|
|
1
|
+
{"mappings":"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","names":[],"sources":["../src/config.ts"],"version":3,"file":"config.js","sourceRoot":""}
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createLightbridgePlugin, LightbridgePlugin, type LightbridgePluginFactoryOptions } from "./opencode.js";
|
|
1
|
+
export { createLightbridgePlugin, LightbridgePlugin, PLUGIN_ID, type LightbridgePluginFactoryOptions, type LightbridgeRegisterHandle } from "./opencode.js";
|
|
2
2
|
export { LightbridgeRuntime, LIGHTBRIDGE_IDENTITY, DEFAULT_CACHE_NAMESPACE, DEFAULT_PROJECT_KEY, ROOT_CACHE_NAMESPACE, ROOT_CACHE_SEGMENT, lightbridgeCacheDir, rootCacheDir, type LightbridgeRuntimeFactory, type LightbridgeRuntimeLike, type LightbridgeRuntimeOptions } from "./plugin.js";
|
|
3
|
-
export { hasOAuth2Conflict, needsProjectToken,
|
|
3
|
+
export { hasOAuth2Conflict, needsProjectToken, parseLightbridgeOptions, type LightbridgeGatewayOptions, type LightbridgeOptions, type LightbridgeRegisterOptions, type ParsedLightbridgeOptions, type ProviderLookup } from "./config.js";
|
|
4
4
|
export { migrateRootTokenIfNeeded } from "./migration.js";
|
package/dist/lib.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { createLightbridgePlugin, LightbridgePlugin } from "./opencode.js";
|
|
1
|
+
export { createLightbridgePlugin, LightbridgePlugin, PLUGIN_ID } from "./opencode.js";
|
|
2
2
|
export { LightbridgeRuntime, LIGHTBRIDGE_IDENTITY, DEFAULT_CACHE_NAMESPACE, DEFAULT_PROJECT_KEY, ROOT_CACHE_NAMESPACE, ROOT_CACHE_SEGMENT, lightbridgeCacheDir, rootCacheDir } from "./plugin.js";
|
|
3
|
-
export { hasOAuth2Conflict, needsProjectToken,
|
|
3
|
+
export { hasOAuth2Conflict, needsProjectToken, parseLightbridgeOptions } from "./config.js";
|
|
4
4
|
export { migrateRootTokenIfNeeded } from "./migration.js";
|
|
5
5
|
|
|
6
6
|
//# sourceMappingURL=lib.js.map
|
package/dist/lib.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAAA,SACE,yBACA,
|
|
1
|
+
{"mappings":"AAAA,SACE,yBACA,mBACA,iBAGK;AAEP,SACE,oBACA,sBACA,yBACA,qBACA,sBACA,oBACA,qBACA,oBAIK;AAEP,SACE,mBACA,mBACA,+BAMK;AAEP,SAAS,gCAAgC","names":[],"sources":["../src/lib.ts"],"version":3,"file":"lib.js","sourceRoot":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createJsonConsoleLogger, LOG_LEVEL_PRIORITY, type LogFields, type Logger, type LogLevel } from "@vymalo/opencode-auth-core/lib";
|
|
2
|
+
import { type Context as EffectContext, Effect } from "effect";
|
|
3
|
+
import { DEFAULT_LOG_LEVEL } from "@vymalo/opencode-auth-core/lib";
|
|
4
|
+
export { createJsonConsoleLogger, DEFAULT_LOG_LEVEL, LOG_LEVEL_PRIORITY };
|
|
5
|
+
export type { LogFields, Logger, LogLevel };
|
|
6
|
+
/**
|
|
7
|
+
* Capture the host's Effect context from inside the plugin's own fiber. The
|
|
8
|
+
* returned value is what {@link createEffectLogger} (and {@link runInHost})
|
|
9
|
+
* needs to put a record on the host's logger rather than on a default one.
|
|
10
|
+
*
|
|
11
|
+
* OpenCode installs its file logger as a `Logger.layer(...)` on the runtime
|
|
12
|
+
* that runs plugin setup, and Effect carries loggers as fiber-level references
|
|
13
|
+
* — so the context captured here is the only route to that sink. A bare
|
|
14
|
+
* `Effect.runFork` would log to Effect's default logger (the terminal) instead,
|
|
15
|
+
* which is exactly what ADR-0014 forbids.
|
|
16
|
+
*/
|
|
17
|
+
export declare const captureHostContext: Effect.Effect<EffectContext.Context<never>>;
|
|
18
|
+
/**
|
|
19
|
+
* Structured logger that writes through the host's Effect logger — the v2
|
|
20
|
+
* replacement for v1's `client.app.log`.
|
|
21
|
+
*
|
|
22
|
+
* ADR-0014 (no plugin writes to the user's TUI) is preserved: OpenCode's own
|
|
23
|
+
* logger is a `Logger.toFile` sink over the shared `opencode-<channel>.log`,
|
|
24
|
+
* so records land in the host log stream and never on the terminal. The event
|
|
25
|
+
* name becomes the log message and `fields` become log annotations.
|
|
26
|
+
*
|
|
27
|
+
* Host-side severity filtering is Effect's job (`OPENCODE_LOG_LEVEL`); the
|
|
28
|
+
* `getMinLevel` gate here is only this plugin's own `logLevel` option, applied
|
|
29
|
+
* before the record is built so a filtered-out call costs nothing.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createEffectLogger(context: EffectContext.Context<never>, getMinLevel: () => LogLevel): Logger;
|
|
32
|
+
/**
|
|
33
|
+
* Run an Effect from a detached callback (a timer, a promise continuation)
|
|
34
|
+
* inside the captured host context, so anything it logs reaches the host
|
|
35
|
+
* logger instead of Effect's default one (ADR-0014).
|
|
36
|
+
*/
|
|
37
|
+
export declare function runInHost(context: EffectContext.Context<never>, effect: Effect.Effect<void>): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve this plugin's log level from its own `logLevel` option, falling back
|
|
40
|
+
* to the host's `OPENCODE_LOG_LEVEL` env var. v2 gives plugins no `config`
|
|
41
|
+
* object, so the v1 `config.logLevel` channel is gone. Replaces v1's
|
|
42
|
+
* `fromOpenCodeLogLevel`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveLogLevel(value: unknown): LogLevel | undefined;
|
package/dist/logging.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createJsonConsoleLogger, LOG_LEVEL_PRIORITY } from "@vymalo/opencode-auth-core/lib";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import { DEFAULT_LOG_LEVEL } from "@vymalo/opencode-auth-core/lib";
|
|
4
|
+
export { createJsonConsoleLogger, DEFAULT_LOG_LEVEL, LOG_LEVEL_PRIORITY };
|
|
5
|
+
function redactFields(fields) {
|
|
6
|
+
if (!fields) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const redacted = {};
|
|
10
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
11
|
+
if (/token|secret|password|authorization/i.test(key)) {
|
|
12
|
+
redacted[key] = "[redacted]";
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
redacted[key] = value;
|
|
16
|
+
}
|
|
17
|
+
return redacted;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Capture the host's Effect context from inside the plugin's own fiber. The
|
|
21
|
+
* returned value is what {@link createEffectLogger} (and {@link runInHost})
|
|
22
|
+
* needs to put a record on the host's logger rather than on a default one.
|
|
23
|
+
*
|
|
24
|
+
* OpenCode installs its file logger as a `Logger.layer(...)` on the runtime
|
|
25
|
+
* that runs plugin setup, and Effect carries loggers as fiber-level references
|
|
26
|
+
* — so the context captured here is the only route to that sink. A bare
|
|
27
|
+
* `Effect.runFork` would log to Effect's default logger (the terminal) instead,
|
|
28
|
+
* which is exactly what ADR-0014 forbids.
|
|
29
|
+
*/
|
|
30
|
+
export const captureHostContext = Effect.withFiber((fiber) => Effect.succeed(fiber.context));
|
|
31
|
+
/**
|
|
32
|
+
* Structured logger that writes through the host's Effect logger — the v2
|
|
33
|
+
* replacement for v1's `client.app.log`.
|
|
34
|
+
*
|
|
35
|
+
* ADR-0014 (no plugin writes to the user's TUI) is preserved: OpenCode's own
|
|
36
|
+
* logger is a `Logger.toFile` sink over the shared `opencode-<channel>.log`,
|
|
37
|
+
* so records land in the host log stream and never on the terminal. The event
|
|
38
|
+
* name becomes the log message and `fields` become log annotations.
|
|
39
|
+
*
|
|
40
|
+
* Host-side severity filtering is Effect's job (`OPENCODE_LOG_LEVEL`); the
|
|
41
|
+
* `getMinLevel` gate here is only this plugin's own `logLevel` option, applied
|
|
42
|
+
* before the record is built so a filtered-out call costs nothing.
|
|
43
|
+
*/
|
|
44
|
+
export function createEffectLogger(context, getMinLevel) {
|
|
45
|
+
// `VYMALO_PLUGIN_CONSOLE_LOG=1` mirrors to stdout for local debugging. Off by
|
|
46
|
+
// default precisely because stdout is the user's terminal (ADR-0014).
|
|
47
|
+
const consoleAll = /^(1|true|yes|on)$/i.test(process.env.VYMALO_PLUGIN_CONSOLE_LOG ?? "");
|
|
48
|
+
const fallback = createJsonConsoleLogger("trace");
|
|
49
|
+
const write = (level, event, fields) => {
|
|
50
|
+
if (LOG_LEVEL_PRIORITY[level] < LOG_LEVEL_PRIORITY[getMinLevel()]) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (consoleAll) {
|
|
54
|
+
fallback[level](event, fields);
|
|
55
|
+
}
|
|
56
|
+
const redacted = redactFields(fields);
|
|
57
|
+
// Effect has no `trace` severity below `debug`; fold the most-verbose tier
|
|
58
|
+
// onto debug, as the v1 adapter did for the host log API (ADR-0008).
|
|
59
|
+
const record = level === "trace" || level === "debug" ? Effect.logDebug(event) : level === "info" ? Effect.logInfo(event) : level === "warn" ? Effect.logWarning(event) : Effect.logError(event);
|
|
60
|
+
const annotated = redacted ? Effect.annotateLogs(record, redacted) : record;
|
|
61
|
+
Effect.runFork(Effect.provideContext(annotated, context));
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
trace: (event, fields) => write("trace", event, fields),
|
|
65
|
+
debug: (event, fields) => write("debug", event, fields),
|
|
66
|
+
info: (event, fields) => write("info", event, fields),
|
|
67
|
+
warn: (event, fields) => write("warn", event, fields),
|
|
68
|
+
error: (event, fields) => write("error", event, fields)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run an Effect from a detached callback (a timer, a promise continuation)
|
|
73
|
+
* inside the captured host context, so anything it logs reaches the host
|
|
74
|
+
* logger instead of Effect's default one (ADR-0014).
|
|
75
|
+
*/
|
|
76
|
+
export function runInHost(context, effect) {
|
|
77
|
+
return Effect.runPromise(Effect.provideContext(effect, context));
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Resolve this plugin's log level from its own `logLevel` option, falling back
|
|
81
|
+
* to the host's `OPENCODE_LOG_LEVEL` env var. v2 gives plugins no `config`
|
|
82
|
+
* object, so the v1 `config.logLevel` channel is gone. Replaces v1's
|
|
83
|
+
* `fromOpenCodeLogLevel`.
|
|
84
|
+
*/
|
|
85
|
+
export function resolveLogLevel(value) {
|
|
86
|
+
if (typeof value !== "string") {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
switch (value.toUpperCase()) {
|
|
90
|
+
// DEBUG unlocks the most-verbose `trace` tier (host has no finer level).
|
|
91
|
+
case "DEBUG":
|
|
92
|
+
case "TRACE": return "trace";
|
|
93
|
+
case "INFO": return "info";
|
|
94
|
+
case "WARN": return "warn";
|
|
95
|
+
case "ERROR": return "error";
|
|
96
|
+
default: return undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
//# sourceMappingURL=logging.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"mappings":"AAAA,SACE,yBACA,0BAIK;AACP,SAAwC,cAAc;AAEtD,SAAS,yBAAyB;AAElC,SAAS,yBAAyB,mBAAmB;AAGrD,SAAS,aAAa,QAA2C;CAC/D,IAAI,CAAC,QAAQ;EACX,OAAO;CACT;CACA,MAAM,WAAsB,CAAC;CAC7B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAAG;EACjD,IAAI,uCAAuC,KAAK,GAAG,GAAG;GACpD,SAAS,OAAO;GAChB;EACF;EACA,SAAS,OAAO;CAClB;CACA,OAAO;AACT;;;;;;;;;;;;AAaA,OAAO,MAAM,qBAAkE,OAAO,WACnF,UAAU,OAAO,QAAQ,MAAM,OAAO,CACzC;;;;;;;;;;;;;;AAeA,OAAO,SAAS,mBACd,SACA,aACQ;;;CAGR,MAAM,aAAa,qBAAqB,KAAK,QAAQ,IAAI,6BAA6B,EAAE;CACxF,MAAM,WAAW,wBAAwB,OAAO;CAEhD,MAAM,SAAS,OAAiB,OAAe,WAA6B;EAC1E,IAAI,mBAAmB,SAAS,mBAAmB,YAAY,IAAI;GACjE;EACF;EACA,IAAI,YAAY;GACd,SAAS,MAAM,CAAC,OAAO,MAAM;EAC/B;EAEA,MAAM,WAAW,aAAa,MAAM;;;EAGpC,MAAM,SACJ,UAAU,WAAW,UAAU,UAC3B,OAAO,SAAS,KAAK,IACrB,UAAU,SACR,OAAO,QAAQ,KAAK,IACpB,UAAU,SACR,OAAO,WAAW,KAAK,IACvB,OAAO,SAAS,KAAK;EAE/B,MAAM,YAAY,WAAW,OAAO,aAAa,QAAQ,QAAQ,IAAI;EACrE,OAAO,QAAQ,OAAO,eAAe,WAAW,OAAO,CAAC;CAC1D;CAEA,OAAO;EACL,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;EACtD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,OAAO,OAAO,WAAW,MAAM,QAAQ,OAAO,MAAM;EACpD,QAAQ,OAAO,WAAW,MAAM,SAAS,OAAO,MAAM;CACxD;AACF;;;;;;AAOA,OAAO,SAAS,UACd,SACA,QACe;CACf,OAAO,OAAO,WAAW,OAAO,eAAe,QAAQ,OAAO,CAAC;AACjE;;;;;;;AAQA,OAAO,SAAS,gBAAgB,OAAsC;CACpE,IAAI,OAAO,UAAU,UAAU;EAC7B,OAAO;CACT;CACA,QAAQ,MAAM,YAAY,GAA1B;;EAEE,KAAK;EACL,KAAK,SACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,KAAK,SACH,OAAO;EACT,SACE,OAAO;CACX;AACF","names":[],"sources":["../src/logging.ts"],"version":3,"file":"logging.js","sourceRoot":""}
|
package/dist/opencode.d.ts
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { type Logger } from "@vymalo/opencode-auth-core/lib";
|
|
1
|
+
import { Plugin } from "@opencode/plugin/effect";
|
|
3
2
|
import { type EnvSource, type ExporterFactories } from "@vymalo/opencode-core-otel";
|
|
3
|
+
import { ProviderModelSyncEngine } from "@vymalo/opencode-provider-sync/lib";
|
|
4
|
+
import { type Logger } from "./logging.js";
|
|
4
5
|
import { type LightbridgeRuntimeFactory } from "./plugin.js";
|
|
5
|
-
|
|
6
|
+
/** Stable plugin id. v2 requires one and keys storage/registrations by it. */
|
|
7
|
+
export declare const PLUGIN_ID = "vymalo.lightbridge";
|
|
8
|
+
/** Test/embedder handle onto the `register` module's background engine. */
|
|
9
|
+
export interface LightbridgeRegisterHandle {
|
|
10
|
+
/** Resolves once every queued engine build + warmup (and its reload) has finished. */
|
|
11
|
+
settled(): Promise<void>;
|
|
12
|
+
/** The current engine, or `undefined` before it is ready / after a collision stand-down. */
|
|
13
|
+
engine(): ProviderModelSyncEngine | undefined;
|
|
14
|
+
}
|
|
6
15
|
export interface LightbridgePluginFactoryOptions {
|
|
16
|
+
/** Override the logger (tests). Defaults to the host's Effect logger. */
|
|
7
17
|
logger?: Logger;
|
|
8
18
|
/** Shared-runtime HTTP client (auth-core `TokenRuntime`). Tests only. */
|
|
9
19
|
fetchImpl?: typeof fetch;
|
|
@@ -17,13 +27,15 @@ export interface LightbridgePluginFactoryOptions {
|
|
|
17
27
|
* neither module ever touches the network.
|
|
18
28
|
*/
|
|
19
29
|
runtimeFactory?: LightbridgeRuntimeFactory;
|
|
30
|
+
/** Observe the `register` module's background engine (tests). */
|
|
31
|
+
onRegister?: (handle: LightbridgeRegisterHandle) => void;
|
|
20
32
|
/** Injected environment; defaults to `process.env`. */
|
|
21
33
|
env?: EnvSource;
|
|
22
34
|
/** Substitute exporters (tests use in-memory ones). */
|
|
23
35
|
exporters?: ExporterFactories;
|
|
24
36
|
/** Injectable clock; defaults to `Date.now`. */
|
|
25
37
|
now?: () => number;
|
|
26
|
-
/** Skip `beforeExit`/`SIGINT`/`SIGTERM`
|
|
38
|
+
/** Skip the `beforeExit`/`SIGINT`/`SIGTERM` exit handlers (tests). See ADR-0018. */
|
|
27
39
|
registerProcessHandlers?: boolean;
|
|
28
40
|
/** Override the resolved host metadata (hostname, version) for tests. */
|
|
29
41
|
hostInfo?: {
|
|
@@ -34,16 +46,22 @@ export interface LightbridgePluginFactoryOptions {
|
|
|
34
46
|
deferredTimeoutMs?: number;
|
|
35
47
|
}
|
|
36
48
|
/**
|
|
37
|
-
* Create the `@vymalo/opencode-lightbridge` umbrella plugin (ADR-0012
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* `
|
|
44
|
-
*
|
|
49
|
+
* Create the `@vymalo/opencode-lightbridge` umbrella plugin (ADR-0012,
|
|
50
|
+
* ADR-0017) for the OpenCode v2 plugin API (ADR-0019): ONE shared
|
|
51
|
+
* `TokenRuntime`, built once from `auth`, drives both the gateway bearer
|
|
52
|
+
* (`gateway`) and the OTEL export credential (`otel`) — each module activates
|
|
53
|
+
* independently, and an `auth`-only config is a valid, inert plugin.
|
|
54
|
+
*
|
|
55
|
+
* - `register`: `provider.transform` registers the provider and merges the
|
|
56
|
+
* discovered models and cached bearer; a queued background build runs the
|
|
57
|
+
* `ProviderModelSyncEngine` and calls `provider.reload()` (the transform is
|
|
58
|
+
* synchronous and cheap by contract — same shape as oauth2).
|
|
59
|
+
* - `gateway`: `session.hook("model.request")` injects the shared bearer and
|
|
60
|
+
* fails closed by dying the request when no bearer can be produced.
|
|
61
|
+
* - `otel`: `event.subscribe` + `prompt`/`context`/`tool`/`permission` hooks
|
|
62
|
+
* feed the recorder through `otel-adapter.ts`; `http.request` carries W3C
|
|
63
|
+
* trace context.
|
|
45
64
|
*/
|
|
46
|
-
export declare function createLightbridgePlugin(factoryOptions?: LightbridgePluginFactoryOptions): Plugin;
|
|
47
|
-
export declare const LightbridgePlugin: Plugin;
|
|
65
|
+
export declare function createLightbridgePlugin(factoryOptions?: LightbridgePluginFactoryOptions): Plugin.Plugin;
|
|
66
|
+
export declare const LightbridgePlugin: Plugin.Plugin;
|
|
48
67
|
export default LightbridgePlugin;
|
|
49
|
-
export type { OpenCodeConfig };
|