hermes-agent/tests/agent
Siddharth Balyan 59529afee0
feat(billing): carry the payment-method union through to clients (#71542)
* feat(billing): add payment_method union to the billing-state wire type

* feat(billing): carry the payment-method union through the gateway

NAS now sends a typed `paymentMethod` union on /api/billing/state alongside
the legacy `card` field. The gateway parses payloads field-by-field, so the
new field was dropped on the floor before reaching TUI/Desktop.

Parse it into PaymentMethodInfo and re-emit it as snake_case `payment_method`,
matching the translation the rest of this payload already does. The payment
method id is deliberately not carried through — clients have no use for it.

No client rendering changes: `card` stays populated for cards, so every
existing consumer behaves exactly as before and the new field is inert until
a surface opts into reading it.

* fix(billing): send only the fields each payment-method kind declares

The serializer emitted every key for every kind, so a Link method went out
carrying brand, last4 and wallet set to null. That contradicts the shared
type, where each kind declares its own fields: a client testing `'brand' in
pm` would read every Link method as a card, and one trusting the declared
non-null `brand` could crash on it.

Send each kind's own fields, and forward an unrecognized kind by name alone
so a client that predates it can still say something honest. The shared type
gains the matching fallback arm its own comment already promised.

Tests now follow a payload from the server response through to the client
wire for each kind, rather than checking parsing and serializing separately —
which is why the old expectation locked in the wrong shape without noticing.

* fix(billing): keep the payment-method kind narrowable

Typing the fallback arm's kind as `string & {}` borrowed a trick that only
works on unions of plain strings. On a union of objects it makes the
discriminant non-literal, so TypeScript stops narrowing on every arm — even
`if (pm.kind === 'card')` no longer gives you `brand`. The first client to
use this would have hit a compile error and reached for a cast.

An unrecognised kind now arrives as `unknown`, carrying the real name
alongside it, so every arm has a literal discriminant. A type-level test
pins this: it fails to compile if the discriminant stops narrowing.

The parser settles which kind it is, the way the card parser already does,
so the record cannot hold fields that do not belong to its kind and the
serializer no longer re-checks. The type comment also stops claiming `card`
is a safe signal — it is null for Link, so `!card` does not mean "nothing on
file".
2026-07-27 01:49:43 +05:30
..
lsp
transports fix(codex): scope 24h retention to Bedrock Mantle 2026-07-24 15:54:08 -07:00
__init__.py
test_account_usage.py
test_anthropic_adapter.py fix(agent): cache static system prompt prefixes 2026-07-24 16:01:38 -07:00
test_anthropic_billing_guidance.py
test_anthropic_keychain.py
test_anthropic_kimi_signed_thinking_replay.py
test_anthropic_kwargs_sanitize.py
test_anthropic_mcp_prefix_strip.py
test_anthropic_oauth_pkce.py
test_anthropic_oauth_ua_prefix.py
test_anthropic_output_field_leak.py
test_anthropic_thinking_block_order.py
test_anthropic_whitespace_text_blocks.py fix(anthropic): keep replay content schema-valid when every block is blank 2026-07-24 15:54:38 -07:00
test_api_content_sidecar.py
test_arcee_trinity_overrides.py
test_async_utils.py
test_aux_progress_streaming.py feat(aux): force streaming for providers that reject non-stream requests 2026-07-25 14:58:04 -07:00
test_auxiliary_anthropic_pool_fallback_regression.py
test_auxiliary_client.py feat(compression): progress-aware timeouts — stop punishing slow summary models 2026-07-25 12:26:28 -07:00
test_auxiliary_client_anthropic_custom.py
test_auxiliary_client_azure_foundry.py
test_auxiliary_client_base_url_host_validation_52608.py
test_auxiliary_client_bootstrap_skew.py
test_auxiliary_client_proxy_env.py
test_auxiliary_client_resolve_dedup.py
test_auxiliary_client_ssl_verify.py
test_auxiliary_client_xai_oauth_recovery.py
test_auxiliary_compression_timeout_floor.py
test_auxiliary_config_bridge.py
test_auxiliary_main_first.py
test_auxiliary_named_custom_providers.py
test_auxiliary_runtime_cache_key.py
test_auxiliary_transient_retry.py
test_auxiliary_transport_autodetect.py
test_auxiliary_user_default_headers.py
test_azure_identity_adapter.py
test_battery.py
test_bedrock_1m_context.py
test_bedrock_adapter.py
test_bedrock_empty_text_blocks.py
test_bedrock_integration.py
test_bedrock_interrupt_post_worker.py
test_billing_links.py
test_billing_usage.py
test_billing_view.py feat(billing): carry the payment-method union through to clients (#71542) 2026-07-27 01:49:43 +05:30
test_bounded_response.py
test_cascading_interrupt_6600.py
test_chat_completion_helpers_provider_sort.py
test_cjk_token_estimation.py
test_close_interrupted_tool_sequence.py
test_codex_app_server_event_bridge.py
test_codex_app_server_persist.py
test_codex_cloudflare_headers.py
test_codex_gpt55_autoraise_notice.py
test_codex_responses_adapter.py
test_codex_runtime_live_events.py
test_codex_ttfb_watchdog.py
test_coding_context.py
test_compaction_anti_thrash.py
test_compaction_redaction_boundaries.py
test_compress_focus.py
test_compress_signal_leak.py
test_compressed_summary_metadata.py
test_compression_anti_thrash_persistence.py
test_compression_anti_thrash_recovery.py fix(compression): add recovery path to anti-thrash auto-compaction block 2026-07-24 15:57:09 -07:00
test_compression_attempt_telemetry.py
test_compression_concurrent_fork.py fix(compression-lock): reclaim crashed holders instead of stranding the lease 2026-07-25 22:47:07 -07:00
test_compression_count_warning_36908.py
test_compression_fallback_budget.py
test_compression_interrupt_protection.py
test_compression_logging_session_context.py
test_compression_max_attempts_config.py
test_compression_progress.py
test_compression_rotation_state.py fix(compression): recover rotated session lineage 2026-07-24 16:00:34 -07:00
test_compression_small_ctx_threshold_floor.py
test_compressor_actionable_tail_anchor.py
test_compressor_assistant_tail_anchor.py
test_compressor_historical_media.py
test_compressor_image_tokens.py
test_compressor_media_stripping.py
test_compressor_tail_cut_tool_pair_floor.py
test_compressor_tool_call_budget.py
test_compressor_zero_user_guard.py
test_context_breakdown.py
test_context_compressor.py
test_context_compressor_cross_session_guard.py
test_context_compressor_session_end_clears_state.py
test_context_compressor_summary_continuity.py
test_context_compressor_temporal_anchoring.py
test_context_compressor_zero_user_provenance.py
test_context_engine.py
test_context_engine_host_contract.py
test_context_engine_on_turn_complete_usage.py
test_context_engine_select_context.py
test_context_references.py fix(desktop): quote persisted @image: paths so spaced paths render 2026-07-24 21:20:52 -05:00
test_context_refs_concurrent.py
test_copilot_acp_client.py fix: decode config and state files as UTF-8 on non-UTF-8 locales 2026-07-24 17:10:39 -07:00
test_copilot_acp_deprecation.py
test_credential_pool.py
test_credential_pool_no_entries_log_throttle.py
test_credential_pool_oat_authtype.py
test_credential_pool_oauth_writethrough.py
test_credential_pool_provider_boundary.py
test_credential_pool_routing.py
test_credential_pool_unmatched_rotation_bound.py fix: break unbounded 401 retry loop in credential pool OAuth path 2026-07-24 15:50:36 -07:00
test_credits_cold_start.py
test_credits_fixture_snapshot.py
test_credits_policy.py
test_credits_tracker.py
test_credits_view.py
test_cron_inline_api_call_62151.py
test_crossloop_client_cache.py
test_curator.py
test_curator_activity.py
test_curator_backup.py
test_curator_classification.py
test_curator_reports.py
test_custom_pool_mismatch_guard.py
test_custom_provider_extra_body.py
test_custom_provider_extra_body_matching.py
test_custom_providers_vision.py
test_deepseek_anthropic_thinking.py
test_direct_provider_url_detection.py
test_display.py
test_display_emoji.py
test_display_todo_progress.py
test_display_tool_failure.py
test_empty_tool_name_loop_dampening.py
test_engine_preflight_wire.py
test_error_classifier.py
test_external_skills.py
test_external_skills_dirs_cache.py
test_failover_identity.py
test_file_safety.py
test_file_safety_container_mirror.py
test_file_safety_credentials.py
test_file_safety_cross_profile.py
test_file_safety_sandbox_mirror.py
test_file_safety_session_state.py
test_gateway_turn_sidecar.py
test_gemini_fast_fallback.py
test_gemini_free_tier_gate.py
test_gemini_native_adapter.py
test_gemini_schema.py
test_ghost_skill_pruning.py
test_i18n.py
test_idle_compaction.py
test_idle_compaction_lock_and_guards.py
test_image_gen_registry.py
test_image_routing.py
test_insights.py
test_intent_ack_continuation.py
test_jiter_preload.py
test_kanban_stop.py
test_kimi_coding_anthropic_thinking.py
test_last_total_tokens.py
test_learn_prompt.py
test_learning_graph.py
test_learning_graph_render.py
test_learning_mutations.py
test_lmstudio_reasoning.py
test_local_stream_timeout.py
test_manual_compression_feedback.py
test_markdown_tables.py
test_memory_async_sync.py
test_memory_boundary_commit.py
test_memory_provider.py
test_memory_session_switch.py
test_memory_skill_scaffolding.py
test_memory_user_id.py
test_memory_write_bridge.py
test_message_content.py
test_minimax_auxiliary_url.py
test_minimax_provider.py
test_moa_aggregator_cache_control.py
test_moa_aggregator_cost_slot.py
test_moa_context_max_tokens.py
test_moa_progress.py
test_moa_quiet_reference_output.py
test_moa_reasoning_effort.py
test_moa_reference_system_prompt.py
test_moa_slot_api_mode.py
test_moa_slot_max_tokens.py
test_moa_switch_api_mode.py
test_moa_trace_streamed_capture.py
test_model_extra_type_guard.py
test_model_metadata.py
test_model_metadata_local_ctx.py
test_model_metadata_ssl.py
test_models_dev.py
test_moonshot_schema.py
test_non_stream_stale_timeout.py
test_none_deref_guards.py
test_nous_credits_gauge.py
test_nous_credits_snapshot.py
test_nous_oauth_401_guidance.py
test_nous_rate_guard.py fix: decode config and state files as UTF-8 on non-UTF-8 locales 2026-07-24 17:10:39 -07:00
test_onboarding.py
test_oneshot.py
test_openrouter_response_cache.py
test_pet_engine.py
test_pet_generate.py
test_platform_hint_desktop.py
test_platform_hint_overrides.py
test_plugin_llm.py
test_portal_tags.py fix(nous-portal): give auxiliary calls the Portal sticky routing key 2026-07-25 22:15:00 -07:00
test_pre_compress_memory_context.py
test_preflight_compression_gate.py
test_preflight_lock_defer.py
test_proactive_prune_config.py
test_proactive_tool_result_pruning.py
test_probe_cache_followups.py
test_prompt_builder.py
test_prompt_caching.py fix(prompt-caching): inject cache breakpoints after message normalization 2026-07-24 16:01:38 -07:00
test_protected_tail_pressure_61932.py
test_proxy_and_url_validation.py
test_rate_limit_tracker.py
test_reactions.py
test_reasoning_stale_timeout_floor.py
test_redact.py
test_replay_cleanup.py
test_restore_primary_pool_reselect.py
test_resume_stale_active_task.py
test_rotation_flush_persisted_boundary_68196.py
test_runtime_cwd.py
test_save_url_image.py
test_secret_scope.py
test_session_rotation_flush_cold_resume_68454.py
test_set_runtime_main_custom_provider.py
test_shell_hooks.py
test_shell_hooks_consent.py
test_skill_bundles.py
test_skill_commands.py
test_skill_commands_reload.py
test_skill_invocation_description.py feat(skills): describe a /skill turn the way the user typed it 2026-07-26 02:58:12 -05:00
test_skill_utils.py
test_skip_memory_store_65429.py
test_ssl_ca_guard.py
test_ssl_verify.py
test_stream_read_timeout_floor.py
test_stream_single_writer_guard.py
test_streaming_context_scrubber.py
test_subagent_progress.py
test_subagent_stop_hook.py
test_subdirectory_hints.py
test_subdirectory_hints_tilde.py
test_subscription_view.py
test_summarize_tool_result_type_safety.py
test_summary_prefix_semantics.py
test_summary_prefix_tool_use.py
test_system_prompt.py fix(agent): cache static system prompt prefixes 2026-07-24 16:01:38 -07:00
test_system_prompt_restore.py fix(caching): reconstruct static system prefix on session restore and post-compression reuse 2026-07-24 16:01:38 -07:00
test_think_scrubber.py
test_thinking_timeout_guidance.py
test_thread_scoped_output.py
test_title_generator.py fix(sessions): stop titling a session after the skill it invoked 2026-07-26 02:58:16 -05:00
test_tool_call_arg_no_redaction.py
test_tool_dispatch_helpers.py
test_tool_executor_checkpoint_paths.py
test_tool_guardrails.py
test_tool_result_classification.py
test_trace_upload.py
test_transcription_registry.py
test_tts_registry.py
test_turn_context.py fix(compression): recover rotated session lineage 2026-07-24 16:00:34 -07:00
test_turn_context_overflow_warning.py
test_turn_finalizer_cleanup_guard.py
test_turn_finalizer_final_response_persistence.py
test_turn_finalizer_interrupt_alternation.py
test_turn_finalizer_iteration_limit_exit.py
test_turn_overlap_tripwire.py
test_turn_retry_state.py
test_unsupported_parameter_retry.py
test_unsupported_temperature_retry.py
test_usage_pricing.py
test_verification_evidence.py
test_verification_evidence_fd_leak.py fix(gateway,tools,agent): close leaked SQLite connections in delivery, delegation, and verification ledgers 2026-07-24 15:55:08 -07:00
test_verification_stop.py
test_verification_stop_caching.py
test_verify_hooks.py
test_vertex_adapter.py
test_video_gen_registry.py
test_vision_resolved_args.py
test_vision_routing_31179.py