@tbox.cn/dsh-acp-bridge-core 0.0.0-stage → 0.1.0-rc.2

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/lib/index.d.ts ADDED
@@ -0,0 +1,524 @@
1
+ import { AgentCapabilities, AvailableCommand, PromptResponse, SessionConfigOption, SessionUpdate } from "@agentclientprotocol/sdk";
2
+ import { SessionEvent } from "@deepseek-ai/dsh-session";
3
+ import { SandboxMode } from "@deepseek-ai/dsh-sandbox";
4
+ import { ApprovalPolicy } from "@deepseek-ai/dsh-user-approval";
5
+
6
+ //#region src/classification.d.ts
7
+ type Classification = 'project' | 'skip';
8
+ /**
9
+ * 事件分类表。
10
+ *
11
+ * project(11):user/message · assistant/message · tool/call · tool/result ·
12
+ * todo/write · session/title · command/run · command/done · subagent/catalog ·
13
+ * turn/start · turn/end(来源:[acp-projection-contract] 投影基准表)。
14
+ *
15
+ * skip 防自产回声显式项:sandbox/mode / permission/preset(桥动作引发)·
16
+ * model/selection(set_config_option 经 api selectModel 自产)。
17
+ * skip 语义注记项:subagent/descriptor(落子日志,决策 subagent-composition-mapping)·
18
+ * goal/change(goal_state 走载体 ext 面,标准面零投影)。
19
+ * compaction 族等未导入 owner 包的词汇走 unknown fallback(降级分级后跳过)。
20
+ */
21
+ declare const CLASSIFICATION: {
22
+ 'user/message': "project";
23
+ 'assistant/message': "project";
24
+ 'tool/call': "project";
25
+ 'tool/result': "project";
26
+ 'todo/write': "project";
27
+ 'session/title': "project";
28
+ 'command/run': "project";
29
+ 'command/done': "project";
30
+ 'subagent/catalog': "project";
31
+ 'turn/start': "project";
32
+ 'turn/end': "project";
33
+ 'step/start': "skip";
34
+ 'step/end': "skip";
35
+ 'developer/message': "skip";
36
+ 'system/message': "skip";
37
+ 'assistant/attempt': "skip";
38
+ 'request/header': "skip";
39
+ 'request/context': "skip";
40
+ 'session/end-seed': "skip";
41
+ 'agent/inbox/spliced': "skip";
42
+ 'tool/ptc-dispatch-start': "skip";
43
+ 'tool/ptc-dispatch': "skip";
44
+ 'subagent/descriptor': "skip";
45
+ 'approval/asked': "skip";
46
+ 'approval/decided': "skip";
47
+ 'approval/policy': "skip";
48
+ 'permission/preset': "skip";
49
+ 'sandbox/mode': "skip";
50
+ 'model/selection': "skip";
51
+ 'goal/change': "skip";
52
+ };
53
+ type ClassifiedEventType = keyof typeof CLASSIFICATION;
54
+ /** 运行时查表:'project' | 'skip' | 'unknown'(未登记词汇,投影入口分级记档后跳过)。 */
55
+ declare function classify(type: string): Classification | 'unknown';
56
+ /** 事件是否 ignorable(dsh informational 记录标记——unknown 降级分级的判据)。 */
57
+ declare function isIgnorable(event: {
58
+ ignorable?: true;
59
+ }): boolean;
60
+ //#endregion
61
+ //#region src/kinds.d.ts
62
+ /**
63
+ * 工具呈现映射——kind 静态表 · locations 门控列 · title 构造器。
64
+ *
65
+ * kind 判定 = bridge-core 自建名字→kind 静态映射(移植基线 TOOL_KIND_MAP,
66
+ * 键面适配 dsh 原生工具名;dsh 呈现层 GenericCallView.kind 是呈现层字段而非
67
+ * 事件流字段,WS 载体不可依赖——决策 [acp-projection-contract] tool_call 行)。
68
+ * 前缀规则:`subagent_` 族 → other(多实例委派工具);`scratch_` 家族镜像
69
+ * bash / write / edit 原型(形态签名呈现的 kind 对位,决策
70
+ * [plan-mode-sandbox-composition] 工具呈现映射节)。
71
+ *
72
+ * locations 规则照抄基线 0.9.20 `toLocations` 门控(input 派生 + [edit, write]
73
+ * 白名单;决策 [dependency-baseline-refresh]——真源 = LOCATIONS_ALLOWED 列,
74
+ * scratch 两件显式 true;dsh meta locations 通道不消费)。
75
+ *
76
+ * title 构造器逐字移植基线(agent/tool/title.ts),键面适配 dsh 名
77
+ * (todo_write / web_fetch / web_search),行为基线 = "verb + object"。
78
+ */
79
+ /** ACP ToolCallKind 词面(对齐 @agentclientprotocol/sdk v1 稳定面)。 */
80
+ type ToolCallKind = 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'think' | 'fetch' | 'other';
81
+ /** locations 白名单列(投影基准表真源;基线 0.9.20 `[edit, write]` + scratch 两件显式 true)。 */
82
+ declare const LOCATIONS_ALLOWED: Set<string>;
83
+ declare function toolKind(name: string): ToolCallKind;
84
+ /**
85
+ * Build ACP tool-call locations from a tool's input.
86
+ *
87
+ * 照抄基线 0.9.20 `toLocations`(projector.ts:155-182):input 派生 +
88
+ * 白名单门控——read/glob/grep 接受目录路径,客户端(zed < fix)对每个
89
+ * location 做 eager 解析会以目录为根建隐藏 worktree 无界扫描(25GB+ 实测);
90
+ * 目录能力工具的 location 是放大器,2026-10-12 起移除。
91
+ */
92
+ declare function toLocations(name: string, input: unknown): Array<{
93
+ path: string;
94
+ line: number | null;
95
+ }>;
96
+ /** Tool title builders——configuration-driven,新工具加一行(基线逐字移植 + dsh 名面)。 */
97
+ declare const TOOL_TITLE_BUILDERS: Record<string, (i: Record<string, unknown>) => string>;
98
+ /**
99
+ * Build a tool title from tool name + input(基线同款语义:known 工具 =
100
+ * "verb + object";未知工具与 MCP 动态工具回落工具名;pending 无 input 时
101
+ * 返回裸动词)。
102
+ */
103
+ declare function buildToolTitle(name: string, input: unknown): string;
104
+ /**
105
+ * 子透传工具 title 前缀(基线 withSubagentPrefix 对位——subagent-native-adoption
106
+ * 收官补齐):`[label|sid后8位] title`。label 缺席(catalog 未到达 / 无 label)
107
+ * 回落 `subagent:<childId 后 8 位>` 中立标签,不猜。
108
+ */
109
+ declare function withSubagentPrefix(title: string, label: string | undefined, childId: string): string;
110
+ /**
111
+ * 解析 tool/call 的 arguments 原始 JSON 字符串(dsh 承诺 unparsed 原样——
112
+ * 解析失败返回 undefined,投影降级为无 input 形态,不抛错)。
113
+ */
114
+ declare function parseToolArguments(argumentsJson: string | undefined): Record<string, unknown> | undefined;
115
+ //#endregion
116
+ //#region src/errors.d.ts
117
+ /**
118
+ * 错误码映射表——dsh RPC 词汇 → ACP 错误面。
119
+ *
120
+ * 基线词汇(openacpagent core/errors.ts + adapter.ts mapSdkError)为语义真源,
121
+ * dsh RPC 词汇(session/writer-held / RemoteError code 体系)为输入,ACP 错误面
122
+ * (JSON-RPC error codes / RequestError / stopReason)为输出。
123
+ * 纯数据返回(结构兼容 RequestError 构造参数),载体包装抛出——直借 RequestError
124
+ * class 为 value import 破运行时零依赖,否决(决策 [bridge-typing-boundary-hardening])。
125
+ *
126
+ * 已知 dsh 错误判别键为语义键(载体层从 Error.code / Error 形态归一后传入);
127
+ * code 值域的精确枚举随载体接线以真实错误样本校准(投影核心切片依赖面登记)。
128
+ */
129
+ /** JSON-RPC 错误码(ACP / JSON-RPC 2.0 标准面 + ACP 扩展段)。 */
130
+ declare const RpcErrorCode: {
131
+ readonly methodNotFound: -32601;
132
+ readonly invalidParams: -32602;
133
+ readonly conflict: -32600;
134
+ readonly internal: -32603;
135
+ readonly sessionNotFound: -32002;
136
+ };
137
+ interface RpcErrorData {
138
+ code: number;
139
+ message: string;
140
+ data?: Record<string, unknown>;
141
+ }
142
+ /** 载体层归一后的错误输入(Error 的 code / message / 附加 data)。 */
143
+ interface RpcErrorInput {
144
+ /** dsh 语义错误键:session/writer-held · session-not-found · retry-after-turn · llm-auth · … */
145
+ code?: string;
146
+ message?: string;
147
+ data?: unknown;
148
+ }
149
+ /**
150
+ * 错误码映射(八行含默认行,表格驱动单测逐行):
151
+ *
152
+ * | 语义 | dsh 输入 | ACP 输出 |
153
+ * | 会话不存在 | session-not-found | -32002 + data.uri(session:<id> 形态) |
154
+ * | 会话被持有 | session/writer-held | -32600 + data{reason, retryable: true} |
155
+ * | turn 失败 | agent/error / RemoteError | -32603 + data{sessionId, kind, retryable, code?, partialOutput} |
156
+ * | 凭据缺失 | llm-auth | -32603 + data.kind = 'auth'(turn 内失败,非连接级) |
157
+ * | 重载进行中 | retry-after-turn | -32603 + data{retryable: true, reason: 'skill_reload_in_progress'} |
158
+ * | 方法未实现 | method-not-found(backlog 面) | -32601 |
159
+ * | 参数非法 | invalid-params(含 zod 校验信息) | -32602 + data.errors 形态对齐基线 `_errors` |
160
+ * | 未知 dsh 错误 | 其余 | -32603 + data.kind = 'unknown-dsh-error' + 原始 code / data 透传 |
161
+ */
162
+ declare function mapRpcError(input: RpcErrorInput): RpcErrorData;
163
+ declare function stopReasonFromTurnEnd(reason: {
164
+ kind: string;
165
+ } | undefined): {
166
+ stopReason: 'end_turn' | 'cancelled' | 'max_tokens' | 'refusal';
167
+ warn?: string;
168
+ } | {
169
+ error: true;
170
+ };
171
+ //#endregion
172
+ //#region src/protocol.d.ts
173
+ /** 支持的 ACP 协议版本集(协议版本恒 1——SDK 1.x 系是 schema 版本非协议版本)。 */
174
+ declare const PROTOCOL_VERSIONS: readonly number[];
175
+ /** 当前最新协议版本(协商回落值)。 */
176
+ declare const LATEST_PROTOCOL_VERSION: number;
177
+ /**
178
+ * 协议版本协商:客户端版本在支持集内原样回,否则回最新(调用方按 warn 标记记档)。
179
+ */
180
+ declare function negotiateProtocolVersion(clientVersion: number | undefined): {
181
+ version: number;
182
+ warn?: string;
183
+ };
184
+ /**
185
+ * agent 能力面(initialize 响应)。
186
+ *
187
+ * loadSession = true(load 回放编排为首期冻结集承诺);terminal 输出 caps 由
188
+ * 载体按客户端 `_meta.terminal_output` 声明门控(基线 supportsTerminalOutput 先例)。
189
+ * `_meta.openacpagent.{usage,image}` 为基线对齐的客户端消费扩展(Zed 实测消费,
190
+ * [zed-available-commands-refresh]);`_meta.tboxcode.protocolVersion` 为本仓扩展
191
+ * 协商面([tbox-extensions-contract])。
192
+ */
193
+ interface AgentCapabilitiesMeta {
194
+ openacpagent: {
195
+ usage: Record<string, never>;
196
+ image: Record<string, never>;
197
+ };
198
+ tboxcode: {
199
+ protocolVersion: number;
200
+ };
201
+ }
202
+ declare function agentCapabilities(negotiatedVersion: number): {
203
+ capabilities: AgentCapabilities;
204
+ meta: AgentCapabilitiesMeta;
205
+ };
206
+ //#endregion
207
+ //#region src/project.d.ts
208
+ /** 工具调用登记——tool/call → { name, input },tool/result 查询(dsh 事件无冗余的对位)。 */
209
+ declare class ToolJournal {
210
+ #private;
211
+ record(callId: string, name: string, argumentsJson: string | undefined): void;
212
+ lookup(callId: string): {
213
+ name: string;
214
+ input?: Record<string, unknown>;
215
+ } | undefined;
216
+ }
217
+ /** 子会话目录编排钩子负载(live 透传归属规则与只读回放寻址的消费源,S8 编排面)。 */
218
+ interface SubagentCatalogPayload {
219
+ childId: string;
220
+ childCreatedAt: number;
221
+ mode: string;
222
+ label?: string;
223
+ }
224
+ /**
225
+ * 委派运行关联状态(per-channel,ProjectOptions 显式注入——stateless 纪律下的
226
+ * 跨事件状态载体)。
227
+ *
228
+ * 关联模型 = per-callId 落定表:catalog 事件到达(帧序 tool/call < catalog <
229
+ * tool/result)时把「当时挂起的委派」落定到该 catalog;tool/result 期查
230
+ * **callId 自己的落定**,与全局最新状态无关——顺序多委派(call1/catalog1/
231
+ * call2/catalog2 序列)下先到委派的迟到 result 不被后到 catalog 误配。
232
+ * catalog 无 parentToolCallId:多委派同时挂起时归属不可判定,落定即标记
233
+ * ambiguous,metaFor 走 runId = callId 中立降级(不猜)。
234
+ */
235
+ declare class SubagentCatalogState {
236
+ #private;
237
+ readonly byChild: Map<string, {
238
+ mode: string;
239
+ label?: string;
240
+ }>;
241
+ /** catalog 事件到达(帧序 tool/call < catalog < tool/result——pending 即被其配对)。 */
242
+ accept(catalog: SubagentCatalogPayload): void;
243
+ /** 委派 tool/call 登记(catalog 未到——保持 pending 待配对;toolName 供 agentType 构造)。 */
244
+ trackDelegation(callId: string, toolName: string): void;
245
+ /** 子会话归属判定(透传路由——childId 是本 channel 跟踪的委派子会话)。 */
246
+ tracks(childId: string): boolean;
247
+ /**
248
+ * 透传合成 id 前缀的父段:单委派 = 精确父 callId;多委派并行(归属不可判)
249
+ * 与未登记委派 = undefined(合成 id 前缀降级 childId——挂错父段与 meta 误配
250
+ * 同性质,一致中立)。
251
+ */
252
+ parentCallIdOf(childId: string): string | undefined;
253
+ /** 子透传 title 前缀用 label 读数(catalog 落定表;未到达 / 无 label → undefined)。 */
254
+ labelOfChild(childId: string): string | undefined;
255
+ /**
256
+ * tool/result 期 `_meta.openacpagent.subagent` 构造:落定非 ambiguous →
257
+ * {runId: childId, name: label};落定 ambiguous 或无落定 → runId = callId
258
+ * 中立值(不猜)。agentType = 委派实例名去前缀('subagent' → 'general',
259
+ * 'subagent_x' → 'x';落定表持有登记名——透传场景 toolName 为子工具名不参与)。
260
+ */
261
+ metaFor(callId: string, toolName: string): {
262
+ runId: string;
263
+ agentType: string;
264
+ name?: string;
265
+ };
266
+ }
267
+ interface ProjectOptions {
268
+ /** live = 流式通道;false = 回放(durable 重放,流式 delta 不投影)。 */
269
+ live: boolean;
270
+ /** per-channel 已投递字符计数(messageId 维度后缀规则——基线 seen 语义)。 */
271
+ seen?: Map<string, {
272
+ text: number;
273
+ reasoning: number;
274
+ }>;
275
+ /** 工具调用登记(载体层持有,随会话生命周期)。 */
276
+ journal?: ToolJournal;
277
+ /** subagent/catalog 编排消费钩子(零标准 update 发射)。 */
278
+ onSubagentCatalog?: (catalog: SubagentCatalogPayload) => void;
279
+ /** 委派关联状态(_meta.subagent 结果期构造 + 透传路由——载体 per-channel 持有)。 */
280
+ subagents?: SubagentCatalogState;
281
+ /** 终端协议门控(客户端 `_meta.terminal_output` 声明——基线 supportsTerminalOutput)。 */
282
+ supportsTerminalOutput?: boolean;
283
+ }
284
+ /**
285
+ * 子会话事件透传投影(live 专用——基线 ephemeral 语义,回放不透传):子 tool
286
+ * 生命周期重投影为父 update,合成 toolCallId = `{父callId|childId}:{子callId}`
287
+ * 确定性拼接(回放稳定);子 text/thought/plan 零透传(子输出经父 task
288
+ * tool_result 返回);kind/locations 门控照常。
289
+ */
290
+ declare function projectSubagentChildEvent(childId: string, ev: SessionEvent, state: SubagentCatalogState, opts: {
291
+ journal: ToolJournal;
292
+ supportsTerminalOutput?: boolean;
293
+ }): SessionUpdate[];
294
+ /**
295
+ * 事件投影入口(分类查表 → 分支投影)。
296
+ *
297
+ * 'skip' 与 'unknown' 返回 [];unknown 按 ignorable 分级记档(ignorable → debug、
298
+ * 无标记 → warn)——记档回调经 opts 缺省为 console 降噪(载体层注入结构化 logger)。
299
+ */
300
+ declare function projectEvent(ev: SessionEvent, opts: ProjectOptions, onUnknown?: (type: string, level: 'debug' | 'warn') => void): SessionUpdate[];
301
+ /** 回放投影(durable 重放:live:false 语义——流式 delta 不投影)。 */
302
+ declare function projectRecord(rec: SessionEvent, opts: ProjectOptions, onUnknown?: (type: string, level: 'debug' | 'warn') => void): SessionUpdate[];
303
+ /** dsh SessionAssistantStreamFrame 的最小结构面(wire 域手写子集——完整契约归 sdk,决策 bridge-typing-boundary-hardening)。 */
304
+ interface AssistantStreamFrameLike {
305
+ type: 'start' | 'chunk' | 'end';
306
+ attemptId: string;
307
+ chunk?: {
308
+ type: string;
309
+ text?: string;
310
+ };
311
+ }
312
+ /**
313
+ * 流式帧投影:text-delta → agent_message_chunk、reasoning-delta → agent_thought_chunk
314
+ * (messageId = attemptId——流 start / durable 记录 id 的边界对位,基准表流式 chunk
315
+ * 边界行);start / end / 其他 chunk 类型零发射。live 专用(回放走 durable)。
316
+ */
317
+ declare function projectStreamFrame(frame: AssistantStreamFrameLike, opts: ProjectOptions): SessionUpdate[];
318
+ /**
319
+ * turn 内未完成工具的派生 failed(基线 TurnFoldTracker:turn_end 时未 resolve
320
+ * 的 tool_call 补 failed 派生帧——基准表 tool_call_update 行派生帧对位)。
321
+ * turns 只增不减 + turn_end 弹栈带守卫(孤儿 turn_end 不错弹)。
322
+ */
323
+ declare class TurnFoldTracker {
324
+ #private;
325
+ private readonly onDerived;
326
+ constructor(onDerived: (update: SessionUpdate) => void);
327
+ accept(ev: {
328
+ type: string;
329
+ data?: unknown;
330
+ }): void;
331
+ }
332
+ //#endregion
333
+ //#region src/fixtures.d.ts
334
+ /**
335
+ * wireFixtures——投影基准样例(单源三用:基准样例 = 守卫单测输入 = runner
336
+ * scenario;场景驱动 [acp-projection-contract] 一一对应)。
337
+ *
338
+ * 事件样例形状 = dsh SessionEvent 鸭子形态(type / seq / time / data + 可选
339
+ * surfaceOp / ignorable);来源分类:dsh 0.2.1-rc.2 类型推导(类型面字段——0.2.1 实测 wire 面字段零漂移,快照免重录)与
340
+ * echo driver 实测形状(流式帧),文件头登记。断言面 = update 判别联合的
341
+ * 逐字段形状(表格驱动,[acp-projection-contract] 场景驱动表行一一对应)。
342
+ */
343
+ interface WireFixture {
344
+ /** 场景名(与契约场景驱动表行对应)。 */
345
+ name: string;
346
+ /** 事件样例序列(SessionEvent 鸭子形态;按序喂投影 + tracker)。 */
347
+ events: Array<Record<string, unknown>>;
348
+ /** 附加流式帧(live 通道)。 */
349
+ streamFrames?: Array<Record<string, unknown>>;
350
+ /** live 通道期望 update 序列。 */
351
+ expectedLive: Array<Record<string, unknown>>;
352
+ /** 回放通道(live:false)期望 update 序列;缺省 = 与 live 相同。 */
353
+ expectedReplay?: Array<Record<string, unknown>>;
354
+ /** TurnFoldTracker 派生帧期望(追加在 update 序列之后)。 */
355
+ expectedDerived?: Array<Record<string, unknown>>;
356
+ /** unknown 事件分级记档期望:[type, level] 序列。 */
357
+ expectedUnknown?: Array<[string, 'debug' | 'warn']>;
358
+ }
359
+ declare const WIRE_FIXTURES: WireFixture[];
360
+ //#endregion
361
+ //#region src/commands.d.ts
362
+ /** 宽松超集前置门正则(dsh 权威 parseCommand 为 `/^\/([a-z][a-z0-9_-]*)(?=$|[\t\n\r ])/u`——超集安全:假阳性被探针消解、欠集才有害)。 */
363
+ declare const COMMAND_GATE_PATTERN: RegExp;
364
+ /**
365
+ * shadow 表(机制共享单源:命令表组装过滤 + probe 门禁两消费)——
366
+ * rationale 见 [acp-command-execution-bridge]:单一真源纪律。
367
+ */
368
+ declare const SHADOW_COMMANDS: ReadonlySet<string>;
369
+ /** shadow 表 rationale(注记列——升级义务 = 门保持超集 + shadow 表判定不变)。 */
370
+ declare const SHADOW_COMMANDS_RATIONALE: Readonly<Record<string, string>>;
371
+ /** probe 探针判定结果。 */
372
+ interface CommandGateResult {
373
+ /** 前置门命中(正则匹配——是否 shadow 另列)。 */
374
+ hit: boolean;
375
+ /** 匹配的命令名(含 shadow 命中——编排层判查)。 */
376
+ name: string;
377
+ /** shadow 命中(真命令降级透传——防绕过单一真源)。 */
378
+ shadow: boolean;
379
+ }
380
+ /**
381
+ * probe 探针判定(prompt 前置):单文本块 trim 后宽松门匹配 + shadow 判查。
382
+ * 编排语义:hit && !shadow → 拦截执行;未命中 / shadow → 正常 prompt 透传
383
+ * (手打 /plan 以普通 prompt 到达模型;skill 手势依赖透传生命线)。
384
+ */
385
+ declare function commandGate(firstBlockText: string | undefined): CommandGateResult;
386
+ /** 命令执行三态(载体从 execute RPC 结局折叠)。 */
387
+ type CommandOutcome = {
388
+ kind: 'success';
389
+ } | {
390
+ kind: 'error';
391
+ error: unknown;
392
+ } | {
393
+ kind: 'aborted';
394
+ };
395
+ /**
396
+ * 三态映射(命令零对话 turn):success / error 同为 end_turn——命令失败 ≠
397
+ * turn 失败,回 error 会被客户端渲染成 turn 错误误导重试,错误文案经
398
+ * `command/done` 投影(agent_message_chunk)到达;usage 0 是诚实值(命令
399
+ * 不消费模型 token;压缩 token 经 compaction summary 既有投影行到达)。
400
+ * abort → cancelled。
401
+ */
402
+ declare function settleToResponse(outcome: CommandOutcome): PromptResponse;
403
+ /** dsh CommandDescriptor 消费子集(wire 域手写——零 import)。 */
404
+ interface CommandDescriptorLike {
405
+ name: string;
406
+ description: string;
407
+ input?: {
408
+ hint: string;
409
+ } | null;
410
+ }
411
+ /** dsh SkillSummary 消费子集(wire 域手写——零 import)。 */
412
+ interface SkillSummaryLike {
413
+ name: string;
414
+ description: string;
415
+ invocation: {
416
+ modelInvocable: boolean;
417
+ userInvocable: boolean;
418
+ };
419
+ }
420
+ /**
421
+ * 命令表单源组装:`ctx.commands.list` + shadow 过滤 ∪ skills snapshot
422
+ * userInvocable;同名宿主命令胜(与 probe 拦截裁决链一致——execute 命中即结算)。
423
+ * 排序:name 字典序(菜单稳定)。skill 无 input hint 概念(dsh snapshot 无此域)。
424
+ */
425
+ declare function commandsProjection(commands: ReadonlyArray<CommandDescriptorLike>, skills: ReadonlyArray<SkillSummaryLike>): AvailableCommand[];
426
+ //#endregion
427
+ //#region src/elicitation.d.ts
428
+ /**
429
+ * question 方言(dsh user-questions ↔ ACP elicitation form)——生成与解析。
430
+ *
431
+ * 方向:桥消费 dsh `AskUserQuestionRequestEvent`,出站 `elicitation/create`
432
+ * (requestedSchema),accept content 反向折叠为 dsh `AskUserQuestionAnswer`。
433
+ * 载荷形状(锁死):属性名 = slug(header ?? question);单选 = string+oneOf
434
+ * (const=title=label,description 折叠 "label — desc");多选 = array +
435
+ * items.anyOf + minItems:1;恒追加 `__custom__` 哨兵选项与 `{prop}_customText`
436
+ * 兄弟属性(required 不含——消费端契约见 agtcodingbox elicitation.ts,fixtures
437
+ * 以该消费端测试样例移植锁死);intent.approve 选项保序首位(BAD_INTENT 前置
438
+ * 校验在 dsh 提问方一侧已保证 approve 命中 options)。
439
+ *
440
+ * 解析(accept 反向):前端 buildElicitationContent 已完成 custom 折叠——
441
+ * content = {prop: value}(值域 string|number|boolean|string[]),哨兵与
442
+ * `_customText` 兄弟不出现;非 label 值即 custom 文本(单选直接替代、多选
443
+ * 追加一元素)。content 不合 schema → throw(fail-safe,不留半答态——载体
444
+ * 转 UserQuestionError 语义拒答)。
445
+ */
446
+ /** dsh AskUserQuestionItem 消费子集(wire 域手写——零 import)。 */
447
+ interface AskUserQuestionItemLike {
448
+ id: string;
449
+ question: string;
450
+ detail?: string;
451
+ header?: string;
452
+ options?: Array<{
453
+ label: string;
454
+ description?: string;
455
+ }>;
456
+ multiSelect?: boolean;
457
+ intent?: {
458
+ kind: string;
459
+ approve: string;
460
+ callId?: string;
461
+ };
462
+ }
463
+ /** dsh AskUserQuestionAnswer 消费子集(wire 域手写——零 import)。 */
464
+ interface AskUserQuestionAnswerLike {
465
+ answers: Array<{
466
+ id: string;
467
+ selected: string[];
468
+ custom?: string;
469
+ }>;
470
+ }
471
+ /** ACP elicitation form 的 requestedSchema(JSON Schema 子集——SDK 校验域)。 */
472
+ interface ElicitationSchema {
473
+ type: 'object';
474
+ properties: Record<string, unknown>;
475
+ required: string[];
476
+ }
477
+ /** ACP accept 响应的 content 值域。 */
478
+ type ElicitationContentValue = string | number | boolean | string[];
479
+ /** 属性名 slug(确定性 + JSON Schema 键合法;空串兜底 question)。 */
480
+ declare function slugifyQuestion(text: string): string;
481
+ /**
482
+ * 方言生成:questions → requestedSchema。required = 全部问题属性名(dsh
483
+ * 提问语义无"跳过"——自由文本经 __custom__ 哨兵表达)。
484
+ */
485
+ declare function buildElicitationSchema(questions: ReadonlyArray<AskUserQuestionItemLike>): ElicitationSchema;
486
+ /**
487
+ * 方言解析:accept content → dsh answer。fail-safe:结构不合(缺属性 /
488
+ * 类型不符)即 throw——调用方转 UserQuestionError 语义(答案形状无拒答
489
+ * 表示;decline/cancel 由调用方在 action 分支处理)。
490
+ */
491
+ declare function parseElicitationContent(questions: ReadonlyArray<AskUserQuestionItemLike>, content: Record<string, ElicitationContentValue>): AskUserQuestionAnswerLike;
492
+ //#endregion
493
+ //#region src/config-options.d.ts
494
+ /** configOption id 常量(in-tree MODEL_CONFIG_ID / REASONING_CONFIG_ID 对位 + mode 扩展)。 */
495
+ declare const MODE_CONFIG_ID = "mode";
496
+ declare const MODEL_CONFIG_ID = "model";
497
+ declare const REASONING_CONFIG_ID = "reasoning_effort";
498
+ /** reasoning effort 的 provider default 哨兵值(in-tree PROVIDER_DEFAULT_REASONING_VALUE 对位)。 */
499
+ declare const PROVIDER_DEFAULT_REASONING_VALUE = "";
500
+ /** tboxcode 权限模式值域(会话中可切换集合——组合轴 custom agent 不入此表)。 */
501
+ type AcpSessionMode = 'build' | 'plan';
502
+ /** mode → dsh 双 knob 语义映射输出。 */
503
+ interface ModeKnobs {
504
+ sandbox: SandboxMode;
505
+ approval: ApprovalPolicy;
506
+ }
507
+ /**
508
+ * 模式映射表([integration-design] Docker 宿主隔离定案 + [plan-mode] 权限硬地板):
509
+ * build = danger-full-access + never(宿主隔离由部署形态保证);
510
+ * plan = read-only + ask。
511
+ */
512
+ declare const MODE_TABLE: Readonly<Record<AcpSessionMode, ModeKnobs>>;
513
+ /** 值域判别(客户端 set_config_option 入口的白名单检查)。 */
514
+ declare function isAcpSessionMode(value: string): value is AcpSessionMode;
515
+ /**
516
+ * mode → 双 knob 语义映射;未知 mode 返回 undefined(调用方转 invalidParams)。
517
+ */
518
+ declare function translateMode(mode: string): ModeKnobs | undefined;
519
+ /** mode 选项构造(category 'mode'——UX 语义分类;currentValue 由载体状态供给)。 */
520
+ declare function modeConfigOption(currentMode: AcpSessionMode): SessionConfigOption;
521
+ /** opaque 选项 value 编码:携带完整 route 身份(in-tree modelValue 对位,无 JSON.parse)。 */
522
+ declare function resolveModelValue(provider: string, model: string): string;
523
+ //#endregion
524
+ export { type AcpSessionMode, type AgentCapabilitiesMeta, type AskUserQuestionAnswerLike, type AskUserQuestionItemLike, type AssistantStreamFrameLike, COMMAND_GATE_PATTERN, type Classification, type ClassifiedEventType, type CommandDescriptorLike, type CommandGateResult, type CommandOutcome, type ElicitationContentValue, type ElicitationSchema, LATEST_PROTOCOL_VERSION, LOCATIONS_ALLOWED, MODEL_CONFIG_ID, MODE_CONFIG_ID, MODE_TABLE, type ModeKnobs, PROTOCOL_VERSIONS, PROVIDER_DEFAULT_REASONING_VALUE, type ProjectOptions, REASONING_CONFIG_ID, RpcErrorCode, type RpcErrorData, type RpcErrorInput, SHADOW_COMMANDS, SHADOW_COMMANDS_RATIONALE, type SkillSummaryLike, type SubagentCatalogPayload, SubagentCatalogState, TOOL_TITLE_BUILDERS, type ToolCallKind, ToolJournal, TurnFoldTracker, WIRE_FIXTURES, type WireFixture, agentCapabilities, buildElicitationSchema, buildToolTitle, classify, commandGate, commandsProjection, isAcpSessionMode, isIgnorable, mapRpcError, modeConfigOption, negotiateProtocolVersion, parseElicitationContent, parseToolArguments, projectEvent, projectRecord, projectStreamFrame, projectSubagentChildEvent, resolveModelValue, settleToResponse, slugifyQuestion, stopReasonFromTurnEnd, toLocations, toolKind, translateMode, withSubagentPrefix };
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ const e={"user/message":`project`,"assistant/message":`project`,"tool/call":`project`,"tool/result":`project`,"todo/write":`project`,"session/title":`project`,"command/run":`project`,"command/done":`project`,"subagent/catalog":`project`,"turn/start":`project`,"turn/end":`project`,"step/start":`skip`,"step/end":`skip`,"developer/message":`skip`,"system/message":`skip`,"assistant/attempt":`skip`,"request/header":`skip`,"request/context":`skip`,"session/end-seed":`skip`,"agent/inbox/spliced":`skip`,"tool/ptc-dispatch-start":`skip`,"tool/ptc-dispatch":`skip`,"subagent/descriptor":`skip`,"approval/asked":`skip`,"approval/decided":`skip`,"approval/policy":`skip`,"permission/preset":`skip`,"sandbox/mode":`skip`,"model/selection":`skip`,"goal/change":`skip`};function t(t){return e[t]??`unknown`}function n(e){return e.ignorable===!0}const r={read:`read`,read_image:`read`,write:`edit`,edit:`edit`,bash:`execute`,pwsh:`execute`,glob:`search`,grep:`search`,web_search:`search`,web_fetch:`fetch`,webfetch:`fetch`,todo_write:`think`,plan:`think`,skill:`other`},i=new Set([`edit`,`write`,`scratch_write`,`scratch_edit`]);function a(e){return r[e]||(e.startsWith(`scratch_`)?r[e.slice(8)]??`other`:(e.startsWith(`subagent_`),`other`))}const o=e=>typeof e==`string`?e:void 0;function s(e,t){if(!i.has(e))return[];let n=t??{},r=o(n.filePath??n.path);return r?[{path:r,line:typeof n.line==`number`?n.line:typeof n.lineNumber==`number`?n.lineNumber:null}]:[]}const c={bash:e=>{let t=o(e.command),n=o(e.description);return n?`${n} (${t?.slice(0,60)??``})`:t?`Execute ${t.slice(0,120)}${t.length>120?`…`:``}`:`Execute`},pwsh:e=>{let t=o(e.command);return t?`Execute ${t.slice(0,120)}${t.length>120?`…`:``}`:`Execute`},read:e=>`Read ${o(e.filePath??e.path)??`file`}`,read_image:e=>`Read image ${o(e.filePath??e.path)??`file`}`,write:e=>`Write ${o(e.filePath??e.path)??`file`}`,edit:e=>`Edit ${o(e.filePath??e.path)??`file`}`,grep:e=>{let t=o(e.pattern),n=o(e.path);return`Grep${t?` "${t}"`:``}${n?` in ${n}`:``}`},glob:e=>`Glob ${o(e.pattern)??``}`,web_fetch:e=>`Fetch ${o(e.url)??`URL`}`,web_search:e=>{let t=o(e.query);return`Search${t?` "${t}"`:``}`},webfetch:e=>{let t=o(e.url),n=o(e.format);return`Fetch ${t??`URL`}${n&&n!==`markdown`?` (${n})`:``}`},todo_write:e=>{let t=e.todos,n=Array.isArray(t)?t:[],r=n.filter(e=>e.status===`completed`).length;return`Update TODOs${n.length?` (${r}/${n.length})`:``}`},ask_user_question:()=>`Ask the user`,skill:e=>`Load skill: ${o(e.name)??``}`};function l(e,t){return(c[e]??(()=>e))(t??{})}function u(e,t,n){return`[${t??`subagent:${n.slice(-8)}`}] ${e}`}function d(e){if(e!==void 0)try{let t=JSON.parse(e);return typeof t==`object`&&t?t:void 0}catch{return}}const f={methodNotFound:-32601,invalidParams:-32602,conflict:-32600,internal:-32603,sessionNotFound:-32002},p=e=>typeof e==`string`?e:void 0;function m(e){let t=e.message,n=e.data&&typeof e.data==`object`?e.data:{};switch(e.code){case`session-not-found`:{let e=p(n.sessionId);return{code:f.sessionNotFound,message:t??`session not found`,data:e===void 0?void 0:{uri:`session:${e}`}}}case`session/writer-held`:return{code:f.conflict,message:t??`session is owned by another writer`,data:{reason:p(n.reason)??`writer-held`,retryable:!0}};case`turn-error`:return{code:f.internal,message:t??`turn failed`,data:{sessionId:p(n.sessionId),kind:p(n.kind)??`turn-error`,retryable:n.retryable===!0,code:p(n.code),partialOutput:n.partialOutput===!0}};case`llm-auth`:return{code:f.internal,message:t??`llm credential missing`,data:{kind:`auth`,retryable:!1}};case`retry-after-turn`:return{code:f.internal,message:t??`reload in progress`,data:{retryable:!0,reason:`skill_reload_in_progress`}};case`method-not-found`:return{code:f.methodNotFound,message:t??`method not found`};case`invalid-params`:return{code:f.invalidParams,message:t??`invalid params`,data:n.errors===void 0?void 0:{errors:n.errors}};default:return{code:f.internal,message:t??`dsh error`,data:{kind:`unknown-dsh-error`,...e.code===void 0?{}:{code:e.code},...Object.keys(n).length>0?{detail:n}:{}}}}}function h(e){let t=e?.kind;switch(t){case`completed`:case`aborted`:case`blocked`:return{stopReason:`end_turn`};case`interrupted`:return{stopReason:`cancelled`};case`max-tokens`:return{stopReason:`max_tokens`};case`error`:return{error:!0};case`forked`:default:return{stopReason:`end_turn`,warn:`unknown turn end reason: ${String(t)}`}}}const g=[1],_=g[g.length-1]??1;function v(e){return e===void 0?{version:_}:g.includes(e)?{version:e}:{version:_,warn:`client protocol version ${e} not in supported set`}}function ee(e){return{capabilities:{loadSession:!0,promptCapabilities:{}},meta:{openacpagent:{usage:{},image:{}},tboxcode:{protocolVersion:e}}}}var y=class{#e=new Map;record(e,t,n){this.#e.set(e,{name:t,input:d(n)})}lookup(e){return this.#e.get(e)}},b=class{byChild=new Map;#e=new Map;#t=new Map;#n=new Map;accept(e){this.byChild.set(e.childId,{mode:e.mode,...e.label===void 0?{}:{label:e.label}});let t=this.#e.size>1;for(let[n,r]of this.#e)this.#t.set(n,{childId:e.childId,toolName:r,...e.label===void 0?{}:{label:e.label},ambiguous:t});this.#e.size===1&&this.#n.set(e.childId,[...this.#e.keys()][0]),this.#e.clear()}trackDelegation(e,t){this.#e.set(e,t)}tracks(e){return this.byChild.has(e)}parentCallIdOf(e){return this.#n.get(e)}labelOfChild(e){return this.byChild.get(e)?.label}metaFor(e,t){let n=this.#t.get(e),r=n?.toolName??t,i=r===`subagent`?`general`:r.startsWith(`subagent_`)?r.slice(9):r;return n===void 0||n.ambiguous?{runId:e,agentType:i}:{runId:n.childId,agentType:i,...n.label===void 0?{}:{name:n.label}}}};const x=e=>typeof e==`string`?e:void 0,S=e=>e.data??{};function C(e,t){return{sessionUpdate:`user_message_chunk`,content:{type:`text`,text:e},...t?{messageId:t}:{}}}function w(e,t){return{sessionUpdate:`agent_message_chunk`,content:{type:`text`,text:e},...t?{messageId:t}:{}}}function T(e,t){return{sessionUpdate:`agent_thought_chunk`,content:{type:`text`,text:e},...t?{messageId:t}:{}}}function E(e,t,n,r){return{sessionUpdate:`usage_update`,used:e,size:t,_meta:{openacpagent:{usage:{cacheReadTokens:n,cacheWriteTokens:r}}}}}function D(e,t){if(e.source?.kind!==`user`)return[];let n=e,r=typeof n.id==`string`?n.id:null,i=n.content??[];if(i.length===0)return[C(``,r)];let a=[];for(let e of i)e.type===`text`?a.push(C(x(e.text)??``,r)):a.push(C(`[${String(e.type)}]`,r));return a}function O(e,t){let n=e.message,r=[],i=typeof n?.id==`string`?n.id:null,a=t.seen,o=n?.content??[];for(let e of o){let t=e.type;if(t!==`text`&&t!==`reasoning`)continue;let n=x(e.text)??``;if(a){let e=i??``,o=a.get(e)??{text:0,reasoning:0},s=t===`reasoning`?`reasoning`:`text`,c=n.slice(o[s]);if(!c)continue;o[s]=n.length,a.set(e,o),r.push(t===`reasoning`?T(c,i):w(c,i))}else r.push(t===`reasoning`?T(n,i):w(n,i))}let s=e.usage;if(s){let e=(typeof s.totalTokens==`number`?s.totalTokens:void 0)??(typeof s.inputTokens==`number`?s.inputTokens:0)+(typeof s.outputTokens==`number`?s.outputTokens:0);r.push(E(e,2e5,typeof s.cacheReadTokens==`number`?s.cacheReadTokens:0,typeof s.cacheWriteTokens==`number`?s.cacheWriteTokens:0))}return r}function te(e,t){let n=x(e.callId)??``,r=x(e.name)??`unknown`,i=x(e.arguments);t.journal?.record(n,r,i);let o=d(i);t.subagents!==void 0&&(r===`subagent`||r.startsWith(`subagent_`))&&t.subagents.trackDelegation(n,r);let c=r===`bash`&&t.supportsTerminalOutput===!0;return[{sessionUpdate:`tool_call`,toolCallId:n,title:l(r,o),kind:a(r),status:`pending`,locations:s(r,o),rawInput:o??{},...c?{content:[{type:`terminal`,terminalId:n}]}:{}}]}function ne(e,t){let n=e.message,r=x(n?.toolCallId)??``,i=t.journal?.lookup(r),o=i?.name??`unknown`,c=i?.input,u=n?.isError===!0||e.error!==void 0?`failed`:`completed`,d=l(o,c),f=(n?.content??[]).filter(e=>e.type===`text`).map(e=>x(e.text)??``).join(``),p=[];if((o===`edit`||o===`write`)&&c!==void 0){let e=c;x(e.filePath)!==void 0&&p.push({type:`diff`,path:String(e.filePath),oldText:x(e.oldString)??null,newText:x(e.newString)??x(e.content)??``})}let m=o===`bash`;m&&t.supportsTerminalOutput===!0?p.push({type:`terminal`,terminalId:r}):f.trimEnd()&&p.push({type:`content`,content:{type:`text`,text:f}});let h={},g=e.meta;return g!=null&&(h.openacpagent={toolMeta:g}),t.subagents!==void 0&&(o===`subagent`||o.startsWith(`subagent_`))&&(h.openacpagent={...h.openacpagent,subagent:t.subagents.metaFor(r,o)}),m&&t.supportsTerminalOutput===!0?[{sessionUpdate:`tool_call_update`,toolCallId:r,_meta:{terminal_output:{terminal_id:r,data:f}}},{sessionUpdate:`tool_call_update`,toolCallId:r,status:u,title:d,kind:a(o),locations:s(o,c),rawInput:c??{},rawOutput:{content:n?.content??[],meta:g,error:e.error},...p.length>0?{content:p}:{},_meta:{...h,terminal_exit:{terminal_id:r,exit_code:u===`completed`?0:1,signal:null}}}]:[{sessionUpdate:`tool_call_update`,toolCallId:r,status:u,title:d,kind:a(o),locations:s(o,c),rawInput:c??{},rawOutput:{content:n?.content??[],meta:g,error:e.error},...p.length>0?{content:p}:{},...Object.keys(h).length>0?{_meta:h}:{}}]}function re(e,t,n,r){let i=t.type,o=S(t),c=n.parentCallIdOf(e)??e;if(i===`tool/call`){let t=x(o.callId)??``,i=x(o.name)??`unknown`,f=x(o.arguments);r.journal.record(t,i,f);let p=d(f),m=i===`bash`&&r.supportsTerminalOutput===!0;return[{sessionUpdate:`tool_call`,toolCallId:`${c}:${t}`,title:u(l(i,p),n.labelOfChild(e),e),kind:a(i),status:`pending`,locations:s(i,p),rawInput:p??{},...m?{content:[{type:`terminal`,terminalId:`${c}:${t}`}]}:{}}]}if(i===`tool/result`){let t=o.message,i=x(t?.toolCallId)??``,d=r.journal.lookup(i),f=d?.name??`unknown`,p=d?.input,m=t?.isError===!0||o.error!==void 0?`failed`:`completed`,h=(t?.content??[]).filter(e=>e.type===`text`).map(e=>x(e.text)??``).join(``);return[{sessionUpdate:`tool_call_update`,toolCallId:`${c}:${i}`,status:m,title:u(l(f,p),n.labelOfChild(e),e),kind:a(f),locations:s(f,p),rawInput:p??{},rawOutput:{content:t?.content??[],error:o.error},...h.trimEnd()?{content:[{type:`content`,content:{type:`text`,text:h}}]}:{},_meta:{openacpagent:{subagent:n.metaFor(c,f)}}}]}return[]}function ie(e){return[{sessionUpdate:`plan`,entries:(e.todos??[]).map(e=>({content:x(e.content)??``,status:e.status===`in_progress`?`in_progress`:e.status===`completed`?`completed`:`pending`}))}]}function ae(e,t){let n=t.source;return[{sessionUpdate:`session_info_update`,title:x(t.title)??null,updatedAt:new Date(e.time).toISOString(),_meta:n?.kind===void 0?{}:{openacpagent:{titleSource:n.kind}}}]}function oe(e){let t=x(e.name)??``,n=x(e.args);return[C(`/${t}${n?` ${n}`:``}`,x(e.commandId))]}function se(e){let t=e.kind===`success`?`success`:`error`,n=w(x(e.text)??(t===`success`?`Command completed`:`Command failed`),x(e.commandId));return typeof e.sourceEventSeq==`number`&&(n._meta={openacpagent:{sourceEventSeq:e.sourceEventSeq}}),[n]}function k(e,r,i){let a=t(e.type);if(a===`skip`)return[];if(a===`unknown`)return i?.(e.type,n(e)?`debug`:`warn`),[];let o=S(e);switch(e.type){case`user/message`:return D(o,r);case`assistant/message`:return O(o,r);case`tool/call`:return te(o,r);case`tool/result`:return ne(o,r);case`todo/write`:return ie(o);case`session/title`:return ae(e,o);case`command/run`:return oe(o);case`command/done`:return se(o);case`subagent/catalog`:{let t=x(o.childId);if(t!==void 0){let n=o;r.subagents?.accept({childId:t,childCreatedAt:typeof n.childCreatedAt==`number`?n.childCreatedAt:e.time,mode:x(n.mode)??`unknown`,label:x(n.label)}),r.onSubagentCatalog?.({childId:t,childCreatedAt:typeof n.childCreatedAt==`number`?n.childCreatedAt:e.time,mode:x(n.mode)??`unknown`,label:x(n.label)})}return[]}case`turn/start`:case`turn/end`:return[];default:return[]}}function ce(e,t,n){return k(e,{...t,live:!1},n)}function le(e,t){if(!t.live||e.type!==`chunk`)return[];let n=e.chunk?.type;return n===`text-delta`?[w(x(e.chunk?.text)??``,e.attemptId)]:n===`reasoning-delta`?[T(x(e.chunk?.text)??``,e.attemptId)]:[]}var ue=class{#e=[];constructor(e){this.onDerived=e}accept(e){let t=e.data??{};if(e.type===`turn/start`&&typeof t.turn==`number`)this.#e.push({turn:t.turn,tools:new Map});else if(e.type===`tool/call`&&typeof t.callId==`string`)this.#e[this.#e.length-1]?.tools.set(t.callId,{resolved:!1});else if(e.type===`tool/result`){let e=t.message,n=x(e?.toolCallId),r=this.#e[this.#e.length-1];if(n!==void 0&&r!==void 0){let e=r.tools.get(n);e&&(e.resolved=!0)}}else if(e.type===`turn/end`){let e=this.#e[this.#e.length-1];if(e){for(let[t,n]of e.tools)n.resolved||this.onDerived({sessionUpdate:`tool_call_update`,toolCallId:t,status:`failed`,_meta:{derived:!0}});this.#e.pop()}}}};let A=0;const j=(e,t,n={})=>({type:e,seq:++A,time:17e11,data:t,...n}),M={id:`msg-u1`,role:`user`,content:[{type:`text`,text:`hello`}],source:{kind:`user`}},N={id:`msg-cat1`,role:`user`,content:[{type:`text`,text:`<skill catalog>`}],source:{kind:`skill-catalog`,form:`catalog`,entries:[]}},P={id:`msg-rc1`,role:`user`,content:[{type:`text`,text:`<runtime context>`}],source:{kind:`runtime-context`}},F={id:`msg-a1`,role:`assistant`,content:[{type:`text`,text:`world`}],source:{kind:`model`,provider:`echo`,model:`echo`}},I={id:`msg-a2`,role:`assistant`,content:[{type:`reasoning`,text:`thinking…`},{type:`text`,text:`answer`}],source:{kind:`model`,provider:`echo`,model:`echo`}},L=[{name:`echo-whitelist`,events:[j(`user/message`,N),j(`user/message`,P),j(`user/message`,M)],expectedLive:[R(`hello`,`msg-u1`)]},{name:`user-last-subagent-task`,events:[j(`user/message`,{...M,id:`msg-task`,content:[{type:`text`,text:`delegate task`}]})],expectedLive:[R(`delegate task`,`msg-task`)]},{name:`assistant-durable-mixed`,events:[j(`assistant/message`,{turn:1,step:1,message:I,stream:[],usage:{inputTokens:10,outputTokens:5,totalTokens:15,cacheReadTokens:3,cacheWriteTokens:2}})],expectedLive:[B(`thinking…`,`msg-a2`),z(`answer`,`msg-a2`),V(15,3,2)]},{name:`assistant-durable-no-usage`,events:[j(`assistant/message`,{turn:1,step:2,message:F,stream:[]})],expectedLive:[z(`world`,`msg-a1`)]},{name:`tool-lifecycle-bash`,events:[j(`turn/start`,{turn:1}),j(`tool/call`,{turn:1,step:1,callId:`c1`,name:`bash`,arguments:`{"command":"ls -la"}`}),j(`tool/result`,{turn:1,step:1,message:{toolCallId:`c1`,role:`tool`,content:[{type:`text`,text:`file.txt`}]}}),j(`turn/end`,{turn:1,reason:{kind:`completed`}})],expectedLive:[U(`c1`,`Execute ls -la`,`execute`,{command:`ls -la`}),W(`c1`,`completed`,`Execute ls -la`,`execute`,[],{command:`ls -la`},{content:[{type:`text`,text:`file.txt`}],contentFrames:[{type:`content`,content:{type:`text`,text:`file.txt`}}]})],expectedDerived:[]},{name:`tool-derived-failed`,events:[j(`turn/start`,{turn:1}),j(`tool/call`,{turn:1,step:1,callId:`c2`,name:`read`,arguments:`{"filePath":"a.ts"}`}),j(`turn/end`,{turn:1,reason:{kind:`error`}})],expectedLive:[U(`c2`,`Read a.ts`,`read`,{filePath:`a.ts`})],expectedDerived:[{sessionUpdate:`tool_call_update`,toolCallId:`c2`,status:`failed`,_meta:{derived:!0}}]},{name:`edit-diff-locations`,events:[j(`tool/call`,{turn:1,step:1,callId:`c3`,name:`edit`,arguments:`{"filePath":"src/a.ts","oldString":"a","newString":"b"}`}),j(`tool/result`,{turn:1,step:1,message:{toolCallId:`c3`,role:`tool`,content:[{type:`text`,text:`ok`}]}})],expectedLive:[U(`c3`,`Edit src/a.ts`,`edit`,{filePath:`src/a.ts`,oldString:`a`,newString:`b`},[{path:`src/a.ts`,line:null}]),W(`c3`,`completed`,`Edit src/a.ts`,`edit`,[{path:`src/a.ts`,line:null}],{filePath:`src/a.ts`,oldString:`a`,newString:`b`},{content:[{type:`text`,text:`ok`}],contentFrames:[{type:`diff`,path:`src/a.ts`,oldText:`a`,newText:`b`},{type:`content`,content:{type:`text`,text:`ok`}}]})]},{name:`locations-gated-read`,events:[j(`tool/call`,{turn:1,step:1,callId:`c4`,name:`read`,arguments:`{"filePath":"a.ts"}`}),j(`tool/result`,{turn:1,step:1,message:{toolCallId:`c4`,role:`tool`,content:[{type:`text`,text:`x`}]}})],expectedLive:[U(`c4`,`Read a.ts`,`read`,{filePath:`a.ts`}),W(`c4`,`completed`,`Read a.ts`,`read`,[],{filePath:`a.ts`},{content:[{type:`text`,text:`x`}],contentFrames:[{type:`content`,content:{type:`text`,text:`x`}}]})]},{name:`journal-missing-degraded`,events:[j(`tool/result`,{turn:1,step:1,message:{toolCallId:`ghost`,role:`tool`,content:[{type:`text`,text:`late`}]}})],expectedLive:[W(`ghost`,`completed`,`unknown`,`other`,[],{},{content:[{type:`text`,text:`late`}],contentFrames:[{type:`content`,content:{type:`text`,text:`late`}}]})]},{name:`plan-todo-write`,events:[j(`todo/write`,{todos:[{content:`a`,status:`completed`},{content:`b`,status:`in_progress`},{content:`c`,status:`pending`}]})],expectedLive:[{sessionUpdate:`plan`,entries:[{content:`a`,status:`completed`},{content:`b`,status:`in_progress`},{content:`c`,status:`pending`}]}]},{name:`session-info-title`,events:[j(`session/title`,{title:`Fix bug`,messageSeqs:[1],source:{kind:`provider`,provider:`p`}})],expectedLive:[{sessionUpdate:`session_info_update`,title:`Fix bug`,updatedAt:new Date(17e11).toISOString(),_meta:{openacpagent:{titleSource:`provider`}}}]},{name:`command-projection`,events:[j(`command/run`,{commandId:`cmd1`,name:`compact`,source:{kind:`user`}}),j(`command/done`,{commandId:`cmd1`,kind:`success`,text:`compacted`,sourceEventSeq:9})],expectedLive:[R(`/compact`,`cmd1`),H(z(`compacted`,`cmd1`),{openacpagent:{sourceEventSeq:9}})]},{name:`command-echo-record-input-false`,events:[j(`command/run`,{commandId:`cmd2`,name:`feedback`,source:{kind:`user`}})],expectedLive:[R(`/feedback`,`cmd2`)]},{name:`stream-frame-boundaries`,events:[],streamFrames:[{type:`start`,attemptId:`att1`},{type:`chunk`,attemptId:`att1`,chunk:{type:`text-delta`,text:`he`}},{type:`chunk`,attemptId:`att1`,chunk:{type:`reasoning-delta`,text:`think`}},{type:`chunk`,attemptId:`att1`,chunk:{type:`tool-call-delta`}},{type:`end`,attemptId:`att1`,index:2,outcome:{kind:`committed`,eventType:`assistant/message`,seq:5}}],expectedLive:[z(`he`,`att1`),B(`think`,`att1`)],expectedReplay:[]},{name:`surface-replace-folded`,events:[j(`user/message`,{...M,id:`msg-ck`,content:[{type:`text`,text:`compacted summary`}]},{surfaceOp:{op:`replace`,startSeq:1,endSeq:3}})],expectedLive:[R(`compacted summary`,`msg-ck`)]},{name:`unknown-fallback-graded`,events:[j(`llm/retry`,{attempt:1},{ignorable:!0}),j(`brand-new-event`,{x:1})],expectedLive:[],expectedUnknown:[[`llm/retry`,`debug`],[`brand-new-event`,`warn`]]},{name:`skip-classified-silent`,events:[j(`sandbox/mode`,{mode:`read-only`}),j(`permission/preset`,{preset:`auto`}),j(`model/selection`,{provider:`p`,model:`m`}),j(`subagent/descriptor`,{childId:`c`}),j(`goal/change`,{kind:`goal/change`,version:1,operation:`create`})],expectedLive:[],expectedUnknown:[]}];function R(e,t){return{sessionUpdate:`user_message_chunk`,content:{type:`text`,text:e},messageId:t}}function z(e,t){return{sessionUpdate:`agent_message_chunk`,content:{type:`text`,text:e},messageId:t}}function B(e,t){return{sessionUpdate:`agent_thought_chunk`,content:{type:`text`,text:e},messageId:t}}function V(e,t,n){return{sessionUpdate:`usage_update`,used:e,size:2e5,_meta:{openacpagent:{usage:{cacheReadTokens:t,cacheWriteTokens:n}}}}}function H(e,t){return{...e,_meta:t}}function U(e,t,n,r,i=[]){return{sessionUpdate:`tool_call`,toolCallId:e,title:t,kind:n,status:`pending`,locations:i,rawInput:r}}function W(e,t,n,r,i,a,o){return{sessionUpdate:`tool_call_update`,toolCallId:e,status:t,title:n,kind:r,...i.length>0?{locations:i}:{locations:[]},rawInput:a,rawOutput:{content:o.content??[],meta:void 0,error:void 0},...o.contentFrames&&o.contentFrames.length>0?{content:o.contentFrames}:{}}}const G=/^\/([a-z][a-z0-9_-]*)(?=$|[\s])/u,K=new Set([`plan`,`permission`,`export`]),de={plan:`mode 单一真源 = configOption 通道(死防御——组合挂回 plan-mode 插件时已正确)`,permission:`权限档单一真源 = configOption 通道(dsh /permission 是会话中切档唯一写路径,投影制造第二写入口)`,export:`产物走 web 认证 GET 路由,ACP 客户端不可达`};function fe(e){let t=e?.trim()??``,n=G.exec(t);if(n===null)return{hit:!1,name:``,shadow:!1};let r=n[1]??``;return{hit:!0,name:r,shadow:K.has(r)}}function pe(e){return e.kind===`aborted`?{stopReason:`cancelled`}:{stopReason:`end_turn`,usage:{totalTokens:0,inputTokens:0,outputTokens:0}}}function me(e,t){let n=new Map;for(let t of e){if(K.has(t.name))continue;let e=t.input?.hint;n.set(t.name,{name:t.name,description:t.description,...e===void 0?{}:{input:{hint:e}}})}for(let e of t)!e.invocation.userInvocable||n.has(e.name)||n.set(e.name,{name:e.name,description:e.description});return[...n.values()].sort((e,t)=>e.name<t.name?-1:e.name>t.name?1:0)}function q(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``);return t===``?`question`:t}function J(e){let t=new Set;return e.map(e=>{let n=q(e.header??e.question),r=n,i=2;for(;t.has(r);)r=`${n}-${i}`,i+=1;return t.add(r),r})}function he(e){let t=e.options??[],n=e=>({const:e.label,title:e.description===void 0?e.label:`${e.label} — ${e.description}`}),r=e.intent===void 0?void 0:t.find(t=>t.label===e.intent?.approve),i=r===void 0?t:t.filter(e=>e!==r);return[...r===void 0?[]:[n(r)],...i.map(n),{const:`__custom__`,title:`Other — type your own answer below`}]}function ge(e){let t=J(e),n={},r=[];return e.forEach((e,i)=>{let a=t[i]??`question-${i}`,o=e.detail===void 0?e.question:`${e.question}\n\n${e.detail}`;if(e.options!==void 0&&e.options.length>0){let t=he(e);n[a]=e.multiSelect===!0?{type:`array`,title:e.header??e.question,description:o,minItems:1,items:{anyOf:t}}:{type:`string`,title:e.header??e.question,description:o,oneOf:t}}else n[a]={type:`string`,title:e.header??e.question,description:o};n[`${a}_customText`]={type:`string`,title:`Custom answer`},r.push(a)}),{type:`object`,properties:n,required:r}}function Y(e,t){return t.has(e)}function _e(e,t){let n=J(e);return{answers:e.map((e,r)=>{let i=n[r]??`question-${r}`,a=t[i];if(a===void 0)throw Error(`elicitation content missing property: ${i}`);let o=new Set((e.options??[]).map(e=>e.label));if(e.options!==void 0&&e.options.length>0&&e.multiSelect===!0){if(!Array.isArray(a)||a.some(e=>typeof e!=`string`))throw Error(`elicitation content property is not a string array: ${i}`);let t=a.filter(e=>Y(e,o)),n=a.filter(e=>!Y(e,o));return{id:e.id,selected:t,...n.length===0?{}:{custom:n.join(`
2
+ `)}}}if(typeof a!=`string`)throw Error(`elicitation content property is not a string: ${i}`);return e.options===void 0||e.options.length===0?{id:e.id,selected:[],...a===``?{}:{custom:a}}:Y(a,o)?{id:e.id,selected:[a]}:{id:e.id,selected:[],custom:a}})}}const X=`mode`,ve=`model`,Z=`reasoning_effort`,ye=``,Q={build:{sandbox:`danger-full-access`,approval:`never`},plan:{sandbox:`read-only`,approval:`ask`}},be={build:`Build`,plan:`Plan`},xe=[`build`,`plan`];function $(e){return e in Q}function Se(e){return $(e)?Q[e]:void 0}function Ce(e){return{id:X,name:`Mode`,category:`mode`,type:`select`,currentValue:e,options:xe.map(e=>({value:e,name:be[e]}))}}function we(e,t){return JSON.stringify([e,t])}export{G as COMMAND_GATE_PATTERN,_ as LATEST_PROTOCOL_VERSION,i as LOCATIONS_ALLOWED,ve as MODEL_CONFIG_ID,X as MODE_CONFIG_ID,Q as MODE_TABLE,g as PROTOCOL_VERSIONS,ye as PROVIDER_DEFAULT_REASONING_VALUE,Z as REASONING_CONFIG_ID,f as RpcErrorCode,K as SHADOW_COMMANDS,de as SHADOW_COMMANDS_RATIONALE,b as SubagentCatalogState,c as TOOL_TITLE_BUILDERS,y as ToolJournal,ue as TurnFoldTracker,L as WIRE_FIXTURES,ee as agentCapabilities,ge as buildElicitationSchema,l as buildToolTitle,t as classify,fe as commandGate,me as commandsProjection,$ as isAcpSessionMode,n as isIgnorable,m as mapRpcError,Ce as modeConfigOption,v as negotiateProtocolVersion,_e as parseElicitationContent,d as parseToolArguments,k as projectEvent,ce as projectRecord,le as projectStreamFrame,re as projectSubagentChildEvent,we as resolveModelValue,pe as settleToResponse,q as slugifyQuestion,h as stopReasonFromTurnEnd,s as toLocations,a as toolKind,Se as translateMode,u as withSubagentPrefix};
package/package.json CHANGED
@@ -1,6 +1,32 @@
1
1
  {
2
2
  "name": "@tbox.cn/dsh-acp-bridge-core",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0-rc.2",
4
+ "type": "module",
5
+ "description": "纯函数翻译核心:dsh 事件 → ACP update 投影、错误码映射、模式表、命令判定(运行时零依赖)",
6
+ "main": "./lib/index.js",
7
+ "types": "./lib/index.d.ts",
8
+ "files": [
9
+ "lib"
10
+ ],
11
+ "devDependencies": {
12
+ "@agentclientprotocol/sdk": "1.8.0",
13
+ "@deepseek-ai/dsh-api-session-controller": "0.2.1-rc.2",
14
+ "@deepseek-ai/dsh-commands": "0.2.1-rc.2",
15
+ "@deepseek-ai/dsh-goal": "0.2.1-rc.2",
16
+ "@deepseek-ai/dsh-llm": "0.2.1-rc.2",
17
+ "@deepseek-ai/dsh-permission-presets": "0.2.1-rc.2",
18
+ "@deepseek-ai/dsh-sandbox": "0.2.1-rc.2",
19
+ "@deepseek-ai/dsh-session": "0.2.1-rc.2",
20
+ "@deepseek-ai/dsh-session-title": "0.2.1-rc.2",
21
+ "@deepseek-ai/dsh-subagent": "0.2.1-rc.2",
22
+ "@deepseek-ai/dsh-tool-todo": "0.2.1-rc.2",
23
+ "@deepseek-ai/dsh-user-approval": "0.2.1-rc.2",
24
+ "@deepseek-ai/dsh-user-questions": "0.2.1-rc.2",
25
+ "zod": "4.6.7",
26
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.1-rc.2"
27
+ },
28
+ "scripts": {
29
+ "build": "tsdown",
30
+ "typecheck": "tsc --noEmit -p tsconfig.json"
31
+ }
6
32
  }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.