Files
OpenViking/sdk/go/helpers.go
T
9eac8a6d3d feat(sdk): sync go/ts/python SDKs with server find/search, recall, an… (#3737)
* feat(sdk): sync go/ts/python SDKs with server find/search, recall, and admin changes

Server-side changes recently landed that the language SDKs had drifted from:

- find/search results now return `tags` and no longer return
  `category`/`match_reason`/`relations`/`overview` (#3730). Go's strict
  struct was the only one broken; update MatchedContext accordingly.
- new admin endpoints for agent-evolution and per-account settings (#3695).
- public `search/recall` endpoint was missing from all SDKs.

Changes:
- python: add `level`/`since`/`until`/`time_field` to find/search; add an
  `extra` escape hatch to find/search/add_resource/write/batch_write so new
  server fields can be passed without an SDK bump (only forwarded when set,
  preserving `level=0`); add `recall` and the four admin methods.
- go: fix MatchedContext (add Tags, drop removed fields), add Recall and the
  four admin methods.
- typescript: type MatchedContext/FindResult, add RecallOptions, add `recall`
  and the four admin methods.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>

feat(sdk): unify options APIs and sync latest server interfaces

- migrate complex Python SDK calls to typed options dictionaries
- add dedicated context search and consistent extra-field handling
- align Go and TypeScript options with omission-aware serialization
- support session config, event tags, Agent Evolution date filters,
  OpenViking Assets, batch write, downloads, and create_parent
- refresh SDK tests and examples across all three languages

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>

fix(sdk): address options API review findings

- fix Go session extra merging and Python message precedence
- adapt LangChain calls to the Python options API
- migrate repository examples, tests, and documentation

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>

fix(sdk): complete options migration and message parity

- migrate remaining Python SDK benchmarks to options dictionaries
- normalize empty parts consistently for single and batch messages
- add regression guards for repository SDK call sites

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>

fix(sdk): align reindex options after main rebase

- preserve reindex tags in Python typed options
- add reindex extra support for Go and TypeScript
- reject official fields passed through extra across SDKs

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>

feat(sdk): support legacy keyword options

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>

docs(sdk): use explicit Python SDK arguments

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>

fix(sdk): support set tags extra options

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>

fix(sdk): expose Go add resource options

Expose AddType and ProcessingMode through Go AddResourceOptions and serialize them to the resources API. Add a regression test covering the resulting request payload.

Co-authored-by: TRAE CLI <noreply@bytedance.com>
Co-authored-by: TRAE CLI <traecli@bytedance.com>

feat(sdk): flatten core Python client options

Co-authored-by: TRAE CLI <traecli@bytedance.com>

docs(sdk): align Python examples with flattened options

Co-authored-by: TRAE CLI <traecli@bytedance.com>

fix(sdk): preserve core API compatibility

Co-authored-by: TRAE CLI <traecli@bytedance.com>

refactor(python-sdk): move resource hints to options

Co-authored-by: TRAE CLI <traecli@bytedance.com>

fix(sdk): align resource option callers

Co-authored-by: TRAE CLI <traecli@bytedance.com>

test(sdk): cover recursive reindex forwarding

Co-authored-by: TRAE CLI <traecli@bytedance.com>

fix(sdk): preserve Go options compatibility

Co-authored-by: TRAE CLI <traecli@bytedance.com>

feat(python-sdk): expose message peer id

Co-authored-by: TRAE CLI <traecli@bytedance.com>

test(python-sdk): consolidate options coverage

Co-authored-by: TRAE CLI <traecli@bytedance.com>

feat(python-sdk): add parts and flatten image search

Co-authored-by: TRAE CLI <traecli@bytedance.com>

* docs(sdk): align Python call examples

Co-authored-by: TRAE CLI <traecli@bytedance.com>

---------

Co-authored-by: TRAE CLI <traecli@bytedance.com>
Co-authored-by: Qin Haojie <qinhaojie.exe@bytedance.com>
2026-08-24 14:09:11 +08:00

173 lines
3.7 KiB
Go

package openviking
import (
"encoding/base64"
"fmt"
"mime"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
)
func setString(m map[string]any, key, value string) {
if value != "" {
m[key] = value
}
}
func setAny(m map[string]any, key string, value any) {
if value != nil {
m[key] = value
}
}
func setQueryString(values url.Values, key, value string) {
if value != "" {
values.Set(key, value)
}
}
// setQueryAny mirrors setAny for query parameters: it sets key only when value
// is non-nil, so an unset optional (e.g. a skill TargetURI) is omitted entirely.
func setQueryAny(values url.Values, key string, value any) {
if value == nil {
return
}
if s, ok := value.(string); ok {
values.Set(key, s)
return
}
values.Set(key, fmt.Sprint(value))
}
func setFloatPtr(m map[string]any, key string, value *float64) {
if value != nil {
m[key] = *value
}
}
func mergeExtra(payload map[string]any, extra map[string]any) error {
return mergeExtraProtected(payload, extra)
}
func mergeExtraProtected(
payload map[string]any,
extra map[string]any,
protected ...string,
) error {
protectedFields := make(map[string]struct{}, len(protected))
for _, key := range protected {
protectedFields[key] = struct{}{}
}
for key, value := range extra {
if _, exists := payload[key]; exists {
return fmt.Errorf("openviking: extra cannot override %q", key)
}
if _, exists := protectedFields[key]; exists {
return fmt.Errorf("openviking: extra cannot override %q", key)
}
if value != nil {
payload[key] = value
}
}
return nil
}
func boolValue(ptr *bool, fallback bool) bool {
if ptr == nil {
return fallback
}
return *ptr
}
// String returns a string pointer for request fields that must distinguish empty from omitted.
func String(s string) *string {
return &s
}
// Bool returns a bool pointer for optional request fields.
func Bool(v bool) *bool {
return &v
}
// Int returns an int pointer for optional request fields.
func Int(v int) *int {
return &v
}
// Float64 returns a float64 pointer for optional request fields.
func Float64(v float64) *float64 {
return &v
}
// Map returns a map pointer for request fields that distinguish null from omitted.
func Map(v map[string]any) *map[string]any {
return &v
}
func queryBool(values url.Values, key string, value bool) {
values.Set(key, strconv.FormatBool(value))
}
func queryInt(values url.Values, key string, value int) {
values.Set(key, strconv.Itoa(value))
}
func queryFloat(values url.Values, key string, value float64) {
values.Set(key, strconv.FormatFloat(value, 'f', -1, 64))
}
func normalizeTarget(target any) any {
switch v := target.(type) {
case nil:
return ""
case string:
if v == "" {
return ""
}
return NormalizeURI(v)
case []string:
uris := make([]string, 0, len(v))
for _, uri := range v {
if uri == "" {
uris = append(uris, uri)
} else {
uris = append(uris, NormalizeURI(uri))
}
}
return uris
default:
return v
}
}
func normalizeImageInput(image string) (string, error) {
if image == "" || strings.HasPrefix(image, "data:image/") ||
strings.HasPrefix(image, "http://") ||
strings.HasPrefix(image, "https://") ||
strings.HasPrefix(image, "viking://") {
return image, nil
}
info, err := os.Stat(image)
if err != nil {
if os.IsNotExist(err) {
return image, nil
}
return "", err
}
if info.IsDir() {
return image, nil
}
data, err := os.ReadFile(image)
if err != nil {
return "", err
}
mimeType := mime.TypeByExtension(strings.ToLower(filepath.Ext(image)))
if mimeType == "" || !strings.HasPrefix(mimeType, "image/") {
mimeType = "image/png"
}
return fmt.Sprintf("data:%s;base64,%s", mimeType, base64.StdEncoding.EncodeToString(data)), nil
}