成品服务端的运行期(C# AguiHost;keel server-http.ss N3):run 归服务端驱动,连接只是订阅者。
run 本身由 clj-agent-agui 的 runtime 跑(会话注册表、取消、HITL 都在那边);这里给每台经 /run 起的 run 挂一只泵
(一个 runtime 订阅):把中立事件编成 AG-UI 帧,进帧环(给 /connect,见 im.ttalk.agent.server.agui.replay)与直连队列
(给起 run 的那条连接),喂线程存储的 :record 钩子。⚠️ 断连 ≠ 按停(刷新也是断连,而刷新正是 /connect 要救的场景);
按停的正门是 /stop/:threadId。
选项(C# AguiRegistryOptions 里服务端用得上的那几格 + AguiServerOptions):
:version 进 /info(缺省 "0.0.0")
:origin-allowed Origin 白名单谓词;缺省 nil = 拒(带 Origin 的请求 403)。im.ttalk.agent.server.agui.http/origin-allow
:credentials? 发 Access-Control-Allow-Credentials: true
:allow-headers 宿主自己的请求头,并进预检的 Allow-Headers
:a2ui? :open-generative-ui? /info 的两格布尔
:thread-store 线程存储:六槽 map 或 clj-agent-agui 的 ThreadStore(见 im.ttalk.agent.server.agui.thread-store);给了才有 /threads*
:heartbeat-ms SSE 心跳(缺省 15000;0 = 关)。⚠️ 不是可有可无:空闲超时的代理会把不出声的流掐掉;JVM 上它还是发现断连的唯一途径
:heartbeat-frame (fn [] 字节);缺省注释帧 : clj-agent-alive。/run、/connect、/suggest 的流都用它
:replay-max-bytes 帧环一轮的字节上限(缺省 4 MiB;超了 ⇒ 这一轮 /connect 回空流)
:replay-keep-ms 跑完之后留多久给迟到的 /connect(缺省 5 分钟)
:replay-max-threads 帧环最多几条线程(缺省 256)
:replay? 帧环攒不攒(缺省 true;false ⇒ /connect 对任何线程 200 空流,/run 照旧)
:orphan-cancel-ms 最后一个订阅者走了之后过这么久没人来就按停(原因 :orphan;缺省 0 = 关)
:max-body-bytes 请求体上限(缺省 16 MiB;超了 413)
:now (fn [] ms),可注入
:info 其余交给 clj-agent-agui codec/run-info 的能力位(:multimodal :parallel-tools? :state? …)
:input-transform 入站插件的缺省值(条目里给了就以条目为准;见 im.ttalk.agent.server.agui 的注册表条目键)
:mcp-proxy MCP Apps 前端代理的缺省值(同上)
:agents 按 agent 注入外部驱动的缺省值(routes 也能再并一份;键同下面的注册表条目键)
同线程上一轮还在飞时再来 /run(C# AguiRegistryOptions.ConcurrentRun)由那台 agent 的 runtime 决定:
rt/runtime 的 :on-concurrent :reject(缺省,⇒ 409 thread_running)或 :supersede(旧的以 :superseded 取消)。
成品服务端的运行期(C# AguiHost;keel server-http.ss N3):**run 归服务端驱动,连接只是订阅者**。 run 本身由 clj-agent-agui 的 runtime 跑(会话注册表、取消、HITL 都在那边);这里给每台经 `/run` 起的 run 挂一只**泵** (一个 runtime 订阅):把中立事件编成 AG-UI 帧,进帧环(给 `/connect`,见 im.ttalk.agent.server.agui.replay)与直连队列 (给起 run 的那条连接),喂线程存储的 :record 钩子。⚠️ 断连 ≠ 按停(刷新也是断连,而刷新正是 `/connect` 要救的场景); 按停的正门是 `/stop/:threadId`。 选项(C# AguiRegistryOptions 里服务端用得上的那几格 + AguiServerOptions): :version 进 /info(缺省 "0.0.0") :origin-allowed Origin 白名单谓词;缺省 nil = **拒**(带 Origin 的请求 403)。im.ttalk.agent.server.agui.http/origin-allow :credentials? 发 Access-Control-Allow-Credentials: true :allow-headers 宿主自己的请求头,并进预检的 Allow-Headers :a2ui? :open-generative-ui? /info 的两格布尔 :thread-store 线程存储:六槽 map 或 clj-agent-agui 的 ThreadStore(见 im.ttalk.agent.server.agui.thread-store);给了才有 /threads* :heartbeat-ms SSE 心跳(缺省 15000;0 = 关)。⚠️ 不是可有可无:空闲超时的代理会把不出声的流掐掉;JVM 上它还是发现断连的唯一途径 :heartbeat-frame (fn [] 字节);缺省注释帧 `: clj-agent-alive`。/run、/connect、/suggest 的流都用它 :replay-max-bytes 帧环一轮的字节上限(缺省 4 MiB;超了 ⇒ 这一轮 /connect 回空流) :replay-keep-ms 跑完之后留多久给迟到的 /connect(缺省 5 分钟) :replay-max-threads 帧环最多几条线程(缺省 256) :replay? 帧环攒不攒(缺省 true;false ⇒ /connect 对任何线程 200 空流,/run 照旧) :orphan-cancel-ms 最后一个订阅者走了之后过这么久没人来就按停(原因 :orphan;缺省 0 = 关) :max-body-bytes 请求体上限(缺省 16 MiB;超了 413) :now (fn [] ms),可注入 :info 其余交给 clj-agent-agui `codec/run-info` 的能力位(:multimodal :parallel-tools? :state? …) :input-transform 入站插件的缺省值(条目里给了就以条目为准;见 im.ttalk.agent.server.agui 的注册表条目键) :mcp-proxy MCP Apps 前端代理的缺省值(同上) :agents 按 agent 注入外部驱动的缺省值(routes 也能再并一份;键同下面的注册表条目键) 同线程上一轮还在飞时再来 `/run`(C# AguiRegistryOptions.ConcurrentRun)由那台 agent 的 runtime 决定: `rt/runtime` 的 `:on-concurrent :reject`(缺省,⇒ 409 thread_running)或 `:supersede`(旧的以 :superseded 取消)。
(cancel-all! h)停机:按停所有在飞的 run(原因 :shutdown)。⚠️ suggest 停不了(clj-agent-agui 的 run-detached! 不交出取消令牌),流随停机关掉。
停机:按停所有在飞的 run(原因 :shutdown)。⚠️ suggest 停不了(clj-agent-agui 的 run-detached! 不交出取消令牌),流随停机关掉。
(external-frame! h tid frame)外部源交付一条 AG-UI 事件 / 已编帧:进帧环,回编好的 SSE 字节。终端事件也由这里判——交付方不再另发收场信号。
外部源交付一条 AG-UI 事件 / 已编帧:进帧环,回编好的 SSE 字节。终端事件也由这里判——交付方不再另发收场信号。
(frame-of agui)AG-UI 事件 ⇒ 一帧 SSE(data: {json}\n\n,不带 id: —— 同 C#)。
AG-UI 事件 ⇒ 一帧 SSE(`data: {json}\n\n`,不带 id: —— 同 C#)。
(host reg)(host reg opts)建运行期。reg = clj-agent-agui 的 registry/registry(条目::id :runtime,可选 :description :suggest? :agent-spec
:memory :server-tool-names :stop …)。心跳为负 ⇒ agui-server/negative-heartbeat;:allow-headers 里有空串 ⇒
agui-registry/allow-headers-empty-string;线程存储一个槽都没有 ⇒ agui-registry/thread-store-no-slot。
建运行期。`reg` = clj-agent-agui 的 `registry/registry`(条目::id :runtime,可选 :description :suggest? :agent-spec :memory :server-tool-names :stop …)。心跳为负 ⇒ `agui-server/negative-heartbeat`;:allow-headers 里有空串 ⇒ `agui-registry/allow-headers-empty-string`;线程存储一个槽都没有 ⇒ `agui-registry/thread-store-no-slot`。
(next-change d)下一次「有新帧 / 收场」时完成的 future。⚠️ 先取它再读帧(否则读完到取之间的那一跳会漏等)。
下一次「有新帧 / 收场」时完成的 future。⚠️ 先取它再读帧(否则读完到取之间的那一跳会漏等)。
(poll-direct d ms)直连队列取一帧:字节 / ::end(收场)/ nil(ms 内没有)。
直连队列取一帧:字节 / `::end`(收场)/ nil(`ms` 内没有)。
(publish-frame! h tid frames)把一帧编好的 SSE 字节交给帧环(外部驱动写入口)。开跑的内置泵先建了环就接着攒;没有就开一条。
把一帧编好的 SSE 字节交给帧环(外部驱动写入口)。开跑的内置泵先建了环就接着攒;没有就开一条。
(run h tid)这条线程上经 /run 起的、在飞的那台:{:thread-id :run-id(客户端给的):runtime-run-id :agent-id};没有 ⇒ nil(C# Registry.Run)。
这条线程上经 /run 起的、在飞的那台:{:thread-id :run-id(客户端给的):runtime-run-id :agent-id};没有 ⇒ nil(C# Registry.Run)。
(start-drive! h {:keys [entry thread-id since] :as args})起泵:帧环 begin、登记、订阅 runtime(从 start-run! 给的 :since 水位起,一条不漏)。 args::entry(注册表条目):thread-id :run-id(runtime 的):client-run-id :since :input(RunAgentInput)。
起泵:帧环 begin、登记、订阅 runtime(从 start-run! 给的 :since 水位起,一条不漏)。 args::entry(注册表条目):thread-id :run-id(runtime 的):client-run-id :since :input(RunAgentInput)。
(track-suggest! h done)记一台 suggest(无状态,不进注册表、不进帧环;只为 in-flight)。done = run-detached! 的 future。
记一台 suggest(无状态,不进注册表、不进帧环;只为 `in-flight`)。`done` = run-detached! 的 future。
(unsubscribe! h d direct?)退订(⛔ 不按停);direct? = 起 run 的那条连接走了 ⇒ 直连队列不再攒帧。最后一个走了且开了 :orphan-cancel-ms ⇒ 到点没人回来就按停。
退订(⛔ 不按停);`direct?` = 起 run 的那条连接走了 ⇒ 直连队列不再攒帧。最后一个走了且开了 :orphan-cancel-ms ⇒ 到点没人回来就按停。
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 |