@sema-agent/client-core 0.2.0 → 0.4.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/README.md +23 -1
- package/dist/agentsWireCaps.d.ts +112 -0
- package/dist/agentsWireCaps.js +319 -0
- package/dist/attachmentsWireCaps.d.ts +47 -0
- package/dist/attachmentsWireCaps.js +46 -0
- package/dist/classifierVerdictWire.d.ts +45 -0
- package/dist/classifierVerdictWire.js +76 -0
- package/dist/clientContextWireCaps.d.ts +46 -0
- package/dist/clientContextWireCaps.js +48 -0
- package/dist/cloudConfigWireCaps.d.ts +110 -0
- package/dist/cloudConfigWireCaps.js +228 -0
- package/dist/controlRouter.d.ts +191 -0
- package/dist/controlRouter.js +244 -0
- package/dist/effortWire.d.ts +34 -0
- package/dist/effortWire.js +38 -0
- package/dist/engineAgentPanelStore.d.ts +111 -0
- package/dist/engineAgentPanelStore.js +93 -0
- package/dist/engineCapsCache.d.ts +32 -0
- package/dist/engineCapsCache.js +64 -0
- package/dist/engineInlineTaskStats.d.ts +66 -0
- package/dist/engineInlineTaskStats.js +97 -0
- package/dist/engineToolLabelStore.d.ts +32 -0
- package/dist/engineToolLabelStore.js +55 -0
- package/dist/engineWireSdk.d.ts +49 -0
- package/dist/engineWireSdk.js +61 -0
- package/dist/fleetAgentPanelProjection.d.ts +31 -0
- package/dist/fleetAgentPanelProjection.js +0 -0
- package/dist/fleetTaskDesc.d.ts +20 -0
- package/dist/fleetTaskDesc.js +35 -0
- package/dist/forkWireCaps.d.ts +25 -0
- package/dist/forkWireCaps.js +42 -0
- package/dist/hostEnv.d.ts +16 -0
- package/dist/hostEnv.js +17 -0
- package/dist/imagesWireCaps.d.ts +28 -0
- package/dist/imagesWireCaps.js +49 -0
- package/dist/index.d.ts +56 -1
- package/dist/index.js +62 -1
- package/dist/liveModelCatalog.d.ts +62 -0
- package/dist/liveModelCatalog.js +79 -0
- package/dist/liveQuestionStore.d.ts +101 -0
- package/dist/liveQuestionStore.js +109 -0
- package/dist/mcpWireCaps.d.ts +41 -0
- package/dist/mcpWireCaps.js +51 -0
- package/dist/modelBudgetRule.d.ts +44 -0
- package/dist/modelBudgetRule.js +73 -0
- package/dist/modelWireCaps.d.ts +17 -0
- package/dist/modelWireCaps.js +16 -0
- package/dist/notifications.d.ts +150 -4
- package/dist/notifications.js +472 -0
- package/dist/permissionWireCaps.d.ts +37 -0
- package/dist/permissionWireCaps.js +46 -0
- package/dist/printToolResultFrame.d.ts +59 -0
- package/dist/printToolResultFrame.js +65 -0
- package/dist/promptProfileWireCaps.d.ts +17 -0
- package/dist/promptProfileWireCaps.js +20 -0
- package/dist/retainBackgroundWireCaps.d.ts +50 -0
- package/dist/retainBackgroundWireCaps.js +58 -0
- package/dist/rewindWireCaps.d.ts +36 -0
- package/dist/rewindWireCaps.js +41 -0
- package/dist/selfOrchestrationWireCaps.d.ts +40 -0
- package/dist/selfOrchestrationWireCaps.js +48 -0
- package/dist/sessionModelLatch.d.ts +35 -0
- package/dist/sessionModelLatch.js +63 -0
- package/dist/skillsWireCaps.d.ts +47 -0
- package/dist/skillsWireCaps.js +41 -0
- package/dist/sseIdleTriage.d.ts +94 -0
- package/dist/sseIdleTriage.js +142 -0
- package/dist/steering.d.ts +4 -0
- package/dist/steering.js +4 -0
- package/dist/subagentContentStore.d.ts +131 -0
- package/dist/subagentContentStore.js +322 -0
- package/dist/types/engineState.d.ts +116 -0
- package/dist/types/engineState.js +17 -0
- package/dist/ultracodeWireCaps.d.ts +90 -0
- package/dist/ultracodeWireCaps.js +159 -0
- package/dist/webSearchWireCaps.d.ts +54 -0
- package/dist/webSearchWireCaps.js +76 -0
- package/dist/workflow.d.ts +40 -8
- package/dist/workflow.js +69 -11
- package/package.json +1 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/sseIdleTriage.ts 逐字搬入(只 import SDK)。
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* src/sema/sseIdleTriage.ts — turn-stream SSE idle-silence triage(TB2.0 反馈批 D · P0-2 壳半场,2026-07-15)。
|
|
6
|
+
*
|
|
7
|
+
* WHY: TB2.0 bench 真实案例 —— agent 长跑前台编译 ~9.5min,工具完成前壳侧 45s 空闲监测器
|
|
8
|
+
* (`@sema-agent/sdk` readSseFrames HEARTBEAT_GRACE_MS)命中 `SSE: no data for 45000ms (heartbeat
|
|
9
|
+
* silence)` → 整轮 rc=1 丢弃,引擎不知情继续跑完(access log 499)。分诊报告判决①修正段拍定:
|
|
10
|
+
* 壳侧独立可发 = S1(SDK grace 透传+typed SseIdleError,0.0.47 已发)+ S4(grace 旋钮)+
|
|
11
|
+
* S3 缩水版(engine-alive-idle 分诊,只改报错文案,不重连)。本模块 = S4 + S3 的共享件。
|
|
12
|
+
*
|
|
13
|
+
* S4 · SEMA_SSE_HEARTBEAT_GRACE_MS(settings.json `env` 块 → 1a-envseed → process.env,其它 wire
|
|
14
|
+
* 旋钮同一车道):整数毫秒,合法域 [5000, 600000];非法/缺省 = 不透传(SDK 默认 45s)——静默
|
|
15
|
+
* fail-soft,一个 settings typo 绝不 brick 任何 run(scenarioWire settings-lane 纪律)。
|
|
16
|
+
* ⚠️ 作用面 = 会话 turn 流(tasks.stream / liveClient)一条车道。SDK 控制通道(SSETransport.ts:21
|
|
17
|
+
* LIVENESS_TIMEOUT_MS=45s)自带重连+give-up 自愈,本旋钮【不】达那条车道——这不是全局 grace。
|
|
18
|
+
*
|
|
19
|
+
* S3 缩水版 · engine-alive-idle 分诊:liveClient 的 tasks.stream 包装 catch 到 SseIdleError 时,
|
|
20
|
+
* 先判 signal.aborted(用户中止契约先行,seamQuery.ts:1073——Esc 撕流绝不被分诊吞),再 GET
|
|
21
|
+
* `/health`(非 /healthz;server dist server.js:290)短超时探引擎活性:引擎死 → 原样抛(现行
|
|
22
|
+
* engine-down/not-restart 路径不变);引擎活 → 给同一错误对象打 engine-alive-idle 标记,
|
|
23
|
+
* seamQuery 的 tearVerdict 恢复腿据此渲染诚实分诊文案(engineAliveIdleContent)。
|
|
24
|
+
*
|
|
25
|
+
* 【本模块绝不重连】(判决①修正段圣旨,范围随 M2 精化):非 detach 车道上 tasks/stream 客户端
|
|
26
|
+
* 断连 = server onDisconnect ac.abort() 终止 run(anti token-burn by design),且该车道帧无 id
|
|
27
|
+
* 不可位置续传——空闲监测器抛出的那一刻 finally 已 cancel res.body,run 已被这次断连自身中止,
|
|
28
|
+
* 同 key in-flight 重放拿到的只是 aborted 结局。前台另有既有裁决:mid-turn 工具副作用非幂等,
|
|
29
|
+
* 绝不自动重发。引擎 E2(server ≥1.196 x-detach-on-disconnect,[854]①)已到货:headless `-p`
|
|
30
|
+
* detach 车道的 R1 换道重连 = 重连腿 M2,住在 headlessReconnectWire.ts(liveClient 管线最内层,
|
|
31
|
+
* 只在 detach 头已发出的流上武装);本模块保持「探活+打标,不重连」——交互 REPL 与一切非
|
|
32
|
+
* detach 车道的取消契约一根毛不动,M2 耗尽预算后判死文案也仍由这里的打标驱动。
|
|
33
|
+
*/
|
|
34
|
+
import { type EnvLike } from './hostEnv.js';
|
|
35
|
+
/** Settings-lane env knob(settings.json `env` 块 → 1a-envseed → process.env)。整数毫秒。 */
|
|
36
|
+
export declare const SSE_HEARTBEAT_GRACE_ENV = "SEMA_SSE_HEARTBEAT_GRACE_MS";
|
|
37
|
+
/** 合法域下界:低于 5s 会把正常 token 间隙误判成静默。 */
|
|
38
|
+
export declare const SSE_GRACE_MIN_MS = 5000;
|
|
39
|
+
/** 合法域上界:10min——超过引擎自身各级 idle 顶,再长没有意义。 */
|
|
40
|
+
export declare const SSE_GRACE_MAX_MS = 600000;
|
|
41
|
+
/** SDK 默认(readSseFrames HEARTBEAT_GRACE_MS)——文案引用用,不在本模块生效。 */
|
|
42
|
+
export declare const SDK_DEFAULT_GRACE_MS = 45000;
|
|
43
|
+
/**
|
|
44
|
+
* S4 — resolve the turn-stream heartbeat grace override. Unset/empty → undefined(SDK 默认 45s,
|
|
45
|
+
* 不透传);非纯十进制整数 / 超出 [5000,600000] → undefined(静默落默认,fail-soft)。
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveSseHeartbeatGraceMs(env?: EnvLike): number | undefined;
|
|
48
|
+
/** 给 SseIdleError 打 engine-alive-idle 标(引擎 /health 已确认活着)。返回同一对象。 */
|
|
49
|
+
export declare function markEngineAliveIdle<E extends Error>(err: E): E;
|
|
50
|
+
/**
|
|
51
|
+
* engine-alive-idle 判型:命中返回静默时长 elapsedMs(SseIdleError 0.0.47 自带;缺失兜 0),
|
|
52
|
+
* 未命中返回 undefined。seamQuery tearVerdict 腿与 headless `-p` 的 stderr 面共用。
|
|
53
|
+
*/
|
|
54
|
+
export declare function engineAliveIdleElapsedMs(err: unknown): number | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* SseIdleError 判型:instanceof 为主;双包风险(bundle 内外两份 SDK class identity 分叉)下
|
|
57
|
+
* name 兜底——name 由 SDK 构造器冻结为 'SseIdleError',非我方铸造。
|
|
58
|
+
*/
|
|
59
|
+
export declare function isSseIdleError(err: unknown): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* 引擎活性探针 — SDK probeHealth(GET `${baseUrl}/health`;端点是 /health 非 /healthz),默认 2s
|
|
62
|
+
* 预算,永不抛:alive = 200 且 status==='ok';非 2xx / 不可达 / 超时 = not alive(引擎死 → 现行
|
|
63
|
+
* 失败路径,分诊绝不让真死引擎空等)。与 engineUpgradeCoordinator 的 classifyStreamTear 同款姿势。
|
|
64
|
+
* SDK 宪法迁移批差分记账:原实现只看 res.ok(200 非 JSON / status!=='ok' 也判活);SDK 额外要
|
|
65
|
+
* status==='ok'——service /health 200 恒报 status:'ok',契约面等价,对「200 但引擎自述非 ok」的
|
|
66
|
+
* 病态更严格诚实。
|
|
67
|
+
*/
|
|
68
|
+
export declare function probeEngineAlive(baseUrl: string, timeoutMs?: number): Promise<boolean>;
|
|
69
|
+
/**
|
|
70
|
+
* S3 缩水版 — the tasks.stream diagnose wrapper(liveClient 出口整流罩)。
|
|
71
|
+
* 透传 inner 的每个事件;仅当 inner 以 SseIdleError 收场时介入:
|
|
72
|
+
* 1. signal.aborted 先行 — 用户中止(Esc)撕流原样抛,绝不探活/绝不改判(seamQuery.ts:1073 契约);
|
|
73
|
+
* 2. GET /health 探引擎活性(2s 预算);
|
|
74
|
+
* 3. 引擎活 → 同一错误对象打 engine-alive-idle 标后重抛(下游 tearVerdict 腿改文案;detach `-p`
|
|
75
|
+
* 车道的 R1 重连发生在更内层的 headlessReconnectWire——错误能到这里 = 重连已耗尽/不可换道);
|
|
76
|
+
* 引擎死/探测失败 → 原样重抛(现行 classifyStreamTear 会诚实判 engine-down)。
|
|
77
|
+
* 非 SseIdleError 一律原样穿透。
|
|
78
|
+
*/
|
|
79
|
+
export declare function diagnoseSseIdleTear<T>(inner: AsyncGenerator<T>, baseUrl: string, signal?: AbortSignal): AsyncGenerator<T>;
|
|
80
|
+
/**
|
|
81
|
+
* engine-alive-idle 的用户可见分诊文案(升级自裸 "API Error: SSE: no data for …" 行)。
|
|
82
|
+
* 措辞如实(判决②契约),按 detach 态分叉:
|
|
83
|
+
* · 非 detach(默认/旋钮关/版本门拒/交互车道):tasks/stream 断连 = server 端 abort 这次 run——
|
|
84
|
+
* 不许说"任务仍在继续"的安慰话;能给的出路只有 grace 旋钮 + 手动重发。字节与批 D 发运稿一致
|
|
85
|
+
* (存量脚本可能 grep)。
|
|
86
|
+
* · detach 态(重连腿 M1,`x-detach-on-disconnect: true` 已随首次 POST 发出,server ≥1.196):
|
|
87
|
+
* 断连【不再】abort run——run 已 detach,引擎会把它后台跑完并落 durable 账本;文案如实改述并
|
|
88
|
+
* 指 `GET /v1/runs/<id>`(taskId 已知时带上)/ `sema resume` 查终局。M1 不重连(M2/M3),
|
|
89
|
+
* 本轮前台 rc 仍非零——这是净改善:结果不再整轮丢弃。
|
|
90
|
+
*/
|
|
91
|
+
export declare function engineAliveIdleContent(elapsedMs: number, detach?: {
|
|
92
|
+
detached: true;
|
|
93
|
+
taskId?: string;
|
|
94
|
+
}): string;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/sseIdleTriage.ts 逐字搬入(只 import SDK)。
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* src/sema/sseIdleTriage.ts — turn-stream SSE idle-silence triage(TB2.0 反馈批 D · P0-2 壳半场,2026-07-15)。
|
|
6
|
+
*
|
|
7
|
+
* WHY: TB2.0 bench 真实案例 —— agent 长跑前台编译 ~9.5min,工具完成前壳侧 45s 空闲监测器
|
|
8
|
+
* (`@sema-agent/sdk` readSseFrames HEARTBEAT_GRACE_MS)命中 `SSE: no data for 45000ms (heartbeat
|
|
9
|
+
* silence)` → 整轮 rc=1 丢弃,引擎不知情继续跑完(access log 499)。分诊报告判决①修正段拍定:
|
|
10
|
+
* 壳侧独立可发 = S1(SDK grace 透传+typed SseIdleError,0.0.47 已发)+ S4(grace 旋钮)+
|
|
11
|
+
* S3 缩水版(engine-alive-idle 分诊,只改报错文案,不重连)。本模块 = S4 + S3 的共享件。
|
|
12
|
+
*
|
|
13
|
+
* S4 · SEMA_SSE_HEARTBEAT_GRACE_MS(settings.json `env` 块 → 1a-envseed → process.env,其它 wire
|
|
14
|
+
* 旋钮同一车道):整数毫秒,合法域 [5000, 600000];非法/缺省 = 不透传(SDK 默认 45s)——静默
|
|
15
|
+
* fail-soft,一个 settings typo 绝不 brick 任何 run(scenarioWire settings-lane 纪律)。
|
|
16
|
+
* ⚠️ 作用面 = 会话 turn 流(tasks.stream / liveClient)一条车道。SDK 控制通道(SSETransport.ts:21
|
|
17
|
+
* LIVENESS_TIMEOUT_MS=45s)自带重连+give-up 自愈,本旋钮【不】达那条车道——这不是全局 grace。
|
|
18
|
+
*
|
|
19
|
+
* S3 缩水版 · engine-alive-idle 分诊:liveClient 的 tasks.stream 包装 catch 到 SseIdleError 时,
|
|
20
|
+
* 先判 signal.aborted(用户中止契约先行,seamQuery.ts:1073——Esc 撕流绝不被分诊吞),再 GET
|
|
21
|
+
* `/health`(非 /healthz;server dist server.js:290)短超时探引擎活性:引擎死 → 原样抛(现行
|
|
22
|
+
* engine-down/not-restart 路径不变);引擎活 → 给同一错误对象打 engine-alive-idle 标记,
|
|
23
|
+
* seamQuery 的 tearVerdict 恢复腿据此渲染诚实分诊文案(engineAliveIdleContent)。
|
|
24
|
+
*
|
|
25
|
+
* 【本模块绝不重连】(判决①修正段圣旨,范围随 M2 精化):非 detach 车道上 tasks/stream 客户端
|
|
26
|
+
* 断连 = server onDisconnect ac.abort() 终止 run(anti token-burn by design),且该车道帧无 id
|
|
27
|
+
* 不可位置续传——空闲监测器抛出的那一刻 finally 已 cancel res.body,run 已被这次断连自身中止,
|
|
28
|
+
* 同 key in-flight 重放拿到的只是 aborted 结局。前台另有既有裁决:mid-turn 工具副作用非幂等,
|
|
29
|
+
* 绝不自动重发。引擎 E2(server ≥1.196 x-detach-on-disconnect,[854]①)已到货:headless `-p`
|
|
30
|
+
* detach 车道的 R1 换道重连 = 重连腿 M2,住在 headlessReconnectWire.ts(liveClient 管线最内层,
|
|
31
|
+
* 只在 detach 头已发出的流上武装);本模块保持「探活+打标,不重连」——交互 REPL 与一切非
|
|
32
|
+
* detach 车道的取消契约一根毛不动,M2 耗尽预算后判死文案也仍由这里的打标驱动。
|
|
33
|
+
*/
|
|
34
|
+
import { hostEnv } from './hostEnv.js';
|
|
35
|
+
import { SseIdleError, probeHealth as sdkProbeHealth } from '@sema-agent/sdk';
|
|
36
|
+
/** Settings-lane env knob(settings.json `env` 块 → 1a-envseed → process.env)。整数毫秒。 */
|
|
37
|
+
export const SSE_HEARTBEAT_GRACE_ENV = 'SEMA_SSE_HEARTBEAT_GRACE_MS';
|
|
38
|
+
/** 合法域下界:低于 5s 会把正常 token 间隙误判成静默。 */
|
|
39
|
+
export const SSE_GRACE_MIN_MS = 5_000;
|
|
40
|
+
/** 合法域上界:10min——超过引擎自身各级 idle 顶,再长没有意义。 */
|
|
41
|
+
export const SSE_GRACE_MAX_MS = 600_000;
|
|
42
|
+
/** SDK 默认(readSseFrames HEARTBEAT_GRACE_MS)——文案引用用,不在本模块生效。 */
|
|
43
|
+
export const SDK_DEFAULT_GRACE_MS = 45_000;
|
|
44
|
+
/**
|
|
45
|
+
* S4 — resolve the turn-stream heartbeat grace override. Unset/empty → undefined(SDK 默认 45s,
|
|
46
|
+
* 不透传);非纯十进制整数 / 超出 [5000,600000] → undefined(静默落默认,fail-soft)。
|
|
47
|
+
*/
|
|
48
|
+
export function resolveSseHeartbeatGraceMs(env = hostEnv()) {
|
|
49
|
+
const raw = env[SSE_HEARTBEAT_GRACE_ENV]?.trim();
|
|
50
|
+
if (!raw)
|
|
51
|
+
return undefined;
|
|
52
|
+
if (!/^\d+$/.test(raw))
|
|
53
|
+
return undefined; // 纯十进制整数——'45e3'/'45000.5'/'-1' 全部落默认
|
|
54
|
+
const n = Number(raw);
|
|
55
|
+
if (!Number.isSafeInteger(n) || n < SSE_GRACE_MIN_MS || n > SSE_GRACE_MAX_MS)
|
|
56
|
+
return undefined;
|
|
57
|
+
return n;
|
|
58
|
+
}
|
|
59
|
+
/** 给 SseIdleError 打 engine-alive-idle 标(引擎 /health 已确认活着)。返回同一对象。 */
|
|
60
|
+
export function markEngineAliveIdle(err) {
|
|
61
|
+
;
|
|
62
|
+
err.semaTearVerdict = 'engine-alive-idle';
|
|
63
|
+
return err;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* engine-alive-idle 判型:命中返回静默时长 elapsedMs(SseIdleError 0.0.47 自带;缺失兜 0),
|
|
67
|
+
* 未命中返回 undefined。seamQuery tearVerdict 腿与 headless `-p` 的 stderr 面共用。
|
|
68
|
+
*/
|
|
69
|
+
export function engineAliveIdleElapsedMs(err) {
|
|
70
|
+
const e = err;
|
|
71
|
+
if (!e || e.semaTearVerdict !== 'engine-alive-idle')
|
|
72
|
+
return undefined;
|
|
73
|
+
return typeof e.elapsedMs === 'number' && Number.isFinite(e.elapsedMs) ? e.elapsedMs : 0;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* SseIdleError 判型:instanceof 为主;双包风险(bundle 内外两份 SDK class identity 分叉)下
|
|
77
|
+
* name 兜底——name 由 SDK 构造器冻结为 'SseIdleError',非我方铸造。
|
|
78
|
+
*/
|
|
79
|
+
export function isSseIdleError(err) {
|
|
80
|
+
if (err instanceof SseIdleError)
|
|
81
|
+
return true;
|
|
82
|
+
return err?.name === 'SseIdleError';
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 引擎活性探针 — SDK probeHealth(GET `${baseUrl}/health`;端点是 /health 非 /healthz),默认 2s
|
|
86
|
+
* 预算,永不抛:alive = 200 且 status==='ok';非 2xx / 不可达 / 超时 = not alive(引擎死 → 现行
|
|
87
|
+
* 失败路径,分诊绝不让真死引擎空等)。与 engineUpgradeCoordinator 的 classifyStreamTear 同款姿势。
|
|
88
|
+
* SDK 宪法迁移批差分记账:原实现只看 res.ok(200 非 JSON / status!=='ok' 也判活);SDK 额外要
|
|
89
|
+
* status==='ok'——service /health 200 恒报 status:'ok',契约面等价,对「200 但引擎自述非 ok」的
|
|
90
|
+
* 病态更严格诚实。
|
|
91
|
+
*/
|
|
92
|
+
export async function probeEngineAlive(baseUrl, timeoutMs = 2_000) {
|
|
93
|
+
return (await sdkProbeHealth(baseUrl, timeoutMs)).alive;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* S3 缩水版 — the tasks.stream diagnose wrapper(liveClient 出口整流罩)。
|
|
97
|
+
* 透传 inner 的每个事件;仅当 inner 以 SseIdleError 收场时介入:
|
|
98
|
+
* 1. signal.aborted 先行 — 用户中止(Esc)撕流原样抛,绝不探活/绝不改判(seamQuery.ts:1073 契约);
|
|
99
|
+
* 2. GET /health 探引擎活性(2s 预算);
|
|
100
|
+
* 3. 引擎活 → 同一错误对象打 engine-alive-idle 标后重抛(下游 tearVerdict 腿改文案;detach `-p`
|
|
101
|
+
* 车道的 R1 重连发生在更内层的 headlessReconnectWire——错误能到这里 = 重连已耗尽/不可换道);
|
|
102
|
+
* 引擎死/探测失败 → 原样重抛(现行 classifyStreamTear 会诚实判 engine-down)。
|
|
103
|
+
* 非 SseIdleError 一律原样穿透。
|
|
104
|
+
*/
|
|
105
|
+
export async function* diagnoseSseIdleTear(inner, baseUrl, signal) {
|
|
106
|
+
try {
|
|
107
|
+
yield* inner;
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
if (!signal?.aborted && isSseIdleError(err) && (await probeEngineAlive(baseUrl))) {
|
|
111
|
+
throw markEngineAliveIdle(err);
|
|
112
|
+
}
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* engine-alive-idle 的用户可见分诊文案(升级自裸 "API Error: SSE: no data for …" 行)。
|
|
118
|
+
* 措辞如实(判决②契约),按 detach 态分叉:
|
|
119
|
+
* · 非 detach(默认/旋钮关/版本门拒/交互车道):tasks/stream 断连 = server 端 abort 这次 run——
|
|
120
|
+
* 不许说"任务仍在继续"的安慰话;能给的出路只有 grace 旋钮 + 手动重发。字节与批 D 发运稿一致
|
|
121
|
+
* (存量脚本可能 grep)。
|
|
122
|
+
* · detach 态(重连腿 M1,`x-detach-on-disconnect: true` 已随首次 POST 发出,server ≥1.196):
|
|
123
|
+
* 断连【不再】abort run——run 已 detach,引擎会把它后台跑完并落 durable 账本;文案如实改述并
|
|
124
|
+
* 指 `GET /v1/runs/<id>`(taskId 已知时带上)/ `sema resume` 查终局。M1 不重连(M2/M3),
|
|
125
|
+
* 本轮前台 rc 仍非零——这是净改善:结果不再整轮丢弃。
|
|
126
|
+
*/
|
|
127
|
+
export function engineAliveIdleContent(elapsedMs, detach) {
|
|
128
|
+
const secs = Math.max(1, Math.round((elapsedMs > 0 ? elapsedMs : SDK_DEFAULT_GRACE_MS) / 1000));
|
|
129
|
+
const graceTail = `If your tasks legitimately go quiet this long (e.g. a long build), raise the idle grace: set ${SSE_HEARTBEAT_GRACE_ENV} ` +
|
|
130
|
+
`(settings env, integer ms, ${SSE_GRACE_MIN_MS}-${SSE_GRACE_MAX_MS}; default ${SDK_DEFAULT_GRACE_MS}).`;
|
|
131
|
+
if (detach?.detached) {
|
|
132
|
+
const runRef = detach.taskId ? `GET /v1/runs/${detach.taskId}` : 'GET /v1/runs/<task-id>';
|
|
133
|
+
return (`The engine is still running, but this turn's event stream went silent for ${secs}s, so the connection was closed as idle. ` +
|
|
134
|
+
`This run was DETACHED (x-detach-on-disconnect): the disconnect did NOT abort it — the engine keeps running it to completion in the background ` +
|
|
135
|
+
`and records the outcome durably. Check the final result with \`${runRef}\` on the engine, or \`sema resume\` to pick the session back up. ` +
|
|
136
|
+
graceTail);
|
|
137
|
+
}
|
|
138
|
+
return (`The engine is still running, but this turn's event stream went silent for ${secs}s, so the connection was closed as idle — ` +
|
|
139
|
+
`and closing the stream aborts the run on the engine side (this turn did NOT finish; a long-running tool may have been killed mid-flight). ` +
|
|
140
|
+
graceTail +
|
|
141
|
+
` The session is intact — resend the prompt to retry.`);
|
|
142
|
+
}
|
package/dist/steering.d.ts
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* steering.ts — `steering_injected` → renderable attachment projection (PURE)。
|
|
3
3
|
* cli src/sema/steeringAttachments.ts 的逐字搬运(#52a;差分守卫钉两侧等价)。
|
|
4
4
|
*
|
|
5
|
+
* B1 批(2026-07-27):本文件正文与 cli `steeringAttachments.ts` 实测**逐字节相同**(`diff` 空),
|
|
6
|
+
* 按设计稿 §2.4.1-A 裁决「不留两份实现」⇒ 本文件即唯一实现,壳侧文件改成本包的 re-export。
|
|
7
|
+
* 双份消解方式是「壳侧让位」而非合并 —— 无需改动本文件任何一行行为码。
|
|
8
|
+
*
|
|
5
9
|
* core 1.251 (design/133, board [479] ask-1) echoes every engine-side SYSTEM steering injection as a
|
|
6
10
|
* `steering_injected` wire event `{source, preview}` — `preview` = the injected body's first 220 chars
|
|
7
11
|
* (runtask.ts:2320), echo-only (the model-facing message is unchanged). Sources today:
|
package/dist/steering.js
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* steering.ts — `steering_injected` → renderable attachment projection (PURE)。
|
|
3
3
|
* cli src/sema/steeringAttachments.ts 的逐字搬运(#52a;差分守卫钉两侧等价)。
|
|
4
4
|
*
|
|
5
|
+
* B1 批(2026-07-27):本文件正文与 cli `steeringAttachments.ts` 实测**逐字节相同**(`diff` 空),
|
|
6
|
+
* 按设计稿 §2.4.1-A 裁决「不留两份实现」⇒ 本文件即唯一实现,壳侧文件改成本包的 re-export。
|
|
7
|
+
* 双份消解方式是「壳侧让位」而非合并 —— 无需改动本文件任何一行行为码。
|
|
8
|
+
*
|
|
5
9
|
* core 1.251 (design/133, board [479] ask-1) echoes every engine-side SYSTEM steering injection as a
|
|
6
10
|
* `steering_injected` wire event `{source, preview}` — `preview` = the injected body's first 220 chars
|
|
7
11
|
* (runtask.ts:2320), echo-only (the model-facing message is unchanged). Sources today:
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B1 批搬迁(2026-07-27,多端改造设计稿 §2.4.1-B):cli src/sema/subagentContentStore.ts 逐字搬入(零依赖;壳侧改 re-export)。
|
|
3
|
+
* 🔴 module 级台账(tasks/parentToTask/ownEngineRuns/bgFacts)= 单实例语义:写方(seam adapter
|
|
4
|
+
* runStream 的子代内容分流 + liveClient 的 run_started own 台账)与读方(查看态/帧级 own 判别)
|
|
5
|
+
* 必须走**同一个模块实例**,否则 own 判别恒 false(帧级校验静默失效)。
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* subagentContentStore — dep-free side-channel store for ENGINE subagent CONTENT events (C1 consumption,
|
|
9
|
+
* service 1.89 `forwardSubagentEvents` + core 1.219; blackboard [381]⑤/[383]③).
|
|
10
|
+
*
|
|
11
|
+
* WIRE FACTS: with `forwardSubagentEvents: true` on the task request, the live stream carries the
|
|
12
|
+
* subagent's text_delta / reasoning_delta / tool_start / tool_end stamped with EventIdentity
|
|
13
|
+
* {taskId, parentToolCallId} (§E1 redact upstream; §E2 identity). The seam adapter (runStream.ts)
|
|
14
|
+
* DIVERTS those events here — they must never reach the main-transcript pipeline (a subagent's tokens
|
|
15
|
+
* rendering as the leader's text is the pollution failure mode).
|
|
16
|
+
*
|
|
17
|
+
* WHAT IT KEEPS (bounded, per task):
|
|
18
|
+
* - a NEUTRAL item log: {kind:'text'|'thinking',text} | {kind:'tool',name,input,output,isError,id}
|
|
19
|
+
* (ring-capped) — the 查看态 transcript backlog, so entering a running agent mid-flight still shows
|
|
20
|
+
* history. Message SHAPES are built by the consumers (engineAgentView/chrome-agentprogress own the
|
|
21
|
+
* CC message creators; this store stays dep-free like engineAgentPanelStore).
|
|
22
|
+
* - live accumulation buffers (streaming text/thinking not yet segment-closed).
|
|
23
|
+
* - taskId → parentToolCallId (the C2 steer target — service routes subagent steer by parentToolCallId).
|
|
24
|
+
*
|
|
25
|
+
* NOTIFY: coalesced (~250ms) per-task notify so a per-token delta storm never turns into per-token
|
|
26
|
+
* AppState writes; consumers pull a snapshot on notify.
|
|
27
|
+
*/
|
|
28
|
+
export type SubagentContentItem = {
|
|
29
|
+
kind: 'text';
|
|
30
|
+
text: string;
|
|
31
|
+
} | {
|
|
32
|
+
kind: 'thinking';
|
|
33
|
+
text: string;
|
|
34
|
+
} | {
|
|
35
|
+
kind: 'tool';
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
input: unknown;
|
|
39
|
+
output?: string;
|
|
40
|
+
isError?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** local user echo (查看态 composer 插话) — rides in the item log so a full rebuild keeps it in order */
|
|
43
|
+
| {
|
|
44
|
+
kind: 'echo';
|
|
45
|
+
text: string;
|
|
46
|
+
};
|
|
47
|
+
export interface SubagentContentEvent {
|
|
48
|
+
type: 'text_delta' | 'reasoning_delta' | 'tool_start' | 'tool_end';
|
|
49
|
+
taskId: string;
|
|
50
|
+
parentToolCallId: string;
|
|
51
|
+
delta?: string;
|
|
52
|
+
toolCallId?: string;
|
|
53
|
+
toolName?: string;
|
|
54
|
+
args?: unknown;
|
|
55
|
+
output?: string;
|
|
56
|
+
isError?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** Register the parentToolCallId ↔ engine-taskId pair (from task_progress, which carries both).
|
|
59
|
+
* Content parked under the parent key migrates to the canonical task key. */
|
|
60
|
+
export declare function registerSubagentAlias(parentToolCallId: string, taskId: string): void;
|
|
61
|
+
export declare function publishSubagentContentEvent(ev: SubagentContentEvent): void;
|
|
62
|
+
/** 查看态 composer echo (C2 steer optimistic display) — segment-closes the buffers first so the echo
|
|
63
|
+
* lands AFTER the text streamed before it. taskId may be unseen (row entered before any content):
|
|
64
|
+
* parentToolCallId may then be unknown — pass '' and the steer path resolves the target separately. */
|
|
65
|
+
export declare function pushSubagentLocalEcho(taskId: string, text: string): void;
|
|
66
|
+
export interface SubagentContentSnapshot {
|
|
67
|
+
items: SubagentContentItem[];
|
|
68
|
+
/** streaming tails not yet segment-closed (render as the live trailing message) */
|
|
69
|
+
textBuf: string;
|
|
70
|
+
thinkBuf: string;
|
|
71
|
+
}
|
|
72
|
+
export declare function getSubagentContentSnapshot(taskId: string): SubagentContentSnapshot | null;
|
|
73
|
+
/**
|
|
74
|
+
* 一个查看态转录槽位。`slot` = 稳定 key(消费端拿去当 message uuid —— 250ms 一次的重组不换 key);
|
|
75
|
+
* `live: true` = 尚未段闭合的流式尾巴(下一次段闭合后由同内容的真 item 接位)。
|
|
76
|
+
*/
|
|
77
|
+
export type SubagentViewSlot = {
|
|
78
|
+
kind: 'text';
|
|
79
|
+
slot: string;
|
|
80
|
+
text: string;
|
|
81
|
+
live?: true;
|
|
82
|
+
} | {
|
|
83
|
+
kind: 'thinking';
|
|
84
|
+
slot: string;
|
|
85
|
+
text: string;
|
|
86
|
+
live?: true;
|
|
87
|
+
} | {
|
|
88
|
+
kind: 'echo';
|
|
89
|
+
slot: string;
|
|
90
|
+
text: string;
|
|
91
|
+
} | {
|
|
92
|
+
kind: 'tool';
|
|
93
|
+
slot: string;
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
input: unknown;
|
|
97
|
+
/** undefined = tool_start 已到、tool_end 未到(在飞工具:卡先上屏,结果就地补) */
|
|
98
|
+
output?: string;
|
|
99
|
+
isError?: boolean;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* 把一个子代的内容账本投影成查看态渲染计划。
|
|
103
|
+
*
|
|
104
|
+
* [1568] 之前的形(壳侧 engineAgentView 里)有两处「等段闭合」:①遇到第一个未闭合工具就 break;
|
|
105
|
+
* ②textBuf/thinkBuf 完全不投影。实测(engine 1.275.0 真跑):数据面 ~23 帧/s 的 delta 连续到壳,
|
|
106
|
+
* 查看态却只在 tool 边界更新(进查看态后 6.0s 全空,之后每 5–15s 才动一次)。现形:在飞工具照投,
|
|
107
|
+
* 流式尾巴作为 live 槽投 —— 屏面粒度 = wire 粒度(store notify 已按 250ms 合并)。
|
|
108
|
+
*/
|
|
109
|
+
export declare function planSubagentViewSlots(taskId: string): SubagentViewSlot[];
|
|
110
|
+
/** C2 steer target: the service routes subagent steer by the delegating tool call's id. */
|
|
111
|
+
export declare function parentToolCallIdOf(taskId: string): string | undefined;
|
|
112
|
+
/** Settle a task's streaming buffers (turn ended / run settled) so the snapshot is complete. */
|
|
113
|
+
export declare function settleSubagentContent(taskId: string): void;
|
|
114
|
+
export declare function clearSubagentContent(taskId: string): void;
|
|
115
|
+
export interface BgTerminalFacts {
|
|
116
|
+
status: string;
|
|
117
|
+
summary?: string;
|
|
118
|
+
recentSteps?: Array<{
|
|
119
|
+
tool?: string;
|
|
120
|
+
target?: string;
|
|
121
|
+
outcome?: string;
|
|
122
|
+
}>;
|
|
123
|
+
}
|
|
124
|
+
export declare function recordBgTerminalFacts(taskId: string, facts: BgTerminalFacts): void;
|
|
125
|
+
export declare function getBgTerminalFacts(taskId: string): BgTerminalFacts | undefined;
|
|
126
|
+
export declare function recordBgParentRun(taskId: string, runId: string): void;
|
|
127
|
+
export declare function getBgParentRun(taskId: string): string | undefined;
|
|
128
|
+
export declare function recordOwnEngineRun(runId: string): void;
|
|
129
|
+
export declare function isOwnEngineRun(runId: string): boolean;
|
|
130
|
+
/** Single consumer (the panel hook). Returns an unsubscribe. */
|
|
131
|
+
export declare function subscribeSubagentContent(fn: (taskId: string) => void): () => void;
|