Commit Graph
11 Commits
Author SHA1 Message Date
dev-claudecodeandClaude Opus 4.8 97efa7f582 docs(sponsors): add 二狗 API (Ergou API) as new sponsor
- Insert 二狗 API in the middle of the sponsor table in both
  README.md and README.zh-CN.md (position 10 of 19).
- Add assets/sponsors/ergou.png (logo provided by sponsor).
- Sponsor copy and affiliate link from 二狗 API's own materials.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 10:37:15 +08:00
dev-claudecodeandClaude Opus 4.8 e2bbe5fbe6 docs(sponsors): emphasize premium accounts in VisionCoder entry
Bold 'Claude Max 200', 'GPT Pro 200', and '高级成品号 /
premium accounts' in both README.md and README.zh-CN.md
per VisionCoder's request.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 11:21:52 +08:00
dev-claudecodeandClaude Opus 4.8 c70da8733d docs(sponsors): move VisionCoder to position 6
Promote VisionCoder earlier in the sponsor table in
both README.md and README.zh-CN.md based on sustained
cooperation and product quality. RunAPI, CaMeL, and
Unity2.ai shift down one position each.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 11:16:11 +08:00
dev-claudecodeandClaude Opus 4.8 2754d715c1 docs(sponsors): update VisionCoder entry
- Switch domain to visioncoder.cn (per VisionCoder request)
- Refresh logo asset (assets/sponsors/visioncoder.png)
- Update sponsor copy to reflect current VisionCoder offerings
  (retail channels for Claude Max 200 / GPT Pro 200 premium accounts)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 10:49:56 +08:00
dev-claudecodeandClaude Opus 4.8 7915635f10 docs(sponsors): add APINEBULA as new sponsor
- Insert APINEBULA at the top of the sponsor table in both
  README.md and README.zh-CN.md (position 1).
- Add assets/sponsors/apinebula.png (logo supplied by
  APINEBULA via their Galaxy Video Bureau platform).
- Sponsor copy and registration link provided by APINEBULA.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 22:41:52 +08:00
dev-claudecodeandClaude Opus 4.8 1e0d8f7fff docs(sponsors): update unity2.ai registration link
Replace placeholder link with the affiliate-tracked
registration URL on unity2.ai's request.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 23:49:07 +08:00
dev-claudecodeandClaude Opus 4.8 5c19196825 docs(sponsors): add unity2.ai as new sponsor
- Insert unity2.ai between CaMeL and AnyRoute.io in both
  README.md and README.zh-CN.md (position 7).
- Add assets/sponsors/unity2ai.png.
- Sponsor copy and link provided by unity2.ai.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 23:32:23 +08:00
dev-claudecodeandCursor 5cf237941a fix(dingtalk): recover panic in stream loop to prevent process crash (#1390)
The upstream dingtalk-stream-sdk-go v0.9.1 has a race condition in
processLoop (client.go:161) that causes "send on closed channel" panic
after overnight idle. The fix exists in upstream PRs but is not yet
merged/released.

Add defer/recover around streamClient.Start() so the panic is caught
and the existing reconnect loop can re-establish the connection instead
of crashing the entire cc-connect process.

Closes #1390

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 07:30:20 +08:00
dev-claudecodeandCursor 809038720a fix(slack): stop chat.update once payload exceeds size limit; deliver full reply via fresh postMessage
Surfaced during v1.4.0-beta.1 QA: when an agent produced a ~7.3 KB
Markdown reply in Slack, the streaming card (#1333) silently failed
mid-stream with `msg_too_long`, then Finalize tried to chat.update the
full reply and also failed, forcing the engine onto its emergency
fallback path. The user perceived the turn as a non-streaming "one-shot
output preceded by ~30s of silence".

Root cause: Slack's `chat.update` text parameter is capped at ~4000
bytes (server-side, despite docs saying chars). The streaming card had
no size guard and Update() also swallowed errors with no log, so the
half-broken state was invisible from logs until Finalize blew up.

Fix:
- Introduce `slackUpdateMaxText = 3500` (conservative; leaves headroom
  for multi-byte CJK content where Go's len() overshoots Slack's limit).
- `Update()`: once rendered exceeds the limit, silently skip the
  chat.update tick (leave the streaming card at its last fitting
  snapshot) and emit a Debug log instead of staying invisible.
- `Update()`: also Debug-log transient render errors (previously
  swallowed entirely).
- `Finalize()`: when the final payload exceeds the limit AND a card has
  already been posted, deliver the full reply via a *fresh*
  chat.postMessage (which has a 40 KB ceiling), so the engine sees
  success and skips its duplicate-fallback emission. The partial
  streaming card stays visible above the new full-content message.
- Extract `postFresh()` helper to share the postMessage logic between
  the lazy first-post path and the new overflow path.

Tests:
- `TestStreamingCard_FinalizeFallsBackToFreshPostOnOversize`: oversized
  Finalize must NOT touch chat.update and must postMessage the full
  payload (and not mark the card failed).
- `TestStreamingCard_UpdateSkipsOversizedPayload`: oversized Update
  tick must silently no-op (no chat.update call).

Net behaviour:
- Short replies (< ~3500 B mrkdwn): unchanged — chat.update streaming
  keeps working as #1333 intended.
- Long replies: no more `msg_too_long` errors, no more duplicate
  fallback messages from the engine. UX is "partial streaming card +
  one final full-content message" instead of "broken card + duplicate
  full-content message".

Closes the third user-visible bug surfaced during v1.4.0-beta.1 QA
pairing (after #1395 image batch window default and the nav.cron i18n
miss).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-22 22:14:26 +08:00
dev-claudecodeandCursor d6c0053a01 fix(i18n): translate nav.cron for ko, ja, es (was leaking raw "Cron")
#1343 added Korean (ko.json) but missed the nav.cron key on the left
sidebar — surfaced during v1.4.0-beta.1 QA pairing (owner spotted the
raw "Cron" label while sanity-checking the Korean UI). Same key was
also missing in ja.json (regressed earlier) and es.json. All three
files already carried the correct translation at `settings.cron`
(line 297) so this just propagates it to the nav label:

- ko: 예약 작업
- ja: スケジュールジョブ
- es: Tareas programadas

en, zh, zh-TW already correct.

No code paths or types touched; only locale string values.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-22 20:49:31 +08:00
dev-claudecodeandCursor 54a3195f2c fix(feishu): make image batch coalesce window configurable; bump default 150ms→500ms
The hardcoded 150ms `imageBatchWindow` introduced in #1395 turned out to be
too narrow for real-world Feishu mobile sending behaviour. In QA we
observed ~330ms between consecutive image sends from the mobile client
when a user taps "send" repeatedly, which exceeds 150ms and defeats the
coalescing logic — each image was dispatched as its own turn, and turns
after the first hit the engine's "busy" guard and returned the
"will process after the current task finishes" notice.

Changes:
- Promote `imageBatchWindow` from a package const to a per-Platform field
  populated from a new platform option `image_batch_window_ms`.
- Bump the default from 150ms to 500ms based on observed mobile send
  intervals.
- Add `batchWindow()` helper so zero-initialised Platforms (constructed
  directly in tests) still fall back to the default and never schedule a
  zero-duration timer.
- Validate the option: reject negative or non-numeric values.
- Document the new knob in `config.example.toml` and `docs/feishu.md`.
- Add `TestNewPlatform_ImageBatchWindow` covering default, custom, zero
  (fallback) and validation paths; update existing batch tests to read
  the effective window via `batchWindow()`.

Operators who need a longer or shorter window can override per-platform:
  [projects.platforms.options]
  image_batch_window_ms = 800

Closes follow-up surfaced during v1.4.0-beta.1 QA pairing.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-22 19:33:37 +08:00