@route_33/opencode 0.4.4 → 0.4.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 CHANGED
@@ -30,7 +30,7 @@ This plugin never writes your `opencode.json` or `opencode.jsonc`: opencode has
30
30
 
31
31
  Run `opencode auth login` and choose `route_33`, or set the `ROUTE33_API_KEY` environment variable. Without a key, the TUI wizard offers to save one: per-project inside a git workspace, global otherwise. A globally stored key applies only outside git workspaces — inside a workspace, keys resolve from the environment, the workspace config, or `.opencode/route33.key` (per-project keys are the metering boundary). Skipping the project-key wizard snoozes it for 7 days — "Skip" for that workspace only, "Skip for all workspaces" everywhere (both live in opencode's TUI kv store; remove `project-key-prompt.dismissed-at*` from `~/.local/state/opencode/kv.json` to re-arm sooner). `ROUTE33_BASE_URL` overrides the default gateway URL; `ROUTE33_TUI_PROMPT=0` disables the wizard.
32
32
 
33
- Your key is never written into the resolved provider configuration: authentication is attached per request at fetch time, so `opencode debug config` output contains no credential material.
33
+ Your key is never written into the resolved provider configuration: authentication is attached per request at fetch time, so `opencode debug config` output contains no credential material. One inert exception: the options carry the non-secret marker `__route33_fetch_shim_auth__` as `apiKey`, because the native per-model SDKs used for `anthropic/`, `openai/`, and `mistralai/` models (`@ai-sdk/anthropic`, `@ai-sdk/openai`, `@ai-sdk/mistral`) refuse to construct a request without one — the marker satisfies that null check, never authenticates anything (the gateway reads only the request-time `Authorization` header, which the fetch shim injects), and no vendor env var (`ANTHROPIC_API_KEY` etc.) is needed or consulted. The marker is skipped by key resolution and never overrides an `apiKey` you authored yourself; it is visible in config dumps precisely because it is not a secret.
34
34
 
35
35
  ## Model catalog
36
36
 
package/dist/index.js CHANGED
@@ -94,6 +94,9 @@ var logger = {
94
94
  // src/shared/models-dev-ttl-ms.ts
95
95
  var MODELS_DEV_TTL_MS = 864e5;
96
96
 
97
+ // src/shared/native-sdk-api-key-placeholder.ts
98
+ var NATIVE_SDK_API_KEY_PLACEHOLDER = "__route33_fetch_shim_auth__";
99
+
97
100
  // src/shared/resolve-cache-dir.ts
98
101
  import * as os2 from "os";
99
102
  import * as path3 from "path";
@@ -217,9 +220,10 @@ function usable4(value) {
217
220
  }
218
221
  function keyFromConfig(cfg) {
219
222
  const literal = usable4(cfg?.provider?.route_33?.options?.apiKey);
220
- if (literal !== void 0 && !literal.includes(UNRESOLVED_TEMPLATE_MARKER2))
221
- return literal;
222
- return void 0;
223
+ if (literal === void 0) return void 0;
224
+ if (literal.includes(UNRESOLVED_TEMPLATE_MARKER2)) return void 0;
225
+ if (literal === NATIVE_SDK_API_KEY_PLACEHOLDER) return void 0;
226
+ return literal;
223
227
  }
224
228
  function resolveKey(cfg, env = process.env, worktree) {
225
229
  return usable4(env[ENV_API_KEY]) ?? keyFromConfig(cfg) ?? readWorkspaceKey(worktree) ?? (worktree !== void 0 && isInsideGitWorktree(worktree) ? void 0 : readAuthEntry(env).key);
@@ -290,7 +294,10 @@ function buildOpenAiChatCompatFetch(fetchImpl) {
290
294
 
291
295
  // src/config/build-options.ts
292
296
  function buildOptions(baseURL, resolveKeyNow = () => void 0) {
293
- const options = { baseURL };
297
+ const options = {
298
+ baseURL,
299
+ apiKey: NATIVE_SDK_API_KEY_PLACEHOLDER
300
+ };
294
301
  options.fetch = buildLiveAuthFetch(
295
302
  resolveKeyNow,
296
303
  buildOpenAiChatCompatFetch()
@@ -623,6 +630,7 @@ function toCatalogModels(entries, env) {
623
630
  if (capabilities !== void 0) model.capabilities = capabilities;
624
631
  const variants = parseVariants(entry.variants);
625
632
  if (variants !== void 0) model.variants = variants;
633
+ if (typeof entry.hasZdrLane === "boolean") model.hasZdrLane = entry.hasZdrLane;
626
634
  const modalities = parseModalities(entry.modalities);
627
635
  if (modalities !== void 0) model.modalities = modalities;
628
636
  if (typeof entry.attachment === "boolean") model.attachment = entry.attachment;
@@ -1036,6 +1044,11 @@ var FORCED_OPTION_FIELDS = /* @__PURE__ */ new Set([
1036
1044
  "baseURL",
1037
1045
  "headers"
1038
1046
  ]);
1047
+ function isForcedValue(field, value) {
1048
+ if (field === "apiKey" && value === NATIVE_SDK_API_KEY_PLACEHOLDER)
1049
+ return false;
1050
+ return FORCED_OPTION_FIELDS.has(field);
1051
+ }
1039
1052
  function mergeProvider(target, patch) {
1040
1053
  if (target.npm === void 0) target.npm = patch.npm;
1041
1054
  if (target.name === void 0) target.name = patch.name;
@@ -1045,7 +1058,7 @@ function mergeProvider(target, patch) {
1045
1058
  const options = target.options;
1046
1059
  for (const [field, value] of Object.entries(patch.options)) {
1047
1060
  if (value === void 0) continue;
1048
- if (FORCED_OPTION_FIELDS.has(field) || options[field] === void 0)
1061
+ if (isForcedValue(field, value) || options[field] === void 0)
1049
1062
  options[field] = value;
1050
1063
  }
1051
1064
  }
package/dist/tui/index.js CHANGED
@@ -31,6 +31,9 @@ var logger = {
31
31
  }
32
32
  };
33
33
 
34
+ // src/shared/native-sdk-api-key-placeholder.ts
35
+ var NATIVE_SDK_API_KEY_PLACEHOLDER = "__route33_fetch_shim_auth__";
36
+
34
37
  // src/shared/resolve-cache-dir.ts
35
38
  import * as os from "os";
36
39
  import * as path2 from "path";
@@ -142,9 +145,10 @@ function usable3(value) {
142
145
  }
143
146
  function keyFromConfig(cfg) {
144
147
  const literal = usable3(cfg?.provider?.route_33?.options?.apiKey);
145
- if (literal !== void 0 && !literal.includes(UNRESOLVED_TEMPLATE_MARKER))
146
- return literal;
147
- return void 0;
148
+ if (literal === void 0) return void 0;
149
+ if (literal.includes(UNRESOLVED_TEMPLATE_MARKER)) return void 0;
150
+ if (literal === NATIVE_SDK_API_KEY_PLACEHOLDER) return void 0;
151
+ return literal;
148
152
  }
149
153
  function resolveKey(cfg, env = process.env, worktree) {
150
154
  return usable3(env[ENV_API_KEY]) ?? keyFromConfig(cfg) ?? readWorkspaceKey(worktree) ?? (worktree !== void 0 && isInsideGitWorktree(worktree) ? void 0 : readAuthEntry(env).key);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@route_33/opencode",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "description": "opencode provider plugin for the route33.ai AI gateway \u2014 key-scoped model discovery, cost/limit enrichment, auth, and the key-setup wizard.",