mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-18 08:14:39 +00:00
fix(vision): fix Lark inline image parsing and MCP bridge read_image (#396)
* fix(vision): fix Lark inline image parsing and MCP bridge read_image
Two fixes for image reading through Lark channel with claude-cli provider:
1. Lark post messages use flat format {"content":[[...]]} but resolvePostElements
only handled language-wrapped format {"zh_cn":{"content":[...]}}. Now checks
flat format first, and skips non-map values in fallback iteration.
2. read_image tool failed via MCP bridge because bridge creates fresh HTTP context
losing WithMediaImages. Fix: enrich <media:image> tags with path attribute
(like documents), pass workspace through X-Workspace bridge header with HMAC,
so read_image can load images from disk via path parameter.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(security): add HMAC backward compat and guard workspace injection
- VerifyBridgeContext falls back to old signature format (without workspace)
for sessions with pre-existing MCP configs, preventing 403 on server restart
- Workspace context injection now requires agent context (agentID/userID)
to prevent unauthenticated path injection bypassing HMAC
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: viettranx <viettranx@gmail.com>
This commit is contained in:
7 files changed
+70
-31
No files matched your search
@@ -100,13 +100,21 @@ func parseMessageContent(rawContent, messageType string) string {
|
||||
}
|
||||
|
||||
// resolvePostElements extracts the flattened element list from a Lark post message JSON.
|
||||
// Handles language variant lookup (zh_cn → en_us → any first key).
|
||||
// Handles two formats:
|
||||
// 1. Language-wrapped: {"zh_cn": {"title":"...", "content": [[...]]}}
|
||||
// 2. Flat (no language key): {"title":"...", "content": [[...]]}
|
||||
func resolvePostElements(rawContent string) []any {
|
||||
var post map[string]any
|
||||
if err := json.Unmarshal([]byte(rawContent), &post); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Format 2: flat — "content" at top level (no language wrapper).
|
||||
if contentArr, ok := post["content"].([]any); ok {
|
||||
return contentArr
|
||||
}
|
||||
|
||||
// Format 1: language-wrapped — try known locales, then first map value.
|
||||
var langContent any
|
||||
for _, lang := range []string{"zh_cn", "en_us"} {
|
||||
if lc, ok := post[lang]; ok {
|
||||
@@ -116,8 +124,10 @@ func resolvePostElements(rawContent string) []any {
|
||||
}
|
||||
if langContent == nil {
|
||||
for _, v := range post {
|
||||
langContent = v
|
||||
break
|
||||
if _, ok := v.(map[string]any); ok {
|
||||
langContent = v
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if langContent == nil {
|
||||
|
||||
Reference in new issue
Block a user