provider 的 HTTP 门面——仅非流式请求/响应。传输在 im.ttalk.http(clj-http,
designs/http-module.md);本 ns 只留 provider 的约定:JSON 编解码、{:status 0 :error …}(IO 失败不抛)、
:success?、canonical error 映射(response->error / success-body / check-model!)。
公开函数的签名与返回形状自 0.4.0 起未变。
流式(SSE)已迁移到 im.ttalk.agent.provider.http.stream-client(java.net.http 真增量,
见 docs/streaming-async-design.md);本模块不再提供流式 API。
用法: (require '[im.ttalk.agent.provider.http.client :as http]) (http/get "https://api.example.com/users") (http/post "https://api.example.com/users" :body {:name "张三"}) (http/post-deferred url :body {...}) ; 异步:返回 deferred<响应 map> (http/post-async url callback :body {...}) ; 异步回调(低层,形状同上) (http/request :get url :async? true :callback (fn [resp] ...))
provider 的 HTTP 门面——**仅非流式**请求/响应。传输在 `im.ttalk.http`(clj-http,
designs/http-module.md);本 ns 只留 provider 的约定:JSON 编解码、`{:status 0 :error …}`(IO 失败不抛)、
`:success?`、canonical error 映射(`response->error` / `success-body` / `check-model!`)。
公开函数的签名与返回形状自 0.4.0 起未变。
流式(SSE)已迁移到 `im.ttalk.agent.provider.http.stream-client`(java.net.http 真增量,
见 docs/streaming-async-design.md);本模块不再提供流式 API。
用法:
(require '[im.ttalk.agent.provider.http.client :as http])
(http/get "https://api.example.com/users")
(http/post "https://api.example.com/users" :body {:name "张三"})
(http/post-deferred url :body {...}) ; 异步:返回 deferred<响应 map>
(http/post-async url callback :body {...}) ; 异步回调(低层,形状同上)
(http/request :get url :async? true :callback (fn [resp] ...))(build-query-string params)将 map 转换为查询字符串
示例: (build-query-string {:q "test" :page 1}) ; => "q=test&page=1"
将 map 转换为查询字符串
示例:
(build-query-string {:q "test" :page 1})
; => "q=test&page=1"(build-url base-url params)构建带查询参数的 URL
示例: (build-url "https://api.example.com/search" {:q "test"}) ; => "https://api.example.com/search?q=test"
构建带查询参数的 URL
示例:
(build-url "https://api.example.com/search" {:q "test"})
; => "https://api.example.com/search?q=test"(check-model! provider requested answered)回包模型名核对(opt-in,designs/provider-reliability.md §4):requested 与 answered 都非空且不相等
→ 抛 {:type :provider-error :retryable? false :code :model-mismatch}。
回包模型名核对(opt-in,designs/provider-reliability.md §4):requested 与 answered 都非空且不相等
→ 抛 `{:type :provider-error :retryable? false :code :model-mismatch}`。默认共享 HttpClient(delay)——就是 im.ttalk.http/default-client:HTTP/1.1、虚拟线程
executor、connect 30s。保留这个 var 是因为宿主可能 @default-client 拿它。
默认共享 HttpClient(delay)——就是 `im.ttalk.http/default-client`:HTTP/1.1、虚拟线程 executor、connect 30s。保留这个 var 是因为宿主可能 `@default-client` 拿它。
(delete url
&
{:or {timeout im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers query-params timeout]})同步 DELETE 请求
同步 DELETE 请求
(delete-async url
callback
&
{:or {timeout
im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers query-params timeout]})异步 DELETE 请求
异步 DELETE 请求
(get url
&
{:or {timeout im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers query-params timeout]})同步 GET 请求
同步 GET 请求
(get-async url
callback
&
{:or {timeout im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers query-params timeout]})异步 GET 请求
异步 GET 请求
(patch url
&
{:or {timeout im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers body query-params timeout]})同步 PATCH 请求
同步 PATCH 请求
(patch-async url
callback
&
{:or {timeout
im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers body query-params timeout]})异步 PATCH 请求
异步 PATCH 请求
(post url
&
{:or {timeout im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers body query-params timeout]})同步 POST 请求
同步 POST 请求
(post-async url
callback
&
{:or {timeout im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers body query-params timeout]})异步 POST 请求
异步 POST 请求
(post-deferred url & {:as opts})异步 POST,返回 deferred<响应 map>(形状同同步 post)。
异步 POST,返回 deferred<响应 map>(形状同同步 `post`)。
(post-json url body)(post-json url body opts)POST JSON 请求(简化版)
POST JSON 请求(简化版)
(put url
&
{:or {timeout im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers body query-params timeout]})同步 PUT 请求
同步 PUT 请求
(put-async url
callback
&
{:or {timeout im.ttalk.agent.provider.http.client/*default-timeout*}
:keys [headers body query-params timeout]})异步 PUT 请求
异步 PUT 请求
(request method
url
&
{:keys [async? callback headers body query-params timeout as]
:or {async? false timeout *default-timeout* as :json}
:as opts})发送 HTTP 请求
发送 HTTP 请求
(request-deferred
method
url
&
{:keys [timeout as] :or {timeout *default-timeout* as :json} :as opts})request 的异步孪生:不阻塞,返回 deferred<响应 map>。
响应 map 的形状与同步 request 逐字相同({:status :headers :body :success?}
/ IO 失败时 {:status 0 :error … :success? false})——形状对齐是刻意的:
provider 的异步路径因此能与同步路径共用后处理(:success? 判定、
response->error、限流头解析),不必另写一条更短的路。仓库里旧的
xxx-call-async 旁路正是栽在没有这条对齐上(docs/async-chat-model-design.md §0)。
非 IO 异常(如响应体解析失败)原样落 error channel,与同步版一致 (同步版也不吞它们)。
`request` 的异步孪生:**不阻塞**,返回 deferred<响应 map>。
**响应 map 的形状与同步 `request` 逐字相同**(`{:status :headers :body :success?}`
/ IO 失败时 `{:status 0 :error … :success? false}`)——形状对齐是刻意的:
provider 的异步路径因此能与同步路径**共用**后处理(`:success?` 判定、
`response->error`、限流头解析),不必另写一条更短的路。仓库里旧的
`xxx-call-async` 旁路正是栽在没有这条对齐上(docs/async-chat-model-design.md §0)。
非 IO 异常(如响应体解析失败)**原样落 error channel**,与同步版一致
(同步版也不吞它们)。(request-id headers)从响应头提取请求 ID(用于排障 / 上报),大小写无关
Anthropic 用 request-id,OpenAI 用 x-request-id。回字符串(此前直接 get,拿到的是
java.net.http 的 List)。
从响应头提取请求 ID(用于排障 / 上报),大小写无关 Anthropic 用 request-id,OpenAI 用 x-request-id。回**字符串**(此前直接 `get`,拿到的是 java.net.http 的 List)。
(response->error response provider)把失败的 HTTP 响应(本模块 request/post 返回的 map)转为 canonical error (D5:ex-info data 即 canonical error map;保留 body/headers/request-id 于 :context 供排查)。
之前 openai_compat / anthropic / dashscope 各自维护同一逻辑,现统一于此;流式非 2xx
(stream-client)也走这里。
provider.common.business-codes/refine-error):
429 + insufficient_quota → :quota-exhausted-error(不可重试)、400 + prompt is too long →
:context-overflow-error、智谱 1309 → 欠费……(designs/provider-reliability.md §1)Retry-After 响应头解析成 :retry-after-ms:解析 HTTP 头是 provider 边界的事,
重试在 ChatModel(core,不认识 HTTP)。没有头时扫正文里的 try again in 1.5s。把失败的 HTTP 响应(本模块 request/post 返回的 map)转为 canonical error (D5:ex-info data 即 canonical error map;保留 body/headers/request-id 于 :context 供排查)。 之前 openai_compat / anthropic / dashscope 各自维护同一逻辑,现统一于此;流式非 2xx (`stream-client`)也走这里。 - 状态码初判之后**过厂商业务码表**(`provider.common.business-codes/refine-error`): 429 + insufficient_quota → :quota-exhausted-error(不可重试)、400 + prompt is too long → :context-overflow-error、智谱 1309 → 欠费……(designs/provider-reliability.md §1) - 把 `Retry-After` 响应头解析成 `:retry-after-ms`:**解析 HTTP 头是 provider 边界的事**, 重试在 ChatModel(core,不认识 HTTP)。没有头时扫正文里的 `try again in 1.5s`。
(success-body response provider)(success-body response provider {:keys [check-model? model]})成功(2xx)响应 → 原始响应体,统一做三件事(openai 兼容 / anthropic / responses 的同步与异步路径共用):
base_resp.status_code ≠ 0)→ 抛 canonical error(§1);{:check-model? true :model "请求的模型"} 时核对 (:model body)(§4);:rate-limit 挂到响应体上(§6;body 是 map 时)。成功(2xx)响应 → 原始响应体,统一做三件事(openai 兼容 / anthropic / responses 的同步与异步路径共用):
1. HTTP 200 里的业务错(MiniMax / 智谱 `base_resp.status_code ≠ 0`)→ 抛 canonical error(§1);
2. opts `{:check-model? true :model "请求的模型"}` 时核对 `(:model body)`(§4);
3. 响应头里的限流信息折成 `:rate-limit` 挂到响应体上(§6;body 是 map 时)。(url-encode s)URL 编码字符串
示例: (url-encode "hello world") ; => "hello+world"
URL 编码字符串 示例: (url-encode "hello world") ; => "hello+world"
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |