@sema-agent/client-core 0.11.18 → 0.11.20
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
CHANGED
|
@@ -23,7 +23,7 @@ Renamed from **`@sema-agent/wire-cc-adapter`** (0.1.x, deprecated — see *Migra
|
|
|
23
23
|
|
|
24
24
|
## Scope
|
|
25
25
|
|
|
26
|
-
**Version:** 0.11.
|
|
26
|
+
**Version:** 0.11.20
|
|
27
27
|
|
|
28
28
|
- **Today** — the adapter seam, the whole `adapt()` pipeline (all 14 A-layer arms plus the
|
|
29
29
|
B/D/E tool-card layers), the notification/caps/model families, the adapter kernel (stream driver
|
|
@@ -22,16 +22,65 @@
|
|
|
22
22
|
* ── 'not-configured' 判别(诚实缺席纪律)────────────────────────────────────────────────────
|
|
23
23
|
* · fleet:面 gated off 时路由在任何帧之前答 **501**(typed)—— 501 ⇒ 'not-configured',
|
|
24
24
|
* 其它错 ⇒ 'unavailable'(拒绝形分档;错误判型走 controlRouter.errCodes 单源)。
|
|
25
|
-
* · assistant:无
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* caps 面自己不可达 ⇒ 判别缺席,**如实回 'ok'**(绝不编造判别)。🔴 残余缺口候引擎位:
|
|
29
|
-
* scheduler:true 而 run store 未配的 `{tasks:[]}` 仍与真空同形 —— 需要 wire 长出判别位
|
|
30
|
-
* (caps 或响应信封)才能收口,本实现不猜。
|
|
25
|
+
* · assistant:无 run store 时 worker 回 `{tasks:[]}` **原样透传** —— wire 上与真空不可区分。
|
|
26
|
+
* 能探则探:`GET /v1/capabilities` 的 **`approvals`** 位为 false ⇒ 'not-configured';
|
|
27
|
+
* caps 面自己不可达 ⇒ 判别缺席,**如实回 'ok'**(绝不编造判别)。
|
|
31
28
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
29
|
+
* 🔴 件 3 考据(读错键的定谳,小黑板 [C33]③.3 → server [C34],server 3.13.0 已把辖域写进
|
|
30
|
+
* 代码注与 ARCHITECTURE):本实现此前读 `scheduler`,那是**错的键**。
|
|
31
|
+
* · `/v1/assistant/*` 的挂载条件是 `checkpointStore`(server `routes/approvals-assistant.ts:67`
|
|
32
|
+
* 的分支头:`if (deps.checkpointStore && (url.startsWith("/v1/approvals") ||
|
|
33
|
+
* url.startsWith("/v1/assistant")))`),而 caps 里**同一个谓词**的键是 `approvals`
|
|
34
|
+
* (`capabilities.ts:56` `approvals: Boolean(deps.checkpointStore)`)。键名窄(approvals)、
|
|
35
|
+
* 辖域宽(整条 assistant 车道)——按名字猜会猜错,这是上游文档欠账不是消费端不小心。
|
|
36
|
+
* · `scheduler` 是**另一回事**:host 单用户腿的自唤醒 cron 工具(CronCreate/CronDelete/
|
|
37
|
+
* CronList),它对自己承诺的东西是诚实的,与「计划运行视图在不在」无关。
|
|
38
|
+
* · 实测后果(3.7.0 local 形,DB_BACKEND=local 无 DURABLE_APPROVAL):caps.scheduler=true 而
|
|
39
|
+
* `GET /v1/assistant/tasks`=404 ⇒ 面板**永久**渲「Scheduled runs can't be reached right now」。
|
|
40
|
+
* · 🔴 两个看似更省事的修法都**不采**(server [C34] 逐条否掉):(a) 把 404 并进
|
|
41
|
+
* not-configured —— 会吞掉「caps 说有路由却 404」这个真信号(真的漏注册/误删就再也看不见);
|
|
42
|
+
* (b) server 把 checkpointStore 与进 scheduler —— 会污染一个本来准确的键。
|
|
43
|
+
* **判别规则一个字没改,只改读哪个键。**
|
|
44
|
+
* · 🔴 换键**不**收口的残余缺口(照旧候引擎位,本实现不猜):`approvals:true`(checkpointStore
|
|
45
|
+
* 在)而 run store 未配时,worker 仍回 `{tasks:[]}` —— 那份空列表与「真的没有任务」在
|
|
46
|
+
* wire 上依旧同形。要收口需要 wire 长出判别位(caps 或响应信封),不是客户端能推出来的。
|
|
47
|
+
*
|
|
48
|
+
* 字段纪律:缺席=键不在场(undefined),🔴 绝不 `?? 0` / `?? false` / `?? ''`;ISO→epoch ms 只在
|
|
49
|
+
* assistant 行边界转一次(updatedAt/createdAt 同一个转换器,fleet 的 startedAt 本就是 epoch ms
|
|
50
|
+
* 直出);fleet 复合 id("<runId> <taskId>")整串不拆;fleet 子行(parentId 在场)不进 rows
|
|
51
|
+
* (子代不是用户的独立后台任务)。两源的时间锚是**两个不同的量**,各占各的契约位、互不顶替:
|
|
52
|
+
* assistant 给 `createdAtMs`(创建时刻)、fleet 给 `startedAtMs`(launch 时刻)——见 contract.ts
|
|
53
|
+
* 两处逐位说明。fleet 行的 `sessionId`/`scope` 被 server `stripT` 剥掉不上 wire,别在投影里等。
|
|
54
|
+
*
|
|
55
|
+
* ── 📋 下一批工单(件 4 调研,不在本批实现):BackgroundRow 的 canonical stop 能力判别 ────────
|
|
56
|
+
* 起因(小黑板 [C33]③.4):web 报「`runs.cancel` 的 id 空间是 taskId,而 fleet 顶层行 id 是 runId、
|
|
57
|
+
* 子行是复合 id」⇒ 他们对 fleet 行**不渲 Stop**(没有已挣得的取消路径就不摆按钮 —— 这个处置本身
|
|
58
|
+
* 是对的,server [C34] 也同意)。主会话裁定:**不是「fleet 行没有停止路径」,而是要按行类型分**。
|
|
59
|
+
* 下一批要落的形状(本批只调研落档,不新建 API):
|
|
60
|
+
* ① **能力判别**应当是行上的一等位(建议 `stop?: { verb, target }` 或等价判别),由包算、端只读
|
|
61
|
+
* —— 端各自判 = 每端一份猜测,正是本批修的那类病。缺席即「本行不可停」,端据此**显隐** Stop。
|
|
62
|
+
* ② **verb × id 映射**(包内既有件,全部已核实):
|
|
63
|
+
* · agent 行(fleet 顶层/子行):`runs.taskStop(hostRunId, handle)`,包内封装 =
|
|
64
|
+
* `src/subagent/engineTaskHandleWire.ts`(`POST /v1/runs/:id/tasks/:handle/stop?session=`)。
|
|
65
|
+
* **handle 取法**:复合 id `"<runId> <taskId>"` 取尾段 = 引擎 taskId —— 包内已有同语义实现
|
|
66
|
+
* `rowIdTail()`(`src/workflow.ts:24`,导出;`src/fleetAgentPanelProjection.ts:94` 有零依赖叶
|
|
67
|
+
* 的私有同款副本);宿主 run 解析走 `getBgParentRun(handle) ?? activeEngineRunId()`。
|
|
68
|
+
* **能力门** = `capabilities.taskHandles`(`src/subagent/engineRowStopGate.ts`
|
|
69
|
+
* `engineTaskHandlesCapable()`),🔴 别 trial-by-404。
|
|
70
|
+
* **回执纪律**(同文件 `engineRowNeedsStopConfirm()`):只有 **200 算停了**;409
|
|
71
|
+
* `stop.not_landed` / `stop.not_local` 一律保持原状(引擎里可能还在跑),端绝不自己翻 killed。
|
|
72
|
+
* · 顶层 durable run 行:`runs.cancel(taskId)`(包内 `controlRouter.cancel`,202 ack)。
|
|
73
|
+
* 🔴 但 **park 住的行不能走它**:suspended/needs_review 行要 cancel-by-DENY
|
|
74
|
+
* (`src/hitl/hitlBridge.ts:283` / `src/hitl/askGateWire.ts:417` 逐字纪律)——
|
|
75
|
+
* 所以「行在等人」(status==='waiting-on-human')时 stop 判别必须映射到决断面而不是 cancel。
|
|
76
|
+
* · workflow 行:**今天包/SDK 面上没有 workflow 的停止 verb** —— 实装 SDK 2.0.0 的
|
|
77
|
+
* `WorkflowsResource` 只有 list/get/journal/stream/steerAgent(逐个核过);而 `runs.d.ts:224`
|
|
78
|
+
* 写着「a workflow handle 404s — stop workflows via their cancel face」,那个 "cancel face"
|
|
79
|
+
* **不在 SDK 公面上**。⇒ 下一批第一步是找 server 把它钉出来(是 `runs.cancel(w* runId)`
|
|
80
|
+
* 还是独立端点),🔴 在拿到 server 的确证之前不许猜、不许在端上摆 Stop。
|
|
81
|
+
* ③ **不可停时端凭什么显隐**:凭①的键缺席,而**不是**凭 status —— 例如 'stopping' 行是「已经在
|
|
82
|
+
* 停」(不该再给 Stop),park 行是「要走决断面」,老引擎无 taskHandles 是「面不在」,三者语义
|
|
83
|
+
* 不同但都落在「不给 Stop」上;把它们压进一个 status 判断会在下一次加词时静默错。
|
|
35
84
|
*/
|
|
36
85
|
import type { AgentClient, AssistantTask, FleetTaskRow, FleetTaskStatus } from '@sema-agent/sdk';
|
|
37
86
|
import type { BackgroundRow, BackgroundSourceHealth, BackgroundStatus, BackgroundView, CreateBackgroundView } from './contract.js';
|
|
@@ -43,7 +92,9 @@ export declare function backgroundStatusFromAssistant(s: AssistantTask['status']
|
|
|
43
92
|
* 'running'(诚实取舍:它既不 queued 也不终态,更不是在等人)。 */
|
|
44
93
|
export declare function backgroundStatusFromFleet(s: FleetTaskStatus): BackgroundStatus;
|
|
45
94
|
/** 一行 AssistantTask → BackgroundRow。gate 是 `AssistantGate | null`(wire 显式 null 形)——
|
|
46
|
-
* null 折成键缺席,非 null 原引用透传(契约位是 unknown,包不重构造)。
|
|
95
|
+
* null 折成键缺席,非 null 原引用透传(契约位是 unknown,包不重构造)。
|
|
96
|
+
* 🔴 [C33]③.1 三键(name / sessionId / createdAtMs)按 wire 在场性投影:缺席=键缺席,绝不
|
|
97
|
+
* `?? 0` / `?? ''` —— 端渲的是「不知道」,不是「0 秒前创建的无名任务」。 */
|
|
47
98
|
export declare function assistantTaskToBackgroundRow(t: AssistantTask): BackgroundRow;
|
|
48
99
|
/** 一行 FleetTaskRow → BackgroundRow;子行(parentId 在场)⇒ null(调用方剔除)。
|
|
49
100
|
* 复合 id 不拆;`currentTool` 契约位是一行字符串 —— 优先 server 已 redact 的 `currentAction`
|
|
@@ -56,15 +56,28 @@ function isoToEpochMs(iso) {
|
|
|
56
56
|
const ms = Date.parse(iso);
|
|
57
57
|
return Number.isFinite(ms) ? ms : undefined;
|
|
58
58
|
}
|
|
59
|
+
/** 非空串才算「有值」:空串是「没有名字」,不是名字(占位归端)。 */
|
|
60
|
+
function nonEmptyString(v) {
|
|
61
|
+
return typeof v === 'string' && v !== '' ? v : undefined;
|
|
62
|
+
}
|
|
59
63
|
/** 一行 AssistantTask → BackgroundRow。gate 是 `AssistantGate | null`(wire 显式 null 形)——
|
|
60
|
-
* null 折成键缺席,非 null 原引用透传(契约位是 unknown,包不重构造)。
|
|
64
|
+
* null 折成键缺席,非 null 原引用透传(契约位是 unknown,包不重构造)。
|
|
65
|
+
* 🔴 [C33]③.1 三键(name / sessionId / createdAtMs)按 wire 在场性投影:缺席=键缺席,绝不
|
|
66
|
+
* `?? 0` / `?? ''` —— 端渲的是「不知道」,不是「0 秒前创建的无名任务」。 */
|
|
61
67
|
export function assistantTaskToBackgroundRow(t) {
|
|
68
|
+
const wire = t;
|
|
62
69
|
const updatedAtMs = isoToEpochMs(t.updatedAt);
|
|
70
|
+
const createdAtMs = isoToEpochMs(t.createdAt);
|
|
71
|
+
const name = nonEmptyString(wire.name);
|
|
72
|
+
const sessionId = nonEmptyString(t.sessionId);
|
|
63
73
|
return {
|
|
64
74
|
key: { source: 'assistant', taskId: t.taskId },
|
|
65
75
|
status: backgroundStatusFromAssistant(t.status),
|
|
66
76
|
...(updatedAtMs !== undefined ? { updatedAtMs } : {}),
|
|
77
|
+
...(createdAtMs !== undefined ? { createdAtMs } : {}),
|
|
78
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
67
79
|
needsAttention: t.needsAttention,
|
|
80
|
+
...(name !== undefined ? { name } : {}),
|
|
68
81
|
...(t.gate !== null ? { gate: t.gate } : {}),
|
|
69
82
|
};
|
|
70
83
|
}
|
|
@@ -81,9 +94,14 @@ export function fleetTaskToBackgroundRow(r) {
|
|
|
81
94
|
? `${r.currentTool.toolName}${r.currentTool.target !== undefined ? ` ${r.currentTool.target}` : ''}`
|
|
82
95
|
: undefined;
|
|
83
96
|
const parked = r.status === 'awaiting approval' || r.status === 'waiting' || r.awaitingPlanApproval === true;
|
|
97
|
+
// [C33]③.2 / server [C36]:launch 时刻 epoch ms(revive 行=本 revive 周期 wake 时刻),
|
|
98
|
+
// ADDITIVE / tolerate-absent —— 排队中的行本就没有,缺席即键缺席(0 不是「1970 年启动」)。
|
|
99
|
+
// 两腿同一个 mapper:`snapshot` 首帧行与 `task` 增量帧行(POST-MERGE FULL row)都过这里。
|
|
100
|
+
const startedAtMs = typeof r.startedAt === 'number' && r.startedAt > 0 ? r.startedAt : undefined;
|
|
84
101
|
return {
|
|
85
102
|
key: { source: 'fleet', rowId: r.id },
|
|
86
103
|
status: backgroundStatusFromFleet(r.status),
|
|
104
|
+
...(startedAtMs !== undefined ? { startedAtMs } : {}),
|
|
87
105
|
...(parked ? { needsAttention: true } : {}),
|
|
88
106
|
...(typeof r.name === 'string' && r.name !== '' ? { name: r.name } : {}),
|
|
89
107
|
...(typeof r.description === 'string' && r.description !== '' ? { description: r.description } : {}),
|
|
@@ -132,8 +150,8 @@ export function createBackgroundView(client, opts) {
|
|
|
132
150
|
let disposed = false;
|
|
133
151
|
let current = null;
|
|
134
152
|
let lastSerialized = null;
|
|
135
|
-
/** caps 探针结果:null = 还没探到/caps 面不可达(判别缺席);boolean =
|
|
136
|
-
let
|
|
153
|
+
/** caps 探针结果:null = 还没探到/caps 面不可达(判别缺席);boolean = approvals 位(见头注件 3)。 */
|
|
154
|
+
let capsApprovals = null;
|
|
137
155
|
const listeners = new Set();
|
|
138
156
|
const abort = new AbortController();
|
|
139
157
|
function notify() {
|
|
@@ -148,26 +166,30 @@ export function createBackgroundView(client, opts) {
|
|
|
148
166
|
}
|
|
149
167
|
}
|
|
150
168
|
}
|
|
151
|
-
/** caps 只需探到一次;失败保持 null 下轮重试(caps 面挂 ≠ assistant 面挂,判别缺席不编造)。
|
|
169
|
+
/** caps 只需探到一次;失败保持 null 下轮重试(caps 面挂 ≠ assistant 面挂,判别缺席不编造)。
|
|
170
|
+
* 🔴 读的是 `approvals` 不是 `scheduler` —— 考据见头注「'not-configured' 判别」节件 3。 */
|
|
152
171
|
async function probeCaps() {
|
|
153
|
-
if (
|
|
172
|
+
if (capsApprovals !== null)
|
|
154
173
|
return;
|
|
155
174
|
try {
|
|
156
175
|
const caps = await client.capabilities({ signal: abort.signal });
|
|
157
|
-
|
|
176
|
+
capsApprovals = caps.approvals === true;
|
|
158
177
|
}
|
|
159
178
|
catch (err) {
|
|
160
|
-
debugLog(`caps probe unavailable (
|
|
179
|
+
debugLog(`caps probe unavailable (approvals 判别缺席,保持 ok 口径): ${String(err)}`);
|
|
161
180
|
}
|
|
162
181
|
}
|
|
163
182
|
async function pullAssistant() {
|
|
164
183
|
try {
|
|
165
184
|
const { tasks } = await client.assistant.tasks({ signal: abort.signal });
|
|
166
|
-
return { health:
|
|
185
|
+
return { health: capsApprovals === false ? 'not-configured' : 'ok', tasks: tasks ?? [] };
|
|
167
186
|
}
|
|
168
187
|
catch (err) {
|
|
169
188
|
debugLog(`assistant.tasks degrade: ${String(err)}`);
|
|
170
|
-
|
|
189
|
+
// 🔴 只有 approvals:false(面本就没挂)与 501(路由自报 gated off)算 not-configured。
|
|
190
|
+
// 「caps 说有(approvals:true)却 404」**留在 unavailable** —— 那是两个真源对不上的报警,
|
|
191
|
+
// 吞掉它以后真的漏注册/误删路由就再也看不见了(server [C34] 明确否掉的修法 (a))。
|
|
192
|
+
const health = capsApprovals === false || isNotImplemented(err) ? 'not-configured' : 'unavailable';
|
|
171
193
|
return { health, tasks: [] };
|
|
172
194
|
}
|
|
173
195
|
}
|
|
@@ -130,6 +130,33 @@ export interface BackgroundRow {
|
|
|
130
130
|
readonly status: BackgroundStatus;
|
|
131
131
|
/** 统一 epoch ms;assistant 的 ISO 串只在边界转一次。 */
|
|
132
132
|
readonly updatedAtMs?: number;
|
|
133
|
+
/**
|
|
134
|
+
* 行**创建**时刻(统一 epoch ms)。语义 = 这一行是什么时候被排上的,不是什么时候开跑的。
|
|
135
|
+
* · assistant 臂:`AssistantTask.createdAt`(wire 是 ISO 串,与 updatedAt 同一个边界转换器);
|
|
136
|
+
* · fleet 臂:wire 上**没有这个量** ⇒ fleet 行恒缺席(fleet 给的是 {@link startedAtMs})。
|
|
137
|
+
* 缺席后果:端渲不出「排了多久」,必须不渲 —— 🔴 绝不 `?? Date.now()`/`?? 0` 冒充,也绝不拿
|
|
138
|
+
* updatedAtMs 顶替(那是「最后一次动」,不是「什么时候来的」)。
|
|
139
|
+
*/
|
|
140
|
+
readonly createdAtMs?: number;
|
|
141
|
+
/**
|
|
142
|
+
* 行**开跑**时刻(统一 epoch ms)= elapsed 的锚。
|
|
143
|
+
* · fleet 臂:`FleetTaskRow.startedAt`(server ≥1.250,fleet-bus.ts:94;launch 时刻,revive 行
|
|
144
|
+
* = 本 revive 周期的 wake 时刻)。契约级别 **ADDITIVE / tolerate-absent** —— 排队中的行本就
|
|
145
|
+
* 没有它(server 侧据此把显示态落 queued),消费端**不能当必填**。
|
|
146
|
+
* · assistant 臂:wire 上没有 launch 时刻 ⇒ assistant 行恒缺席(它给的是 {@link createdAtMs})。
|
|
147
|
+
* 为什么是它而不是 server 的 `elapsedMs`:后者是发帧那一刻的快照,客户端拿着自算会漂;
|
|
148
|
+
* 锚是绝对时刻才稳(server [C36])。缺席后果:端**不渲时长**(假 0s 比不渲更坏)。
|
|
149
|
+
*/
|
|
150
|
+
readonly startedAtMs?: number;
|
|
151
|
+
/**
|
|
152
|
+
* 这一行所属的引擎会话 id。语义 = 「跳到该会话 / 按会话归组」这类 affordance 的目标。
|
|
153
|
+
* · assistant 臂:`AssistantTask.sessionId`(wire 恒在场);
|
|
154
|
+
* · fleet 臂:server 在 `stripT`(routes/fleet.ts:95)里把 `sessionId`/`scope` 剥掉不上 wire
|
|
155
|
+
* ⇒ fleet 行恒缺席,别在投影里等它([C36] 事实②)。
|
|
156
|
+
* 缺席后果:那条跳转/归组的 affordance **必须显隐** —— 没有已挣得的目标就不摆入口
|
|
157
|
+
* (假 affordance 比没有更坏);🔴 绝不 `?? ''` 造一个空会话 id 出来。
|
|
158
|
+
*/
|
|
159
|
+
readonly sessionId?: string;
|
|
133
160
|
readonly needsAttention?: boolean;
|
|
134
161
|
readonly name?: string;
|
|
135
162
|
readonly description?: string;
|
|
@@ -48,6 +48,18 @@ export interface FleetTaskView {
|
|
|
48
48
|
toolName: string;
|
|
49
49
|
target?: string;
|
|
50
50
|
};
|
|
51
|
+
/**
|
|
52
|
+
* server ≥1.250 的 launch 真锚(epoch ms;ADDITIVE / tolerate-absent)。
|
|
53
|
+
*
|
|
54
|
+
* 🔴 **本键此前在这一层被丢弃** —— wire 有、`fleetLedger` 也读到了(只拿它算 `elapsedMs`,
|
|
55
|
+
* `fleetLedger.ts:447-448`),但投影视图不带它出去 ⇒ 下游拿不到 launch 时刻,只能锚「自己建行的
|
|
56
|
+
* 那一刻」,遗留/重挂的行就渲出 1h+ 的假时长(2026-07-31 用户实拍,五报清查报④)。
|
|
57
|
+
* 这是同一个 wire 键的**第四个投影面**:`fleetAgentPanelProjection`(面板事件)、
|
|
58
|
+
* `backgroundView`(web/桌面跨端视图)、本视图(fleet 树)、以及 ledger 内部的 elapsed 自算 ——
|
|
59
|
+
* 前两个先后补过,本层是最后一处([[new-data-source-systemic-checks]] ④:补一处不等于补齐)。
|
|
60
|
+
* 缺席 = 旧引擎/排队中的行,消费端必须容忍(禁 `?? 0`,0 不是「1970 年启动」)。
|
|
61
|
+
*/
|
|
62
|
+
startedAt?: number;
|
|
51
63
|
/**
|
|
52
64
|
* [1832] P1-2(server ≥1.290 / engine 1.432):发起本子代的父 tool_use id **原值**。
|
|
53
65
|
* B6 新落键 —— 归属不再靠猜,按 tool_use id 建卡树的消费端直接绑定。缺席 = 旧端。
|
|
@@ -236,6 +236,9 @@ export function projectTasks(allRows, opts) {
|
|
|
236
236
|
// 🔴 「键缺席」与「值为 0/''」是两件事 —— 只有真给了才落键(下游据「键在不在」判三态)。
|
|
237
237
|
...(toolUses !== undefined ? { toolUses } : {}),
|
|
238
238
|
...(transcriptId !== undefined ? { transcriptId } : {}),
|
|
239
|
+
// launch 真锚原值透传(> 0 才算有值)。ledger 拿它算 elapsedMs 是**另一件事** —— 下游要的是
|
|
240
|
+
// 时刻本身(自己的钟去减),elapsedMs 是发帧那一刻的快照,客户端存着会漂([C36] server 判据)。
|
|
241
|
+
...(typeof r.startedAt === 'number' && r.startedAt > 0 ? { startedAt: r.startedAt } : {}),
|
|
239
242
|
...(currentTool !== undefined ? { currentTool } : {}),
|
|
240
243
|
...(parentToolCallId !== undefined ? { parentToolCallId } : {}),
|
|
241
244
|
...(stoppedBy !== undefined ? { stoppedBy } : {}),
|
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.20",
|
|
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",
|