opencode-smart-approval
v0.7.1
Published
OpenCode command approval plugin with deterministic rules, Tirith scanning, and a restricted direct OpenCode approval agent.
Maintainers
Readme
opencode-smart-approval
一个 OpenCode 命令审批插件,组合严格的个人规则、Tree-sitter Shell 分析、Tirith 与受限的 OpenCode 直接审批 Agent。
这是应用层审批边界,不是命令沙盒。OpenCode、所选模型/Provider 以及所有同时加载的插件仍属于可信计算基。本插件用于减少误审批并对证据实行失败封闭处理;它不提供操作系统级文件系统或网络隔离。
要求与安装
生产契约固定在 OpenCode 1.17.14 的 @opencode-ai/plugin 及其根客户端。
npm install -g opencode-smart-approvalOpenCode 必须允许 Shell 工具,tool.execute.before 才能检查它。Provider 凭证与模型继续保存在用户的 OpenCode 配置中,例如:
{
"permission": { "bash": "allow" },
"plugin": ["opencode-smart-approval"],
"small_model": "provider/reviewer-model"
}如果 OpenCode 在执行前就 deny 或 ask bash,本插件不会收到该工具调用。可选的 small_model 按下文的模型优先级参与选择。
决策管线
每个受支持的 Shell 调用都复用同一份分析和同一个已加载策略快照:
配置访问守卫 → 用户规则 → 内置规则 → Tirith → OpenCode 直接审批 Agent| 阶段 | 行为 |
|---|---|
| 配置访问守卫 | 已证实会写入当前审批策略的操作直接阻断;无法排除策略写入的操作不能走 allow 快速路径,而会继续审查。 |
| 用户规则 | 完整的显式 deny 立即终止;完整显式 allow 也会终止,除非配置访问守卫强制审查。部分匹配、未匹配或显式 review 会继续。 |
| 内置规则 | 为基础 Shell 连接与查看命令提供极小、平台无关的快速路径:Shell 谓词(true、false、test、[)、基础位置或目录查看(ls、pwd、basename、dirname)以及 command -v 查找,均不含重定向。其他所有命令,包括所有 Git 子命令,都必须审查。 |
| Tirith | 扫描完整、未拆分的命令。block 立即终止;allow 或 warn 会携带扫描证据继续。 |
| 审批 Agent | 创建隐藏的 OpenCode primary 审查子会话,验证最终运行时身份,提交带有 direct_question: null 的有界证据,解析一个严格裁决,并在失败时封闭。子会话的内置 question 被拒绝;首次未授权的 high 风险 needs_confirmation 会转交主机,由父级主会话持有并呈现绑定到精确命令、规范化 cwd 与 effect SHA-256 的问题。 |
对于管道或列表,必须所有静态解析出的可执行段都获准,allow 才能短路。任一段 deny 都拒绝整条命令。同优先级冲突按 deny > review > allow;先比较更高的整数 priority。
裁决接收器只接受恰好一个完整裁决,且只能是以下两种严格形式之一:前后没有任何其他内容的原始 JSON,或内容恰为该 JSON 的单个小写 json 代码围栏。裁决周围的文本、多个或歧义的 JSON 值,以及任何其他围栏语言都会被拒绝并失败封闭。
OpenCode 根客户端直连架构
生产代码复用插件收到的精确根 PluginInput.client。它不导入 SDK /v2 客户端、不构造另一个 OpenCode 客户端或服务器、不调用 opencode run,也不启动 OpenCode 子进程。按照 OpenCode 1.17.14 的声明,每个根方法只接收一个生成的 options 对象,其中 path、query、body 和 signal 位于固定层级。插件只捕获一次这些方法,并使用:
app.agents与app.log;session.messages、session.create、session.prompt、session.abort和session.delete。
app.log 只用于有界、尽力而为的 late-create 清理诊断;它绝不发出审批裁决,也不记录命令、prompt、路径或 Provider 内容。
审查器确实会在已经运行的 OpenCode 实例中创建子会话,并以隐藏的 primary Agent 运行;该子会话不启用内置 question,其权限明确为 deny。隐藏 primary 是固定身份属性,并不把提问所有权交给审查器。不会启动额外 OpenCode 进程,插件会在每个终局结果之后无条件删除精确的自有子会话;需要确认时,问题由父级主会话持有并呈现。
1.17.14 的生成声明与运行时传输并不完全一致。生成声明暴露 builtIn、tools、maxSteps 及旧权限形状;实测 app.agents 运行时则暴露 native、steps、规范化权限规则,以及可为 null 的 hidden、topP、color、variant。运行时消息数据也包含滞后于声明的源字段。因此所有客户端响应先视为 unknown,再由严格、锁定到源代码的 schema 解析;未知字段、错误 null 规则、重复固定 Agent 或身份漂移都会失败封闭。
策略版本 3
可信全局策略位于 ~/.config/opencode/command-approval.jsonc,或 $XDG_CONFIG_HOME/opencode/command-approval.jsonc。文件不存在时会用 v3 默认值创建。
项目可以提供 ./command-approval.jsonc,但只有可信全局文件设置 "allow_local_config": true 时才使用。本地文件启用后会完整替代该项目的全局策略,因此应把已启用的项目策略视为可信代码。
最小有效策略是:
{
"version": 3
}省略 review 是默认且推荐的做法:所有 review 选项都会回退到默认值,LLM 审批审查仍然启用。review: {} 仍然有效且等价,但没有必要写。
版本 3 有意采用严格模式。顶层、review、self_protection、tirith、rules 以及每条规则对象都拒绝未知字段。字符串简写、别名、无版本/v1/v2 文档及旧 command-approval.json 文件名都会被拒绝,不提供兼容回退或自动替换。
策略选项
| 选项 | 默认值与契约 |
|---|---|
| version | 必填字面量 3。 |
| allow_local_config | false;只从可信全局文件读取。 |
| self_protection.enabled | true;启用尽力而为的配置访问守卫。 |
| review | 可选对象。省略或写 {} 都保持下表所有默认值,并仍然启用 LLM 审批审查。 |
| review.model | 默认不存在;出现时必须是精确 trim 的 provider/model 身份,model 部分可以包含后续 /。 |
| review.timeout_ms | 45000;1000 到 300000 的安全整数。 |
| review.context_messages | 20;0 到 200 的安全整数;0 禁用审查器对话上下文。 |
| review.confirmation | "ask";"ask" 对符合条件的首次 high 风险审查使用宿主一次性确认路径,"deny" 则不提问并把同一情形收紧为终局拒绝。它绝不会削弱任何 deny。 |
| review.prompt | 默认不存在;精确 trim 的非空可信策略后缀,最多 8,192 个 UTF-16 code unit。它附加在不可变安全契约之后,不能替换契约。 |
| tirith.enabled | true。 |
| tirith.path | 默认不存在;精确 trim 的本地二进制绝对路径会跳过自动下载。 |
| tirith.timeout_ms | 5000;500 到 60000 的安全整数。 |
| tirith.fail_open | false。 |
| rules.deny、rules.review、rules.allow | 用户列表默认为空,之后仍合并极小内置规则集。 |
每条规则都是严格对象:必填非空 match,以及可选非空 reason、scope: "command" | "segment"、安全整数 priority。针对可执行文件的信任应使用 segment scope。只有分析得到恰好一个静态可执行节点时,command-scope allow 才有资格终止后续阶段。
模型优先级
固定审批 Agent 按以下精确顺序选择模型:
- 审批策略中的有效
review.model; - OpenCode
opencode.json或opencode.jsonc中的small_model; - 省略 Agent 的
model属性,让 OpenCode 继承其已配置选择。
只要策略中出现无效 model,策略加载就会失败,绝不会回退到 small_model。
从 v1/v2 破坏性迁移
配置兼容已明确移除,因此迁移必须手工完成:
- Provider URL、API key、Provider 插件及 Provider 模型定义继续放在 OpenCode 自身配置中。
- 创建
command-approval.jsonc,写入version: 3;review可选,默认省略。不要继续使用旧.json文件名。 - 将个人规则复制为
rules.deny、rules.review、rules.allow下的严格对象条目。 - 只按上表加入当前 v3 的审查、Tirith、本地策略或守卫选项。
- 启动 OpenCode 后按报告的精确字段类别修正;加载器不会猜测旧语义。
下面是不能复制的已移除形状示例。严格加载器会先在 version 类别拒绝它,不会使用任何退役字段:
{
"version": 2,
"review": {
"base_url": "https://api.example.invalid/v1",
"api_key": "removed",
"max_script_bytes": 20000,
"max_tool_calls": 3,
"max_retries": 3
}
}已移除标识包括 base_url、api_key、max_script_bytes、max_tool_calls、max_retries、rules.block、risk_tool、camelCase 别名、字符串规则简写及版本 1/2 迁移行为。Provider 传输和认证现在完全归 OpenCode 管理;审查器上限与工具由插件固定,不再由策略控制。
固定受限审批 Agent
配置钩子会在自身加载顺序位置覆盖固定名称 opencode-smart-approval-reviewer,并保留无关 Agent。独立冻结的预期配置包含:
- 固定描述
Reviews one shell command for opencode-smart-approval using only the plugin-owned guarded reader.及不可变安全契约; mode: "primary"、hidden: true、steps: 4、temperature: 0;- 所选的可选模型;
- 权限 map
{"*":"deny","external_directory":"deny","question":"deny","opencode_smart_approval_read":"allow"}。
primary 模式与隐藏状态是固定身份属性,隐藏固定 Agent 让它不参与普通 Agent 选择。创建前及 prompt 前,app.agents 都必须暴露恰好一个匹配 Agent,并满足固定描述、prompt、mode、steps、temperature、model、空 options、native: false、不存在已启用的可选覆盖,以及以下精确最终规范化权限后缀:
| Permission | Pattern | Action |
|---|---|---|
| * | * | deny |
| external_directory | * | deny |
| question | * | deny |
| opencode_smart_approval_read | * | allow |
OpenCode 可以在末尾追加一条宿主管理的精确 .../opencode/tool-output/* 目录 allow;再出现其他后续权限规则就验证失败。每次 session.prompt 还会发送精确工具 map {"*":false,"opencode_smart_approval_read":true}。
审批 Agent 被限制为恰好一个工具:插件拥有的受守卫读取器。内置 question 工具被拒绝;本插件也不会向审批 Agent 授予 Shell、网络、通用 read/list、write/edit 或权限管理工具。这是 OpenCode 工具调度限制,不是 OS 沙盒。
受守卫读取器边界
唯一由插件提供给审查器的工具是 opencode_smart_approval_read,严格参数为 path 与可选非负安全整数 offset(默认 0)。单次调用最多返回 65,536 字节。
访问必须同时匹配当前拥有的子会话 ID、固定 Agent 名称、规范化审查目录、worktree、活动 generation 以及未中止的 prompt。清理前先撤销所有权。
- 工作区文件在锚定的 workspace 根下按需打开。
- 工作区之外,只租约共享 Shell 分析静态引用、且位于规范化临时根或独立 worktree 下的精确现存文件;Agent 不能浏览整个临时目录。
- 每个路径组件都通过锚定描述符遍历。最终目标必须是只有一个链接的常规文件;符号链接、硬链接、特殊文件、路径穿越、畸形路径和作用域逃逸都失败封闭。
- 临时引用保留 activation 时打开的精确描述符快照;工作区读取在有界 read 前后比较描述符。撤销、路径替换或身份变化不能切换被审批的字节。
权威 POSIX 敏感路径谓词不区分大小写,并拒绝任何以 / 或 = 分隔、值等于 .env、.env.local、.git、.git-credentials、.netrc、.npmrc、.pypirc、.ssh、.aws、.docker、.kube、.azure、auth.json 的组件;任何以 .env. 开头的组件;.config/gh 与 .config/gcloud;以及精确 /proc/self/environ、/proc/thread-self/environ 或数字进程/task 的 environ 路径。反斜杠在 POSIX 中仍是普通字符。描述符遍历前,会分别对请求拼写、根相对拼写和绝对拼写应用此谓词。
上下文与授权边界
审查器可以看到有界证据:命令、规范化 cwd、工具参数、Shell 分析、匹配规则、Tirith 结果、静态引用及投影后的父会话 transcript。策略 context_messages 限制请求消息数;独立上限约束复制 envelope、单 part/总文本、part 数、工具名及完整序列化审查请求。独立的确认授权读取若超过完整 envelope 上限,只会针对这一种超限按最新消息窗口 32、16、8、4、2、1 有界重试。每次重试仍执行同一套复制、schema、身份、顺序、当前调用与 deadline 校验;若单条最新消息仍超限或精确调用边界不存在,依然失败封闭。synthetic/ignored 文本、附件、summary、不支持的 part 及畸形身份/顺序会失败封闭或被排除。普通父文本会作为有界 transcript 证据被复制,不会按短语形状擦除。
Transcript 文本只是证据,不是插件授权。用户可以在其中表达意图,审查器也可以独立判断某动作安全;但引用命令、助手文本、旧审批和泛化的“继续”都不会成为插件确认。只有审查请求中由宿主验证的 authorization_candidates 部分携带来源、当前轮次新鲜度、一次性状态,以及对精确完整命令、规范化 cwd 与 effect SHA-256 的绑定。自由文本的精确语义由审查器模型判断,宿主代码则确定性地执行周边契约。序列化的 direct_question 字段始终为 null;子审查器撰写的问题及 question part 都不能授权任何内容。
两条通道是分开的:投影后的 transcript 是有界证据,可以到达审查器与 Provider;authorization_candidates 则是宿主验证的授权通道。宿主验证控制候选的来源、新鲜度、绑定与一次性使用;它不是对任意 transcript 文本的语义擦除。
审查器独立评估命令固有风险与用户授权,运行时对 allow 只做收窄式一致性处理。高风险 allow 只有在 transcript 提供 medium/high 授权或有宿主验证的授权候选时才成立;critical allow 一律拒绝;low/medium allow 即使没有任何用户授权也可以放行。
一次性知情确认
常规 low/medium 风险审查必须直接返回 allow 或 deny,不能询问用户;critical 风险必须返回 deny。当 review.confirmation: "ask" 时,只有首次、未获授权且为 high 风险的审查可以返回 needs_confirmation,并给出具体 action、data、destination、risk。当配置为 "deny" 时,审查器与宿主都会把这个精确的可确认情形转换为 deny,不发出问题。该设置不能覆盖显式规则 deny、敏感数据或 critical 风险的强制拒绝、畸形证据、超时或任何其他失败封闭结果。在 "ask" 路径上,插件会阻断该次尝试,并渲染这四项、精确完整命令、规范化 cwd、effect/disclosure SHA-256、替换状态,以及一个固定选项为 Authorize once 与 Deny 的严格宿主会话内置 question payload。原生 OpenCode 可能省略默认的 custom: true 并显示 Type your own answer;只有精确 Authorize once 才授权按 request 路由的重试,其他结构有效的单个答案都拒绝该调用且不改变兄弟待处理调用。宿主至多询问一次;子 question part、low/medium/critical 的确认请求,以及已授权重试再次返回 needs_confirmation 都会失败封闭。
等待中或已询问的宿主确认不会仅因时间经过而过期。只有宿主收到精确肯定回复 Authorize once 时,300 秒的一次性授权窗口才开始。宿主绝不会截断披露字段;如果精确命令、规范化 cwd 或确认正文超过表示性上限,请求会失败封闭,而不是询问一个不完整的问题。
回退答案只授权一次对完全相同命令的重试,而且必须等临时 current-call 身份解析为真实的持久化 assistant/tool 边界之后。临时身份只按 call ID、工具与 effect SHA-256 命名当前调用,不会伪造 part 坐标;在宿主定位到恰好一条包含恰好一个匹配被阻断工具 part 的持久化 assistant 消息之前,回退不能被 claim,因此重试绑定到 transcript 中实际被阻断的命令 part。在该精确边界解析成功之前,待处理 handoff 继续等待,不授权任何重试。
授权证据有界且只能使用一次:
- 最新普通父用户消息中的精确 prompt 预授权,只要精确覆盖命令、effect 与 disclosure,就可以作为首次审查的证据。
- 对宿主会话 payload 的已完成匹配
question答案,从肯定回复时起 300 秒内只授权一次匹配重试,且必须针对完全相同的命令。 - question 被拒绝或出错时,至多允许一次有界的失败后普通用户回退。
- question 答案与回退文本绝不直接创建 allow。每次被接受的重试都会按适用情况重新运行用户规则与内置规则、Tirith,以及一个全新的受限审查器,且该审查必须独立 allow。
- 无论证据如何,critical 风险仍然一律拒绝。
重放、不匹配、过期、effect 或 disclosure 改变、边界被替换/驱逐、多个候选、歧义,以及未发出或伪造的 question 完成都会失败封闭。用户响应前的自动重试会继续等待,不会旋转 handoff。
并行工具调用
OpenCode 会把 Codex、Hermes 与 Provider 的工具调用归一化为同一种分发形状,并且可能在同一 prompt 下并发运行相互独立的兄弟调用。审查前分析可以重叠,但完整审查轮次会在每个精确父会话内按 FIFO 准入。不同父会话仍可并发,并可按相反顺序完成。这个窄准入队列不调度工具执行、宿主确认问题、工具结果、兄弟结果交付或全局插件工作,也不声称拥有批处理控制。每个审批调用仍由自己的 (sessionID, callID) 对在 before-hook 审批边界解析;没有兄弟调用会继承另一个调用的键。
每个兄弟调用仍保留自己的调用键审查状态、子会话与失败结果。同一父会话的交互式轮次按到达顺序执行;不同父会话的审查子会话与失败仍相互独立,可以乱序完成,一个兄弟 settle 或失败绝不会提供另一个兄弟的结果。同一个精确用户来源最多只授权一个兄弟:当两个调用解析到同一个普通用户 prompt 时,恰好一个 claim 该槽位,另一个只携带有界 transcript 证据而不 claim。所有已 claim 的授权都保持一次性。
一个回退 handoff 只属于一个调用。渲染副本携带精确的被阻断调用身份 blocked_call_id 与指向该调用的 call_reference,并命名精确命令、规范化 cwd、effect 与 disclosure SHA-256。回复与拒绝按精确 requestID 路由,因此两个待处理、显示前缀相撞的兄弟 handoff 不会互相干扰。未变化的重复渲染会复用同一份字节,而不是替换兄弟的 prompt,因此用户永远不会看到重复或被替换的兄弟 prompt。
删除或 dispose 父会话会移除所有待处理与已 claim 的兄弟状态,包括来源预留与请求映射。在 clear 或 dispose 之后到达的迟到事件不能复活交互,它们会被忽略,也不能新增任何授权 claim。
ToolPart 及其结果只由 OpenCode 持久化。插件不持久化或重排 ToolPart;它只消费发出的 transcript,发出的 part 的确定性顺序归 OpenCode 所有,而非本插件。
面向用户的错误安全
不可信工具名、规则/扫描器/Provider/审查器 reason、路径及确认字段统一经过一个 renderer。它转义反斜杠、引号、反引号、控制字符、双向控制符与 BOM;无效 UTF-16 在普通错误中安全替换,并使确认渲染失败。
普通阻断错误把转义后工具名限制为 1,024 字节、单条 reason 1,024 字节、reason 数 16、category 数 32、reason 聚合文本 8,192 字节、完整 body 16,384 字节。确认不会截断单个披露字段:转义后的 command 上限为 8,192 字节,完整 body 上限为 16,384 字节;超限就失败封闭。
审查会话生命周期
预检查成功后,每次审查在同一个共享 deadline 下最多顺序执行三次全新子尝试,同一时刻最多只有一个活动子会话。每次被接受的授权重试也会启动一次全新的受限审查器运行,因此任何证据都不会复用先前的审查结果。每次尝试都会创建自己的精确子会话,并按 ID、目录、固定 Agent 类型、prompt settlement 与 reader lease 跟踪;返回的子会话 ID 若已被使用过,则失败封闭。只有无效裁决(invalid verdict)可以重试,且必须在其异常清理成功之后。并发调用清理的调用方会加入同一个进行中的清理 promise,因此 idle、deleted、instance disposed、hook dispose、超时及 late settlement 路径不会删除外部会话或重复删除。已到达 deleted 的句柄,后续清理直接返回 already_deleted。非终态失败的清理会清空进行中的 promise,因此后续清理或 dispose 可以重试。
在同一父会话的交互式审查 FIFO 中等待时,只暂停该等待者自己的单调审查 deadline。准入时按非负排队时长平移原有 expiry,并保留同一个单调时钟,从而精确恢复入队时测得的剩余预算;绝不会重新授予完整 timeout。准入后,Agent 验证、子会话创建、prompt、重试与清理输入仍受恢复后的 deadline 约束。立即准入则原样保留原 deadline。
解析先对完成进行分类,再决定生命周期路径:完整解析出的裁决是普通完成,malformed_envelope、limit_exceeded、identity_mismatch 与 invalid_verdict 都是异常完成。只有无 question 的普通无效裁决可以重试:即没有任何子 question part、且不是有效 JSON 的裁决。每个子 question part 都是终局且不可重试;畸形 envelope、表示性上限、身份不匹配及跟在 question part 后的坏裁决也一样。普通完成先撤销 reader lease,再删除精确子会话。异常完成会先撤销访问,按需中止尚未 settle 的 prompt,在时限内 drain,然后尝试精确删除,因此无效或畸形尝试在重试之前必定被删除。匹配的外部 session.deleted 事件会被视为已删除。
session.idle 事件只 settle 恰好属于本插件的 prompt 并撤销 reader 访问,本身不会删除子会话。普通完成和所有异常终局路径都会删除精确子会话。Dispose 会对每个剩余的非终态自有句柄执行异常清理,包括已 idle settle 的句柄与 cleanup_failed 句柄;终态的 deleted 句柄已被移出 registry,不会被重新解释。
Tirith 完整性与离线行为
配置 tirith.path 时必须使用绝对路径。未配置时,插件选择平台资产,下载有界 release/checksum/archive 数据,校验上游 archive SHA-256,在严格条目/大小限制下解压,记录二进制摘要,并原子安装到缓存。
小于 24 小时的缓存只有在元数据及当前二进制摘要匹配时才复用。刷新不可用时,过期缓存只有在重新读取元数据并重新验证精确二进制、asset、release、archive digest 与 binary digest 证明后,才可明确返回 stale_verified。畸形上游数据、已变化/撤销 release、缺失证明或被篡改字节都不能走 stale 回退。扫描器执行失败按可信 tirith.fail_open 处理,默认失败封闭。
配置访问守卫的限制
self_protection.enabled 控制一个尽力而为的执行前守卫,保护当前 reload-effective 全局策略,以及仅在显式启用时的本地策略。它会阻断已证实的 Shell 重定向/写入器及已识别的 OpenCode write、edit、patch 目标。静态歧义会强制进入 deny 之后的审查路径,因此宽泛 allow 不能静默绕过;已证实的只读操作和相邻/非活动文件不会被误阻断。
该守卫不是文件系统 ACL,无法阻止手工编辑、其他进程、宿主/core 修改、未观测到的共存插件行为或所有 TOCTOU 竞争。未知文件工具与动态 effect 可能不可见,或只能强制审查。只有在其他控制已承担风险时,才应在可信全局策略中关闭它。
宿主、插件与沙盒信任
OpenCode 1.17.14 以进程为单位加载插件,不存在针对某个审查子会话的插件开关。本插件永不修改 OPENCODE_DISABLE_DEFAULT_PLUGINS 或 OPENCODE_PURE:
- 启动后修改
OPENCODE_DISABLE_DEFAULT_PLUGINS无法改变单个子会话;启动时设置它还会移除已配置模型依赖的内置 Provider 集成; OPENCODE_PURE会移除包括本审批插件在内的外部插件;- 两者都保持不变,用户现有 OpenCode/Provider 插件配置才继续作为权威配置并保持可用。
产品没有 pure 选项。只有后续、不会打包发布的 Todo 12 验证 harness 负责隔离的 boot-only disable-default-plugins 探针;生产代码不会复制该环境。
配置钩子会在自身加载位置覆盖同名 Agent,运行时字段/权限验证也能检测后续 Agent 修改。但 app.agents 既不暴露实际启用工具 map,也不提供工具定义来源。OpenCode 可能保留重复同名工具定义,而后续 session 组装可能选择更晚的共存插件定义。因此恶意或不兼容插件可以替换受守卫读取器实现或改变宿主行为。必须审查完整插件列表,并把共存插件与 OpenCode 本身视为可信。
固定 permission/tool map 只限制 OpenCode 调度,不隔离 Provider 代码、插件、宿主进程、文件系统 syscall 或网络访问。它们只限制 OpenCode 可以把哪些工具路由给审查器;不能替代宿主验证的授权检查。子 question 被拒绝且 direct_question 为 null,因此审查器撰写或篡改的问题不能授权任何内容。允许网络的更广 OS 沙盒仍然推迟,因为 OpenCode 配置/data/cache/state/Provider 访问需要单独设计。
隐私摘要
- 所选 Provider 可以看到
direct_question: null的有界审查请求,以及模型与唯一受守卫读取器的交互。宿主确认发生在父会话,而不是审查子会话。 - 审批子会话位于现有 OpenCode 进程/数据库中,并在每个终局结果之后按精确 ID 删除。
- prompt 预授权与回退文本可能保留在父历史中,并作为有界 transcript 证据到达审查器与 Provider。宿主验证的
authorization_candidates通道不是对任意 transcript 文本的擦除。 - Tirith 自动下载与模型/Provider 流量遵循各自配置的网络路径。
- 插件不会启动
opencode run、构造第二个客户端/服务器,也不会改变 Provider/插件环境标志。
从 0.6.4 迁移
0.6.4 使用需要用户精确复述的生成确认短语。该协议已退役。审查子会话现在拒绝 question 并接收 direct_question: null。首次、未获授权的 high 风险 needs_confirmation 裁决可以产生一个绑定到精确命令、规范化 cwd、effect SHA-256 与被阻断调用的宿主会话问题;肯定回复从该回复时刻启动 300 秒的一次性重试窗口。无需修改配置:同一套策略、规则与审查器设置继续有效,每次被接受的重试仍会重新运行规则、Tirith 与全新的受限审查器。
开发
bun install
bun run typecheck
bun test参考项目
许可
MIT
