Skip to content

refactor: unify result types with discriminated Result<T, E> union#1125

Open
Hweinstock wants to merge 1 commit intomainfrom
refactor/unified-result-type-v2
Open

refactor: unify result types with discriminated Result<T, E> union#1125
Hweinstock wants to merge 1 commit intomainfrom
refactor/unified-result-type-v2

Conversation

@Hweinstock
Copy link
Copy Markdown
Contributor

@Hweinstock Hweinstock commented May 5, 2026

Description

Problem

The codebase uses an inconsistent result-like type that changes depending on the context. The implementations vary slightly, and are not explicit about (usually) sharing a common shape. This common shape also strips error types, and distills their information down to a string, which leads to brittle behavior when catching errors.

As an example, systems that span modules (ex. telemetry) must handle each result type individually, resulting in excessive branching and complexity. Additionally, loss of error information, means loss of this information in telemetry, making it difficult to impossible to tell the type of error, and if it was user/application caused.

Solution

  • unify result types behind a common flexible interface loosely based on Rust results. The main difference is that data is hoisted to the top level to be consistent with existing patterns.
  • store full error information on the result, allowing for instanceof checking and error name matching for stronger exception handling and telemetry.

Future Work

There are other result types that could be generalized with further work to support spread operators on the error as well. I left this OOS since the PR is already very large. Some other small patterns that this PR continues, but I think should change in the future:

  • excessive mocking (Ex. some tests mock entire modules, rather than the underlying dependencies. We mock our own code in some places).
  • testing implementation rather than behavior (error messages are matches verbatim in many places, likely because thats all we had before. However, we should change these tests the verify error "shape" rather than exact content.
  • higher level utilities for working with results. There are common patterns that could be useful to abstract. As an example, a mapResult function that allows data transformations with clear error propagation. This could avoid some nesting of try/catches in a few places.
  • add more error types as we see fit.
  • avoid using console.log directly for more flexibility.

Related Issue

Closes #

Documentation PR

N/A — internal refactor, no user-facing changes.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (please describe): Internal refactor — unify result types

Testing

How have you tested the change?

  • I ran npm run test:unit and npm run test:integ
  • I ran npm run typecheck
  • I ran npm run lint
  • If I modified src/assets/, I ran npm run test:update-snapshots and committed the updated snapshots

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.

@github-actions github-actions Bot added size/xl PR size: XL agentcore-harness-reviewing AgentCore Harness review in progress labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch 2 times, most recently from 6cde6f8 to cc14f84 Compare May 5, 2026 20:54
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL agentcore-harness-reviewing AgentCore Harness review in progress labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from cc14f84 to 2a57e34 Compare May 5, 2026 20:58
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from 2a57e34 to db3248f Compare May 5, 2026 21:00
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from db3248f to a17bbae Compare May 5, 2026 21:02
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from a17bbae to 9cb5022 Compare May 5, 2026 21:09
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from 9cb5022 to 6642045 Compare May 5, 2026 21:20
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from 6642045 to 25dd47a Compare May 5, 2026 21:41
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
Comment thread src/cli/commands/invoke/command.tsx Fixed
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from 25dd47a to ec8b476 Compare May 5, 2026 21:48
@github-actions github-actions Bot removed the size/xl PR size: XL label May 5, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from ee1d76e to 0ec9e0f Compare May 5, 2026 22:11
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from 0ec9e0f to 49f1732 Compare May 5, 2026 22:14
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from 49f1732 to ce554da Compare May 5, 2026 22:17
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from ce554da to cd560e1 Compare May 5, 2026 22:19
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from cd560e1 to 450861e Compare May 5, 2026 22:21
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from 450861e to b6de8aa Compare May 5, 2026 22:23
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from b6de8aa to 352f76a Compare May 5, 2026 22:26
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from 352f76a to 29296d0 Compare May 5, 2026 22:27
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels May 5, 2026
@Hweinstock Hweinstock force-pushed the refactor/unified-result-type-v2 branch from 29296d0 to 8cc8d41 Compare May 5, 2026 22:29
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 43.09% 9025 / 20942
🔵 Statements 42.38% 9583 / 22612
🔵 Functions 39.97% 1559 / 3900
🔵 Branches 39.94% 5808 / 14540
Generated in workflow #2559 for commit eea25e4 by the Vitest Coverage Report Action

Introduce a shared Result<T, E> type (inspired by Rust's Result) that
replaces ad-hoc { success: boolean; error?: string } patterns across
the codebase.

Key changes:
- Add src/lib/types.ts with Result<T, E> discriminated union type
- Add toError() helper in src/cli/errors.ts for catch blocks
- Migrate all command, operation, and primitive result types to Result<T>
- Error field is now Error (not string) on the failure branch
- Data fields only exist on the success branch (proper narrowing)
- Update all consumers to narrow before accessing branch-specific fields
- Update test assertions to match new Error objects and add narrowing
@padmak30
Copy link
Copy Markdown
Contributor

padmak30 commented May 6, 2026

Bug Bash Report — refactor: unify result types with discriminated Result<T, E> union

Branch: refactor/unified-result-type-v2 | Version: 0.13.0 | Base: main

TL;DR

No in-scope blockers, highs, or mediums found. Refactor is behavior-preserving: every happy/error path exercised produces identical output to main. Two pre-existing quirks re-observed (documented below as pre-existing). 1 note for maintainers.

In-scope bugs

None.

Pre-existing bugs (reproduce identically on main)

[medium] Commands exit 0 on error

  • Reproducer:
    cd /tmp/empty-dir
    node dist/cli/index.mjs validate; echo "exit=$?"   # prints "No agentcore project found…" exit=0
    node dist/cli/index.mjs status;   echo "exit=$?"   # same
    node dist/cli/index.mjs status --json; echo "exit=$?"
    # inside a project, with malformed agentcore.json
    echo '{invalid json' > agentcore/agentcore.json
    node dist/cli/index.mjs validate;  echo "exit=$?"  # exit=0
    node dist/cli/index.mjs status --json; echo "exit=$?"  # exit=0
  • Evidence it's pre-existing: Checked out origin/main (9afd3f0), rebuilt, reproduced identical output + exit=0 for every case. Not introduced by this PR.

[low] status --json prints human-readable text on error, not JSON

  • Reproducer: With a malformed agentcore.json, status --json prints Error: Failed to parse JSON in config file… as plain text instead of a JSON error envelope.
  • Evidence it's pre-existing: Same output on origin/main.

Notes

  • invoke/logs/traces without a TTY print command help instead of an error. When running invoke --name X --prompt hello in a non-TTY shell, the CLI renders the subcommand help and exits 0 instead of reporting that an interactive terminal is required (or attempting non-interactive execution). Reproduces identically on main, so out of scope for this refactor; flagging for future UX work. The sole "interactive terminal required" message only surfaces for deploy.

What works ✓

  • agentcore create --project-name bbtest --name myagent --defaults --skip-git --skip-install produces a valid project with correct agentcore.json.
  • validate on a good project → Valid, exit=0.
  • status / status --json on a good project → correct human + JSON output; resources array and deploymentState: local-only reported.
  • Schema violations are surfaced with precise per-field errors:
    • {}name: expected "string", version: expected "number".
    • runtimes[0].build: "BogusBuild"expected "CodeZip" | "Container".
  • Malformed JSON → Invalid JSON in agentcore.json: Expected property name… (position included).
  • remove agent --name nonexistent -y → structured JSON {"success":false,"error":"Agent \"nonexistent\" not found."}.
  • remove agent --name myagent -y → structured success JSON; subsequent status --json shows resources: [].
  • remove all -y{"success":true,"message":"All schemas reset to empty state"}.
  • Build clean, --version prints 0.13.0, all CLI help rendered correctly.

Test coverage

Surface Tested Result
Build yes pass
CLI happy path (create/validate/status) yes pass
Error paths (missing project, malformed JSON, bad schema) yes pass (behavior identical to base)
Schema validation yes pass
Removal paths (remove agent, remove all, nonexistent) yes pass
Partition correctness n/a PR does not touch ARN/endpoint code

Refactor LGTM from a black-box behavioral standpoint — every tested surface produces identical stdout/stderr/exit code to main.

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

Labels

size/xl PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants