Liking cljdoc? Tell your friends :D

im.ttalk.agent.tools

clj-agent-tools 门面:一行拿到绑定好工作区的编码类工具(设计:designs/tools-module.md)。

(require '[im.ttalk.agent.tools :as tools]) (def ws (tools/workspace {:root "/abs/repo"})) (tools/workspace-tools ws {:groups #{:files :edit}}) ;; ⇒ [#'read_file …] 放进 :tools

工具是 deftool 定义的 var;workspace-tools 为每个工具造一个匿名 var,根值是 (fn [args] (binding [ws/*workspace* ws] (f args))),元数据沿用 deftool 的(可按实例覆盖 :tool/sensitive 与 description)。绑定发生在工具函数体内部——与哪个引擎 / 线程执行它无关 (design-principles §3)。用 var 而不用内联工具 map,是因为 :sensitive 只对 var 生效 (tool_registry/build-func-def),审批 filter 与 :on-pause 才看得见。

组(缺省只开只读的 :files;写、删、跑进程、出网都要显式开):

  • :files read_file list_dir glob grep
  • :edit write_file edit_file apply_patch(敏感、串行)
  • :delete delete_path(敏感、串行)
  • :exec exec exec_command write_stdin(敏感、串行;必须给 {:exec {:backend ..}})
  • :web-fetch web_fetch(缺省敏感,{:web-fetch {:sensitive false}} 可关)
  • :skill skill({:skills {:dirs [..]}})
  • :notes notes_list notes_read notes_write(必须给 {:notes store};{:notes-write-sensitive? true} 让写走审批)
clj-agent-tools 门面:一行拿到绑定好工作区的编码类工具(设计:designs/tools-module.md)。

(require '[im.ttalk.agent.tools :as tools])
(def ws (tools/workspace {:root "/abs/repo"}))
(tools/workspace-tools ws {:groups #{:files :edit}})   ;; ⇒ [#'read_file …] 放进 :tools

工具是 deftool 定义的 var;`workspace-tools` 为每个工具造一个**匿名 var**,根值是
`(fn [args] (binding [ws/*workspace* ws] (f args)))`,元数据沿用 deftool 的(可按实例覆盖
`:tool/sensitive` 与 description)。绑定发生在工具函数体内部——与哪个引擎 / 线程执行它无关
(design-principles §3)。用 var 而不用内联工具 map,是因为 `:sensitive` 只对 var 生效
(tool_registry/build-func-def),审批 filter 与 :on-pause 才看得见。

组(缺省只开只读的 :files;写、删、跑进程、出网都要显式开):
- :files     read_file list_dir glob grep
- :edit      write_file edit_file apply_patch(敏感、串行)
- :delete    delete_path(敏感、串行)
- :exec      exec exec_command write_stdin(敏感、串行;必须给 {:exec {:backend ..}})
- :web-fetch web_fetch(缺省敏感,{:web-fetch {:sensitive false}} 可关)
- :skill     skill({:skills {:dirs [..]}})
- :notes     notes_list notes_read notes_write(必须给 {:notes store};{:notes-write-sensitive? true} 让写走审批)
raw docstring

im.ttalk.agent.tools.edit

edit_file(T-03;出处 Keelson EditFileTool.cs,借鉴 coxswain edit.ss):把文件里一段一字不差的 原文换成另一段。

为什么是精确原文、不是行号也不是 diff:行号会漂、改错行不报错;模型生成的 diff 常常是坏的、模糊匹配会打歪。 精确原文要么原样对上,要么什么都不发生。⚠️ 不唯一就拒(默默改第一处,模型无从察觉);要全改显式传 all。

0 次时按顺序给三种诊断(⛔ 拿诊断去做模糊匹配):① old 每行都带 read_file 的 L数字: 前缀; ② 空白归一化后能对上(附行号);③ 都不是 ⇒「先 read_file 看实际内容」。 新鲜度闸在匹配之前(建立在过期内容上的编辑可能照样对得上)。

edit_file(T-03;出处 Keelson `EditFileTool.cs`,借鉴 coxswain `edit.ss`):把文件里一段**一字不差**的
原文换成另一段。

为什么是精确原文、不是行号也不是 diff:行号会漂、改错行不报错;模型生成的 diff 常常是坏的、模糊匹配会打歪。
精确原文要么原样对上,要么什么都不发生。⚠️ 不唯一就拒(默默改第一处,模型无从察觉);要全改显式传 all。

0 次时按顺序给三种诊断(⛔ 拿诊断去做模糊匹配):① old 每行都带 read_file 的 `L数字:` 前缀;
② 空白归一化后能对上(附行号);③ 都不是 ⇒「先 read_file 看实际内容」。
新鲜度闸在匹配**之前**(建立在过期内容上的编辑可能照样对得上)。
raw docstring

im.ttalk.agent.tools.exec

进程工具(T-05):exec(单发)、exec_command / write_stdin(有状态会话)。

移植自 OpenAI Codex CLI(Apache-2.0,Copyright 2025 OpenAI;见模块根 THIRD-PARTY-NOTICES.md),经 Keelson Process/* 转写:

  • HeadTailBuffer ← codex-rs/core/src/unified_exec/head_tail_buffer.rs(头尾各半、中间丢弃并计数);
  • 单发执行 ← codex-rs/core/src/exec.rs(时限 10 s、超时退出码 124、128 + 信号、杀后排空 2 s);
  • 固定环境 ← unified_exec/process_manager.rs 的 UNIFIED_EXEC_ENV(不带 CODEX_CI);
  • 会话 ← unified_exec/{mod.rs, process_manager.rs}(yield 250–30000 ms、空轮询 ≥ 5000 ms、64 个会话、 最近 8 个不驱逐、先驱逐已退出的、\u0003 中断);
  • 结果文本 ← core/src/tools/context.rs 与 core/src/tools/mod.rs(format_exec_output_for_model)。

两个协议,宿主接沙箱的缝:

  • IExecBackend(起进程):缺省 local-backend(ProcessBuilder);argv-prefix-backend 一行把每条命令包进 bwrap … / firejail … / ssh host …。会话只经它。
  • ICommandRunner(单发跑完再返回):缺省 backend-runner;可在这里做「沙箱里失败 → 问人 → 重跑」的编排。 Keelson.Agent.Sandbox 不移植。不做 PTY(会话是管道,stdin 可写)。
进程工具(T-05):exec(单发)、exec_command / write_stdin(有状态会话)。

移植自 OpenAI Codex CLI(Apache-2.0,Copyright 2025 OpenAI;见模块根 THIRD-PARTY-NOTICES.md),经 Keelson
`Process/*` 转写:
- HeadTailBuffer ← codex-rs/core/src/unified_exec/head_tail_buffer.rs(头尾各半、中间丢弃并计数);
- 单发执行 ← codex-rs/core/src/exec.rs(时限 10 s、超时退出码 124、128 + 信号、杀后排空 2 s);
- 固定环境 ← unified_exec/process_manager.rs 的 UNIFIED_EXEC_ENV(不带 CODEX_CI);
- 会话 ← unified_exec/{mod.rs, process_manager.rs}(yield 250–30000 ms、空轮询 ≥ 5000 ms、64 个会话、
  最近 8 个不驱逐、先驱逐已退出的、\u0003 中断);
- 结果文本 ← core/src/tools/context.rs 与 core/src/tools/mod.rs(format_exec_output_for_model)。

两个协议,宿主接沙箱的缝:
- `IExecBackend`(起进程):缺省 `local-backend`(ProcessBuilder);`argv-prefix-backend` 一行把每条命令包进
  `bwrap …` / `firejail …` / `ssh host …`。会话只经它。
- `ICommandRunner`(单发跑完再返回):缺省 `backend-runner`;可在这里做「沙箱里失败 → 问人 → 重跑」的编排。
Keelson.Agent.Sandbox 不移植。不做 PTY(会话是管道,stdin 可写)。
raw docstring

im.ttalk.agent.tools.files

文件工具(T-02):read_file / list_dir / glob / grep / write_file / delete_path。

read_file / list_dir / grep 的口径翻译自 OpenAI Codex CLI(Apache-2.0,Copyright 2025 OpenAI; 见模块根 THIRD-PARTY-NOTICES.md),经 Keelson ReadFileTool.cs / ListDirTool.cs / GrepTool.cs 转写:

  • read_file:codex-rs/core/src/tools/handlers/read_file.rs(14c35a16a8^)——offset 缺省 1、limit 缺省 2000、 单行 500 字节、TAB 宽 4、行前缀 L{n}:、slice / indentation 两种模式;
  • list_dir:codex-rs/core/src/tools/handlers/list_dir.rs(70807730f5^)——offset 1、limit 25、depth 2、 条目名 500 字节、每层缩进 2 空格;
  • grep:codex-rs/core/src/tools/handlers/grep_files.rs(178c3b15b4^)——limit 100、顶 2000、按修改时间倒序。 glob 是 Keelson 新增(Codex 没有);write_file / delete_path 借鉴 coxswain(Apache-2.0)。

每个工具函数体只读 (ws/current)——工作区由 im.ttalk.agent.tools/workspace-tools 绑定。

文件工具(T-02):read_file / list_dir / glob / grep / write_file / delete_path。

read_file / list_dir / grep 的口径翻译自 OpenAI Codex CLI(Apache-2.0,Copyright 2025 OpenAI;
见模块根 THIRD-PARTY-NOTICES.md),经 Keelson `ReadFileTool.cs` / `ListDirTool.cs` / `GrepTool.cs` 转写:
- read_file:codex-rs/core/src/tools/handlers/read_file.rs(14c35a16a8^)——offset 缺省 1、limit 缺省 2000、
  单行 500 字节、TAB 宽 4、行前缀 `L{n}: `、slice / indentation 两种模式;
- list_dir:codex-rs/core/src/tools/handlers/list_dir.rs(70807730f5^)——offset 1、limit 25、depth 2、
  条目名 500 字节、每层缩进 2 空格;
- grep:codex-rs/core/src/tools/handlers/grep_files.rs(178c3b15b4^)——limit 100、顶 2000、按修改时间倒序。
glob 是 Keelson 新增(Codex 没有);write_file / delete_path 借鉴 coxswain(Apache-2.0)。

每个工具函数体只读 `(ws/current)`——工作区由 `im.ttalk.agent.tools/workspace-tools` 绑定。
raw docstring

im.ttalk.agent.tools.freshness

读写新鲜度闸(T-03;出处 Keelson ReadFreshness.cs + FileReadTable.cs,借鉴 coxswain seen.ss)。

已读表:真实路径 ⇒ 最近一次交给模型的内容 tag。宿主记,不让模型回传——模型的上下文 会被裁剪压缩,tag 交给它保管会丢。

⚠️ 登记点 = 凡把 tag 交给模型的地方(read_file 的 [路径#TAG] 头、写类工具回的「新的 TAG」), 一处都不能漏——漏一处就是「读过却说你没读过」。写成功之后也登记(模型知道自己写成了什么)。

表的来处:工作区的 :reads(缺省每个 workspace-tools 实例一张);:read-tracking? false ⇒ 没有表, 闸与登记全不做。

读写新鲜度闸(T-03;出处 Keelson `ReadFreshness.cs` + `FileReadTable.cs`,借鉴 coxswain `seen.ss`)。

已读表:真实路径 ⇒ 最近一次**交给模型**的内容 tag。**宿主记,不让模型回传**——模型的上下文
会被裁剪压缩,tag 交给它保管会丢。

⚠️ 登记点 = 凡把 tag 交给模型的地方(`read_file` 的 `[路径#TAG]` 头、写类工具回的「新的 TAG」),
一处都不能漏——漏一处就是「读过却说你没读过」。写成功之后也登记(模型知道自己写成了什么)。

表的来处:工作区的 `:reads`(缺省每个 `workspace-tools` 实例一张);`:read-tracking? false` ⇒ 没有表,
闸与登记全不做。
raw docstring

im.ttalk.agent.tools.notes

笔记三件(T-06;出处 Keelson NotesTools.cs,借鉴 coxswain memory.ss):notes_list / notes_read / notes_write。

机制(存哪、按什么分)归宿主的 INotesStore 实现;这一层只把它包成模型能调的三件事,并把「什么时候该记」 写进说明——只说「写一篇笔记」的说明会得到两种极端:一条都不记,或把每轮对话都记成日志。

自带两个实现:dir-store(一个目录下一篇一个文件)、memory-store(进程内,测试 / 临时用)。 名字校验在工具层统一做(⛔ 拿名字拼路径逃出去),存储实现可以信任它。

笔记三件(T-06;出处 Keelson `NotesTools.cs`,借鉴 coxswain `memory.ss`):notes_list / notes_read / notes_write。

机制(存哪、按什么分)归宿主的 `INotesStore` 实现;这一层只把它包成模型能调的三件事,并把「什么时候该记」
写进说明——只说「写一篇笔记」的说明会得到两种极端:一条都不记,或把每轮对话都记成日志。

自带两个实现:`dir-store`(一个目录下一篇一个文件)、`memory-store`(进程内,测试 / 临时用)。
名字校验在工具层统一做(⛔ 拿名字拼路径逃出去),存储实现可以信任它。
raw docstring

im.ttalk.agent.tools.patch

apply_patch(T-04):Codex 补丁文法的解析器 + 内存应用器 + 工具壳。

翻译自 OpenAI Codex CLI(Apache-2.0,Copyright 2025 OpenAI;见模块根 THIRD-PARTY-NOTICES.md 与 LICENSE-codex.txt),经 Keelson Keelson.Text/Patch/* 与 ApplyPatchTool.cs 转写:

  • 解析:codex-rs/apply-patch/src/parser.rs(边界检查、宽松模式剥 heredoc)与 streaming_parser.rs(逐行状态机)@ 4bad6d78e9;
  • 匹配:codex-rs/apply-patch/src/seek_sequence.rs(精确 → 忽略行尾空白 → 忽略两端空白 → Unicode 标点归 ASCII);
  • 应用:codex-rs/apply-patch/src/{text_file.rs, file_update.rs, lib.rs}(逐行保行尾、compute_replacements、成功摘要);
  • 工具壳:codex-rs/core/src/tools/handlers/apply_patch.rs(先验证整份补丁、写前逐路径过权限)。

与上游的差别:引擎不碰 IO——读由调用方给,产出「先全部算好、再由调用方落盘」的 plan: 任一文件对不上 ⇒ 一个也不写。

apply_patch(T-04):Codex 补丁文法的解析器 + 内存应用器 + 工具壳。

翻译自 OpenAI Codex CLI(Apache-2.0,Copyright 2025 OpenAI;见模块根 THIRD-PARTY-NOTICES.md 与
LICENSE-codex.txt),经 Keelson `Keelson.Text/Patch/*` 与 `ApplyPatchTool.cs` 转写:
- 解析:codex-rs/apply-patch/src/parser.rs(边界检查、宽松模式剥 heredoc)与 streaming_parser.rs(逐行状态机)@ 4bad6d78e9;
- 匹配:codex-rs/apply-patch/src/seek_sequence.rs(精确 → 忽略行尾空白 → 忽略两端空白 → Unicode 标点归 ASCII);
- 应用:codex-rs/apply-patch/src/{text_file.rs, file_update.rs, lib.rs}(逐行保行尾、compute_replacements、成功摘要);
- 工具壳:codex-rs/core/src/tools/handlers/apply_patch.rs(先验证整份补丁、写前逐路径过权限)。

与上游的差别:引擎不碰 IO——读由调用方给,产出「先全部算好、再由调用方落盘」的 plan:
**任一文件对不上 ⇒ 一个也不写**。
raw docstring

im.ttalk.agent.tools.skill

skill 工具(T-06;出处 Keelson SkillTool.cs,借鉴 coxswain skill.ss)。

解决的是「几百字一条、只在特定活上用得着的操作手册全塞进系统提示是每轮白烧,全不给则每次现摸」: 工具说明里只列目录(名字 + 一句描述),模型对上了再调 skill 把整份装进对话。

目录由宿主给({:skills {:dirs ["/repo/.skills" "~/skills"]}},⛔ 库内写死 .claude/skills 一类位置), 按给的顺序同名先到的赢;每个目录下一层子目录各放一份 SKILL.md(frontmatter name / description; 没有 name 用目录名)。说明在 workspace-tools 时扫描一次(说明稳定 ⇒ 不打碎提示缓存前缀);调用时重扫。

skill 工具(T-06;出处 Keelson `SkillTool.cs`,借鉴 coxswain `skill.ss`)。

解决的是「几百字一条、只在特定活上用得着的操作手册全塞进系统提示是每轮白烧,全不给则每次现摸」:
工具说明里只列目录(名字 + 一句描述),模型对上了再调 skill 把整份装进对话。

目录由宿主给(`{:skills {:dirs ["/repo/.skills" "~/skills"]}}`,⛔ 库内写死 .claude/skills 一类位置),
按给的顺序同名先到的赢;每个目录下一层子目录各放一份 `SKILL.md`(frontmatter `name` / `description`;
没有 name 用目录名)。说明在 `workspace-tools` 时扫描一次(说明稳定 ⇒ 不打碎提示缓存前缀);调用时重扫。
raw docstring

im.ttalk.agent.tools.syntax

「不更糟」语法闸(T-07;出处 Keelson SyntaxGuard.cs / SyntaxCheckers.cs,借鉴 coxswain check.ss)。

判据是更糟不是「不合法」:before 看得了、且 after 的问题数比 before 多才拒(0→1、3→5 拒; 3→1、3→3 放)。只查 after 会退化成「不合法就拒」,把修复它的那次编辑也拦掉,然后彻底卡死。

⚠️ 检查器 check 返回 nil(「看不了」)与返回 [](「看过了,没问题」)是两件事:审批预览对后者 说「✓ 改完之后语法没问题」,对前者一个字都不说。拿不准的写法一律回 nil,⛔ 猜。检查器抛异常等同 nil。

内置:JSON(Jackson,cheshire 带来的)、EDN 与 Clojure 源码(Clojure 读取器)、XML(JDK SAX,禁 DTD)。 BracketScan.cs 不移植——理由见 designs/tools-module.md §6。

「不更糟」语法闸(T-07;出处 Keelson `SyntaxGuard.cs` / `SyntaxCheckers.cs`,借鉴 coxswain `check.ss`)。

判据是**更糟**不是「不合法」:before 看得了、且 after 的问题数比 before 多才拒(0→1、3→5 拒;
3→1、3→3 放)。只查 after 会退化成「不合法就拒」,把修复它的那次编辑也拦掉,然后彻底卡死。

⚠️ 检查器 `check` 返回 nil(「看不了」)与返回 [](「看过了,没问题」)是**两件事**:审批预览对后者
说「✓ 改完之后语法没问题」,对前者一个字都不说。拿不准的写法一律回 nil,⛔ 猜。检查器抛异常等同 nil。

内置:JSON(Jackson,cheshire 带来的)、EDN 与 Clojure 源码(Clojure 读取器)、XML(JDK SAX,禁 DTD)。
BracketScan.cs 不移植——理由见 designs/tools-module.md §6。
raw docstring

im.ttalk.agent.tools.text

文本小件:内容 tag、UTF-8 字节截断、「按原样读进来、按原样写回去」的可编辑文本、统一格式 diff。

  • content-tag:FNV-1a 32 位、8 位大写十六进制(出处 Keelson ContentTag.cs, 借鉴 coxswain tag.ss;测试向量 "hello" ⇒ 4F9F2CAB)。是内容哈希不是 mtime—— 「同一秒改成同样长度」正是新鲜度闸要抓的那类。
  • decode-editable / encode-editable:换行 / 编码 / BOM 原样写回,二进制拒绝 (出处 Keelson EditableText.cs)。只认 UTF-8(可带 BOM)、带 BOM 的 UTF-16/32、 严格 GBK(编回去逐字节相同才认);其余拒(⛔ 猜一个写回去)。
  • unified-diff:审批预览用(出处 Keelson PatchDiff.cs 的格式口径,算法用 LCS)。
文本小件:内容 tag、UTF-8 字节截断、「按原样读进来、按原样写回去」的可编辑文本、统一格式 diff。

- `content-tag`:FNV-1a 32 位、8 位大写十六进制(出处 Keelson `ContentTag.cs`,
  借鉴 coxswain `tag.ss`;测试向量 "hello" ⇒ 4F9F2CAB)。是**内容**哈希不是 mtime——
  「同一秒改成同样长度」正是新鲜度闸要抓的那类。
- `decode-editable` / `encode-editable`:换行 / 编码 / BOM 原样写回,二进制拒绝
  (出处 Keelson `EditableText.cs`)。只认 UTF-8(可带 BOM)、带 BOM 的 UTF-16/32、
  严格 GBK(编回去逐字节相同才认);其余拒(⛔ 猜一个写回去)。
- `unified-diff`:审批预览用(出处 Keelson `PatchDiff.cs` 的格式口径,算法用 LCS)。
raw docstring

im.ttalk.agent.tools.walk

目录遍历(glob / grep 共用;出处 Keelson WorkspaceWalker.cs)。

  • path-glob:JDK glob(* 不跨目录、** 跨任意级、{a,b} 任选、?、[...]),并补上 「**/ 也匹配零级目录」的口径(**/*.clj 匹配根下的 a.clj;JDK 原生不认)。
  • ignore-rules:.gitignore / .ignore 的常见子集——空行与 # 跳过、! 取反、结尾 / 只配目录、 模式里有 /(不算结尾的)⇒ 相对忽略文件所在目录锚定,否则按名字在任意深度匹配;后写的胜出; 被忽略的目录整棵剪掉(git 同样不能在其下再取反)。
  • walk:⛔ 跟随符号链接(rg 缺省同)、总是跳过 .git、可选跳过隐藏条目、认忽略规则(根的祖先里的 忽略文件也读,直到含 .git 的那层)、路径策略不许读的不进。
目录遍历(glob / grep 共用;出处 Keelson `WorkspaceWalker.cs`)。

- `path-glob`:JDK glob(`*` 不跨目录、`**` 跨任意级、`{a,b}` 任选、`?`、`[...]`),并补上
  「`**/` 也匹配零级目录」的口径(`**/*.clj` 匹配根下的 `a.clj`;JDK 原生不认)。
- `ignore-rules`:`.gitignore` / `.ignore` 的常见子集——空行与 `#` 跳过、`!` 取反、结尾 `/` 只配目录、
  模式里有 `/`(不算结尾的)⇒ 相对忽略文件所在目录锚定,否则按名字在任意深度匹配;后写的胜出;
  被忽略的目录整棵剪掉(git 同样不能在其下再取反)。
- `walk`:⛔ 跟随符号链接(rg 缺省同)、总是跳过 `.git`、可选跳过隐藏条目、认忽略规则(根的祖先里的
  忽略文件也读,直到含 `.git` 的那层)、路径策略不许读的不进。
raw docstring

im.ttalk.agent.tools.web

web_fetch(T-06;出处 Keelson WebFetchTool.cs,借鉴 coxswain fetch.ss)。

它挡的是「模型要看一页文档只能 exec curl ⇒ 回来整页 HTML,几十 KB 的 <script> 把输出上限吃光、正文一个字都没到」 那一类:抓 → 认 Content-Type → HTML 简化成文本,一步到位。传输走 clj-http(零依赖,JDK java.net.http)。

  • 手动跟随重定向(≤ :max-redirects),每一跳都过 :allow-url(宿主的网络策略钩子);
  • 体积上限数实际读到的字节(⛔ 信 Content-Length);
  • 缺省 Sensitive(它不改盘,但它出网:URL 本身就是一条出口),宿主可 {:web-fetch {:sensitive false}} 关掉。

选项(工作区 :web-fetch)::allow-url (fn [^java.net.URI uri] bool)、:timeout-ms(30000)、 :default-max-chars(40000)、:max-chars(200000)、:max-body-bytes(5 MiB)、:max-redirects(5)、:user-agent、 :client(自带 java.net.http.HttpClient;须不自动跟随重定向,否则中间跳转不过 :allow-url)、 :proxy(没给 :client 时用::env 读 https_proxy / no_proxy …、代理地址串、或 ProxySelector;缺省直连)。

web_fetch(T-06;出处 Keelson `WebFetchTool.cs`,借鉴 coxswain `fetch.ss`)。

它挡的是「模型要看一页文档只能 exec curl ⇒ 回来整页 HTML,几十 KB 的 <script> 把输出上限吃光、正文一个字都没到」
那一类:抓 → 认 Content-Type → HTML 简化成文本,一步到位。传输走 clj-http(零依赖,JDK `java.net.http`)。

- **手动**跟随重定向(≤ :max-redirects),每一跳都过 `:allow-url`(宿主的网络策略钩子);
- 体积上限数**实际读到的**字节(⛔ 信 Content-Length);
- 缺省 Sensitive(它不改盘,但它出网:URL 本身就是一条出口),宿主可 `{:web-fetch {:sensitive false}}` 关掉。

选项(工作区 `:web-fetch`)::allow-url (fn [^java.net.URI uri] bool)、:timeout-ms(30000)、
:default-max-chars(40000)、:max-chars(200000)、:max-body-bytes(5 MiB)、:max-redirects(5)、:user-agent、
:client(自带 java.net.http.HttpClient;须不自动跟随重定向,否则中间跳转不过 :allow-url)、
:proxy(没给 :client 时用:`:env` 读 https_proxy / no_proxy …、代理地址串、或 ProxySelector;缺省直连)。
raw docstring

im.ttalk.agent.tools.workspace

工作区:路径策略 + 文件层 + 每实例状态(设计:designs/tools-module.md §3 §4)。

  • IPathPolicy:每个路径碰之前都问它。缺省 workspace-policy——可写根、只读根、 受保护名(.git .agents .codex .aws,照 Codex PROTECTED_METADATA_PATH_NAMES), 判定在字面(.. 已折叠)与解链接后两个口径上都做(出处 Keelson WorkspacePathPolicy.cs)。
  • IFileLayer:读写类工具只经它碰文件(出处 Keelson FileLayer.cs),缺省 local-file-layer——原子写(同目录临时文件 + ATOMIC_MOVE)、写解链接后的真实路径。
  • workspace:把选项收成一个 ws map;*workspace* 由 im.ttalk.agent.tools/workspace-tools 造的匿名 var 在工具函数体内部绑定(与引擎 / 线程无关,见 design-principles §3)。

业务失败一律 fail!:抛 ex-info,ex-data 带 :error-class :semantic 与 :code, tool/invoke 把它变成给模型的「错误: …」。

工作区:路径策略 + 文件层 + 每实例状态(设计:designs/tools-module.md §3 §4)。

- `IPathPolicy`:每个路径碰之前都问它。缺省 `workspace-policy`——可写根、只读根、
  受保护名(`.git .agents .codex .aws`,照 Codex `PROTECTED_METADATA_PATH_NAMES`),
  判定在**字面**(`..` 已折叠)与**解链接后**两个口径上都做(出处 Keelson
  `WorkspacePathPolicy.cs`)。
- `IFileLayer`:读写类工具只经它碰文件(出处 Keelson `FileLayer.cs`),缺省
  `local-file-layer`——原子写(同目录临时文件 + ATOMIC_MOVE)、写解链接后的真实路径。
- `workspace`:把选项收成一个 ws map;`*workspace*` 由 `im.ttalk.agent.tools/workspace-tools`
  造的匿名 var 在**工具函数体内部**绑定(与引擎 / 线程无关,见 design-principles §3)。

业务失败一律 `fail!`:抛 `ex-info`,ex-data 带 `:error-class :semantic` 与 `:code`,
`tool/invoke` 把它变成给模型的「错误: …」。
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close