@sema-agent/client-core 0.60.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +180 -0
- package/README.md +10 -3
- package/dist/adapt/arms.js +76 -13
- package/dist/adapt/textStream.d.ts +31 -2
- package/dist/adapt/textStream.js +12 -1
- package/dist/adapter/runStream.js +15 -0
- package/dist/agentsWireCaps.d.ts +6 -2
- package/dist/engineWireSdk.d.ts +23 -2
- package/dist/engineWireSdk.js +71 -4
- package/dist/fleetTaskDesc.d.ts +19 -0
- package/dist/fleetTaskDesc.js +34 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/interactiveHalt.d.ts +40 -17
- package/dist/interactiveHalt.js +32 -20
- package/dist/readFacePosture.d.ts +53 -0
- package/dist/readFacePosture.js +93 -0
- package/dist/seam.d.ts +24 -1
- package/dist/seam.js +7 -0
- package/dist/seatContract.d.ts +84 -1
- package/dist/seatContract.js +37 -0
- package/dist/sqlEngineCapability.d.ts +2 -2
- package/dist/sqlEngineCapability.js +13 -14
- package/dist/subagentContentStore.d.ts +68 -1
- package/dist/subagentContentStore.js +390 -15
- package/dist/writeProtectionCapability.d.ts +4 -0
- package/dist/writeProtectionCapability.js +7 -3
- package/docs/INTEGRATION-CLIENTS.md +440 -10
- package/package.json +3 -3
package/dist/seatContract.d.ts
CHANGED
|
@@ -512,6 +512,34 @@ export interface SendMessageRequest {
|
|
|
512
512
|
* shell's lane defaults it ON (2026-07-26 flip), so a seat that cannot send it is not "defaulting
|
|
513
513
|
* to the same thing" — it is letting the ENGINE's default decide, which is a different decision. */
|
|
514
514
|
retainBackgroundProcesses?: boolean;
|
|
515
|
+
/**
|
|
516
|
+
* 这一轮把**子代的正文帧**转发到父流上 → `TaskRequest.forwardSubagentEvents`。缺席 = 不开
|
|
517
|
+
* (父流只有进度帧,没有子代的 text/reasoning/tool 帧)。
|
|
518
|
+
*
|
|
519
|
+
* 🔴 **能力位说的是「这个键被接受」,不是「它已经开着」**:引擎的 `capabilities.forwardSubagentEvents`
|
|
520
|
+
* 是一个恒真的**受理位**,把它读成「转发已生效」的消费方会接出一个**永远空着**的子代转录面,
|
|
521
|
+
* 而能力面一直在回答「是」。⇒ 想要子代正文,**每一轮都得自己带这个键**。
|
|
522
|
+
* 🔴 结构性缺席故事与 `reasoningEffort` 同款:闭集载体就是这条 lane 本身,不在集里 = 「这一轮要不要
|
|
523
|
+
* 看子代正文」这个决定在座位 lane 上**没有位置可放**。座位端此前只能整条放弃子代转录面
|
|
524
|
+
* (或绕开闭集从逃生口塞一个没登记的键上 wire —— 那是本包整张契约存在的理由所要消灭的形)。
|
|
525
|
+
*/
|
|
526
|
+
forwardSubagentEvents?: boolean;
|
|
527
|
+
/**
|
|
528
|
+
* 这一轮**保留已结束的子代会话**以便日后续跑 → `TaskRequest.retainSubagentSessions`。
|
|
529
|
+
* `true` = 按引擎默认保留;对象形调保留**窗口**(`ttlMs`)与**条数**(`max`)。缺席 = 不保留。
|
|
530
|
+
*
|
|
531
|
+
* 🔴 **过大的请求会被引擎悄悄收紧、而不是拒绝**(server 侧 clamp:窗口上限 24 小时、条数上限 64)。
|
|
532
|
+
* ⇒ 渲染端**不许**把自己请求的值当成生效值回显 —— 那是替引擎说了一句它没说的话;要显示生效值
|
|
533
|
+
* 就去读引擎那一面,读不到就诚实留白。
|
|
534
|
+
* 🔴 它是「子代续跑」那条路的**另一半**:续跑能力位可以是真、路由可以在,调用照样会被拒 ——
|
|
535
|
+
* 因为保留是**逐 run**的、且默认关。只看能力位就渲一个「继续这个子代」的入口 = 假 affordance。
|
|
536
|
+
* 🔴 结构性缺席故事同上:此前座位 lane 没有这一位,于是「这条会话要不要留子代」只能由部署默认决定,
|
|
537
|
+
* 而那与「端替用户做了这个决定」不是一回事。
|
|
538
|
+
*/
|
|
539
|
+
retainSubagentSessions?: boolean | {
|
|
540
|
+
ttlMs?: number;
|
|
541
|
+
max?: number;
|
|
542
|
+
};
|
|
515
543
|
/** Per-turn settings sub-object → `TaskRequest.settings`. Closed shape (`SeatTurnSettings`);
|
|
516
544
|
* today's only member is the `ultracode` preset boolean. */
|
|
517
545
|
settings?: SeatTurnSettings;
|
|
@@ -739,7 +767,62 @@ export declare const SEAT_EVENT_METHOD_NAMES: readonly ["onEvent", "onToolPermis
|
|
|
739
767
|
export declare const LOCAL_SESSION_EVENT_KEYS: readonly ["type", "sessionId", "message", "messages", "error", "errorCategory", "code", "request", "data", "sources", "permissionMode", "session", "userMessageUuid", "hasPreClearSession", "requestId", "outcome", "chrome"];
|
|
740
768
|
export declare const TOOL_PERMISSION_REQUEST_KEYS: readonly ["requestId", "sessionId", "toolName", "toolCallId", "input", "message", "toctouBinding", "createdAtMs", "governanceForced", "delegation"];
|
|
741
769
|
export declare const LOCAL_SESSION_RECORD_KEYS: readonly ["sessionId", "engineSessionId", "model", "title", "isRunning", "createdAt", "lastActivityAt", "queuedMessages", "parked"];
|
|
742
|
-
export declare const SEND_MESSAGE_REQUEST_KEYS: readonly ["sessionId", "text", "model", "userMessageUuid", "permissionMode", "attachmentIds", "reasoningEffort", "retainBackgroundProcesses", "settings", "scenario"];
|
|
770
|
+
export declare const SEND_MESSAGE_REQUEST_KEYS: readonly ["sessionId", "text", "model", "userMessageUuid", "permissionMode", "attachmentIds", "reasoningEffort", "retainBackgroundProcesses", "forwardSubagentEvents", "retainSubagentSessions", "settings", "scenario"];
|
|
771
|
+
/**
|
|
772
|
+
* **座位键 → 引擎请求位**的出身表(0.62.0;`SEND_MESSAGE_REQUEST_KEYS` 的逐键出身登记)。
|
|
773
|
+
*
|
|
774
|
+
* 为什么要有它:座位 lane 的载荷是一个**闭集接口**,而它的绝大多数位最终是要**原样落到引擎请求
|
|
775
|
+
* 体上**的。这两件事此前没有任何东西把它们接起来 —— 一个座位位可以叫一个引擎请求体上**根本不存在**
|
|
776
|
+
* 的名字(端照着它写、上了 wire 被引擎整键忽略,面上是「开关点了没反应」这类静默缺席),而引擎请求
|
|
777
|
+
* 体新长出一个位时,也没有任何信号说「座位 lane 还没有它的席位」。本表把每个座位键的出身写成**数据**:
|
|
778
|
+
* · `taskRequestKey` —— 这个位**原样转投**引擎请求体的同名/异名位。常驻门拿它对**装在盘上的**
|
|
779
|
+
* sdk 型面逐名核(型直读,不手抄):名字不在引擎请求体上 ⇒ 当天红。
|
|
780
|
+
* · `seatOnly` —— 这个位**不上 wire**,只活在座位 lane 上;字符串写清它是什么、为什么不转投。
|
|
781
|
+
*
|
|
782
|
+
* 🔴 `sessionId` 是**同名不同义**的典型:座位这一位是**座位会话句柄**(渲染端持有的本地 id),而引擎
|
|
783
|
+
* 请求体上那个同名位是**引擎会话 id**(座位记录里另有 `engineSessionId` 承载)。两者恰好同名,
|
|
784
|
+
* 把它登记成「转投」会让下一个人以为直接透传就行 —— 那是把本地句柄当引擎会话送上 wire。
|
|
785
|
+
* 🔴 `text` 是**异名转投**:座位说 `text`,引擎请求体那一位叫 `objective`。异名不是问题,**没记账**
|
|
786
|
+
* 才是;本表就是那本账。
|
|
787
|
+
*/
|
|
788
|
+
export declare const SEAT_SEND_MESSAGE_KEY_ORIGINS: {
|
|
789
|
+
readonly sessionId: {
|
|
790
|
+
readonly seatOnly: "座位会话句柄(渲染端持有的本地 id);引擎会话 id 由座位记录的 `engineSessionId` 承载 —— 与引擎请求体上的同名位**同名不同义**,绝不直传";
|
|
791
|
+
};
|
|
792
|
+
readonly text: {
|
|
793
|
+
readonly taskRequestKey: "objective";
|
|
794
|
+
};
|
|
795
|
+
readonly model: {
|
|
796
|
+
readonly taskRequestKey: "model";
|
|
797
|
+
};
|
|
798
|
+
readonly userMessageUuid: {
|
|
799
|
+
readonly seatOnly: "用户消息的回声键(对标产品形态:客户端自铸、原样回显到转录上),不是引擎请求体上的位";
|
|
800
|
+
};
|
|
801
|
+
readonly permissionMode: {
|
|
802
|
+
readonly taskRequestKey: "permissionMode";
|
|
803
|
+
};
|
|
804
|
+
readonly attachmentIds: {
|
|
805
|
+
readonly taskRequestKey: "attachmentIds";
|
|
806
|
+
};
|
|
807
|
+
readonly reasoningEffort: {
|
|
808
|
+
readonly taskRequestKey: "reasoningEffort";
|
|
809
|
+
};
|
|
810
|
+
readonly retainBackgroundProcesses: {
|
|
811
|
+
readonly taskRequestKey: "retainBackgroundProcesses";
|
|
812
|
+
};
|
|
813
|
+
readonly forwardSubagentEvents: {
|
|
814
|
+
readonly taskRequestKey: "forwardSubagentEvents";
|
|
815
|
+
};
|
|
816
|
+
readonly retainSubagentSessions: {
|
|
817
|
+
readonly taskRequestKey: "retainSubagentSessions";
|
|
818
|
+
};
|
|
819
|
+
readonly settings: {
|
|
820
|
+
readonly taskRequestKey: "settings";
|
|
821
|
+
};
|
|
822
|
+
readonly scenario: {
|
|
823
|
+
readonly taskRequestKey: "scenario";
|
|
824
|
+
};
|
|
825
|
+
};
|
|
743
826
|
export declare const TOOL_PERMISSION_DECISION_KEYS: readonly ["sessionId", "requestId", "decision", "answer", "updatedInput", "remember"];
|
|
744
827
|
export declare const START_SESSION_OPTION_KEYS: readonly ["model", "title", "cwd", "excludeTools"];
|
|
745
828
|
/**
|
package/dist/seatContract.js
CHANGED
|
@@ -753,10 +753,45 @@ export const SEND_MESSAGE_REQUEST_KEYS = [
|
|
|
753
753
|
// 载体本身,不在集里 = 那个决定在这条 lane 上根本没有位置可放。
|
|
754
754
|
"reasoningEffort",
|
|
755
755
|
"retainBackgroundProcesses",
|
|
756
|
+
// 0.62.0(子代面两位补载体):同上结构性缺席形 —— 「这一轮要不要看子代正文 / 要不要留子代会话」
|
|
757
|
+
// 此前在座位 lane 上没有位置可放。两位都**原样转投**同名引擎请求位(出身表 + 常驻门对账)。
|
|
758
|
+
"forwardSubagentEvents",
|
|
759
|
+
"retainSubagentSessions",
|
|
756
760
|
"settings",
|
|
757
761
|
// [C131] 补载体(2026-08-08):scenario 拨盘的座位 lane 席位(同上结构性缺席形)。
|
|
758
762
|
"scenario",
|
|
759
763
|
];
|
|
764
|
+
/**
|
|
765
|
+
* **座位键 → 引擎请求位**的出身表(0.62.0;`SEND_MESSAGE_REQUEST_KEYS` 的逐键出身登记)。
|
|
766
|
+
*
|
|
767
|
+
* 为什么要有它:座位 lane 的载荷是一个**闭集接口**,而它的绝大多数位最终是要**原样落到引擎请求
|
|
768
|
+
* 体上**的。这两件事此前没有任何东西把它们接起来 —— 一个座位位可以叫一个引擎请求体上**根本不存在**
|
|
769
|
+
* 的名字(端照着它写、上了 wire 被引擎整键忽略,面上是「开关点了没反应」这类静默缺席),而引擎请求
|
|
770
|
+
* 体新长出一个位时,也没有任何信号说「座位 lane 还没有它的席位」。本表把每个座位键的出身写成**数据**:
|
|
771
|
+
* · `taskRequestKey` —— 这个位**原样转投**引擎请求体的同名/异名位。常驻门拿它对**装在盘上的**
|
|
772
|
+
* sdk 型面逐名核(型直读,不手抄):名字不在引擎请求体上 ⇒ 当天红。
|
|
773
|
+
* · `seatOnly` —— 这个位**不上 wire**,只活在座位 lane 上;字符串写清它是什么、为什么不转投。
|
|
774
|
+
*
|
|
775
|
+
* 🔴 `sessionId` 是**同名不同义**的典型:座位这一位是**座位会话句柄**(渲染端持有的本地 id),而引擎
|
|
776
|
+
* 请求体上那个同名位是**引擎会话 id**(座位记录里另有 `engineSessionId` 承载)。两者恰好同名,
|
|
777
|
+
* 把它登记成「转投」会让下一个人以为直接透传就行 —— 那是把本地句柄当引擎会话送上 wire。
|
|
778
|
+
* 🔴 `text` 是**异名转投**:座位说 `text`,引擎请求体那一位叫 `objective`。异名不是问题,**没记账**
|
|
779
|
+
* 才是;本表就是那本账。
|
|
780
|
+
*/
|
|
781
|
+
export const SEAT_SEND_MESSAGE_KEY_ORIGINS = {
|
|
782
|
+
sessionId: { seatOnly: "座位会话句柄(渲染端持有的本地 id);引擎会话 id 由座位记录的 `engineSessionId` 承载 —— 与引擎请求体上的同名位**同名不同义**,绝不直传" },
|
|
783
|
+
text: { taskRequestKey: "objective" },
|
|
784
|
+
model: { taskRequestKey: "model" },
|
|
785
|
+
userMessageUuid: { seatOnly: "用户消息的回声键(对标产品形态:客户端自铸、原样回显到转录上),不是引擎请求体上的位" },
|
|
786
|
+
permissionMode: { taskRequestKey: "permissionMode" },
|
|
787
|
+
attachmentIds: { taskRequestKey: "attachmentIds" },
|
|
788
|
+
reasoningEffort: { taskRequestKey: "reasoningEffort" },
|
|
789
|
+
retainBackgroundProcesses: { taskRequestKey: "retainBackgroundProcesses" },
|
|
790
|
+
forwardSubagentEvents: { taskRequestKey: "forwardSubagentEvents" },
|
|
791
|
+
retainSubagentSessions: { taskRequestKey: "retainSubagentSessions" },
|
|
792
|
+
settings: { taskRequestKey: "settings" },
|
|
793
|
+
scenario: { taskRequestKey: "scenario" },
|
|
794
|
+
};
|
|
760
795
|
export const TOOL_PERMISSION_DECISION_KEYS = [
|
|
761
796
|
"sessionId",
|
|
762
797
|
"requestId",
|
|
@@ -957,6 +992,8 @@ export const SEAT_VALIDATOR_COVERAGE_EXEMPT = [
|
|
|
957
992
|
const _seatContractPins = [
|
|
958
993
|
true, true, true, true, true, true, true, true, true,
|
|
959
994
|
true, true, true, true, true, true, true, true,
|
|
995
|
+
// 0.62.0:出身表 ↔ 载荷键集双向
|
|
996
|
+
true, true,
|
|
960
997
|
true, true,
|
|
961
998
|
true, true, true, true,
|
|
962
999
|
true, true, true, true,
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
*
|
|
39
39
|
* ── 🔴 UNTRUSTED-for-display ──────────────────────────────────────────────────────────────
|
|
40
40
|
* `isolation` 是从**数据库服务器**变量里回读的串(`@@transaction_isolation` 一族),不是引擎铸的
|
|
41
|
-
*
|
|
42
|
-
* ({@link
|
|
41
|
+
* 闭词;三座一律只渲染、绝不参与任何判定,呈现前过本包的单行消毒 + 封长单源
|
|
42
|
+
* ({@link capForDisplay}:先转义、后按转义结果封长)。
|
|
43
43
|
*/
|
|
44
44
|
/**
|
|
45
45
|
* 三座俱全时的读数(server `SqlEngineCapability` 逐字同形)。
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
*
|
|
39
39
|
* ── 🔴 UNTRUSTED-for-display ──────────────────────────────────────────────────────────────
|
|
40
40
|
* `isolation` 是从**数据库服务器**变量里回读的串(`@@transaction_isolation` 一族),不是引擎铸的
|
|
41
|
-
*
|
|
42
|
-
* ({@link
|
|
41
|
+
* 闭词;三座一律只渲染、绝不参与任何判定,呈现前过本包的单行消毒 + 封长单源
|
|
42
|
+
* ({@link capForDisplay}:先转义、后按转义结果封长)。
|
|
43
43
|
*/
|
|
44
|
-
import {
|
|
44
|
+
import { capForDisplay } from './fleetTaskDesc.js';
|
|
45
45
|
import { engineWireTarget } from './engineWireTarget.js';
|
|
46
46
|
import { engineCapsGeneration } from './engineCapsCache.js';
|
|
47
47
|
/**
|
|
@@ -131,21 +131,20 @@ export function observedSqlEngine(baseUrl = engineWireTarget()?.baseUrl) {
|
|
|
131
131
|
/** 单行 UNTRUSTED 座的展示上限(UTF-16 单元;与壳侧那份同值)。 */
|
|
132
132
|
const SQL_DETAIL_MAX = 40;
|
|
133
133
|
/**
|
|
134
|
-
* 单行 UNTRUSTED
|
|
134
|
+
* 单行 UNTRUSTED 座的呈前规整:**先转义、后按转义结果封长**({@link capForDisplay})。
|
|
135
135
|
*
|
|
136
|
-
* 🔴
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* (
|
|
136
|
+
* 🔴 0.62.0 改了顺序,理由记全(此前这里刻意写的是先截后转义):旧注释担心的是「先清后截会把一个
|
|
137
|
+
* 转义序列拦腰截断,屏上留下 `\u20` 这种既不是字符也不是转义的残片」—— 那个顾虑是对的,但它的
|
|
138
|
+
* 解法不是把顺序反过来,而是**截点避让**:共用铸点在截点落进一枚 `\uXXXX` 中间时回退到该 token
|
|
139
|
+
* 之前(合法代理对同理回退一位)。两个毛病只能同时消掉一次:先截后转义留下的是**预算失守**
|
|
140
|
+
* (纯控制字符的 40 字符原文转义后占 240 个显示字符,是承诺列宽的六倍),那是比残片更硬的一条。
|
|
141
141
|
* ⚠️ **与壳那份的已知呈现差分**(换装时随批裁一次):壳 `sqlEngineDoctorDetail` 走的是
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* `pessimistic`)两侧逐字节相同,只有含控制符的病态值渲染形不同。
|
|
142
|
+
* `.` 占位形消毒器(1:1,先截后清与先清后截等价),而壳自己的头注写着「单行字段(路径/URL/
|
|
143
|
+
* 参数键值)**必须**用可见转义形」—— 三座正是单行标量。本包按那条规则实现,所以对**正常读数**
|
|
144
|
+
* (`tidb` / `REPEATABLE-READ` / `pessimistic`)两侧逐字节相同,只有含控制符的病态值渲染形不同。
|
|
146
145
|
*/
|
|
147
146
|
function cleanSqlDetailScalar(v) {
|
|
148
|
-
return
|
|
147
|
+
return capForDisplay(v, SQL_DETAIL_MAX);
|
|
149
148
|
}
|
|
150
149
|
/**
|
|
151
150
|
* 四态 → doctor 那一行的 detail 串。**唯一措辞真源**(三端共用一句话;别在各端的行装配里另写
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
*
|
|
11
11
|
* WIRE FACTS: with `forwardSubagentEvents: true` on the task request, the live stream carries the
|
|
12
12
|
* subagent's text_delta / reasoning_delta / tool_start / tool_end stamped with EventIdentity
|
|
13
|
+
* —— 🔴 **durable 腿(重放)送的是同一段的聚合形** `text` / `reasoning`(整段全文,同样带
|
|
14
|
+
* EventIdentity)。两类都要收:只收增量的话,续听重放尾的宿主整条子代转录都是空的
|
|
15
|
+
* (0.62.0 补;两类的处置**不同**,见 {@link publishSubagentContentEvent} 的吸收规则)
|
|
13
16
|
* (§E1 redact upstream; §E2 identity). 🔴 EventIdentity 的键是 `eventId` / `parentToolCallId`
|
|
14
17
|
* (+ LIVE 白名单四臂上的 `sourceTaskId` / `bgAgentId`)—— **没有 `taskId`**(sdk `events.d.ts` 的
|
|
15
18
|
* `interface EventIdentity` 直证;`taskId` 只长在 `meta` 首帧上)。所以内容帧到不了「自带引擎
|
|
@@ -46,6 +49,19 @@ export type SubagentContentItem = {
|
|
|
46
49
|
| {
|
|
47
50
|
kind: 'echo';
|
|
48
51
|
text: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* **截尾留痕**(0.62.0):字节预算把这条子代早先的内容丢掉了多少。恒**排在 items 最前**、
|
|
55
|
+
* 每条子代**至多一条**(丢一次加一条会把账本自己撑爆),随后续丢弃**原地更新**。
|
|
56
|
+
*
|
|
57
|
+
* 🔴 它存在的唯一理由是「不许无声消失」:没有它,用户读到的转录比真实发生的少一截而毫无提示,
|
|
58
|
+
* 而那正是本包在别处反复记账的那类静默失败。渲染端该把它渲成一行可见的省略说明。
|
|
59
|
+
* 🔴 本记录**自身不计入预算**(它是关于预算的元信息,不是内容)。
|
|
60
|
+
*/
|
|
61
|
+
| {
|
|
62
|
+
kind: 'truncated';
|
|
63
|
+
droppedBytes: number;
|
|
64
|
+
keptFrom: number;
|
|
49
65
|
};
|
|
50
66
|
/**
|
|
51
67
|
* 🔴 [2393] sweep-F15(2026-08-03 全窗复审)**记一笔口径分叉**(裁定:留 `| undefined`,写明为什么):
|
|
@@ -61,10 +77,22 @@ export type SubagentContentItem = {
|
|
|
61
77
|
* (那时两种口径就不能再共存了)。
|
|
62
78
|
*/
|
|
63
79
|
export interface SubagentContentEvent {
|
|
64
|
-
|
|
80
|
+
/**
|
|
81
|
+
* 🔴 六臂,两类语义(0.62.0 加 `text` / `reasoning` 两个**聚合**臂):
|
|
82
|
+
* · `*_delta` = **增量**,语义是「往缓冲里追加」;
|
|
83
|
+
* · `text` / `reasoning` = 一段的**权威全文**(durable 重放腿送的就是这一形),语义是
|
|
84
|
+
* 「这一段最终是这样」—— 处置**不是追加**,见 {@link publishSubagentContentEvent} 的吸收规则。
|
|
85
|
+
* 两类必须分得开:把聚合帧折成一发 `*_delta` 会让「活体流过 + 重放聚合」变成**双份**。
|
|
86
|
+
*/
|
|
87
|
+
type: 'text_delta' | 'reasoning_delta' | 'text' | 'reasoning' | 'tool_start' | 'tool_end';
|
|
65
88
|
taskId: string;
|
|
66
89
|
parentToolCallId: string;
|
|
67
90
|
delta?: string | undefined;
|
|
91
|
+
/** 聚合两臂(`text` / `reasoning`)的**整段全文**。刻意不复用 `delta` 位:同名不同义会让
|
|
92
|
+
* 「这一位是增量还是全文」变成读者要靠 `type` 去反推的事,而反推错的代价是内容重复上屏。 */
|
|
93
|
+
text?: string | undefined;
|
|
94
|
+
/** wire 上那一帧的**事件身份**(聚合两臂的幂等键;缺席 ⇒ 退回内容判据,见 publish 的两道闸)。 */
|
|
95
|
+
eventId?: string | undefined;
|
|
68
96
|
toolCallId?: string | undefined;
|
|
69
97
|
toolName?: string | undefined;
|
|
70
98
|
args?: unknown;
|
|
@@ -104,6 +132,38 @@ export interface SubagentContentEvent {
|
|
|
104
132
|
* 动本函数的块数组分支 ⇒ 同批看那条断言。
|
|
105
133
|
*/
|
|
106
134
|
export declare function coerceOutput(v: unknown): string | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* 本账本的**字节预算**。此前只有条数帽(每条子代 ≤ 200 条 item、≤ 32 条子代),而条数帽对
|
|
137
|
+
* 「一条工具结果里的一整个 base64 附件」「一段几 MB 的模型输出」**零判别力** —— 200 条的上限在
|
|
138
|
+
* **单条无上限**的前提下根本不是一个预算,实测面上一个子代槽位吃到十几 MB 常驻是可复现的。
|
|
139
|
+
*
|
|
140
|
+
* 🔴 单位是 **UTF-8 字节**(不是 JS 串长度):账本里装的是引擎送来的文本,而「多少内存 / 多少屏」
|
|
141
|
+
* 这两件事都跟编码后的体量走;按串长度算会让一段 CJK 的真实占用是名义值的三倍。
|
|
142
|
+
* 🔴 缺省值的来历(如实):对标产品的语料里**没有**对应的「子代转录字节预算」可对齐(查过),
|
|
143
|
+
* 所以这两个数不假称是 parity —— 它们来自 web 端探针实测的「单槽十几 MB」这一观测:总帽取
|
|
144
|
+
* 16 MiB(把整本账本按住在那个量级),每子代帽取总帽的 1/8 = 2 MiB(一条子代吃满也留得下
|
|
145
|
+
* 另外七条的位置)。端可以按自己的宿主改配,这两个数只是「不配时不至于无界」。
|
|
146
|
+
*/
|
|
147
|
+
export interface SubagentContentStoreConfig {
|
|
148
|
+
/** 单条子代**保留**的内容字节上限。超出 ⇒ 从最早的内容开始丢,并留一条 `truncated` 记录。 */
|
|
149
|
+
maxBytesPerTask: number;
|
|
150
|
+
/** 整本账本保留的内容字节上限。超出 ⇒ 整条**最久未用**的子代账本被清掉(不是无差别清空)。 */
|
|
151
|
+
maxBytesTotal: number;
|
|
152
|
+
}
|
|
153
|
+
/** 不配时生效的两位(理由见 {@link SubagentContentStoreConfig} 顶注)。 */
|
|
154
|
+
export declare const SUBAGENT_CONTENT_STORE_DEFAULTS: Readonly<SubagentContentStoreConfig>;
|
|
155
|
+
/**
|
|
156
|
+
* 配字节预算(宿主启动时调一次;两位可分开配,只给一位时另一位保持现值)。
|
|
157
|
+
*
|
|
158
|
+
* 🔴 **fail-loud**:0 / 负数 / 非有限数 / 非整数一律 `throw` —— 一个被**静默忽略**的预算配置正是
|
|
159
|
+
* 这本账本要消灭的那类失败(宿主以为配上了,而账本还在按缺省无声地丢或不丢)。
|
|
160
|
+
* 🔴 拒绝是**原子**的:任何一位不合法就整只拒,既有配置一个字节不动(半套配置比不配更坏)。
|
|
161
|
+
*/
|
|
162
|
+
export declare function configureSubagentContentStore(next: Partial<SubagentContentStoreConfig>): void;
|
|
163
|
+
/** 当前生效的两位(**快照**:改返回值不影响账本)。 */
|
|
164
|
+
export declare function subagentContentStoreConfig(): SubagentContentStoreConfig;
|
|
165
|
+
/** 测试钩:把预算复位到缺省。 */
|
|
166
|
+
export declare function __resetSubagentContentStoreConfigForTests(): void;
|
|
107
167
|
/**
|
|
108
168
|
* **内容归账那一半**(`parentToolCallId → taskId`,多对一):把停在 parent 键下的内容迁到 canonical
|
|
109
169
|
* task 键,并让后续内容帧的 `canonicalKey` 解析到 task。**不写** `taskToParent`。
|
|
@@ -157,6 +217,13 @@ export type SubagentViewSlot = {
|
|
|
157
217
|
kind: 'echo';
|
|
158
218
|
slot: string;
|
|
159
219
|
text: string;
|
|
220
|
+
}
|
|
221
|
+
/** 截尾留痕(0.62.0):渲染端渲一行「更早的 N 字节输出已被预算丢弃」类说明。 */
|
|
222
|
+
| {
|
|
223
|
+
kind: 'truncated';
|
|
224
|
+
slot: string;
|
|
225
|
+
droppedBytes: number;
|
|
226
|
+
keptFrom: number;
|
|
160
227
|
} | {
|
|
161
228
|
kind: 'tool';
|
|
162
229
|
slot: string;
|