Skip to content

feat: a smaller public API - #108

Open
viztor wants to merge 2 commits into
claude/vigilant-mendel-bctz9n-p1bfrom
claude/vigilant-mendel-bctz9n-p2
Open

viztor wants to merge 2 commits into
claude/vigilant-mendel-bctz9n-p1bfrom
claude/vigilant-mendel-bctz9n-p2

Conversation

@viztor

@viztor viztor commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Phase P2 of docs/improvement-plan.md. It is stacked on #107 (P1b). Below that come #106 (P1a) and #105.

This is a 1.x minor (D6). Nobody consumes the removed exports, so there is no ! and no BREAKING footer.

The barrel

src/index.ts is the host's contract and nothing more:

export { inject, name } from "./identity.ts";
export { apply } from "./lifecycle.ts";
export { Config, type ModelOverrideConfig, type ModelRouteConfig, type PluginConfig, type ResolvedPluginConfig } from "./config.ts";
export { type EndpointFamily, type KeySourcePolicy } from "./config-values.ts";

test/public-api.test.ts pins this list, so widening it is a reviewed change. It opened as a green pin of the old barrel, then shrank in this PR.

  • Added: ModelRouteConfig. PluginConfig.modelRoutes already referenced it, but it could not be named from the barrel.
  • Removed (no longer re-exported):
    • Identity: LEGACY_NAME, LEGACY_PKG, OPENCODE_CLI_VERSION, OPENCODE_PATCH_USER_AGENT, OPENCODE_USER_AGENT.
    • Config: CONFIG_DEFAULTS, the ten DEFAULT_* constants, ENDPOINT_FAMILIES, KEY_SOURCE_POLICIES, resolveConfig, ALL_MODELS_MARKER, readBoolean, readString, readStringList, unwrapNode.
    • Session: fallbackSessionId, isOpenCodeMessageId, isOpenCodeSessionId, headerValueFor, newOpenCodeMessageId, openCodeSessionIdFor, OPENCODE_UA, pinnedSessionId, sessionIdForRequest and the four session header constants; also withStore and the ActiveTurnState type.
    • Request path: DUMMY_BASH_TOOL, DUMMY_READ_TOOL, isCoreToolModel, maybeInjectCoreTools, RESPONSES_PATH, hasSessionHeader, isOpenCodeRequest, patchFetch and the CordisContext type.
    • Credentials: clearCapturedApiKeys, extractApiKeyFromHeaders, getCapturedApiKey, isPlaceholderApiKey, recordCapturedApiKey, tierForRequest, discoverGoConfig, effectiveGoKeyRef, resolveGoApiKey, resolveGoBaseURL, resolveOpencodeStoreKey, resolveZenCreditInfo, toGoBaseURL.
    • Usage and cost: GoUsageService, parseGoUsage, parseUsageQuery and the GoUsage, UsageQuery and UsageWindow types; calculateTurnCost, clearSessionUsageStore, describeModel, formatModelRate, formatUsd, getSessionUsage, recordTurnUsage and the ModelCostRate and SessionUsageSnapshot types.
    • Catalog: every models-catalog constant and function, plus the CatalogModelSpec, CatalogProvider and ParsedCatalogs types.
    • Discovery: the models-discovery decorators and helpers.
    • Routes: every responses-routes constant and function, and the responses-provider helpers.
  • Deleted outright: resolveRoutedKey and the RoutedKeyDetails type (D4: exported and never called).

scripts/check.ts' consumer probe reads only apply and Config, so it still passes.

Also in this PR

  • One door for tests. All 62 test files that imported src now go through test/support/src.ts. It re-exports each name from the module that defines it. A gate in architecture.test.ts rejects a static src import anywhere else. Its exemptions are named: vi.mock targets, re-imports after vi.resetModules(), the architecture and public-API tests, the jsdom client tests, and test/support/. The source-reading gates share a comment blanker that has its own known-answer tests.
  • exports ⊆ files. ./src/* is gone from exports. check.ts now fails when an exports target is outside the published files, using the pure helpers in scripts/package-checks.ts, which are tested against fixtures.
  • internalRoutes is deleted (D2). The per-protocol routes always mount until P-R1 makes the plugin own the plane routes. A row that still carries internalRoutes validates and the key is ignored; a test feeds such a row and pins that. The bridge-disposer test now targets the "every internal route is already declared" exit.
  • @viztor/dsh-opencode is no longer published (D9). The deprecation message already on npm stays as its final word.
    • SCOPED_TARGETS lives in a side-effect-free scripts/scoped-targets.ts.
    • release.yml verifies exactly that list, and check.ts asserts the two agree.
    • P1a's wrapper-forwarder helper and its test are gone with the wrapper.
  • Docs. AGENTS.md (barrel scope, the test door), CONTRIBUTING.md, the README's "Changed in 1.x", and three prose mentions of resolveRoutedKey.

Review

Three lenses reviewed the change (correctness and host contracts, tests, repository rules), and two independent skeptics checked each finding. Over three rounds, every upheld finding was fixed: 3 medium and 18 low.

Verification

All run locally:

Node Step Result
26 pnpm run check 0 errors; 21 warnings, unchanged from the base
26 unit suite 1234 tests pass, up from 1222
26 shuffled, seeds 1 / 42 / 1234 pass
26 test:mock 51 pass
26 build and scripts/check.ts pass; this includes the new exports ⊆ files and publish-list checks
26 coverage 96.4% lines, 92.3% branches
24 shuffled (seed 7) and test:mock pass

The diff contains no local paths.


Generated by Claude Code

The barrel is the host's contract and nothing more: apply, Config,
inject, name and the config types. Everything else is internal, and
test/public-api.test.ts pins the list, so widening it is a reviewed
change. The 1.x line keeps its version scheme: nobody consumes the
removed exports (D6).

- Every test reaches src through test/support/src.ts, importing each
  name from the module that defines it; a gate rejects a static src
  import anywhere else outside its named exemptions.
- package.json no longer exports ./src/*, and check.ts fails when an
  exports target is outside the published files.
- resolveRoutedKey is deleted: it was exported and never called.
- The internalRoutes setting is deleted; the per-protocol routes always
  mount until the plugin owns the plane routes. A row that still carries
  it validates and the key is ignored.
- @viztor/dsh-opencode is no longer published. The deprecation message
  already on npm stays as its final word, and check.ts asserts that the
  release workflow verifies exactly what publish-scoped.ts publishes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD

viztor commented Oct 23, 2026

Copy link
Copy Markdown
Owner Author

catalog freshness is red, and the cause is not this PR's diff. The job compares src/catalog-data.ts with the live catalog at models.opencode.ai. Between this branch's base and this run, the vendor added one Go model:

opencode-go: 28 -> 29
  + 1: kimi-k3.1-pro
opencode  : 82 -> 82
shim is STALE — re-run with --write

This PR doesn't touch the catalog or its generator. Any branch that runs the check now fails it the same way, including the base of this stack (#105).

There is no fix yet. The shim has to be regenerated with pnpm run catalog:shim -- --write, which needs network access to models.opencode.ai. The session that built this stack can't reach that host. The generated file must not be hand-edited.

The repository's nightly run (37 4 * * *) regenerates it and opens chore: refresh the generated catalog and limits tables against main. Once that merges, I'll merge main up through this stack. I'm re-running the failed job once to confirm it reproduces identically.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants