Skip to content

refactor(byethrow): update result handling for 0.11 - #1041

Merged
ryoppippi merged 3 commits into
mainfrom
codex/update-byethrow-0-11
May 17, 2026
Merged

refactor(byethrow): update result handling for 0.11#1041
ryoppippi merged 3 commits into
mainfrom
codex/update-byethrow-0-11

Conversation

@ryoppippi

@ryoppippi ryoppippi commented May 17, 2026

Copy link
Copy Markdown
Member

Summary

  • update @praha/byethrow and @praha/byethrow-docs to 0.11.2
  • migrate Result.try call sites to the 0.11 direct-return API
  • use Result.fn, Result.parse, and Result.pipe for recoverable parsing, validation, and progress/error handling
  • switch touched ESLint presets to app mode so byethrow return types can be inferred

Testing

  • pnpm run format
  • pnpm typecheck
  • pnpm run test

Summary by CodeRabbit

Release Notes

  • Chores
    • Updated internal error-handling patterns across the application for improved code consistency and maintainability.
    • Upgraded dependency versions to latest stable releases.

Review Change Stack

Upgrade @praha/byethrow and @praha/byethrow-docs to 0.11.2 so the runtime package and local LLM docs stay aligned.

The new byethrow API returns Result values directly from Result.try and provides Result.fn/Result.parse helpers. Update existing call sites to the direct Result.try shape, wrap reusable JSON parsing with Result.fn, and use Result.parse where Valibot validation was only branching on success.

Switch the touched app/internal ESLint presets to app mode so these Result-returning helpers can rely on inference instead of spelling out byethrow return types.
@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5b11454d-1bb5-4612-8650-9f41fa1b6796

📥 Commits

Reviewing files that changed from the base of the PR and between 2533c23 and 6a3f414.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (26)
  • apps/ccusage/eslint.config.js
  • apps/ccusage/scripts/generate-json-schema.ts
  • apps/ccusage/src/adapter/amp/parser.ts
  • apps/ccusage/src/adapter/amp/pricing-macro.ts
  • apps/ccusage/src/adapter/codex/parser.ts
  • apps/ccusage/src/adapter/codex/pricing-macro.ts
  • apps/ccusage/src/adapter/codex/pricing.ts
  • apps/ccusage/src/adapter/index.ts
  • apps/ccusage/src/adapter/opencode/loader.ts
  • apps/ccusage/src/adapter/opencode/paths.ts
  • apps/ccusage/src/adapter/pi/parser.ts
  • apps/ccusage/src/adapter/shared.ts
  • apps/ccusage/src/commands/agent.ts
  • apps/ccusage/src/commands/all.ts
  • apps/ccusage/src/commands/codex.ts
  • apps/ccusage/src/commands/daily.ts
  • apps/ccusage/src/commands/monthly.ts
  • apps/ccusage/src/commands/session.ts
  • apps/ccusage/src/commands/statusline.ts
  • apps/ccusage/src/commands/weekly.ts
  • apps/ccusage/src/config-loader-tokens.ts
  • apps/ccusage/src/debug.ts
  • apps/ccusage/src/utils.ts
  • packages/internal/eslint.config.js
  • packages/internal/src/pricing.ts
  • pnpm-workspace.yaml

📝 Walkthrough

Walkthrough

This PR upgrades @praha/byethrow from ^0.6.3 to ^0.11.2 and refactors the codebase to use the new API patterns. Changes include wrapping promises in async functions within Result.try, introducing reusable JSON parsing helpers across adapters, unifying command error handling from try/catch/finally to Result.pipe pipelines, and removing explicit return type annotations from the pricing fetcher in favor of type inference.

Changes

Dependency upgrade and @praha/byethrow API adaptation

