Commit Graph
5 Commits
Author SHA1 Message Date
averatec0773 a29cb4d5ed ci: install the anthropic extra so the prompt cache wire tests actually run
Signed-off-by: averatec0773 <575907690@qq.com>
2026-09-05 22:43:38 -05:00
averatec0773 a7e587aad8 feat(providers): cache the Anthropic static prefix and record cache usage
Every model call in a run resent the same tool schemas and system prompt at full price because no cache_control was ever sent. ChatLLM now sends, for the direct Anthropic adapter only and only when the request carries the agent's leading system prompt, an explicit cache breakpoint on the system prompt block plus the top-level automatic breakpoint as a per-call kwarg. One-shot calls without a system prompt (context compaction, image vision, title generation) are unchanged, other providers are byte-identical, and the caller's message list is never mutated.

_normalize_llm_usage keeps cache_read_tokens and cache_creation_tokens from input_token_details when the provider reports them, summing the per-TTL creation keys that langchain-anthropic splits out, so llm_usage.json shows what was read and written. Providers that report no details produce unchanged artifacts.

Tests build the real ChatAnthropic through build_llm with a dummy key and assert the assembled request dict, drive chat and stream_chat through recording fakes, and push a real anthropic Usage through langchain's converter. No network is opened.

Signed-off-by: averatec0773 <575907690@qq.com>
2026-09-05 22:43:38 -05:00
averatec0773 4bdfd81bb2 feat(config): add VIBE_TRADING_ANTHROPIC_PROMPT_CACHE flag
Default on. Documented in .env.example next to the other Anthropic settings; it is the off switch for a compatible proxy that rejects the cache_control request parameter.

Signed-off-by: averatec0773 <575907690@qq.com>
2026-09-05 22:43:38 -05:00
averatec0773 d79669eb06 fix(session): persist the attempt start so the elapsed clock survives navigation, reload and history
The attempt's wall-clock start was never persisted or transmitted, so the
Agent page could only guess it: the live clock restarted from 0 after a
same-session re-mount (tab switch), and history hydration started the
durable "Done" row at the first tool call, or at created_at for a
tool-less turn, which then read 0s.

Backend
- Attempt.started_at (epoch seconds) is set in mark_running() and
  persisted with the attempt.
- attempt.started and the reply metadata carry started_at; terminal
  events carry started_at and ended_at.
- GET /sessions/{id}/events?replay=active re-announces attempt.started
  from the persisted attempt while one is running, so a client that joins
  after the ring buffer rotated past the original event still learns the
  real start.
- EventBus(heartbeat_interval_s=...) so the route test does not idle on
  the 30 s heartbeat.

Frontend
- identifyActivity seeds the clock from started_at; a repeated
  attempt.started for the same attempt is a no-op.
- The same-session re-mount path carries the running activity's
  startedAt across switchSession(); history hydration drops a carried
  activity whose reply is already committed.
- buildToolTimelineMessages accepts startedAt; history uses
  metadata.started_at, else created_at minus elapsed_ms, else the legacy
  first-tool guess.
- attempt.completed backdates a late-joined activity to the backend
  start before archiving it.

Signed-off-by: averatec0773 <575907690@qq.com>
2026-09-02 23:40:31 -05:00
averatec0773 47c274719a fix(providers): strip relocated extra_body.temperature in the Anthropic self-heal
The temperature self-heal for Claude models that reject `temperature`
retries after popping the top-level `temperature` key. langchain-anthropic
1.4.x, on an anthropic SDK whose `Messages.create` no longer accepts
sampling parameters as named arguments, relocates `temperature` into
`extra_body` before the request is sent, so the retry still carried
`extra_body={"temperature": 0.0}` and failed with the same HTTP 400.

Drop `temperature` from `extra_body` as well when the model is a remembered
rejecter, keep any other `extra_body` keys, and omit `extra_body` entirely
once it is empty so an empty object is never sent.

Tests mirror the relocating payload shape with a fake ChatAnthropic base:
the retry is clean, unrelated `extra_body` keys survive, and models that
still accept `temperature` are untouched.

Signed-off-by: averatec0773 <575907690@qq.com>
2026-09-02 02:56:19 -05:00