opencode-blablador 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 the opencode-blablador authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,136 @@
1
- # Temporary Holding Version
1
+ # opencode-blablador
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Blablador provider for [OpenCode](https://opencode.ai) v2. It registers the Helmholtz / JSC
4
+ Blablador gateway with the models, context ceilings, and reasoning levels the service actually
5
+ supports.
6
+
7
+ - **All chat aliases**, with a verified 21-model fallback catalog and live `/v1/models` discovery.
8
+ - **Measured context windows**: 1,048,576 / 262,144 / 131,072 tokens instead of a blanket 98k cap.
9
+ - **16,384-token output ceiling**, matching the gateway limit that otherwise causes HTTP 400s.
10
+ - **Per-family reasoning variants** that translate OpenCode's levels into each backend's
11
+ `reasoning_effort` vocabulary.
12
+ - **Env or `/connect` authentication**, with no plaintext token in the config file.
13
+ - Uses OpenCode's native `@opencode/ai/providers/openai-compatible` driver for streaming and tools.
14
+
15
+ ## Requirements
16
+
17
+ - OpenCode v2 with `@opencode/plugin` 2.1.4 or newer.
18
+ - Node.js 22 or newer.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ opencode plugin add opencode-blablador
24
+ ```
25
+
26
+ Or add it to `opencode.jsonc`:
27
+
28
+ ```jsonc
29
+ {
30
+ "plugins": ["opencode-blablador"]
31
+ }
32
+ ```
33
+
34
+ ## Authenticate
35
+
36
+ Either store a token through OpenCode:
37
+
38
+ ```text
39
+ /connect -> Blablador -> API key
40
+ ```
41
+
42
+ Or export it before starting OpenCode:
43
+
44
+ ```bash
45
+ export BLABLADOR_API_TOKEN="your-jsc-blablador-token"
46
+ ```
47
+
48
+ The provider is `auto`-activated: it appears once OpenCode can see an env or `/connect`
49
+ connection. Discovery and requests use the stored `/connect` key when one exists and the env var
50
+ otherwise; keys are trimmed, because a pasted token with surrounding whitespace is what the gateway
51
+ 401s on. On first load the plugin queries `/v1/models` with that credential. If discovery fails or
52
+ returns fewer than five chat models, the bundled catalog is used and a warning is logged. Switching
53
+ the credential with `/connect` re-runs discovery without a restart.
54
+
55
+ ## Use
56
+
57
+ Select **Blablador** in the model picker. Models that reason expose variants such as `low`,
58
+ `medium`, `high`, and `xhigh`. Picking no variant leaves the field unset, so the backend default
59
+ applies.
60
+
61
+ The output cap is 16,384 tokens, including reasoning tokens.
62
+
63
+ ## Context ceilings
64
+
65
+ These numbers are the ceilings the gateway actually enforces.
66
+
67
+ | Context | Models |
68
+ | --- | --- |
69
+ | **1,048,576** | `alias-huge`, `alias-kimi-k3-1m`, `alias-glm-5.3-flash`, `alias-deepseek-v41-flash-booster`, `alias-mimo-v2.6-flash`, `alias-mimo-v2.6-pro`, `alias-muse-spark`, `deepseek-v4.1-flash-at-hzdr` |
70
+ | **262,144** | `alias-code`, `alias-large`, `alias-qwen3.8-27b`, `alias-qwen3.8-flash-next`, `alias-qwen38-27b`, `alias-qwen38-quick`, `alias-aleph-kolibri-1`, `alias-apertus`, `alias-apertus-70b`, `alias-ocr`, `Swift-Qwen3.8-27b` |
71
+ | **131,072** | `alias-fast`, `alias-eve` |
72
+
73
+ ## Reasoning levels
74
+
75
+ Blablador backends accept different `reasoning_effort` values. Sending a value a backend does not
76
+ know returns HTTP 400, so the plugin maps OpenCode's levels per family:
77
+
78
+ | Family | Models | Backend vocabulary |
79
+ | --- | --- | --- |
80
+ | Qwen | `alias-code`, `alias-large`, `alias-qwen*`, `Swift-Qwen3.8-27b` | `none`, `low`, `medium`, `xhigh` |
81
+ | gpt-oss | `alias-fast` | `low`, `medium`, `high` |
82
+ | Kimi | `alias-kimi-k3-1m` | `none`, `low`, `high`, `max` |
83
+ | DeepSeek | `alias-deepseek-*`, `deepseek-v4.1-flash-at-hzdr` | `none`, `low`, `high`, `xhigh`, `max` |
84
+ | Muse | `alias-muse-spark` | `low`, `medium`, `high`, `xhigh` |
85
+ | Generic | unlisted aliases | `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max` |
86
+ | None | Apertus, Eve, OCR | the field is never sent |
87
+
88
+ The mapping preserves intent where definitions differ: `high` becomes `xhigh` on Qwen, while
89
+ `xhigh` and `max` clamp to `high` on gpt-oss.
90
+
91
+ If JSC adds a family with its own vocabulary, add a pattern to `FAMILY` and an entry to `EFFORT`
92
+ in blablador-core, the shared catalog this plugin depends on; until then it uses the generic map.
93
+
94
+ ## Live catalog
95
+
96
+ `GET /v1/models` carries no capability metadata and JSC says aliases come and go without notice.
97
+ At startup the plugin:
98
+
99
+ 1. Keeps `alias-*` chat models plus the two verified unaliased chat models.
100
+ 2. Drops embeddings, rerankers, image/video/voice endpoints, and other non-chat models.
101
+ 3. Fills missing roots and context windows from the bundled catalog.
102
+ 4. Replaces the fallback list only if at least five chat models remain.
103
+
104
+ Discovery runs at startup and again whenever the Blablador credential changes. The output cap
105
+ shrinks below 16,384 for any model whose live window is smaller than the gateway ceiling, so the
106
+ prompt always keeps room inside the window.
107
+
108
+ ## Limitations
109
+
110
+ - The live catalog is fetched at startup, not on every model-picker open.
111
+ - Vision support is a fixed allowlist because `/v1/models` does not report modalities.
112
+ - Blablador returns no prompt-cache accounting, so the plugin does not configure caching.
113
+ - Blablador is a shared research service; rate limits and alias availability are controlled by JSC.
114
+
115
+ ## Development
116
+
117
+ The catalog rules (fallback list, family/effort maps, live merge, token trimming) live in
118
+ blablador-core; this package is the OpenCode adapter around them. It lives in a monorepo, so install from the
119
+ repo root — the workspace links the core, no symlinks:
120
+
121
+ ```bash
122
+ npm install # at the monorepo root
123
+ npm run typecheck
124
+ npm test # builds dist/ and runs the host tests (catalog rules are tested in the core)
125
+ npm run test:live # loads dist/ in an isolated real OpenCode and checks its catalog against /v1/models,
126
+ # runs one #high completion (the effort word end-to-end) and one red-PNG image via -f;
127
+ # needs BLABLADOR_API_TOKEN and the opencode binary, skips without them
128
+ ```
129
+
130
+ To point a local OpenCode at the built plugin, `"plugins": ["./dist"]` in this repo's
131
+ `opencode.jsonc` does it — a path plugin entry must be a **directory** (a `.ts` file path is
132
+ ignored with a warning), and relative paths resolve against the config file's directory.
133
+
134
+ ## License
135
+
136
+ MIT
@@ -0,0 +1,20 @@
1
+ /**
2
+ * OpenCode adapter over blablador-core.
3
+ *
4
+ * The catalog, family/effort maps, live merge, token normalization and output cap all live in the
5
+ * shared core so pi-blablador and this plugin cannot drift. This file re-exports that surface and
6
+ * adds the only OpenCode-specific piece: turning a model's effort map into `variants`.
7
+ */
8
+ export { BASE_URL, DEFAULT_CONTEXT, EFFORT, EXTRA_CHAT, FALLBACK_MODELS, MAX_OUTPUT, MIN_CATALOG, NOT_CHAT, TOKEN_ENV, VISION, displayName, familyOf, fetchLiveModels, mergeLiveModels, outputCap, resolveToken, type CatalogModel, type EffortMap, type Level, type RemoteModel, } from "blablador-core";
9
+ import { type CatalogModel, type Level } from "blablador-core";
10
+ export interface ModelVariant {
11
+ readonly id: Level;
12
+ readonly reasoningEffort: string;
13
+ }
14
+ /**
15
+ * OpenCode variants for a model. IDs are the user-facing levels; settings carry the value the
16
+ * family's backend accepts, which the native OpenAI-compatible driver lowers to `reasoning_effort`.
17
+ * A family with no reasoning (`EFFORT[family] === null`) advertises no variants.
18
+ */
19
+ export declare function variantsFor(model: Pick<CatalogModel, "id" | "root">): ModelVariant[];
20
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,QAAQ,EACR,eAAe,EACf,MAAM,EACN,UAAU,EACV,eAAe,EACf,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,MAAM,EACN,WAAW,EACX,QAAQ,EACR,eAAe,EACf,eAAe,EACf,SAAS,EACT,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,KAAK,EACV,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAoB,KAAK,YAAY,EAAE,KAAK,KAAK,EAAkB,MAAM,gBAAgB,CAAC;AAEjG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG,YAAY,EAAE,CAOpF"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * OpenCode adapter over blablador-core.
3
+ *
4
+ * The catalog, family/effort maps, live merge, token normalization and output cap all live in the
5
+ * shared core so pi-blablador and this plugin cannot drift. This file re-exports that surface and
6
+ * adds the only OpenCode-specific piece: turning a model's effort map into `variants`.
7
+ */
8
+ export { BASE_URL, DEFAULT_CONTEXT, EFFORT, EXTRA_CHAT, FALLBACK_MODELS, MAX_OUTPUT, MIN_CATALOG, NOT_CHAT, TOKEN_ENV, VISION, displayName, familyOf, fetchLiveModels, mergeLiveModels, outputCap, resolveToken, } from "blablador-core";
9
+ import { EFFORT, familyOf } from "blablador-core";
10
+ /**
11
+ * OpenCode variants for a model. IDs are the user-facing levels; settings carry the value the
12
+ * family's backend accepts, which the native OpenAI-compatible driver lowers to `reasoning_effort`.
13
+ * A family with no reasoning (`EFFORT[family] === null`) advertises no variants.
14
+ */
15
+ export function variantsFor(model) {
16
+ const effort = EFFORT[familyOf(model.id, model.root)];
17
+ if (!effort)
18
+ return [];
19
+ return Object.entries(effort).map(([id, reasoningEffort]) => ({
20
+ id,
21
+ reasoningEffort,
22
+ }));
23
+ }
24
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,QAAQ,EACR,eAAe,EACf,MAAM,EACN,UAAU,EACV,eAAe,EACf,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,MAAM,EACN,WAAW,EACX,QAAQ,EACR,eAAe,EACf,eAAe,EACf,SAAS,EACT,YAAY,GAKb,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAiD,MAAM,gBAAgB,CAAC;AAOjG;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAwC;IAClE,MAAM,MAAM,GAAiC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACpF,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,OAAQ,MAAM,CAAC,OAAO,CAAC,MAAM,CAA4B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC;QACxF,EAAE;QACF,eAAe;KAChB,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Plugin } from "@opencode/plugin";
2
+ declare const _default: Plugin.Plugin;
3
+ export default _default;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,MAAM,EAAY,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,160 @@
1
+ import { Integration, Model, Plugin, Provider } from "@opencode/plugin";
2
+ import { BASE_URL, EFFORT, FALLBACK_MODELS, TOKEN_ENV, VISION, displayName, familyOf, fetchLiveModels, outputCap, resolveToken, variantsFor, } from "./catalog.js";
3
+ const PACKAGE = "@opencode/ai/providers/openai-compatible";
4
+ const PROVIDER_ID = Provider.ID.make("blablador");
5
+ const INTEGRATION_ID = Integration.ID.make("blablador");
6
+ const FETCH_TIMEOUT_MS = 10_000;
7
+ function modelInfo(model, all) {
8
+ const base = Model.Info.default(PROVIDER_ID, Model.ID.make(model.id));
9
+ return {
10
+ ...base,
11
+ name: displayName(model, all),
12
+ capabilities: {
13
+ ...base.capabilities,
14
+ input: VISION.has(model.id) ? ["text", "image"] : ["text"],
15
+ },
16
+ // outputCap keeps room for the prompt when a live window is smaller than the gateway ceiling.
17
+ limit: { context: model.contextWindow, output: outputCap(model.contextWindow) },
18
+ variants: variantsFor(model).map((variant) => ({
19
+ id: Model.VariantID.make(variant.id),
20
+ settings: { reasoningEffort: variant.reasoningEffort },
21
+ })),
22
+ };
23
+ }
24
+ export default Plugin.define({
25
+ id: "opencode-blablador",
26
+ async setup(ctx) {
27
+ // Auth entry points: /connect stores a key, or the integration reads the env var directly.
28
+ await ctx.integration.transform((integrations) => {
29
+ integrations.update(INTEGRATION_ID, (integration) => {
30
+ integration.name = "Blablador";
31
+ });
32
+ integrations.method.update({
33
+ integrationID: INTEGRATION_ID,
34
+ method: { type: "env", names: [TOKEN_ENV] },
35
+ });
36
+ integrations.method.update({
37
+ integrationID: INTEGRATION_ID,
38
+ method: { type: "key", label: "Blablador API token" },
39
+ });
40
+ });
41
+ // The active catalog. The provider transform reads it on every rebuild, so a refresh plus
42
+ // ctx.provider.reload() republishes models without a restart.
43
+ const catalog = {
44
+ models: FALLBACK_MODELS,
45
+ roots: new Map(FALLBACK_MODELS.map((model) => [model.id, model.root])),
46
+ };
47
+ // Discovery must use the same credential the model resolver uses for inference: the active
48
+ // connection first (a stored /connect key wins over the env var), env as the fallback.
49
+ // resolveToken trims: a pasted key with surrounding whitespace is what the gateway 401s on.
50
+ async function currentToken() {
51
+ const connection = await ctx.integration.connection
52
+ .active(INTEGRATION_ID)
53
+ .catch(() => undefined);
54
+ const credential = connection
55
+ ? await ctx.integration.connection.resolve(connection).catch(() => undefined)
56
+ : undefined;
57
+ return resolveToken(credential, process.env[TOKEN_ENV]);
58
+ }
59
+ async function discover() {
60
+ const token = await currentToken();
61
+ if (!token)
62
+ return;
63
+ try {
64
+ const models = await fetchLiveModels(token, AbortSignal.timeout(FETCH_TIMEOUT_MS));
65
+ catalog.models = models;
66
+ catalog.roots = new Map(models.map((model) => [model.id, model.root]));
67
+ }
68
+ catch (error) {
69
+ const message = error instanceof Error ? error.message : String(error);
70
+ console.warn(`blablador: keeping the ${catalog.models.length}-model catalog; ${message}`);
71
+ }
72
+ }
73
+ await discover();
74
+ await ctx.provider.transform((providers) => {
75
+ providers.add({
76
+ info: {
77
+ ...Provider.Info.empty(PROVIDER_ID),
78
+ name: "Blablador",
79
+ activation: "auto",
80
+ package: PACKAGE,
81
+ settings: { baseURL: BASE_URL },
82
+ integrationID: INTEGRATION_ID,
83
+ },
84
+ models: catalog.models.map((model) => modelInfo(model, catalog.models)),
85
+ });
86
+ });
87
+ // V2 has no chat.params. These hooks build every request shape, so mapping here covers the
88
+ // agent loop plus compaction, title generation, and synthetic requests.
89
+ const sanitize = (event) => {
90
+ const options = event.options;
91
+ const requested = options.reasoningEffort ?? options.reasoning_effort;
92
+ delete options.reasoningEffort;
93
+ delete options.reasoning_effort;
94
+ if (requested === undefined)
95
+ return;
96
+ const rule = EFFORT[familyOf(event.model.id, catalog.roots.get(event.model.id) ?? null)];
97
+ if (!rule)
98
+ return;
99
+ const mapped = typeof requested === "string" ? rule[requested] : undefined;
100
+ options.reasoningEffort = mapped ?? "low";
101
+ };
102
+ // A stored key with stray whitespace 401s every chat even when discovery is fine, because
103
+ // inference auth is OpenCode's own. Trim it on the wire: the clean-key path only reads a
104
+ // header, and the value is rewritten only when trimming actually changes it.
105
+ const trimAuth = (event) => {
106
+ const value = event.request.headers.get("authorization");
107
+ if (!value)
108
+ return;
109
+ const bearer = /^Bearer (.*)$/.exec(value);
110
+ const raw = bearer?.[1];
111
+ if (raw === undefined)
112
+ return;
113
+ const token = raw.trim();
114
+ if (token === raw)
115
+ return;
116
+ event.request.headers.set("authorization", `Bearer ${token}`);
117
+ };
118
+ const registrations = await Promise.all([
119
+ ctx.session.hook("context", sanitize, { providerID: PROVIDER_ID }),
120
+ ctx.session.hook("compaction", sanitize, { providerID: PROVIDER_ID }),
121
+ ctx.session.hook("generate", sanitize, { providerID: PROVIDER_ID }),
122
+ ctx.session.hook("title", sanitize, { providerID: PROVIDER_ID }),
123
+ ctx.session.hook("http.request", trimAuth, { providerID: PROVIDER_ID }),
124
+ ]);
125
+ // /connect or a credential switch changes the key and the reachable aliases: re-discover and
126
+ // reload instead of telling the user to restart. Switched is what `credential create` emits
127
+ // when a new key becomes active; a bad key just keeps the fallback with a warning.
128
+ const watch = new AbortController();
129
+ let refreshing = false;
130
+ void (async () => {
131
+ try {
132
+ for await (const event of ctx.event.subscribe({ signal: watch.signal })) {
133
+ if (event.type !== "credential.switched")
134
+ continue;
135
+ if (event.data.integrationID !== INTEGRATION_ID)
136
+ continue;
137
+ if (refreshing)
138
+ continue;
139
+ refreshing = true;
140
+ try {
141
+ await discover();
142
+ await ctx.provider.reload();
143
+ }
144
+ finally {
145
+ refreshing = false;
146
+ }
147
+ }
148
+ }
149
+ catch (error) {
150
+ if (!watch.signal.aborted)
151
+ console.warn("blablador: credential watch stopped", error);
152
+ }
153
+ })();
154
+ return async () => {
155
+ watch.abort();
156
+ await Promise.all(registrations.map((registration) => registration.dispose()));
157
+ };
158
+ },
159
+ });
160
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,49 @@
1
1
  {
2
2
  "name": "opencode-blablador",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Blablador (Helmholtz / JSC) provider plugin for OpenCode: measured context windows, live catalog, and reasoning effort mapping",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "opencode",
9
+ "opencode-plugin",
10
+ "blablador",
11
+ "helmholtz",
12
+ "jsc",
13
+ "openai-compatible"
14
+ ],
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "import": "./dist/index.js",
25
+ "types": "./dist/index.d.ts"
26
+ }
27
+ },
28
+ "engines": {
29
+ "node": ">=22"
30
+ },
31
+ "scripts": {
32
+ "build": "tsc -p tsconfig.json",
33
+ "typecheck": "tsc -p tsconfig.json --noEmit",
34
+ "test": "npm run build && node --test test/*.test.mjs",
35
+ "test:live": "npm run build && node test/live.mjs",
36
+ "prepublishOnly": "npm run typecheck && npm test"
37
+ },
38
+ "peerDependencies": {
39
+ "@opencode/plugin": ">=2.1.4"
40
+ },
41
+ "dependencies": {
42
+ "blablador-core": "0.1.0"
43
+ },
44
+ "devDependencies": {
45
+ "@opencode/plugin": "2.1.4",
46
+ "@types/node": "^24.12.2",
47
+ "typescript": "^7.0.2"
48
+ }
49
+ }