feat(logger): add structured JSON logger with redaction; fill silent catches
Add a minimal structured logger (src/logger.ts) and replace 19 catch blocks
across 9 source files that previously swallowed errors silently (with
comments only) with scoped logger.debug() calls. This makes the silently-
swallowed errors observable under OPENCODE_ANTHROPIC_DEBUG=1 without
changing any runtime behavior — each catch keeps its original "don't
crash" intent.
The logger:
- JSON output: { level, scope, message, timestamp, ...fields }.
- Levels: debug, info, warn, error. debug + info are gated on
OPENCODE_ANTHROPIC_DEBUG (already documented in AGENTS.md); warn +
error always emit to stderr.
- Auto-redacts bearer tokens (/sk-ant-oat01-[A-Za-z0-9_-]{10,}/) from
any string, including nested fields and Error.stack.
- Redacts common credential keys (access, access_token, refresh,
refreshToken, token, bearer, authorization) when they appear as
object keys.
Catches filled (file:line → scope):
- src/oauth.ts:111,256 → "oauth"
- src/storage.ts:113,421,434 → "storage"
- src/backoff.ts:96 → "backoff"
- src/token-refresh.ts:324,340 → "token-refresh"
- src/request-orchestration-helpers.ts:228,395,809 → "request-orchestration"
- src/accounts.ts:561 → "accounts"
- src/env.ts:65,77,142 → "env"
- src/refresh-lock.ts:71 → "refresh-lock"
- src/response/streaming.ts:203,476,483 → "response/streaming"
- src/response/mcp.ts:19 → "response/mcp"
Tests added:
- tests/unit/logger.test.ts (12 tests): redaction for strings, objects,
nested structures, Error instances, primitives; isDebugEnabled with
truthy/falsy values; emit gating at debug level; stderr vs stdout
routing by level; field-level credential masking.
- tests/unit/no-empty-catches.test.ts (1 test): regression guard that
walks src/**/*.ts and asserts zero matches for the empty-catch regex.
Prevents future silent swallows from landing.
Verification:
- 80 test files / 1369 tests pass + 5 skipped (up from 78/1356).
- lint clean (fixed pre-existing unnecessary escape in the bearer regex
and added eslint-disable directives for the intentional console
statements inside the logger emit path).
- typecheck clean.
Preserves original behavior: every filled catch keeps its "continue,
don't throw" intent. The logger calls only activate when
OPENCODE_ANTHROPIC_DEBUG=1; production users see zero new output
unless they opt in. V
Vacbo committed
316ff6e93888f4f3a240817b7b7d86441576e158
Parent: 4f77f30