@sema-agent/server 7.2.0 → 7.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 +2 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +26 -1
- package/dist/approval-ask-machine.d.ts +39 -0
- package/dist/approval-ask-machine.js +101 -0
- package/dist/approval-card.d.ts +244 -0
- package/dist/approval-card.js +237 -0
- package/dist/approval-deny-reasons.d.ts +56 -0
- package/dist/approval-deny-reasons.js +54 -0
- package/dist/approval-reconciler.d.ts +174 -0
- package/dist/approval-reconciler.js +307 -0
- package/dist/boot/coordinators.d.ts +1 -0
- package/dist/boot/coordinators.js +39 -4
- package/dist/boot/deferred-sandbox-path-env.d.ts +99 -0
- package/dist/boot/deferred-sandbox-path-env.js +279 -0
- package/dist/boot/execution-env.js +11 -1
- package/dist/boot/lexical-path-env.d.ts +10 -0
- package/dist/boot/lexical-path-env.js +88 -0
- package/dist/boot/reapers.d.ts +34 -0
- package/dist/boot/reapers.js +198 -23
- package/dist/boot/resolve-spec.js +97 -33
- package/dist/capabilities/center-prompts.js +4 -1
- package/dist/capabilities/oa-tools.d.ts +15 -0
- package/dist/capabilities/oa-tools.js +54 -0
- package/dist/config-types.d.ts +68 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +138 -2
- package/dist/elicitation.d.ts +4 -0
- package/dist/elicitation.js +7 -3
- package/dist/finance/cost-taxonomy.d.ts +34 -0
- package/dist/finance/cost-taxonomy.js +26 -0
- package/dist/hooks/hook-runner.js +32 -0
- package/dist/http/routes/capabilities.js +14 -0
- package/dist/http/routes/diagnostics.d.ts +84 -0
- package/dist/http/routes/diagnostics.js +140 -0
- package/dist/http/routes/runs.d.ts +1 -0
- package/dist/http/routes/runs.js +548 -16
- package/dist/http/routes/tasks.js +175 -12
- package/dist/http/server.d.ts +6 -1
- package/dist/http/server.js +120 -4
- package/dist/http/sse-log.d.ts +51 -0
- package/dist/http/sse-log.js +64 -0
- package/dist/http/wire-types.d.ts +20 -5
- package/dist/main.js +35 -4
- package/dist/observability/fail-open.d.ts +98 -0
- package/dist/observability/fail-open.js +216 -0
- package/dist/observability/prompt-manifest.d.ts +13 -0
- package/dist/observability/prompt-manifest.js +8 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +38 -0
- package/dist/plugins/approval-ask-store-memory.js +299 -0
- package/dist/plugins/approval-ask-store-sql.d.ts +341 -0
- package/dist/plugins/approval-ask-store-sql.js +705 -0
- package/dist/plugins/approval-store-sql.d.ts +116 -0
- package/dist/plugins/approval-store-sql.js +151 -0
- package/dist/plugins/background-agent-store-sql.js +20 -1
- package/dist/plugins/checkpoint-store-sql.d.ts +84 -9
- package/dist/plugins/checkpoint-store-sql.js +297 -16
- package/dist/plugins/file-workflow-journal-store.d.ts +12 -0
- package/dist/plugins/file-workflow-journal-store.js +12 -0
- package/dist/plugins/local-checkpoint-store.d.ts +6 -5
- package/dist/plugins/local-checkpoint-store.js +4 -0
- package/dist/plugins/pg-approval-store.d.ts +9 -0
- package/dist/plugins/pg-approval-store.js +9 -0
- package/dist/plugins/pg-breaker-state.d.ts +8 -0
- package/dist/plugins/pg-breaker-state.js +8 -0
- package/dist/plugins/pg-checkpoint-store.d.ts +10 -0
- package/dist/plugins/pg-checkpoint-store.js +10 -0
- package/dist/plugins/pg-file-snapshot-store.d.ts +8 -0
- package/dist/plugins/pg-file-snapshot-store.js +8 -0
- package/dist/plugins/pg-image-bake.d.ts +12 -0
- package/dist/plugins/pg-image-bake.js +11 -0
- package/dist/plugins/pg-image-index.d.ts +12 -0
- package/dist/plugins/pg-image-index.js +11 -0
- package/dist/plugins/pg-outcome-ledger.d.ts +12 -0
- package/dist/plugins/pg-outcome-ledger.js +11 -0
- package/dist/plugins/pg-pool.js +11 -0
- package/dist/plugins/pg-resume-anchor-store.d.ts +7 -0
- package/dist/plugins/pg-resume-anchor-store.js +7 -0
- package/dist/plugins/pg-run-store.d.ts +9 -0
- package/dist/plugins/pg-run-store.js +9 -0
- package/dist/plugins/pg-session-policy-store.d.ts +7 -0
- package/dist/plugins/pg-session-policy-store.js +7 -0
- package/dist/plugins/pg-session-store.d.ts +12 -0
- package/dist/plugins/pg-session-store.js +12 -0
- package/dist/plugins/pg-tool-result-store.d.ts +9 -0
- package/dist/plugins/pg-tool-result-store.js +9 -0
- package/dist/plugins/pg-workflow-journal-store.d.ts +9 -0
- package/dist/plugins/pg-workflow-journal-store.js +9 -0
- package/dist/plugins/pg-workflow-run-store.d.ts +9 -0
- package/dist/plugins/pg-workflow-run-store.js +9 -0
- package/dist/plugins/store-backend.d.ts +18 -0
- package/dist/plugins/store-backend.js +10 -0
- package/dist/plugins/tidb-approval-store.d.ts +8 -0
- package/dist/plugins/tidb-approval-store.js +8 -0
- package/dist/plugins/tidb-breaker-state.d.ts +7 -0
- package/dist/plugins/tidb-breaker-state.js +7 -0
- package/dist/plugins/tidb-checkpoint-store.d.ts +9 -0
- package/dist/plugins/tidb-checkpoint-store.js +9 -0
- package/dist/plugins/tidb-file-snapshot-store.d.ts +8 -0
- package/dist/plugins/tidb-file-snapshot-store.js +8 -0
- package/dist/plugins/tidb-image-bake.d.ts +12 -0
- package/dist/plugins/tidb-image-bake.js +11 -0
- package/dist/plugins/tidb-image-index.d.ts +12 -0
- package/dist/plugins/tidb-image-index.js +11 -0
- package/dist/plugins/tidb-outcome-ledger.d.ts +12 -0
- package/dist/plugins/tidb-outcome-ledger.js +12 -0
- package/dist/plugins/tidb-pool.js +27 -4
- package/dist/plugins/tidb-resume-anchor-store.d.ts +7 -0
- package/dist/plugins/tidb-resume-anchor-store.js +7 -0
- package/dist/plugins/tidb-run-store.d.ts +10 -0
- package/dist/plugins/tidb-run-store.js +9 -0
- package/dist/plugins/tidb-session-policy-store.d.ts +7 -0
- package/dist/plugins/tidb-session-policy-store.js +7 -0
- package/dist/plugins/tidb-tool-result-store.d.ts +8 -0
- package/dist/plugins/tidb-tool-result-store.js +10 -0
- package/dist/plugins/tidb-workflow-journal-store.d.ts +9 -0
- package/dist/plugins/tidb-workflow-journal-store.js +9 -0
- package/dist/plugins/tidb-workflow-run-store.d.ts +10 -0
- package/dist/plugins/tidb-workflow-run-store.js +10 -0
- package/dist/plugins/workflow-journal-limits.d.ts +12 -0
- package/dist/plugins/workflow-journal-limits.js +12 -0
- package/dist/question.d.ts +21 -14
- package/dist/question.js +83 -34
- package/dist/runs.d.ts +16 -1
- package/dist/runs.js +61 -3
- package/dist/runtime-caps-resolver.d.ts +7 -1
- package/dist/runtime-caps-resolver.js +65 -3
- package/dist/sema-registry.d.ts +41 -0
- package/dist/sema-registry.js +40 -0
- package/dist/spec-fields.d.ts +4 -0
- package/dist/spec-fields.js +6 -0
- package/dist/task-settings.d.ts +36 -15
- package/dist/task-settings.js +19 -5
- package/dist/tool-approval.d.ts +296 -3
- package/dist/tool-approval.js +1074 -50
- package/dist/trace/core-keyset-guard.d.ts +2 -2
- package/dist/trace/ledger-sink.js +14 -1
- package/dist/trace/project.d.ts +90 -0
- package/dist/trace/project.js +188 -0
- package/package.json +5 -4
|
@@ -26,9 +26,9 @@ type _GuardBgNotif = AssertAllKeysHandled<Exclude<keyof BackgroundChildEvent, Bg
|
|
|
26
26
|
type RosterProjected = "name" | "agentId" | "sessionId" | "toolUseId" | "owner" | "scope" | "sessionScoped" | "rootSessionId" | "model" | "modelFallback" | "createdAt";
|
|
27
27
|
type _GuardRoster = AssertAllKeysHandled<Exclude<keyof RosterEntry, RosterProjected>>;
|
|
28
28
|
type AskProjected = "toolName" | "toolCallId" | "args" | "message" | "sourceTaskId" | "fromSubagent" | "sourceAgentName" | "delegation";
|
|
29
|
-
type AskExcluded = "preview" | "principal" | "requiresRealApproval";
|
|
29
|
+
type AskExcluded = "preview" | "principal" | "requiresRealApproval" | "riskAxes" | "boundInputHash";
|
|
30
30
|
type _GuardAsk = AssertAllKeysHandled<Exclude<keyof AskRequest, AskProjected | AskExcluded>>;
|
|
31
|
-
type TaskEventHandled = "text_delta" | "reasoning_delta" | "tool_start" | "tool_end" | "turn_end" | "compacted" | "diagnostics" | "message_committed" | "status" | "task_notification" | "task_progress" | "steering_injected" | "workspace_changed" | "done" | "context_usage" | "compaction_outcome";
|
|
31
|
+
type TaskEventHandled = "text_delta" | "reasoning_delta" | "tool_start" | "tool_end" | "turn_end" | "compacted" | "diagnostics" | "message_committed" | "status" | "task_notification" | "task_progress" | "steering_injected" | "workspace_changed" | "done" | "context_usage" | "compaction_outcome" | "human_input" | "wiring_manifest";
|
|
32
32
|
type _GuardTaskEvent = AssertAllKeysHandled<Exclude<TaskEvent["type"], TaskEventHandled>>;
|
|
33
33
|
export type CoreKeysetGuards = [_GuardNotification, _GuardBgNotif, _GuardRoster, _GuardAsk, _GuardTaskEvent];
|
|
34
34
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { redactSecrets } from "./redact.js";
|
|
2
|
-
import { toolStartEventData, toolEndEventData, taskProgressEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, workspaceChangedEventData, turnEndEventData, contextUsageEventData } from "./project.js";
|
|
2
|
+
import { toolStartEventData, toolEndEventData, taskProgressEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, workspaceChangedEventData, wiringManifestEventData, humanInputEventData, turnEndEventData, contextUsageEventData } from "./project.js";
|
|
3
3
|
import { NotifiedKeys, taskNotificationStreamKey } from "../orchestration/workflow-completion-inbox.js";
|
|
4
4
|
export function createLedgerSink(opts) {
|
|
5
5
|
const keys = opts.notifiedKeys ?? new NotifiedKeys();
|
|
@@ -114,6 +114,19 @@ export function createLedgerSink(opts) {
|
|
|
114
114
|
await flush();
|
|
115
115
|
await append("workspace_changed", workspaceChangedEventData(ev));
|
|
116
116
|
break;
|
|
117
|
+
case "wiring_manifest":
|
|
118
|
+
// 🔴 core 5.14.0 design/173:装配自证清单。账本行**同样**要剥 `governance` 段——durable 行可经
|
|
119
|
+
// `GET /v1/runs/:id/events` 重放给同一批租户订阅者,是与 sync 腿完全相同的泄露面,所以用**同一个**
|
|
120
|
+
// 构造器(两腿分头挑键就是下一次泄露的种子)。core 契约:no projection ⇒ do not disclose。
|
|
121
|
+
await flush();
|
|
122
|
+
await append("wiring_manifest", wiringManifestEventData(ev));
|
|
123
|
+
break;
|
|
124
|
+
case "human_input":
|
|
125
|
+
// core 5.14.0 design/171:人类输入生命周期账本(谁/经哪条载体/投递成没成)。落账是本臂的
|
|
126
|
+
// 正当用途——「这条 run 是谁喂的」正是事后对账要的历史事实;身份串的脱敏在共享构造器里。
|
|
127
|
+
await flush();
|
|
128
|
+
await append("human_input", humanInputEventData(ev));
|
|
129
|
+
break;
|
|
117
130
|
case "task_progress":
|
|
118
131
|
// core breakpoint⑤: a subagent's live progress tick → an INLINE "subagent working" card for the tailing
|
|
119
132
|
// client (S2-a). Shared whitelist+redact builder (+ E2 identity for the exact concurrent-tick binding).
|
package/dist/trace/project.d.ts
CHANGED
|
@@ -142,6 +142,7 @@ export declare function toolEndEventData(ev: {
|
|
|
142
142
|
* exactly by them; the 1.72 whitelist dropped them, leaving a FIFO heuristic). */
|
|
143
143
|
export declare function taskProgressEventData(ev: {
|
|
144
144
|
taskId: string;
|
|
145
|
+
taskType?: string;
|
|
145
146
|
parentTaskId?: string;
|
|
146
147
|
name?: string;
|
|
147
148
|
status?: string;
|
|
@@ -259,6 +260,95 @@ export declare function workspaceChangedEventData(ev: {
|
|
|
259
260
|
eventId?: string;
|
|
260
261
|
parentToolCallId?: string;
|
|
261
262
|
}): Record<string, unknown>;
|
|
263
|
+
/**
|
|
264
|
+
* `wiring_manifest`(core 5.14.0 design/173 新 `TaskEvent` 臂)—— 每条腿(root/child/resume)在 prepare
|
|
265
|
+
* 时自证「我到底接了什么线」的清单帧。
|
|
266
|
+
*
|
|
267
|
+
* 🔴 **本构造器存在的唯一理由是剥掉 `governance` 段**。core 给该段盖了 `audience: "operator"` 并成文
|
|
268
|
+
* 了服务层义务:*a serving layer forwarding this event to a multi-tenant stream MUST project the governance
|
|
269
|
+
* section for operators only; **no projection ⇒ do not disclose***。我方的三条腿(sync SSE / durable 账本 /
|
|
270
|
+
* resume 账本)都是租户可读面,而 operator 投影是 #154 的独立大件——按 core 写死的失败方向,**没有投影
|
|
271
|
+
* 就不得披露**,所以本批先把整段剥掉止泄(此前 sync 腿的裸 catch-all 会把它连同 `lockedConfig` /
|
|
272
|
+
* `compliance` / `memoryAdmission` / `retention` 四个治理面在场位原样透传给任意订阅者)。
|
|
273
|
+
* operator 投影是**另一个**构造器({@link wiringManifestOperatorEventData},live 腿按调用方身份挑),
|
|
274
|
+
* 不是往这里加键 —— 两条 durable 腿没有调用方身份可挑,所以它们恒用本构造器。
|
|
275
|
+
* ⚠️ 剥段还必须连**对该段取的哈希**一起剥:`configFingerprint` 同样不投影,理由见下方它那一行的旁注
|
|
276
|
+
* (无盐哈希 + 4 布尔 = 16 组合的谕示器,把「结构上藏起来」的段原样还原出来)。
|
|
277
|
+
*
|
|
278
|
+
* 其余段逐键挑(禁 `{...manifest}`:1.72 task_progress 教训——未来 core 加段必须由人显式处置,而不是
|
|
279
|
+
* 顺着 spread 裸上线,尤其当新段可能又是一个 audience 受限面时)。所有值都是引擎派生的闭枚举/布尔/
|
|
280
|
+
* 有限数/不透明摘要串,**非用户内容 ⇒ 不脱敏**;畸形值一律按缺席处理(不铸假值,与 compacted 同规)。
|
|
281
|
+
*
|
|
282
|
+
* 🔴 **未标签面的准入裁定逐面记录在此,缺省不是「放行」**(#154 裁定 C)。core 只给 `governance` 标了
|
|
283
|
+
* audience,其余段没有标签 —— 没标签**不等于**可以默认投给租户,每一段都要有一次人的裁定,写在这里:
|
|
284
|
+
* · `interaction.posture`(三值:interactive / headless / absent)—— **裁:租户可见**。它是部署形的
|
|
285
|
+
* 自述(这条腿有没有人能答问题),消费端据此决定渲不渲交互面;不是治理秘密,也不构成任何治理位的
|
|
286
|
+
* 侧信道(它不参与 governance 那 4 个布尔的还原)。
|
|
287
|
+
* 未来 core 加一段而它没有 audience 标签时,**先在这里补一条裁定再决定挑不挑键** —— 段级完备性钉
|
|
288
|
+
* (test/wiring-manifest-projection.test.ts)会在那一刻先把人拦下来。
|
|
289
|
+
*/
|
|
290
|
+
export declare function wiringManifestEventData(ev: {
|
|
291
|
+
manifest?: unknown;
|
|
292
|
+
eventId?: unknown;
|
|
293
|
+
parentToolCallId?: unknown;
|
|
294
|
+
}): Record<string, unknown>;
|
|
295
|
+
/**
|
|
296
|
+
* `wiring_manifest` 的 **operator 投影**(#154 件一)—— {@link wiringManifestEventData} 的租户形加上
|
|
297
|
+
* `governance` 段与 core 的真 `configFingerprint`。
|
|
298
|
+
*
|
|
299
|
+
* 🔴 分叉发生在**读口**,不在账本:两条 durable 腿(ledger-sink / resume)恒存剥后形,因为账本写的那一刻
|
|
300
|
+
* 不知道未来的读者是谁(`GET /v1/runs/:id/events` 任何 run owner 都读得到),往账本存全量 = 把 operator-only
|
|
301
|
+
* 面写进租户可读介质;存两份则是双写漂移源。所以只有 live 腿在**知道调用方身份**的那一刻挑构造器。
|
|
302
|
+
* 代价是 operator 看不到历史腿的 governance 段 —— 治理四布尔是部署形事实(不随 leg 漂),静态自检面
|
|
303
|
+
* (`GET /v1/diagnostics/wiring`)随时给出当前真值。
|
|
304
|
+
*
|
|
305
|
+
* 准入判据是 `explicitOperatorOk`(**不是** `isOperator`):空 `OPERATOR_PRINCIPALS` 必须是「没有人是
|
|
306
|
+
* operator」,不能是「所有人都是」—— 后者会让一个没配 operator 名单的部署把治理面发给每一个订阅者。
|
|
307
|
+
*
|
|
308
|
+
* `configFingerprint` 只在本构造器里透传:它是 `sha256(canonicalize(manifest 去 leg/去两个 provenance))`
|
|
309
|
+
* 前 16 hex,**无盐**且输入含整个 governance 段,而 governance 只有 4 个布尔 ⇒ 16 种组合。租户手里已有其余
|
|
310
|
+
* 全部哈希输入,发给租户等于把剥掉的四位原样还原(谕示器);发给 operator 无损 —— 同一份产物里四布尔本就
|
|
311
|
+
* 在场。
|
|
312
|
+
*
|
|
313
|
+
* governance **逐键挑**(禁 `{...governance}`):core 往这个段里加第五键时必须由人显式处置,而不是顺着
|
|
314
|
+
* spread 裸上线 —— 这个段的每一键都是部署治理面,新键的默认待遇必须是「不发」。
|
|
315
|
+
*/
|
|
316
|
+
export declare function wiringManifestOperatorEventData(ev: {
|
|
317
|
+
manifest?: unknown;
|
|
318
|
+
eventId?: unknown;
|
|
319
|
+
parentToolCallId?: unknown;
|
|
320
|
+
}): Record<string, unknown>;
|
|
321
|
+
/**
|
|
322
|
+
* `human_input`(core 5.14.0 design/171 新 `TaskEvent` 臂)—— 「谁把什么喂进了这条 run」的生命周期账本
|
|
323
|
+
* 帧(objective / 实时 steer / nextTurn / parked-steer 续跑 / wake 五个载体共用一个投影点)。
|
|
324
|
+
*
|
|
325
|
+
* 信任划线(与 tool_approval 帧同族):
|
|
326
|
+
* · `inputId` / `sessionSeq` / `carrier` / `source` / `delivery` / `entryId` —— 引擎铸的标识与枚举值,
|
|
327
|
+
* **非用户内容** ⇒ verbatim。注意本帧**不带正文**(core 的臂里就没有 text 字段),所以没有内容脱敏面。
|
|
328
|
+
* · `issuer` 与 `actor.id` / `actor.issuer` —— 宿主从入口凭据派生的**身份串**,自由文本形(`slack:U123`
|
|
329
|
+
* 这类命名空间串里可以嵌任何东西)⇒ 过 `redactSecrets`,与 `sourceAgentName` 同待遇。
|
|
330
|
+
* · `actor.hostAsserted` —— 布尔,verbatim。**它是消费端唯一能判「这个署名可信吗」的位**(core 的
|
|
331
|
+
* `[from …]` 渲染就是靠它决定加不加 `(unverified)`),剥掉它比剥掉 id 更坏:剩下一个看不出真假的名字。
|
|
332
|
+
* · `principal` —— **刻意不投影**(与 ToolApprovalFrame 的 `principal` 同裁):帧本就经 owner-scoped 流
|
|
333
|
+
* 投递,租户身份不必再由帧自述。要它请先提消费需求,别顺手加。
|
|
334
|
+
*
|
|
335
|
+
* `actor` 逐键挑(禁 spread):core 已声明 `ActorAssertion` 是冻结三键形,但白名单的意义正是「core 加第
|
|
336
|
+
* 四键时由人处置」——身份对象上多出来的键裸上线是本文件反复登记的病族。
|
|
337
|
+
* 形参全可选 `unknown` 的理由同 {@link wiringManifestEventData}(两条 durable 腿手里只有 `{type:string}`)。
|
|
338
|
+
*/
|
|
339
|
+
export declare function humanInputEventData(ev: {
|
|
340
|
+
inputId?: unknown;
|
|
341
|
+
sessionSeq?: unknown;
|
|
342
|
+
carrier?: unknown;
|
|
343
|
+
source?: unknown;
|
|
344
|
+
delivery?: unknown;
|
|
345
|
+
issuer?: unknown;
|
|
346
|
+
actor?: unknown;
|
|
347
|
+
principal?: unknown;
|
|
348
|
+
entryId?: unknown;
|
|
349
|
+
eventId?: unknown;
|
|
350
|
+
parentToolCallId?: unknown;
|
|
351
|
+
}): Record<string, unknown>;
|
|
262
352
|
/** S4 (SILENT-FALLBACK P0-a): the durable `brain_status` observation row, shared by the bg + resume append
|
|
263
353
|
* sites. core marks the live `status` frame EPHEMERAL (never replayed by core on resume) — this row is the
|
|
264
354
|
* SERVICE's own observation record (why a turn stalled: rate_limited/retrying/reconnecting/circuit_open),
|
package/dist/trace/project.js
CHANGED
|
@@ -175,6 +175,12 @@ export function toolEndEventData(ev) {
|
|
|
175
175
|
export function taskProgressEventData(ev) {
|
|
176
176
|
return {
|
|
177
177
|
taskId: ev.taskId,
|
|
178
|
+
// core 5.14.0([2854] 六车批②):委派种类判别键(core `DelegationTaskType` =
|
|
179
|
+
// "background_agent" | "workflow")—— 消费端据此路由一条 progress 帧,不必再从 id 形状猜。
|
|
180
|
+
// 形参取 `string` 而非闭枚举:该类型**没有**从 core 包根导出(亲验 index.d.ts 零命中,与发车帖
|
|
181
|
+
// 「新导出」的说法不符),抄一份闭集就是值拷贝漂移源;`stoppedBy` 先例同款——core 的开集串
|
|
182
|
+
// verbatim,消费端按契约容忍未知值。缺席=同步子代(无 fleet 行),缺席即不铸键。
|
|
183
|
+
...(typeof ev.taskType === "string" && ev.taskType.length > 0 ? { taskType: ev.taskType } : {}),
|
|
178
184
|
...(ev.parentTaskId ? { parentTaskId: ev.parentTaskId } : {}),
|
|
179
185
|
...(ev.name ? { name: redactSecrets(ev.name) } : {}),
|
|
180
186
|
// core [1414]#3 settle 终态 tick("completed"/"failed"——[1543]§三族B:此前被剥,消费方只见最后
|
|
@@ -333,6 +339,188 @@ export function workspaceChangedEventData(ev) {
|
|
|
333
339
|
...identityFields(ev),
|
|
334
340
|
};
|
|
335
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* `wiring_manifest`(core 5.14.0 design/173 新 `TaskEvent` 臂)—— 每条腿(root/child/resume)在 prepare
|
|
344
|
+
* 时自证「我到底接了什么线」的清单帧。
|
|
345
|
+
*
|
|
346
|
+
* 🔴 **本构造器存在的唯一理由是剥掉 `governance` 段**。core 给该段盖了 `audience: "operator"` 并成文
|
|
347
|
+
* 了服务层义务:*a serving layer forwarding this event to a multi-tenant stream MUST project the governance
|
|
348
|
+
* section for operators only; **no projection ⇒ do not disclose***。我方的三条腿(sync SSE / durable 账本 /
|
|
349
|
+
* resume 账本)都是租户可读面,而 operator 投影是 #154 的独立大件——按 core 写死的失败方向,**没有投影
|
|
350
|
+
* 就不得披露**,所以本批先把整段剥掉止泄(此前 sync 腿的裸 catch-all 会把它连同 `lockedConfig` /
|
|
351
|
+
* `compliance` / `memoryAdmission` / `retention` 四个治理面在场位原样透传给任意订阅者)。
|
|
352
|
+
* operator 投影是**另一个**构造器({@link wiringManifestOperatorEventData},live 腿按调用方身份挑),
|
|
353
|
+
* 不是往这里加键 —— 两条 durable 腿没有调用方身份可挑,所以它们恒用本构造器。
|
|
354
|
+
* ⚠️ 剥段还必须连**对该段取的哈希**一起剥:`configFingerprint` 同样不投影,理由见下方它那一行的旁注
|
|
355
|
+
* (无盐哈希 + 4 布尔 = 16 组合的谕示器,把「结构上藏起来」的段原样还原出来)。
|
|
356
|
+
*
|
|
357
|
+
* 其余段逐键挑(禁 `{...manifest}`:1.72 task_progress 教训——未来 core 加段必须由人显式处置,而不是
|
|
358
|
+
* 顺着 spread 裸上线,尤其当新段可能又是一个 audience 受限面时)。所有值都是引擎派生的闭枚举/布尔/
|
|
359
|
+
* 有限数/不透明摘要串,**非用户内容 ⇒ 不脱敏**;畸形值一律按缺席处理(不铸假值,与 compacted 同规)。
|
|
360
|
+
*
|
|
361
|
+
* 🔴 **未标签面的准入裁定逐面记录在此,缺省不是「放行」**(#154 裁定 C)。core 只给 `governance` 标了
|
|
362
|
+
* audience,其余段没有标签 —— 没标签**不等于**可以默认投给租户,每一段都要有一次人的裁定,写在这里:
|
|
363
|
+
* · `interaction.posture`(三值:interactive / headless / absent)—— **裁:租户可见**。它是部署形的
|
|
364
|
+
* 自述(这条腿有没有人能答问题),消费端据此决定渲不渲交互面;不是治理秘密,也不构成任何治理位的
|
|
365
|
+
* 侧信道(它不参与 governance 那 4 个布尔的还原)。
|
|
366
|
+
* 未来 core 加一段而它没有 audience 标签时,**先在这里补一条裁定再决定挑不挑键** —— 段级完备性钉
|
|
367
|
+
* (test/wiring-manifest-projection.test.ts)会在那一刻先把人拦下来。
|
|
368
|
+
*/
|
|
369
|
+
export function wiringManifestEventData(ev) {
|
|
370
|
+
// 形参照 `compactionOutcomeEventData` / `contextUsageEventData` 先例:全可选 `unknown` + 内部逐层窄化。
|
|
371
|
+
// 两个理由,不是风格:①三条腿里有两条(ledger-sink.onEvent / resume switch)手里只有 `{type:string}`,
|
|
372
|
+
// 窄形参会逼出 `as unknown as` 双铸型(类型卫生棘轮门当场红);②窄化在这里做,账本回放/第三方 producer
|
|
373
|
+
// 送来的畸形段也走同一道门,而不是只保护 live 腿。
|
|
374
|
+
const str = (v) => (typeof v === "string" && v.length > 0 ? v : undefined);
|
|
375
|
+
const bool = (v) => (typeof v === "boolean" ? v : undefined);
|
|
376
|
+
const num = (v) => (typeof v === "number" && Number.isFinite(v) ? v : undefined);
|
|
377
|
+
/** 段读:非对象即缺席(不铸空段)。 */
|
|
378
|
+
const sec = (v) => (typeof v === "object" && v !== null && !Array.isArray(v) ? { ...v } : undefined);
|
|
379
|
+
const nonEmpty = (o) => (Object.keys(o).length > 0 ? o : undefined);
|
|
380
|
+
const m = sec(ev.manifest) ?? {};
|
|
381
|
+
const askIn = sec(m.ask) ?? {};
|
|
382
|
+
const questionIn = sec(m.question) ?? {};
|
|
383
|
+
const elicitIn = sec(m.elicit) ?? {};
|
|
384
|
+
const parkIn = sec(m.parkLane) ?? {};
|
|
385
|
+
const sessionIn = sec(m.session) ?? {};
|
|
386
|
+
const fleetIn = sec(m.fleet) ?? {};
|
|
387
|
+
const legIn = sec(m.leg) ?? {};
|
|
388
|
+
const interactionIn = sec(m.interaction) ?? {};
|
|
389
|
+
const ask = nonEmpty({
|
|
390
|
+
...(str(askIn.form) !== undefined ? { form: askIn.form } : {}),
|
|
391
|
+
...(str(askIn.provenance) !== undefined ? { provenance: askIn.provenance } : {}),
|
|
392
|
+
...(str(askIn.effective) !== undefined ? { effective: askIn.effective } : {}),
|
|
393
|
+
});
|
|
394
|
+
const question = nonEmpty({
|
|
395
|
+
...(str(questionIn.wired) !== undefined ? { wired: questionIn.wired } : {}),
|
|
396
|
+
...(str(questionIn.provenance) !== undefined ? { provenance: questionIn.provenance } : {}),
|
|
397
|
+
// 组装谎言标(交互工具在场却没有投递面)——只在 core 真铸时带,缺席不折 false。
|
|
398
|
+
...(questionIn.interactiveToolsWithoutDeliveryFace === true ? { interactiveToolsWithoutDeliveryFace: true } : {}),
|
|
399
|
+
});
|
|
400
|
+
const elicit = nonEmpty({
|
|
401
|
+
...(bool(elicitIn.seamWired) !== undefined ? { seamWired: elicitIn.seamWired } : {}),
|
|
402
|
+
...(num(elicitIn.serversOptedIn) !== undefined ? { serversOptedIn: elicitIn.serversOptedIn } : {}),
|
|
403
|
+
});
|
|
404
|
+
const parkLane = nonEmpty({
|
|
405
|
+
...(bool(parkIn.capable) !== undefined ? { capable: parkIn.capable } : {}),
|
|
406
|
+
// `effective` 是三态(true / false / "unresolved")——布尔与字符串两支都得过。折成布尔会把
|
|
407
|
+
// 「还没定」谎报成「不能 park」,而那正是这个字段被造出来要区分的那一格。
|
|
408
|
+
...(bool(parkIn.effective) !== undefined || str(parkIn.effective) !== undefined ? { effective: parkIn.effective } : {}),
|
|
409
|
+
...(Array.isArray(parkIn.reasons) ? { reasons: parkIn.reasons.filter((r) => typeof r === "string") } : {}),
|
|
410
|
+
...(str(parkIn.checkpointDurability) !== undefined ? { checkpointDurability: parkIn.checkpointDurability } : {}),
|
|
411
|
+
});
|
|
412
|
+
const fleet = nonEmpty({
|
|
413
|
+
...(bool(fleetIn.backgroundAgentStore) !== undefined ? { backgroundAgentStore: fleetIn.backgroundAgentStore } : {}),
|
|
414
|
+
...(bool(fleetIn.hostChildEventSink) !== undefined ? { hostChildEventSink: fleetIn.hostChildEventSink } : {}),
|
|
415
|
+
});
|
|
416
|
+
return {
|
|
417
|
+
...(num(m.schemaVersion) !== undefined ? { schemaVersion: m.schemaVersion } : {}),
|
|
418
|
+
...(str(legIn.kind) !== undefined ? { leg: { kind: legIn.kind } } : {}),
|
|
419
|
+
...(ask !== undefined ? { ask } : {}),
|
|
420
|
+
...(question !== undefined ? { question } : {}),
|
|
421
|
+
...(str(interactionIn.posture) !== undefined ? { interaction: { posture: interactionIn.posture } } : {}),
|
|
422
|
+
...(elicit !== undefined ? { elicit } : {}),
|
|
423
|
+
...(parkLane !== undefined ? { parkLane } : {}),
|
|
424
|
+
...(str(sessionIn.store) !== undefined ? { session: { store: sessionIn.store } } : {}),
|
|
425
|
+
...(fleet !== undefined ? { fleet } : {}),
|
|
426
|
+
// governance —— **刻意不在此**(见头注:受众标 operator,无投影不披露)。
|
|
427
|
+
// configFingerprint —— **也刻意不在此**(codex 复审 2026-08-06 F1,验真后采纳)。剥掉一个段却把
|
|
428
|
+
// **对它取的哈希**发出去,等于没剥:core 的算法是
|
|
429
|
+
// `sha256(canonicalize(manifest 去掉 leg 与两个 provenance))` 取前 16 hex —— 无盐、输入里含整个
|
|
430
|
+
// governance 段,而 governance 只有 4 个布尔(audience 是常量)⇒ **16 种组合**。租户手里已经有其余
|
|
431
|
+
// 全部哈希输入(它们正是我们投影出去的那些段),把 16 种组合逐个拼进去重算一遍即可比中,
|
|
432
|
+
// lockedConfig / compliance / memoryAdmission / retention 四位当场还原。
|
|
433
|
+
// 「结构上藏起来、经哈希谕示器泄出去」仍然是泄出去,core 写死的失败方向(no projection ⇒ do not
|
|
434
|
+
// disclose)对侧信道一样适用。它的广告用途(判两条腿是不是同一套装配)在本仓与 SDK **今天零消费端**,
|
|
435
|
+
// 所以直接不发,而不是另铸一个「只对已投影字段取哈希」的服务端自造值(那是新 wire 语义,要跨仓对表)。
|
|
436
|
+
// 带 core 真 fingerprint 的是 {@link wiringManifestOperatorEventData}(explicitOperatorOk 为真的 live
|
|
437
|
+
// 连接才走那条),对那个受众而言四布尔本就在同一份产物里,哈希不再是侧信道。
|
|
438
|
+
...identityFields(ev),
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* `wiring_manifest` 的 **operator 投影**(#154 件一)—— {@link wiringManifestEventData} 的租户形加上
|
|
443
|
+
* `governance` 段与 core 的真 `configFingerprint`。
|
|
444
|
+
*
|
|
445
|
+
* 🔴 分叉发生在**读口**,不在账本:两条 durable 腿(ledger-sink / resume)恒存剥后形,因为账本写的那一刻
|
|
446
|
+
* 不知道未来的读者是谁(`GET /v1/runs/:id/events` 任何 run owner 都读得到),往账本存全量 = 把 operator-only
|
|
447
|
+
* 面写进租户可读介质;存两份则是双写漂移源。所以只有 live 腿在**知道调用方身份**的那一刻挑构造器。
|
|
448
|
+
* 代价是 operator 看不到历史腿的 governance 段 —— 治理四布尔是部署形事实(不随 leg 漂),静态自检面
|
|
449
|
+
* (`GET /v1/diagnostics/wiring`)随时给出当前真值。
|
|
450
|
+
*
|
|
451
|
+
* 准入判据是 `explicitOperatorOk`(**不是** `isOperator`):空 `OPERATOR_PRINCIPALS` 必须是「没有人是
|
|
452
|
+
* operator」,不能是「所有人都是」—— 后者会让一个没配 operator 名单的部署把治理面发给每一个订阅者。
|
|
453
|
+
*
|
|
454
|
+
* `configFingerprint` 只在本构造器里透传:它是 `sha256(canonicalize(manifest 去 leg/去两个 provenance))`
|
|
455
|
+
* 前 16 hex,**无盐**且输入含整个 governance 段,而 governance 只有 4 个布尔 ⇒ 16 种组合。租户手里已有其余
|
|
456
|
+
* 全部哈希输入,发给租户等于把剥掉的四位原样还原(谕示器);发给 operator 无损 —— 同一份产物里四布尔本就
|
|
457
|
+
* 在场。
|
|
458
|
+
*
|
|
459
|
+
* governance **逐键挑**(禁 `{...governance}`):core 往这个段里加第五键时必须由人显式处置,而不是顺着
|
|
460
|
+
* spread 裸上线 —— 这个段的每一键都是部署治理面,新键的默认待遇必须是「不发」。
|
|
461
|
+
*/
|
|
462
|
+
export function wiringManifestOperatorEventData(ev) {
|
|
463
|
+
// 租户形整体复用(不是复制一份键表):operator 面 ⊇ 租户面 是结构性的,两个构造器不可能在共有段上漂。
|
|
464
|
+
const tenant = wiringManifestEventData(ev);
|
|
465
|
+
// 窄读器与租户构造器内的孪生同形而独立 —— 那只构造器被 16 组合谕示器钉钉着,本件不改它一个字节。
|
|
466
|
+
const str = (v) => (typeof v === "string" && v.length > 0 ? v : undefined);
|
|
467
|
+
const bool = (v) => (typeof v === "boolean" ? v : undefined);
|
|
468
|
+
const sec = (v) => (typeof v === "object" && v !== null && !Array.isArray(v) ? { ...v } : undefined);
|
|
469
|
+
const m = sec(ev.manifest) ?? {};
|
|
470
|
+
const g = sec(m.governance) ?? {};
|
|
471
|
+
const governance = {
|
|
472
|
+
...(str(g.audience) !== undefined ? { audience: g.audience } : {}),
|
|
473
|
+
...(bool(g.lockedConfig) !== undefined ? { lockedConfig: g.lockedConfig } : {}),
|
|
474
|
+
...(bool(g.compliance) !== undefined ? { compliance: g.compliance } : {}),
|
|
475
|
+
...(bool(g.memoryAdmission) !== undefined ? { memoryAdmission: g.memoryAdmission } : {}),
|
|
476
|
+
...(bool(g.retention) !== undefined ? { retention: g.retention } : {}),
|
|
477
|
+
};
|
|
478
|
+
return {
|
|
479
|
+
...tenant,
|
|
480
|
+
...(Object.keys(governance).length > 0 ? { governance } : {}),
|
|
481
|
+
...(str(m.configFingerprint) !== undefined ? { configFingerprint: m.configFingerprint } : {}),
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* `human_input`(core 5.14.0 design/171 新 `TaskEvent` 臂)—— 「谁把什么喂进了这条 run」的生命周期账本
|
|
486
|
+
* 帧(objective / 实时 steer / nextTurn / parked-steer 续跑 / wake 五个载体共用一个投影点)。
|
|
487
|
+
*
|
|
488
|
+
* 信任划线(与 tool_approval 帧同族):
|
|
489
|
+
* · `inputId` / `sessionSeq` / `carrier` / `source` / `delivery` / `entryId` —— 引擎铸的标识与枚举值,
|
|
490
|
+
* **非用户内容** ⇒ verbatim。注意本帧**不带正文**(core 的臂里就没有 text 字段),所以没有内容脱敏面。
|
|
491
|
+
* · `issuer` 与 `actor.id` / `actor.issuer` —— 宿主从入口凭据派生的**身份串**,自由文本形(`slack:U123`
|
|
492
|
+
* 这类命名空间串里可以嵌任何东西)⇒ 过 `redactSecrets`,与 `sourceAgentName` 同待遇。
|
|
493
|
+
* · `actor.hostAsserted` —— 布尔,verbatim。**它是消费端唯一能判「这个署名可信吗」的位**(core 的
|
|
494
|
+
* `[from …]` 渲染就是靠它决定加不加 `(unverified)`),剥掉它比剥掉 id 更坏:剩下一个看不出真假的名字。
|
|
495
|
+
* · `principal` —— **刻意不投影**(与 ToolApprovalFrame 的 `principal` 同裁):帧本就经 owner-scoped 流
|
|
496
|
+
* 投递,租户身份不必再由帧自述。要它请先提消费需求,别顺手加。
|
|
497
|
+
*
|
|
498
|
+
* `actor` 逐键挑(禁 spread):core 已声明 `ActorAssertion` 是冻结三键形,但白名单的意义正是「core 加第
|
|
499
|
+
* 四键时由人处置」——身份对象上多出来的键裸上线是本文件反复登记的病族。
|
|
500
|
+
* 形参全可选 `unknown` 的理由同 {@link wiringManifestEventData}(两条 durable 腿手里只有 `{type:string}`)。
|
|
501
|
+
*/
|
|
502
|
+
export function humanInputEventData(ev) {
|
|
503
|
+
const str = (v) => (typeof v === "string" && v.length > 0 ? v : undefined);
|
|
504
|
+
const a = typeof ev.actor === "object" && ev.actor !== null && !Array.isArray(ev.actor) ? { ...ev.actor } : {};
|
|
505
|
+
const actor = {
|
|
506
|
+
...(str(a.id) !== undefined ? { id: redactSecrets(String(a.id)) } : {}),
|
|
507
|
+
...(typeof a.hostAsserted === "boolean" ? { hostAsserted: a.hostAsserted } : {}),
|
|
508
|
+
...(str(a.issuer) !== undefined ? { issuer: redactSecrets(String(a.issuer)) } : {}),
|
|
509
|
+
};
|
|
510
|
+
return {
|
|
511
|
+
// 缺键守卫同 compactionOutcomeEventData:无条件 String() 会把缺席铸成字面 "undefined" 落进 durable 行,
|
|
512
|
+
// 回放端读到一个看起来合法的 id/枚举值,比缺席更难发现。
|
|
513
|
+
...(str(ev.inputId) !== undefined ? { inputId: ev.inputId } : {}),
|
|
514
|
+
...(typeof ev.sessionSeq === "number" && Number.isFinite(ev.sessionSeq) ? { sessionSeq: ev.sessionSeq } : {}),
|
|
515
|
+
...(str(ev.carrier) !== undefined ? { carrier: ev.carrier } : {}),
|
|
516
|
+
...(str(ev.source) !== undefined ? { source: ev.source } : {}),
|
|
517
|
+
...(str(ev.delivery) !== undefined ? { delivery: ev.delivery } : {}),
|
|
518
|
+
...(str(ev.issuer) !== undefined ? { issuer: redactSecrets(String(ev.issuer)) } : {}),
|
|
519
|
+
...(Object.keys(actor).length > 0 ? { actor } : {}),
|
|
520
|
+
...(str(ev.entryId) !== undefined ? { entryId: ev.entryId } : {}),
|
|
521
|
+
...identityFields(ev),
|
|
522
|
+
};
|
|
523
|
+
}
|
|
336
524
|
/** S4 (SILENT-FALLBACK P0-a): the durable `brain_status` observation row, shared by the bg + resume append
|
|
337
525
|
* sites. core marks the live `status` frame EPHEMERAL (never replayed by core on resume) — this row is the
|
|
338
526
|
* SERVICE's own observation record (why a turn stalled: rate_limited/retrying/reconnecting/circuit_open),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sema-agent/server",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.0",
|
|
4
4
|
"description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@sema-agent/core": "^5.
|
|
57
|
+
"@sema-agent/core": "^5.16.0",
|
|
58
58
|
"@sema-agent/registry-core": "^0.16.0",
|
|
59
59
|
"e2b": "^2.28.0",
|
|
60
60
|
"libsodium-wrappers": "^0.8.4",
|
|
@@ -62,13 +62,14 @@
|
|
|
62
62
|
"pg": "^8.22.0",
|
|
63
63
|
"ssh2": "^1.17.0",
|
|
64
64
|
"typebox": "1.1.39",
|
|
65
|
-
"ws": "^8.21.0"
|
|
65
|
+
"ws": "^8.21.0",
|
|
66
|
+
"zod": "^4.4.3"
|
|
66
67
|
},
|
|
67
68
|
"optionalDependencies": {
|
|
68
69
|
"sharp": "^0.35.3"
|
|
69
70
|
},
|
|
70
71
|
"devDependencies": {
|
|
71
|
-
"@sema-agent/sdk": "^6.
|
|
72
|
+
"@sema-agent/sdk": "^6.7.0",
|
|
72
73
|
"@types/libsodium-wrappers": "^0.7.14",
|
|
73
74
|
"@types/node": "22.10.2",
|
|
74
75
|
"@types/pg": "^8.20.0",
|