@sema-agent/server 7.125.1 → 7.127.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/MIGRATION.md +229 -2
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/USAGE.md +346 -145
- package/deploy/sema-up/README.md +1 -1
- package/deploy/sema-up/chart/templates/networkpolicy-sandbox.yaml +57 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +32 -1
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +3 -2
- package/deploy/sema-up/chart/templates/server.yaml +2 -1
- package/deploy/sema-up/chart/values.yaml +22 -0
- package/deploy/sema-up/cluster-up.sh +10 -10
- package/deploy/sema-up/kube-up.sh +20 -13
- package/deploy/sema-up/lib/dataroot.sh +1 -1
- package/deploy/sema-up/lib/envf.sh +5 -5
- package/deploy/sema-up/lib/flagshape.sh +5 -5
- package/deploy/sema-up/lib/lanes.py +1 -1
- package/deploy/sema-up/lib/node-addrs.sh +42 -0
- package/deploy/sema-up/lib/parse-machines.py +2 -2
- package/deploy/sema-up/lib/shell-access.sh +1 -1
- package/deploy/sema-up/preflight.sh +4 -4
- package/deploy/sema-up/sema-up.sh +33 -33
- package/deploy/sema-up/smoke.sh +3 -3
- package/deploy/sema-up/stack/compose.yaml +1 -1
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +26 -3
- package/dist/approval-card.d.ts +20 -4
- package/dist/approval-content-kind.d.ts +38 -22
- package/dist/approval-content-kind.js +20 -4
- package/dist/audit.js +3 -0
- package/dist/bench/s1/arms.d.ts +9 -37
- package/dist/bench/s1/arms.js +4 -61
- package/dist/bench/s1/live-deps.d.ts +4 -10
- package/dist/bench/s1/live-deps.js +1 -222
- package/dist/bench/s1/oracle.d.ts +1 -1
- package/dist/bench/s1/reviewer.d.ts +1 -1
- package/dist/bench/s1/row.d.ts +5 -7
- package/dist/bench/s1/row.js +0 -2
- package/dist/bench/s1/run-firm.d.ts +2 -2
- package/dist/bench/s1/run-firm.js +1 -4
- package/dist/bench/s1/runner-ctx.d.ts +17 -29
- package/dist/bench/s1/runner-ctx.js +3 -7
- package/dist/bench/s1/tasks.d.ts +9 -46
- package/dist/bench/s1/tasks.js +4 -63
- package/dist/boot/execution-env.d.ts +38 -26
- package/dist/boot/execution-env.js +87 -41
- package/dist/boot/leader.d.ts +2 -1
- package/dist/boot/memory-boundary.d.ts +1 -1
- package/dist/boot/memory-consolidation.d.ts +37 -3
- package/dist/boot/memory-consolidation.js +18 -2
- package/dist/boot/parked-revive-gate.d.ts +0 -3
- package/dist/boot/parked-revive-gate.js +2 -2
- package/dist/boot/resolve-spec.d.ts +0 -2
- package/dist/boot/resolve-spec.js +12 -17
- package/dist/boot/retention-lane.d.ts +12 -1
- package/dist/boot/retention-lane.js +2 -0
- package/dist/boot/runner-deps.d.ts +7 -6
- package/dist/boot/runner-deps.js +5 -16
- package/dist/boot/session-faces.d.ts +7 -2
- package/dist/boot/session-faces.js +37 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +2 -2
- package/dist/boot/stage-05-execution-env.js +7 -4
- package/dist/boot/stage-06-runners.d.ts +2 -3
- package/dist/boot/stage-06-runners.js +13 -9
- package/dist/boot/stage-07-capability-layer.d.ts +2 -3
- package/dist/boot/stage-07-capability-layer.js +3 -4
- package/dist/boot/stage-08-reapers.d.ts +2 -3
- package/dist/boot/stage-08-reapers.js +2 -2
- package/dist/boot/stage-09-leader.d.ts +2 -3
- package/dist/boot/stage-09-leader.js +2 -1
- package/dist/boot/stage-10-http-server.d.ts +2 -3
- package/dist/boot/stage-10-http-server.js +2 -2
- package/dist/boot/stores.d.ts +1 -0
- package/dist/boot/stores.js +4 -3
- package/dist/boot/web-admin.d.ts +5 -0
- package/dist/boot/web-admin.js +28 -14
- package/dist/brain.d.ts +2 -2
- package/dist/brain.js +1 -1
- package/dist/capabilities/builtin-tools.d.ts +2 -1
- package/dist/capabilities/composite-members.d.ts +1 -1
- package/dist/capabilities/composite-members.js +1 -1
- package/dist/capabilities/hands-lane.d.ts +9 -6
- package/dist/capabilities/hands-lane.js +2 -2
- package/dist/capabilities/memory-notice.d.ts +27 -22
- package/dist/capabilities/memory-notice.js +15 -17
- package/dist/capabilities/scenarios.d.ts +9 -14
- package/dist/capabilities/scenarios.js +5 -50
- package/dist/capability-facts.d.ts +22 -11
- package/dist/capability-facts.js +13 -6
- package/dist/config-catalog.js +14 -5
- package/dist/config-provider.d.ts +5 -1
- package/dist/config-provider.js +23 -4
- package/dist/config-types.d.ts +19 -2
- package/dist/config.js +41 -6
- package/dist/deployment-governance.d.ts +19 -21
- package/dist/deployment-governance.js +7 -8
- package/dist/env-name-allowlist-knobs.d.ts +5 -5
- package/dist/env-name-allowlist-knobs.js +1 -0
- package/dist/execution-lane-caps.d.ts +12 -0
- package/dist/execution-lane-caps.js +18 -4
- package/dist/fleet/subagent-tail-bus.js +15 -5
- package/dist/hooks/hook-runner.d.ts +84 -30
- package/dist/hooks/hook-runner.js +74 -41
- package/dist/http/admission.js +17 -10
- package/dist/http/durable-run-leg.d.ts +5 -4
- package/dist/http/durable-run-leg.js +2 -4
- package/dist/http/idempotency.d.ts +28 -6
- package/dist/http/idempotency.js +10 -2
- package/dist/http/principal-gate.d.ts +14 -0
- package/dist/http/principal-gate.js +7 -0
- package/dist/http/request-guards.d.ts +2 -1
- package/dist/http/request-guards.js +14 -14
- package/dist/http/resume-legs.d.ts +2 -2
- package/dist/http/resume-legs.js +20 -10
- package/dist/http/route-ctx.d.ts +15 -7
- package/dist/http/routes/a2a-serve.js +11 -7
- package/dist/http/routes/approvals-assistant.js +18 -3
- package/dist/http/routes/background.d.ts +1 -1
- package/dist/http/routes/background.js +1 -1
- package/dist/http/routes/capabilities.js +10 -2
- package/dist/http/routes/mcp-reconnect.js +1 -1
- package/dist/http/routes/runs.d.ts +4 -3
- package/dist/http/routes/runs.js +35 -14
- package/dist/http/routes/session-sync.js +14 -11
- package/dist/http/routes/sessions.js +9 -9
- package/dist/http/routes/side-query.js +6 -19
- package/dist/http/routes/tasks.js +29 -19
- package/dist/http/routes/workflows.js +8 -0
- package/dist/http/server.d.ts +4 -0
- package/dist/http/server.js +3 -5
- package/dist/http/submit-replay.d.ts +15 -8
- package/dist/http/submit-replay.js +6 -0
- package/dist/http/wire-types.d.ts +7 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal-run-env.d.ts +30 -0
- package/dist/internal-run-env.js +11 -0
- package/dist/leader/wire.js +3 -2
- package/dist/lsp/manager.js +1 -1
- package/dist/memory-scope.d.ts +19 -7
- package/dist/memory-scope.js +25 -8
- package/dist/observability/fail-open.d.ts +31 -3
- package/dist/observability/fail-open.js +31 -3
- package/dist/observability/metrics.d.ts +0 -1
- package/dist/observability/metrics.js +1 -4
- package/dist/observability/run-terminal.js +72 -4
- package/dist/permission-rule-vocab.d.ts +3 -2
- package/dist/permission-rule-vocab.js +1 -1
- package/dist/plan-cache-probe.d.ts +3 -2
- package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
- package/dist/plugins/caching-session-store.d.ts +42 -22
- package/dist/plugins/caching-session-store.js +19 -9
- package/dist/plugins/checkpoint-store-sql.d.ts +42 -28
- package/dist/plugins/checkpoint-store-sql.js +57 -11
- package/dist/plugins/file-run-store.d.ts +25 -21
- package/dist/plugins/file-run-store.js +70 -34
- package/dist/plugins/k8s-exec-protocol.js +3 -0
- package/dist/plugins/local-checkpoint-store.d.ts +8 -5
- package/dist/plugins/local-checkpoint-store.js +5 -15
- package/dist/plugins/local-session-store.d.ts +66 -7
- package/dist/plugins/local-session-store.js +168 -101
- package/dist/plugins/mailbox-recipient-lifecycle.d.ts +1 -1
- package/dist/plugins/memory-run-store.d.ts +19 -3
- package/dist/plugins/memory-run-store.js +38 -3
- package/dist/plugins/one-time-migrations.d.ts +165 -39
- package/dist/plugins/one-time-migrations.js +51 -144
- package/dist/plugins/pg-pool.js +11 -1
- package/dist/plugins/pg-session-storage.d.ts +2 -0
- package/dist/plugins/pg-session-storage.js +9 -5
- package/dist/plugins/remote-env-adb.d.ts +3 -0
- package/dist/plugins/remote-env-adb.js +1 -0
- package/dist/plugins/remote-env-device.d.ts +3 -0
- package/dist/plugins/remote-env-device.js +1 -0
- package/dist/plugins/remote-env-e2b.d.ts +4 -0
- package/dist/plugins/remote-env-e2b.js +2 -1
- package/dist/plugins/remote-env-host.d.ts +23 -1
- package/dist/plugins/remote-env-host.js +20 -2
- package/dist/plugins/remote-env-k8s.d.ts +264 -41
- package/dist/plugins/remote-env-k8s.js +551 -82
- package/dist/plugins/remote-env-local-docker.d.ts +4 -0
- package/dist/plugins/remote-env-local-docker.js +2 -1
- package/dist/plugins/remote-env-ssh.d.ts +3 -0
- package/dist/plugins/remote-env-ssh.js +1 -0
- package/dist/plugins/retention-store-sql.d.ts +4 -1
- package/dist/plugins/retention-store-sql.js +11 -9
- package/dist/plugins/run-store-sql.d.ts +44 -6
- package/dist/plugins/run-store-sql.js +92 -27
- package/dist/plugins/session-capture-record-store-sql.d.ts +2 -3
- package/dist/plugins/session-store.d.ts +4 -3
- package/dist/plugins/session-store.js +1 -1
- package/dist/plugins/sql-driver.d.ts +2 -1
- package/dist/plugins/store-backend.d.ts +12 -5
- package/dist/plugins/store-backend.js +13 -4
- package/dist/plugins/store-contracts.d.ts +20 -3
- package/dist/plugins/store-open-wait.js +3 -0
- package/dist/plugins/tidb-pool.js +15 -3
- package/dist/plugins/tidb-session-storage.js +3 -2
- package/dist/plugins/tidb-session-store.d.ts +2 -0
- package/dist/plugins/tidb-session-store.js +6 -2
- package/dist/request-key-closure.d.ts +32 -7
- package/dist/request-key-closure.js +25 -9
- package/dist/router/route-orchestration.d.ts +3 -11
- package/dist/router/route-orchestration.js +0 -4
- package/dist/rule-entry-list.js +0 -4
- package/dist/rules-consent.js +3 -0
- package/dist/run-acceptance.d.ts +51 -0
- package/dist/run-acceptance.js +27 -0
- package/dist/run-local.d.ts +5 -4
- package/dist/run-local.js +23 -17
- package/dist/runs.d.ts +7 -11
- package/dist/runs.js +6 -16
- package/dist/sandbox-egress-policy.d.ts +61 -0
- package/dist/sandbox-egress-policy.js +235 -0
- package/dist/security.d.ts +7 -0
- package/dist/security.js +5 -0
- package/dist/server-secret-env.d.ts +10 -4
- package/dist/server-secret-env.js +4 -1
- package/dist/session-error-wire.d.ts +2 -2
- package/dist/session-incarnation.d.ts +46 -2
- package/dist/session-incarnation.js +14 -3
- package/dist/session-sync-kernel.d.ts +10 -3
- package/dist/session-titler.d.ts +5 -3
- package/dist/spec-fields.d.ts +24 -8
- package/dist/spec-fields.js +21 -2
- package/dist/task-workflow.d.ts +6 -4
- package/dist/task-workflow.js +3 -2
- package/dist/tool-approval.d.ts +78 -6
- package/dist/tool-approval.js +7 -3
- package/dist/trace/core-keyset-guard.d.ts +6 -5
- package/dist/trace/engine-notice-wire.d.ts +26 -1
- package/dist/trace/engine-notice-wire.js +7 -2
- package/dist/trace/ledger-events.d.ts +9 -3
- package/dist/trace/ledger-sink.d.ts +7 -0
- package/dist/trace/ledger-sink.js +14 -4
- package/dist/trace/project.d.ts +57 -11
- package/dist/trace/project.js +54 -8
- package/dist/trace/self-minted-wire.d.ts +94 -2
- package/dist/trace/self-minted-wire.js +28 -0
- package/dist/trace/tool-output-media.d.ts +26 -0
- package/dist/trace/tool-output-media.js +57 -0
- package/dist/trace/wire-projection-faces.d.ts +7 -1
- package/dist/trace/wire-projection-faces.js +2 -1
- package/dist/web-admin-client/apply-effective.d.ts +13 -7
- package/dist/web-admin-client/apply-effective.js +11 -26
- package/dist/web-admin-client/apply-ledger.d.ts +2 -2
- package/dist/web-admin-client/candidate-gate.d.ts +39 -4
- package/dist/web-admin-client/candidate-gate.js +9 -2
- package/dist/web-admin-client/facade.d.ts +2 -2
- package/dist/web-admin-client/http-client.d.ts +3 -1
- package/dist/web-admin-client/http-client.js +4 -3
- package/dist/web-admin-client/read-warnings.d.ts +33 -5
- package/dist/web-admin-client/read-warnings.js +41 -6
- package/dist/web-admin-client/types.d.ts +11 -5
- package/dist/workspace-cache.d.ts +45 -0
- package/dist/workspace-cache.js +30 -0
- package/dist/workspace-space-commit.d.ts +116 -0
- package/dist/workspace-space-commit.js +117 -0
- package/dist/workspace-space.d.ts +75 -9
- package/dist/workspace-space.js +52 -1
- package/package.json +4 -4
- package/dist/boot/session-incarnation-seat.d.ts +0 -41
- package/dist/boot/session-incarnation-seat.js +0 -69
- package/dist/capabilities/code-review-council.d.ts +0 -49
- package/dist/capabilities/code-review-council.js +0 -111
- package/dist/capabilities/collab-wire.d.ts +0 -36
- package/dist/capabilities/collab-wire.js +0 -2
- package/dist/capabilities/collab-workflows.d.ts +0 -47
- package/dist/capabilities/collab-workflows.js +0 -90
- package/dist/capabilities/prompts/code-review.d.ts +0 -25
- package/dist/capabilities/prompts/code-review.js +0 -39
- package/dist/capabilities/prompts/team.d.ts +0 -10
- package/dist/capabilities/prompts/team.js +0 -6
- package/dist/capabilities/team.d.ts +0 -113
- package/dist/capabilities/team.js +0 -70
package/dist/spec-fields.d.ts
CHANGED
|
@@ -66,12 +66,12 @@ export declare function skillToolListRefusal(skill: Record<string, unknown>): st
|
|
|
66
66
|
/** [ref] 单条 agent 定义的形状裁决:null=合法;否则一句可 400 的英文错误(不带索引,调用方自己加)。
|
|
67
67
|
* 白名单外键 fail-loud —— 与 resilience/limits 的「容忍未知键」相反:agents 是能力定义,静默丢字段 =
|
|
68
68
|
* 定义被悄悄削(一个丢掉的 isolation 就是放宽),比 400 更危险,故整条拒。`allowTools` / `denyTools` 本门只判形与条数(`toolList`),
|
|
69
|
-
* **名字归引擎一只判**(core 7.
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* `
|
|
74
|
-
* (
|
|
69
|
+
* **名字归引擎一只判**(core 7.49.0 #1623 / #1433 第二步起与根 run 的 `allowTools` / `excludeTools` 是同一只选择器,开跑前,三来源同判):没有任何工具答应的名字
|
|
70
|
+
* (无人挂的名、大小写孪生 / 退役名 `bash` / `BASH`、坏拼法、非字符串条目)⇒ 整 run 拒 `config.agent.unknown_tool` —— 主车道的委派工具带 extraTools 工厂,本仓在同一处
|
|
71
|
+
* 声明它的名册(core 7.46.0 `extraToolNames`;工厂与名册读同一批工具对象,`capabilities/builtin-tools.ts` `createSubagentExtraTools`),引擎因此列得出子代工具池。
|
|
72
|
+
* 两张表管子代可挂载的**全部**工具:委派池、hands 内建、引擎自己的工具(`Monitor` / `Artifact` / `Skill` / 记忆工具 …)与父的 MCP 挂载 ——
|
|
73
|
+
* `denyTools:["Monitor"]` ⇒ 子代没有 `Monitor`;`allowTools` 只点了调用方工具 ⇒ 子代只剩那几只与它这条腿的协议工具。`denyTools` 的 `Tool(content)` ⇒ 整只工具。
|
|
74
|
+
* 本仓不在受理口另做名字对照(那会是同一问的第二个判官)。
|
|
75
75
|
* ⚠️ 键判断必须 Object.hasOwn:`in` 走原型链,JSON 里的 "toString"/"constructor"/"__proto__" 键会被
|
|
76
76
|
* 误判为白名单字段,随后 SHAPES[k].ok 不是函数 ⇒ TypeError(fresh 500 / resume 砖;cross-review 复现)。 */
|
|
77
77
|
export declare function taskAgentIssue(item: unknown): string | null;
|
|
@@ -130,6 +130,22 @@ export declare function retainBackgroundProcessesFromBody(raw: unknown, requireP
|
|
|
130
130
|
* DEFENSIVE(resume 重放不过 HTTP 400 门):非数组 ⇒ undefined;项非非空字符串 ⇒ 逐项 DROP;空数组 ⇒
|
|
131
131
|
* undefined(不挂键=core 缺省,byte-compat)。HTTP 门另有 fail-loud 400(提交面邻居姿势)。 */
|
|
132
132
|
export declare function toolNameListFromBody(raw: unknown): string[] | undefined;
|
|
133
|
+
/** 引擎从哪一版起认 `TaskSpec.allowTools`(core 7.49.0 #1623,[ref])。 */
|
|
134
|
+
export declare const ALLOW_TOOLS_MIN_ENGINE = "7.49.0";
|
|
135
|
+
/**
|
|
136
|
+
* S-1448(core 7.49.0 #1623 / [ref])—— body.allowTools → `TaskSpec.allowTools`:引擎的**可用性选择器**,原样透传。
|
|
137
|
+
*
|
|
138
|
+
* 一条规则:这一 run 能用哪些工具由引擎一只运算答(`universe ∩ ceiling ∩ allow − deny`,prepare 对真实挂载的一切算一次)。
|
|
139
|
+
* 本仓**零读法** —— 不算补集、不逐项过滤(`[]` = 什么都不给,是合法值,不折成缺席;非串条目与未知名由引擎在 prepare 拒,
|
|
140
|
+
* `config.tool_face_control`)、不与 allow 层 `allowedTools`(免问)混词。受理门只判 wire 形(与 `excludeTools` / `deferTools` 同一只门)。
|
|
141
|
+
* 续跑重放同经此处:存量体逐字再投,坏形交引擎拒(收窄键丢了 = 放宽,所以不 DROP)。
|
|
142
|
+
*
|
|
143
|
+
* 装着的引擎不认该座(< {@link ALLOW_TOOLS_MIN_ENGINE})⇒ **响亮拒** 400 `request.field_invalid`(点名键、所需版本与装着的版本),
|
|
144
|
+
* 不静默丢。`engineVersion` 缺省读装着的 core(`CORE_ENGINE_VERSION`);测试传假低版。
|
|
145
|
+
*/
|
|
146
|
+
export declare function allowToolsSpecFragment(raw: unknown, engineVersion?: string): {
|
|
147
|
+
allowTools?: string[];
|
|
148
|
+
};
|
|
133
149
|
/** [ref]/[ref] — body.promptProfile → `TaskSpec.promptProfile`(core 1.328 R2 主件,CC LT(model_id)
|
|
134
150
|
* 同构双形轴)。语义:纯呈现轴不碰策略(simple=CC 212 短形面缺省;classic=长形面,可按任务/模型试分)
|
|
135
151
|
* ⇒ 无租户门(deferTools 同姿势);全委托树继承由 core 管。缺省不挂键(引擎缺省 simple,byte-compat)。
|
|
@@ -177,10 +193,10 @@ export declare function normalizeApproachNotice(raw: unknown): false | {
|
|
|
177
193
|
* [ref]④ — body.limits 与 env 墙钟的合成规则(resolveSpec 的唯一 limits 装配点;run-local 无 body 车道不经此):
|
|
178
194
|
* - `timeoutSec`:body 给了就用 body(caller 明确配速;已在 normalizeLimits 里被 TASK_TIMEOUT_MAX_SEC 封顶)。
|
|
179
195
|
* body 缺席保持既有姿势 = tenancy 墙钟 + env `TASK_TIMEOUT_SEC` 只抬不降(taskWallClockSec 内 Math.max,
|
|
180
|
-
* 误配低值不能砍
|
|
196
|
+
* 误配低值不能砍 tenancy 基值)。注意两条纪律不叠加:「只抬不降」是 env 对内建缺省墙的规则,body 是
|
|
181
197
|
* caller 的显式意图,直接生效(可低于 env 墙 —— 交互短任务要更紧的配速正是本件诉求)。
|
|
182
198
|
* - `maxOutputTokens` / `maxTurns`:直透传(各自可选 env 上限已 clamp)。
|
|
183
199
|
* 全空 ⇒ undefined(spec 不挂 limits 键,byte-compat)。
|
|
184
200
|
*/
|
|
185
|
-
export declare function resolveTaskLimits(bodyLimits: unknown, caps: TaskLimitCaps, envTimeoutSec: number, requirePrincipal: boolean | undefined,
|
|
201
|
+
export declare function resolveTaskLimits(bodyLimits: unknown, caps: TaskLimitCaps, envTimeoutSec: number, requirePrincipal: boolean | undefined, warn?: (event: string, fields: Record<string, unknown>) => void): TaskSpec["limits"];
|
|
186
202
|
//# sourceMappingURL=spec-fields.d.ts.map
|
package/dist/spec-fields.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { isThinkingLevel } from "@sema-agent/core";
|
|
2
2
|
import { taskWallClockSec } from "./task-workflow.js";
|
|
3
3
|
import { isAbsoluteHostPath } from "@sema-agent/settings-schema";
|
|
4
|
+
import { CORE_ENGINE_VERSION } from "./prompts-domain-validate.js";
|
|
5
|
+
import { createCodedHttpError } from "./security.js";
|
|
4
6
|
import { allowLayerEntryCountIssue, ruleEntryListShapeOk } from "./rule-entry-list.js";
|
|
5
7
|
export function normalizeSuggestNextPrompts(v) {
|
|
6
8
|
if (v === true)
|
|
@@ -270,6 +272,23 @@ export function toolNameListFromBody(raw) {
|
|
|
270
272
|
const names = raw.filter((v) => typeof v === "string" && v.length > 0);
|
|
271
273
|
return names.length > 0 ? names : undefined;
|
|
272
274
|
}
|
|
275
|
+
export const ALLOW_TOOLS_MIN_ENGINE = "7.49.0";
|
|
276
|
+
function engineAtLeast(version, floor) {
|
|
277
|
+
const parse = (v) => v.split(/[-+]/, 1)[0].split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
278
|
+
const [a, b] = [parse(version), parse(floor)];
|
|
279
|
+
for (let i = 0; i < 3; i++)
|
|
280
|
+
if ((a[i] ?? 0) !== (b[i] ?? 0))
|
|
281
|
+
return (a[i] ?? 0) > (b[i] ?? 0);
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
export function allowToolsSpecFragment(raw, engineVersion = CORE_ENGINE_VERSION) {
|
|
285
|
+
if (raw === undefined)
|
|
286
|
+
return {};
|
|
287
|
+
if (!engineAtLeast(engineVersion, ALLOW_TOOLS_MIN_ENGINE)) {
|
|
288
|
+
throw createCodedHttpError(400, "request.field_invalid", `allowTools needs engine ${ALLOW_TOOLS_MIN_ENGINE} or later; this server runs engine ${engineVersion}, which would drop the list and leave every tool available — send the request without allowTools, or upgrade the server`);
|
|
289
|
+
}
|
|
290
|
+
return { allowTools: raw };
|
|
291
|
+
}
|
|
273
292
|
export function promptProfileFromBody(raw) {
|
|
274
293
|
return raw === "simple" || raw === "classic" ? raw : undefined;
|
|
275
294
|
}
|
|
@@ -318,10 +337,10 @@ export function normalizeApproachNotice(raw) {
|
|
|
318
337
|
const frac = (n) => typeof n === "number" && Number.isFinite(n) && n > 0 && n <= 1;
|
|
319
338
|
return frac(a) && frac(b) && a <= b ? { at: [a, b] } : undefined;
|
|
320
339
|
}
|
|
321
|
-
export function resolveTaskLimits(bodyLimits, caps, envTimeoutSec, requirePrincipal,
|
|
340
|
+
export function resolveTaskLimits(bodyLimits, caps, envTimeoutSec, requirePrincipal, warn) {
|
|
322
341
|
const dropped = retiredLimitKeysPresent(bodyLimits);
|
|
323
342
|
const requested = normalizeLimits(bodyLimits, caps);
|
|
324
|
-
const wallSec = taskWallClockSec(envTimeoutSec, requirePrincipal
|
|
343
|
+
const wallSec = taskWallClockSec(envTimeoutSec, requirePrincipal);
|
|
325
344
|
const maxWalltimeMs = requested?.maxWalltimeMs ?? (wallSec !== undefined ? wallSec * 1000 : undefined);
|
|
326
345
|
if (dropped.length > 0)
|
|
327
346
|
warn?.("task_limits_legacy_key_dropped", { droppedKeys: dropped, effectiveMaxWalltimeMs: maxWalltimeMs ?? null });
|
package/dist/task-workflow.d.ts
CHANGED
|
@@ -113,10 +113,12 @@ export declare function normalizeRetainSubagentSessions(raw: unknown): boolean |
|
|
|
113
113
|
* - SINGLE-USER turnkey(`requirePrincipal !== true`)= the user IS the superadmin → **NO wall clock**
|
|
114
114
|
* (undefined; core arms none — its separate wedge safety-net still catches a stuck tool call, so "no wall"
|
|
115
115
|
* never means "hangs forever"). CC has no whole-task decapitation either.
|
|
116
|
-
* - MULTI-TENANT: base 2400s (big
|
|
117
|
-
*
|
|
116
|
+
* - MULTI-TENANT: base 2400s (one base: the 3600s big-task lane existed only for council/debate/discuss, which
|
|
117
|
+
* left with the engine's team runtime in 7.49.0).
|
|
118
118
|
* - Explicit `TASK_TIMEOUT_SEC` wins in ANY tenancy (the operator's deliberate wall) and keeps its documented
|
|
119
|
-
* raise-only floor (`Math.max` with the base, so a misconfigured low value cannot shrink
|
|
119
|
+
* raise-only floor (`Math.max` with the base, so a misconfigured low value cannot shrink the tenancy base).
|
|
120
120
|
*/
|
|
121
|
-
|
|
121
|
+
/** 多租户(requirePrincipal)任务墙钟基值(秒)—— 唯一来源:`taskWallClockSec` 与 resolve-spec 的 `server.limits.wallClockBaseSec` 声明都读它(3600 s 大任务档已随团队编排面退役删除)。 */
|
|
122
|
+
export declare const TENANCY_WALL_CLOCK_BASE_SEC = 2400;
|
|
123
|
+
export declare function taskWallClockSec(envTimeoutSec: number, requirePrincipal: boolean | undefined): number | undefined;
|
|
122
124
|
//# sourceMappingURL=task-workflow.d.ts.map
|
package/dist/task-workflow.js
CHANGED
|
@@ -39,8 +39,9 @@ export function normalizeRetainSubagentSessions(raw) {
|
|
|
39
39
|
return undefined;
|
|
40
40
|
return { ...(ttlMs !== undefined ? { ttlMs } : {}), ...(max !== undefined ? { max } : {}) };
|
|
41
41
|
}
|
|
42
|
-
export
|
|
43
|
-
|
|
42
|
+
export const TENANCY_WALL_CLOCK_BASE_SEC = 2400;
|
|
43
|
+
export function taskWallClockSec(envTimeoutSec, requirePrincipal) {
|
|
44
|
+
const base = TENANCY_WALL_CLOCK_BASE_SEC;
|
|
44
45
|
if (envTimeoutSec > 0)
|
|
45
46
|
return Math.max(envTimeoutSec, base);
|
|
46
47
|
return requirePrincipal === true ? base : undefined;
|
package/dist/tool-approval.d.ts
CHANGED
|
@@ -1,6 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [ref]/[ref]② tool-approval bridge — the SERVICE side of core's `RunnerDeps.onAsk` seam (core `tool-policy.ts`
|
|
3
|
+
* `resolveAsk`, 1.290's sync-ask leg). The SIBLING of {@link import("./question.js").QuestionCoordinator}: onQuestion
|
|
4
|
+
* routes the agent's AskUserQuestion tool to a live human; THIS routes a policy `ask` DECISION (e.g. the
|
|
5
|
+
* `createFsWriteGatePolicy` fs-write gate, an ask-list rule, or a non-durable safety ask) to the live human as a
|
|
6
|
+
* CC-parity three-choice card (Yes / Yes-allow-all-session / No).
|
|
7
|
+
*
|
|
8
|
+
* Wire shape (mirrors question end to end): core adjudicates a tool call `ask` → `resolveAsk(req, onAsk)` calls this
|
|
9
|
+
* coordinator's `ask` → we mint a pending entry + emit a `tool_approval` SSE frame on the run's live stream → the
|
|
10
|
+
* shell renders the three-choice card → `POST /v1/tool-approvals/:id/respond` settles the parked promise →
|
|
11
|
+
* `resolveAsk` maps our boolean to allow/deny. RESPOND BODY selection rationale: the question precedent's body is
|
|
12
|
+
* core's own QuestionAnswer (a structured multi-answer object) because core FENCES its semantics; an approval has no
|
|
13
|
+
* core-side answer object — `OnAsk` resolves to a BARE boolean — so the wire body is a minimal closed enum
|
|
14
|
+
* `{decision: "allow" | "allow_session" | "deny"}` mapping 1:1 onto the CC card's three choices (no free text = no
|
|
15
|
+
* fence needed; "allow_session" carries the Yes-allow-all intent that a boolean cannot).
|
|
16
|
+
*
|
|
17
|
+
* Session state ([ref]② "桥内会话态"): `allow_session` remembers a per-CAPABILITY grant keyed by
|
|
18
|
+
* `[owner, sessionId, category]` — a LATER ask in that (owner, session) whose tool maps to the SAME category
|
|
19
|
+
* auto-allows WITHOUT a card (CC 207: "Yes, allow all edits during this session") only through the FOUR-WAY
|
|
20
|
+
* conjunction at the short-circuit (see `ask`): {@link standingAnswerHome} over the ask's three facts
|
|
21
|
+
* (NOT governance-forced [ref] 件7/[ref], NOT `requiresRealApproval` [ref], NOT `mandated` S-660 — the SAME
|
|
22
|
+
* predicate decides whether an `allow_session` answer may MINT a grant, see `finishRespond`) ∧ a truthy sessionId ∧
|
|
23
|
+
* the grant itself ∧ `sessionGrantUncontestedByRow` (the durable row must not contradict the local peek). The category collapses the
|
|
24
|
+
* fs-WRITE tool family (Write/Edit/NotebookEdit, canonical space) into ONE bucket `"fs-write"`; any OTHER tool is
|
|
25
|
+
* its OWN bucket `"tool:<canonical>"`. 🔴 A `allow_session` on a NON-fs-write ask (an irreversible-Bash safety ask,
|
|
26
|
+
* an ask-list rule on another tool) therefore unlocks ONLY that same tool for the session — it must NEVER unlock the
|
|
27
|
+
* fs-write family (the "approve a cheap ask once → all future Write/Edit auto-allowed" scope widening, 三路复审 A 组 修2).
|
|
28
|
+
* The key is scoped to the VERIFIED owner too, so a session id shared across principals cannot inherit another's
|
|
29
|
+
* grant. This is the cheapest mid-task implementation; a mode SWITCH (default → acceptEdits) still goes through the
|
|
30
|
+
* shell's intent on the next task ([ref] table).
|
|
31
|
+
*
|
|
32
|
+
* 🔒 FAIL-CLOSED everywhere (the inverse of the question lane — an unanswered QUESTION never blocks the run: since
|
|
33
|
+
* [ref] the coordinator reports `unavailable` and CORE decides the landing, which depends on WHEN the human became
|
|
34
|
+
* unreachable — at policy time the durable gate says `ask` and the leg parks; once the tool is already running core is
|
|
35
|
+
* past `suspendAsk`, so it continues on `declined_unavailable`; an unanswered APPROVAL must NOT let the write
|
|
36
|
+
* proceed): TTL expiry and client disconnect ([ref] `parkOpenAsksForTask` → `forceParkNow`) land on the ONE
|
|
37
|
+
* unattended-outcome former ({@link ToolApprovalCoordinator.unattendedOutcome}, [ref] R-13) — park route
|
|
38
|
+
* ("unavailable" ⇒ core durable-parks) by default, a DEPLOYMENT-POLICY refusal (`{allow:false, settledBy:"policy",
|
|
39
|
+
* reason}` ⇒ core settles `policy_refused`; S-689 — never a bare `false`, which core reads as a PERSON's refusal)
|
|
40
|
+
* ONLY where the deployment declared `UNATTENDED_APPROVAL_POLICY=deny`; a run ABORT (task cancel → `runCancel`)
|
|
41
|
+
* still resolves `false` — the row goes VOID, there is nothing left to redeem. Since [ref] G1 (core 1.295
|
|
42
|
+
* OnAsk 三值化) the "no reachable human" class returns
|
|
43
|
+
* "unavailable" instead of false — no ALS context AND no bound-closure broker hit(1.258 起 bg/嵌套子代经
|
|
44
|
+
* spec.onAsk 的 bound 闭包 + streams broker 直达宿主活流,「无 ctx」只剩 durable-submit/headless resume
|
|
45
|
+
* 残余腿)and emit failure
|
|
46
|
+
* (card never delivered, and only when this catch is the first settler — a human verdict that raced in during the
|
|
47
|
+
* await keeps its boolean) ⇒ "unavailable" → core durable-parks (or fail-closed denies without a checkpoint). core's
|
|
48
|
+
* `resolveAsk` maps false to a deny WITH the ask message, so the model can re-route (deny + continue turn, [ref]⑤).
|
|
49
|
+
* Owner gate on respond = the VERIFIED principal (gatedPrincipal at the HTTP layer), 404 without an existence oracle
|
|
50
|
+
* — same posture as question/elicit. The frame's model-authored surfaces (message + args) are secret-REDACTED
|
|
51
|
+
* before they are streamed; the SIZE bound is per-surface: args ride a byte cap (`MAX_APPROVAL_ARGS_BYTES`,
|
|
52
|
+
* over-cap ⇒ `argsOmitted`), while the legacy frame's `message` is redacted but NOT length-capped — the char
|
|
53
|
+
* cap (`MAX_MESSAGE`, approval-card.ts `clip`) lives on the card/`approval_request` projection only (same
|
|
54
|
+
* redact-at-write contract as question; the args are shown to a human,
|
|
55
|
+
* never re-fed to a model). No throttle (unlike question): an approval breach-default would be a DENY (task failure),
|
|
56
|
+
* and asks are turn-blocking by construction — the TTL bounds the human-side exposure instead.
|
|
57
|
+
*/
|
|
58
|
+
import { type ParkedGateFace } from "./approval-content-kind.js";
|
|
1
59
|
import { type ApprovalDecidedBy, type HostSettledBy, type RetiredDecisionKeyFacts } from "./host-decision.js";
|
|
2
60
|
import type { IncomingMessage } from "node:http";
|
|
3
|
-
import { type AskClass, type AskRequest, type AskOutcome, type PermissionResult, type CheckpointGate, type PendingAction, type PersistedRuleMandate, type ReadRootGrantCandidate, type RuleOffer, type AutoModeFallbackCause, type BoundSkillGrants } from "@sema-agent/core";
|
|
61
|
+
import { type AskClass, type AskRequest, type AskOutcome, type PermissionResult, type CheckpointGate, type PendingAction, type PersistedRuleMandate, type ReadRootGrantCandidate, type RuleOffer, type AutoModeFallbackCause, type BoundSkillGrants, type ToolApprovalCard } from "@sema-agent/core";
|
|
4
62
|
import { type CardRulePersisted, type RuleConsentLane } from "./rules-consent.js";
|
|
5
63
|
import { type AllowRuleShadowProjection, type DenialLimitFallback, type RuleOffersAbsence, type ApprovalRequestFrame, type ApprovalRevokeFrame, type RuleEvidenceProjection } from "./approval-card.js";
|
|
6
64
|
import { type ApprovalAskStore, type AskRow } from "./plugins/approval-ask-store-sql.js";
|
|
@@ -18,6 +76,11 @@ import { type ApprovalExemptionStore } from "./plugins/approval-exemption-store.
|
|
|
18
76
|
export declare const APPROVAL_GATE_KINDS: readonly ["human", "irreversible_ask"];
|
|
19
77
|
export type ApprovalGateKind = (typeof APPROVAL_GATE_KINDS)[number];
|
|
20
78
|
export declare function isApprovalGateKind(k: string | undefined): k is ApprovalGateKind;
|
|
79
|
+
/**
|
|
80
|
+
* 停驻行的到期归 SLA 拒扫腿(deny)而不是作废(expire)?—— **一只谓词**:审批门型 ∧ core `facetOf(gate)` 读作 `A`(问答卡 ⇒ `B`,到期作废;
|
|
81
|
+
* 无门型 / 非审批门 ⇒ 不归拒扫)。两只店的拒扫选行与作废腿的补集都读这一只(SQL 腿的 `gate_kind IN …` 只是它的粗筛前置,判官仍是 core)。
|
|
82
|
+
*/
|
|
83
|
+
export declare function denySweepOwns(gate: ParkedGateFace | undefined): boolean;
|
|
21
84
|
/** 两方言同形的 SQL IN 片段(值为闭集常量字面,无注入面)。 */
|
|
22
85
|
export declare const APPROVAL_GATE_KINDS_SQL_IN: string;
|
|
23
86
|
/**
|
|
@@ -345,7 +408,7 @@ export interface ToolApprovalFrame {
|
|
|
345
408
|
/**
|
|
346
409
|
* **S-721(core 7.32.0 #1092;ADDITIVE,`"tool_approval"` only)** —— 强制位**站在哪一个词上**:core `PERSISTED_RULE_MANDATES`
|
|
347
410
|
* 六词之一(`operator_always` / `tool_marks` / `probe_mandate` / `probe_unanswered` / `write_protection` /
|
|
348
|
-
* `
|
|
411
|
+
* `target_unresolved`,词义属主在 core)。只在 `mandated: true` 的**整因**是那一个词时在场;另一扇门(治理 / hook /
|
|
349
412
|
* 祖先)或不止一个理由 ⇒ 缺席 —— **缺席从不命名一个词**,也不等于「不强制」(读 `mandated`)。值经 `approval-card.ts` 的
|
|
350
413
|
* `readClosedWordSeat(req, "mandate")` 窄读(闭集筛 = core `isPersistedRuleMandate`,本仓不抄词表;集外词读作缺席 + 计一次)。echo-only:
|
|
351
414
|
* 本仓不按词分支。耐久面同一个词:运维队列行(`parkRowFacts`,park 行孪生座)与 inbox 行(core `CheckpointSummary.mandate`)。
|
|
@@ -407,6 +470,15 @@ export interface ToolApprovalFrame {
|
|
|
407
470
|
/** core 7.43.0 #1353:分类器没给判词的成因词(`error` / `timeout` / `parse_error`;只在类 `classifier_no_ruling` 的卡上)。闭集经 core 的
|
|
408
471
|
* `readClosedWordSeat(req, "classifierNoRuling")` 窄读(筛 = core `isAutoModeFallbackCause`),集外 ⇒ 缺席 + 计一次。display:本仓不按它裁决。 */
|
|
409
472
|
classifierNoRuling?: AutoModeFallbackCause;
|
|
473
|
+
/**
|
|
474
|
+
* **core 7.49.0 #1414(ADDITIVE,`"tool_approval"` only)—— 这一问渲在哪张卡上**:引擎在闸站铸的那一个词(闭集 core `TOOL_APPROVAL_CARDS`:
|
|
475
|
+
* `file-edit` / `file-write` / `notebook-edit` / `shell` / `fetch` / `plan` / `question` / `generic`),`AskRequest.approvalCard` 逐字过境,经
|
|
476
|
+
* `approval-content-kind.ts` 的 `readApprovalCard` 闭集窄读(集外 ⇒ 缺席 + 计一次 closed-word-out-of-set)。`question` = 问用户的问题(引擎保留的
|
|
477
|
+
* 问答工具),不是副作用工具。**本仓不从工具名回推卡**(工具名只作展示):此前按名字铸的 `livePending` 行 / 队列行 `contentKind` 随本键删。
|
|
478
|
+
* 停驻孪生 = 门的 `gate.approvalCard`(运维队列行顶层同名键,两只店读同一只 `parkedApprovalCard`)。display:本仓不按它裁决。
|
|
479
|
+
* 🔴 缺席即缺席(宿主自建的 ask / 老引擎),不编 `generic`。⚠️ `card_json` 卡面不带本键(`ApprovalCardSchema` `.strict()`,与 `mandated` 同)。
|
|
480
|
+
*/
|
|
481
|
+
approvalCard?: ToolApprovalCard;
|
|
410
482
|
/**
|
|
411
483
|
* **[ref]**(core 7.19.0;**ADDITIVE**,`"tool_approval"` only)—— 这只**根外读** ask 的**清障目录**:
|
|
412
484
|
* 把 `dir` 加进本会话的读目录(壳侧既有的 `/add-dir` 口),同一条调用就不会再问。
|
|
@@ -675,10 +747,10 @@ export interface LivePendingRow {
|
|
|
675
747
|
* 子代 ask)上恒等成立。缺席 = 顶层 ask。`fromSubagent` 保留不动(byte-compat:先于本键的消费方仍按
|
|
676
748
|
* 它判别)。 */
|
|
677
749
|
originTaskId?: string;
|
|
678
|
-
/**
|
|
679
|
-
* `
|
|
680
|
-
*
|
|
681
|
-
|
|
750
|
+
/** core 7.49.0 #1414:这一问的卡词 —— 与 {@link frame} 上的 `approvalCard` **同一个值**(行读帧上那一格,不另读一遍),与 durable
|
|
751
|
+
* 队列行顶层的同名键同层同形(那一面读门的 `gate.approvalCard`)。缺席 = 引擎没给(宿主自建 ask / 老引擎)。展示/分诊用,永不参与决议路由。
|
|
752
|
+
* (此前此处是按工具名铸的 `contentKind`,随 #1414 删:卡只有引擎铸的这一个词。) */
|
|
753
|
+
approvalCard?: ToolApprovalCard;
|
|
682
754
|
/**
|
|
683
755
|
* 🔴 S-454(P1;cli L-397 / 板 [ref]):这只 ask **本来会 emit 的那只活卡帧**。
|
|
684
756
|
*
|
package/dist/tool-approval.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parkedFacetOf, readApprovalCard } from "./approval-content-kind.js";
|
|
2
2
|
import { heldAskOf, liveSettledBy, readDecidedBy, retiredDecisionKeyFacts, DECIDED_BY_OUTSIDE_CLOSED_SET, POLICY_CANNOT_ALLOW_PERSON_ASK } from "./host-decision.js";
|
|
3
3
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
4
|
import { uuidv7, classifyAsk, foldArbitrationRow, policyCannotAnswer, screenAskClassMembers, MAX_RULE_TEXT_CHARS, READ_ROOT_CANDIDATE_DIR_MAX, parseRuleText, pathConfinableWriteToolNames } from "@sema-agent/core";
|
|
@@ -23,6 +23,9 @@ export const APPROVAL_GATE_KINDS = ["human", "irreversible_ask"];
|
|
|
23
23
|
export function isApprovalGateKind(k) {
|
|
24
24
|
return k !== undefined && APPROVAL_GATE_KINDS.includes(k);
|
|
25
25
|
}
|
|
26
|
+
export function denySweepOwns(gate) {
|
|
27
|
+
return isApprovalGateKind(typeof gate?.kind === "string" ? gate.kind : undefined) && parkedFacetOf(gate) === "A";
|
|
28
|
+
}
|
|
26
29
|
export const APPROVAL_GATE_KINDS_SQL_IN = `(${APPROVAL_GATE_KINDS.map((k) => `'${k}'`).join(",")})`;
|
|
27
30
|
const MAX_APPROVAL_ARGS_BYTES = 16384;
|
|
28
31
|
const DEFAULT_APPROVAL_TTL_MS = 5 * 60_000;
|
|
@@ -1151,6 +1154,7 @@ export class ToolApprovalCoordinator {
|
|
|
1151
1154
|
let ruleLaneMaterial = this.buildRuleLaneMaterial(req, origin.owner, governanceForced, origin.sessionId);
|
|
1152
1155
|
const mandateWord = readClosedWordSeat(req, "mandate");
|
|
1153
1156
|
const noRulingCause = readClosedWordSeat(req, "classifierNoRuling");
|
|
1157
|
+
const cardWord = readApprovalCard(req.approvalCard);
|
|
1154
1158
|
const originWord = typeof req.origin === "string" && req.origin.length > 0 ? req.origin : undefined;
|
|
1155
1159
|
const askClassPair = readAskClassPair(req);
|
|
1156
1160
|
const frame = {
|
|
@@ -1181,6 +1185,7 @@ export class ToolApprovalCoordinator {
|
|
|
1181
1185
|
...(standingAnswerHome(askStandingAnswerFacts(req, governanceForced, deploymentListAsks)) === "none" ? { rememberRefused: true } : {}),
|
|
1182
1186
|
...(typeof req.boundGrantDigest === "string" ? { boundGrantDigest: req.boundGrantDigest, ...(req.boundGrants !== undefined ? { boundGrants: req.boundGrants } : {}) } : {}),
|
|
1183
1187
|
...(noRulingCause !== undefined ? { classifierNoRuling: noRulingCause } : {}),
|
|
1188
|
+
...(cardWord !== undefined ? { approvalCard: cardWord } : {}),
|
|
1184
1189
|
...(mandateWord !== undefined ? { mandate: mandateWord } : {}),
|
|
1185
1190
|
...(originWord !== undefined ? { origin: originWord } : {}),
|
|
1186
1191
|
...(askClassPair ?? {}),
|
|
@@ -2434,7 +2439,6 @@ export class ToolApprovalCoordinator {
|
|
|
2434
2439
|
for (const [id, e] of this.pending) {
|
|
2435
2440
|
if (scope !== undefined && e.owner !== scope)
|
|
2436
2441
|
continue;
|
|
2437
|
-
const contentKind = contentKindOf(e.toolName);
|
|
2438
2442
|
rows.push({
|
|
2439
2443
|
approvalId: id,
|
|
2440
2444
|
toolName: e.toolName,
|
|
@@ -2448,7 +2452,7 @@ export class ToolApprovalCoordinator {
|
|
|
2448
2452
|
...(e.mandate !== undefined ? { mandate: e.mandate } : {}),
|
|
2449
2453
|
...(e.origin !== undefined ? { origin: e.origin } : {}),
|
|
2450
2454
|
...(e.originTaskId !== undefined ? { fromSubagent: true, originTaskId: e.originTaskId } : {}),
|
|
2451
|
-
...(
|
|
2455
|
+
...(e.frame.approvalCard !== undefined ? { approvalCard: e.frame.approvalCard } : {}),
|
|
2452
2456
|
frame: e.frame.approvalId === id ? e.frame : { ...e.frame, approvalId: id },
|
|
2453
2457
|
});
|
|
2454
2458
|
}
|
|
@@ -43,14 +43,14 @@ type _GuardBgNotifReverse = AssertAllKeysHandled<Exclude<BgNotifProjected | BgNo
|
|
|
43
43
|
type RosterProjected = "name" | "agentId" | "sessionId" | "toolUseId" | "owner" | "scope" | "sessionScoped" | "rootSessionId" | "model" | "modelFallback" | "createdAt";
|
|
44
44
|
type _GuardRoster = AssertAllKeysHandled<Exclude<keyof RosterEntry, RosterProjected>>;
|
|
45
45
|
type _GuardRosterReverse = AssertAllKeysHandled<Exclude<RosterProjected, keyof RosterEntry>>;
|
|
46
|
-
type AskProjected = "toolName" | "toolCallId" | "args" | "message" | "sourceTaskId" | "fromSubagent" | "sourceAgentName" | "delegation" | "ruleOffers" | "ruleOffersAbsence" | "allowRuleShadowed" | "probeCause" | "probeReason" | "ruleEvidence" | "requiresRealApproval" | "denialLimitFallback" | "origin" | "readRootCandidate" | "mandated" | "mandate" | "askClass" | "classes" | "boundGrantDigest" | "boundGrants" | "classifierNoRuling";
|
|
46
|
+
type AskProjected = "toolName" | "toolCallId" | "args" | "message" | "sourceTaskId" | "fromSubagent" | "sourceAgentName" | "delegation" | "ruleOffers" | "ruleOffersAbsence" | "allowRuleShadowed" | "probeCause" | "probeReason" | "ruleEvidence" | "requiresRealApproval" | "denialLimitFallback" | "origin" | "readRootCandidate" | "mandated" | "mandate" | "askClass" | "classes" | "boundGrantDigest" | "boundGrants" | "classifierNoRuling" | "approvalCard";
|
|
47
47
|
type AskExcluded = "preview" | "principal" | "riskAxes" | "boundInputHash" | "isDelegatedChild" | "hasBidiControls" | "previewWithheld" | "execCwd" | "authoredBy";
|
|
48
48
|
type _GuardAsk = AssertAllKeysHandled<Exclude<keyof AskRequest, AskProjected | AskExcluded>>;
|
|
49
49
|
type _GuardAskReverse = AssertAllKeysHandled<Exclude<AskProjected | AskExcluded, keyof AskRequest>>;
|
|
50
50
|
type AskFrameServerMinted = "type" | "approvalId" | "argsOmitted" | "outcome" | "governanceForced" | "expiresAtMs" | "expiresInMs" | "serverNowMs" | "parked" | "cause" | "inputHasBidi" | "rememberRefused";
|
|
51
51
|
type _GuardAskFrame = AssertAllKeysHandled<Exclude<keyof ToolApprovalFrame, AskProjected | AskFrameServerMinted>>;
|
|
52
52
|
type _GuardAskFrameReverse = AssertAllKeysHandled<Exclude<AskProjected | AskFrameServerMinted, keyof ToolApprovalFrame>>;
|
|
53
|
-
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" | "text_end" | "tool_roster_delta" | "tool_progress" | "tool_disclosure";
|
|
53
|
+
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" | "text_end" | "tool_roster_delta" | "tool_progress" | "tool_disclosure" | "task_started";
|
|
54
54
|
type _GuardTaskEvent = AssertAllKeysHandled<Exclude<TaskEvent["type"], TaskEventHandled>>;
|
|
55
55
|
type _GuardTaskEventReverse = AssertAllKeysHandled<Exclude<TaskEventHandled, TaskEvent["type"]>>;
|
|
56
56
|
type MailboxProjected = "seq" | "from" | "content" | "sentAt" | "hopChain" | "peerMeta";
|
|
@@ -137,7 +137,7 @@ type _GuardPermissionTraceReverse = AssertAllKeysHandled<Exclude<PermissionTrace
|
|
|
137
137
|
type AssertNonEmpty<T> = [T] extends [never] ? "EMPTY" : never;
|
|
138
138
|
type _GuardPermissionTraceNonEmpty = AssertAllKeysHandled<AssertNonEmpty<PermissionTraceKind>>;
|
|
139
139
|
type SummaryProjected = "sessionId" | "scope" | "createdAt" | "gateKind" | "severity" | "spentMicroUsd" | "deadline" | "hasBidiControls" | "requiresRealApproval" | "denialLimitFallback" | "origin" | "mandated" | "mandate" | "boundGrantDigest" | "boundGrants" | "classifierNoRuling";
|
|
140
|
-
type SummaryExcluded = "token" | "toolInput" | "toolName" | "toolCallId" | "preview" | "principal" | "sourceTaskId" | "
|
|
140
|
+
type SummaryExcluded = "token" | "toolInput" | "toolName" | "toolCallId" | "preview" | "principal" | "sourceTaskId" | "approvalCard" | "restoreMode" | "checkpointId" | "previewWithheld" | "authoredBy";
|
|
141
141
|
type _GuardInboxSummary = AssertAllKeysHandled<Exclude<keyof CheckpointSummary, SummaryProjected | SummaryExcluded>>;
|
|
142
142
|
type _GuardInboxSummaryReverse = AssertAllKeysHandled<Exclude<SummaryProjected | SummaryExcluded, keyof CheckpointSummary>>;
|
|
143
143
|
type ParkArmKeys = keyof Extract<PendingAction, {
|
|
@@ -148,8 +148,9 @@ type ParkArmQueueExcluded = "kind" | "args" | "batchToolCallIds" | "completedCal
|
|
|
148
148
|
type _GuardParkArmQueue = AssertAllKeysHandled<Exclude<ParkArmKeys, ParkArmQueueProjected | ParkArmQueueExcluded>>;
|
|
149
149
|
type _GuardParkArmQueueReverse = AssertAllKeysHandled<Exclude<ParkArmQueueProjected | ParkArmQueueExcluded, ParkArmKeys>>;
|
|
150
150
|
type _NoDoubleBookParkArmQueue = AssertAllKeysHandled<Extract<ParkArmQueueProjected, ParkArmQueueExcluded>>;
|
|
151
|
-
type TaskSpecWired = "objective" | "principal" | "images" | "sessionId" | "requireExistingSession" | "oneShot" | "clientContext" | "resumeAt" | "resumeAtMode" | "model" | "compactionModel" | "thinking" | "systemPrompt" | "appendSystemPrompt" | "promptProvider" | "memory" | "suggestNextPrompts" | "restoreFiles" | "acceptPartialRestore" | "rewindFilesTo" | "tools" | "excludeTools" | "deferTools" | "toolMaterializeStrategy" | "promptProfile" | "toolPolicy" | "onAsk" | "onQuestion" | "hooks" | "durableApproval" | "resourceSuspend" | "resilience" | "finalVerification" | "checkpointStore" | "handsReadOnly" | "memoryPersistenceCapable" | "additionalDirectories" | "additionalReadDirectories" | "enablePlanMode" | "interactiveTools" | "enableFork" | "shellGate" | "approvalReach" | "writeFace" | "mcp" | "a2a" | "skills" | "backgroundScope" | "envFacts" | "limits" | "configOverrides" | "forwardSubagentEvents" | "retainSubagentSessions" | "retainBackgroundProcesses" | "outputSchema" | "outputRetries" | "compaction" | "attachments" | "selfOrchestration" | "getApiKeyAndHeaders" | "interactionPosture" | "agents" | "permissionMode" | "taskId" | "signal" | "preemptSignal" | "
|
|
152
|
-
|
|
151
|
+
type TaskSpecWired = "objective" | "principal" | "images" | "sessionId" | "requireExistingSession" | "oneShot" | "clientContext" | "resumeAt" | "resumeAtMode" | "model" | "compactionModel" | "thinking" | "systemPrompt" | "appendSystemPrompt" | "promptProvider" | "memory" | "suggestNextPrompts" | "restoreFiles" | "acceptPartialRestore" | "rewindFilesTo" | "tools" | "excludeTools" | "deferTools" | "toolMaterializeStrategy" | "promptProfile" | "toolPolicy" | "onAsk" | "onQuestion" | "hooks" | "durableApproval" | "resourceSuspend" | "resilience" | "finalVerification" | "checkpointStore" | "handsReadOnly" | "memoryPersistenceCapable" | "additionalDirectories" | "additionalReadDirectories" | "enablePlanMode" | "interactiveTools" | "enableFork" | "shellGate" | "approvalReach" | "writeFace" | "mcp" | "a2a" | "skills" | "backgroundScope" | "envFacts" | "limits" | "configOverrides" | "forwardSubagentEvents" | "retainSubagentSessions" | "retainBackgroundProcesses" | "outputSchema" | "outputRetries" | "compaction" | "attachments" | "selfOrchestration" | "getApiKeyAndHeaders" | "interactionPosture" | "agents" | "permissionMode" | "taskId" | "signal" | "preemptSignal" | "maxSuspends" | "skillListingBudgetFraction" | "skillListingMaxDescChars" | "excludeAllTools" | "fileHistory" | "userInvokedSkills" | "outputStyle" | "allowedTools" | "allowTools";
|
|
152
|
+
/** 导出:请求体键闭集门(`request-key-closure.ts`)据它锁「本仓记为未接线的引擎座,提交口不许受理」—— 两处分类只能同向。 */
|
|
153
|
+
export type TaskSpecUnwired = "actor" | "roles" | "lspManager" | "tracer" | "readFace" | "readDenyPatterns" | "interactiveQuestionFallback" | "alwaysLoadTools" | "restoreGatedTools" | "deferSelfResolve" | "basePolicyForResumeEdit" | "lspDiagnostics" | "streamingToolExecution" | "toolResultThresholdChars" | "peerPresence" | "writeProtectedAdditions" | "complianceAdditionalDenies" | "modelRole" | "enableBlockedReport" | "userAttachments";
|
|
153
154
|
type _GuardTaskSpec = AssertAllKeysHandled<Exclude<keyof TaskSpec, TaskSpecWired | TaskSpecUnwired>>;
|
|
154
155
|
type _GuardTaskSpecReverse = AssertAllKeysHandled<Exclude<TaskSpecWired | TaskSpecUnwired, keyof TaskSpec>>;
|
|
155
156
|
type TaskResultForwarded = "taskId" | "runId" | "sessionId" | "terminal" | "model" | "effectiveReasoning" | "result" | "salvagedOutput" | "remoteEnvFailures" | "apiFailure" | "retryAfterMs" | "degraded" | "structuredOutput" | "rewindNotes" | "haltedOnUserRejection" | "haltedByUser" | "strandedHumanAnswers" | "pendingApproval" | "approvalWaitedMs" | "effectiveReadFace" | "effectiveReadDenyPatterns" | "effectiveWriteFace" | "effectiveMemoryScopes" | "stats" | "editedFiles" | "responseModel" | "compaction";
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* 同文件 G1 e2e 的全码扇出夹具、以及契约文档附录 D.3 那张表(含**小节标题里的码数** —— 那道门本批
|
|
17
17
|
* 刚立,立完就在下一次加码时自己咬住了)。
|
|
18
18
|
*/
|
|
19
|
-
export declare const ENGINE_NOTICE_WIRE_CODES: readonly ["memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "task.turn_interrupted", "steering.parked_input_blocked", "task.user_steer_undrained", "task.user_followup_undrained", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "task.halt_unconsumed", "task.late_approval", "config.durable_gate_unavailable", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit", "mcp.injection_dropped", "delegation.ask_unresolvable", "task.interrupt_unconsumed", "approval.read_root_granted", "approval.read_root_grant_rejected", "instructions.source_changed", "session.records_skipped", "server.model_unreachable", "classifier.unavailable", "config.permission_mode_unavailable", "permission.ask_released_by_mode", "permission.read_deny_unapplied", "permission.rule_store_unavailable", "permission.rule_row_dropped", "permission.allowed_tool_not_granted", "task.tool_turn_incomplete"];
|
|
19
|
+
export declare const ENGINE_NOTICE_WIRE_CODES: readonly ["memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "task.turn_interrupted", "steering.parked_input_blocked", "task.user_steer_undrained", "task.user_followup_undrained", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "task.halt_unconsumed", "task.late_approval", "config.durable_gate_unavailable", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit", "mcp.injection_dropped", "delegation.ask_unresolvable", "task.interrupt_unconsumed", "approval.read_root_granted", "approval.read_root_grant_rejected", "instructions.source_changed", "session.records_skipped", "server.model_unreachable", "classifier.unavailable", "config.permission_mode_unavailable", "permission.ask_released_by_mode", "permission.read_deny_unapplied", "permission.rule_store_unavailable", "permission.rule_row_dropped", "permission.allowed_tool_not_granted", "task.tool_turn_incomplete", "route.finish_reason_unknown", "route.stream_end_ignored"];
|
|
20
20
|
export type EngineNoticeWireCode = (typeof ENGINE_NOTICE_WIRE_CODES)[number];
|
|
21
21
|
/** 白名单谓词(单点):路由与门都读这一个,不许第二处手抄码串。 */
|
|
22
22
|
export declare function isEngineNoticeWireCode(code: string): code is EngineNoticeWireCode;
|
|
@@ -62,6 +62,31 @@ export interface EngineNoticeWireRow {
|
|
|
62
62
|
* · 其余(function / symbol / bigint / undefined)⇒ 丢键(JSON 不可承载或语义不明)。
|
|
63
63
|
*/
|
|
64
64
|
export declare function sanitizeNoticeDetail(detail: Record<string, unknown> | undefined): Record<string, unknown>;
|
|
65
|
+
/**
|
|
66
|
+
* `engine_notice` 载荷构造器(三条终点腿同源:live SSE / durable 账本 / 未来的任何第四条腿)。
|
|
67
|
+
*
|
|
68
|
+
* 与 `trace/project.ts` 的 `*EventData` 族同纪律(白名单挑键、禁 `{...notice}`),但**不住在那个文件里**:
|
|
69
|
+
* 那一族的入参全是 core `TaskEvent` 的臂(有 `wire-whitelist-exhaustiveness` 的臂集编译门看着),
|
|
70
|
+
* 而 `EngineNotice` 不是 `TaskEvent` —— 混进去会让那道门的语义变成"两个不同来源的联合",判别力反而降。
|
|
71
|
+
*/
|
|
72
|
+
/**
|
|
73
|
+
* 通告 `detail` 里**规则文本**的坐标:码 → `{ 数组键, 元素上的文本键 }`。新码的 detail 带规则文本时在这里登记(一张表,不在各处写分支)。
|
|
74
|
+
* 规则文本是人或模型写下的条目原串,最可能夹着凭据;这张表管的只有一件事 —— 它离开进程的每一条路都先过 {@link redactListEntry}。
|
|
75
|
+
* 导出是给钉用的:`test/notice-entry-presentation.test.ts` 的「日志行 = 会话流行」一组逐码迭代这张表,新登记的码自动入组。
|
|
76
|
+
*/
|
|
77
|
+
export declare const RULE_TEXT_DETAIL_FIELDS: Readonly<Record<string, {
|
|
78
|
+
readonly array: string;
|
|
79
|
+
readonly field: string;
|
|
80
|
+
}>>;
|
|
81
|
+
/**
|
|
82
|
+
* 通告 `message`(引擎铸的人读句)的脱敏 —— **唯一一只**:会话流行(经 {@link engineNoticeEventData},之后截到 {@link NOTICE_TEXT_MAX})与运维日志行
|
|
83
|
+
* (`boot/runner-deps.ts` 的转发席,不截)同调它 ⇒ 同一条通告的 `message` 在两条出路上逐字节同(会话流行另有 {@link NOTICE_TEXT_MAX} 字上限,
|
|
84
|
+
* 超长的那一截只在日志行上)。对**全部**通告码一视同仁,不按码分支:带规则文本的码(本表 {@link RULE_TEXT_DETAIL_FIELDS} 的登记码)的 `message` 里
|
|
85
|
+
* 条目以引擎的转义形出现,和别的自由文本一样只在这一只上被认凭据;认出凭据形才改字节,没有凭据形的句子逐字节原样。
|
|
86
|
+
* ⚠️ 已知边界(既有,两条出路同,见 CHANGELOG 7.120.0「条目」条):引擎把条目里的零宽字符写成 `\uXXXX` 转义,夹零宽字符的凭据在转义后的句子里认不出;
|
|
87
|
+
* 句子归引擎,本仓不改写 —— 机读位 `detail` 里的规则文本是在原串上认的({@link redactNoticeRuleText}),不受此限。
|
|
88
|
+
*/
|
|
89
|
+
export declare function redactNoticeMessage(message: unknown): string;
|
|
65
90
|
/**
|
|
66
91
|
* 通告 `detail` 里的**规则文本**换成条目的脱敏原值({@link redactListEntry}:凭据换记号,不加引号、不转义 —— 机读位不是显示面,显示形只属于人读句)。
|
|
67
92
|
* 会话流行(经 {@link engineNoticeEventData},之后照常过 {@link sanitizeNoticeDetail})与运维日志行(`boot/runner-deps.ts` 的转发席,其余字段逐字)
|
|
@@ -37,6 +37,8 @@ export const ENGINE_NOTICE_WIRE_CODES = [
|
|
|
37
37
|
"permission.rule_row_dropped",
|
|
38
38
|
"permission.allowed_tool_not_granted",
|
|
39
39
|
"task.tool_turn_incomplete",
|
|
40
|
+
"route.finish_reason_unknown",
|
|
41
|
+
"route.stream_end_ignored",
|
|
40
42
|
];
|
|
41
43
|
const WIRE_CODES = new Set(ENGINE_NOTICE_WIRE_CODES);
|
|
42
44
|
export function isEngineNoticeWireCode(code) {
|
|
@@ -93,10 +95,13 @@ function sanitizeValue(v, depth) {
|
|
|
93
95
|
}
|
|
94
96
|
return undefined;
|
|
95
97
|
}
|
|
96
|
-
const RULE_TEXT_DETAIL_FIELDS = {
|
|
98
|
+
export const RULE_TEXT_DETAIL_FIELDS = {
|
|
97
99
|
"permission.allowed_tool_not_granted": { array: "entries", field: "entry" },
|
|
98
100
|
"permission.rule_row_dropped": { array: "rows", field: "rule" },
|
|
99
101
|
};
|
|
102
|
+
export function redactNoticeMessage(message) {
|
|
103
|
+
return redactSecrets(String(message));
|
|
104
|
+
}
|
|
100
105
|
export function redactNoticeRuleText(code, detail) {
|
|
101
106
|
const at = Object.hasOwn(RULE_TEXT_DETAIL_FIELDS, code) ? RULE_TEXT_DETAIL_FIELDS[code] : undefined;
|
|
102
107
|
if (at === undefined || detail === undefined)
|
|
@@ -113,7 +118,7 @@ export function redactNoticeRuleText(code, detail) {
|
|
|
113
118
|
export function engineNoticeEventData(notice, sessionId, nowMs) {
|
|
114
119
|
return {
|
|
115
120
|
code: notice.code,
|
|
116
|
-
message:
|
|
121
|
+
message: redactNoticeMessage(notice.message).slice(0, NOTICE_TEXT_MAX),
|
|
117
122
|
detail: sanitizeNoticeDetail(redactNoticeRuleText(notice.code, notice.detail)),
|
|
118
123
|
sessionId,
|
|
119
124
|
ts: nowMs,
|
|
@@ -39,9 +39,15 @@ export type LedgerEventType = "reasoning" | "text" | "tool_start" | "tool_end" |
|
|
|
39
39
|
/** [ref](core 7.18.0):本条腿的**延迟工具普查**快照(policy / thresholdPercent? / deferred[] / activated[])。
|
|
40
40
|
* 与 `tool_roster_delta` 同判、同理由——**快照语义**(整只替换,回放零合并),而开腿那一份住在
|
|
41
41
|
* `wiring_manifest` 之后的首帧、**之后每一次激活**只活在本帧上。整帧缺席 = 这条腿什么都没延迟。
|
|
42
|
-
* 🔴 `tool_progress`([ref])
|
|
43
|
-
*
|
|
44
|
-
|
|
42
|
+
* 🔴 `tool_progress`([ref])**刻意不在本表**,理由是它自己的、不是「core 标了 LIVE ONLY」:那一条只是**引擎**的义务
|
|
43
|
+
* (不进会话树 / 检查点 / 续跑重放),本仓的账本是异步车道的活流与断线重连面,律是「EPHEMERAL 帧带着回放面没有第二来源的
|
|
44
|
+
* 事实 ⇒ 落账」(`status` / `task_progress` / `task_started` 都落)。`tool_progress` 的事实由同一只调用的 `tool_end` 推出
|
|
45
|
+
* (真源在那里;帧的缺席也从不是证据 —— 一个周期内跑完的调用零帧),所以它不落。 */
|
|
46
|
+
| "tool_disclosure" | "human_input"
|
|
47
|
+
/** core 7.50.0:委派子代**起跑**帧(每周期一只,先于子代的首个 `task_progress`)。按上面那一条律落账:
|
|
48
|
+
* `agentType` / `rootSessionId` / `parentSessionId` / `startedAt` 只骑这一帧,`task_progress` 上没有 ⇒ 不落则异步车道
|
|
49
|
+
* (`POST /v1/runs` 的活流就是 `GET /v1/runs/:id/events` 的账本 tail)永远读不到。两条 durable 腿主流 + forward 道各一处写口。 */
|
|
50
|
+
| "task_started" | "task_progress" | "task_notification" | "turn_end"
|
|
45
51
|
/** park 行名**两个**(`appendParked(kind)` 逐字取自 `result.status`)—— 运行期闭集见
|
|
46
52
|
* {@link PARK_LEDGER_EVENT_TYPES}(本联合是它的类型面,两者由下方的双向断言锁步)。 */
|
|
47
53
|
| "suspended" | "needs_review" | "done" | "failed" | "suggestions" | "model_usage" | "prompt_assembled" | "config_assembled" | "file_link"
|
|
@@ -97,6 +97,13 @@ export interface LedgerSink {
|
|
|
97
97
|
* ⚠️ 用它的前提是**这条腿的全部写口都走它**(混用一个绕开链的写口 = 病灶原样保留)。
|
|
98
98
|
*/
|
|
99
99
|
export declare function createSerialLedgerAppend(appendEvent: (seq: number, type: LedgerEventType, data: unknown) => Promise<void>, startSeq: number): (type: LedgerEventType, data: unknown) => Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* durable 腿 forward 道(fire-and-forget,同步回调里不能 await)的写失败出口 —— 一只,两处用:本汇的 `onForwardEvent`(bg 腿 +
|
|
102
|
+
* sync detach 车道 + 续跑腿的 verify 臂)与续跑腿自己的 forward 回调(`http/resume-legs.ts`,那里另有既有的逐次 warn 行)。
|
|
103
|
+
* F 类留痕 `server.ledger.forward-append-failed`:这一帧永远不在回放面(子代的起跑帧 / tick / 工具卡),run 照跑、不改任何裁决。
|
|
104
|
+
* 返回 `.catch` 用的处理器(产物是函数 ⇒ `create*`)。
|
|
105
|
+
*/
|
|
106
|
+
export declare function createForwardAppendFailedNote(type: string): (err: unknown) => void;
|
|
100
107
|
export declare function createLedgerSink(opts: {
|
|
101
108
|
/** The seq-stamped durable append — typically `(seq, type, data) => runStore.appendEvent(taskId, seq, type, data)`. */
|
|
102
109
|
appendEvent: (seq: number, type: LedgerEventType, data: unknown) => Promise<void>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {} from "@sema-agent/core";
|
|
2
2
|
import { outwardPlane } from "../terminal.js";
|
|
3
|
-
import {
|
|
3
|
+
import { recordFailOpen } from "../observability/fail-open.js";
|
|
4
|
+
import { modelTextEventData, toolStartEventData, toolEndEventData, taskProgressEventData, taskStartedEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, workspaceChangedEventData, wiringManifestEventData, toolRosterDeltaEventData, toolDisclosureEventData, humanInputEventData, turnEndEventData, contextUsageEventData } from "./project.js";
|
|
4
5
|
import { NotifiedKeys, taskNotificationStreamKeyOf } from "../orchestration/workflow-completion-inbox.js";
|
|
5
6
|
import { isParkLedgerEventType } from "./ledger-events.js";
|
|
6
7
|
import { isModelSegmentBoundary, reasoningDeltaBytes, reasoningSegmentEventId } from "./model-segment.js";
|
|
@@ -13,6 +14,9 @@ export function createSerialLedgerAppend(appendEvent, startSeq) {
|
|
|
13
14
|
return step;
|
|
14
15
|
};
|
|
15
16
|
}
|
|
17
|
+
export function createForwardAppendFailedNote(type) {
|
|
18
|
+
return (err) => recordFailOpen("server.ledger.forward-append-failed", `type=${type} err=${err instanceof Error ? err.message : String(err)}`);
|
|
19
|
+
}
|
|
16
20
|
export function createLedgerSink(opts) {
|
|
17
21
|
const keys = opts.notifiedKeys ?? new NotifiedKeys();
|
|
18
22
|
let seq = 0;
|
|
@@ -114,6 +118,9 @@ export function createLedgerSink(opts) {
|
|
|
114
118
|
case "human_input":
|
|
115
119
|
await append("human_input", humanInputEventData(ev));
|
|
116
120
|
break;
|
|
121
|
+
case "task_started":
|
|
122
|
+
await append("task_started", taskStartedEventData(ev));
|
|
123
|
+
break;
|
|
117
124
|
case "task_progress":
|
|
118
125
|
await append("task_progress", taskProgressEventData(ev));
|
|
119
126
|
break;
|
|
@@ -140,13 +147,16 @@ export function createLedgerSink(opts) {
|
|
|
140
147
|
const onForwardEvent = (e) => {
|
|
141
148
|
const t = e.type;
|
|
142
149
|
if (t === "task_progress") {
|
|
143
|
-
void append("task_progress", taskProgressEventData(e)).catch(()
|
|
150
|
+
void append("task_progress", taskProgressEventData(e)).catch(createForwardAppendFailedNote(t));
|
|
151
|
+
}
|
|
152
|
+
else if (t === "task_started") {
|
|
153
|
+
void append("task_started", taskStartedEventData(e)).catch(createForwardAppendFailedNote(t));
|
|
144
154
|
}
|
|
145
155
|
else if (t === "tool_start") {
|
|
146
|
-
void append("tool_start", toolStartEventData(e)).catch(()
|
|
156
|
+
void append("tool_start", toolStartEventData(e)).catch(createForwardAppendFailedNote(t));
|
|
147
157
|
}
|
|
148
158
|
else if (t === "tool_end") {
|
|
149
|
-
void append("tool_end", toolEndEventData(e)).catch(()
|
|
159
|
+
void append("tool_end", toolEndEventData(e)).catch(createForwardAppendFailedNote(t));
|
|
150
160
|
}
|
|
151
161
|
};
|
|
152
162
|
const appendStatus = (ev) => {
|