Layer / File(s) Summary
Dependency upgrade and ESLint preset changes
pnpm-workspace.yaml, apps/ccusage/eslint.config.js, packages/internal/eslint.config.js
@praha/byethrow and @praha/byethrow-docs are bumped to ^0.11.2; ESLint flat config type is changed from 'lib' to 'app' in both app and internal packages.
Adapter JSON parsing helpers and Result.try pattern standardization
apps/ccusage/src/adapter/*/parser.ts, apps/ccusage/src/adapter/*/pricing-macro.ts, apps/ccusage/src/adapter/*/loader.ts, apps/ccusage/src/adapter/shared.ts, apps/ccusage/src/adapter/index.ts, apps/ccusage/src/utils.ts
Introduces reusable parseJson and parseJsonLine helpers via Result.fn across adapter parsers; refactors file I/O and fetches to wrap promises in async arrow functions within Result.try; updates safeTimeZone to use Result.pipe for timezone validation and caching; adds Result import to shared.ts.
OpenCode path resolution and Result.try invocation refactoring
apps/ccusage/src/adapter/opencode/paths.ts
Removes immediately-invoked function wrappers from Result.try calls and replaces manual try/catch in hasOpenCodeDatabase with Result.pipe chains to detect database file existence.
Config loading, schema generation, and debug utilities Result.try updates
apps/ccusage/src/config-loader-tokens.ts, apps/ccusage/scripts/generate-json-schema.ts, apps/ccusage/src/debug.ts
Adjusts Result.try invocation forms in config and schema-generation files by removing extra call syntax; refactors file operation wrappers in generate-json-schema.ts; simplifies JSON parse result handling in debug.ts.
Commands refactored to unified Result.pipe error handling
apps/ccusage/src/commands/agent.ts, apps/ccusage/src/commands/all.ts, apps/ccusage/src/commands/codex.ts, apps/ccusage/src/commands/daily.ts, apps/ccusage/src/commands/monthly.ts, apps/ccusage/src/commands/session.ts, apps/ccusage/src/commands/weekly.ts, apps/ccusage/src/commands/statusline.ts
Systematically replaces try/catch/finally blocks with Result.pipe(Result.try(...)) pipelines across all command files; centralizes error logging via Result.inspectError; unifies progress indicator and logger.level restoration on both success and failure paths; ensures consistent process.exitCode setting and early returns on load failures.
Pricing fetcher type annotations and control flow updates
packages/internal/src/pricing.ts
Removes explicit Result.ResultAsync return type annotations from public methods (fetchModelPricing, getModelPricing, getModelContextLimit, calculateCostFromTokens) in favor of type inference; refactors offline pricing loader to use Result.fn; updates handleFallbackToCachedPricing to async function returning Result.pipe chain; adjusts loadPricing JSON parsing to use async arrow function in Result.try.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ryoppippi/ccusage#1002: Both PRs modify apps/ccusage/src/commands/all.ts to refactor runAllReport's error-handling and progress-restoration flow around loading usage rows.
  • ryoppippi/ccusage#566: Both PRs adjust Result.try usage patterns in apps/ccusage/src/commands/statusline.ts for consistent error-handling flows.
  • ryoppippi/ccusage#238: Both PRs refactor the pricing fetcher's Result-based error handling and fallback logic around fetchModelPricing, getModelPricing, and calculateCostFromTokens.

Poem

🐰 A hop, a skip through @praha/byethrow's new way,
From promises direct to async functions at play—
Helpers parse JSON with Result.fn flair,
Commands now pipe their errors with care,
Type inference blooms where annotations once lay. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective of the PR: upgrading @praha/byethrow to version 0.11 and refactoring Result handling throughout the codebase to use the new API.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/update-byethrow-0-11

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/ccusage/src/adapter/amp/parser.ts

[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: npm i baseline-browser-mapping@latest -D
tsconfig.json is not found. we cannot use type-aware rules.

Oops! Something went wrong! :(

ESLint: 9.35.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'eslint-plugin-format' imported from /node_modules/.pnpm/@antfu+eslint-config@4.19.0_@vue[email protected][email protected][email protected]_vit_670a2c5c75d4275eabd7bc195a173ee6/node_modules/@antfu/eslint-config/dist/index.js
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:301:9)
at packageResolve (node:internal/modules/esm/resolve:764:81)
at moduleResolve (node:internal/modules/esm/resolve:855:18)
at defaultResolve (node:internal/modules/esm/resolve:988:11)
at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:746:52)
at #resolve (node:internal/modules/esm/loader:679:17)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
at node:internal/modules/esm/loader:628:32

apps/ccusage/eslint.config.js

[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: npm i baseline-browser-mapping@latest -D
tsconfig.json is not found. we cannot use type-aware rules.

Oops! Something went wrong! :(

ESLint: 9.35.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'eslint-plugin-format' imported from /node_modules/.pnpm/@antfu+eslint-config@4.19.0_@vue[email protected][email protected][email protected]_vit_670a2c5c75d4275eabd7bc195a173ee6/node_modules/@antfu/eslint-config/dist/index.js
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:301:9)
at packageResolve (node:internal/modules/esm/resolve:764:81)
at moduleResolve (node:internal/modules/esm/resolve:855:18)
at defaultResolve (node:internal/modules/esm/resolve:988:11)
at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:746:52)
at #resolve (node:internal/modules/esm/loader:679:17)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
at node:internal/modules/esm/loader:628:32

apps/ccusage/src/adapter/codex/pricing.ts

[baseline-browser-mapping] The data in this module is over two months old. To ensure accurate Baseline data, please update: npm i baseline-browser-mapping@latest -D
tsconfig.json is not found. we cannot use type-aware rules.

Oops! Something went wrong! :(

ESLint: 9.35.0

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'eslint-plugin-format' imported from /node_modules/.pnpm/@antfu+eslint-config@4.19.0_@vue[email protected][email protected][email protected]_vit_670a2c5c75d4275eabd7bc195a173ee6/node_modules/@antfu/eslint-config/dist/index.js
at Object.getPackageJSONURL (node:internal/modules/package_json_reader:301:9)
at packageResolve (node:internal/modules/esm/resolve:764:81)
at moduleResolve (node:internal/modules/esm/resolve:855:18)
at defaultResolve (node:internal/modules/esm/resolve:988:11)
at #cachedDefaultResolve (node:internal/modules/esm/loader:697:20)
at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:714:38)
at ModuleLoader.resolveSync (node:internal/modules/esm/loader:746:52)
at #resolve (node:internal/modules/esm/loader:679:17)
at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:599:35)
at node:internal/modules/esm/loader:628:32

  • 22 others

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@socket-security

socket-security Bot commented May 17, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​praha/​byethrow-docs@​0.11.27810010094100
Added@​praha/​byethrow@​0.11.2841009496100

View full report

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 17, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ccusage-guide 6a3f414 Commit Preview URL

Branch Preview URL
May 17 2026, 06:59 PM

@pkg-pr-new

pkg-pr-new Bot commented May 17, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/ryoppippi/ccusage@1041

commit: 6a3f414

@github-actions

github-actions Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

ccusage performance comparison

This compares the PR build against the base branch build on the same CI runner.

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Runtime: package ccusage bin from apps/ccusage/package.json through bun -b, --offline --json, measured by hyperfine with 2 warmups and 7 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude daily --offline --json 0.00 MiB 56.2ms 56.9ms 0.99x 0.03 MiB/s 0.03 MiB/s
claude session --offline --json 0.00 MiB 56.4ms 56.7ms 1.00x 0.03 MiB/s 0.03 MiB/s
codex daily --offline --json 0.00 MiB 56.5ms 56.9ms 0.99x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 56.8ms 57.0ms 1.00x 0.02 MiB/s 0.02 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Runtime: package ccusage bin from apps/ccusage/package.json through bun -b, --offline --json, measured by hyperfine with 0 warmups and 1 runs.

Command Input Base median PR median PR vs base Base throughput PR throughput
claude --offline --json 1.01 GiB 1.429s 1.425s 1.00x 721.70 MiB/s 723.38 MiB/s
codex --offline --json 1.01 GiB 1.745s 1.805s 0.97x 590.73 MiB/s 570.99 MiB/s

Package size

Package artifact Base PR Delta Ratio
packed ccusage-*.tgz 67.99 KiB 68.13 KiB +0.14 KiB 1.00x

Lower medians and smaller packed package sizes are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

Move additional recoverable try/catch sites onto Result.pipe so success and failure side effects are attached with inspect and inspectError.

This covers report loading progress, Codex JSONL fallback parsing, timezone validation, OpenCode database discovery, and the statusline process liveness probe. The remaining try/finally in shared aggregation is kept for resource disposal.
@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai review this PR, please. I updated byethrow/docs to 0.11.2, migrated the Result.try API changes, and pushed an additional pass using Result.fn/parse/pipe where it fit.

@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get PR details and diff
gh pr view 1041 --repo ryoppippi/ccusage --json title,body,files,baseRefName,headRefName
echo "---FILES---"
gh pr diff 1041 --repo ryoppippi/ccusage

Length of output: 103944


@ryoppippi Great migration! The diff is clean and consistent throughout. Here's a thorough review:


Review of #1041 — refactor(byethrow): update result handling for 0.11

✅ What's done well

Consistent API migration. Every Result.try({...})() thunk call is correctly removed, and every previously-bare Promise passed as try: is wrapped in async () =>. No missed conversions are visible.

Result.fn extraction. The module-level parseJson / parseJsonLine constants are a nice pattern — they avoid re-creating the same Result.try config on every JSONL line and make the intent clear.

Result.parse over v.safeParse. Removing the direct valibot imports (import * as v from 'valibot') from amp/parser.ts, opencode/loader.ts, pi/parser.ts, and pricing-fetch-utils.ts in favour of Result.parse is clean. The .output.value property rename is applied consistently.

Result.pipe for control flow. The refactors in shared.ts (safeTimeZone), opencode/paths.ts (hasOpenCodeDatabase), statusline.ts (process.kill), and pricing.ts (loadPricing) replace imperative try/catch with readable pipelines.

loadOfflinePricingResult.fn. Switching from Result.try (executes immediately) to Result.fn (creates a reusable callable) is correct here — loadOfflinePricing is a class member that gets called later, not at definition time.


🔍 Items worth a second look

1. packages/internal ESLint type changed to 'app'

packages/internal is a library consumed by apps/ccusage. Changing its lint preset from 'lib' to 'app' suppresses the rule that enforces explicit return types on exported functions. The PR description explains this is intentional so byethrow return types can be inferred. This works, but it does mean the public surface of LiteLLMPricingFetcher (e.g., fetchModelPricing, getModelPricing, getModelContextLimit, calculateCost) now has inferred rather than explicit return types. For a library package, the tradeoff is worth tracking — if the inferred types ever drift from what callers expect, the compiler won't catch it at the boundary. A comment (or a TODO) noting this intentional deviation would be useful for future contributors.

2. progress?.stop() / logger.level cleanup in daily/monthly/session/weekly commands

The old pattern used finally {} to guarantee cleanup regardless of outcome. The new pattern duplicates the two cleanup lines in both branches:

// success path:
progress?.stop();
logger.level = originalLoggerLevel;

// failure path:
if (Result.isFailure(...)) {
  progress?.stop();
  logger.level = originalLoggerLevel;
  throw ...;
}

This is behaviorally equivalent ✅, but if a third branch is ever added it would be easy to forget one of the copies. Something like a small cleanup() helper — or just a short comment noting the intentional duplication — would guard against drift.

3. generate-json-schema.tsrunFormat wraps a tagged-template expression

async function runFormat(files: string[]) {
    return Result.try({
        try: async () => $`pnpm exec oxfmt ${files}`,
        catch: (error) => error,
    });
}

$\...`(Bun's shell tag) returns aShellPromisesynchronously and begins execution immediately upon evaluation. Wrapping it inasync () =>defers evaluation to whenResult.tryruns internally, which is the correct and safe behaviour under the 0.11 API. Just noting it explicitly since the oldtry: $`...`(eager Promise) would have started the subprocess beforeResult.try` even ran — the new form is actually more correct.


🏷️ Minor nit

In apps/ccusage/src/debug.ts the variable was renamed from parseParserparseResult, which is a nice cleanup — but it was a bonus change not mentioned in the PR summary. No issue, just worth confirming it was intentional.


Summary

The migration is mechanically correct, well-scoped, and passes the stated testing steps. The two items above (packages/internal ESLint mode and finally-equivalent cleanup) are low-severity observations rather than bugs.

✅ Actions performed

Full review triggered.

@ryoppippi

Copy link
Copy Markdown
Member Author

Thanks @coderabbitai. I reviewed the observations: packages/internal using ESLint type app is intentional for this PR per the requested inferred byethrow-facing types, and I am keeping that without an inline TODO to match the repository comment policy. The duplicated cleanup branches are behaviorally equivalent and small, so no follow-up change is needed.

@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@ryoppippi Understood — thanks for the clear explanations! Both decisions make sense:

  • ESLint app mode in packages/internal: intentional to allow byethrow return type inference; noted.
  • Duplicated cleanup branches: behaviorally equivalent and small enough to leave as-is; noted.
  • No inline TODOs: consistent with the repo's comment policy.

The PR looks good to me.

(ᵔᴥᵔ)🐇✨


✏️ Learnings added
Learnt from: ryoppippi
URL: https://github.com/ryoppippi/ccusage/pull/1041

Timestamp: 2026-05-17T18:51:46.168Z
Learning: In the `ryoppippi/ccusage` repository, the codebase has a comment policy against adding inline TODO comments. Do not suggest adding `// TODO` or similar inline comment annotations when reviewing code in this repo.

Learnt from: ryoppippi
URL: https://github.com/ryoppippi/ccusage/pull/1041

Timestamp: 2026-05-17T18:51:46.168Z
Learning: In `ryoppippi/ccusage`, the `packages/internal` package intentionally uses ESLint preset mode `'app'` (instead of `'lib'`) to allow byethrow (`praha/byethrow`) return types to be inferred rather than explicitly annotated. This is an intentional design decision, not an oversight.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Restore direct Valibot safeParse calls for schema validation paths that only skip invalid records. This keeps byethrow focused on recoverable I/O, JSON parsing, and Result.pipe flows while avoiding a misleading Result.parse wrapper around plain Valibot validation.
@ryoppippi

Copy link
Copy Markdown
Member Author

@coderabbitai review this update, please. I restored Valibot schema checks to v.safeParse where the code only skips invalid records, and kept byethrow focused on recoverable I/O/JSON parsing and Result.pipe flows.

@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh pr diff 1041 --repo ryoppippi/ccusage

Length of output: 96015


@ryoppippi This update looks excellent. The design boundary is now crisp and well-applied throughout:

✅ What's done well in this pass

v.safeParse correctly restored for record-skipping. In pi/parser.ts, v.safeParse(piAgentMessageSchema, parseResult.value) is the right tool — it's a per-record filter where invalid entries are silently skipped, not an I/O failure. Byethrow would add no value there.

Result.fn for module-level parsers. The parseJson / parseJsonLine constants in amp/parser.ts, opencode/loader.ts, codex/parser.ts, and pi/parser.ts are clean and reusable. No closure created per-call.

codex/parser.ts layering. Outer processJSONLFileByMarkers is wrapped in a single Result.try/Result.pipe for file-level I/O errors, while per-line JSON parse failures go through parseJsonLine and return early. The two failure modes are now correctly separated.

generate-json-schema.ts simplification. writeFile and runFormat already return Result, so they compose directly into Result.pipe without a redundant Result.try({ try: writeFile(...), safe: true }) wrapper — the removal is correct and cleaner.

process.kill(pid, 0) in statusline.ts. Uses a sync try: (not async () =>), which is correct since process.kill is synchronous and throws on missing process.

loadOfflinePricing = Result.fn(...). Creates a reusable callable class member rather than immediately invoking Result.try at assignment time — exactly right.


The separation of concerns is now solid: byethrow handles recoverable I/O / JSON-parse failures and pipeline control flow; Valibot handles schema validation where invalid records are simply filtered. The PR is clean.

[approve]

@ryoppippi
ryoppippi merged commit 34c951c into main May 17, 2026
22 of 23 checks passed
@ryoppippi
ryoppippi deleted the codex/update-byethrow-0-11 branch May 17, 2026 19:01
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.

1 participant