// Package io implements the built-in I/O and network tools for Cyrene v2 // (DevDocs/design/09-插件生态.md). It exposes file, image-crop, document-read, http, // web-search, web-fetch and knowledge as pkg/plugins/sdk.Tool values, wired to the // process-internal config, logger and runtime/memory retriever. // // Build the full configured tool set with New(cfg, opts...). Tools() and // Register(reg) are convenience wrappers that use platform defaults; production // wiring should call New(cfg, opts...) so the tools honor the real DataDir, // search endpoint and knowledge retriever. // // Security constraints // // - file: every path is cleaned and validated to stay inside the configured // data directory or an explicit whitelist; ".." traversal and symlink escape // are rejected; reads and writes are size-capped. // - image-crop: crops a region out of a large image so the agent can read it in // parts (an image service downsamples big images); path sources go through the // file sandbox, URL sources through the SSRF guard, and the returned data URI // is size-capped. // - http: GET/POST only, timeouts, response truncation and SSRF protection // (loopback/private/link-local addresses and localhost are refused unless // the host is on an explicit allowlist). // - web-search: queries the configured search **provider** through the registry in // plugins/tools/io/search (searxng / zhipu / aliyun_iqs / bocha / volcengine / // baidu_qianfan; one provider per file, design/27 §4). The model sees exactly one // tool whose schema never changes with the backend. A configured fallback chain is // tried in order, and only an *unavailable* provider (missing key, auth / rate // limit / quota / network failure) advances the chain — an empty result set does // not, and it is reported as "no results" rather than as success. The result names // the provider that actually answered. When no usable backend is configured the // composition root passes WithoutSearch, so the tool is not registered at all — the // model never sees a tool that could only error. Provider endpoints are operator // configuration (the model only supplies the query), hence their hosts are trusted // by this tool alone: a loopback fallback endpoint stays reachable without widening // the shared http/web-fetch allowlist. API keys never reach logs, results or prompts. // - web-fetch: size- and content-type-limited readable text extraction. // - knowledge: RAG lookup over the runtime memory retriever; a clear message // when no knowledge base is configured. // // # File-level mutual exclusion // // The two tools that touch files declare the file each call will touch // (tool.FileTargeter, implemented in file_targets.go): file declares read for // read/list/search and write for write; image-crop declares a read when its image // is a local path. When another in-flight parallel leg is already operating on that // same file, the call returns tool.ErrFileBusy with the file's state instead of // running or queueing; two reads of one file still run in parallel, and calls that // cannot touch a file (a sandbox-rejected path, an HTTP or data: URI source) declare // nothing and keep their previous behavior. // // All tools are safe for concurrent use, as required by sdk.Tool. package io