@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,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/forkWireCaps.ts 逐字搬入(零依赖)。
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* src/sema/forkWireCaps.ts — Fork wire projection: the top-level `TaskRequest.enableFork` boolean →
|
|
6
|
+
* core fork governance → the model's Agent(subagent_type:"fork") availability (core 1.257 撤除独立
|
|
7
|
+
* Fork 工具,能力收编进 Agent;CC `subagent_type:fork`: the model forks ITSELF into a subagent that
|
|
8
|
+
* INHERITS the parent context + shares the prompt cache, vs Task's clean-context subagent).
|
|
9
|
+
*
|
|
10
|
+
* DEFAULT = CC parity(clay 2026-07-08 拍板,订正:此前壳里引用的「默认对 LLM 不开」是过时拍板):
|
|
11
|
+
* core ≥1.257 的 fork 治理是 opt-OUT——enableFork 缺省 = GRANTED(与 CC 一致)。壳默认 **不 stamp**,
|
|
12
|
+
* 让引擎默认生效(模型默认可用 Agent-fork)。`SEMA_ENABLE_FORK` 保留为显式开关:truthy ⇒ stamp true
|
|
13
|
+
* (对老引擎 <1.257 也点亮),显式 falsy('0'/'false'/'no'/'off')⇒ stamp false(用户关闭的口子,
|
|
14
|
+
* service [503]② 的 fail-OPEN 教训:关必须显式 false,缺省不再是"关")。
|
|
15
|
+
*
|
|
16
|
+
* PURE — no env/file IO of its OWN (callers pass `env`), so it bundles + unit-tests without the
|
|
17
|
+
* settings graph. The CALLER (seamQuery / the -p ask) gates the env read to LIVE mode so the mock
|
|
18
|
+
* request shape never changes.
|
|
19
|
+
*/
|
|
20
|
+
import { type EnvLike } from './hostEnv.js';
|
|
21
|
+
/** The env key the shell reads. SEMA_-namespaced so it never collides with a worker's own deploy env. */
|
|
22
|
+
export declare const ENABLE_FORK_ENV: "SEMA_ENABLE_FORK";
|
|
23
|
+
/** ENV source → explicit `true`/`false` when the user set SEMA_ENABLE_FORK either way, else
|
|
24
|
+
* `undefined` (⇒ no stamp ⇒ the engine default applies — GRANTED on core ≥1.257, CC parity). */
|
|
25
|
+
export declare function enableForkFromEnv(env?: EnvLike): boolean | undefined;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/forkWireCaps.ts 逐字搬入(零依赖)。
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* src/sema/forkWireCaps.ts — Fork wire projection: the top-level `TaskRequest.enableFork` boolean →
|
|
6
|
+
* core fork governance → the model's Agent(subagent_type:"fork") availability (core 1.257 撤除独立
|
|
7
|
+
* Fork 工具,能力收编进 Agent;CC `subagent_type:fork`: the model forks ITSELF into a subagent that
|
|
8
|
+
* INHERITS the parent context + shares the prompt cache, vs Task's clean-context subagent).
|
|
9
|
+
*
|
|
10
|
+
* DEFAULT = CC parity(clay 2026-07-08 拍板,订正:此前壳里引用的「默认对 LLM 不开」是过时拍板):
|
|
11
|
+
* core ≥1.257 的 fork 治理是 opt-OUT——enableFork 缺省 = GRANTED(与 CC 一致)。壳默认 **不 stamp**,
|
|
12
|
+
* 让引擎默认生效(模型默认可用 Agent-fork)。`SEMA_ENABLE_FORK` 保留为显式开关:truthy ⇒ stamp true
|
|
13
|
+
* (对老引擎 <1.257 也点亮),显式 falsy('0'/'false'/'no'/'off')⇒ stamp false(用户关闭的口子,
|
|
14
|
+
* service [503]② 的 fail-OPEN 教训:关必须显式 false,缺省不再是"关")。
|
|
15
|
+
*
|
|
16
|
+
* PURE — no env/file IO of its OWN (callers pass `env`), so it bundles + unit-tests without the
|
|
17
|
+
* settings graph. The CALLER (seamQuery / the -p ask) gates the env read to LIVE mode so the mock
|
|
18
|
+
* request shape never changes.
|
|
19
|
+
*/
|
|
20
|
+
import { hostEnv } from './hostEnv.js';
|
|
21
|
+
/** The env key the shell reads. SEMA_-namespaced so it never collides with a worker's own deploy env. */
|
|
22
|
+
export const ENABLE_FORK_ENV = 'SEMA_ENABLE_FORK';
|
|
23
|
+
function isTruthy(v) {
|
|
24
|
+
const s = v.trim().toLowerCase();
|
|
25
|
+
return s === '1' || s === 'true' || s === 'yes' || s === 'on';
|
|
26
|
+
}
|
|
27
|
+
function isFalsy(v) {
|
|
28
|
+
const s = v.trim().toLowerCase();
|
|
29
|
+
return s === '0' || s === 'false' || s === 'no' || s === 'off';
|
|
30
|
+
}
|
|
31
|
+
/** ENV source → explicit `true`/`false` when the user set SEMA_ENABLE_FORK either way, else
|
|
32
|
+
* `undefined` (⇒ no stamp ⇒ the engine default applies — GRANTED on core ≥1.257, CC parity). */
|
|
33
|
+
export function enableForkFromEnv(env = hostEnv()) {
|
|
34
|
+
const raw = env[ENABLE_FORK_ENV];
|
|
35
|
+
if (typeof raw !== 'string' || raw.trim() === '')
|
|
36
|
+
return undefined;
|
|
37
|
+
if (isTruthy(raw))
|
|
38
|
+
return true;
|
|
39
|
+
if (isFalsy(raw))
|
|
40
|
+
return false;
|
|
41
|
+
return undefined; // unrecognized spelling — don't guess, let the engine default apply
|
|
42
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hostEnv.ts — B2 批引入的**唯一**宿主环境读口(多端改造设计稿 §5.2 浏览器可移植性)。
|
|
3
|
+
*
|
|
4
|
+
* 为什么需要:搬入的 `*WireCaps` 族有 11 个函数签名是 `(env: NodeJS.ProcessEnv = process.env)`
|
|
5
|
+
* —— 两个问题:① `NodeJS` 命名空间在本包(tsconfig `types: []`、无 @types/node)不存在;
|
|
6
|
+
* ② 浏览器里 `process` 未定义,**不传参调用会 ReferenceError**(不是类型问题,是运行时崩)。
|
|
7
|
+
*
|
|
8
|
+
* 🔴 等价性记账(逐字):Node 下 `hostEnv()` 返回的就是 `process.env` 那个**同一对象**
|
|
9
|
+
* (`globalThis.process === process`),所以壳侧既有「不传 env 参数」的调用点行为一字节不变;
|
|
10
|
+
* 浏览器/worker 下返回 `{}` —— 相当于「所有 env 旋钮未设置」,即各函数自己的缺省档。
|
|
11
|
+
* `EnvLike` 与 `NodeJS.ProcessEnv`(= `Dict<string>`)结构等价,壳侧传 `process.env` 照样过型。
|
|
12
|
+
*/
|
|
13
|
+
/** `process.env` 的结构等价形(`NodeJS.ProcessEnv` 的包内替身)。 */
|
|
14
|
+
export type EnvLike = Record<string, string | undefined>;
|
|
15
|
+
/** 宿主 env(Node = 真 `process.env` 同一对象;无 process 的宿主 = 空表)。 */
|
|
16
|
+
export declare function hostEnv(): EnvLike;
|
package/dist/hostEnv.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hostEnv.ts — B2 批引入的**唯一**宿主环境读口(多端改造设计稿 §5.2 浏览器可移植性)。
|
|
3
|
+
*
|
|
4
|
+
* 为什么需要:搬入的 `*WireCaps` 族有 11 个函数签名是 `(env: NodeJS.ProcessEnv = process.env)`
|
|
5
|
+
* —— 两个问题:① `NodeJS` 命名空间在本包(tsconfig `types: []`、无 @types/node)不存在;
|
|
6
|
+
* ② 浏览器里 `process` 未定义,**不传参调用会 ReferenceError**(不是类型问题,是运行时崩)。
|
|
7
|
+
*
|
|
8
|
+
* 🔴 等价性记账(逐字):Node 下 `hostEnv()` 返回的就是 `process.env` 那个**同一对象**
|
|
9
|
+
* (`globalThis.process === process`),所以壳侧既有「不传 env 参数」的调用点行为一字节不变;
|
|
10
|
+
* 浏览器/worker 下返回 `{}` —— 相当于「所有 env 旋钮未设置」,即各函数自己的缺省档。
|
|
11
|
+
* `EnvLike` 与 `NodeJS.ProcessEnv`(= `Dict<string>`)结构等价,壳侧传 `process.env` 照样过型。
|
|
12
|
+
*/
|
|
13
|
+
/** 宿主 env(Node = 真 `process.env` 同一对象;无 process 的宿主 = 空表)。 */
|
|
14
|
+
export function hostEnv() {
|
|
15
|
+
const p = globalThis.process;
|
|
16
|
+
return p?.env ?? {};
|
|
17
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/imagesWireCaps.ts 逐字搬入(零依赖)。
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* src/sema/imagesWireCaps.ts — PURE projection of a CC user message's IMAGE content blocks → engine ImageInput[]
|
|
6
|
+
* (CC paste-image / drag-image parity). seamQuery imports it.
|
|
7
|
+
*
|
|
8
|
+
* The signature "壳渲染后端空" hole: REPL.tsx:3444 builds Anthropic image blocks
|
|
9
|
+
* { type:'image', source:{ type:'base64', media_type, data } } (or { type:'url', url })
|
|
10
|
+
* into the user message's `content` block array, but seamQuery.objectiveFromMessage kept ONLY `type==='text'`
|
|
11
|
+
* blocks — so pasted images RENDERED but never reached the live engine. core/service already consume
|
|
12
|
+
* `body.images` (main.ts:1296 → core `TaskSpec.images?: ImageInput[]`, types.ts:416 + brain toUserBlocks); this
|
|
13
|
+
* is purely the missing shell-side projection. config-class (model-content the caller chose for their OWN turn).
|
|
14
|
+
*
|
|
15
|
+
* core ImageInput = `{ data: base64, mimeType } | { url }`. We map the Anthropic base64 source
|
|
16
|
+
* (`source.media_type`/`source.data`) → `{ data, mimeType }`, and a url source → `{ url }`.
|
|
17
|
+
*/
|
|
18
|
+
export type ImageInput = {
|
|
19
|
+
data: string;
|
|
20
|
+
mimeType: string;
|
|
21
|
+
} | {
|
|
22
|
+
url: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Extract the IMAGE blocks of a CC user message → ImageInput[]. Reads `message.content` (string | block[]) the
|
|
26
|
+
* same way objectiveFromMessage reads its text; a bare-string content has no images ⇒ []. Malformed blocks drop.
|
|
27
|
+
*/
|
|
28
|
+
export declare function imagesFromMessage(msg: unknown): ImageInput[];
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/imagesWireCaps.ts 逐字搬入(零依赖)。
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* src/sema/imagesWireCaps.ts — PURE projection of a CC user message's IMAGE content blocks → engine ImageInput[]
|
|
6
|
+
* (CC paste-image / drag-image parity). seamQuery imports it.
|
|
7
|
+
*
|
|
8
|
+
* The signature "壳渲染后端空" hole: REPL.tsx:3444 builds Anthropic image blocks
|
|
9
|
+
* { type:'image', source:{ type:'base64', media_type, data } } (or { type:'url', url })
|
|
10
|
+
* into the user message's `content` block array, but seamQuery.objectiveFromMessage kept ONLY `type==='text'`
|
|
11
|
+
* blocks — so pasted images RENDERED but never reached the live engine. core/service already consume
|
|
12
|
+
* `body.images` (main.ts:1296 → core `TaskSpec.images?: ImageInput[]`, types.ts:416 + brain toUserBlocks); this
|
|
13
|
+
* is purely the missing shell-side projection. config-class (model-content the caller chose for their OWN turn).
|
|
14
|
+
*
|
|
15
|
+
* core ImageInput = `{ data: base64, mimeType } | { url }`. We map the Anthropic base64 source
|
|
16
|
+
* (`source.media_type`/`source.data`) → `{ data, mimeType }`, and a url source → `{ url }`.
|
|
17
|
+
*/
|
|
18
|
+
/** Map one Anthropic image block's `source` → ImageInput, or null if malformed/unsupported. */
|
|
19
|
+
function sourceToImageInput(source) {
|
|
20
|
+
if (typeof source !== 'object' || source === null)
|
|
21
|
+
return null;
|
|
22
|
+
const s = source;
|
|
23
|
+
if (s.type === 'base64' && typeof s.data === 'string' && s.data.length > 0) {
|
|
24
|
+
return { data: s.data, mimeType: typeof s.media_type === 'string' && s.media_type ? s.media_type : 'image/png' };
|
|
25
|
+
}
|
|
26
|
+
if (s.type === 'url' && typeof s.url === 'string' && s.url.length > 0) {
|
|
27
|
+
return { url: s.url };
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Extract the IMAGE blocks of a CC user message → ImageInput[]. Reads `message.content` (string | block[]) the
|
|
33
|
+
* same way objectiveFromMessage reads its text; a bare-string content has no images ⇒ []. Malformed blocks drop.
|
|
34
|
+
*/
|
|
35
|
+
export function imagesFromMessage(msg) {
|
|
36
|
+
const m = msg;
|
|
37
|
+
const content = m?.message?.content ?? m?.content;
|
|
38
|
+
if (!Array.isArray(content))
|
|
39
|
+
return [];
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const block of content) {
|
|
42
|
+
if (block && typeof block === 'object' && block.type === 'image') {
|
|
43
|
+
const img = sourceToImageInput(block.source);
|
|
44
|
+
if (img)
|
|
45
|
+
out.push(img);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,27 @@
|
|
|
4
4
|
* seam 设计对签:[1651]/[1652]/[1653];依赖方向:sdk(wire)+agent-types(词汇表)→ 本包,永不反向。
|
|
5
5
|
* 沿革:@sema-agent/wire-cc-adapter 0.1.0 = seam 类型 + id 确定性派生 + 首批踩坑纯函数;
|
|
6
6
|
* 0.1.2(#52a)= adapt() 管线首批(纯投影臂全落 + 壳态耦合臂投影成 ChromeEvent + 差分守卫);
|
|
7
|
-
* 0.2.0 = 迁入 sema-client-core 独立仓并改名(旧 npm 名 deprecate 指本包)
|
|
7
|
+
* 0.2.0 = 迁入 sema-client-core 独立仓并改名(旧 npm 名 deprecate 指本包);
|
|
8
|
+
* 0.4.0 = **B2 批**(设计稿 §3 B2):通知族三文件合并进 notifications.ts(engineTaskNotification 全文 +
|
|
9
|
+
* taskNotificationErrorSupplement 全文 + hookNoticeStore 判定半场)· 17 个 `*WireCaps` + engineWireSdk +
|
|
10
|
+
* sseIdleTriage + classifierVerdictWire 判定半场 + controlRouter + 模型面纯逻辑 4 件 + 新写 hostEnv;
|
|
11
|
+
* 宿主耦合的 6 件(hooksWireCaps/scratchpadWireCaps/liveInitToolFace/engineSessionParam/
|
|
12
|
+
* modelContextResolver/agentModelResolver)**本批不搬**,原因逐条见交接报告。
|
|
13
|
+
* 0.3.0 = **B1 批**(多端改造设计稿 §3 批次表第二批):纯函数/台账 11 文件 + 1 纯类型文件搬入
|
|
14
|
+
* (壳侧 shim 替换随后批)。B1 只搬现行为、零收编、零行为改动;唯一的形状订正是 workflow.ts
|
|
15
|
+
* 补齐 `agent_runs[].errorCode` 类型位(0.2.0 抄件漏项)。
|
|
16
|
+
*
|
|
17
|
+
* 🔴 **单实例纪律**(B1 起本包不再只有纯函数):下列模块持 module 级可变状态,写方与读方必须解析到
|
|
18
|
+
* **同一个包实例** —— 壳侧本地旧副本与 npm 包同时进 bundle = 状态分裂(台账写进一份、读另一份,
|
|
19
|
+
* 症状是「台账恒空」的静默失效,不报错)。清单见各文件头 🔴 段:
|
|
20
|
+
* workflow.ts(workflowAgentTaskIds)· subagentContentStore.ts · engineAgentPanelStore.ts ·
|
|
21
|
+
* fleetAgentPanelProjection.ts · liveQuestionStore.ts · engineInlineTaskStats.ts ·
|
|
22
|
+
* engineCapsCache.ts · engineToolLabelStore.ts
|
|
23
|
+
* —— B2 新增:notifications.ts(11 个通知台账 + 队列 port + 两个 probe 槽)·
|
|
24
|
+
* agentsWireCaps.ts(prepare 缓存/投影闭包/一次性告警集)· liveModelCatalog.ts(目录 + refresher)·
|
|
25
|
+
* sessionModelLatch.ts(三个 latch)· ultracodeWireCaps.ts(sticky preset)。
|
|
26
|
+
* 🔴 **宿主装配**(B2 起本包有必须由宿主注入才完整的口):`installNotificationQueuePort()` ——
|
|
27
|
+
* 不装 = task-notification 投递静默丢失(`notificationQueuePortMisses()` 恒应为 0)。
|
|
8
28
|
*/
|
|
9
29
|
export * from './seam.js';
|
|
10
30
|
export * from './workflow.js';
|
|
@@ -13,3 +33,38 @@ export * from './steering.js';
|
|
|
13
33
|
export * from './diagnostics.js';
|
|
14
34
|
export * from './retryStatus.js';
|
|
15
35
|
export * from './adapt.js';
|
|
36
|
+
export * from './subagentContentStore.js';
|
|
37
|
+
export * from './engineAgentPanelStore.js';
|
|
38
|
+
export * from './fleetAgentPanelProjection.js';
|
|
39
|
+
export * from './liveQuestionStore.js';
|
|
40
|
+
export * from './engineInlineTaskStats.js';
|
|
41
|
+
export * from './printToolResultFrame.js';
|
|
42
|
+
export * from './engineCapsCache.js';
|
|
43
|
+
export * from './engineToolLabelStore.js';
|
|
44
|
+
export * from './fleetTaskDesc.js';
|
|
45
|
+
export type * from './types/engineState.js';
|
|
46
|
+
export * from './hostEnv.js';
|
|
47
|
+
export * from './controlRouter.js';
|
|
48
|
+
export * from './sseIdleTriage.js';
|
|
49
|
+
export * from './engineWireSdk.js';
|
|
50
|
+
export * from './classifierVerdictWire.js';
|
|
51
|
+
export * from './agentsWireCaps.js';
|
|
52
|
+
export * from './attachmentsWireCaps.js';
|
|
53
|
+
export * from './clientContextWireCaps.js';
|
|
54
|
+
export * from './cloudConfigWireCaps.js';
|
|
55
|
+
export * from './forkWireCaps.js';
|
|
56
|
+
export * from './imagesWireCaps.js';
|
|
57
|
+
export * from './mcpWireCaps.js';
|
|
58
|
+
export * from './modelWireCaps.js';
|
|
59
|
+
export * from './permissionWireCaps.js';
|
|
60
|
+
export * from './promptProfileWireCaps.js';
|
|
61
|
+
export * from './retainBackgroundWireCaps.js';
|
|
62
|
+
export * from './rewindWireCaps.js';
|
|
63
|
+
export * from './selfOrchestrationWireCaps.js';
|
|
64
|
+
export * from './skillsWireCaps.js';
|
|
65
|
+
export * from './ultracodeWireCaps.js';
|
|
66
|
+
export * from './webSearchWireCaps.js';
|
|
67
|
+
export * from './liveModelCatalog.js';
|
|
68
|
+
export * from './modelBudgetRule.js';
|
|
69
|
+
export * from './sessionModelLatch.js';
|
|
70
|
+
export * from './effortWire.js';
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,27 @@
|
|
|
4
4
|
* seam 设计对签:[1651]/[1652]/[1653];依赖方向:sdk(wire)+agent-types(词汇表)→ 本包,永不反向。
|
|
5
5
|
* 沿革:@sema-agent/wire-cc-adapter 0.1.0 = seam 类型 + id 确定性派生 + 首批踩坑纯函数;
|
|
6
6
|
* 0.1.2(#52a)= adapt() 管线首批(纯投影臂全落 + 壳态耦合臂投影成 ChromeEvent + 差分守卫);
|
|
7
|
-
* 0.2.0 = 迁入 sema-client-core 独立仓并改名(旧 npm 名 deprecate 指本包)
|
|
7
|
+
* 0.2.0 = 迁入 sema-client-core 独立仓并改名(旧 npm 名 deprecate 指本包);
|
|
8
|
+
* 0.4.0 = **B2 批**(设计稿 §3 B2):通知族三文件合并进 notifications.ts(engineTaskNotification 全文 +
|
|
9
|
+
* taskNotificationErrorSupplement 全文 + hookNoticeStore 判定半场)· 17 个 `*WireCaps` + engineWireSdk +
|
|
10
|
+
* sseIdleTriage + classifierVerdictWire 判定半场 + controlRouter + 模型面纯逻辑 4 件 + 新写 hostEnv;
|
|
11
|
+
* 宿主耦合的 6 件(hooksWireCaps/scratchpadWireCaps/liveInitToolFace/engineSessionParam/
|
|
12
|
+
* modelContextResolver/agentModelResolver)**本批不搬**,原因逐条见交接报告。
|
|
13
|
+
* 0.3.0 = **B1 批**(多端改造设计稿 §3 批次表第二批):纯函数/台账 11 文件 + 1 纯类型文件搬入
|
|
14
|
+
* (壳侧 shim 替换随后批)。B1 只搬现行为、零收编、零行为改动;唯一的形状订正是 workflow.ts
|
|
15
|
+
* 补齐 `agent_runs[].errorCode` 类型位(0.2.0 抄件漏项)。
|
|
16
|
+
*
|
|
17
|
+
* 🔴 **单实例纪律**(B1 起本包不再只有纯函数):下列模块持 module 级可变状态,写方与读方必须解析到
|
|
18
|
+
* **同一个包实例** —— 壳侧本地旧副本与 npm 包同时进 bundle = 状态分裂(台账写进一份、读另一份,
|
|
19
|
+
* 症状是「台账恒空」的静默失效,不报错)。清单见各文件头 🔴 段:
|
|
20
|
+
* workflow.ts(workflowAgentTaskIds)· subagentContentStore.ts · engineAgentPanelStore.ts ·
|
|
21
|
+
* fleetAgentPanelProjection.ts · liveQuestionStore.ts · engineInlineTaskStats.ts ·
|
|
22
|
+
* engineCapsCache.ts · engineToolLabelStore.ts
|
|
23
|
+
* —— B2 新增:notifications.ts(11 个通知台账 + 队列 port + 两个 probe 槽)·
|
|
24
|
+
* agentsWireCaps.ts(prepare 缓存/投影闭包/一次性告警集)· liveModelCatalog.ts(目录 + refresher)·
|
|
25
|
+
* sessionModelLatch.ts(三个 latch)· ultracodeWireCaps.ts(sticky preset)。
|
|
26
|
+
* 🔴 **宿主装配**(B2 起本包有必须由宿主注入才完整的口):`installNotificationQueuePort()` ——
|
|
27
|
+
* 不装 = task-notification 投递静默丢失(`notificationQueuePortMisses()` 恒应为 0)。
|
|
8
28
|
*/
|
|
9
29
|
export * from './seam.js';
|
|
10
30
|
export * from './workflow.js';
|
|
@@ -13,3 +33,44 @@ export * from './steering.js';
|
|
|
13
33
|
export * from './diagnostics.js';
|
|
14
34
|
export * from './retryStatus.js';
|
|
15
35
|
export * from './adapt.js';
|
|
36
|
+
// ── B1 批:纯函数 / 侧信道台账 / 投影闸(2026-07-27)──────────────────────────────────────────
|
|
37
|
+
export * from './subagentContentStore.js';
|
|
38
|
+
export * from './engineAgentPanelStore.js';
|
|
39
|
+
export * from './fleetAgentPanelProjection.js';
|
|
40
|
+
export * from './liveQuestionStore.js';
|
|
41
|
+
export * from './engineInlineTaskStats.js';
|
|
42
|
+
export * from './printToolResultFrame.js';
|
|
43
|
+
export * from './engineCapsCache.js';
|
|
44
|
+
export * from './engineToolLabelStore.js';
|
|
45
|
+
export * from './fleetTaskDesc.js';
|
|
46
|
+
// ── B2 批:通知族合并 / caps-wire 门族 / 模型面纯逻辑 / control 路由(2026-07-27)──────────────
|
|
47
|
+
// 通知族(engineTaskNotification + taskNotificationErrorSupplement + hookNoticeStore 判定半场)
|
|
48
|
+
// 已并入 notifications.js,不需要新增导出行。
|
|
49
|
+
export * from './hostEnv.js';
|
|
50
|
+
export * from './controlRouter.js';
|
|
51
|
+
export * from './sseIdleTriage.js';
|
|
52
|
+
export * from './engineWireSdk.js';
|
|
53
|
+
export * from './classifierVerdictWire.js';
|
|
54
|
+
// caps / wire 门族(17 个 *WireCaps —— 壳侧 hooksWireCaps / scratchpadWireCaps 因宿主耦合未搬,
|
|
55
|
+
// 见 README 的 B2 记账)
|
|
56
|
+
export * from './agentsWireCaps.js';
|
|
57
|
+
export * from './attachmentsWireCaps.js';
|
|
58
|
+
export * from './clientContextWireCaps.js';
|
|
59
|
+
export * from './cloudConfigWireCaps.js';
|
|
60
|
+
export * from './forkWireCaps.js';
|
|
61
|
+
export * from './imagesWireCaps.js';
|
|
62
|
+
export * from './mcpWireCaps.js';
|
|
63
|
+
export * from './modelWireCaps.js';
|
|
64
|
+
export * from './permissionWireCaps.js';
|
|
65
|
+
export * from './promptProfileWireCaps.js';
|
|
66
|
+
export * from './retainBackgroundWireCaps.js';
|
|
67
|
+
export * from './rewindWireCaps.js';
|
|
68
|
+
export * from './selfOrchestrationWireCaps.js';
|
|
69
|
+
export * from './skillsWireCaps.js';
|
|
70
|
+
export * from './ultracodeWireCaps.js';
|
|
71
|
+
export * from './webSearchWireCaps.js';
|
|
72
|
+
// 模型面纯逻辑族
|
|
73
|
+
export * from './liveModelCatalog.js';
|
|
74
|
+
export * from './modelBudgetRule.js';
|
|
75
|
+
export * from './sessionModelLatch.js';
|
|
76
|
+
export * from './effortWire.js';
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/liveModelCatalog.ts 逐字搬入(零依赖;🔴 catalog/refresher 是单实例态 —— 写口 setLiveModelCatalog/installer 与读口 getLiveModelCatalog 必须同实例)。
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* src/sema/liveModelCatalog.ts — the LIVE model-catalog singleton (TEAM-C / clay decision #1 = A).
|
|
6
|
+
*
|
|
7
|
+
* WHY THIS FILE EXISTS
|
|
8
|
+
* --------------------
|
|
9
|
+
* The `/model` picker, the header model line, the /status "Model" row, and the picker's ✔ are all stuck on
|
|
10
|
+
* a STATIC opus[1m] / a STATIC fictional catalog (mock/control/modelOptionsSeam.ts). The live engine actually
|
|
11
|
+
* serves a different fleet — `client.models.list()` returns `{ models, default }` (the REAL catalog), and
|
|
12
|
+
* `done.result.model` echoes the REAL served model (MF-25). This module is the one-shot, process-wide bridge
|
|
13
|
+
* between the LIVE wire read (done once at boot in replEntry's live block) and the SYNCHRONOUS render-time
|
|
14
|
+
* readers (getModelOptions, called inside the picker's React render — it cannot await).
|
|
15
|
+
*
|
|
16
|
+
* SINGLE INSTANCE (build discipline): replEntry.tsx (build-src/src/sema/replEntry.tsx) SETS the catalog and
|
|
17
|
+
* mock/control/modelOptionsSeam.ts (build-src/mock/control/…, the aliased getModelOptions target) READS it.
|
|
18
|
+
* Both resolve this module to ONE staged path (build-src/src/sema/liveModelCatalog.ts), so the singleton is
|
|
19
|
+
* shared — the same single-instance invariant the seam-module fix in scripts/build.sema.mjs guarantees.
|
|
20
|
+
*
|
|
21
|
+
* MOCK PATH UNCHANGED: with SEMA_LIVE_BASEURL unset, no one calls setLiveModelCatalog → the catalog stays
|
|
22
|
+
* null → getModelOptions falls back to the static fleetModels mock and the boot keeps opus[1m]. So the
|
|
23
|
+
* cell-exact mock parity (the /model picker mock rows, the opus[1m] header/status, the /context 20-glyph
|
|
24
|
+
* grid driven by has1mContext('opus[1m]')) is preserved byte-for-byte.
|
|
25
|
+
*/
|
|
26
|
+
/** The neutral wire shape of one model-catalog row (a structural subset of @sema-ai/sdk ModelInfo +
|
|
27
|
+
* mock/control/modelSelect.ts ModelInfo — name/id/provider/reasoning/vision drive the picker badges). */
|
|
28
|
+
export interface LiveModelInfo {
|
|
29
|
+
name: string;
|
|
30
|
+
id?: string;
|
|
31
|
+
provider?: string;
|
|
32
|
+
reasoning?: boolean;
|
|
33
|
+
vision?: boolean;
|
|
34
|
+
[k: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
/** The `GET /v1/models` envelope: the catalog rows + the deployment default model id (display-only). */
|
|
37
|
+
export interface LiveModelCatalog {
|
|
38
|
+
models: LiveModelInfo[];
|
|
39
|
+
/** The served-by-default model id (models.list().default) — the boot mainLoopModel + the picker default desc. */
|
|
40
|
+
default: string;
|
|
41
|
+
}
|
|
42
|
+
/** Install the live catalog (called once at boot from replEntry's live block). null clears it. */
|
|
43
|
+
export declare function setLiveModelCatalog(next: LiveModelCatalog | null): void;
|
|
44
|
+
/** boot 注册的重取器(与 boot fetch 同参)。k3 案(clay 2026-07-20):/config 改 Model ID 后
|
|
45
|
+
* 同会话 /model 仍显旧目录名——目录只在 boot 拉一次。Hub 保存/面板打开时经此重取。 */
|
|
46
|
+
export declare function setLiveModelCatalogRefresher(fn: (() => Promise<LiveModelCatalog | null>) | null): void;
|
|
47
|
+
/** Re-fetch the live catalog (boot 参数);成功即替换 singleton 并返回 true。mock 路径(无
|
|
48
|
+
* refresher)/拉取失败 → false,现值不动(fail-soft,绝不用 null 清掉可用旧目录)。 */
|
|
49
|
+
export declare function refreshLiveModelCatalog(): Promise<boolean>;
|
|
50
|
+
/** Read the live catalog (null = mock path / live read failed → callers fall back to the static mock). */
|
|
51
|
+
export declare function getLiveModelCatalog(): LiveModelCatalog | null;
|
|
52
|
+
/**
|
|
53
|
+
* 件4/MOD-6(F1 模型面批):id/name 双键归一。目录行有两个可寻址键 —— `name`(池 entry id,
|
|
54
|
+
* /model 面板行的 value、@mention 的 handle)和 `id`(上游 modelId);/v1/models 的 `default`
|
|
55
|
+
* 与 boot 回读可能给 id,面板/appState 用 name ⇒ 单键比对时 id≠name 的行匹配不上,面板追加
|
|
56
|
+
* 合成 "Current model" 重复行、✔ 落错行。归一规则:ref 已是某行 name ⇒ 原样;否则命中某行
|
|
57
|
+
* id ⇒ 归一到该行 name;目录缺失(mock 路径)/未命中 ⇒ 原样返回(mock parity 零影响)。
|
|
58
|
+
*/
|
|
59
|
+
export declare function normalizeLiveModelRef(ref: string): string;
|
|
60
|
+
/** 件4(S2 回显):目录 default 的用户名 —— name(池 entry id)优先,id 兜底;null=无目录
|
|
61
|
+
* (mock 路径,调用方回落 CC 字面护 parity)。 */
|
|
62
|
+
export declare function liveDefaultModelName(): string | null;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B2 批搬迁(2026-07-27,多端改造设计稿 §3 B2):cli src/sema/liveModelCatalog.ts 逐字搬入(零依赖;🔴 catalog/refresher 是单实例态 —— 写口 setLiveModelCatalog/installer 与读口 getLiveModelCatalog 必须同实例)。
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* src/sema/liveModelCatalog.ts — the LIVE model-catalog singleton (TEAM-C / clay decision #1 = A).
|
|
6
|
+
*
|
|
7
|
+
* WHY THIS FILE EXISTS
|
|
8
|
+
* --------------------
|
|
9
|
+
* The `/model` picker, the header model line, the /status "Model" row, and the picker's ✔ are all stuck on
|
|
10
|
+
* a STATIC opus[1m] / a STATIC fictional catalog (mock/control/modelOptionsSeam.ts). The live engine actually
|
|
11
|
+
* serves a different fleet — `client.models.list()` returns `{ models, default }` (the REAL catalog), and
|
|
12
|
+
* `done.result.model` echoes the REAL served model (MF-25). This module is the one-shot, process-wide bridge
|
|
13
|
+
* between the LIVE wire read (done once at boot in replEntry's live block) and the SYNCHRONOUS render-time
|
|
14
|
+
* readers (getModelOptions, called inside the picker's React render — it cannot await).
|
|
15
|
+
*
|
|
16
|
+
* SINGLE INSTANCE (build discipline): replEntry.tsx (build-src/src/sema/replEntry.tsx) SETS the catalog and
|
|
17
|
+
* mock/control/modelOptionsSeam.ts (build-src/mock/control/…, the aliased getModelOptions target) READS it.
|
|
18
|
+
* Both resolve this module to ONE staged path (build-src/src/sema/liveModelCatalog.ts), so the singleton is
|
|
19
|
+
* shared — the same single-instance invariant the seam-module fix in scripts/build.sema.mjs guarantees.
|
|
20
|
+
*
|
|
21
|
+
* MOCK PATH UNCHANGED: with SEMA_LIVE_BASEURL unset, no one calls setLiveModelCatalog → the catalog stays
|
|
22
|
+
* null → getModelOptions falls back to the static fleetModels mock and the boot keeps opus[1m]. So the
|
|
23
|
+
* cell-exact mock parity (the /model picker mock rows, the opus[1m] header/status, the /context 20-glyph
|
|
24
|
+
* grid driven by has1mContext('opus[1m]')) is preserved byte-for-byte.
|
|
25
|
+
*/
|
|
26
|
+
let catalog = null;
|
|
27
|
+
let refresher = null;
|
|
28
|
+
/** Install the live catalog (called once at boot from replEntry's live block). null clears it. */
|
|
29
|
+
export function setLiveModelCatalog(next) {
|
|
30
|
+
catalog = next;
|
|
31
|
+
}
|
|
32
|
+
/** boot 注册的重取器(与 boot fetch 同参)。k3 案(clay 2026-07-20):/config 改 Model ID 后
|
|
33
|
+
* 同会话 /model 仍显旧目录名——目录只在 boot 拉一次。Hub 保存/面板打开时经此重取。 */
|
|
34
|
+
export function setLiveModelCatalogRefresher(fn) {
|
|
35
|
+
refresher = fn;
|
|
36
|
+
}
|
|
37
|
+
/** Re-fetch the live catalog (boot 参数);成功即替换 singleton 并返回 true。mock 路径(无
|
|
38
|
+
* refresher)/拉取失败 → false,现值不动(fail-soft,绝不用 null 清掉可用旧目录)。 */
|
|
39
|
+
export async function refreshLiveModelCatalog() {
|
|
40
|
+
if (!refresher)
|
|
41
|
+
return false;
|
|
42
|
+
try {
|
|
43
|
+
const next = await refresher();
|
|
44
|
+
if (next && Array.isArray(next.models) && next.models.length > 0) {
|
|
45
|
+
catalog = next;
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
/* fail-soft */
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
/** Read the live catalog (null = mock path / live read failed → callers fall back to the static mock). */
|
|
55
|
+
export function getLiveModelCatalog() {
|
|
56
|
+
return catalog;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 件4/MOD-6(F1 模型面批):id/name 双键归一。目录行有两个可寻址键 —— `name`(池 entry id,
|
|
60
|
+
* /model 面板行的 value、@mention 的 handle)和 `id`(上游 modelId);/v1/models 的 `default`
|
|
61
|
+
* 与 boot 回读可能给 id,面板/appState 用 name ⇒ 单键比对时 id≠name 的行匹配不上,面板追加
|
|
62
|
+
* 合成 "Current model" 重复行、✔ 落错行。归一规则:ref 已是某行 name ⇒ 原样;否则命中某行
|
|
63
|
+
* id ⇒ 归一到该行 name;目录缺失(mock 路径)/未命中 ⇒ 原样返回(mock parity 零影响)。
|
|
64
|
+
*/
|
|
65
|
+
export function normalizeLiveModelRef(ref) {
|
|
66
|
+
if (!catalog || !ref)
|
|
67
|
+
return ref;
|
|
68
|
+
if (catalog.models.some(m => m.name === ref))
|
|
69
|
+
return ref;
|
|
70
|
+
const row = catalog.models.find(m => typeof m.id === 'string' && m.id === ref);
|
|
71
|
+
return row?.name || ref;
|
|
72
|
+
}
|
|
73
|
+
/** 件4(S2 回显):目录 default 的用户名 —— name(池 entry id)优先,id 兜底;null=无目录
|
|
74
|
+
* (mock 路径,调用方回落 CC 字面护 parity)。 */
|
|
75
|
+
export function liveDefaultModelName() {
|
|
76
|
+
if (!catalog?.default)
|
|
77
|
+
return null;
|
|
78
|
+
return normalizeLiveModelRef(catalog.default);
|
|
79
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⇄ B1 批搬迁(2026-07-27,多端改造设计稿 §2.4.1-B):cli src/sema/liveQuestionStore.ts 逐字搬入(零依赖;壳侧改 re-export)。
|
|
3
|
+
* 本模块自持 AskUserQuestion 的 wire 词汇(SDK 0.0.44 删掉了 questions 资源导出),搬入后这套
|
|
4
|
+
* 类型随包发布 —— web/桌面端的 HITL 覆盖层与 TUI 共用同一份 QuestionFrame/QuestionAnswer 形。
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* src/sema/liveQuestionStore.ts — the SIDE-CHANNEL for §4④ live-stream AskUserQuestion (the conversation-seam
|
|
8
|
+
* twin of liveSessionStore.ts).
|
|
9
|
+
*
|
|
10
|
+
* WHY THIS EXISTS
|
|
11
|
+
* ---------------
|
|
12
|
+
* In TOC (two-process) the MODEL runs in the engine; its `AskUserQuestion` tool fires on core's
|
|
13
|
+
* `RunnerDeps.onQuestion` seam and the service (question.ts, 1.61.0) emits a NAMED SSE frame
|
|
14
|
+
* (`event: question` / `event: question_complete`) that INTERLEAVES on the same live token stream as the
|
|
15
|
+
* AgentEvents. That frame is NOT an AgentEvent arm (it is a DISTINCT vocabulary, exactly like elicitation) —
|
|
16
|
+
* so it must be DEMUXED out of the transcript-render pipeline and routed to an interactive DIALOG overlay
|
|
17
|
+
* instead. This tiny, dependency-FREE module is that route: liveClient WRITES the demuxed frame here (on each
|
|
18
|
+
* `question`/`question_complete`) and publishes its `client.questions.respond` binding; the UI overlay
|
|
19
|
+
* (main.tsx / REPL) READS the frames and answers via `respondToQuestion`. Same shape as liveSessionStore /
|
|
20
|
+
* rewindAnchorStore — the overlay stays testable (no @sema-ai/sdk graph) and seamQuery/normalizeToolNames are
|
|
21
|
+
* untouched.
|
|
22
|
+
*
|
|
23
|
+
* 🔴 LIVE-ONLY + SAME-REPLICA (the `steer()`-class of HITL): the service parks the answer promise in-memory,
|
|
24
|
+
* so a respond that lands after the TTL (5 min) / after answer / on another replica → 404. No durable resume
|
|
25
|
+
* anchor — a mid-question disconnect just lets the run proceed with the headless default (the model never
|
|
26
|
+
* hangs). The overlay must therefore treat `respondToQuestion` as best-effort (a 404 = "already released",
|
|
27
|
+
* dismiss the dialog, never retry).
|
|
28
|
+
*
|
|
29
|
+
* 🔴 UNTRUSTED: the `questions` payload is model-authored (service secret-redacted, but still UNTRUSTED for
|
|
30
|
+
* display). The overlay RENDERS it; it must NEVER be re-fed to a model. The answer the overlay sends back is
|
|
31
|
+
* fenced by CORE (`selected ⊆ options`, `note` untrusted-fenced) — the overlay must echo the EXACT option
|
|
32
|
+
* labels the user saw, never fabricate one.
|
|
33
|
+
*/
|
|
34
|
+
/** One option of an AskUserQuestion question (CC AskUserQuestionTool option shape). */
|
|
35
|
+
export interface AskQuestionOption {
|
|
36
|
+
/** EXACT display label — the answer echoes labels verbatim (core fences `selected ⊆ options`). */
|
|
37
|
+
label: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
}
|
|
40
|
+
/** One model-authored question (UNTRUSTED: render-only, never re-fed to a model). */
|
|
41
|
+
export interface AskQuestion {
|
|
42
|
+
/** The question text (the CC dialog keys its answers Record by this). */
|
|
43
|
+
question: string;
|
|
44
|
+
/** Short header — the WIRE answer is keyed by this (see {@link QuestionAnswer}). */
|
|
45
|
+
header: string;
|
|
46
|
+
options: AskQuestionOption[];
|
|
47
|
+
multiSelect: boolean;
|
|
48
|
+
}
|
|
49
|
+
/** A demuxed/synthetic live question frame (legacy 1.61 wire payload `{type,questionId,questions?,outcome?}`;
|
|
50
|
+
* today also synthesized locally by liveHitlAskWire (`hitl-ask:*`) and planReviewWire (`plan-review:*`)).
|
|
51
|
+
* `question` opens the dialog overlay; `question_complete` dismisses a still-open one. */
|
|
52
|
+
export interface QuestionFrame {
|
|
53
|
+
type: 'question' | 'question_complete';
|
|
54
|
+
questionId: string;
|
|
55
|
+
/** Present on `question` frames; may be absent when the service dropped an over-cap payload. */
|
|
56
|
+
questions?: AskQuestion[];
|
|
57
|
+
/** `question_complete` only (legacy wire): why the ask was released (answered/expired/aborted). */
|
|
58
|
+
outcome?: string;
|
|
59
|
+
}
|
|
60
|
+
/** The answer the overlay sends back — keyed by HEADER; `selected` echoes exact option labels
|
|
61
|
+
* (`selected ⊆ options`, core's fence); off-list / free-text input rides `note` (untrusted-fenced).
|
|
62
|
+
* Entry shape === hitlBridge's AskAnswer (the T23 ApprovalDecision.answer leg consumes it as-is). */
|
|
63
|
+
export interface QuestionAnswer {
|
|
64
|
+
answers: Array<{
|
|
65
|
+
header: string;
|
|
66
|
+
selected: string[];
|
|
67
|
+
note?: string;
|
|
68
|
+
}>;
|
|
69
|
+
}
|
|
70
|
+
type QuestionFrameHandler = (frame: QuestionFrame) => void;
|
|
71
|
+
type RespondFn = (id: string, answer: QuestionAnswer, opts?: {
|
|
72
|
+
signal?: AbortSignal;
|
|
73
|
+
}) => Promise<unknown>;
|
|
74
|
+
/** Register a one-shot local responder for a SYNTHETIC question frame (e.g. `plan-review:<taskId>`).
|
|
75
|
+
* Returns an unregister fn (dialog dismissed without answering ⇒ caller cleans up). */
|
|
76
|
+
export declare function registerLocalQuestionResponder(id: string, fn: RespondFn): () => void;
|
|
77
|
+
/**
|
|
78
|
+
* Publish a demuxed live question frame (called from liveClient's demuxQuestionFrames on each
|
|
79
|
+
* `question`/`question_complete`). Best-effort: a UI handler error is swallowed so a broken overlay can NEVER
|
|
80
|
+
* break the live stream drain (the run must keep flowing; a lost frame just headless-defaults the ask).
|
|
81
|
+
*/
|
|
82
|
+
export declare function publishQuestionFrame(frame: QuestionFrame): void;
|
|
83
|
+
/** Whether a UI overlay is currently subscribed (liveHitlAskWire gates on this: print/non-REPL mode has no
|
|
84
|
+
* dialog to park on, so the suspended terminal must fall through honestly instead of hanging the stream). */
|
|
85
|
+
export declare function hasQuestionOverlay(): boolean;
|
|
86
|
+
/** Subscribe the UI overlay to live question frames. Returns an unsubscribe. Last writer wins (one overlay). */
|
|
87
|
+
export declare function onQuestionFrame(handler: QuestionFrameHandler): () => void;
|
|
88
|
+
/** Publish the live client's `questions.respond` binding (called from createLiveConversationClient). `null`
|
|
89
|
+
* clears it (offline/mock → respondToQuestion rejects cleanly). */
|
|
90
|
+
export declare function setQuestionRespond(fn: RespondFn | null): void;
|
|
91
|
+
/**
|
|
92
|
+
* Answer a parked live question (POST /v1/questions/:id/respond via the live client). Rejects when no live
|
|
93
|
+
* client is wired (offline/mock) so the overlay can fall back / dismiss. The 404 (answered/expired/wrong
|
|
94
|
+
* replica) surfaces as a thrown ApiError — the overlay treats it as "already released", never a retry.
|
|
95
|
+
*/
|
|
96
|
+
export declare function respondToQuestion(id: string, answer: QuestionAnswer, opts?: {
|
|
97
|
+
signal?: AbortSignal;
|
|
98
|
+
}): Promise<unknown>;
|
|
99
|
+
/** Test-only reset. */
|
|
100
|
+
export declare function _resetLiveQuestionStore(): void;
|
|
101
|
+
export {};
|