Skip to content

fix(nofxi): review fixes on top of #1495 — chat trade unblock + management fast path + claw402 + UX - #1498

Open
shinchan-zhai wants to merge 24 commits into
NoFxAiOS:feat/nofxifrom
shinchan-zhai:nofxi-review-fixes
Open

fix(nofxi): review fixes on top of #1495 — chat trade unblock + management fast path + claw402 + UX#1498
shinchan-zhai wants to merge 24 commits into
NoFxAiOS:feat/nofxifrom
shinchan-zhai:nofxi-review-fixes

Conversation

@shinchan-zhai

Copy link
Copy Markdown
Collaborator

Context

Stacked on top of #1495 (NOFXi agent chat workflow). The 4 commits added by this PR are the review-fix follow-ups; everything in #1495 itself is unchanged. Please merge #1495 first or merge this together with #1495.

Summary of the 4 commits

  1. fix(claw402) — re-apply stripMaxTokens (regression vs dev — Kimi K2.5 / DeepSeek R1/V4 thinking models drop content), drop assistant history on thinking endpoints (reasoning_content protocol), add deepseek-v4-flash/v4-pro endpoints (PR feat(payment): add new DeepSeek V4 models to claw402 endpoints and pricing #1488 missing), and override Claw402Client.CallWithRequest so all 20+ agent call sites get x402 payment retry instead of failing on bare 402.

  2. feat(agent): unblock chat-driven trade execution — three independent gates were closing this path: parseTradeCommand was defined but never called (explicit "做多 BTC 0.01" went through LLM router and got reinterpreted), AllowTradeExecution defaulted false with no code path setting it true, and CanExecuteTrade was hardcoded to admin-only (CLAUDE.md specifies single-user local). All three fixed; risk caps and confirmation prompt still apply.

  3. feat(agent): deterministic management fast path — LLM router consistently picks direct_answer for management commands ("创建一个新交易员" → conversational preface, action never executes). Prompt strengthening + 14 worked few-shot examples kept pass rate at ~21/36; new agent/management_fastpath.go (regex 6 verbs × 4 entities, dispatches to driveActiveSession directly) + planner_runtime.go reason step emitStreamText fix + SSE timeout protection moved it to 36/36 on the self-test matrix.

  4. chore(review) — shutdown order (agent before traderManager), agent_preferences body cap.

Test plan

  • Self-test matrix: 36 prompts × 11 user journeys (greeting / onboarding / trade-advice / trade-exec / trader-mgmt / exchange-mgmt / model-mgmt / strategy-mgmt / diagnosis / ambiguous / multilingual / prompt-injection) — 36/36 PASS
  • Manual UI smoke: trade verb → confirmation prompt; "创建交易员" → slot-fill flow; "换 v4 pro" → DB updated; "你好" → friendly reply
  • Build + go test ./agent/ ./api/ ./mcp/payment/
  • Real-trade testnet dogfood — deferred to follow-up
  • Anthropic Messages API support for claude-opus — deferred

Notes for reviewer

  • No schema changes
  • No public API contract changes (agent_preferences body limit is the only enforcement, normal callers unaffected)
  • Default change: AllowTradeExecution: false → true. CLAUDE.md says single-user local deployment; the user owns their own nofx-server. Each trade still goes through explicit confirmation + risk caps. If you'd prefer an env opt-out, happy to add.
  • agent/management_fastpath.go 248 lines new code — regex/keyword dispatcher. Intentional duplicate of skill JSON intents until follow-up unifies them.
  • Comprehensive test matrix and runner are at /tmp/nofxi_test_* locally; can be promoted to agent/agent_e2e_test.go in a follow-up PR.

🤖 Generated with Claude Code

lky-spec and others added 24 commits April 18, 2026 16:06
…4 endpoints, x402-aware CallWithRequest

- stripMaxTokens reapplied (regression vs dev — Kimi K2.5 / DeepSeek R1/V4
  let reasoning tokens consume the entire budget, leaving delta.content empty)
- dropAssistantHistory for /v4-flash, /v4-pro, /chat/reasoner: DeepSeek
  thinking models reject any assistant turn lacking reasoning_content
  ("The reasoning_content in the thinking mode must be passed back to the API")
- Add deepseek-v4-flash and deepseek-v4-pro endpoints (PR NoFxAiOS#1488 on dev,
  missing on feat/nofxi)
- New Claw402Client.CallWithRequest override: base mcp.Client.CallWithRequest
  issues a bare HTTP request and treats 402 as terminal, bypassing the x402
  payment loop. The agent has 20+ CallWithRequest sites (planner, brain,
  workflow, llm_skill_router, memory, etc.) — without this override every
  one of them fails with "API returned error (status 402)"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three independent gates were closing this path:

1. parseTradeCommand existed but was never called — explicit trade verbs
   like "做多 BTC 0.01" went through the LLM router and got reinterpreted
   as analysis or trader-creation requests. New handleTradeIntent provides
   a deterministic fast path: parse → resolve trader → validate → enqueue
   pending trade → return confirmation prompt. Bypasses the LLM router so
   unambiguous orders cannot be re-routed to "let me first analyse the
   market" flows.

2. parseTradeCommand silently dropped unparseable quantity / leverage,
   producing TradeAction{Quantity: 0}. For close_long/close_short that
   forwards to underlyingTrader.CloseLong(symbol, 0, ...), which most
   exchanges interpret as "close entire position" — different from what
   the user typed. Now reject the parse instead.

3. CanExecuteTrade was hardcoded to (user_id == "admin"). On a single-user
   local deployment (CLAUDE.md) every authenticated user is the operator
   of their own nofx-server, so the literal-string admin gate locked out
   non-admin users from ever triggering trades via chat. Allow all
   authenticated users; risk caps and the explicit confirmation prompt
   still apply.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…fixes + prompt strengthening

Routing
- New management_fastpath.go: regex matches 6 verbs (create / list / delete /
  stop / start / configure / switch) × 4 entities (trader / exchange / model /
  strategy) → dispatches directly through driveActiveSession, bypassing the
  LLM router. The LLM router consistently picks direct_answer for these
  unambiguous commands ("创建一个新交易员" → "好的我来帮你..."conversational
  preface, action never executes), and prompt strengthening alone did not
  shift this — measured: hand-tuned rules + 14 worked few-shot examples kept
  pass rate at ~21/36; deterministic fast path moved it to 36/36.
- Diagnosis cues ("怎么没下单", "连不上", "失败") plus an entity keyword route
  to *_diagnosis skills.
- agent.go wires both handleTradeIntent and handleManagementIntent into
  stream + non-stream entry points, in front of the LLM router.

LLM client
- Use mcp.NewAIClientByProvider so claw402 routes through Claw402Client
  (with x402 EIP-712 signing + per-model endpoint mapping) instead of the
  bare OpenAI-compatible client. AllowTradeExecution defaults to true on
  single-user local deployments.

Streaming UX
- web.go: 120s → 180s ctx timeout (multi-step planner with v4-flash
  routinely needs 100s+); on context cancellation OR empty resp, emit
  event:error + event:done so the React layer no longer falls back to
  the misleading "No response" string.
- planner_runtime.go: planStepTypeReason now calls emitStreamText for the
  reasoning text. Without this, reason steps emit only step_complete
  events — the analysis text stays in OutputSummary and observation log
  but never reaches SSE deltas, so the UI shows step labels with no body.

Prompts
- llm_skill_router.go: distinguish "give me a trading decision /
  recommendation" (planned_agent) from "create/configure trader entity"
  (trader_management); add 14 worked few-shot examples covering all major
  zh management/diagnosis intents. Largely ineffective at runtime — kept
  as belt-and-suspenders alongside the deterministic fast path.
- central_brain.go: add ACTION VERBS REQUIRE NEW_TASK rule with concrete
  zh examples; forbid EXPLAIN_KNOWLEDGE as a soft "好的我来帮你..." preface.
- model_provider_catalog.go: add deepseek-v4-flash / -pro / -reasoner +
  kimi-k2.5 to claw402 RecommendedModelHints; remove claude-opus
  (claw402 routes it to /api/v1/ai/anthropic/messages/opus which speaks
  Anthropic Messages API — the planner JSON contract doesn't parse this
  format, every turn fails with "invalid next step decision json").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- main.go: stop the NOFXi agent BEFORE traderManager.StopAll. Chat-driven
  goroutines call into TraderManager (start/stop/open trade), so tearing
  the manager down first risks nil-deref or write-to-closed-channel from
  in-flight requests. Also remove the misleading "✅ NOFXi agent stopped"
  log that fired before the deferred Stop() actually ran.
- api/agent_preferences.go: cap POST /api/agent/preferences body to 8 KB
  via http.MaxBytesReader BEFORE bind. The post-bind 500-rune check on
  Text was too late if the raw body was already huge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cla-assistant

cla-assistant Bot commented May 5, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
0 out of 2 committers have signed the CLA.

❌ lky-spec
❌ shinchan-zhai
You have signed the CLA already but the status is still pending? Let us recheck it.

1 similar comment
@cla-assistant

cla-assistant Bot commented May 5, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
0 out of 2 committers have signed the CLA.

❌ lky-spec
❌ shinchan-zhai
You have signed the CLA already but the status is still pending? Let us recheck it.

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.

2 participants