@coda-console/protocol 2.6.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/README.md +38 -10
- package/docs/agent-protocol.md +26 -21
- package/docs/protocol.md +363 -0
- package/package.json +5 -4
- package/protocol.mjs +140 -0
- package/schemas/agent/wait.json +4 -0
- package/schemas/plugin/extension-points.json +2 -0
- package/schemas/plugin/plugin.json +2 -0
- package/schemas/plugin/protocol-implementations.json +10 -0
- package/schemas/plugin/protocols.json +11 -0
- package/schemas/protocol/v1/agent.json +69 -0
- package/schemas/protocol/v1/definition.json +57 -0
- package/schemas/protocol/v1/environment.json +105 -0
- package/schemas/protocol/v1/executor.json +279 -0
- package/schemas/protocol/v1/request.json +29 -0
- package/schemas/protocol/v1/response.json +25 -0
- package/schemas/protocol/v1/run.json +75 -0
- package/schemas/protocol/v1/session.json +206 -0
- package/validate.mjs +4 -1
- package/workflow/actions.json +0 -2
- package/workflow/moddle.json +1 -2
- package/workflow/values.json +2 -2
- package/docs/executor-protocol.md +0 -261
- package/executor.mjs +0 -21
- package/schemas/executor/v1/common.json +0 -89
- package/schemas/executor/v1/execution.json +0 -246
- package/schemas/executor/v1/executor.json +0 -98
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# 变更记录
|
|
2
|
+
|
|
3
|
+
按 semver。协议自己的大版本写在协议名里(如 `coda/run@1`),与 npm 包版本、插件清单的 v2 独立;更早的版本见 git 历史。
|
|
4
|
+
|
|
5
|
+
## 3.0.0 — 2026-11-05
|
|
6
|
+
|
|
7
|
+
不兼容变更:
|
|
8
|
+
|
|
9
|
+
- 删除 `executor`、`execution` 两个公共对象协议、`schemas/executor/v1/` 与 `@coda-console/protocol/executor`(`EXECUTOR_PROTOCOL`、`EXECUTION_PROTOCOL`)。
|
|
10
|
+
- 执行请求并入 `coda/executor@1` 的 `execute` 操作,运行改由 `coda/run@1` 表达;不再有 `target`、`executor`、`assignmentId` 绑定,也不回写调用方的记录。
|
|
11
|
+
- 插件清单的 `contributes.protocolImplementations` 从草案里的 `{ kind, version, id }` 改为协议名列表。
|
|
12
|
+
- 删除流程动作 `hand-to-user` 与人工任务的 `coda:handback`;`coda:choice` 的 `id` 不再保留 `handback`。人工任务先给运行所属会话的 Agent 一轮,没答就逐层往上,最上面是用户;`coda:assignee="user"` 与有输入字段的直接到用户。
|
|
13
|
+
|
|
14
|
+
新增:
|
|
15
|
+
|
|
16
|
+
- 协议定义格式与 `schemas/protocol/v1/definition.json`;`protocol.mjs` 导出名字解析、格式化、短名、定义校验与命名空间校验。短名至多 63 个字符,超长的协议名被拒绝,不截断、不哈希。
|
|
17
|
+
- `contributes.protocols`,以及协议名列表形式的 `contributes.protocolImplementations`。
|
|
18
|
+
- 统一调用信封 `schemas/protocol/v1/request.json`、`response.json`;请求带 `parent` 与 `awaited`,记录引用的 `kind` 是协议名。
|
|
19
|
+
- 核心协议 `coda/run@1`、`coda/executor@1`、`coda/agent@1`;`execute` 的源码引用使用 `git/snapshot@1`、`git/source@1`。`coda/run@1` 的 `canceled` 可带 `result`,`failed` 的 `result` 约定为 `{ code, message }`,`code: "unknown"` 表示结局不明。
|
|
20
|
+
- `_coda/wait` 增加可选 `awaited`;Agent 活动默认在等、挡会话静止,`false` 为单向的「不等它了」;Agent 协议按调用只交回一次改写。
|
|
21
|
+
- 核心协议 `coda/session@1`(外部会话:参与者、`head` 游标,操作 `read`、`post`;撤回、编辑、表情用 `about` 指向旧消息)与只读的 `coda/environment@1`(操作 `list`、`read`),导出 `SESSION_PROTOCOL`、`ENVIRONMENT_PROTOCOL`。
|
|
22
|
+
- 操作定义的 `safe: true`:只读、没有副作用、立即给结果,只能与 `result` 一起写;调用双方都不按 `requestId` 留它的请求和回答,重发就再做一次。`coda/session@1` 的 `read` 与 `coda/environment@1` 的 `list`、`read` 标为 `safe`。
|
|
23
|
+
- `coda/session@1` 消息的 `mentions`:回复一条消息就算 @ 了它的发送者,Provider 把被回复消息的发送者也写进来。
|
|
24
|
+
- `docs/protocol.md`:名字、版本、短名推导、调用信封与五个核心协议。
|
|
25
|
+
|
|
26
|
+
## 2.6.0 — 2026-11-07
|
|
27
|
+
|
|
28
|
+
- 工作流卡片的链接接受 iOS OTA 安装链接:新 format `link-url` 接受 https 网址,或 `action=download-manifest` 且 `url` 解码后为 https 网址的 `itms-services:` 链接(#25)。
|
|
29
|
+
|
|
30
|
+
## 2.5.0 — 2026-11-07
|
|
31
|
+
|
|
32
|
+
- 插件清单加 `icon`:插件目录里的 PDF(`light` 必填,`dark`、`template` 可选,同 Agent 的图标),或 SF Symbols 符号加系统色底(`symbol`、`color`)(#24)。
|
|
33
|
+
- `description` 写明是一句话简介,长说明放插件目录的 `README.md`。
|
|
34
|
+
|
|
35
|
+
## 2.4.0 — 2026-11-06
|
|
36
|
+
|
|
37
|
+
- `contributes.views` 加 `frame`:`document` 由客户端整页滚动、横向锁死;`canvas` 铺满视图、自己滚动;不写暂与 `canvas` 相同(#23)。
|
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@ Coda 与插件之间的约定,Coda 和插件都引用它,独立演进:
|
|
|
4
4
|
|
|
5
5
|
- **插件清单的类型**(`schemas/plugin/`):插件目录 `package.json` 里 `contributes` 的每个键是一种类型,各有一份 JSON Schema(draft 2020-12,`$id` 为 `https://coda.pub/schemas/plugin/v2/<文件>`)。`plugin.json` 是整份清单,`setting.json` 是一项设置的声明。插件写的合乎它用到的类型就对;写给别的插件扩展点的键由那个插件声明,扩展点可以带自己的 schema(`extensionPoints.<名>.schema`,声明它的插件目录里的一个文件),写给它的东西合乎那份 schema 才对。
|
|
6
6
|
- **通用校验器**(`validate.mjs`):用 Ajv 对清单做 schema 校验。JSON Schema 说不了的只用五个通用关键字(`x-unique-by`、`x-max-contains`、`x-ref`、`x-placeholders`、`x-file`,照 Kubernetes 的 `x-kubernetes-*`),每个在哪里写都是同一个意思,写法见文件开头。校验器不随功能变长:类型加字段就是改 schema。
|
|
7
|
+
- **协议定义与调用**(`schemas/protocol/`、`protocol.mjs`、`docs/protocol.md`):协议是 `命名空间/名字@大版本` + spec/status 的 JSON Schema + 操作;插件在 `contributes.protocols` 里定义自己命名空间下的协议,在 `contributes.protocolImplementations` 里声明实现哪些协议。调用是 `{ record, operation, input, requestId, parent, awaited }`,回答是 `{ result }` 或 `{ run }`;`coda/run@1`、`coda/executor@1`、`coda/agent@1`、`coda/session@1`、`coda/environment@1` 是五个核心协议。
|
|
7
8
|
- **流程方言**(`workflow/`):项目和插件的流程(`.coda/workflows/*.bpmn`,BPMN 2.0)在 Coda 的命名空间 `https://coda.pub/schema/bpmn/1.0` 里能写什么。`moddle.json` 是 `coda:` 属性与元素(bpmn-moddle 的描述格式),`values.json` 是每个值能写什么(每个 `coda:` 类型的属性组成的对象的 JSON Schema,一个元素里同种 `coda:` 元素成组的 schema),`actions.json` 是 `coda:action` 的各个动作和它们接受的参数,`dialect.json` 是流程种类、Coda 自己发的事件、步骤失败的错误码、表达式能读的运行变量和运行的输入能是哪些类型。`workflow.mjs` 用它们读一份流程:方言里没有的、值不合 schema 的都拒绝,说法是「位置:schema 对那里的说明」。值的 schema 用清单的那几个关键字,另加三个:`x-feel`(是 FEEL:「=」开头是表达式,否则文字里的 `{{ … }}` 是,按这份流程里的名字读得通)、`x-duration`(ISO 8601 时长,不为负)、`x-number`(文字换算成数字是个有限的数)。`structure.json` 声明流程结构规则,`structure.mjs` 负责跨节点检查。
|
|
8
9
|
- **Agent 接入扩展**(`schemas/agent/`、`agent.mjs`、`docs/agent-protocol.md`):Coda 怎样用 ACP 接 Agent,以及 Coda 加的扩展(会话指令、插话、`_coda/wait`、执行失败、工具调用的审核)。
|
|
9
10
|
|
|
@@ -36,6 +37,24 @@ valueProblem('composer-modes.json#/$defs/parameters', parameters, '插件给出
|
|
|
36
37
|
pointProblem(panelsSchema, manifest.contributes.panels, 'contributes.panels', 'plugin');
|
|
37
38
|
```
|
|
38
39
|
|
|
40
|
+
```js
|
|
41
|
+
import {
|
|
42
|
+
RUN_PROTOCOL, EXECUTOR_PROTOCOL, AGENT_PROTOCOL, SESSION_PROTOCOL, ENVIRONMENT_PROTOCOL, CORE_PROTOCOLS,
|
|
43
|
+
definitionProblem, ownedProtocolsProblem, runStatusProblem,
|
|
44
|
+
invocationRequestProblem, invocationResponseProblem,
|
|
45
|
+
parseProtocolName, formatProtocolName, protocolShortName,
|
|
46
|
+
} from '@coda-console/protocol/protocol';
|
|
47
|
+
|
|
48
|
+
parseProtocolName('coda/run@1'); // { namespace: 'coda', name: 'run', major: 1 }
|
|
49
|
+
protocolShortName('coda/run@1'); // 'coda-1run-21'
|
|
50
|
+
definitionProblem(RUN_PROTOCOL); // null,或说明
|
|
51
|
+
ownedProtocolsProblem(manifest); // contributes.protocols 只能在自己的命名空间下
|
|
52
|
+
runStatusProblem({ state: 'completed', result: null }, { state: 'working' }); // 终态不能再变
|
|
53
|
+
invocationRequestProblem({ record: { kind: 'coda/executor@1', id: 'host' }, operation: 'execute', input: {},
|
|
54
|
+
requestId: 'r1', parent: { kind: 'coda/run@1', id: 'caller-run' }, awaited: true });
|
|
55
|
+
invocationResponseProblem({ run: { kind: 'coda/run@1', id: 'run-1' } });
|
|
56
|
+
```
|
|
57
|
+
|
|
39
58
|
```js
|
|
40
59
|
import { workflowProblem, readWorkflow, fieldProblem, fieldsProblem, CODA_FIELDS } from '@coda-console/protocol/workflow';
|
|
41
60
|
|
|
@@ -51,7 +70,7 @@ fieldsProblem(JSON.parse(fieldsJSON), 'ask');
|
|
|
51
70
|
|
|
52
71
|
扩展点的 schema 和这里的并列:可以 `$ref` 协议的 schema(`common.json#/$defs/line40`),可以用五个关键字;它自己写的 `$id` 不算数,指针只指它校验的那份值里的位置。
|
|
53
72
|
|
|
54
|
-
`TYPES` 是 Coda 自己的类型(`contributes` 的键),`SCHEMAS`
|
|
73
|
+
`TYPES` 是 Coda 自己的类型(`contributes` 的键),`SCHEMAS` 是 `schemas/plugin/` 里的全部 schema(按文件名)。协议定义的 schema 在 `schemas/protocol/v1/`,由 `@coda-console/protocol/protocol` 导出。
|
|
55
74
|
|
|
56
75
|
## 插件的后端通道
|
|
57
76
|
|
|
@@ -96,16 +115,22 @@ agentValueProblem('review.json', review, '工具的审核');
|
|
|
96
115
|
深层/大型 JSON 用显式栈检查,非有限数字与循环引用不会通过。会话归属、活动状态迁移、调用起因、协商、超时、重试和授权仍由宿主判断;
|
|
97
116
|
丢弃未知风险值、压缩答复的裁剪与兜底等整理也留在 Coda。详见正文的兼容性与接入说明。
|
|
98
117
|
|
|
99
|
-
##
|
|
118
|
+
## 协议定义与核心协议
|
|
100
119
|
|
|
101
|
-
从
|
|
102
|
-
`
|
|
103
|
-
`
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
120
|
+
从 3.0.0 起,协议是 `命名空间/名字@大版本` + 记录格式(spec、status 的 JSON Schema)+ 操作,见[协议正文](docs/protocol.md)。
|
|
121
|
+
插件用 `contributes.protocols` 定义自己命名空间下的协议,用 `contributes.protocolImplementations` 声明实现哪些协议;
|
|
122
|
+
命名空间 `coda` 保留给核心协议。
|
|
123
|
+
|
|
124
|
+
- **`coda/run@1`**:被调用方自己的运行记录。spec 记录调用的记录、操作、输入、请求 ID、父引用和是否被等待;status 是 `working`、`input-required`、`completed`、`failed`、`canceled`,后三个是终态。`completed`/`failed` 必带 `result`,`failed` 的 `result` 约定为 `{ code, message }`(`code: "unknown"` 表示结局不明),`canceled` 可带取消前的话和留下的东西;另有可选的 `progress` 和等输入时的 `awaiting`。操作是 `cancel`。
|
|
125
|
+
- **`coda/executor@1`**:执行器。操作 `execute` 接一份执行工作并返回运行引用,运行记录在执行器那边;没有 `target`、`executor` 或 `assignmentId` 绑定,也不回写调用方的记录。
|
|
126
|
+
- **`coda/agent@1`**:Agent 资源,spec 照 Coda 的 Agent 资源(`agent`、`title`、`defaultModel`、`models`、`modes` 等),删除 `plugin` 字段;status 为空对象,本版本不定义操作。
|
|
127
|
+
- **`coda/session@1`**:插件提供的外部会话。spec 是标题、容器和可选的环境引用;status 是 `head` 游标与参与者;操作 `read`、`post` 都是立即结果,撤回、编辑、表情是用 `about` 指向旧消息的新消息。
|
|
128
|
+
- **`coda/environment@1`**:插件提供的只读外部环境。spec 带 `actions`;操作 `list` 列目录、`read` 读文件(一次至多 1 MiB)。
|
|
129
|
+
|
|
130
|
+
统一调用是 `{ record: {kind,id}, operation, input, requestId, parent: {kind,id}, awaited }`,回答恰为 `{ result }` 或 `{ run: {kind,id} }` 之一。同一 `requestId` 重发只做一次;慢操作返回运行引用,调用方 watch 运行记录取结果,没有推送或回写。
|
|
131
|
+
|
|
132
|
+
旧 `executor`、`execution` 对象协议与 `@coda-console/protocol/executor` 在 3.0.0 删除;`contributes.executors` 不变,仍用于流程的执行环境 hook。
|
|
133
|
+
协议大版本、npm 包版本与插件清单 v2 独立演进;不提供旧格式兼容代码。
|
|
109
134
|
|
|
110
135
|
## 谁在用
|
|
111
136
|
|
|
@@ -118,6 +143,9 @@ executor 无 target,status 由持有端写;execution 绑定后由执行方
|
|
|
118
143
|
|
|
119
144
|
- 只加东西(新的可选字段、新的类型、放宽限制)升次版本;
|
|
120
145
|
- 改名、删除、收紧(旧的清单会变得不合)升主版本,`$id` 里的 `v1` 随之变成 `v2`。
|
|
146
|
+
- 协议自己的大版本写在协议名里(`coda/run@1`);同一大版本只加可选字段和新操作,改含义或删东西升大版本,新旧可并存。
|
|
147
|
+
|
|
148
|
+
3.0.0 删除了 `executor` 与 `execution`,并把执行请求并入 `coda/executor@1` 的 `execute`;这是不兼容变更,旧代码须改用 `@coda-console/protocol/protocol` 与 `coda/run@1`。
|
|
121
149
|
|
|
122
150
|
改协议就在这里开 PR,说明写清动了哪个类型、旧插件受不受影响;发布后 Coda 与检查包各自升依赖。
|
|
123
151
|
|
package/docs/agent-protocol.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Coda 用 [ACP](https://agentclientprotocol.com)(Agent Client Protocol)接 Agent,要求 Agent 接受[会话指令](#会话指令)(ACP 的 `systemPrompt`),
|
|
4
4
|
可选支持[插话](#插话)(`_session/steering`),另收 Agent 活动报告(`_coda/wait`)、[执行失败事实](#执行失败)(ACP 错误数据里的 `_meta.coda.failure`)和[工具调用的审核](#工具调用的审核)(`_meta.coda.review`)。本文是这份协议的唯一正文,写给要让一个 Agent(比如 Cursor 的)接入 Coda 的人:照它实现,
|
|
5
5
|
Coda 就知道这个 Agent 在一轮之外还在做什么,如实显示、不回收它的进程,把它处理这些东西时的输出、审批和提问放进正确的一轮,
|
|
6
|
-
|
|
6
|
+
并在这次调用结清时把结果只交回一次。产品上这些规则的来由见会话行为契约(Coda 的 docs/session-contracts.md)与完成唤醒契约(Coda 的 docs/subagent-design.md「完成唤醒契约」)。
|
|
7
7
|
|
|
8
8
|
**改协议**:本文在 `coda-console/coda-protocol`,与插件清单的类型(`schemas/`)同一个仓库、同一个版本(npm 包 `@coda-console/protocol`)。Coda 与公开仓库 `coda-console/coda-plugins` 的契约检查包都依赖这个包:改协议就在这里开 PR,发布新版本后两边各自升依赖。检查要换判定方式时(新的请求怎么发、怎样算合格),另给 coda-plugins 开 PR 改检查本身。文中提到的 Coda 文档与源码在 Coda 的仓库里。
|
|
9
9
|
|
|
@@ -54,7 +54,7 @@ Coda 过去静默丢弃的值,契约检查现在可得到具体位置;过去
|
|
|
54
54
|
插件在 `contributes.agents[]` 声明 `lifecycle`,默认 `managed`;外部自主运行的 Bot 声明 `external`。
|
|
55
55
|
这是生命周期的归属,不是任务时长。普通 Agent 的长期委派仍按原有调用关系汇报。
|
|
56
56
|
|
|
57
|
-
- `managed`:Coda
|
|
57
|
+
- `managed`:Coda 按轮次建立回复关系;属于调用的后台活动算在等,挡这次调用结清与会话静止,结束时结果算进这次调用,只交回一次。
|
|
58
58
|
- `external`:Coda 连接适配器,观测原生对话与活动;连接或本地轮次结束不代表外部 Bot 或其调度停止。
|
|
59
59
|
发给它的会话消息是一次委派,附原请求编号和回传地址;没有自动回复或后续跟随,不根据原生发言的时间猜测回复对象。
|
|
60
60
|
需要交回结果时调用 Coda `send`,`childId` 为回传地址,`replyTo` 为原请求编号,`prompt` 为结果,`final` 默认 `true`。
|
|
@@ -62,7 +62,7 @@ Coda 过去静默丢弃的值,契约检查现在可得到具体位置;过去
|
|
|
62
62
|
原委派授权覆盖指定接收方到发起方的回传,Coda 校验这两方与原请求;另发新请求仍走通常授权。
|
|
63
63
|
外部 Agent 使用独立会话,不能被 `spawn` 接管为受管子会话,也不接受 `takeOver` 抢占回复轮次。
|
|
64
64
|
|
|
65
|
-
常驻观测连接及外部运行记录使用 `_coda/wait` 的 `kind: "observation"
|
|
65
|
+
常驻观测连接及外部运行记录使用 `_coda/wait` 的 `kind: "observation"`,保持适配器在线;它不在等,不影响会话静止与调用结清。
|
|
66
66
|
`waiting` 表示正在观测,界面用呼吸状态;有新原生活动要交互时仍以 `handling` 开始、回到 `waiting` 结束自主轮次。
|
|
67
67
|
外部生命周期的原生活动起因记作 `external`,不归到碰巧进行中的 Coda 调用,也不向以前的调用方自动回传。
|
|
68
68
|
`session/cancel` 只表达适配器明确支持的局部停止;插件必须说明它实际停止的对象。
|
|
@@ -183,7 +183,7 @@ HTTP 429 或上游的认证错误分类判断。真正的认证失败仍沿用 A
|
|
|
183
183
|
Coda 按该类别显示「额度不足」,保留完整原因,不安排自动重试;这个类别不要求 `input`,即使带了也不进入服务故障重试。
|
|
184
184
|
该回执确认本轮因额度不足而结束,轮次记为 `ended`、`stopReason: quota_exhausted` 并保留 `error`,操作记为 `completed`;
|
|
185
185
|
操作已结算不代表任务成功,子会话向调用方交回 `failed`。两端同一原因只显示一次,不再标作「执行结果未知」。
|
|
186
|
-
交回 `failed`
|
|
186
|
+
交回 `failed` 的状态文案为「失败」,涵盖准备与执行阶段。调用结清前,后续轮次的额度错误仍连同原因算进这次调用的结果,即使没有正文或还有其他活动在等;结清后不再另交。
|
|
187
187
|
插件以普通执行错误返回(例如 -32603),不得把额度耗尽伪装成要求重新登录的 -32000。
|
|
188
188
|
恢复条件(等待窗口重置、补充额度等)由插件放在原因中,重置时刻按[文字里的时刻](#文字里的时刻)写;上游没有给出确切恢复时间时,不推算时间。
|
|
189
189
|
|
|
@@ -289,10 +289,10 @@ Coda 存的就是这段文字,两端客户端显示时按看的那台设备的
|
|
|
289
289
|
|
|
290
290
|
## Agent 活动
|
|
291
291
|
|
|
292
|
-
`session/prompt` 的回复结束一轮,也就是 Agent
|
|
292
|
+
`session/prompt` 的回复结束一轮,也就是 Agent 说眼下的信息它处理完了;这一轮结束不代表调用完成,Coda 还要等这次调用树下在等的东西都回来,才结清并只交回一次。
|
|
293
293
|
一轮之后 Agent 还可能有东西在进行:放到后台的命令、派出去的子 Agent、到点会叫醒它的定时。ACP 不说这些,Coda 看不见就会把会话
|
|
294
294
|
显示成空闲、回收它的进程,也不知道它们之后叫醒 Agent 的那一轮属于哪次调用。Agent 活动报告让 Agent 把这些告诉 Coda,
|
|
295
|
-
|
|
295
|
+
每一样一项,从开始到结束;默认在等、挡会话静止与调用结清([规则](#规则)第 2 条),`awaited: false`、反复的定时与观测除外。
|
|
296
296
|
|
|
297
297
|
### 能力协商
|
|
298
298
|
|
|
@@ -317,7 +317,7 @@ Agent 发给 Coda 的通知(没有 `id`,不回复),和 `session/update`
|
|
|
317
317
|
| `sessionId` | 是 | 它属于哪个会话:本会话,或 Coda 已经认得的子会话(之前某项活动的 `childSessionId`)。子 Agent 自己起的活动从子 Agent 的会话报,起因记为那个子 Agent([规则](#规则)第 1 条)。别的会话的一律丢弃 |
|
|
318
318
|
| `waitId` | 是 | Agent 自己取的身份,同一会话内不重复,至多 200 字 |
|
|
319
319
|
| `state` | 是 | `waiting`、`handling`、`done`、`failed`、`cancelled`,见下 |
|
|
320
|
-
| `kind` | 否 | `task`(默认)、`subagent`、`timer`,或别的词(按 `task` 算);第一次报告时定下,之后可以省略,改了也按第一次的算 |
|
|
320
|
+
| `kind` | 否 | `task`(默认)、`subagent`、`timer`、`observation`,或别的词(按 `task` 算);第一次报告时定下,之后可以省略,改了也按第一次的算 |
|
|
321
321
|
| `title` | 否 | 给人看的名字,至多 500 字 |
|
|
322
322
|
| `detail` | 否 | 说明:任务在做什么,定时按什么计划触发;至多 4000 字。其中的时刻按[文字里的时刻](#文字里的时刻)写 |
|
|
323
323
|
| `stoppable` | 否 | Coda 能不能经 [`_coda/wait/stop`](#_codawaitstop) 停它,默认不能 |
|
|
@@ -327,9 +327,12 @@ Agent 发给 Coda 的通知(没有 `id`,不回复),和 `session/update`
|
|
|
327
327
|
| `toolCallId` | 否 | 启动它的那次工具调用,同一会话里的 `toolCallId`:任务详情据此显示启动命令;它没结束时,那次调用缺结果也不被收束为结果未确认。后台命令的原调用保留 Agent 报的状态,记录 `backgroundTaskId` 关联任务;展示为已转入后台,不再计入前台执行 |
|
|
328
328
|
| `at` | `timer` 知道时带 | 下次触发的时刻,ISO 8601。不带时会话底部的定时一行只写 `detail`(没有就是标题),不显示下次时间;定时照样登记,到点仍由 Agent 报 `handling` |
|
|
329
329
|
| `recurring` | 否 | 定时是否反复触发 |
|
|
330
|
+
| `awaited` | 否 | 是否在等;省略按 `kind`(见下表)。`false` 即「不等它了」:照样登记、显示,但不参与调用完成与会话静止,结束时结果只记下,不叫醒谁 |
|
|
330
331
|
|
|
331
332
|
缺必填字段、`state` 不在上表、字段过长或 `at` 读不出时间的,整条丢弃,不报错。之后的报告只需带变了的字段,没带的保持原样。
|
|
332
333
|
|
|
334
|
+
`awaited` 省略时按 `kind`:`task` 与其他词(`observation` 除外)、`subagent`、一次性 `timer` 在等;反复的 `timer` 与 `observation` 不等。第一次报告或之后任何一次都可以报 `false`;报了 `false` 之后再报 `true` 不算,不等是单向的。Coda 也可能替用户或父会话把一项改成不等,Agent 不会收到通知。
|
|
335
|
+
|
|
333
336
|
| `state` | 含义 |
|
|
334
337
|
| --- | --- |
|
|
335
338
|
| `waiting` | 在等,Agent 没在处理它 |
|
|
@@ -338,11 +341,12 @@ Agent 发给 Coda 的通知(没有 `id`,不回复),和 `session/update`
|
|
|
338
341
|
|
|
339
342
|
`kind` 决定 Coda 把它当成什么,不只是怎么显示:
|
|
340
343
|
|
|
341
|
-
| `kind` | Coda 当它是 | 显示 | 会话的事实(Coda 的 docs/session-contracts.md「事件」) |
|
|
342
|
-
| --- | --- | --- | --- |
|
|
343
|
-
| `task`
|
|
344
|
-
| `subagent` | 委派 | 委派清单(Coda 的 docs/subagent-design.md「委派清单」)里的一项(`kind: task`),点开是它的过程视图,子会话的输出都归它;圆环「等待后续结果」,同子会话 | `background` |
|
|
345
|
-
| `timer` | 定时唤醒 | 会话底部的定时一行(计划、是否反复);不进历史 | `scheduled`,不算 `background` |
|
|
344
|
+
| `kind` | Coda 当它是 | 显示 | 会话的事实(Coda 的 docs/session-contracts.md「事件」) | 默认是否在等 |
|
|
345
|
+
| --- | --- | --- | --- | --- |
|
|
346
|
+
| `task` 与其他词(除 `observation`) | 后台命令 | 发起记录留在原位,任务等待时沉底、结束时留在自己的结束位置;`stoppable` 时有停止按钮;圆环「后台任务运行中」 | `background` | 是 |
|
|
347
|
+
| `subagent` | 委派 | 委派清单(Coda 的 docs/subagent-design.md「委派清单」)里的一项(`kind: task`),点开是它的过程视图,子会话的输出都归它;圆环「等待后续结果」,同子会话 | `background` | 是 |
|
|
348
|
+
| `timer` | 定时唤醒 | 会话底部的定时一行(计划、是否反复);不进历史 | `scheduled`,不算 `background` | 一次性是,反复的不等 |
|
|
349
|
+
| `observation` | 常驻观测 | 呼吸状态,保持适配器在线 | `observing`,不算 `background` | 否 |
|
|
346
350
|
|
|
347
351
|
```json
|
|
348
352
|
{"jsonrpc":"2.0","method":"_coda/wait","params":{"sessionId":"s1","waitId":"build-1","kind":"task","state":"waiting","title":"构建","detail":"npm run build","stoppable":true,"outputFile":"/tmp/build-1.log"}}
|
|
@@ -350,6 +354,7 @@ Agent 发给 Coda 的通知(没有 `id`,不回复),和 `session/update`
|
|
|
350
354
|
{"jsonrpc":"2.0","method":"_coda/wait","params":{"sessionId":"s1","waitId":"build-1","state":"done"}}
|
|
351
355
|
{"jsonrpc":"2.0","method":"_coda/wait","params":{"sessionId":"s1","waitId":"review","kind":"subagent","state":"waiting","title":"评审改动","childSessionId":"s1/review","stoppable":true}}
|
|
352
356
|
{"jsonrpc":"2.0","method":"_coda/wait","params":{"sessionId":"s1","waitId":"hourly","kind":"timer","state":"waiting","title":"每小时看一次 CI","at":"2026-10-12T10:00:00Z","recurring":true}}
|
|
357
|
+
{"jsonrpc":"2.0","method":"_coda/wait","params":{"sessionId":"s1","waitId":"watch-1","kind":"task","state":"waiting","title":"看日志","detail":"tail -f build.log","awaited":false}}
|
|
353
358
|
```
|
|
354
359
|
|
|
355
360
|
### `_coda/wait/stop`
|
|
@@ -357,7 +362,7 @@ Agent 发给 Coda 的通知(没有 `id`,不回复),和 `session/update`
|
|
|
357
362
|
请求参数和答复见 [wait-stop.json](../schemas/agent/wait-stop.json)。
|
|
358
363
|
|
|
359
364
|
Coda 发给 Agent 的请求,参数 `{ "sessionId": …, "waitId": … }`,Agent 回 `{}`。只对声明了 `stoppable` 的活动发:
|
|
360
|
-
用户点了任务或子 Agent
|
|
365
|
+
用户点了任务或子 Agent 的停止、父会话取消这次调用时它树下的项。
|
|
361
366
|
回复只表示收到;Coda 不当它已经停了,直到 Agent 随后用 `_coda/wait` 报它结束(通常是 `cancelled`)。
|
|
362
367
|
|
|
363
368
|
### 规则
|
|
@@ -366,23 +371,23 @@ Coda 发给 Agent 的请求,参数 `{ "sessionId": …, "waitId": … }`,Age
|
|
|
366
371
|
起因是那个子 Agent 的这次运行,不论报来时有没有轮次在进行。没有轮次在进行、又不是子 Agent 起的,起因未知(见起因(Coda 的 docs/session-contracts.md「起因」)):
|
|
367
372
|
Agent 在一轮之外自己开始干活,就要在这一轮里报 `handling` 说明是为哪一项(第 3 条);说不出来时自造的那一项起因未知。
|
|
368
373
|
它归起因沿链走得到的那次调用:父会话派来的那一轮里登记的,归那次调用;用户直接发的消息那一轮里登记的,不归父会话的调用;
|
|
369
|
-
|
|
370
|
-
2.
|
|
371
|
-
|
|
372
|
-
|
|
374
|
+
起因未知的属于所在的会话,不算任何一次调用。
|
|
375
|
+
2. **在等**:活动在进行时会话不算静止,所属调用也不结清(会话静止(Coda 的 docs/session-contracts.md「会话静止」)):
|
|
376
|
+
调用要等这些活动结束、并且它们叫醒的那一轮收尾之后才完成,结果只交回一次。报 `awaited: false` 的不等:不参与调用完成与会话静止。
|
|
377
|
+
活动在进行时进程不被空闲回收,`!` 命令不执行,会话照实显示。
|
|
373
378
|
3. **处理(`handling`)**:Agent 在一轮之外处理活动时,Coda 为它开一轮自主轮次。这一轮的起因是最先进入 `handling` 的那一项,
|
|
374
|
-
|
|
379
|
+
所以这一轮属于那一项的调用,它说的话算进这次调用的结果,调用结清时只交回一次。这一轮进行中别的项进入 `handling`,并入这一轮,起因不变。所有项都离开 `handling`
|
|
375
380
|
(回到 `waiting`,或结束)时这一轮结束。这一轮里 Agent 的输出、审批与提问都归它,子会话发来的也一样;用户这时发的消息排队,等这一轮结束再送。
|
|
376
381
|
在 Coda 发起的一轮(`session/prompt`)进行中进入 `handling` 的,算在那一轮里;那一轮结束时还有项在 `handling`,接着开一轮自主轮次。
|
|
377
382
|
用户停止这一轮时,Coda 对本会话发 `session/cancel`:Agent 应停止处理,把这些项改回 `waiting` 或报结束;这一轮随之结束,
|
|
378
383
|
因为分不清停止和做完谁先到,结果记为未知。30 秒内这一轮还没结束,Coda 关掉托管连接与它的进程组,结果未知,不自动重跑。
|
|
379
384
|
4. **定时**:`kind: timer` 带 `recurring`,知道下次触发的时刻就带 `at`。到点时报 `handling`,处理完反复的回到 `waiting`(可以带新的 `at`),
|
|
380
385
|
一次性的报 `done`。`at` 是触发时刻,不是期限:到点没报不算过期。父会话取消这次调用时,它树下 `stoppable` 的定时经 `_coda/wait/stop` 停掉,
|
|
381
|
-
其余的 Coda
|
|
386
|
+
其余的 Coda 不删除,改成不等,并如实告诉父会话留下了哪几个(要删得请 Agent 自己删);到点它们仍会唤醒 Agent,但不再属于这次调用,结果不再交回。
|
|
382
387
|
5. **子会话与继续**:`childSessionId` 让 Coda 认得那个会话。子 Agent 结束后,Agent 以新的 `waitId`、同一个 `childSessionId` 再登记一次,
|
|
383
388
|
就是继续同一个子 Agent:委派清单里还是那一项,多一次运行,这一次的起因是再登记时进行的那一轮。
|
|
384
389
|
6. **进程结束**:Agent 进程结束(崩溃、停止超时被关、空闲回收、机器重启),它所有没结束的活动以 `disconnected` 结束,结果未知,
|
|
385
|
-
Coda
|
|
390
|
+
Coda 不重放;这次调用按结果未知收尾(`failed` 的 `result.code: "unknown"`),只交回一次。后端重启而托管还在时一切照旧:活动、`handling` 的那一轮都接回,
|
|
386
391
|
后端不在期间的 `_coda/wait` 从托管日志续读,各只算一次。
|
|
387
392
|
7. **会话加载中**:`session/new`、`session/load` 期间发来的 `_coda/wait` 先存着,会话身份确定后按原顺序处理,只收本会话与这些登记里公告的子会话。
|
|
388
393
|
所以 Agent 恢复会话时可以把还在等的东西重报一遍:同一个 `waitId` 再报 `waiting` 不会多登记一项。
|
|
@@ -433,7 +438,7 @@ Agent、模型、强度、审批档位、其他配置、标题和任务全文;
|
|
|
433
438
|
|
|
434
439
|
允许后在目标目录建根会话(`shared` 用原目录,`worktree` 从卡片写明的默认分支新建工作树),第一条消息就是 `prompt`,审批档位保留卡片批准的参数,不跟随 Bot;标题固定为批准的标题。
|
|
435
440
|
没有 parent,但首条任务建立发起会话的一次调用(沿用 `send` 的会话间回复机制)。任务完成或失败后,结果自动送回并唤醒发起会话;
|
|
436
|
-
|
|
441
|
+
这次任务引发的后续仍算在这次调用里,结清时只交回一次;用户在新会话里另发的消息仍回复用户。PR 事件的 `coda.session` 仍采用新会话自己的 Agent 与配置。
|
|
437
442
|
会话数据的 `initiatedBy` 保存 `{threadId, title, reference}`,表示「由哪个会话发起」,不附带旧上下文;回复关系由首条任务的调用保存。
|
|
438
443
|
`reference` 是发起会话的 `coda://threads/…`。两端客户端尚未显示这个来源字段。
|
|
439
444
|
|