@sema-agent/client-core 0.11.1 → 0.11.3

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.
@@ -219,7 +219,8 @@ function errCodes(e) {
219
219
  if (!e || typeof e !== 'object')
220
220
  return {};
221
221
  const o = e;
222
- return { code: o.errorCode ?? o.code, name: o.name, status: o.status ?? o.statusCode };
222
+ // [1912] errorCode 恒在(server ≥1.302 canonical)——`?? o.code` 老兜底已清;status 双键保留(HTTP 层形非 wire 键)。
223
+ return { code: o.errorCode, name: o.name, status: o.status ?? o.statusCode };
223
224
  }
224
225
  /** 409 `steering.not_running` / `SteeringNotRunningError` — the run is suspended/terminal (runs.ts:45). */
225
226
  function isSteeringNotRunning(e) {
@@ -248,7 +248,8 @@ function isBindingMismatch(e) {
248
248
  if (!e || typeof e !== 'object')
249
249
  return false;
250
250
  const o = e;
251
- const code = o.errorCode ?? o.code;
251
+ // [1912] errorCode 恒在(server ≥1.302 canonical;全端引擎达标线 ≥1.303)——`?? o.code` 老兜底已清。
252
+ const code = o.errorCode;
252
253
  if (code === 'approval_binding_mismatch')
253
254
  return true;
254
255
  // SDK throws a named ApprovalBindingMismatchError (index.ts:19).
@@ -88,6 +88,12 @@ export interface ToolApprovalFrame {
88
88
  type: 'tool_approval' | 'tool_approval_complete';
89
89
  approvalId: string;
90
90
  toolName?: string;
91
+ /** server ≥1.307([1940] 兑现 [1939],ADDITIVE):引擎 tool-call id——与 assistant 消息
92
+ * `tool_use` block 的 `call_…` 同一枚。**审批卡锚这个**,不锚 approvalId(现铸 uuidv7,流上
93
+ * 再无人提起 ⇒ 按它键的卡永不被回收)也不锚「最近一次 tool_start」(审批帧先于 tool_start
94
+ * 到达,契约 §4a-bis 实测 4020ms vs 4142ms)。`tool_approval_complete` 上刻意不带(免多锚
95
+ * 歧义)。旧 server 缺席 ⇒ 消费方保留 approvalId 兜底但必须能被真 id 收敛。 */
96
+ toolCallId?: string;
91
97
  message?: string;
92
98
  args?: unknown;
93
99
  argsOmitted?: boolean;
@@ -102,6 +108,12 @@ export interface ToolApprovalFrame {
102
108
  /** core 1.378 RB-39②:展示身份(UNTRUSTED-for-display,server redact 后上帧)——徽章名一手源。 */
103
109
  sourceAgentName?: string;
104
110
  }
111
+ /**
112
+ * 本地值拷贝的**运行时键集镜像**([1950]② 建议形):对账测试拿它与 SDK 0.1.6+ 的同源锚
113
+ * `TOOL_APPROVAL_FRAME_KEYS` 比对——SDK additive 增键时对账当天红,不再人肉追平。
114
+ * 下面两个类型钉保证镜像与 interface 本身不可能漂移(少键/多键都是编译错)。
115
+ */
116
+ export declare const TOOL_APPROVAL_FRAME_KEYS_MIRROR: readonly ["type", "approvalId", "toolCallId", "toolName", "sourceTaskId", "fromSubagent", "sourceAgentName", "message", "args", "argsOmitted", "outcome"];
105
117
  /** 子代帧判别:显式键 fromSubagent(core 1.378 RB-39②)优先;缺席退 sourceTaskId 在场性权宜式
106
118
  * (server 1.258 [1549]①3,旧代际兼容)。 */
107
119
  export declare function isFromSubagent(frame: ToolApprovalFrame): boolean;
@@ -158,6 +158,26 @@ export async function surfaceFsApprovalAndDecide(deps, taskId, argsByCall, signa
158
158
  }
159
159
  }
160
160
  }
161
+ /**
162
+ * 本地值拷贝的**运行时键集镜像**([1950]② 建议形):对账测试拿它与 SDK 0.1.6+ 的同源锚
163
+ * `TOOL_APPROVAL_FRAME_KEYS` 比对——SDK additive 增键时对账当天红,不再人肉追平。
164
+ * 下面两个类型钉保证镜像与 interface 本身不可能漂移(少键/多键都是编译错)。
165
+ */
166
+ export const TOOL_APPROVAL_FRAME_KEYS_MIRROR = [
167
+ 'type',
168
+ 'approvalId',
169
+ 'toolCallId',
170
+ 'toolName',
171
+ 'sourceTaskId',
172
+ 'fromSubagent',
173
+ 'sourceAgentName',
174
+ 'message',
175
+ 'args',
176
+ 'argsOmitted',
177
+ 'outcome',
178
+ ];
179
+ const _mirrorPin = [true, true];
180
+ void _mirrorPin;
161
181
  /** 子代帧判别:显式键 fromSubagent(core 1.378 RB-39②)优先;缺席退 sourceTaskId 在场性权宜式
162
182
  * (server 1.258 [1549]①3,旧代际兼容)。 */
163
183
  export function isFromSubagent(frame) {
@@ -47,6 +47,8 @@ export interface ToolEndResultArmLike {
47
47
  toolName?: unknown;
48
48
  isError?: unknown;
49
49
  output?: unknown;
50
+ /** 引擎 CC-shaped details(core 1.199+ AgentToolResult.details;Bash 时带 exitCode)。 */
51
+ structured?: unknown;
50
52
  truncated?: unknown;
51
53
  parentToolCallId?: unknown;
52
54
  uuid?: unknown;
@@ -25,12 +25,21 @@ export function flattenToolOutput(output) {
25
25
  * Bash 臂的 is_error 派生(真行为实证,2026-07-16):引擎 tool_end.isError 语义 = 「工具本身
26
26
  * 是否执行失败」——命令非零退出时工具照常返回模型面框架文本(core runShell `exit code: N\n---
27
27
  * stdout ---…`)且 isError:false。CC 2.1.207 的 Bash tool_result 对非零退出置 is_error:true;
28
- * 交互 REPL 桥已按同款派生(upstreamBridge.ts:384 `failed = isError || exitCode !== 0`)。
29
- * 这里对 Bash 输出的框架头做同源轻量嗅探(不拖 REPL 桥的重 import 图)。
28
+ * 交互 REPL 桥按同款派生。
29
+ *
30
+ * 🔴 语序与 toolResult.ts T11 逐字同款([1948] E4 / core RB-257,2026-07-29):
31
+ * **structured.exitCode 在场 ⇒ 权威直读;缺席 ⇒ 正则反解兜底**。此前只有正则——输出超
32
+ * 30000 字符溢写成 persisted-output 引用后,前缀把 `exit code: N` 挤出行首,锚失配 ⇒
33
+ * 非零退出照样 is_error:false(test AI 生产轨迹 2/2 命中);而 structured 字段在溢写时
34
+ * **完好保留**,正是为这种形准备的。兜底失锚时如实 false,绝不按内容嗅探瞎猜
35
+ * (与 core [1951] 同判断:拿前缀猜 isError = 用一个谎换另一个谎)。
30
36
  */
31
- function bashExitCodeFailed(toolName, text) {
37
+ function bashExitCodeFailed(toolName, text, structured) {
32
38
  if (typeof toolName !== 'string' || toolName.toLowerCase() !== 'bash')
33
39
  return false;
40
+ const ec = structured?.exitCode;
41
+ if (typeof ec === 'number')
42
+ return ec !== 0;
34
43
  const m = /^exit code: (\d+)\b/.exec(text);
35
44
  return m !== null && m[1] !== '0';
36
45
  }
@@ -52,7 +61,7 @@ export function toolEndResultToUserFrame(arm) {
52
61
  tool_use_id: arm.toolCallId,
53
62
  // truncated 输出如实标注(观察面注记;截断体绝不回喂模型——upstreamBridge 同款)。
54
63
  content: arm.truncated === true ? `${text}\n…(truncated)` : text,
55
- is_error: arm.isError === true || bashExitCodeFailed(arm.toolName, text),
64
+ is_error: arm.isError === true || bashExitCodeFailed(arm.toolName, text, arm.structured),
56
65
  },
57
66
  ],
58
67
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/client-core",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
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",
@@ -14,7 +14,7 @@
14
14
  "sideEffects": false,
15
15
  "scripts": {
16
16
  "build": "tsc -p tsconfig.json",
17
- "test": "node scripts/run-client-core-pure-test.mjs && node scripts/run-client-core-portability-test.mjs && node scripts/run-client-core-diff-test.mjs"
17
+ "test": "node scripts/run-client-core-pure-test.mjs && node scripts/run-client-core-portability-test.mjs && node scripts/run-client-core-diff-test.mjs && node scripts/run-print-bash-iserror-test.mjs && node scripts/run-approval-frame-keys-test.mjs"
18
18
  },
19
19
  "dependencies": {
20
20
  "diff": "^9.0.0"
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "devDependencies": {
27
27
  "@sema-agent/agent-types": "^0.2.0",
28
- "@sema-agent/sdk": "^0.1.0",
28
+ "@sema-agent/sdk": "^0.1.7",
29
29
  "esbuild": "^0.27.4",
30
30
  "typescript": "^6.0.2"
31
31
  }