dsh-a2a-server 0.1.1 → 0.3.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 +28 -0
- package/CHANGELOG.zh-CN.md +28 -0
- package/README.md +151 -54
- package/README.zh-CN.md +113 -53
- package/cordis.patch.yml +10 -6
- package/lib/briefing.d.ts +39 -0
- package/lib/briefing.d.ts.map +1 -0
- package/lib/briefing.js +108 -0
- package/lib/briefing.js.map +1 -0
- package/lib/config.d.ts +69 -22
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +76 -6
- package/lib/config.js.map +1 -1
- package/lib/contexts.d.ts +9 -4
- package/lib/contexts.d.ts.map +1 -1
- package/lib/contexts.js +7 -13
- package/lib/contexts.js.map +1 -1
- package/lib/index.d.ts +1 -26
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +420 -408
- package/lib/index.js.map +1 -1
- package/lib/management.d.ts +5 -0
- package/lib/management.d.ts.map +1 -0
- package/lib/management.js +74 -0
- package/lib/management.js.map +1 -0
- package/lib/projection.d.ts +67 -22
- package/lib/projection.d.ts.map +1 -1
- package/lib/projection.js +30 -11
- package/lib/projection.js.map +1 -1
- package/lib/protocol/card.d.ts +25 -7
- package/lib/protocol/card.d.ts.map +1 -1
- package/lib/protocol/card.js +35 -14
- package/lib/protocol/card.js.map +1 -1
- package/lib/protocol/index.d.ts +10 -10
- package/lib/protocol/index.d.ts.map +1 -1
- package/lib/protocol/index.js +8 -8
- package/lib/protocol/index.js.map +1 -1
- package/lib/protocol/jsonrpc.d.ts +54 -6
- package/lib/protocol/jsonrpc.d.ts.map +1 -1
- package/lib/protocol/jsonrpc.js +70 -8
- package/lib/protocol/jsonrpc.js.map +1 -1
- package/lib/protocol/parse.d.ts +79 -0
- package/lib/protocol/parse.d.ts.map +1 -0
- package/lib/protocol/parse.js +249 -0
- package/lib/protocol/parse.js.map +1 -0
- package/lib/protocol/sse.d.ts +6 -3
- package/lib/protocol/sse.d.ts.map +1 -1
- package/lib/protocol/sse.js +4 -2
- package/lib/protocol/sse.js.map +1 -1
- package/lib/protocol/wire.d.ts +165 -54
- package/lib/protocol/wire.d.ts.map +1 -1
- package/lib/protocol/wire.js +54 -9
- package/lib/protocol/wire.js.map +1 -1
- package/lib/router.d.ts +55 -1
- package/lib/router.d.ts.map +1 -1
- package/lib/router.js +419 -137
- package/lib/router.js.map +1 -1
- package/lib/security.d.ts +37 -3
- package/lib/security.d.ts.map +1 -1
- package/lib/security.js +48 -4
- package/lib/security.js.map +1 -1
- package/lib/state.d.ts +37 -0
- package/lib/state.d.ts.map +1 -0
- package/lib/state.js +146 -0
- package/lib/state.js.map +1 -0
- package/lib/tasks.d.ts +4 -0
- package/lib/tasks.d.ts.map +1 -1
- package/lib/tasks.js +23 -5
- package/lib/tasks.js.map +1 -1
- package/lib/types.d.ts +12 -3
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +1 -1
- package/lib/types.js.map +1 -1
- package/lib/version.d.ts +20 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/version.js +20 -0
- package/lib/version.js.map +1 -0
- package/lib/workspace-read.d.ts +9 -0
- package/lib/workspace-read.d.ts.map +1 -0
- package/lib/workspace-read.js +152 -0
- package/lib/workspace-read.js.map +1 -0
- package/package.json +39 -30
- package/lib/protocol/normalize.d.ts +0 -72
- package/lib/protocol/normalize.d.ts.map +0 -1
- package/lib/protocol/normalize.js +0 -278
- package/lib/protocol/normalize.js.map +0 -1
package/README.zh-CN.md
CHANGED
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
<p align="center">
|
|
16
16
|
<a href="https://www.npmjs.com/package/dsh-a2a-server"><img src="https://img.shields.io/npm/v/dsh-a2a-server?style=flat&label=npm&color=CB3837" alt="npm 版本"></a>
|
|
17
17
|
<a href="https://github.com/huangjuhua-aigc/dsh-a2a/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-2EA44F?style=flat" alt="MIT License"></a>
|
|
18
|
-
<img src="https://img.shields.io/badge/A2A-
|
|
19
|
-
<img src="https://img.shields.io/badge/DSH-0.1
|
|
20
|
-
<img src="https://img.shields.io/badge/tests-
|
|
18
|
+
<img src="https://img.shields.io/badge/A2A-v1.0%20JSON--RPC-4D6BFE?style=flat" alt="A2A v1.0 JSON-RPC 绑定">
|
|
19
|
+
<img src="https://img.shields.io/badge/DSH-0.2.1--rc.2-4493F8?style=flat" alt="基于 DSH 0.2.1-rc.2 构建">
|
|
20
|
+
<img src="https://img.shields.io/badge/tests-217-2EA44F?style=flat" alt="217 项测试">
|
|
21
21
|
</p>
|
|
22
22
|
|
|
23
23
|
`dsh-a2a-server` 让 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
24
24
|
上的 agent 可以通过 [A2A(Agent2Agent)](https://a2a-protocol.org)协议被访问。它在
|
|
25
|
-
well-known 路径发布 Agent Card,并实现 **
|
|
25
|
+
well-known 路径发布 Agent Card,并实现 **v1.0 JSON-RPC 绑定**——任何知道本部署
|
|
26
26
|
URL 的合规 peer 都能发现这个 agent 并向它提交任务。
|
|
27
27
|
|
|
28
28
|
本插件**只做入站**:从不主动连接其他 agent,没有 client、没有 peer 目录、没有 A2A
|
|
@@ -30,12 +30,16 @@ subagent provider。它是 `ctx.agents` 之上的传输适配层,不是能力
|
|
|
30
30
|
|
|
31
31
|
## 安装
|
|
32
32
|
|
|
33
|
+
需要本机配置界面或跨网络访问时,先看配套 [Talk2MyAgent 使用说明](https://github.com/huangjuhua-aigc/Talk2MyAgent)。
|
|
34
|
+
访客读取权限、自动简报、主人 IPC 与 Tailscale 部署详见[部署与迁移指南](https://github.com/huangjuhua-aigc/dsh-a2a/blob/main/docs/public-access-hardening.md)。
|
|
35
|
+
|
|
33
36
|
```sh
|
|
34
|
-
dsh plugin --profile web add dsh-a2a-server
|
|
37
|
+
dsh plugin --profile web add dsh-a2a-server@0.3.0
|
|
35
38
|
```
|
|
36
39
|
|
|
37
40
|
`dsh plugin` 会在 profile 目录里转发给 pnpm,并把这个 bundle 追加进
|
|
38
|
-
`dsh.profile.bundles`——因为包中声明了 `dsh.bundle
|
|
41
|
+
`dsh.profile.bundles`——因为包中声明了 `dsh.bundle`。自 DSH v0.2.1-alpha.1 起,
|
|
42
|
+
`--profile` 必须放在所有 pnpm 参数之前——上面的写法已经是正确的。
|
|
39
43
|
|
|
40
44
|
若想直接使用本地检出,把路径指过去即可:
|
|
41
45
|
|
|
@@ -48,12 +52,25 @@ dsh plugin --profile web add ./path/to/dsh-a2a-server
|
|
|
48
52
|
| `ctx.agents` | `dsh-base` |
|
|
49
53
|
| `ctx.credentials` | `dsh-base` |
|
|
50
54
|
| `ctx.webServer` | **`dsh-web-app`** |
|
|
51
|
-
| `ctx.
|
|
55
|
+
| `ctx.tools` 和 `ctx.systemPrompt` | 必需的访客工具及提示词隔离服务 |
|
|
56
|
+
| `ctx.sessionProjections`(可选) | 组合层;提供任务生命周期投影 |
|
|
52
57
|
|
|
53
|
-
|
|
58
|
+
必需服务齐备之前,插件保持 PENDING。`ctx.webServer` 由 `dsh-web-app` 提供而不在
|
|
54
59
|
`dsh-base` 中,因此 `headless` profile 需要先挂载 `@deepseek-ai/dsh-host-webserver`。
|
|
55
60
|
`dsh --profile <name> --dump-config` 可以打印组合出来的配置行。
|
|
56
61
|
|
|
62
|
+
### 从 0.2.x 升级
|
|
63
|
+
|
|
64
|
+
0.3.0 适配 DSH `>=0.2.1-rc.2 <0.3.0`。先停止 agent,将
|
|
65
|
+
`dsh-a2a-server@0.3.0` 安装到原有 profile,再重新启动;配套 Portal 也需更新。
|
|
66
|
+
主人 RPC 和监控已改为需要认证的本机 IPC,公网 HTTP 不接受主人凭据。
|
|
67
|
+
访客可聊天并读取授权目录,其他工具关闭;空白名单 `trustedPeers: []` 拒绝所有访客。
|
|
68
|
+
任务结果与空闲会话在保留期内可跨驱逐和重启恢复。
|
|
69
|
+
|
|
70
|
+
新版 [Talk2MyAgent Portal](https://github.com/huangjuhua-aigc/Talk2MyAgent) 默认开启每小时简报更新,
|
|
71
|
+
用一个开关控制,完成后直接写入 `.hop/handoff.md`。单独安装协议插件而未配置 `briefing`
|
|
72
|
+
不会自动执行简报任务。详见 [0.3.0 发布说明](https://github.com/huangjuhua-aigc/dsh-a2a/blob/main/CHANGELOG.zh-CN.md)。
|
|
73
|
+
|
|
57
74
|
## 快速开始
|
|
58
75
|
|
|
59
76
|
仓库自带的示例组合会运行真实模型并启动一个监听服务。
|
|
@@ -88,9 +105,10 @@ curl -s http://127.0.0.1:9922/.well-known/agent-card.json
|
|
|
88
105
|
curl -s http://127.0.0.1:9922/a2a \
|
|
89
106
|
-H "authorization: Bearer demo123" \
|
|
90
107
|
-H 'content-type: application/json' \
|
|
91
|
-
-
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
-H 'a2a-version: 1.0' \
|
|
109
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"SendMessage","params":{
|
|
110
|
+
"message":{"messageId":"m1","role":"ROLE_USER",
|
|
111
|
+
"parts":[{"text":"hello"}]}}}'
|
|
94
112
|
```
|
|
95
113
|
|
|
96
114
|
| 变量 | 默认值 | 含义 |
|
|
@@ -98,10 +116,10 @@ curl -s http://127.0.0.1:9922/a2a \
|
|
|
98
116
|
| `A2A_PEERS` | `alice` | `名字[:token]` 列表;每个 peer 都必须有 token |
|
|
99
117
|
| `A2A_PORT` | `9900` | 监听端口 |
|
|
100
118
|
| `A2A_SEND_MODE` | `block` | `block` 或 `immediate` |
|
|
101
|
-
| `A2A_WORKSPACE_ROOT` | 临时目录 | per-peer 工作目录的父目录 |
|
|
119
|
+
| `A2A_WORKSPACE_ROOT` | 临时目录 | 访客授权资料目录,同时作为 per-peer 工作目录的父目录 |
|
|
102
120
|
| `DEEPSEEK_MODEL` | `deepseek-v4-flash` | 向适配器请求的模型 id |
|
|
103
121
|
|
|
104
|
-
一次性探针会对运行中的服务执行
|
|
122
|
+
一次性探针会对运行中的服务执行 67 项检查,任何一项不符即以非零码退出:
|
|
105
123
|
|
|
106
124
|
```sh
|
|
107
125
|
pnpm probe # 默认 :9922 / demo123
|
|
@@ -115,21 +133,42 @@ node example/probe.mjs http://127.0.0.1:9922 demo123
|
|
|
115
133
|
| `/.well-known/agent-card.json` | GET | 默认公开 |
|
|
116
134
|
| `/.well-known/agent.json` | GET | 默认公开 |
|
|
117
135
|
| `{basePath}`(默认 `/a2a`) | POST | 必须携带 Bearer |
|
|
136
|
+
| `{basePath}/admin/contexts[/<id>]` | GET | 仅本机 IPC + admin token,公网 HTTP 不挂载 |
|
|
118
137
|
|
|
119
|
-
| JSON-RPC 方法 |
|
|
138
|
+
| JSON-RPC 方法 | 状态 |
|
|
139
|
+
| --- | --- |
|
|
140
|
+
| `SendMessage` | 是否等待逐请求协商 |
|
|
141
|
+
| `SendStreamingMessage` | SSE |
|
|
142
|
+
| `GetTask` | 幂等;结算后仍可应答 |
|
|
143
|
+
| `ListTasks` | 游标分页、可过滤;包括保留期内的持久化任务 |
|
|
144
|
+
| `CancelTask` | 取消正在执行的 turn |
|
|
145
|
+
| `SubscribeToTask` | 续订活任务;终态任务返回 `-32004` |
|
|
146
|
+
| `GetExtendedAgentCard` | 已认证 peer 可见的额外 skill;未配置时 `-32007` |
|
|
147
|
+
| `*TaskPushNotificationConfig` | `-32003` |
|
|
148
|
+
|
|
149
|
+
**只提供 A2A v1.0。** v0.3 的方法名、`kind` 判别字段、小写枚举、嵌套 `file`
|
|
150
|
+
part 是被**删除**而不是做了别名:本服务写出的每一个回包都是 v1.0 JSON,v0.3
|
|
151
|
+
客户端本就读不懂,所以“应答一个 v0.3 请求”只会让故障离成因更远。已退役的方法回
|
|
152
|
+
`-32601` 并直接告知新名字;显式的 `A2A-Version: 0.3` 回 `-32009`
|
|
153
|
+
(`VersionNotSupportedError`)。不带 `A2A-Version` 头的请求按 1.0 处理——这是本接口
|
|
154
|
+
在 Card 上声明的唯一版本。
|
|
155
|
+
|
|
156
|
+
具体到线上,与 v0.3 的差异:
|
|
157
|
+
|
|
158
|
+
| 关注点 | v0.3 | 本服务的 v1.0 |
|
|
120
159
|
| --- | --- | --- |
|
|
121
|
-
|
|
|
122
|
-
| `
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
160
|
+
| 任务引用 | `params.taskId` | `params.id` |
|
|
161
|
+
| `SendMessage` 结果 | 裸 `Task` | `{ "task": … }` |
|
|
162
|
+
| 任务状态 | `"working"` | `"TASK_STATE_WORKING"` |
|
|
163
|
+
| 消息角色 | `"user"` | `"ROLE_USER"` |
|
|
164
|
+
| Part | `{"kind":"text","text":…}` | `{"text":…}`;文件 part 展平为 `url`/`raw`/`filename`/`mediaType` |
|
|
165
|
+
| 流帧 | `{"kind":"status-update",…,"final":true}` | `{"statusUpdate":{…}}`;流关闭即终态信号 |
|
|
166
|
+
| 流首帧 | 一帧非终态 status update | `Task` 对象本身 |
|
|
167
|
+
| 等待控制 | `configuration.blocking` | `configuration.returnImmediately`(语义反转,默认等待) |
|
|
168
|
+
| Card 端点 | `url` + `preferredTransport` | `supportedInterfaces[]`,每条自带 `protocolVersion` |
|
|
169
|
+
| Card 鉴权 | `securitySchemes` + `security` | scheme 包在 `httpAuthSecurityScheme` 里;改用 `securityRequirements` |
|
|
170
|
+
| 扩展 Card | `supportsAuthenticatedExtendedCard` | `capabilities.extendedAgentCard` |
|
|
171
|
+
| A2A 错误细节 | 无 | `error.data[]` 携带 `google.rpc.ErrorInfo`,含 `reason` 与 `domain` |
|
|
133
172
|
|
|
134
173
|
入站消息可携带 text、file、data 三类 part。file 与 data 会以方括号引用的形式进入模型
|
|
135
174
|
上下文。回复为纯文本。
|
|
@@ -145,18 +184,17 @@ node example/probe.mjs http://127.0.0.1:9922 demo123
|
|
|
145
184
|
config:
|
|
146
185
|
basePath: /a2a
|
|
147
186
|
publicUrl: https://agents.example.com/a2a # 写入 Card 的对外地址
|
|
148
|
-
protocolVersion: 0.3.0
|
|
149
187
|
provider: deepseek-official
|
|
150
188
|
model: deepseek-v4-flash
|
|
151
189
|
|
|
152
190
|
card:
|
|
153
191
|
name: dsh-harness
|
|
154
|
-
description:
|
|
192
|
+
description: 读取授权目录中的代码和资料,回答访客问题。
|
|
155
193
|
public: true
|
|
156
194
|
skills:
|
|
157
195
|
- id: general
|
|
158
196
|
name: general
|
|
159
|
-
description:
|
|
197
|
+
description: 对话与授权目录内的文件读取。
|
|
160
198
|
tags: [coding, research]
|
|
161
199
|
provider:
|
|
162
200
|
organization: Example Inc.
|
|
@@ -188,21 +226,26 @@ node example/probe.mjs http://127.0.0.1:9922 demo123
|
|
|
188
226
|
| --- | --- | --- |
|
|
189
227
|
| `basePath` | `/a2a` | JSON-RPC 路由 |
|
|
190
228
|
| `publicUrl` | 由 `Host` 推导 | 写入 Card 的可路由地址 |
|
|
191
|
-
| `protocolVersion` | `0.3.0` | Card 上声明的协议版本 |
|
|
192
229
|
| `provider` · `model` | — | 本服务创建的每个 agent 使用的模型路由 |
|
|
193
230
|
| `card.public` | `true` | 无需凭据即可获取 Card |
|
|
194
231
|
| `card.skills` | `[]` | 声明的 skills;为空时回退到一条 `general` |
|
|
232
|
+
| `card.extendedSkills` | `[]` | 只对已认证 peer 经 `GetExtendedAgentCard` 公开的 skills |
|
|
195
233
|
| `peers` | `{}` | 身份 → 凭据**引用名** |
|
|
196
|
-
| `trustedPeers` | 全部已认证身份 |
|
|
234
|
+
| `trustedPeers` | 全部已认证身份 | 对话与受限文件读取白名单;`[]` 拒绝所有访客 |
|
|
197
235
|
| `rateLimitPerMinute` | `60` | 按身份的滑动窗口 |
|
|
198
236
|
| `maxContextTurns` | `5` | 单个 context 接受的消息数上限,超出后 `rejected` |
|
|
199
237
|
| `sendMode` | `block` | 客户端未表态时的默认行为 |
|
|
200
|
-
| `blockTimeoutMs` | `60000` |
|
|
238
|
+
| `blockTimeoutMs` | `60000` | 最长阻塞等待;到期返回任务当前状态,客户端可继续查询 |
|
|
201
239
|
| `contextIdleTtlMs` | `1800000` | context 的 agent 被释放前的空闲时长 |
|
|
202
240
|
| `maxResidentContexts` | `64` | 常驻 context 数量上限 |
|
|
203
241
|
| `isolation.workspaceMode` | `per-peer` | `per-peer` 或 `shared` |
|
|
204
|
-
| `isolation.workspaceRoot` | — |
|
|
205
|
-
| `isolation.peerWorkspaces` | `{}` |
|
|
242
|
+
| `isolation.workspaceRoot` | — | 必填;授权资料目录,同时作为访客 cwd 的父目录或共享 cwd |
|
|
243
|
+
| `isolation.peerWorkspaces` | `{}` | 按身份覆盖工作目录和授权读取范围 |
|
|
244
|
+
| `preamble.files` | `[".hop/handoff.md"]` | 主人背景简报文件(**agent 级**:相对工作区根目录解析,全体访客共用一份;绝对路径直通),合并进每个 context 的首条访客消息;文件不存在则跳过 |
|
|
245
|
+
| `briefing.prompt` | — | 可选的单次简报更新指令,由 Portal 配置,通过有执行预算的主人 agent 每小时运行 |
|
|
246
|
+
| `briefing.settingsFile` | — | 绝对路径;读取 `{ "enabled": boolean }` 设置,缺省开启,每 5 秒检查 |
|
|
247
|
+
| `admin.tokenEnv` | — | 本机主人 RPC 和监控的凭据引用,公网 RPC 拒绝此凭据 |
|
|
248
|
+
| `admin.socketPath` | 按部署生成 | Windows 命名管道或私有 Unix socket |
|
|
206
249
|
| `push.enabled` | `false` | 保留字段,见[边界](#边界) |
|
|
207
250
|
|
|
208
251
|
以下情况在加载期即被拒绝:缺少 `isolation.workspaceRoot`;peer 名不匹配
|
|
@@ -220,7 +263,8 @@ peers:
|
|
|
220
263
|
|
|
221
264
|
```yaml
|
|
222
265
|
# ~/.dsh/.credentials.yaml
|
|
223
|
-
|
|
266
|
+
refs:
|
|
267
|
+
A2A_PEER_ALICE: <32-byte-hex-from-openssl-rand>
|
|
224
268
|
```
|
|
225
269
|
|
|
226
270
|
`ctx.credentials` 在每次请求时跨四层解析该引用——进程环境、托管文档、`<cwd>/.env`、
|
|
@@ -234,11 +278,18 @@ A2A_PEER_ALICE: <32-byte-hex-from-openssl-rand>
|
|
|
234
278
|
| --- | --- | --- |
|
|
235
279
|
| 模型上下文 | 一个 peer 的对话不会进入另一个 peer 的模型请求 | 不同 `contextId` → 不同 Session → 不同 log |
|
|
236
280
|
| 协议访问 | peer 无法读取、续接或取消他人的 context 与任务 | 按认证身份判定归属 |
|
|
237
|
-
| 工具层 |
|
|
281
|
+
| 工具层 | 仅提供受控 `read_file`,不开放写入、命令、联网或跨会话工具 | 屏蔽继承工具、专用读取工具、执行校验 |
|
|
282
|
+
| 提示词 | 访客不继承可选的主人个性化提示与运行时上下文 | 独立的公共系统提示词 |
|
|
283
|
+
|
|
284
|
+
`per-peer`(默认)依据 `workspaceRoot` 为每个身份派生独立 `cwd`;`shared` 使用同一个目录。
|
|
285
|
+
这只是工作目录策略,不是文件系统沙箱。`read_file` 的读取范围默认是用户选择的
|
|
286
|
+
`workspaceRoot`,有 `peerWorkspaces` 覆盖时限制为该访客的专属目录。工具相对路径从
|
|
287
|
+
这个资料目录解析;插件私有状态目录始终排除。
|
|
238
288
|
|
|
239
|
-
`
|
|
240
|
-
|
|
241
|
-
|
|
289
|
+
`read_file({"path":"."})` 列出资料目录;文件支持 UTF-8 文本,按 `offset`/`limit`
|
|
290
|
+
分页。单文件上限 2 MiB,单次最多 32000 字符、500 行/项,目录扫描最多 1000 项。
|
|
291
|
+
拒绝越界、符号链接/junction、硬链接和 Windows ADS。主人维护能力使用独立本机 IPC,
|
|
292
|
+
保留可信管理工具,不能从公网入口调用。资源配额的完整配置表见英文 README。
|
|
242
293
|
|
|
243
294
|
## 边界
|
|
244
295
|
|
|
@@ -246,14 +297,16 @@ A2A_PEER_ALICE: <32-byte-hex-from-openssl-rand>
|
|
|
246
297
|
- 只提供 JSONRPC 绑定。不提供 gRPC 与 HTTP+JSON,Card 上如实声明。
|
|
247
298
|
- 未实现推送通知。`push.enabled` 仅决定推送方法返回哪个错误码,Card 上声明
|
|
248
299
|
`pushNotifications: false`。
|
|
249
|
-
-
|
|
300
|
+
- 不支持 `stateTransitionHistory`、协议扩展与 Card 签名。
|
|
250
301
|
- 流式只推送已提交的 assistant 消息,未实现逐 chunk 推送。
|
|
251
|
-
-
|
|
252
|
-
|
|
302
|
+
- 有并发准入、任务期限及模型调用预算;超时后等待底层适配器完成取消才释放执行名额。
|
|
303
|
+
不响应取消的适配器仍需进程级监管,这些额度不是按货币计费的预算。
|
|
304
|
+
- 访客仅能使用有目录边界的 `read_file`;改变沙箱模式不会自动开放其他工具。
|
|
305
|
+
该工具边界不替代针对恶意本机管理员的操作系统隔离。
|
|
253
306
|
- 触及 token 上限的任务结算为 `completed`,真实的 turn 结束原因放在
|
|
254
307
|
`Task.metadata.dsh.stopReason`——A2A 的状态枚举无法表达它。
|
|
255
|
-
-
|
|
256
|
-
|
|
308
|
+
- 任务结果与空闲会话在保留期内可跨进程重启恢复;中断的任务标记失败,不重放。
|
|
309
|
+
- 每个 context 同时只允许一个任务,并发提交返回 409;messageId 不是提交去重键。
|
|
257
310
|
- `ctx.webServer` 不提供 TLS。任何非回环地址的暴露都应置于反向代理之后。
|
|
258
311
|
- 修改配置会重启插件并取消进行中的任务。
|
|
259
312
|
|
|
@@ -262,8 +315,8 @@ A2A_PEER_ALICE: <32-byte-hex-from-openssl-rand>
|
|
|
262
315
|
```
|
|
263
316
|
src/
|
|
264
317
|
├── protocol/ 零依赖库:不碰 Cordis、不碰 HTTP、不碰 harness
|
|
265
|
-
│ ├── wire.ts A2A
|
|
266
|
-
│ ├──
|
|
318
|
+
│ ├── wire.ts A2A v1.0 词汇表:只有一种形状,不需要翻译
|
|
319
|
+
│ ├── parse.ts 入站解析与方法表
|
|
267
320
|
│ ├── jsonrpc.ts 信封框架与 A2A 错误码
|
|
268
321
|
│ ├── card.ts Agent Card 构造
|
|
269
322
|
│ └── sse.ts SSE 帧编码
|
|
@@ -273,6 +326,10 @@ src/
|
|
|
273
326
|
├── tasks.ts 任务槽位与三段式 turn 关联
|
|
274
327
|
├── projection.ts 在 session log 上折叠出的 a2aTask 读模型
|
|
275
328
|
├── security.ts 认证、限流、注入去势、外发脱敏
|
|
329
|
+
├── workspace-read.ts 授权目录内受限的 read_file
|
|
330
|
+
├── management.ts 本机 IPC 主人 RPC 与监控
|
|
331
|
+
├── state.ts 持久化任务及对话 checkpoint
|
|
332
|
+
├── briefing.ts 每小时简报更新与持久化调度
|
|
276
333
|
├── config.ts schema,以及加载期就会拒绝的跨字段校验
|
|
277
334
|
└── types.ts 向 SessionEventMap / MessageSourceMap 的声明合并
|
|
278
335
|
```
|
|
@@ -286,17 +343,18 @@ src/
|
|
|
286
343
|
历史。
|
|
287
344
|
|
|
288
345
|
**驻留是显式管理的。** HTTP 没有连接生命周期,因此每个 `contextId` 对应一个 Activation,
|
|
289
|
-
|
|
346
|
+
空闲后被驱逐。私有 checkpoint 保留任务结果与对话历史,冷恢复时创建新的 harness session。
|
|
290
347
|
|
|
291
348
|
## 开发
|
|
292
349
|
|
|
293
350
|
```sh
|
|
294
351
|
pnpm install
|
|
295
352
|
pnpm typecheck
|
|
296
|
-
pnpm test #
|
|
353
|
+
pnpm test # 15 个文件共 217 项测试
|
|
297
354
|
pnpm serve # 启动监听服务
|
|
298
|
-
pnpm probe # 对运行中的服务执行
|
|
355
|
+
pnpm probe # 对运行中的服务执行 67 项检查
|
|
299
356
|
pnpm build # 产出 lib/
|
|
357
|
+
pnpm test:package # 仅声明运行依赖时验证构建产物导入
|
|
300
358
|
```
|
|
301
359
|
|
|
302
360
|
端到端测试会启动真实的 Cordis 组合与真实的 agent loop,并通过 HTTP 驱动它;模型使用
|
|
@@ -308,13 +366,15 @@ pnpm build # 产出 lib/
|
|
|
308
366
|
|
|
309
367
|
官方项目提供 agent 运行时、插件系统,以及本插件所消费的各个能力接缝。本项目提供:
|
|
310
368
|
|
|
311
|
-
- 入站的 A2A
|
|
312
|
-
- Agent Card
|
|
369
|
+
- 入站的 A2A v1.0 JSON-RPC 绑定
|
|
370
|
+
- Agent Card 构造与入站请求解析
|
|
313
371
|
- A2A task 与 harness turn 之间的映射
|
|
314
372
|
- 按 peer 的认证、隔离与工作目录策略
|
|
315
373
|
|
|
316
|
-
harness 处于 pre-release
|
|
317
|
-
|
|
374
|
+
harness 处于 pre-release 阶段,不承诺跨重命名或重新打包的兼容性,因此兼容性通过
|
|
375
|
+
`engines.dsh`(`>=0.2.1-rc.2 <0.3.0`)加上按 range 声明的 `@deepseek-ai/dsh-*`
|
|
376
|
+
peer 依赖来表达:安装预检会拒绝任何插件未曾适配过的组合,而这个 range 也放行后续
|
|
377
|
+
所有的 0.2.x 补丁版本。
|
|
318
378
|
|
|
319
379
|
## 社区交流
|
|
320
380
|
|
package/cordis.patch.yml
CHANGED
|
@@ -7,12 +7,15 @@
|
|
|
7
7
|
# REQUIRES ctx.webServer, which ships in `dsh-web-app`, NOT in `dsh-base`. On a
|
|
8
8
|
# profile without it this row loads but stays PENDING (Cordis holds a plugin
|
|
9
9
|
# whose injected services are absent), so nothing serves and nothing errors.
|
|
10
|
+
#
|
|
11
|
+
# NOTE: keep this file plain YAML — the installer's package validation parses
|
|
12
|
+
# it with a strict loader that rejects `!!js` expressions, even though the
|
|
13
|
+
# runtime overlay loader accepts them.
|
|
10
14
|
- insert:
|
|
11
15
|
- id: a2a-server
|
|
12
16
|
name: dsh-a2a-server
|
|
13
17
|
config:
|
|
14
18
|
basePath: /a2a
|
|
15
|
-
protocolVersion: '0.3.0'
|
|
16
19
|
card:
|
|
17
20
|
name: dsh-harness
|
|
18
21
|
description: A DeepSeek Harness agent reachable over A2A.
|
|
@@ -20,11 +23,12 @@
|
|
|
20
23
|
skills: []
|
|
21
24
|
peers: {}
|
|
22
25
|
isolation:
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
26
|
+
# Each peer gets its own working directory. This is not a filesystem
|
|
27
|
+
# sandbox: read_file separately restricts reads to the selected root,
|
|
28
|
+
# or to a peerWorkspaces override. Other visitor tools are disabled.
|
|
29
|
+
# This placeholder is overridden by any real deployment layer (the
|
|
30
|
+
# console's overlay sets it per agent); supply an absolute path.
|
|
27
31
|
workspaceMode: per-peer
|
|
28
|
-
workspaceRoot:
|
|
32
|
+
workspaceRoot: /srv/dsh/a2a
|
|
29
33
|
push:
|
|
30
34
|
enabled: false
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare const BRIEFING_INTERVAL_MS: number;
|
|
2
|
+
interface LegacyBriefingScheduler {
|
|
3
|
+
catalog(): Promise<Array<{
|
|
4
|
+
id: string;
|
|
5
|
+
sessionId: string;
|
|
6
|
+
title: string;
|
|
7
|
+
prompt: string;
|
|
8
|
+
}>>;
|
|
9
|
+
delete(request: {
|
|
10
|
+
id: string;
|
|
11
|
+
sessionId: string;
|
|
12
|
+
}): Promise<unknown>;
|
|
13
|
+
}
|
|
14
|
+
/** Retire only the old Portal-generated job for this exact project. */
|
|
15
|
+
export declare function retireLegacyBriefing(scheduler: LegacyBriefingScheduler | undefined, root: string): Promise<void>;
|
|
16
|
+
export declare class AutomaticBriefing {
|
|
17
|
+
private readonly options;
|
|
18
|
+
private timer;
|
|
19
|
+
private closed;
|
|
20
|
+
private running;
|
|
21
|
+
private enabled;
|
|
22
|
+
private nextRunAt;
|
|
23
|
+
private readonly stateFile;
|
|
24
|
+
constructor(options: {
|
|
25
|
+
settingsFile: string;
|
|
26
|
+
stateDirectory: string;
|
|
27
|
+
run: () => Promise<void>;
|
|
28
|
+
warn: (message: string) => void;
|
|
29
|
+
now?: () => number;
|
|
30
|
+
});
|
|
31
|
+
private save;
|
|
32
|
+
private readEnabled;
|
|
33
|
+
/** Polling also observes an off/on switch without restarting the agent. */
|
|
34
|
+
tick(): Promise<void>;
|
|
35
|
+
start(): void;
|
|
36
|
+
stop(): void;
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=briefing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"briefing.d.ts","sourceRoot":"","sources":["../src/briefing.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,oBAAoB,QAAiB,CAAA;AAGlD,UAAU,uBAAuB;IAC/B,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;IAC3F,MAAM,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACrE;AAED,uEAAuE;AACvE,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,uBAAuB,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUtH;AAED,qBAAa,iBAAiB;IAQhB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAO;IACtB,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;gBAEL,OAAO,EAAE;QACpC,YAAY,EAAE,MAAM,CAAA;QACpB,cAAc,EAAE,MAAM,CAAA;QACtB,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;QACxB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;QAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;KACnB;IAWD,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,WAAW;IAWnB,2EAA2E;IACrE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B,KAAK,IAAI,IAAI;IAOb,IAAI,IAAI,IAAI;CAIb"}
|
package/lib/briefing.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/** One automatic briefing loop owned by the online agent, independent of Portal. */
|
|
2
|
+
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
export const BRIEFING_INTERVAL_MS = 60 * 60 * 1000;
|
|
5
|
+
const CHECK_INTERVAL_MS = 5000;
|
|
6
|
+
/** Retire only the old Portal-generated job for this exact project. */
|
|
7
|
+
export async function retireLegacyBriefing(scheduler, root) {
|
|
8
|
+
if (!scheduler?.catalog || !scheduler.delete)
|
|
9
|
+
return;
|
|
10
|
+
const prefix = `【简报维护任务】受信任的项目范围只有一个:\n ${root}\n`;
|
|
11
|
+
for (const task of await scheduler.catalog()) {
|
|
12
|
+
if (task.title === '简报维护' && task.prompt.startsWith(prefix)
|
|
13
|
+
&& (task.prompt.includes('4. 把简报写入当前工作目录的 handoff.draft.md')
|
|
14
|
+
|| task.prompt.includes('4. 完整生成并检查上述内容后,直接覆盖写入当前工作目录的 handoff.md。'))) {
|
|
15
|
+
await scheduler.delete({ id: task.id, sessionId: task.sessionId });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class AutomaticBriefing {
|
|
20
|
+
options;
|
|
21
|
+
timer;
|
|
22
|
+
closed = false;
|
|
23
|
+
running = false;
|
|
24
|
+
enabled = true;
|
|
25
|
+
nextRunAt = 0;
|
|
26
|
+
stateFile;
|
|
27
|
+
constructor(options) {
|
|
28
|
+
this.options = options;
|
|
29
|
+
mkdirSync(options.stateDirectory, { recursive: true, mode: 0o700 });
|
|
30
|
+
this.stateFile = join(options.stateDirectory, 'briefing-state.json');
|
|
31
|
+
try {
|
|
32
|
+
const state = JSON.parse(readFileSync(this.stateFile, 'utf8'));
|
|
33
|
+
if (typeof state.enabled !== 'boolean' || !Number.isSafeInteger(state.nextRunAt) || state.nextRunAt < 0)
|
|
34
|
+
throw new Error('invalid briefing state');
|
|
35
|
+
this.enabled = state.enabled;
|
|
36
|
+
this.nextRunAt = state.nextRunAt;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error.code !== 'ENOENT')
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
save() {
|
|
44
|
+
const temporary = `${this.stateFile}.tmp`;
|
|
45
|
+
try {
|
|
46
|
+
writeFileSync(temporary, JSON.stringify({ enabled: this.enabled, nextRunAt: this.nextRunAt }), { mode: 0o600 });
|
|
47
|
+
renameSync(temporary, this.stateFile);
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
rmSync(temporary, { force: true });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
readEnabled() {
|
|
54
|
+
try {
|
|
55
|
+
const value = JSON.parse(readFileSync(this.options.settingsFile, 'utf8'));
|
|
56
|
+
if (typeof value.enabled !== 'boolean')
|
|
57
|
+
throw new Error('invalid automatic briefing setting');
|
|
58
|
+
return value.enabled;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (error.code === 'ENOENT')
|
|
62
|
+
return true;
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Polling also observes an off/on switch without restarting the agent. */
|
|
67
|
+
async tick() {
|
|
68
|
+
if (this.closed)
|
|
69
|
+
return;
|
|
70
|
+
try {
|
|
71
|
+
const enabled = this.readEnabled();
|
|
72
|
+
const now = this.options.now?.() ?? Date.now();
|
|
73
|
+
if (enabled !== this.enabled) {
|
|
74
|
+
this.enabled = enabled;
|
|
75
|
+
if (enabled)
|
|
76
|
+
this.nextRunAt = now;
|
|
77
|
+
this.save();
|
|
78
|
+
}
|
|
79
|
+
if (!enabled || this.running || now < this.nextRunAt)
|
|
80
|
+
return;
|
|
81
|
+
// Persist before paid work: restarting must not immediately repeat a run.
|
|
82
|
+
this.nextRunAt = now + BRIEFING_INTERVAL_MS;
|
|
83
|
+
this.save();
|
|
84
|
+
this.running = true;
|
|
85
|
+
try {
|
|
86
|
+
await this.options.run();
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
this.running = false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
this.options.warn(`a2a: automatic briefing failed: ${String(error)}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
start() {
|
|
97
|
+
if (this.closed || this.timer)
|
|
98
|
+
return;
|
|
99
|
+
this.timer = setInterval(() => { void this.tick(); }, CHECK_INTERVAL_MS);
|
|
100
|
+
this.timer.unref();
|
|
101
|
+
void this.tick();
|
|
102
|
+
}
|
|
103
|
+
stop() {
|
|
104
|
+
this.closed = true;
|
|
105
|
+
clearInterval(this.timer);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=briefing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"briefing.js","sourceRoot":"","sources":["../src/briefing.ts"],"names":[],"mappings":"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"}
|
package/lib/config.d.ts
CHANGED
|
@@ -15,40 +15,39 @@ export interface PeerConfig {
|
|
|
15
15
|
/** Credential reference name, NOT the token itself. */
|
|
16
16
|
tokenEnv: string;
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
19
|
-
* How peers are kept from reaching each other.
|
|
20
|
-
*
|
|
21
|
-
* DEFERRED — a tool deny-list (`session_search`, `session_event_search`,
|
|
22
|
-
* `session_trace`, `session_event_trace`, `session_event_read`, `list_agents`)
|
|
23
|
-
* plus a named `unsafeAllowCrossSessionSearch` escape hatch for single-peer
|
|
24
|
-
* deployments. Both were designed as defense in depth behind `workspaceMode`,
|
|
25
|
-
* and neither is declared here until it is enforced: a security knob that
|
|
26
|
-
* silently does nothing is worse than no knob at all.
|
|
27
|
-
*/
|
|
18
|
+
/** Working directories and the data roots exposed through the scoped reader. */
|
|
28
19
|
export interface IsolationConfig {
|
|
29
20
|
/**
|
|
30
|
-
* `per-peer` gives each identity its own cwd
|
|
31
|
-
*
|
|
32
|
-
* `shared` is the collaborative posture and must be chosen deliberately.
|
|
21
|
+
* `per-peer` gives each identity its own cwd. Neither mode is a filesystem
|
|
22
|
+
* security boundary. read_file enforces its own canonical data-root boundary.
|
|
33
23
|
*/
|
|
34
24
|
workspaceMode: 'per-peer' | 'shared';
|
|
35
|
-
/**
|
|
25
|
+
/** Shared read-only data root; also the cwd parent in `per-peer` mode. */
|
|
36
26
|
workspaceRoot: string;
|
|
37
|
-
/**
|
|
27
|
+
/** Overrides both a peer's cwd and its authorized read root. */
|
|
38
28
|
peerWorkspaces: Record<string, string>;
|
|
39
29
|
}
|
|
30
|
+
/** One declared skill, as it appears on the Agent Card. */
|
|
31
|
+
export interface SkillConfig {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
description: string;
|
|
35
|
+
tags: string[];
|
|
36
|
+
}
|
|
40
37
|
/** Agent Card content and exposure. */
|
|
41
38
|
export interface CardConfig {
|
|
42
39
|
name: string;
|
|
43
40
|
description: string;
|
|
44
41
|
/** Serve the card without a credential, as discovery expects. */
|
|
45
42
|
public: boolean;
|
|
46
|
-
skills:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
skills: SkillConfig[];
|
|
44
|
+
/**
|
|
45
|
+
* Skills revealed only through `GetExtendedAgentCard`, after a peer has
|
|
46
|
+
* authenticated. Declaring any turns on `capabilities.extendedAgentCard`;
|
|
47
|
+
* leaving this empty means the deployment has no extended card, and the
|
|
48
|
+
* method answers with the spec's own ExtendedAgentCardNotConfiguredError.
|
|
49
|
+
*/
|
|
50
|
+
extendedSkills: SkillConfig[];
|
|
52
51
|
provider?: {
|
|
53
52
|
organization: string;
|
|
54
53
|
url: string;
|
|
@@ -73,11 +72,32 @@ export interface PushConfig {
|
|
|
73
72
|
*/
|
|
74
73
|
enabled: boolean;
|
|
75
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* The host's background briefing, injected when a visitor's context opens.
|
|
77
|
+
*
|
|
78
|
+
* The files are read once per Activation (best effort: an absent file is the
|
|
79
|
+
* normal "nothing to hand over" case) and merged into the context's FIRST
|
|
80
|
+
* visitor message rather than sent as their own turn — one model call is
|
|
81
|
+
* spared, and the turn counters stay about the visitor's messages only.
|
|
82
|
+
*/
|
|
83
|
+
export interface PreambleConfig {
|
|
84
|
+
/** Publication-safe paths relative to the workspace root; absolute paths pass through. */
|
|
85
|
+
files: string[];
|
|
86
|
+
}
|
|
87
|
+
/** Local-only monitoring surface credentials. */
|
|
88
|
+
export interface AdminConfig {
|
|
89
|
+
/**
|
|
90
|
+
* Credential REFERENCE name holding the admin token, NOT the token itself.
|
|
91
|
+
* Empty or absent means the monitoring surface stays unmounted.
|
|
92
|
+
*/
|
|
93
|
+
tokenEnv: string;
|
|
94
|
+
/** Local named pipe / Unix socket. Never served on the public HTTP carrier. */
|
|
95
|
+
socketPath?: string;
|
|
96
|
+
}
|
|
76
97
|
/** The whole plugin configuration. */
|
|
77
98
|
export interface A2AServerConfig {
|
|
78
99
|
basePath: string;
|
|
79
100
|
publicUrl?: string;
|
|
80
|
-
protocolVersion: string;
|
|
81
101
|
/**
|
|
82
102
|
* Provider route for every agent this server creates. Optional so another
|
|
83
103
|
* `agent/request` listener may supply the target instead; a runnable
|
|
@@ -95,7 +115,34 @@ export interface A2AServerConfig {
|
|
|
95
115
|
blockTimeoutMs: number;
|
|
96
116
|
contextIdleTtlMs: number;
|
|
97
117
|
maxResidentContexts: number;
|
|
118
|
+
maxConcurrentTasks: number;
|
|
119
|
+
maxConcurrentTasksPerPeer: number;
|
|
120
|
+
maxTasksPerPeerPerDay: number;
|
|
121
|
+
taskTimeoutMs: number;
|
|
122
|
+
maxModelCallsPerTask: number;
|
|
123
|
+
maxOutputTokens: number;
|
|
124
|
+
maxInputChars: number;
|
|
125
|
+
maxOutputChars: number;
|
|
126
|
+
streamHeartbeatMs: number;
|
|
127
|
+
maxStreamsPerTask: number;
|
|
128
|
+
maxStreamBufferBytes: number;
|
|
129
|
+
storage: {
|
|
130
|
+
directory?: string;
|
|
131
|
+
retentionMs: number;
|
|
132
|
+
maxContexts: number;
|
|
133
|
+
maxContextBytes: number;
|
|
134
|
+
};
|
|
98
135
|
isolation: IsolationConfig;
|
|
136
|
+
preamble: PreambleConfig;
|
|
137
|
+
/** Optional Portal-managed automatic updates; omission leaves the transport inert. */
|
|
138
|
+
briefing?: {
|
|
139
|
+
settingsFile: string;
|
|
140
|
+
prompt: string;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Enables owner RPC and monitoring on private local IPC, never public HTTP.
|
|
144
|
+
*/
|
|
145
|
+
admin?: AdminConfig;
|
|
99
146
|
push: PushConfig;
|
|
100
147
|
}
|
|
101
148
|
export declare const Config: Schema<A2AServerConfig>;
|