Skip to content

fix: WebSocket 切断問題を修正#23

Open
leivy-dev wants to merge 8 commits intomoltlaunch:mainfrom
leivy-dev:fix/ws-reconnect-stability
Open

fix: WebSocket 切断問題を修正#23
leivy-dev wants to merge 8 commits intomoltlaunch:mainfrom
leivy-dev:fix/ws-reconnect-stability

Conversation

@leivy-dev
Copy link

問題

cashclaw が WebSocket 切断を頻発していた。原因は3点:

  1. 二重バックオフバグ: error イベントが ws.close() + scheduleWsReconnect() を呼び、その後 close イベントも scheduleWsReconnect() を呼ぶ。1回の切断でバックオフが2倍ずつ2回加速していた
  2. 古いリスナー残留: connectWs() で前の ws を removeAllListeners せずに新規作成していた
  3. keepalive なし: ping/pong がなくプロキシやサーバーのアイドルタイムアウトで切断された

修正内容

  • error ハンドラから scheduleWsReconnect() 削除(close イベントに任せる)
  • connectWs()ws.removeAllListeners() + terminate() してから新規作成
  • 20s 間隔の keepalive ping を追加
  • pong タイムアウト 10s を追加(dead connection を検知して強制再接続)
  • disconnectWs() で ping/pong タイマーもクリーンアップ

テスト計画

  • cashclaw 起動後、長時間(数時間)放置して切断が発生しないか確認
  • ネットワーク遮断後に自動再接続することを確認
  • pnpm tsc --noEmit パス済み

🤖 Generated with Claude Code

leivy-dev and others added 8 commits March 14, 2026 11:32
Add src/cli.ts as a new CLI entrypoint providing subcommands:
- init: configure cashclaw without browser UI (reads ANTHROPIC/OPENAI/OPENROUTER_API_KEY from env)
- start: start daemon with PID file, no browser auto-open
- stop: stop daemon via PID file
- status: show config and daemon running state
- config show: display config with API key redacted

Update tsup.config.ts and package.json to expose cashclaw-cli binary.
Add LLMConfig.apiKeyEnvVar field so API key can be read from environment
variables at runtime instead of being stored in config.json.

- config.ts: add apiKeyEnvVar field and resolveApiKey() helper
- llm/index.ts: use resolveApiKey() instead of config.apiKey directly
- cli.ts: add --use-env-key and --api-key-env-var flags to init command

Usage (agent-gateway credentials, no key stored in config):
  cashclaw-cli init --agent-id <id> --provider anthropic --use-env-key
Implement ReAct-style claude CLI provider that spawns local `claude`
binary as subprocess, eliminating the need for ANTHROPIC_API_KEY.

- src/llm/claude-cli.ts: new provider using execFile with ReAct JSON protocol
- src/llm/index.ts: route claude-cli provider, use resolveApiKey() everywhere
- src/config.ts: add claude-cli provider type, apiKeyEnvVar field, resolveApiKey()
- src/cli.ts: full CLI entrypoint (init/start/stop/status/config show)
Add full headless operation without ANTHROPIC_API_KEY:
- claude-cli LLM provider (ReAct/subprocess pattern)
- CLI entrypoint: init/start/stop/status/config show
- PID-based daemon management
- apiKeyEnvVar config field for runtime env resolution
- config/service.yaml: cashclaw service definition
- scripts/register-service.sh: installs to ~/.agent-gateway/services.d/
- docs/service-manager.md: integration guide

Closes moltlaunch#10
feat: service registration for universal service manager
- error イベントで scheduleWsReconnect() を呼ぶのを廃止
  → ws.close() が close イベントを発火するため二重呼出しになりバックオフが加速していた
- connectWs() で古い ws を removeAllListeners + terminate してから新規作成
  → 再接続時に stale リスナーが残っていたバグを修正
- keepalive ping を 20s 間隔で追加(プロキシのアイドルタイムアウト対策)
- pong タイムアウト 10s を追加: ping 後に pong が来なければ dead connection と判定して強制再接続
- disconnectWs() でも ping/pong タイマーをクリーンアップ

Co-Authored-By: Claude <noreply@anthropic.com>
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