@sema-agent/client-core 0.62.2 → 0.63.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +180 -0
- package/README.md +9 -2
- package/dist/autoModeUnavailable.d.ts +77 -0
- package/dist/autoModeUnavailable.js +101 -0
- package/dist/engineIdentity.d.ts +94 -0
- package/dist/engineIdentity.js +143 -0
- package/dist/engineNoticeCodes.d.ts +91 -0
- package/dist/engineNoticeCodes.js +215 -0
- package/dist/gateVocabulary.d.ts +67 -0
- package/dist/gateVocabulary.js +134 -0
- package/dist/hitl/persistedRulesWire.d.ts +63 -1
- package/dist/hitl/persistedRulesWire.js +86 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +21 -0
- package/dist/liveInitToolFace.js +13 -0
- package/dist/permissionRuleIssue.d.ts +33 -0
- package/dist/permissionRuleIssue.js +126 -0
- package/dist/postureKnob.d.ts +92 -0
- package/dist/postureKnob.js +181 -0
- package/dist/steering.d.ts +6 -1
- package/dist/steering.js +10 -2
- package/dist/subagentContentStore.d.ts +5 -1
- package/dist/subagentContentStore.js +4 -2
- package/dist/toolRoster.d.ts +182 -0
- package/dist/toolRoster.js +236 -0
- package/dist/workflow.js +4 -1
- package/dist/workflowClient.js +63 -6
- package/dist/workflowMonitor.d.ts +20 -4
- package/dist/workflowMonitor.js +10 -0
- package/docs/INTEGRATION-CLIENTS.md +526 -9
- package/package.json +4 -4
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { capForDisplay } from './fleetTaskDesc.js';
|
|
2
|
+
/**
|
|
3
|
+
* 一个旋钮的值是谁定的 —— 四词闭集,**顺序即优先序**(engine 侧是穷举 switch,加词在那里编译红)。
|
|
4
|
+
* · `env` —— 这台机器的 env 变量钉的(部署主权,恒赢任何下发值);
|
|
5
|
+
* · `center` —— 配置中心发布的(重启生效;本机写同名 env 即把这个键收回);
|
|
6
|
+
* · `posture` —— 从**部署形**派生的(单用户 turnkey);
|
|
7
|
+
* · `engine-default` —— 没人钉过,内建缺省在岗。
|
|
8
|
+
* 🔴 本包按**开集**读实际值(词表属主在引擎侧,加词不该让消费端把一个合法读数判没);这张表是
|
|
9
|
+
* **优先序与判据**的真源,不是一道准入门。
|
|
10
|
+
|
|
11
|
+
* 🔴 形制:`Object.freeze` 的数组,**不是**只在类型面只读的 `readonly T[]` —— 后者一行 `.splice()`
|
|
12
|
+
* 就能改,而公面消费者拿到的正是这个实例(本仓已定谳的病形,同 `RESUME_RETRY_LATER_CODES`)。
|
|
13
|
+
*/
|
|
14
|
+
export const POSTURE_SOURCE_WORDS = Object.freeze(['env', 'center', 'posture', 'engine-default']);
|
|
15
|
+
/**
|
|
16
|
+
* 「**运维显式表态过吗**」——只有 `env` / `center` 两词算数。
|
|
17
|
+
*
|
|
18
|
+
* 🔴 `posture` 派生出来的 `true` **不是**「有人要求过」:它是部署形状的推论,换一台机器就变。
|
|
19
|
+
* 把它读成表态,会让「运维明确开过这个开关」这句话在一台谁都没碰过的机器上为真。
|
|
20
|
+
* 🔴 表外词(开集逃生口)一律**不算**表态:读不懂的来源不是「有人钉过」的证据。
|
|
21
|
+
*/
|
|
22
|
+
export function postureSourceIsOperatorPinned(source) {
|
|
23
|
+
return source === 'env' || source === 'center';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 这根旋钮的来源词,**答不出来就答不出来**。
|
|
27
|
+
* 🔴 legacy 行(老 worker 的裸值)⇒ `undefined`:形上的占位值不是一次观测,交出去就是编答案。
|
|
28
|
+
*/
|
|
29
|
+
export function postureKnobSourceOf(knob) {
|
|
30
|
+
if (knob === undefined || knob.legacy === true)
|
|
31
|
+
return undefined;
|
|
32
|
+
return knob.source;
|
|
33
|
+
}
|
|
34
|
+
/** 旋钮 → 人话名。**唯一铸点**(三端共用一套词;别在各端的行装配里另起一份)。 */
|
|
35
|
+
const KNOB_LABELS = Object.freeze({
|
|
36
|
+
durableApproval: 'durable approval',
|
|
37
|
+
streamAskWindowMs: 'approval window',
|
|
38
|
+
sessionAutoTitle: 'session auto-title',
|
|
39
|
+
});
|
|
40
|
+
/** `note` 上屏封长(UTF-16 单元,按**转义后**的长度算;与 readFace 那一格同值同理由)。 */
|
|
41
|
+
const KNOB_NOTE_MAX = 256;
|
|
42
|
+
/** `source` 上屏封长(同上)。 */
|
|
43
|
+
const KNOB_WORD_MAX = 40;
|
|
44
|
+
/** 一只 `{value, source, note}` 读数的公共窄读(值判据由调用方给)。坏形 ⇒ `undefined`。 */
|
|
45
|
+
function readKnob(raw, valueOk) {
|
|
46
|
+
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
47
|
+
return undefined;
|
|
48
|
+
const r = raw;
|
|
49
|
+
if (!valueOk(r.value))
|
|
50
|
+
return undefined;
|
|
51
|
+
if (typeof r.source !== 'string' || r.source.length === 0)
|
|
52
|
+
return undefined;
|
|
53
|
+
// `note` 允许空串(自由文本;空文本本身也是一句读数,不是「读不出」)。
|
|
54
|
+
if (typeof r.note !== 'string')
|
|
55
|
+
return undefined;
|
|
56
|
+
return { value: r.value, source: r.source, note: r.note };
|
|
57
|
+
}
|
|
58
|
+
const isBool = (v) => typeof v === 'boolean';
|
|
59
|
+
/** 窗值:有限**非负**数(负窗在引擎侧是拒启门,一个负数读数是坏形不是事实)。 */
|
|
60
|
+
const isWindowMs = (v) => typeof v === 'number' && Number.isFinite(v) && v >= 0;
|
|
61
|
+
/**
|
|
62
|
+
* `wiring.serverGates` → 三旋钮读数;**畸形一律 `undefined`**,绝不抛出。
|
|
63
|
+
*
|
|
64
|
+
* 🔴 **判别锚是 `durableApproval`**:它是这一面上唯一**两代都在**的旋钮(老 worker 上是裸布尔,
|
|
65
|
+
* 新 worker 上是读数)。它读不出来 ⇒ 整段缺席 —— 一份没有主锚的旋钮面答不了运维要问的那一问,
|
|
66
|
+
* 而半段会被当成完整答案(与 `writeProtectionPosture` 缺 `source` ⇒ 整段缺席同一条纪律)。
|
|
67
|
+
* 🔴 **旁枝坏形只丢那一根**:`streamAskWindowMs` / `sessionAutoTitle` 各自独立,一根形坏不该把
|
|
68
|
+
* 另外两根一起藏起来(旁枝与主锚的处置刻意不同,理由见上一条)。
|
|
69
|
+
* 🔴 **缺席不铸默认**:另两根整键缺席时这两格就是缺席。铸 `300000` / `true` 会把「这台 worker
|
|
70
|
+
* 说不出来」渲成「它说了这个值」——那正是本面存在要根治的病。
|
|
71
|
+
* ⚠️ 「整键缺席(老 worker)」与「在场但形坏」在旁枝上折成同一个缺席;「为什么答不出来」不是
|
|
72
|
+
* 这一位该回答的(见 {@link postureKnobDetail} 的 `reachable` 段)。
|
|
73
|
+
*/
|
|
74
|
+
export function projectServerGateKnobs(wiring) {
|
|
75
|
+
if (typeof wiring !== 'object' || wiring === null || Array.isArray(wiring))
|
|
76
|
+
return undefined;
|
|
77
|
+
const sg = wiring.serverGates;
|
|
78
|
+
if (typeof sg !== 'object' || sg === null || Array.isArray(sg))
|
|
79
|
+
return undefined;
|
|
80
|
+
const g = sg;
|
|
81
|
+
const raw = g.durableApproval;
|
|
82
|
+
let durableApproval;
|
|
83
|
+
let legacy = false;
|
|
84
|
+
if (typeof raw === 'boolean') {
|
|
85
|
+
// 老 worker(<7.67.0)的裸布尔:折进同一只壳,但立 legacy 位。`source` 是形上的占位,
|
|
86
|
+
// **不是**一次观测 —— 机读走 `postureKnobSourceOf`(它对 legacy 行答 undefined)。
|
|
87
|
+
durableApproval = { value: raw, source: 'engine-default', note: '', legacy: true };
|
|
88
|
+
legacy = true;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
durableApproval = readKnob(raw, isBool);
|
|
92
|
+
}
|
|
93
|
+
if (durableApproval === undefined)
|
|
94
|
+
return undefined;
|
|
95
|
+
const streamAskWindowMs = readKnob(g.streamAskWindowMs, isWindowMs);
|
|
96
|
+
const sessionAutoTitle = readKnob(g.sessionAutoTitle, isBool);
|
|
97
|
+
return {
|
|
98
|
+
durableApproval,
|
|
99
|
+
...(streamAskWindowMs !== undefined ? { streamAskWindowMs } : {}),
|
|
100
|
+
...(sessionAutoTitle !== undefined ? { sessionAutoTitle } : {}),
|
|
101
|
+
legacy,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 毫秒 → 人话。
|
|
106
|
+
* 🔴 **只在整除时才升单位**:`90m` 比 `1.5h` 更不容易被读错,而 `5400000ms` 谁也读不出是一个半
|
|
107
|
+
* 小时。除不尽 ⇒ 原样报毫秒(诚实优于好看)。
|
|
108
|
+
*/
|
|
109
|
+
function humanMs(ms) {
|
|
110
|
+
// 天不单列:`24h` 比 `1d` 更贴近运维钉回时写的那个数(`STREAM_ASK_WINDOW_MS`),小时这一档
|
|
111
|
+
// 已经把它读成人话了。
|
|
112
|
+
if (ms > 0 && ms % 3600000 === 0)
|
|
113
|
+
return `${ms / 3600000}h`;
|
|
114
|
+
if (ms > 0 && ms % 60000 === 0)
|
|
115
|
+
return `${ms / 60000}m`;
|
|
116
|
+
if (ms > 0 && ms % 1000 === 0)
|
|
117
|
+
return `${ms / 1000}s`;
|
|
118
|
+
return `${ms}ms`;
|
|
119
|
+
}
|
|
120
|
+
/** 值 → 上屏词。布尔渲 `on`/`off`(`true`/`false` 是给机器读的);数值按毫秒渲人话。 */
|
|
121
|
+
function knobValueWord(value) {
|
|
122
|
+
if (typeof value === 'boolean')
|
|
123
|
+
return value ? 'on' : 'off';
|
|
124
|
+
return humanMs(value);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 四态措辞的**唯一铸点**(三端共用一句话;别在各端的行装配里另写一遍 —— 与
|
|
128
|
+
* `readFacePostureDetail` / `writeProtectionDoctorDetail` 同一条纪律)。
|
|
129
|
+
*
|
|
130
|
+
* 🔴 四句刻意**逐字互异**(黑盒锚),对运维是四条不同的下一步:
|
|
131
|
+
* ① 读数在场 —— `<旋钮> <值> (source: <来源> — <指路句>)`;
|
|
132
|
+
* ② 读数在场但来自老 worker 的裸值(`legacy`)—— 报得出**值**,但逐字点明「这台 worker 说不出
|
|
133
|
+
* 是谁定的」;**句中不出现任何来源词**(冒称来源比不说更坏:它会让人以为查过了);
|
|
134
|
+
* ③ `opts.reachable === false` —— 「未观测」:这一次进程没读到 operator 响应。
|
|
135
|
+
* 🔴 **这一格先判**(0.63.1):它压过任何在手的读数 —— 宿主拿着上一拍的 view、这一拍探测
|
|
136
|
+
* 打不通时,它能翻的只有这一位;先看读数在不在会照渲上一拍的值,等于拿陈读数冒充现势;
|
|
137
|
+
* ④ `reachable:true` 但读数仍缺席 —— 「不报」:响应读到了,只是这一位读不出来。
|
|
138
|
+
* **不武断咎为版本**:整键缺席(老引擎)与在场却形坏折成同一个缺席,句子不能替一种情形撒谎。
|
|
139
|
+
* 🔴 ③④ 两句**一个值都不报** —— 它们要是顺口说了 `off`,消费端就会把「读不出」当成「关着」。
|
|
140
|
+
*
|
|
141
|
+
* ⚠️ **数值一律按毫秒读**:本面今天唯一的数值旋钮就是那只毫秒窗(门里有一条对 sdk spec 的钉:
|
|
142
|
+
* `ServerWiringGates` 上 `type: number` 的旋钮恰一根)。上游哪天加第二根非时长数值旋钮,那条
|
|
143
|
+
* 钉先红,免得这里的措辞开始对它撒谎。
|
|
144
|
+
*/
|
|
145
|
+
export function postureKnobDetail(knob, opts) {
|
|
146
|
+
// 🔴 **按自有属性查表**(同形族扫):键在型面上是闭三词,但本口吃的是运行期值 —— 一个 JS 调用方
|
|
147
|
+
// 塞进 `toString`,裸下标会命中 `Object.prototype` 上的函数并被拼进句子。读不出名字时退到
|
|
148
|
+
// 一个中性词:**名字读不出不该让「这根旋钮的值是什么」也一起说不出来**。
|
|
149
|
+
const label = Object.hasOwn(KNOB_LABELS, opts.knob) ? KNOB_LABELS[opts.knob] : 'posture knob';
|
|
150
|
+
// 🔴 **判序承重**(0.63.1,G-3):`!reachable` **先判**,压过任何在手的读数。调用惯例上宿主手里
|
|
151
|
+
// 就只有上一拍那一只 view —— 探测这一拍打不通时它能翻的只有 `reachable`,别的没得换。先看
|
|
152
|
+
// `knob !== undefined` 的旧序会照渲**上一拍的读数**,屏上一个字都看不出这一次根本没读到,
|
|
153
|
+
// 等于把陈读数冒充现势。打不通时旧读数不是现势:值与来源词一个都不许漏出去。
|
|
154
|
+
// ⇒ 求值序是 ③ → ①/② → ④(与上方四句的编号次序无关,编号只是四种情形的清单)。
|
|
155
|
+
if (!opts.reachable) {
|
|
156
|
+
return `${label} not observed (this end could not read the engine's diagnostics)`;
|
|
157
|
+
}
|
|
158
|
+
if (knob !== undefined) {
|
|
159
|
+
const word = knobValueWord(knob.value);
|
|
160
|
+
if (knob.legacy === true) {
|
|
161
|
+
return `${label} ${word} (this worker does not report who set it — an engine below 7.67.0)`;
|
|
162
|
+
}
|
|
163
|
+
const source = capForDisplay(knob.source, KNOB_WORD_MAX);
|
|
164
|
+
const note = capForDisplay(knob.note, KNOB_NOTE_MAX);
|
|
165
|
+
return note.length > 0
|
|
166
|
+
? `${label} ${word} (source: ${source} — ${note})`
|
|
167
|
+
: `${label} ${word} (source: ${source})`;
|
|
168
|
+
}
|
|
169
|
+
return `${label} not reported by this engine (an engine below 7.67.0, or a response this end could not parse)`;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* **编译期对账钉**(不出公面):sdk 的读数形必须能赋给本视图,`ServerWiringGates` 的三根旋钮
|
|
173
|
+
* 必须真是读数形 —— 上游改形时这一行是本包第一个红的地方。
|
|
174
|
+
*
|
|
175
|
+
* 🔴 反向**刻意不钉**(本视图不必能赋给 sdk 形):`source` 在本视图上放宽成任意 `string`(开集读),
|
|
176
|
+
* 那是**故意比铸点宽** —— 窄读域只许等于或宽于铸点域,钉反向会把这条纪律反过来判成错。
|
|
177
|
+
*/
|
|
178
|
+
const _postureKnobShapePin = (w) => w;
|
|
179
|
+
void _postureKnobShapePin;
|
|
180
|
+
const _serverGateKnobsShapePin = (g) => g;
|
|
181
|
+
void _serverGateKnobsShapePin;
|
package/dist/steering.d.ts
CHANGED
|
@@ -50,7 +50,12 @@ export interface EngineTaskStatusAttachment {
|
|
|
50
50
|
deltaSummary: null;
|
|
51
51
|
}
|
|
52
52
|
export type SteeringRenderable = SteeringInjectedAttachment | EngineTaskStatusAttachment;
|
|
53
|
-
/** Default-arm label for a source this shell build predates.
|
|
53
|
+
/** Default-arm label for a source this shell build predates.
|
|
54
|
+
*
|
|
55
|
+
* 🔴 **按自有属性查表**(0.63.0 同形存量清剿;与 `gateVocabulary` / `permissionRuleIssue` /
|
|
56
|
+
* `engineNoticeCodes` 三处同一条病形):`SOURCE_LABELS` 是对象表而 `source` **来自 wire**,
|
|
57
|
+
* 裸下标会命中 `Object.prototype` 上的成员 —— `steeringLabel('constructor')` 返回一个**函数**,
|
|
58
|
+
* 而 `??` 对函数不生效 ⇒ 它被原样拼进 attachment 的 label。默认臂在这一形上等于不存在。 */
|
|
54
59
|
export declare function steeringLabel(source: string): string;
|
|
55
60
|
/**
|
|
56
61
|
* Project one `steering_injected` wire event into its renderable attachment(s). Always returns at
|
package/dist/steering.js
CHANGED
|
@@ -38,9 +38,17 @@ const SOURCE_LABELS = {
|
|
|
38
38
|
background_tasks: 'Background tasks from before compaction announced to the model',
|
|
39
39
|
tools_delta: 'Newly available tools announced to the model',
|
|
40
40
|
};
|
|
41
|
-
/** Default-arm label for a source this shell build predates.
|
|
41
|
+
/** Default-arm label for a source this shell build predates.
|
|
42
|
+
*
|
|
43
|
+
* 🔴 **按自有属性查表**(0.63.0 同形存量清剿;与 `gateVocabulary` / `permissionRuleIssue` /
|
|
44
|
+
* `engineNoticeCodes` 三处同一条病形):`SOURCE_LABELS` 是对象表而 `source` **来自 wire**,
|
|
45
|
+
* 裸下标会命中 `Object.prototype` 上的成员 —— `steeringLabel('constructor')` 返回一个**函数**,
|
|
46
|
+
* 而 `??` 对函数不生效 ⇒ 它被原样拼进 attachment 的 label。默认臂在这一形上等于不存在。 */
|
|
42
47
|
export function steeringLabel(source) {
|
|
43
|
-
|
|
48
|
+
const known = typeof source === 'string' && Object.hasOwn(SOURCE_LABELS, source)
|
|
49
|
+
? SOURCE_LABELS[source]
|
|
50
|
+
: undefined;
|
|
51
|
+
return known ?? `Steering injected (${source})`;
|
|
44
52
|
}
|
|
45
53
|
/**
|
|
46
54
|
* core turn-attachments.ts renderBackgroundTasks line shape (198 vbl VERBATIM phrases):
|
|
@@ -97,7 +97,11 @@ export interface SubagentContentEvent {
|
|
|
97
97
|
* 「这一位是增量还是全文」变成读者要靠 `type` 去反推的事,而反推错的代价是内容重复上屏。 */
|
|
98
98
|
text?: string | undefined;
|
|
99
99
|
/** wire 上那一帧的**事件身份**(聚合两臂的幂等键;缺席 ⇒ 退回内容判据,见 publish 的两道闸)。
|
|
100
|
-
* 🔴
|
|
100
|
+
* 🔴 工具两臂**不拿它当身份**:那次调用的身份是 `toolCallId`,账本是 `items` 上那张卡。
|
|
101
|
+
* ⚠️ 但两臂**确实读它**(0.62.2 起):它是那张卡逐半的**阶段水位**({@link CardPhase} 的
|
|
102
|
+
* `start` / `end`),回答「这一发比卡上现在承载的那一阶段新还是旧」。缺席是一个值 ——
|
|
103
|
+
* 身份缺席而内容真的变了 ⇒ 那一半的水位被清掉(判不出新旧就诚实地说判不出)。
|
|
104
|
+
* 旧注写的「工具两臂不读这一位」自 0.62.2 起不成立。 */
|
|
101
105
|
eventId?: string | undefined;
|
|
102
106
|
toolCallId?: string | undefined;
|
|
103
107
|
toolName?: string | undefined;
|
|
@@ -445,7 +445,8 @@ function pushItem(s, item) {
|
|
|
445
445
|
/**
|
|
446
446
|
* 段闭合:把两条缓冲收成 item(段边界 = 工具起头,或这一轮 settle)。
|
|
447
447
|
*
|
|
448
|
-
* 🔴 **在所有还没兑现的段边界处一起切**({@link
|
|
448
|
+
* 🔴 **在所有还没兑现的段边界处一起切**({@link TaskContentState.pendingCuts};收口先于开始帧
|
|
449
|
+
* 到达时记下的位置)。
|
|
449
450
|
* 为什么不是「只切触发这一次闭合的那张卡的那一条」:边界记的是**缓冲上的位置**,不是某张卡的
|
|
450
451
|
* 私产 —— 一条缓冲上可以同时压着好几条(两张 orphan 卡交错),而闭合一旦发生缓冲就整只清空,
|
|
451
452
|
* 没被兑现的那些位置从此无处可切。异源复审 R5 的两个反例都是这一形:①兑现者是 `settle` 或
|
|
@@ -896,7 +897,8 @@ export function publishSubagentContentEvent(ev) {
|
|
|
896
897
|
});
|
|
897
898
|
// 🔴 边界虽然不在这里切,**位置**要在这里记下来:此刻缓冲里的那一截是「工具之前」那一段,
|
|
898
899
|
// 之后再流进来的是「工具之后」那一段。迟到的 `tool_start` 按这个位置切开两段(见
|
|
899
|
-
// {@link
|
|
900
|
+
// {@link TaskContentState.pendingCuts})—— 不记的话它只能把整条缓冲当成一段闭合,
|
|
901
|
+
// 两段就此黏死。"
|
|
900
902
|
recordCut(s);
|
|
901
903
|
// 卡是这一刻新铸的 ⇒ 结果那一半当然是「变了」
|
|
902
904
|
stampPhase(s, synthId, 'end', ev.eventId, true);
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/toolRoster.ts — 一条腿的**工具名册**(`wiring_manifest.tools: ToolRoster`)窄读器 +
|
|
3
|
+
* `tool_roster_delta` 应用(0.63.0;L-161;engine >=7.66.0 有臂 / >=7.9.0 真推 /
|
|
4
|
+
* sdk 8.6.0 型面 + 8.7.0 `pathTarget` 三键)。
|
|
5
|
+
*
|
|
6
|
+
* -- 名册回答的是三端一直在猜的那一问 --------------------------------------------------------
|
|
7
|
+
* 「这条腿到底挂了哪些工具、每一只是什么面」此前只能猜:`liveInitToolFace.ts` 那三张词表
|
|
8
|
+
* (`ENGINE_HANDS_BAND` / `ENGINE_SCENARIO_EXTRAS_DEFAULT` / `ENGINE_RUNNER_FACE`)是 2026-07-16
|
|
9
|
+
* 一次 tap 实测的**估计值**,按 pin 的引擎版本定稿;外接别的引擎、别的场景、别的 env 门就会偏。
|
|
10
|
+
* 名册是**引擎自己说的**:每只工具的身份(契约 id / 形状指纹 / 能力 id)、轴(effect / egress /
|
|
11
|
+
* irreversibility)、面(family / pathTarget / renderHints)。
|
|
12
|
+
* 🔴 **名册在场用名册,缺席才回落三表**。本批**不删**那三张表(名册只在 effective 半场、且只有
|
|
13
|
+
* >=7.9.0 的引擎才真推,回落还得留着);`liveInitToolFace.ts` 的头注登记了退役条款:
|
|
14
|
+
* **名册恒在场的版本到货即删表**。
|
|
15
|
+
*
|
|
16
|
+
* -- 🔴 绝不半张名册(照抄上游的纪律)--------------------------------------------------------
|
|
17
|
+
* 引擎的 fail-open 台账逐字写着:载荷过不了 core 自己的判形器 => 那一段缺席 / 那一帧不发,
|
|
18
|
+
* **绝不半张脸上 wire**;并写明反方向更坏 ——「把一份判不了形的名册照发,消费端会把读不出的行
|
|
19
|
+
* 当成**这只工具没挂**」。本窄读器照抄这条:**任一行读不出 => 整只 `undefined`**;`count` 与真实
|
|
20
|
+
* 行数对不上同理(core 在铸点 run-time 断言两者相等)。少几行的名册比没有名册坏。
|
|
21
|
+
* ⚠️ 例外只有**面**:一行的 `pathTarget` / `renderHints` 自己形坏时只丢那一格,行还在 —— 面不是
|
|
22
|
+
* 身份,丢一张面不等于「这只工具没挂」。
|
|
23
|
+
*
|
|
24
|
+
* -- 🔴 `fromDigest` 对不上**不是拒绝** ------------------------------------------------------
|
|
25
|
+
* 契约里唯一的硬话:`fromDigest` 对不上时,**携带的整只名册无论如何都是新状态**,只有 `summary`
|
|
26
|
+
* 变得不可用(消费端记一次 skew 后按快照重同步)。所以 {@link applyToolRosterDelta} 在 skew 时
|
|
27
|
+
* **照换名册、只丢 summary**。拒绝换会让消费端永远抱着一份过期名册 —— 那比一次 skew 坏得多,
|
|
28
|
+
* 而且它把「位置从名册来、永远不从 summary 来」这条契约反过来用了。
|
|
29
|
+
*
|
|
30
|
+
* -- 开集读 -----------------------------------------------------------------------------------
|
|
31
|
+
* `source`(七词)/ `effect` / `family` / `access` 等词表的属主都是引擎,一律**原样透传**,不窄读成
|
|
32
|
+
* 枚举 —— 那会在引擎加词当天把一份真名册判没。
|
|
33
|
+
*/
|
|
34
|
+
/** 一只工具的**路径目标**(引擎的 `pathTarget`;`base`/`absent`/`patternParam` 是 core 7.9.1 #635 加的)。 */
|
|
35
|
+
export interface ToolRosterPathTargetView {
|
|
36
|
+
/** 输入里哪个键是路径。 */
|
|
37
|
+
param: string;
|
|
38
|
+
/** `read` / `create` / `edit`;**开集读**。 */
|
|
39
|
+
access: string;
|
|
40
|
+
/** 同义键。 */
|
|
41
|
+
aliases?: readonly string[];
|
|
42
|
+
skillScopeEligible?: true;
|
|
43
|
+
/** 相对路径按哪个基解析(`cwd` 活目录 / `root` 任务根);**声明时才在场**,缺席就是缺席。 */
|
|
44
|
+
base?: string;
|
|
45
|
+
/** 参数缺席时目标是什么(`none` 无 / `base` 基目录)。同上,缺席不铸默认。 */
|
|
46
|
+
absent?: string;
|
|
47
|
+
/** 承载 glob **模式**的输入键(如 `Glob.pattern`)。 */
|
|
48
|
+
patternParam?: string;
|
|
49
|
+
}
|
|
50
|
+
/** 一只工具的**渲染提示**(引擎自己给的人话名 / 进行时文案 / 摘要参数 / 结果卡 / 审批卡型)。
|
|
51
|
+
* 🔴 端渲这只工具时用它,**别按工具名猜** —— 按名字猜正是 `liveInitToolFace` 三张估计词表的病根。 */
|
|
52
|
+
export interface ToolRosterRenderHintsView {
|
|
53
|
+
userFacingName?: string;
|
|
54
|
+
activity?: string;
|
|
55
|
+
summaryParams?: readonly string[];
|
|
56
|
+
resultCards?: readonly string[];
|
|
57
|
+
approvalCard?: string;
|
|
58
|
+
}
|
|
59
|
+
/** 名册里的一行。身份两键必填,其余全可选(缺席即缺席,绝不铸默认)。 */
|
|
60
|
+
export interface ToolRosterEntryView {
|
|
61
|
+
name: string;
|
|
62
|
+
aliases?: readonly string[];
|
|
63
|
+
/** `builtin` / `caller` / `host` / `mcp` / `a2a` / `external` / `synthetic`;**开集读**。 */
|
|
64
|
+
source: string;
|
|
65
|
+
/** mcp / a2a / external 行才有的出身(`peer` = 声明名)。 */
|
|
66
|
+
origin?: {
|
|
67
|
+
peer: string;
|
|
68
|
+
declaredBy?: string;
|
|
69
|
+
};
|
|
70
|
+
contract?: {
|
|
71
|
+
contractId: string;
|
|
72
|
+
implementationRevision?: string;
|
|
73
|
+
};
|
|
74
|
+
shapeDigest?: string;
|
|
75
|
+
wireSchemaDigest?: string;
|
|
76
|
+
/** 卡的身份。**同名不同身的两行按两只 id 去重,不按 `name`**。 */
|
|
77
|
+
cardId?: string;
|
|
78
|
+
capabilityId?: string;
|
|
79
|
+
/** `read` / `write` / `idempotent`;开集读。 */
|
|
80
|
+
effect?: string;
|
|
81
|
+
egress?: boolean;
|
|
82
|
+
/** `never` / `maybe` / `always`;开集读。 */
|
|
83
|
+
irreversibility?: string;
|
|
84
|
+
contentOrigin?: string;
|
|
85
|
+
family?: string;
|
|
86
|
+
pathTarget?: ToolRosterPathTargetView;
|
|
87
|
+
renderHints?: ToolRosterRenderHintsView;
|
|
88
|
+
ruleFace?: {
|
|
89
|
+
primaryParams?: readonly string[];
|
|
90
|
+
params?: readonly string[];
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** 一条腿的整只名册。 */
|
|
94
|
+
export interface ToolRosterView {
|
|
95
|
+
schemaVersion: number;
|
|
96
|
+
/** 引擎自报的行数;本读器已核过它等于 `entries.length`(对不上 => 整只判没)。 */
|
|
97
|
+
count: number;
|
|
98
|
+
/** 整只名册的指纹,**恰 16 位小写 hex**;任一轴/面/契约/别名变化都会移动它。重同步的锚。 */
|
|
99
|
+
digest: string;
|
|
100
|
+
/** **声明序 = 模型看到的 `tools[]` 序**(不排序、不去重、不重排)。 */
|
|
101
|
+
entries: readonly ToolRosterEntryView[];
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* `wiring_manifest` 的 `tools` 段 → 名册视图;整段缺席 / 任一行读不出 / `count` 对不上 =>
|
|
105
|
+
* `undefined`,绝不抛出。
|
|
106
|
+
*
|
|
107
|
+
* ⚠️ **空名册是正面事实**(这条腿一只工具都没挂),照读成 0 行 —— 与 `wiring_manifest.mcp[]` 的
|
|
108
|
+
* 空数组同一条已定谳的纪律,把它折成缺席等于把引擎明说的一句话读成「不知道」。
|
|
109
|
+
* ⚠️ 只在 **effective 半场**(live 帧)才有;诊断端点返回的 `static` 半场恒无 —— 那里的缺席是
|
|
110
|
+
* 结构性的,不是「这台引擎太老」。
|
|
111
|
+
*/
|
|
112
|
+
export declare function projectToolRoster(manifest: unknown): ToolRosterView | undefined;
|
|
113
|
+
/** 名册里的工具名,**按声明序**(= 模型看到的 `tools[]` 序)。 */
|
|
114
|
+
export declare function toolRosterNames(roster: ToolRosterView | undefined): readonly string[];
|
|
115
|
+
/**
|
|
116
|
+
* 端渲一只工具时要用的那张**面**(`liveInitToolFace.ts` 三张估计词表的继任形)。
|
|
117
|
+
*
|
|
118
|
+
* 🔴 **面只从名册的行取,绝不从工具名猜**:一个叫 `Bash` 的行不一定是 shell 家族(caller 挂的
|
|
119
|
+
* 同名工具、mcp 命名空间下的同名工具都可能),而「按名字猜出来的面」正是三张估计词表的病根。
|
|
120
|
+
* 🔴 **缺席就是缺席**:轴(`egress` / `irreversibility` / `effect`)读不出时留空,**绝不**填
|
|
121
|
+
* `false` / `'never'` —— 那会把「不知道」渲成「安全」,是这条面上最贵的一种谎。
|
|
122
|
+
*/
|
|
123
|
+
export interface ToolShim {
|
|
124
|
+
name: string;
|
|
125
|
+
source: string;
|
|
126
|
+
family?: string;
|
|
127
|
+
userFacingName?: string;
|
|
128
|
+
activity?: string;
|
|
129
|
+
approvalCard?: string;
|
|
130
|
+
summaryParams?: readonly string[];
|
|
131
|
+
effect?: string;
|
|
132
|
+
egress?: boolean;
|
|
133
|
+
irreversibility?: string;
|
|
134
|
+
/** 输入里哪个键是路径(端渲写卡/围栏提示要用)。 */
|
|
135
|
+
pathTargetParam?: string;
|
|
136
|
+
/** mcp / a2a / external 行的声明名。 */
|
|
137
|
+
peer?: string;
|
|
138
|
+
/** 身份两只 id:**同名不同身的两行按它们去重,不按 `name`**。 */
|
|
139
|
+
cardId?: string;
|
|
140
|
+
capabilityId?: string;
|
|
141
|
+
}
|
|
142
|
+
/** 名册的一行 → 端用的面。行不成形(身份两键读不出)=> `undefined`,绝不抛出。 */
|
|
143
|
+
export declare function toolShimFromRoster(entry: unknown): ToolShim | undefined;
|
|
144
|
+
/** 一次 `tool_roster_delta` 应用之后的状态。 */
|
|
145
|
+
export interface ToolRosterDeltaApplication {
|
|
146
|
+
/** 应用后消费端该持有的名册。帧判不出形 => 原样是入参那一份(什么都没发生)。 */
|
|
147
|
+
roster: ToolRosterView | undefined;
|
|
148
|
+
/** 这一帧被采纳了吗(帧判不出形 => `false`)。 */
|
|
149
|
+
applied: boolean;
|
|
150
|
+
/**
|
|
151
|
+
* `fromDigest` 与手上那份对不上(或手上压根没有名册)。
|
|
152
|
+
* 🔴 **这不是拒绝** —— 名册照换,只有 {@link summary} 变得不可用。消费端据此记一次偏斜。
|
|
153
|
+
*/
|
|
154
|
+
skew: boolean;
|
|
155
|
+
/**
|
|
156
|
+
* 三张**互不相交**的名单。`skew` 为真、或这一段自己形坏时**缺席** —— 交一份对不上的名单比
|
|
157
|
+
* 不交更坏(位置永远从名册来,从来不从 summary 来)。
|
|
158
|
+
* ⚠️ 三张全空是**正面事实**(一次字节相同的 re-mint 也会发帧),不是「读不出」。
|
|
159
|
+
*/
|
|
160
|
+
summary?: ToolRosterDeltaSummary;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* 一次名册变更的**名字摘要**:三张**互不相交**的名单。
|
|
164
|
+
* ⚠️ 位置永远从名册来,从来不从这里来 —— 这三张名单只回答「变了哪些名字」。
|
|
165
|
+
* ⚠️ 三张全空是**正面事实**(一次字节相同的 re-mint 也会发帧),不是「读不出」。
|
|
166
|
+
*/
|
|
167
|
+
export interface ToolRosterDeltaSummary {
|
|
168
|
+
added: readonly string[];
|
|
169
|
+
removed: readonly string[];
|
|
170
|
+
changed: readonly string[];
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* `tool_roster_delta` → 新的持有状态。**纯函数**(不改入参)。
|
|
174
|
+
*
|
|
175
|
+
* 🔴 `fromDigest` 对不上**不是拒绝**(契约里唯一的硬话):携带的整只名册无论如何都是新状态,
|
|
176
|
+
* 只有 `summary` 变得不可用。拒绝换会让消费端永远抱着一份过期名册 —— 比一次 skew 坏得多。
|
|
177
|
+
* 🔴 手上**没有**名册(首帧就是 delta)同样算 `skew`:没有可比的 digest 就是比不出来,而
|
|
178
|
+
* 「比不出来」不许被读成「对上了」。
|
|
179
|
+
* 🔴 帧本身判不出形 => **什么都没发生**:原样交回入参那一份(不清空 —— 清空会把一次读不懂的帧
|
|
180
|
+
* 变成一次「所有工具都没挂」)。
|
|
181
|
+
*/
|
|
182
|
+
export declare function applyToolRosterDelta(held: ToolRosterView | undefined, delta: unknown): ToolRosterDeltaApplication;
|