@x-otto/interchange 0.1.0-alpha.4 → 0.1.0-alpha.6
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/README.md +1 -0
- package/dist/context-fragment.d.ts +37 -0
- package/dist/context-fragment.js +2 -0
- package/dist/image.d.ts +39 -0
- package/dist/image.js +1 -0
- package/dist/index.d.ts +270 -506
- package/dist/index.js +2 -3
- package/dist/input.d.ts +230 -0
- package/dist/input.js +1 -0
- package/dist/message.d.ts +216 -0
- package/dist/message.js +1 -0
- package/package.json +17 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,217 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type KnownProvider = 'anthropic' | 'openai' | 'google' | 'amazon-bedrock' | 'github-copilot' | 'xai' | 'groq' | 'openrouter' | 'deepseek' | 'ollama' | 'moonshot' | 'custom';
|
|
7
|
-
type Provider = KnownProvider | (string & {});
|
|
8
|
-
type StopReason = 'end_turn' | 'max_tokens' | 'tool_use' | 'stop_sequence' | 'refusal';
|
|
9
|
-
interface Usage {
|
|
10
|
-
inputTokens: number;
|
|
11
|
-
outputTokens: number;
|
|
12
|
-
cacheReadTokens: number;
|
|
13
|
-
cacheWriteTokens: number;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* 结构化的 zod 兼容垫片——协议层不直接依赖 zod,靠结构类型让 provider/工具定义喂入真 zod schema。
|
|
17
|
-
*/
|
|
18
|
-
interface ZodType<T = unknown> {
|
|
19
|
-
parse(data: unknown): T;
|
|
20
|
-
safeParse(data: unknown): {
|
|
21
|
-
success: boolean;
|
|
22
|
-
data?: T;
|
|
23
|
-
error?: unknown;
|
|
24
|
-
};
|
|
25
|
-
toJSONSchema?: () => unknown;
|
|
26
|
-
}
|
|
27
|
-
interface TextContent {
|
|
28
|
-
type: 'text';
|
|
29
|
-
text: string;
|
|
30
|
-
signature?: string;
|
|
31
|
-
}
|
|
32
|
-
interface ImageContent {
|
|
33
|
-
type: 'image';
|
|
34
|
-
mime: string;
|
|
35
|
-
source: string;
|
|
36
|
-
}
|
|
37
|
-
interface ThinkingContent {
|
|
38
|
-
type: 'thinking';
|
|
39
|
-
text: string;
|
|
40
|
-
signature?: string;
|
|
41
|
-
}
|
|
42
|
-
interface ToolCall {
|
|
43
|
-
type: 'tool_call';
|
|
44
|
-
id: string;
|
|
45
|
-
name: string;
|
|
46
|
-
arguments: Record<string, unknown>;
|
|
47
|
-
/**
|
|
48
|
-
* 流式参数 JSON 解析失败标记(RFC-142 D4)——`stopReason: max_tokens` 截断半截
|
|
49
|
-
* JSON 时 `parseToolArguments` 置位,runtime 责任链据此把该调用转为明确错误
|
|
50
|
-
* tool_result 而非带空参数进入 zod 校验(与污染类错误分离错误通道)。
|
|
51
|
-
*
|
|
52
|
-
* **进程内标记,不进 wire**:各 provider 序列化发给模型时均为显式字段拾取
|
|
53
|
-
* (`{type, id, name, input: arguments}`,无 spread),本字段天然剥除——有测试钉住
|
|
54
|
-
* (RFC-142 重要事项规则4)。
|
|
55
|
-
*/
|
|
56
|
-
argumentsParseFailed?: boolean;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* A2UI content block(RFC-105 D6/M105-5b):agent 生成的声明式 UI payload。
|
|
60
|
-
* 对齐 a2ui-project/a2ui(v0.9)的核心哲学——扁平组件列表 + ID 引用 + 受信组件 catalog、
|
|
61
|
-
* 纯数据非代码、未知组件类型文本降级。
|
|
62
|
-
*
|
|
63
|
-
* 组件类型(TUI 终端安全子集,首阶段只读 display):
|
|
64
|
-
* - Text:纯文本(text 字段)。
|
|
65
|
-
* - Card:带标题容器(title + children ID 引用)。
|
|
66
|
-
* - List:条目列表(items ID 引用 + ordered 标志)。
|
|
67
|
-
* - Progress:ASCII 进度条(value 0-100,label 可选)。
|
|
68
|
-
* - Chip:内联彩色标签(text + color)。
|
|
69
|
-
* - Button:交互按钮(RFC-105 D6 F5/M105-5c,数字键触发 a2ui action;只读 display 通过
|
|
70
|
-
* renderA2uiBlock 提取为 A2uiButtonInfo 元数据)。
|
|
71
|
-
* - Form:交互式表单(RFC-211 M1:字段定义 + TUI 弹窗填写 + web-ui 原生表单)。
|
|
72
|
-
* 字段类型 text/select/toggle,payload 原样回流,不可执行代码。
|
|
73
|
-
* 未知 type → 文本摘要表示(不崩,fail-soft,R7)。
|
|
74
|
-
*/
|
|
75
|
-
interface A2uiComponent {
|
|
76
|
-
id: string;
|
|
77
|
-
type: 'Text' | 'Card' | 'List' | 'Progress' | 'Chip' | 'Button' | 'Form' | (string & {});
|
|
78
|
-
text?: string;
|
|
79
|
-
title?: string;
|
|
80
|
-
children?: string[];
|
|
81
|
-
items?: string[];
|
|
82
|
-
ordered?: boolean;
|
|
83
|
-
value?: number;
|
|
84
|
-
max?: number;
|
|
85
|
-
label?: string;
|
|
86
|
-
color?: 'accent' | 'green' | 'amber' | 'red' | 'gray';
|
|
87
|
-
action?: string;
|
|
88
|
-
shortcut?: string;
|
|
89
|
-
/** 表单标题(弹窗标题 + 对话流摘要标题)。 */
|
|
90
|
-
formTitle?: string;
|
|
91
|
-
/** 表单字段定义。 */
|
|
92
|
-
fields?: A2uiFormField[];
|
|
93
|
-
}
|
|
94
|
-
/** 单个表单字段(`A2uiComponent.type === 'Form'` 时使用)。 */
|
|
95
|
-
interface A2uiFormField {
|
|
96
|
-
/** 字段 id(Form 内唯一,submit payload 的 key)。 */
|
|
97
|
-
id: string;
|
|
98
|
-
/** 字段类型。 */
|
|
99
|
-
type: 'text' | 'select' | 'toggle';
|
|
100
|
-
/** 显示标签。 */
|
|
101
|
-
label: string;
|
|
102
|
-
/** 默认值(text=字符串, select=option id, toggle=boolean)。 */
|
|
103
|
-
defaultValue?: string | boolean;
|
|
104
|
-
/** 占位符(text 类型)。 */
|
|
105
|
-
placeholder?: string;
|
|
106
|
-
/** 选项列表(select 类型必填)。 */
|
|
107
|
-
options?: Array<{
|
|
108
|
-
id: string;
|
|
109
|
-
label: string;
|
|
110
|
-
}>;
|
|
111
|
-
/** 是否必填(渲染提示,不做前端校验——非目标)。 */
|
|
112
|
-
required?: boolean;
|
|
113
|
-
}
|
|
114
|
-
interface A2uiContent {
|
|
115
|
-
type: 'a2ui';
|
|
116
|
-
/** A2UI 协议版本(v0.9 snapshot),供未来版本迁移用。 */
|
|
117
|
-
version: string;
|
|
118
|
-
/** 扁平组件列表,ID 引用构建组件树,增量子集可追加/替换。 */
|
|
119
|
-
components: A2uiComponent[];
|
|
120
|
-
}
|
|
121
|
-
type ContentPart = TextContent | ImageContent | ThinkingContent | ToolCall | A2uiContent;
|
|
122
|
-
interface UserMessage {
|
|
123
|
-
role: 'user';
|
|
124
|
-
content: string | ContentPart[];
|
|
125
|
-
timestamp: Timestamp;
|
|
126
|
-
uuid?: string;
|
|
127
|
-
/**
|
|
128
|
-
* RFC-050 REV-1:引擎注入的内部消息(如预算收尾 steering、截断续写提示),模型需要看到、
|
|
129
|
-
* 但**不应渲染给用户**(否则 resume 时显示成用户从未输入的发言)。provider 序列化忽略此字段。
|
|
130
|
-
*/
|
|
131
|
-
internal?: boolean;
|
|
132
|
-
}
|
|
133
|
-
interface AssistantMessage {
|
|
134
|
-
role: 'assistant';
|
|
135
|
-
/**
|
|
136
|
-
* 消息内容。A2uiContent 是前向兼容新增(RFC-155 M2 结案后的协议层收口):
|
|
137
|
-
* provider 序列化层仅消费 text/tool_call/thinking,a2ui 块被静默跳过不出进 LLM 请求体;
|
|
138
|
-
* 渲染层(message-lines.ts)经 `renderA2uiBlock` 渲染。
|
|
139
|
-
*/
|
|
140
|
-
content: (TextContent | ThinkingContent | ToolCall | A2uiContent)[];
|
|
141
|
-
api: Api;
|
|
142
|
-
provider: Provider;
|
|
143
|
-
model: string;
|
|
144
|
-
usage: Usage;
|
|
145
|
-
stopReason: StopReason;
|
|
146
|
-
uuid?: string;
|
|
147
|
-
}
|
|
148
|
-
interface ToolResultMessage<T extends unknown = unknown> {
|
|
149
|
-
role: 'tool_result';
|
|
150
|
-
toolCallId: string;
|
|
151
|
-
toolName: string;
|
|
152
|
-
/**
|
|
153
|
-
* 工具结果内容。A2uiContent 是前向兼容新增(RFC-155 M2 结案后的协议层收口):
|
|
154
|
-
* provider 序列化仅消费 text,a2ui 块被静默跳过;渲染层(message-lines.ts)经
|
|
155
|
-
* `renderA2uiBlock` 渲染为终端卡片。
|
|
156
|
-
*/
|
|
157
|
-
content: (TextContent | ImageContent | A2uiContent)[];
|
|
158
|
-
details: T;
|
|
159
|
-
isError: boolean;
|
|
160
|
-
timestamp: Timestamp;
|
|
161
|
-
uuid?: string;
|
|
162
|
-
/** RFC-050 REV-1:引擎合成的内部 tool_result(如预算耗尽未执行的占位),不渲染给用户。 */
|
|
163
|
-
internal?: boolean;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* RFC-144 M1:mid-conversation system 通知消息——**真正进 provider 请求**的协议消息类型
|
|
167
|
-
* (区别于 `@x-otto/hook-contracts` 的 `SystemAgentMessage`,后者是 hooks/UI 域、
|
|
168
|
-
* convertToLLM 类型边界显式过滤、绝不进 provider 请求)。
|
|
169
|
-
*
|
|
170
|
-
* 用途:lifecycleAsync 工具(RFC-144)真正完成时,追加一条独立消息告知 LLM"运营方观察到
|
|
171
|
-
* 的状态变化"(Anthropic mid-conversation system message 官方场景之一),不修改/替换任何
|
|
172
|
-
* 历史消息(纯追加语义),LLM 在下一轮推理中作为权威事实处理。
|
|
173
|
-
*
|
|
174
|
-
* provider 序列化:
|
|
175
|
-
* - Anthropic(原生支持,Claude Opus 4.8+)→ `{role: 'system', content}` 追加进 messages 数组,
|
|
176
|
-
* 放置规则见 RFC-144 重要事项规则 5(必须紧跟携带 tool_result 的 user turn 之后)。
|
|
177
|
-
* - 不支持该特性的模型/provider(如 OpenAI,或 Anthropic 旧模型)→ 降级为等价的
|
|
178
|
-
* `role: 'user'` 消息 + 显式文本前缀(牺牲"运营方权威"语义,保留基本可用性),
|
|
179
|
-
* 降级逻辑归属 provider adapter 层(本类型定义不关心降级细节)。
|
|
180
|
-
*
|
|
181
|
-
* 不可变性(RFC-144 禁区):一旦追加,绝不编辑或删除已发送的 system 通知——结果更新一律
|
|
182
|
-
* 追加新消息,不改写旧消息(Anthropic 官方限制:编辑会使该点之后的 prompt cache 失效)。
|
|
183
|
-
*/
|
|
184
|
-
interface SystemNotificationMessage {
|
|
185
|
-
role: 'system_notification';
|
|
186
|
-
/** 通知正文(如 "[Tool completion] pnpm build finished: exit 0")。 */
|
|
187
|
-
content: string;
|
|
188
|
-
/**
|
|
189
|
-
* 该通知对应的工具执行是否失败——显式字段,供消费方(渲染层/审计)直接读取,不必解析
|
|
190
|
-
* `content` 文案判断状态(RFC-144 M2:文案格式可能演进,靠字符串匹配脆弱且易误判)。
|
|
191
|
-
*/
|
|
192
|
-
isError?: boolean;
|
|
193
|
-
/** 关联的 lifecycleAsync 工具调用 id,供消费方(渲染层/审计)溯源。 */
|
|
194
|
-
relatedToolCallId?: string;
|
|
195
|
-
timestamp: Timestamp;
|
|
196
|
-
uuid?: string;
|
|
197
|
-
}
|
|
198
|
-
type Message = UserMessage | AssistantMessage | ToolResultMessage | SystemNotificationMessage;
|
|
199
|
-
/**
|
|
200
|
-
* 历史压缩摘要消息的标记前缀——单一真相源(跨包协议常量)。
|
|
201
|
-
* 生产者 @x-otto/memory 注入摘要消息时用、压缩去重(isSummaryMessage)时识别;消费者
|
|
202
|
-
* @x-otto/agent 的 ContextPipeline 从会话树恢复摘要时用同一前缀重建摘要消息。放在协议叶子,
|
|
203
|
-
* 避免双份字面量漂移导致 isSummaryMessage 失配。
|
|
204
|
-
*/
|
|
205
|
-
declare const CONVERSATION_SUMMARY_PREFIX = "[Conversation Summary]";
|
|
206
|
-
/**
|
|
207
|
-
* 从 assistant 消息的内容块中提取全部 tool_call 项(终局架构 review 2026-07-10 P0-3:
|
|
208
|
-
* 从 @x-otto/ai 物理迁移——此前是 @x-otto/ai 唯一自己实现(非 re-export)的两个函数,只依赖
|
|
209
|
-
* AssistantMessage/ToolCall,真源本就该在协议叶子而非模型注册中枢)。
|
|
210
|
-
*/
|
|
211
|
-
declare function getToolCallsByAssistantMessage(message: AssistantMessage): ToolCall[];
|
|
212
|
-
/** 该 assistant 消息是否含至少一个 tool_call。 */
|
|
213
|
-
declare function hasToolCalls(message: AssistantMessage): boolean;
|
|
214
|
-
//#endregion
|
|
1
|
+
import { ContextFragment, ContextFragmentId, boundFragment, contextFragmentBytes } from "./context-fragment.js";
|
|
2
|
+
import { AnthropicImageMime, CommonImageMime, NormalizedImage, normalizeImageData, toAnthropicImageMime } from "./image.js";
|
|
3
|
+
import { A2uiComponent, A2uiContent, Api, AssistantMessage, CONVERSATION_SUMMARY_PREFIX, ContentPart, ImageContent, KnownApi, KnownProvider, Message, Provider, StopReason, SystemNotificationMessage, TextContent, ThinkingContent, ToolCall, ToolResultMessage, Usage, UserMessage, ZodType, getToolCallsByAssistantMessage, hasToolCalls } from "./message.js";
|
|
4
|
+
import { DismissedSigil, PluginInputRegistry, SigilEntry, SigilKind, SigilPrefix, SigilProvider, SigilResolveContext, SigilResolver, SigilSource, SigilTrigger, SigilTriggerDecision, TextChangeSource, adjustDismissedSigil, applySigilCompletion, applySigilReplacement, evaluateSigilTrigger, extractSigilPrefix, isSigilDismissed, sigilOf } from "./input.js";
|
|
5
|
+
|
|
215
6
|
//#region src/stream.d.ts
|
|
216
7
|
/**
|
|
217
8
|
* 供应商 usage 快照(状态栏「周/小时额度」展示,RFC 无编号临时功能——状态栏 provider usage)。
|
|
@@ -465,45 +256,137 @@ interface ModelCapabilityFacts {
|
|
|
465
256
|
/** 收集某模型的能力事实快照(纯函数,无 I/O)。 */
|
|
466
257
|
declare function collectModelCapabilityFacts(model: Pick<Model, 'input'>): ModelCapabilityFacts;
|
|
467
258
|
//#endregion
|
|
468
|
-
//#region src/
|
|
259
|
+
//#region src/prompt-sections.d.ts
|
|
469
260
|
/**
|
|
470
|
-
*
|
|
261
|
+
* prompt-sections.ts —— system-prompt 注入 section 的**唯一有序声明**(RFC-429 从
|
|
262
|
+
* `@x-otto/runtime` 下沉至 interchange 叶包)。
|
|
471
263
|
*
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
264
|
+
* 下沉动机(RFC-429):本表的姊妹类型 `ContextFragmentId`(`context-fragment.ts`)已在
|
|
265
|
+
* interchange,但值层(`SYSTEM_PROMPT_SECTIONS`)此前留在 runtime,导致 tui 等 UI 应用层
|
|
266
|
+
* 为读 section 元数据不得不**值 import `@x-otto/runtime`**(而 runtime 值依赖 agent/ai/hooks
|
|
267
|
+
* 全家桶,且不在 tui 的 package.json 依赖里,独立发布即 MODULE_NOT_FOUND)。下沉后 id/section/
|
|
268
|
+
* 预算三者同住 interchange 叶包,tui/coding hooks 均从叶包取,消除跨层值依赖。
|
|
477
269
|
*
|
|
478
|
-
*
|
|
479
|
-
*
|
|
480
|
-
*
|
|
270
|
+
* 治病灶(原 RFC-020 Phase 3 M54 P3-04)——此前各 section 的 priority 数字散在 coding hooks
|
|
271
|
+
* 与 runtime context-sources 两包里,"system prompt 各段什么顺序"得捞齐多处数字才能拼出。
|
|
272
|
+
* 现收敛为此处一张表:
|
|
273
|
+
* - 数组/字段顺序即 priority 升序 = 实际 `system.prompt.transform` hook 的执行/拼接顺序;
|
|
274
|
+
* - `lane` 标明该段落 **stable 前缀**(systemPrompt,进 prompt cache)还是 **volatile 尾段**
|
|
275
|
+
* (systemTail,落在 cache 断点之后,逐轮可变不击穿缓存);
|
|
276
|
+
* - runtime context-sources(environment/memory-index/memory-delta)与 coding hooks
|
|
277
|
+
* (tool-guidance/lesson/skill-catalog)均从此处取 priority —— 单一真相源,改序只此一处。
|
|
278
|
+
*
|
|
279
|
+
* 注:本表是**排序权威**(方案 H:section 仍由各自 hook 自注册,priority 数字降级为对本表的引用);
|
|
280
|
+
* 不强行把 `SYSTEM_PROMPT_SECTIONS` 各 section 物理并入单一 registry(那超出外科尺度、非目标)。
|
|
281
|
+
* section 数量以该常量的字段数为准,不在本段注释里重复写死具体数字(history: 建表时 7 个,
|
|
282
|
+
* 后追加 docSyncReminder 成 8 个,又补 skillLoopGuidance 成 9 个——写死数字会重犯本次发现的漂移)。
|
|
481
283
|
*/
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
284
|
+
type SystemPromptLane = 'stable' | 'volatile';
|
|
285
|
+
interface SystemPromptSectionSpec {
|
|
286
|
+
/** 对应 hook / ContextSource 的 name/id(与注册名一致,供 drift guard 比对)。 */
|
|
287
|
+
readonly name: string;
|
|
288
|
+
readonly priority: number;
|
|
289
|
+
readonly lane: SystemPromptLane;
|
|
290
|
+
/**
|
|
291
|
+
* RFC-374 M3:本 section 的注入字节硬顶(UTF-8)。注入点经
|
|
292
|
+
* `applySectionBudget` 统一裁剪——预算只此一处声明,各注入点不持局部常量。
|
|
293
|
+
* 取值原则:明显高于常态内容(防御失控注入而非改变正常行为),
|
|
294
|
+
* 需要收紧时只改本表。
|
|
295
|
+
*/
|
|
296
|
+
readonly budgetBytes: number;
|
|
488
297
|
}
|
|
489
|
-
|
|
490
|
-
|
|
298
|
+
declare const SYSTEM_PROMPT_SECTIONS: {
|
|
299
|
+
readonly toolGuidance: {
|
|
300
|
+
readonly name: "tool-guidance-injection";
|
|
301
|
+
readonly priority: 20;
|
|
302
|
+
readonly lane: "stable";
|
|
303
|
+
readonly budgetBytes: 20000;
|
|
304
|
+
};
|
|
305
|
+
/**
|
|
306
|
+
* RFC-318 D7:三分流判别(缺工具 / 流程重复 / 其余)。紧跟 toolGuidance——它是对
|
|
307
|
+
* "现有工具够不够用"的元判断,语义上属工具指引的延伸;内容恒定故走 stable lane。
|
|
308
|
+
*/
|
|
309
|
+
readonly skillLoopGuidance: {
|
|
310
|
+
readonly name: "skill-loop-guidance-injection";
|
|
311
|
+
readonly priority: 21;
|
|
312
|
+
readonly lane: "stable";
|
|
313
|
+
readonly budgetBytes: 2000;
|
|
314
|
+
};
|
|
315
|
+
readonly environment: {
|
|
316
|
+
readonly name: "runtime:environment";
|
|
317
|
+
readonly priority: 25;
|
|
318
|
+
readonly lane: "stable";
|
|
319
|
+
readonly budgetBytes: 8000;
|
|
320
|
+
};
|
|
321
|
+
readonly agentKnowledge: {
|
|
322
|
+
readonly name: "agent-knowledge-injection";
|
|
323
|
+
readonly priority: 35;
|
|
324
|
+
readonly lane: "stable";
|
|
325
|
+
readonly budgetBytes: 28000;
|
|
326
|
+
};
|
|
327
|
+
readonly skillCatalog: {
|
|
328
|
+
readonly name: "skill-catalog-injection";
|
|
329
|
+
readonly priority: 38;
|
|
330
|
+
readonly lane: "stable";
|
|
331
|
+
readonly budgetBytes: 12000;
|
|
332
|
+
}; /** RFC-318 R7 治理补全:lesson-relevant-hints 原为表外 hook,现纳入统一预算面(volatile 尾段)。 */
|
|
333
|
+
readonly lessonRelevantHints: {
|
|
334
|
+
readonly name: "lesson-relevant-hints";
|
|
335
|
+
readonly priority: 41;
|
|
336
|
+
readonly lane: "volatile";
|
|
337
|
+
readonly budgetBytes: 4000;
|
|
338
|
+
};
|
|
339
|
+
/**
|
|
340
|
+
* RFC-383 M2(§9 修订 6):高频 skill 内化指令核心——引擎内部 hook
|
|
341
|
+
* `internalize-skill-injection` 的 volatile 尾段预算面。**必须注册**:不注册则
|
|
342
|
+
* applySectionBudget 原样放行、4KB 硬顶失效(决策器提炼不受控)。priority 42 排在
|
|
343
|
+
* lessonRelevantHints(41) 之后、memoryDelta(60) 之前。
|
|
344
|
+
*/
|
|
345
|
+
readonly internalize: {
|
|
346
|
+
readonly name: "internalize-skill-injection";
|
|
347
|
+
readonly priority: 42;
|
|
348
|
+
readonly lane: "volatile";
|
|
349
|
+
readonly budgetBytes: 4000;
|
|
350
|
+
};
|
|
351
|
+
readonly memoryDelta: {
|
|
352
|
+
readonly name: "memory-delta-injection";
|
|
353
|
+
readonly priority: 60;
|
|
354
|
+
readonly lane: "volatile";
|
|
355
|
+
readonly budgetBytes: 8000;
|
|
356
|
+
};
|
|
357
|
+
readonly todoReminder: {
|
|
358
|
+
readonly name: "todo-reminder-injection";
|
|
359
|
+
readonly priority: 62;
|
|
360
|
+
readonly lane: "volatile";
|
|
361
|
+
readonly budgetBytes: 4000;
|
|
362
|
+
};
|
|
363
|
+
readonly docSyncReminder: {
|
|
364
|
+
readonly name: "doc-sync-reminder-injection";
|
|
365
|
+
readonly priority: 64;
|
|
366
|
+
readonly lane: "volatile";
|
|
367
|
+
readonly budgetBytes: 4000;
|
|
368
|
+
};
|
|
369
|
+
};
|
|
370
|
+
/** 按 priority 升序的 section 序列(= 实际组装顺序的显式视图)。 */
|
|
371
|
+
declare const SYSTEM_PROMPT_SECTION_ORDER: readonly SystemPromptSectionSpec[];
|
|
491
372
|
/**
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
*
|
|
373
|
+
* RFC-374 M3:按 section name 应用注入预算。内容超预算时裁剪(boundFragment,
|
|
374
|
+
* 纯文本截断后缀,RFC-142 红线兼容);name 不在表中时原样返回(插件自定义
|
|
375
|
+
* context source 不受本表预算约束——它不进表就不进预算面,是显式而非默认)。
|
|
495
376
|
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
377
|
+
* 截断诊断(08-14 lesson 字节顶事故跟进):超预算裁剪是静默丢信息——内容里的
|
|
378
|
+
* 截断后缀模型能看见但宿主日志看不见,预算配置漂移(如 pack 内容长大超过
|
|
379
|
+
* budgetBytes)只表现为「注入内容莫名缺尾」。此处 warn(每进程每 section 一次)
|
|
380
|
+
* 把截断升级为可诊断事件,触发即提示检查 budgetBytes 与内容常态体积是否匹配。
|
|
498
381
|
*/
|
|
499
|
-
declare function
|
|
382
|
+
declare function applySectionBudget(name: string, content: string): string;
|
|
500
383
|
//#endregion
|
|
501
384
|
//#region src/tool.d.ts
|
|
502
385
|
/**
|
|
503
386
|
* 工具错误的类型化类别——在**产生处**定型,取代下游对错误文本的英文子串猜测
|
|
504
387
|
* (agent work-loop 旧 categoriseToolError)。未设时下游回退启发式匹配(向后兼容未迁移的工具)。
|
|
505
388
|
*/
|
|
506
|
-
type ToolErrorKind = 'validation' | 'permission' | 'not_found' | 'timeout' | 'network' | 'io' | 'runtime' | 'aborted' | 'unknown';
|
|
389
|
+
type ToolErrorKind = 'validation' | 'permission' | 'not_found' | 'timeout' | 'network' | 'io' | 'runtime' | 'aborted' | 'sandbox-denied' | 'unknown';
|
|
507
390
|
interface ToolResult {
|
|
508
391
|
content: (TextContent | ImageContent)[];
|
|
509
392
|
isError?: boolean;
|
|
@@ -546,14 +429,44 @@ interface ToolCallEvent {
|
|
|
546
429
|
interface ToolDescriptionContext {
|
|
547
430
|
projectRoot: string;
|
|
548
431
|
}
|
|
432
|
+
/**
|
|
433
|
+
* 工具的**协议核心**契约(RFC-399 M1)——只保留「模型可见的工具是什么」这一协议语义:
|
|
434
|
+
* 工具名、描述、参数 schema、执行函数。**不含任何引擎执行策略字段**(并发/暴露/
|
|
435
|
+
* 生命周期/路径守卫等),那些属 `ToolExecutionPolicy`。
|
|
436
|
+
*
|
|
437
|
+
* 工具定义方与消费方(agent 循环)实际使用的运行时对象形状是 `AgentToolDefinition`
|
|
438
|
+
* (= 本类型 & Partial<ToolExecutionPolicy>):运行时字段仍在同一对象上,
|
|
439
|
+
* 拆分只发生在**类型职责层面**(协议 vs 执行策略),不改变运行时形状。
|
|
440
|
+
*/
|
|
549
441
|
interface AgentTool<Params = unknown> {
|
|
550
442
|
name: string;
|
|
551
443
|
description: string | ((ctx: ToolDescriptionContext) => string);
|
|
552
444
|
parameters: ZodType<Params>;
|
|
445
|
+
execute: (ctx: ToolCallContext<Params>) => Promise<ToolResult>;
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* 工具的**引擎执行策略**(RFC-399 M1:从 `AgentTool` 剥离)——描述 agent 循环该如何
|
|
449
|
+
* 调度/暴露/守卫本工具,全部可选。由工具定义方声明、agent 执行路径按 toolName 查表消费
|
|
450
|
+
* (tool-executor / tool-turn-runner / turn-loop / progress-window / stall-detector)。
|
|
451
|
+
*
|
|
452
|
+
* 与协议核心 `AgentTool` 的边界:本类型的字段**不进模型可见的工具 schema**,只影响引擎
|
|
453
|
+
* 内部的执行决策。两者在运行时合并为同一对象(`AgentToolDefinition`),类型层面分离
|
|
454
|
+
* 以保持协议层 `AgentTool` 的纯净(RFC-399 D3)。
|
|
455
|
+
*/
|
|
456
|
+
interface ToolExecutionPolicy<Params = unknown> {
|
|
553
457
|
/** 工具对模型的暴露策略,替换旧 visibility。缺省 'direct'。 */
|
|
554
458
|
exposure?: 'direct' | 'deferred' | 'hidden';
|
|
555
459
|
/** 标记为只读工具,可与其他只读工具并发执行 */
|
|
556
460
|
readonly?: boolean;
|
|
461
|
+
/**
|
|
462
|
+
* RFC review D5:steering(用户新指令)到达时对**正在执行**的本工具的处置语义。
|
|
463
|
+
* - 'block'(缺省,= 改动前行为):工具跑完,steering 只拦未执行工具;
|
|
464
|
+
* - 'cancel':声明「可安全中止」——steering 到达即 abort 本工具(per-tool abort
|
|
465
|
+
* signal,执行方快速终止、结果 errorKind='aborted'),用户指令立刻接管。
|
|
466
|
+
* 约束:取消语义只对「副作用可安全中止」的工具声明(如搜索/分析类);写类工具
|
|
467
|
+
* (bash/edit)不得声明 cancel(其副作用不可回滚)。
|
|
468
|
+
*/
|
|
469
|
+
interruptBehavior?: 'cancel' | 'block';
|
|
557
470
|
/**
|
|
558
471
|
* RFC-093:本工具结果的上下文预算(chars)。超预算时结果落盘、上下文留 preview+路径占位符。
|
|
559
472
|
* 缺省用引擎全局 maxToolResultChars(100K)。声明更小值(如 30K)促使大输出工具更早落盘。
|
|
@@ -616,8 +529,27 @@ interface AgentTool<Params = unknown> {
|
|
|
616
529
|
* 主代理在收到完成通知前不应读写可能冲突的路径。声明后追加到 placeholder 文本末尾。
|
|
617
530
|
*/
|
|
618
531
|
lifecycleAsyncNote?: string;
|
|
619
|
-
|
|
532
|
+
/**
|
|
533
|
+
* RFC-437:声明本工具的输出是**可再生的**——prune 可安全将其剪为占位符
|
|
534
|
+
* (`[output pruned — N tokens]`),模型需要时可重跑工具获得。缺省 undefined =
|
|
535
|
+
* 不声明 = 不可再生(fail-closed,与 prune 对未知工具默认保留一致)。
|
|
536
|
+
*
|
|
537
|
+
* 适用:无副作用的查询/检索类(read/grep/find/web_search 等)。**写类工具不得声明**
|
|
538
|
+
* (write/edit 的输出是用户意图落点,剪掉即丢信息)——作者判断纪律,同
|
|
539
|
+
* `interruptBehavior: 'cancel'` 的约束(副作用不可回滚的不得声明)。
|
|
540
|
+
*
|
|
541
|
+
* 消费方:`@x-otto/memory` prune 经装配注入的 `regenerableToolNames` 惰性 getter
|
|
542
|
+
* 收集全部已注册工具的声明(RFC-437 D2/D3)。此字段不进模型可见的工具 schema。
|
|
543
|
+
*/
|
|
544
|
+
regenerableOutput?: boolean;
|
|
620
545
|
}
|
|
546
|
+
/**
|
|
547
|
+
* 工具定义方与 agent 消费方实际使用的**运行时对象形状**(RFC-399 M1):协议核心
|
|
548
|
+
* `AgentTool` 与可选执行策略 `ToolExecutionPolicy` 的交叉。类型层面职责分离,运行时
|
|
549
|
+
* 所有字段合并在同一对象上——工具定义字面量与 agent 的 `toolByName.get(name)?.<字段>`
|
|
550
|
+
* 消费点因此无需任何改动。
|
|
551
|
+
*/
|
|
552
|
+
type AgentToolDefinition<Params = unknown> = AgentTool<Params> & Partial<ToolExecutionPolicy<Params>>;
|
|
621
553
|
//#endregion
|
|
622
554
|
//#region src/session-event.d.ts
|
|
623
555
|
interface AskUserQuestion {
|
|
@@ -687,6 +619,7 @@ type AgentSessionEvent = {
|
|
|
687
619
|
model?: string;
|
|
688
620
|
thinkingLevel?: string;
|
|
689
621
|
stopReason?: PromptStopReason;
|
|
622
|
+
errorMessage?: string;
|
|
690
623
|
} /** RFC-094 D3:todo 闸门自动续跑的中间轮信号(一个用户 prompt 恰好一对 start/end,中间每次续跑发一次)。 */ | {
|
|
691
624
|
type: 'prompt.continued';
|
|
692
625
|
sessionId: string;
|
|
@@ -988,6 +921,15 @@ type AgentSessionEvent = {
|
|
|
988
921
|
arguments: Record<string, unknown>;
|
|
989
922
|
description: string; /** HITL 显示风险等级(权限层派生,仅显示提示;缺省下游回退 medium)。 */
|
|
990
923
|
risk?: 'low' | 'medium' | 'high';
|
|
924
|
+
/**
|
|
925
|
+
* RFC-380 T4:LLM 语义审批层(opt-in)的自动裁决标记。仅宿主配置了 semanticReviewer
|
|
926
|
+
* 且命中升级审批(description 含 [sandbox-escalation])时出现:
|
|
927
|
+
* - 'allow':runtime 已自动放行(approvalGate 已 resolve true),宿主只需记命令 bypass、
|
|
928
|
+
* 不得再弹窗/再 resolve(PendingGate.resolve 对已 settle 幂等返回 false,安全);
|
|
929
|
+
* - 'deny':runtime 已自动拒绝(已 resolve false),宿主不得弹窗。
|
|
930
|
+
* 缺省(未配置 reviewer / abstain)不出现 → 宿主走既有弹窗流程。
|
|
931
|
+
*/
|
|
932
|
+
semanticVerdict?: 'allow' | 'deny';
|
|
991
933
|
} | {
|
|
992
934
|
type: 'approval.resolved';
|
|
993
935
|
sessionId: string;
|
|
@@ -1039,6 +981,63 @@ type AgentSessionEvent = {
|
|
|
1039
981
|
};
|
|
1040
982
|
type AgentSessionSubscriber = (event: AgentSessionEvent) => void;
|
|
1041
983
|
type AgentSessionEventMap = { [E in AgentSessionEvent as E['type']]: (event: E) => void };
|
|
984
|
+
/**
|
|
985
|
+
* RFC-394 D4/R3:事件三域标记——每个事件归属一个域:
|
|
986
|
+
* - `durable`:可从日志重建、必须存活重载(prompt/turn/tool 生命周期、消息持久化、
|
|
987
|
+
* 会话生命周期、压缩、清除)。
|
|
988
|
+
* - `live`:活体运行时状态、不可重放(流式、状态变更、steer、运行暂停/恢复)。
|
|
989
|
+
* - `capability`:能力缝/交互请求(审批、ask user、plan approval、预算通知、
|
|
990
|
+
* 工具不匹配/图像降级/进度停滞/压缩反应通知)。
|
|
991
|
+
*
|
|
992
|
+
* 消费方按域订阅——durable 事件可重放/可落盘,live 事件不可重放,
|
|
993
|
+
* capability 事件是交互请求需宿主响应。新增事件必须在此映射中声明 domain(R3)。
|
|
994
|
+
*/
|
|
995
|
+
declare const EVENT_DOMAIN: {
|
|
996
|
+
readonly 'session.start': "durable";
|
|
997
|
+
readonly 'session.end': "durable";
|
|
998
|
+
readonly 'session.cleared': "durable";
|
|
999
|
+
readonly 'prompt.start': "durable";
|
|
1000
|
+
readonly 'prompt.end': "durable";
|
|
1001
|
+
readonly 'prompt.continued': "durable";
|
|
1002
|
+
readonly 'turn.start': "durable";
|
|
1003
|
+
readonly 'turn.end': "durable";
|
|
1004
|
+
readonly 'tool.call.start': "durable";
|
|
1005
|
+
readonly 'tool.call.end': "durable";
|
|
1006
|
+
readonly 'messages.persist': "durable";
|
|
1007
|
+
readonly 'compaction.start': "durable";
|
|
1008
|
+
readonly 'compaction.end': "durable";
|
|
1009
|
+
readonly 'memory.pruned': "durable";
|
|
1010
|
+
readonly error: "durable";
|
|
1011
|
+
readonly 'stream.event': "live";
|
|
1012
|
+
readonly 'streaming.start': "live";
|
|
1013
|
+
readonly 'streaming.end': "live";
|
|
1014
|
+
readonly 'agent.status': "live";
|
|
1015
|
+
readonly 'steer.consumed': "live";
|
|
1016
|
+
readonly 'run.paused': "live";
|
|
1017
|
+
readonly 'run.resumed': "live";
|
|
1018
|
+
readonly 'run.pause_requested': "live";
|
|
1019
|
+
readonly 'run.pause_cancelled': "live";
|
|
1020
|
+
readonly 'approval.required': "capability";
|
|
1021
|
+
readonly 'approval.resolved': "capability";
|
|
1022
|
+
readonly 'ask.user.required': "capability";
|
|
1023
|
+
readonly 'ask.user.resolved': "capability";
|
|
1024
|
+
readonly 'plan.approval.required': "capability";
|
|
1025
|
+
readonly 'plan.approval.resolved': "capability";
|
|
1026
|
+
readonly 'budget.notice': "capability";
|
|
1027
|
+
readonly 'prompt.budget.notice': "capability";
|
|
1028
|
+
readonly 'tool.call.mismatch.notice': "capability";
|
|
1029
|
+
readonly 'image.degradation.notice': "capability";
|
|
1030
|
+
readonly 'progress.stall.notice': "capability";
|
|
1031
|
+
readonly 'compaction.reactive.notice': "capability";
|
|
1032
|
+
readonly 'session.cost-budget-exceeded': "capability";
|
|
1033
|
+
readonly 'session.crash-gap-detected': "capability";
|
|
1034
|
+
readonly 'session.history-capped': "capability";
|
|
1035
|
+
readonly 'session.write-lease-denied': "capability";
|
|
1036
|
+
readonly 'session.write-lease-restored': "capability";
|
|
1037
|
+
};
|
|
1038
|
+
type EventDomain = 'durable' | 'live' | 'capability';
|
|
1039
|
+
/** 查询某事件类型的域归属。未登记的事件返回 undefined。 */
|
|
1040
|
+
declare function getEventDomain(eventType: string): EventDomain | undefined;
|
|
1042
1041
|
//#endregion
|
|
1043
1042
|
//#region src/engine-command.d.ts
|
|
1044
1043
|
/**
|
|
@@ -1107,6 +1106,36 @@ type EngineCommand = {
|
|
|
1107
1106
|
count: number;
|
|
1108
1107
|
};
|
|
1109
1108
|
//#endregion
|
|
1109
|
+
//#region src/file-command.d.ts
|
|
1110
|
+
/**
|
|
1111
|
+
* file-command.ts — 文件式 slash 命令协议类型(RFC-421 D1).
|
|
1112
|
+
*
|
|
1113
|
+
* `FileCommand` 是"文件式命令"的跨包协议类型:`.claude/commands`、`.otto/commands`
|
|
1114
|
+
* 与插件 `commands/` 目录发现的 markdown 命令,经解析后统一为本类型。
|
|
1115
|
+
*
|
|
1116
|
+
* 归属本包(`@x-otto/interchange`):原定义在 `@x-otto/claude-compat`(兼容层包),
|
|
1117
|
+
* 但该类型是宿主核心公共 API 的地基(coding/types.ts、app.ts、ports.ts 等多处 import),
|
|
1118
|
+
* 宿主核心类型不应以可选兼容层为真源。RFC-421 D1 将其上移到零依赖协议类型域,
|
|
1119
|
+
* claude-compat 与 coding 都从本包取,消除依赖倒置。
|
|
1120
|
+
*
|
|
1121
|
+
* 语义不变:字段与迁移前逐字段一致(RFC-421 规则 1:只动归属不动语义)。
|
|
1122
|
+
*/
|
|
1123
|
+
interface FileCommand {
|
|
1124
|
+
/** 命名空间名(子目录 `/` → `:`),如 `frontend:component` 或 `review`。 */
|
|
1125
|
+
name: string;
|
|
1126
|
+
description?: string;
|
|
1127
|
+
argumentHint?: string;
|
|
1128
|
+
/** §3.0 归一后的工具名(仅提示/将来收敛用,D2 不强制收敛回合工具集——见 RFC §10 C8)。 */
|
|
1129
|
+
allowedTools?: string[];
|
|
1130
|
+
model?: string;
|
|
1131
|
+
body: string;
|
|
1132
|
+
source: 'claude' | 'otto' | 'plugin';
|
|
1133
|
+
scope: 'project' | 'repository' | 'user';
|
|
1134
|
+
/** 贡献来源插件 id(`source==='plugin'` 时存在)= unregister key(RFC-044 R6)。 */
|
|
1135
|
+
pluginId?: string;
|
|
1136
|
+
filePath: string;
|
|
1137
|
+
}
|
|
1138
|
+
//#endregion
|
|
1110
1139
|
//#region src/todo.d.ts
|
|
1111
1140
|
/**
|
|
1112
1141
|
* Todo 状态与条目 — 单一真源,供 write_todos 等工具跨层消费。
|
|
@@ -1163,43 +1192,6 @@ interface ProcessTracker {
|
|
|
1163
1192
|
};
|
|
1164
1193
|
}
|
|
1165
1194
|
//#endregion
|
|
1166
|
-
//#region src/image.d.ts
|
|
1167
|
-
/** Image: base64/mime/url model for image payloads (unified image type). */
|
|
1168
|
-
interface NormalizedImage {
|
|
1169
|
-
/** 裸 base64(已去空白),不含 `data:...;base64,` 前缀。 */
|
|
1170
|
-
base64: string;
|
|
1171
|
-
/** 尽力得到的 MIME(小写),如 `image/png`;无法判定时为 ''。 */
|
|
1172
|
-
mediaType: string;
|
|
1173
|
-
/**
|
|
1174
|
-
* base64 是否可解码:非空 + 合法 charset + 长度 %4≠1 + 不是字面量 "undefined"。
|
|
1175
|
-
* 为 false 时调用方应**降级为文本占位**而非把坏数据发往 API(否则整请求 400)。
|
|
1176
|
-
*/
|
|
1177
|
-
valid: boolean;
|
|
1178
|
-
}
|
|
1179
|
-
/**
|
|
1180
|
-
* 把图片来源归一为 { 裸 base64, mediaType, valid }。
|
|
1181
|
-
* 接受两种形态:完整 data URI 或裸 base64。
|
|
1182
|
-
* mediaType 优先取 data URI 内声明的 mime,其次回退到显式传入的 mime。
|
|
1183
|
-
*/
|
|
1184
|
-
declare function normalizeImageData(source: string, mime?: string): NormalizedImage;
|
|
1185
|
-
/**
|
|
1186
|
-
* 终局架构 review 建议优化项:类型名从 AnthropicImageMime 改为 CommonImageMime——这 4 种
|
|
1187
|
-
* 格式(jpeg/png/gif/webp)是业界广泛支持的通用图片格式,非 Anthropic 独有(OpenAI 等
|
|
1188
|
-
* provider 同样接受这 4 种)。保留 `toAnthropicImageMime` 函数名不变——该名字准确描述了
|
|
1189
|
-
* 它的真实用途("归一到 Anthropic API 要求的枚举值",函数体内的兜底逻辑与 400 错误规避
|
|
1190
|
-
* 都是针对 Anthropic API 的具体行为),改类型名不改函数名两者互不矛盾:类型是通用值域,
|
|
1191
|
-
* 函数是该值域到 Anthropic 特定契约的映射。
|
|
1192
|
-
*/
|
|
1193
|
-
type CommonImageMime = 'image/jpeg' | 'image/png' | 'image/gif' | 'image/webp';
|
|
1194
|
-
/** @deprecated 改名为 CommonImageMime(类型语义修正,非厂商专属)。保留别名过渡,下个大版本移除。 */
|
|
1195
|
-
type AnthropicImageMime = CommonImageMime;
|
|
1196
|
-
/**
|
|
1197
|
-
* 归一到 Anthropic 接受的 4 种图片 MIME 之一。
|
|
1198
|
-
* 未知 mediaType 时按 base64 魔数嗅探,仍无法判定回退 image/png。
|
|
1199
|
-
* **永不返回空**——避免 media_type 字段缺失被 Anthropic API 以 "Field required" 拒绝。
|
|
1200
|
-
*/
|
|
1201
|
-
declare function toAnthropicImageMime(mediaType: string, base64: string): CommonImageMime;
|
|
1202
|
-
//#endregion
|
|
1203
1195
|
//#region src/plugin-perf.d.ts
|
|
1204
1196
|
/**
|
|
1205
1197
|
* plugin-perf.ts — 插件性能采集器结果的共享契约(RFC-118 小修,review S10)。
|
|
@@ -1216,233 +1208,5 @@ interface PluginPerfMetricResult {
|
|
|
1216
1208
|
error?: string;
|
|
1217
1209
|
}
|
|
1218
1210
|
//#endregion
|
|
1219
|
-
|
|
1220
|
-
/** Input: mentions, sigils, content providers — user input enrichment types. */
|
|
1221
|
-
/** sigil 子类型:`hashtag` 属 `#`,其余属 `@`。`resource` = 插件自定义资源(RFC-210 D2);
|
|
1222
|
-
* `shortcut` = 用户在本仓库自定义的文本快捷方式(RFC-233);`effort` = 推理投入档
|
|
1223
|
-
* (low/medium/high/xhigh/max,RFC-360 D3——不复用 `model`,两者在 `@` 面板需独立
|
|
1224
|
-
* 分类展示,复用会导致 effort 档位被误标"模型"分类)。 */
|
|
1225
|
-
type SigilKind = 'hashtag' | 'file' | 'person' | 'agent' | 'skill' | 'mcp' | 'plugin' | 'model' | 'resource' | 'shortcut' | 'effort';
|
|
1226
|
-
/** 触发前缀。 */
|
|
1227
|
-
type SigilPrefix = '#' | '@';
|
|
1228
|
-
/** 条目来源标识(unregisterBySource 据此批量注销,防僵尸条目)。 */
|
|
1229
|
-
type SigilSource = 'builtin' | 'plugin' | 'skill' | 'mcp' | (string & {});
|
|
1230
|
-
/**
|
|
1231
|
-
* 动态供给函数(pull 模型):按 query 懒查候选,服务 @file 等大候选集——
|
|
1232
|
-
* 不全量 register()。可同步或异步(文件系统遍历走异步)。
|
|
1233
|
-
*/
|
|
1234
|
-
type SigilProvider = (query: string, sigil: SigilPrefix) => SigilEntry[] | Promise<SigilEntry[]>;
|
|
1235
|
-
/** sigil 面板条目:label(展示)与 value(替换内容)严格分离(R2)。 */
|
|
1236
|
-
interface SigilEntry {
|
|
1237
|
-
/** 面板中展示的名称(简短、人类可读)。绝不进入 prompt 文本。 */
|
|
1238
|
-
label: string;
|
|
1239
|
-
/** 选中后替换 #trigger/@trigger 的实质内容。绝不在面板中完整展示。 */
|
|
1240
|
-
value: string;
|
|
1241
|
-
/** 面板中展示的描述(可选,列表副标题)。 */
|
|
1242
|
-
description?: string;
|
|
1243
|
-
/** 条目类型(影响面板分组/着色,并决定属于 # 还是 @)。 */
|
|
1244
|
-
kind: SigilKind;
|
|
1245
|
-
/** 来源标识(builtin | plugin | skill | mcp | 自定义 pluginId)。 */
|
|
1246
|
-
source?: SigilSource;
|
|
1247
|
-
/**
|
|
1248
|
-
* RFC-210 D2:resolve 引用。非空 = "提交时展开"型资源——展开管线(app.expandSigilChips)
|
|
1249
|
-
* 用此 id 查 SigilResolverRegistry 拿 resolve 函数,把该条目的 chip 替换为其返回值。
|
|
1250
|
-
* 空 = 透传型(chip 原样给 LLM)或纯文本型(value 即内容),行为与现状完全一致。
|
|
1251
|
-
*/
|
|
1252
|
-
resolverId?: string;
|
|
1253
|
-
}
|
|
1254
|
-
/**
|
|
1255
|
-
* RFC-210 D2:@ 资源提交时展开函数(代码契约——不可序列化,归 coding 层
|
|
1256
|
-
* SigilResolverRegistry,与纯数据的 PluginInputRegistry 平行;D9 两类契约纪律)。
|
|
1257
|
-
*/
|
|
1258
|
-
interface SigilResolver {
|
|
1259
|
-
/** resolver id,命名空间 `<pluginId>:<name>`(内置无前缀)。 */
|
|
1260
|
-
id: string;
|
|
1261
|
-
/** 提交时展开:输入 chip 参数(`[@kind:param]` 的 param 段),返回发给 LLM 的内容。 */
|
|
1262
|
-
resolve: (param: string, ctx: SigilResolveContext) => string | Promise<string>;
|
|
1263
|
-
/** 超时(ms,缺省 10_000,对齐既有 CONTEXT_CHIPS 约束)。 */
|
|
1264
|
-
timeoutMs?: number;
|
|
1265
|
-
/**
|
|
1266
|
-
* uiHostOnly(RFC-210 评审 B11):true = 读取"UI 所在机器"的本地资源(非 workspaceDir
|
|
1267
|
-
* 内容),只应在与用户同机的宿主进程(TUI/cli)执行;service expand 端点跳过执行。
|
|
1268
|
-
* @clipboard = true(读桌面剪贴板);@changes/@git = false(读 workspaceDir git 状态,
|
|
1269
|
-
* service 为远程 workspace 服务时服务器上的状态正是用户要的内容)。
|
|
1270
|
-
*/
|
|
1271
|
-
uiHostOnly?: boolean;
|
|
1272
|
-
}
|
|
1273
|
-
/** SigilResolver.resolve 的执行上下文。 */
|
|
1274
|
-
interface SigilResolveContext {
|
|
1275
|
-
workspaceDir: string;
|
|
1276
|
-
/** 输出上限(字符,缺省 20_000,超限截断——对齐既有 MAX_OUTPUT)。 */
|
|
1277
|
-
maxOutput: number;
|
|
1278
|
-
}
|
|
1279
|
-
/**
|
|
1280
|
-
* 插件输入注册表(UI 无关,由 createApp() 创建单例,实现留 @x-otto/coding)。
|
|
1281
|
-
*
|
|
1282
|
-
* 静态 push 供给(register)+ 动态 pull 供给(registerProvider,服务 @file
|
|
1283
|
-
* 大候选集懒查,RFC §1.3.1 F-domain / RFC-044 M044-07)。
|
|
1284
|
-
*/
|
|
1285
|
-
interface PluginInputRegistry {
|
|
1286
|
-
/** 注册一批条目(last-write-wins,按 (label, kind) 复合键去重)。 */
|
|
1287
|
-
register(entries: SigilEntry[]): void;
|
|
1288
|
-
/**
|
|
1289
|
-
* 注册某 sigil 的动态供给器(pull 模型,按 query 懒查,如 @file)。
|
|
1290
|
-
* 返回注销函数。其结果在 searchAsync 中与静态条目合并。
|
|
1291
|
-
*/
|
|
1292
|
-
registerProvider(sigil: SigilPrefix, provider: SigilProvider): () => void;
|
|
1293
|
-
/**
|
|
1294
|
-
* 按 query + sigil 过滤匹配条目。过滤在此完成(R4),UI 只渲染结果。
|
|
1295
|
-
* 命中数达 maxResults 立即返回,不全量遍历(F-domain 性能)。
|
|
1296
|
-
* 仅静态条目;动态 provider 结果见 searchAsync。
|
|
1297
|
-
*/
|
|
1298
|
-
search(query: string, sigil?: SigilPrefix, maxResults?: number): SigilEntry[];
|
|
1299
|
-
/**
|
|
1300
|
-
* 异步搜索:静态条目(即时)+ 动态 provider 结果(await)合并去重。
|
|
1301
|
-
* UI 应优先用此方法以纳入 @file 等懒查候选;无 provider 时等价 search。
|
|
1302
|
-
*/
|
|
1303
|
-
searchAsync(query: string, sigil?: SigilPrefix, maxResults?: number): Promise<SigilEntry[]>;
|
|
1304
|
-
/** 返回某 sigil(或全部)的全量条目(只读快照)。 */
|
|
1305
|
-
getAll(sigil?: SigilPrefix): readonly SigilEntry[];
|
|
1306
|
-
/** 按 label 查首个匹配条目。 */
|
|
1307
|
-
findByLabel(label: string): SigilEntry | undefined;
|
|
1308
|
-
/** 注销某 label 的所有条目,返回是否删除过。 */
|
|
1309
|
-
unregister(label: string): boolean;
|
|
1310
|
-
/** 注销某 source 的所有条目(插件 unload 必调,防僵尸——R5)。 */
|
|
1311
|
-
unregisterBySource(source: string): void;
|
|
1312
|
-
}
|
|
1313
|
-
/** 根据 kind 推断其归属的 sigil 前缀。 */
|
|
1314
|
-
declare function sigilOf(kind: SigilKind): SigilPrefix;
|
|
1315
|
-
/** sigil 触发信息:检测到的 sigil 字符 + 查询串 + 锚点位置。 */
|
|
1316
|
-
interface SigilTrigger {
|
|
1317
|
-
/** 触发的 sigil 字符。 */
|
|
1318
|
-
sigil: SigilPrefix;
|
|
1319
|
-
/** sigil 后的查询串(不含 sigil 字符本身)。 */
|
|
1320
|
-
query: string;
|
|
1321
|
-
/** sigil 字符在文本中的起始偏移(替换时从此处删到 cursorOffset)。 */
|
|
1322
|
-
anchor: number;
|
|
1323
|
-
}
|
|
1324
|
-
/**
|
|
1325
|
-
* 从光标前文本提取 sigil 触发。无触发返回 null。
|
|
1326
|
-
* anchor 指向 sigil 字符位置(替换区间 = [anchor, cursorOffset))。
|
|
1327
|
-
*/
|
|
1328
|
-
declare function extractSigilPrefix(input: string, cursorOffset: number): SigilTrigger | null;
|
|
1329
|
-
/**
|
|
1330
|
-
* 设计问题 #5 / RFC-212 D1:判断当前触发是否落在「已被 Esc 驳回」的同一 sigil token 上。
|
|
1331
|
-
* 为真则不应弹回面板——用户 Esc 关掉后继续在同一 `@`/`#` 上输入,不再打扰。
|
|
1332
|
-
* 比较只看 sigil + anchor(token 身份)——anchor 由 `adjustDismissedSigil` 随编辑动态位移,
|
|
1333
|
-
* 不是原始触发时的绝对位置,故本函数无需再关心"位置是否漂移"。
|
|
1334
|
-
*/
|
|
1335
|
-
declare function isSigilDismissed(trig: Pick<SigilTrigger, 'sigil' | 'anchor'>, dismissed: Pick<SigilTrigger, 'sigil' | 'anchor'> | null): boolean;
|
|
1336
|
-
/**
|
|
1337
|
-
* RFC-212 D1:token 身份绑定的驳回记录。`tokenLength` 锚定在驳回快照时刻
|
|
1338
|
-
* (= `cursorOffset - anchor`,即 1 + query.length),后续编辑不动态重算,
|
|
1339
|
-
* 语义见 `adjustDismissedSigil` 的四类区间判定。
|
|
1340
|
-
*/
|
|
1341
|
-
interface DismissedSigil {
|
|
1342
|
-
sigil: SigilPrefix;
|
|
1343
|
-
anchor: number;
|
|
1344
|
-
tokenLength: number;
|
|
1345
|
-
}
|
|
1346
|
-
/**
|
|
1347
|
-
* RFC-212 D1 状态机核心:给定旧驳回记录与本次文本编辑(oldText → newText),
|
|
1348
|
-
* 计算编辑后应生效的驳回记录(`null` = 清态回 IDLE,编辑摧毁了 token 或与其无关)。
|
|
1349
|
-
* 纯函数,不依赖 React state/ref,可独立单测。
|
|
1350
|
-
*
|
|
1351
|
-
* 判定依据编辑区间 `[start, end)`(old 坐标系)与 token 范围 `[anchor, anchor+tokenLength)`
|
|
1352
|
-
* 的相对关系,四类穷举(`anchor < tokenEnd` 恒成立,`start <= end` 恒成立):
|
|
1353
|
-
*
|
|
1354
|
-
* 1. `end <= anchor`(编辑完全在 token 之前)→ 锚点位移:`anchor += delta`,tokenLength 不变。
|
|
1355
|
-
* 2. `start >= tokenEnd`(编辑完全在 token 之后,"离开"场景)→ anchor/tokenLength 不变;
|
|
1356
|
-
* 是否真的维持驳回态,由调用方比较新触发的 anchor 是否等于此处的 anchor 决定
|
|
1357
|
-
* (`isSigilDismissed`)——本函数只负责"token 本身未被触碰"这一半的判定。
|
|
1358
|
-
* 3. `start > anchor && start < tokenEnd`(编辑落在 token 内部、不含 `@`/`#` 字符本身)
|
|
1359
|
-
* → 维持驳回态,anchor/tokenLength 均不变(不因编辑扩大 tokenLength——用户打字越过
|
|
1360
|
-
* 快照边界即落入情形 2,交由新触发比较决定去留,而非线性扩张判定区间)。
|
|
1361
|
-
* 4. 其余(`start <= anchor` 且与 token 有重叠,即编辑波及了 sigil 字符本身)
|
|
1362
|
-
* → 清态回 IDLE(token 身份已被破坏)。
|
|
1363
|
-
*/
|
|
1364
|
-
declare function adjustDismissedSigil(dismissed: DismissedSigil | null, oldText: string, newText: string): DismissedSigil | null;
|
|
1365
|
-
/**
|
|
1366
|
-
* 用选中条目的 value 替换 [anchor, cursorOffset) 区间(即 `#query`/`@query`)。
|
|
1367
|
-
* 返回新文本与新光标偏移(落在替换内容末尾)。
|
|
1368
|
-
*
|
|
1369
|
-
* 注意:value 原样注入(含换行/markdown 不校验,R2)。
|
|
1370
|
-
* 调用方应走 PromptInput.update() 应用结果,以重算 detectMode(D7:# 替换后 mode 通常变 'send')。
|
|
1371
|
-
*/
|
|
1372
|
-
declare function applySigilCompletion(input: string, cursorOffset: number, anchor: number, entry: SigilEntry): {
|
|
1373
|
-
text: string;
|
|
1374
|
-
offset: number;
|
|
1375
|
-
};
|
|
1376
|
-
/**
|
|
1377
|
-
* RFC-212 D3:用选中条目的 value 替换一个**已存在 chip**的 `[chipStart, chipEnd)` 区间
|
|
1378
|
-
* ——与 `applySigilCompletion`(从 anchor 插入,输入是"用户刚打的 @query")语义不同:
|
|
1379
|
-
* 这里输入是"光标停靠在一个已展开的 chip 上,用户按 Enter 重新选择替换它",替换区间是
|
|
1380
|
-
* chip 的实际边界,不涉及 anchor/query 概念。返回新文本与新光标偏移(落在替换内容末尾)。
|
|
1381
|
-
*
|
|
1382
|
-
* 注意:与 `applySigilCompletion` 不同,本函数不追加尾随空格——chip 替换场景两侧通常
|
|
1383
|
-
* 已有边界(chip 本身的方括号,或前后文本),追加空格会破坏原有间距,交由调用方决定
|
|
1384
|
-
* 是否需要额外分隔符。
|
|
1385
|
-
*/
|
|
1386
|
-
declare function applySigilReplacement(input: string, chipStart: number, chipEnd: number, entry: SigilEntry): {
|
|
1387
|
-
text: string;
|
|
1388
|
-
offset: number;
|
|
1389
|
-
};
|
|
1390
|
-
/**
|
|
1391
|
-
* RFC-215 D1:文本变更来源。每个修改输入框文本的路径必须声明自己是谁——
|
|
1392
|
-
* 取代旧 `detectSigil: boolean`(普查发现 16 类调用点中 10 类语义错误,布尔无法
|
|
1393
|
-
* 强迫调用方思考来源语义,见 RFC-215 §0.4)。
|
|
1394
|
-
*
|
|
1395
|
-
* sigil 触发准入的唯一判定:仅 `'typing'` 允许进入检测(`evaluateSigilTrigger`)。
|
|
1396
|
-
* 新增来源归类不确定时选 `'programmatic'`(最保守:不触发任何检测)。
|
|
1397
|
-
*/
|
|
1398
|
-
type TextChangeSource = /** 用户逐字键入/删除(editKey 路径、IME 多字符 chunk)。 */'typing' /** 历史导航召回、搜索回填、/history 面板回填、外部编辑器写回、undo 回退、提交阻断跳转。 */ | 'programmatic' /** 粘贴插入(含短粘贴直插与大段折叠后插入)——RFC-215 D2:不触发 sigil 面板。 */ | 'paste'
|
|
1399
|
-
/**
|
|
1400
|
-
* ghost/typeahead/shell 补全接受、sigil 补全/删除/chip 替换回写。
|
|
1401
|
-
* 当前对 sigil 检测的行为等价 `'programmatic'`(都不触发),预留语义位——
|
|
1402
|
-
* 补全接受保留 typeahead 上下文语义、程序回填重置一切瞬态,未来分叉时不需改签名
|
|
1403
|
-
* (RFC-215 D1,评审 F2:勿因"有值无独立消费"误删)。
|
|
1404
|
-
*/
|
|
1405
|
-
| 'completion';
|
|
1406
|
-
/** `evaluateSigilTrigger` 的判定结果(RFC-215 D3)。 */
|
|
1407
|
-
interface SigilTriggerDecision {
|
|
1408
|
-
/**
|
|
1409
|
-
* - `'open'`:产生新触发,调用方应设触发上下文并打开面板。
|
|
1410
|
-
* - `'suppress'`:本次变更不产生新触发,也不主动关闭已开面板——调用方仅清触发上下文,
|
|
1411
|
-
* 面板关闭交由既有失焦/Esc 机制(与旧 `!detectSigil` 分支行为一致)。
|
|
1412
|
-
* - `'close'`:触发条件已消失(原 `@query` 被编辑破坏),调用方应清触发上下文并
|
|
1413
|
-
* 通知宿主关闭面板(宿主未接线关闭回调时退化为 suppress 行为,向后兼容)。
|
|
1414
|
-
*/
|
|
1415
|
-
action: 'open' | 'suppress' | 'close';
|
|
1416
|
-
/** action='open' 时的触发信息。 */
|
|
1417
|
-
trigger?: SigilTrigger;
|
|
1418
|
-
/** 经 `adjustDismissedSigil` 位移后的驳回态(任何来源都执行位移;open 时已清为 null)。 */
|
|
1419
|
-
dismissed: DismissedSigil | null;
|
|
1420
|
-
}
|
|
1421
|
-
/**
|
|
1422
|
-
* RFC-215 D3:sigil 触发准入状态机(纯函数)。与 `adjustDismissedSigil`(RFC-212 D1,
|
|
1423
|
-
* 驳回态维护)合并为完整的一台触发机器——本函数管"是否触发",后者管"已驳回状态下
|
|
1424
|
-
* 是否重新触发",调用顺序内聚在此,外部只消费 decision。
|
|
1425
|
-
*
|
|
1426
|
-
* 判定顺序(RFC-215 D3,六步):
|
|
1427
|
-
* ① 位移驳回态(任何来源都执行——粘贴/回填同样会移动被驳回 token 的位置,
|
|
1428
|
-
* 跳过位移会复发 RFC-212 缺陷 1;重要事项规则 3);
|
|
1429
|
-
* ② 非 `'typing'` 来源 → suppress(历史导航/粘贴/补全接受不触发面板——本 RFC 的 bug 修复本体);
|
|
1430
|
-
* ③ 文本非增长 → suppress(保留既有 `grew` 优化语义:删除/替换不产生新触发);
|
|
1431
|
-
* ④ 无 sigil 触发命中(或被 `sigilFilter` 过滤)→ close(原触发被编辑破坏,面板应关闭);
|
|
1432
|
-
* ⑤ 触发命中但落在已驳回 token 上 → suppress(Esc 驳回后继续输入不再打扰);
|
|
1433
|
-
* ⑥ 触发命中且未被驳回 → open + 清驳回态。
|
|
1434
|
-
*
|
|
1435
|
-
* `sigilFilter` 缺省 `(sigil) => sigil === '@'`——与 TUI 现状的 @-only 硬过滤一致
|
|
1436
|
-
* (`#` 走 memory 模式检测,不在本函数管辖;评审 F4-2)。
|
|
1437
|
-
*/
|
|
1438
|
-
declare function evaluateSigilTrigger(input: {
|
|
1439
|
-
source: TextChangeSource;
|
|
1440
|
-
oldText: string;
|
|
1441
|
-
newText: string;
|
|
1442
|
-
cursorOffset: number;
|
|
1443
|
-
dismissed: DismissedSigil | null;
|
|
1444
|
-
sigilFilter?: (sigil: SigilPrefix) => boolean;
|
|
1445
|
-
}): SigilTriggerDecision;
|
|
1446
|
-
//#endregion
|
|
1447
|
-
export { type A2uiComponent, type A2uiContent, type AgentSessionEvent, type AgentSessionEventMap, type AgentSessionEventType, type AgentSessionSubscriber, type AgentTool, type AnthropicImageMime, type Api, type AskUserQuestion, type AssistantMessage, CONVERSATION_SUMMARY_PREFIX, type CapabilityFact, type ChildProcessConfig, type CommonImageMime, type ContentPart, type ContextFragment, type ContextFragmentId, type Cost, type DismissedSigil, type EngineCommand, type GrillAnswer, type GrillOption, type GrillQuestion, type GrillRequest, type ImageContent, type KnownApi, type KnownProvider, type Message, type Model, type ModelCapabilityFacts, type ModelSpec, type ModelStrength, type NormalizedImage, type PluginInputRegistry, type PluginPerfMetricResult, type ProcessTracker, type PromptStopReason, type Provider, type ProviderUsageSnapshot, type SigilEntry, type SigilKind, type SigilPrefix, type SigilProvider, type SigilResolveContext, type SigilResolver, type SigilSource, type SigilTrigger, type SigilTriggerDecision, type StopReason, type StreamEvent, type SystemNotificationMessage, type TextChangeSource, type TextContent, type ThinkingContent, type ThinkingLevel, type TodoItem, type TodoStatus, type ToolCall, type ToolCallContext, type ToolCallEvent, type ToolDescriptionContext, type ToolErrorKind, type ToolResult, type ToolResultMessage, type Usage, type UserMessage, type ZodType, adjustDismissedSigil, applySigilCompletion, applySigilReplacement, boundFragment, collectModelCapabilityFacts, contextFragmentBytes, evaluateSigilTrigger, extractSigilPrefix, extractToolResultText, getToolCallsByAssistantMessage, hasToolCalls, isSigilDismissed, modelImageCapability, modelSupportsImages, normalizeImageData, sigilOf, toAnthropicImageMime };
|
|
1211
|
+
export { type A2uiComponent, type A2uiContent, type AgentSessionEvent, type AgentSessionEventMap, type AgentSessionEventType, type AgentSessionSubscriber, type AgentTool, type AgentToolDefinition, type AnthropicImageMime, type Api, type AskUserQuestion, type AssistantMessage, CONVERSATION_SUMMARY_PREFIX, type CapabilityFact, type ChildProcessConfig, type CommonImageMime, type ContentPart, type ContextFragment, type ContextFragmentId, type Cost, type DismissedSigil, EVENT_DOMAIN, type EngineCommand, type EventDomain, type FileCommand, type GrillAnswer, type GrillOption, type GrillQuestion, type GrillRequest, type ImageContent, type KnownApi, type KnownProvider, type Message, type Model, type ModelCapabilityFacts, type ModelSpec, type ModelStrength, type NormalizedImage, type PluginInputRegistry, type PluginPerfMetricResult, type ProcessTracker, type PromptStopReason, type Provider, type ProviderUsageSnapshot, SYSTEM_PROMPT_SECTIONS, SYSTEM_PROMPT_SECTION_ORDER, type SigilEntry, type SigilKind, type SigilPrefix, type SigilProvider, type SigilResolveContext, type SigilResolver, type SigilSource, type SigilTrigger, type SigilTriggerDecision, type StopReason, type StreamEvent, type SystemNotificationMessage, type SystemPromptLane, type SystemPromptSectionSpec, type TextChangeSource, type TextContent, type ThinkingContent, type ThinkingLevel, type TodoItem, type TodoStatus, type ToolCall, type ToolCallContext, type ToolCallEvent, type ToolDescriptionContext, type ToolErrorKind, type ToolExecutionPolicy, type ToolResult, type ToolResultMessage, type Usage, type UserMessage, type ZodType, adjustDismissedSigil, applySectionBudget, applySigilCompletion, applySigilReplacement, boundFragment, collectModelCapabilityFacts, contextFragmentBytes, evaluateSigilTrigger, extractSigilPrefix, extractToolResultText, getEventDomain, getToolCallsByAssistantMessage, hasToolCalls, isSigilDismissed, modelImageCapability, modelSupportsImages, normalizeImageData, sigilOf, toAnthropicImageMime };
|
|
1448
1212
|
//# sourceMappingURL=index.d.ts.map
|