@sema-agent/client-core 0.11.6 → 0.11.8
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/dist/adapter/downstream/terminalToSdkResult.d.ts +5 -3
- package/dist/adapter/downstream/terminalToSdkResult.js +42 -11
- package/dist/request/taskRequest.d.ts +2 -0
- package/dist/request/taskRequest.js +10 -1
- package/dist/seatContract.d.ts +47 -2
- package/dist/seatContract.js +30 -1
- package/package.json +2 -2
|
@@ -49,9 +49,11 @@
|
|
|
49
49
|
* timeout salvage:写出窗兑现的 r.result(非空)骑 additive `result` 字段——CC error 帧无
|
|
50
50
|
* result,但把引擎已救回的最终文本静默丢弃对 -p 消费者是净损失。
|
|
51
51
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
52
|
+
* 成本取数 = `TaskStats.costMicroUsd`(整数 micro-USD 单轨,SDK 1.0.0 / server 1.319.0 /
|
|
53
|
+
* core 2.0.0 起;legacy float `costUsd` 已删,见 costOrNull 头注)。零成本 is AMBIGUOUS
|
|
54
|
+
* (free vs. no MODEL_COST_* configured): disambiguate upstream via
|
|
55
|
+
* Capabilities.pricingConfigured (contract 02 §2.10 VERIFY); this projector converts
|
|
56
|
+
* the integer to USD (/1e6) and passes it through verbatim otherwise.
|
|
55
57
|
*/
|
|
56
58
|
import type { AgentEvent } from '@sema-agent/sdk';
|
|
57
59
|
import { type SDKMessage, type EmitContext } from '../types.js';
|
|
@@ -21,14 +21,41 @@ function elapsedMs(ctx) {
|
|
|
21
21
|
return typeof ctx.startedAtMs === 'number' ? Math.max(0, Date.now() - ctx.startedAtMs) : 0;
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* micro-USD → USD。引擎账面的成本单位是 **micro-USD**(百万分之一美元,整数轨:1e6 micro = 1 USD;
|
|
25
|
+
* 整数是为了不吃 FP 漂移)。CC 的输出面字段 `total_cost_usd` / `costUSD` 单位是 **USD**(字段名即
|
|
26
|
+
* 单位),所以出口一律 `/1e6`。非有限值(NaN/Infinity)不上账 —— Infinity 比 undefined 更糟,它会被
|
|
27
|
+
* 当成真数字参与求和,把一条离谱账悄悄摊进总计(与 SDK `taskCostMicroUsd()` 的规约逐条同义;
|
|
28
|
+
* `mapModelUsage()` 里的 `costMicroUsd / 1e6` 是同一换算的既有用法,两处此后共用本函数)。
|
|
29
|
+
*
|
|
30
|
+
* 为什么不直接调 SDK 的 `taskCostMicroUsd()`:本文件在 `runStream` **可移植闭包**内,portability 门
|
|
31
|
+
* 对该闭包断言「值级外部包 = 空集」(EXPECTED_PACKAGES_KERNEL),值级 import SDK 会当场红。故就地
|
|
32
|
+
* 复刻规约,单一真源以 SDK 那份注释为准。
|
|
33
|
+
*/
|
|
34
|
+
function microUsdToUsd(micro) {
|
|
35
|
+
return typeof micro === 'number' && Number.isFinite(micro) ? micro / 1e6 : null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* P1-5 — `total_cost_usd` truthfulness: 成本 `0` is AMBIGUOUS (free vs. no MODEL_COST_* configured
|
|
25
39
|
* on the worker — the local TOC engine ships unconfigured, so `-p --output-format json` was reporting a
|
|
26
40
|
* fake `0`). Emit the number only when it is a REAL positive cost; otherwise `null` (JSON consumers see
|
|
27
41
|
* "unknown", never a fabricated zero). CC's schema field is numeric — number-guarded readers
|
|
28
42
|
* (replEntry cost fold) already treat non-number as absent.
|
|
43
|
+
*
|
|
44
|
+
* 🔴 键迁移([2006] cli 自查最重命中,2026-07-29):取数源从 legacy float `TaskStats.costUsd` 换成
|
|
45
|
+
* 整数 `TaskStats.costMicroUsd`。`costUsd` 已被 **core 2.0.0 / server 1.319.0 / SDK 1.0.0 同批删除**
|
|
46
|
+
* (发端、适配、类型三层),对 core 2.0.0+ 引擎该键恒 undefined ⇒ 本函数恒 null ⇒ `sema -p
|
|
47
|
+
* --output-format json` 的 `total_cost_usd` **恒 null**,而账其实一直在 `costMicroUsd` 上
|
|
48
|
+
* (本文件 `mapModelUsage()` 早就在读它 = 两代键并存的实锤)。devDep 此前钉 SDK `^0.1.7`(0.x 的 caret 是精确锁)
|
|
49
|
+
* ⇒ 类型层看到的还是「两轨都在」的旧声明,对 1.0.0 才报 TS2345 —— 校旧物的门抓不住这类断链,故
|
|
50
|
+
* 另有 `run-sdk-floor-test.mjs` 断言实装 SDK 地板 ≥ 1.1。
|
|
51
|
+
*
|
|
52
|
+
* 老引擎只发 float `costUsd` 时**不做兼容换算**:单轨之后读到 undefined(当场可见「不知道」)好过
|
|
53
|
+
* 把一笔来源可疑的账静默吸收成看起来正常的数字(SDK normalize.ts 的 BREAKING 留档同款裁定;
|
|
54
|
+
* 本仓 [clean-cut-no-legacy-compat])。
|
|
29
55
|
*/
|
|
30
|
-
function costOrNull(
|
|
31
|
-
|
|
56
|
+
function costOrNull(stats) {
|
|
57
|
+
const usd = microUsdToUsd(stats?.costMicroUsd);
|
|
58
|
+
return usd !== null && usd > 0 ? usd : null;
|
|
32
59
|
}
|
|
33
60
|
// 件2a(中断事故修复批 G,2026-07-15,症状2 第一环):参数放宽 TaskStats | undefined + 全链守卫。
|
|
34
61
|
// 409 active-run 拒绝时引擎的 done 帧本体是 {status:'failed', errorMessage, activeTaskId} —— NO stats
|
|
@@ -51,7 +78,7 @@ function mapModelUsage(stats) {
|
|
|
51
78
|
cacheReadInputTokens: num(m.cacheReadTokens),
|
|
52
79
|
cacheCreationInputTokens: num(m.cacheWriteTokens),
|
|
53
80
|
webSearchRequests: 0,
|
|
54
|
-
costUSD:
|
|
81
|
+
costUSD: microUsdToUsd(m.costMicroUsd) ?? 0, // ⇐ 与 costOrNull 同一个换算口(旧写法 num(...)/1e6 逐值等价)
|
|
55
82
|
contextWindow: 0,
|
|
56
83
|
maxOutputTokens: 0,
|
|
57
84
|
};
|
|
@@ -79,7 +106,11 @@ export function doneToSdkResult(ev, ctx) {
|
|
|
79
106
|
modelUsage = {
|
|
80
107
|
[r.model]: {
|
|
81
108
|
...usage,
|
|
82
|
-
|
|
109
|
+
// 键迁移(见 costOrNull 头注):legacy float `costUsd` → 整数 `costMicroUsd`(/1e6 → USD)。
|
|
110
|
+
// ⚠️ 这一处**类型门抓不到**:TaskStats 带 `[key: string]: unknown` 开集索引,`typeof
|
|
111
|
+
// stats?.costUsd === 'number'` 的旧写法在 SDK 1.x 下照样编译得过,只是恒假 ⇒ 合成行的
|
|
112
|
+
// costUSD 静默恒 0(比报错更隐蔽)。tsc 只红了 6 处直传,这处靠人核。
|
|
113
|
+
costUSD: microUsdToUsd(stats?.costMicroUsd) ?? 0,
|
|
83
114
|
contextWindow: 0,
|
|
84
115
|
maxOutputTokens: 0,
|
|
85
116
|
},
|
|
@@ -129,7 +160,7 @@ export function doneToSdkResult(ev, ctx) {
|
|
|
129
160
|
is_error: true,
|
|
130
161
|
num_turns: stats?.turns ?? 0,
|
|
131
162
|
stop_reason: null,
|
|
132
|
-
total_cost_usd: costOrNull(stats
|
|
163
|
+
total_cost_usd: costOrNull(stats), // P1-5: null when unknown, never a fake 0
|
|
133
164
|
usage,
|
|
134
165
|
modelUsage,
|
|
135
166
|
permission_denials: [],
|
|
@@ -178,7 +209,7 @@ export function doneToSdkResult(ev, ctx) {
|
|
|
178
209
|
is_error: true,
|
|
179
210
|
num_turns: stats?.turns ?? 0,
|
|
180
211
|
stop_reason: null,
|
|
181
|
-
total_cost_usd: costOrNull(stats
|
|
212
|
+
total_cost_usd: costOrNull(stats),
|
|
182
213
|
usage,
|
|
183
214
|
modelUsage,
|
|
184
215
|
permission_denials: [],
|
|
@@ -207,7 +238,7 @@ export function doneToSdkResult(ev, ctx) {
|
|
|
207
238
|
is_error: true,
|
|
208
239
|
num_turns: stats?.turns ?? 0,
|
|
209
240
|
stop_reason: null,
|
|
210
|
-
total_cost_usd: costOrNull(stats
|
|
241
|
+
total_cost_usd: costOrNull(stats),
|
|
211
242
|
usage,
|
|
212
243
|
modelUsage,
|
|
213
244
|
permission_denials: [],
|
|
@@ -256,7 +287,7 @@ export function doneToSdkResult(ev, ctx) {
|
|
|
256
287
|
is_error: true,
|
|
257
288
|
num_turns: stats?.turns ?? 0, // 件2a 同款守卫 —— park 帧多数不带 stats,不炸
|
|
258
289
|
stop_reason: null,
|
|
259
|
-
total_cost_usd: costOrNull(stats
|
|
290
|
+
total_cost_usd: costOrNull(stats),
|
|
260
291
|
usage,
|
|
261
292
|
modelUsage,
|
|
262
293
|
permission_denials: [],
|
|
@@ -280,7 +311,7 @@ export function doneToSdkResult(ev, ctx) {
|
|
|
280
311
|
is_error: true,
|
|
281
312
|
num_turns: stats?.turns ?? 0,
|
|
282
313
|
stop_reason: null,
|
|
283
|
-
total_cost_usd: costOrNull(stats
|
|
314
|
+
total_cost_usd: costOrNull(stats),
|
|
284
315
|
usage,
|
|
285
316
|
modelUsage,
|
|
286
317
|
permission_denials: [],
|
|
@@ -308,7 +339,7 @@ export function doneToSdkResult(ev, ctx) {
|
|
|
308
339
|
})(),
|
|
309
340
|
...degradedField,
|
|
310
341
|
stop_reason: null, // dropped (contract 02 §2.10)
|
|
311
|
-
total_cost_usd: costOrNull(stats
|
|
342
|
+
total_cost_usd: costOrNull(stats), // P1-5: 零成本 = "unconfigured pricing" → null, never a fake 0
|
|
312
343
|
usage,
|
|
313
344
|
// MF-25/P1-5 — the per-model usage split (wire `stats.modelUsage`, or the synthesized current-model row).
|
|
314
345
|
modelUsage,
|
|
@@ -79,6 +79,8 @@ export interface TaskRequestInput {
|
|
|
79
79
|
promptProfile?: string;
|
|
80
80
|
enableFork?: boolean;
|
|
81
81
|
attachments?: Record<string, unknown>;
|
|
82
|
+
/** 预上传附件句柄(`uploadAttachment` 回执 id)。空数组 = 没带附件 ⇒ 整键不 stamp。 */
|
|
83
|
+
attachmentIds?: readonly string[];
|
|
82
84
|
finalVerification?: boolean;
|
|
83
85
|
limits?: Record<string, unknown>;
|
|
84
86
|
interactiveTools?: false;
|
|
@@ -28,7 +28,12 @@ export const REQUEST_FIELD_MATRIX = [
|
|
|
28
28
|
{ field: 'finalVerification', lanes: ['print'], live: true, why: 'P1-1 终验:无人值守车道才需要引擎自证;交互 REPL 由人当场看结果。#106 裁 B(让位+告知)后交互面默认关' },
|
|
29
29
|
{ field: 'limits', lanes: ['print'], live: true, why: 'P2-3-b:`-p` 的预算护栏(--max-* flag 族),交互 REPL 由人随时 Esc' },
|
|
30
30
|
{ field: 'interactiveTools', lanes: ['print'], live: true, why: '[909]B 件3:无人值守 stamp false,从 roster 源头灭掉 AskUserQuestion/plan 门。交互车道 stamp false 等于自废武功' },
|
|
31
|
-
// ──
|
|
31
|
+
// ── interactive 车道独有 ────────────────────────────────────────────────────────────────────
|
|
32
|
+
// ⚠️ 「interactive」**不等于**「TUI」:web 的 BFF lane 也报 `interactive`
|
|
33
|
+
// (`sema-web-client` `WEB_REQUEST_LANE`)。下面多数条目的理由写的是壳的 TUI 面 —— 它们是
|
|
34
|
+
// B4 从壳的三个构造器逐行读出来的,那时这条车道只有壳一个消费者。`attachmentIds` 是**反过来**
|
|
35
|
+
// 的第一条:它今天只有 web/desktop 在发,壳反而没有这个入口。别把本节读成「壳独有」。
|
|
36
|
+
{ field: 'attachmentIds', lanes: ['interactive'], live: true, why: '附件**字节通道**(uploadAttachment 回执 id;server ≥1.289 绑定会话并把文件物化进 run 的 attachments/)。有上传入口的端才有 id 可引用:web/desktop 有,壳走 images / 本地文件路径,`-p` 车道连 uploadAttachment 都没有 ⇒ print 缺席是**没有来源**,不是漏。🔴 与上面的 `attachments` 同名不同物(那是 turn 边界的配置键),两条永远不许合并' },
|
|
32
37
|
{ field: 'settings.ultracode', lanes: ['interactive'], live: true, why: 'design/111:sticky `/effort ultracode` 拨盘 + 当轮关键词嗅探,两个来源都只在交互面存在', gap: true },
|
|
33
38
|
{ field: 'systemPrompt', lanes: ['interactive'], live: false, why: 'CC QueryParams.systemPrompt;print 腿的 params 没有这一位' },
|
|
34
39
|
{ field: 'reasoningEffort', lanes: ['interactive'], live: false, why: '`/effort` 拨盘存在 AppState,print 无 AppState', gap: true },
|
|
@@ -106,6 +111,10 @@ export function buildTaskRequest(input, lane) {
|
|
|
106
111
|
...(on('promptProfile', input.promptProfile) ? { promptProfile: input.promptProfile } : {}),
|
|
107
112
|
...(on('enableFork', input.enableFork) ? { enableFork: input.enableFork } : {}),
|
|
108
113
|
...(on('attachments', input.attachments) ? { attachments: input.attachments } : {}),
|
|
114
|
+
// 空数组按 `images` 同款处理:没带附件与「带了 0 个附件」在 wire 上是同一件事,发小的那个。
|
|
115
|
+
...(on('attachmentIds', input.attachmentIds) && (input.attachmentIds?.length ?? 0) > 0
|
|
116
|
+
? { attachmentIds: [...(input.attachmentIds ?? [])] }
|
|
117
|
+
: {}),
|
|
109
118
|
...(on('clientContext', input.clientContext) ? { clientContext: input.clientContext } : {}),
|
|
110
119
|
...(on('scratchpadDir', input.scratchpadDir) ? { scratchpadDir: input.scratchpadDir } : {}),
|
|
111
120
|
...(on('finalVerification', input.finalVerification)
|
package/dist/seatContract.d.ts
CHANGED
|
@@ -10,8 +10,12 @@
|
|
|
10
10
|
* 「接缝记账」里写下的第 1 条,它一直没被销账的原因就是没有任何机制会让它红。
|
|
11
11
|
*
|
|
12
12
|
* 落点为什么是本包:desktop 与 web 都已经依赖 `@sema-agent/client-core`(0.11.5),而本文件是
|
|
13
|
-
* **纯类型 + 常量 +
|
|
13
|
+
* **纯类型 + 常量 + 纯谓词**,零值级 import、零 Node 内建 ⇒ 不动本包的可移植闭包(portability 门的
|
|
14
14
|
* `EXPECTED_PACKAGES_INDEX` 一个字不变)。
|
|
15
|
+
* ⚠️ 唯一一条 `import type`(`./effortWire.js` 的 `ReasoningEffort`)是**类型边**:portability 门
|
|
16
|
+
* 走值级传递闭包时按规则剥掉 type-only import(门里 `/^\s*type\b/` 那一跳),bundle 里一个字节都
|
|
17
|
+
* 不多。写成 import 而不是就地复刻那七档,是因为「座位闭集」与「wire 投影闭集」必须是**同一套词**
|
|
18
|
+
* ——复刻一份就等于埋一条只有真用户能发现的漂移(拨盘上的档在座位 lane 上静默到不了引擎)。
|
|
15
19
|
*
|
|
16
20
|
* ── 搬迁时按「真源为准」收敛的漂移(逐条,web 侧镜像 → 本文件)────────────────────────────
|
|
17
21
|
* 🔴 D1 `LocalSessionEvent.outcome` —— web 镜像整位缺席 ⇒ `tool_permission_resolved` 只会清面,
|
|
@@ -50,6 +54,7 @@
|
|
|
50
54
|
* neutral typed position. Our implementation体 differs (sema wire via @sema-agent/sdk +
|
|
51
55
|
* @sema-agent/client-core), the contract shape does not.
|
|
52
56
|
*/
|
|
57
|
+
import type { ReasoningEffort } from "./effortWire.js";
|
|
53
58
|
export type EipcMethodKind = "invoke" | "event";
|
|
54
59
|
export interface EipcMethodSpec {
|
|
55
60
|
kind: EipcMethodKind;
|
|
@@ -258,6 +263,29 @@ export declare const PERMISSION_MODE_INTENTS: readonly PermissionModeIntent[];
|
|
|
258
263
|
/** Per-task attachment cap — the server's own limit (`attachmentIds` > 16 ⇒ 400). Gated here so the
|
|
259
264
|
* seat gets a precise local error instead of a wire 400 halfway through a turn. */
|
|
260
265
|
export declare const ATTACHMENT_IDS_PER_TASK_CAP = 16;
|
|
266
|
+
/** The per-turn `reasoningEffort` accept-set — core's ThinkingLevel tiers, re-exported from the
|
|
267
|
+
* package's own wire projection (`effortWire.ReasoningEffort`) rather than re-typed here.
|
|
268
|
+
*
|
|
269
|
+
* CLOSED for the same reason `PERMISSION_MODE_INTENTS` is: the word ORIGINATES in our own composer
|
|
270
|
+
* and travels OUT to a wire that 400s (fail-loud) on an unknown tier — so an unknown value is a
|
|
271
|
+
* local bug we want reported at the seat's door, not a future wire word to tolerate. `ultracode` is
|
|
272
|
+
* deliberately NOT a tier here: in CC it is a standalone `settings.ultracode` preset boolean that
|
|
273
|
+
* COEXISTS with `xhigh` (see `SeatTurnSettings`), and folding it into this axis is exactly how the
|
|
274
|
+
* orchestration axis gets eaten by the reasoning axis. */
|
|
275
|
+
export declare const SEAT_REASONING_EFFORTS: readonly ReasoningEffort[];
|
|
276
|
+
/** The `settings` sub-object a seat turn may carry. A CLOSED set with its own name list + pin,
|
|
277
|
+
* exactly like the top-level request: `SEND_MESSAGE_REQUEST_KEYS` checks `keyof SendMessageRequest`
|
|
278
|
+
* (top-level names), so a dotted `"settings.ultracode"` entry could never be pinned by `Covers` —
|
|
279
|
+
* the shape that stays consistent with the existing closed sets is one top-level key plus a nested
|
|
280
|
+
* closed set of its own. */
|
|
281
|
+
export interface SeatTurnSettings {
|
|
282
|
+
/** CC's `settings.ultracode` PRESET boolean (max thinking × workflow orchestration, service ≥1.48.0
|
|
283
|
+
* reads `body.settings.ultracode` and expands it). NOT a seventh effort tier — the dial separately
|
|
284
|
+
* coerces the reasoning axis to `xhigh`, and collapsing the two loses the orchestration half
|
|
285
|
+
* (`ultracodeWireCaps` in this package records that semantics verbatim). */
|
|
286
|
+
ultracode?: boolean;
|
|
287
|
+
}
|
|
288
|
+
export declare const SEAT_TURN_SETTINGS_KEYS: readonly ["ultracode"];
|
|
261
289
|
export interface SendMessageRequest {
|
|
262
290
|
sessionId: string;
|
|
263
291
|
text: string;
|
|
@@ -270,6 +298,23 @@ export interface SendMessageRequest {
|
|
|
270
298
|
* Bytes never ride this call: they went up once through the dedicated verb and the engine
|
|
271
299
|
* materializes them into the run's `attachments/` dir. */
|
|
272
300
|
attachmentIds?: string[];
|
|
301
|
+
/** Per-turn `/effort` dial pick → `TaskRequest.reasoningEffort`. Omit ⇒ the engine's own default.
|
|
302
|
+
* Closed set (`SEAT_REASONING_EFFORTS`) — gate it at the host's door, not at the wire.
|
|
303
|
+
*
|
|
304
|
+
* 🔴 Why this position exists (web 收编第一批, 2026-07-29): it did NOT, and the absence was
|
|
305
|
+
* STRUCTURAL — the seat lane's only payload is this closed-set interface, so the composer's effort
|
|
306
|
+
* dial had nowhere to put the user's pick and the web client honestly disabled the control on the
|
|
307
|
+
* desktop seat lane. "The control is missing" was the visible symptom; the missing wire position
|
|
308
|
+
* was the cause. */
|
|
309
|
+
reasoningEffort?: ReasoningEffort;
|
|
310
|
+
/** Keep this turn's background processes alive past the turn boundary → `TaskRequest.
|
|
311
|
+
* retainBackgroundProcesses`. Same structural-absence story as `reasoningEffort` above; the
|
|
312
|
+
* shell's lane defaults it ON (2026-07-26 flip), so a seat that cannot send it is not "defaulting
|
|
313
|
+
* to the same thing" — it is letting the ENGINE's default decide, which is a different decision. */
|
|
314
|
+
retainBackgroundProcesses?: boolean;
|
|
315
|
+
/** Per-turn settings sub-object → `TaskRequest.settings`. Closed shape (`SeatTurnSettings`);
|
|
316
|
+
* today's only member is the `ultracode` preset boolean. */
|
|
317
|
+
settings?: SeatTurnSettings;
|
|
273
318
|
}
|
|
274
319
|
/** `uploadAttachment` receipt — the SDK's `AttachmentInfo` verbatim (server POST /v1/attachments 201).
|
|
275
320
|
* `name` is the SERVER's sanitized basename, not the local filename: it is the name the engine
|
|
@@ -436,6 +481,6 @@ export declare const SEAT_EVENT_METHOD_NAMES: readonly ["onEvent", "onToolPermis
|
|
|
436
481
|
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"];
|
|
437
482
|
export declare const TOOL_PERMISSION_REQUEST_KEYS: readonly ["requestId", "sessionId", "toolName", "toolCallId", "input", "message", "boundCallId", "boundInputHash", "createdAt"];
|
|
438
483
|
export declare const LOCAL_SESSION_RECORD_KEYS: readonly ["sessionId", "engineSessionId", "model", "title", "isRunning", "createdAt", "lastActivityAt", "queuedMessages"];
|
|
439
|
-
export declare const SEND_MESSAGE_REQUEST_KEYS: readonly ["sessionId", "text", "model", "userMessageUuid", "permissionMode", "attachmentIds"];
|
|
484
|
+
export declare const SEND_MESSAGE_REQUEST_KEYS: readonly ["sessionId", "text", "model", "userMessageUuid", "permissionMode", "attachmentIds", "reasoningEffort", "retainBackgroundProcesses", "settings"];
|
|
440
485
|
export declare const TOOL_PERMISSION_DECISION_KEYS: readonly ["sessionId", "requestId", "decision", "answer", "updatedInput", "remember"];
|
|
441
486
|
export declare const START_SESSION_OPTION_KEYS: readonly ["model", "title", "cwd", "excludeTools"];
|
package/dist/seatContract.js
CHANGED
|
@@ -10,8 +10,12 @@
|
|
|
10
10
|
* 「接缝记账」里写下的第 1 条,它一直没被销账的原因就是没有任何机制会让它红。
|
|
11
11
|
*
|
|
12
12
|
* 落点为什么是本包:desktop 与 web 都已经依赖 `@sema-agent/client-core`(0.11.5),而本文件是
|
|
13
|
-
* **纯类型 + 常量 +
|
|
13
|
+
* **纯类型 + 常量 + 纯谓词**,零值级 import、零 Node 内建 ⇒ 不动本包的可移植闭包(portability 门的
|
|
14
14
|
* `EXPECTED_PACKAGES_INDEX` 一个字不变)。
|
|
15
|
+
* ⚠️ 唯一一条 `import type`(`./effortWire.js` 的 `ReasoningEffort`)是**类型边**:portability 门
|
|
16
|
+
* 走值级传递闭包时按规则剥掉 type-only import(门里 `/^\s*type\b/` 那一跳),bundle 里一个字节都
|
|
17
|
+
* 不多。写成 import 而不是就地复刻那七档,是因为「座位闭集」与「wire 投影闭集」必须是**同一套词**
|
|
18
|
+
* ——复刻一份就等于埋一条只有真用户能发现的漂移(拨盘上的档在座位 lane 上静默到不了引擎)。
|
|
15
19
|
*
|
|
16
20
|
* ── 搬迁时按「真源为准」收敛的漂移(逐条,web 侧镜像 → 本文件)────────────────────────────
|
|
17
21
|
* 🔴 D1 `LocalSessionEvent.outcome` —— web 镜像整位缺席 ⇒ `tool_permission_resolved` 只会清面,
|
|
@@ -124,6 +128,25 @@ export const PERMISSION_MODE_INTENTS = [
|
|
|
124
128
|
/** Per-task attachment cap — the server's own limit (`attachmentIds` > 16 ⇒ 400). Gated here so the
|
|
125
129
|
* seat gets a precise local error instead of a wire 400 halfway through a turn. */
|
|
126
130
|
export const ATTACHMENT_IDS_PER_TASK_CAP = 16;
|
|
131
|
+
/** The per-turn `reasoningEffort` accept-set — core's ThinkingLevel tiers, re-exported from the
|
|
132
|
+
* package's own wire projection (`effortWire.ReasoningEffort`) rather than re-typed here.
|
|
133
|
+
*
|
|
134
|
+
* CLOSED for the same reason `PERMISSION_MODE_INTENTS` is: the word ORIGINATES in our own composer
|
|
135
|
+
* and travels OUT to a wire that 400s (fail-loud) on an unknown tier — so an unknown value is a
|
|
136
|
+
* local bug we want reported at the seat's door, not a future wire word to tolerate. `ultracode` is
|
|
137
|
+
* deliberately NOT a tier here: in CC it is a standalone `settings.ultracode` preset boolean that
|
|
138
|
+
* COEXISTS with `xhigh` (see `SeatTurnSettings`), and folding it into this axis is exactly how the
|
|
139
|
+
* orchestration axis gets eaten by the reasoning axis. */
|
|
140
|
+
export const SEAT_REASONING_EFFORTS = [
|
|
141
|
+
"off",
|
|
142
|
+
"minimal",
|
|
143
|
+
"low",
|
|
144
|
+
"medium",
|
|
145
|
+
"high",
|
|
146
|
+
"xhigh",
|
|
147
|
+
"max",
|
|
148
|
+
];
|
|
149
|
+
export const SEAT_TURN_SETTINGS_KEYS = ["ultracode"];
|
|
127
150
|
// ───────────────────────────── validators (CC dual-gate posture) ─────────────────────────────
|
|
128
151
|
export function isLocalSessionRecord(s) {
|
|
129
152
|
const e = s;
|
|
@@ -381,6 +404,11 @@ export const SEND_MESSAGE_REQUEST_KEYS = [
|
|
|
381
404
|
"userMessageUuid",
|
|
382
405
|
"permissionMode",
|
|
383
406
|
"attachmentIds",
|
|
407
|
+
// 2026-07-29(web 收编第一批②):三位补齐。此前座位 lane **结构性**拿不到它们 —— 闭集就是
|
|
408
|
+
// 载体本身,不在集里 = 那个决定在这条 lane 上根本没有位置可放。
|
|
409
|
+
"reasoningEffort",
|
|
410
|
+
"retainBackgroundProcesses",
|
|
411
|
+
"settings",
|
|
384
412
|
];
|
|
385
413
|
export const TOOL_PERMISSION_DECISION_KEYS = [
|
|
386
414
|
"sessionId",
|
|
@@ -394,5 +422,6 @@ export const START_SESSION_OPTION_KEYS = ["model", "title", "cwd", "excludeTools
|
|
|
394
422
|
const _seatContractPins = [
|
|
395
423
|
true, true, true, true, true, true, true, true, true,
|
|
396
424
|
true, true, true, true, true, true, true, true,
|
|
425
|
+
true, true,
|
|
397
426
|
];
|
|
398
427
|
void _seatContractPins;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/client-core",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.8",
|
|
4
4
|
"description": "Client-side session runtime shared by every sema human client (TUI / web / desktop): sema wire frames (AgentEvent) -> CC session vocabulary (SDKMessage) with dual-plane output (transcript/chrome), deterministic transcript ids, lane discipline as a type, and the notification/dedup ledgers. Every CC-skin shape is collected here so the wire itself stays neutral. Blackboard [1832] design axioms; [1651]/[1652]/[1653] signed seam design. Renamed from @sema-agent/wire-cc-adapter (0.1.x).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@sema-agent/agent-types": "^0.2.0",
|
|
34
|
-
"@sema-agent/sdk": "^
|
|
34
|
+
"@sema-agent/sdk": "^1.1.0",
|
|
35
35
|
"esbuild": "^0.27.4",
|
|
36
36
|
"typescript": "^6.0.2"
|
|
37
37
|
}
|