@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FileError, StubExecutionEnv, type ExecutionEnv, type Result, type ToolPolicy } from "@sema-agent/core";
|
|
1
|
+
import { FileError, StubExecutionEnv, type ExecutionEnv, type PathFamily, type Result, type ToolPolicy } from "@sema-agent/core";
|
|
2
2
|
import { type DeploymentListExemption } from "./approval.js";
|
|
3
3
|
import type { ServiceConfig } from "./config.js";
|
|
4
4
|
import type { applyRuntimeGovernance } from "./runtime-governance.js";
|
|
@@ -15,8 +15,9 @@ export interface DeploymentGovernanceConfigView {
|
|
|
15
15
|
readonly agentConfigDir?: ServiceConfig["agentConfigDir"];
|
|
16
16
|
/**
|
|
17
17
|
* 本部署的**本地店根**(`LOCAL_DATA_ROOT → CONFIG_LOCAL_DIR → AGENT_DATA_DIR → ~/.ai-agent`)—— 在本口只喂
|
|
18
|
-
* **誊本门**(`<localDataRoot>/sessions`)。S-133
|
|
19
|
-
*
|
|
18
|
+
* **誊本门**(`<localDataRoot>/sessions`)。S-133 起它**不再**当守卫集的数据根(那是引擎记忆根);core 7.49.0 [ref] 起守卫集
|
|
19
|
+
* 根本不收数据根 —— 豁免根只从 `RunnerDeps.memoryEngineDir` 一处来(`boot/runner-deps.ts` 共享基座,每只 boot Runner 同一个值)。
|
|
20
|
+
* 下面这段历史注保留,记的是 S-125 件⑦ 把两根混作一根的由来。
|
|
20
21
|
*
|
|
21
22
|
* S-125 件⑦(core 7.4.0 [ref] HRD-PRM-10)—— 当时把本键原样交给 `createSensitivePathPolicy` 的 `dataRoot`。
|
|
22
23
|
*
|
|
@@ -28,21 +29,10 @@ export interface DeploymentGovernanceConfigView {
|
|
|
28
29
|
* ⇒ 本键 = 「这道门与 transcript 门说的是同一个目录」的单一属主,值与 `ServiceConfig.localDataRoot`
|
|
29
30
|
* **同一个**解析结果(不在本口重算,重算就是第二个写者)。
|
|
30
31
|
*
|
|
31
|
-
* 缺席(窄接口的老调用方 / 测试夹具)⇒
|
|
32
|
-
* `rootPath` 条件展开同姿势:缺席是「本调用方没有这项知识」,不是「数据根是 undefined」。
|
|
32
|
+
* 缺席(窄接口的老调用方 / 测试夹具)⇒ 不铸誊本门(缺席是「本调用方没有这项知识」,不是「店根是 undefined」)。
|
|
33
33
|
*/
|
|
34
34
|
readonly localDataRoot?: ServiceConfig["localDataRoot"];
|
|
35
35
|
}
|
|
36
|
-
/**
|
|
37
|
-
* S-133 —— 守卫集 `dataRoot` 的**显式供给**(与 `DeploymentGovernanceConfigView.localDataRoot` 是两件事):
|
|
38
|
-
* `engineDataRoot` = 引擎写记忆的根 = boot 已铸的 `memoryEngine.root`(boot/stores.ts 是唯一写者;推导函数
|
|
39
|
-
* `memoryEngineRootFor` 只在那里与 `memoryEngineBackendFor` 里调)。**调用腿读那只活对象,不重推导**——重推导
|
|
40
|
-
* 就是第二个写者(7.59.0 重扫 codex 轮抓到 HTTP 腿的 fallback 与 stores 不同源,正是这一形)。参数非可选:
|
|
41
|
-
* 一条腿忘了 = 编译红。`undefined` = 引擎未接(或窄接口的测试夹具),那时不铸 `dataRoot` 键,core 走自己的缺省。
|
|
42
|
-
*/
|
|
43
|
-
export interface DeploymentGovernanceRoots {
|
|
44
|
-
readonly engineDataRoot: string | undefined;
|
|
45
|
-
}
|
|
46
36
|
/** 审批基线读的配置切面(同上,窄接口)。 */
|
|
47
37
|
export interface ApprovalBaselineConfigView {
|
|
48
38
|
readonly approvalRequire: ServiceConfig["approvalRequire"];
|
|
@@ -175,18 +165,26 @@ export declare function createDurableQuestionGate(live: LiveQuestionFace | undef
|
|
|
175
165
|
* · 词法层(`RelativeTargetLexicalEnv`)判 **缺戳相对形**(自身拼写里的守卫段,fail-closed);
|
|
176
166
|
* 两层射程互补、无重叠、无缝隙;各自射程外**显式 allow**(= 让位给另一层),canon 失败留给真的判不了的形
|
|
177
167
|
* (UNC/NUL/越根)—— 那正是 7.17.1 要 deny 的。提取写目标用 core 自家 `protectivePathTargetOf` + `pathTargetValue`
|
|
178
|
-
* (与 core 守卫策略同一只提取器,零复刻);「算不算绝对」用 core `isAbsoluteForFamily(
|
|
179
|
-
*
|
|
168
|
+
* (与 core 守卫策略同一只提取器,零复刻);「算不算绝对」用 core `isAbsoluteForFamily(SANDBOX_TREE_FAMILY, …)` —— 两层读
|
|
169
|
+
* **同一只**谓词(词法层的 `absolutePath` 拒的正是这一形),射程因此按构造互补。
|
|
170
|
+
*/
|
|
171
|
+
/**
|
|
172
|
+
* 沙箱 lane 的树是 **POSIX** 树(core 7.49.0 [ref] 起 `isAbsoluteForFamily` 的族参数必写:树的族,或无树时的 `"own"`)。
|
|
173
|
+
* 沙箱的文件系统是远端容器 / 机器的 POSIX 文件系统,词法层也按 POSIX 归一(`posix.normalize`)—— 所以这里写树的族,而不是 `"own"`:
|
|
174
|
+
* `"own"` 会把 `C:\x` / UNC 拼法读成绝对形送进真身层,而在 POSIX 树上它们是**相对文件名**(写进 cwd 的一个叫 `C:\x` 的文件)。
|
|
175
|
+
* 7.48.0 的 `undefined` 只认 `/`-rooted,与本常量逐字同判(读数不变)。
|
|
180
176
|
*/
|
|
177
|
+
export declare const SANDBOX_TREE_FAMILY: PathFamily;
|
|
181
178
|
type WriteTargetForm = "unstamped-relative" | "absolute-or-stamped";
|
|
182
179
|
/**
|
|
183
180
|
* 只在 `form` 那一类写目标上说话,其余显式 allow(让位);非写调用与提不出目标的调用原样交给 policy(它自己判 allow)。
|
|
184
181
|
*
|
|
185
182
|
* 🔴 **S-877(core 7.35.0 #1200):本包装不是 `wrapToolPolicy`,它自报成员**。core 的 wrap 契约是「包装至少拒内层所拒」,
|
|
186
183
|
* 而本包装**放行**内层会拒的另一形写目标 ⇒ 按契约它是一只自己的策略,内层的成员不能照搬(core wire 单点名这一只):
|
|
187
|
-
* · `
|
|
188
|
-
* ({@link
|
|
189
|
-
*
|
|
184
|
+
* · `writeGuardRows`(core 7.49.0 [ref] 起;7.48.0 叫 `writeTargetGuard`,旧成员 core **不按名拒** ⇒ 不改就是壳写站静默丢部署守卫行)
|
|
185
|
+
* —— 守卫集策略自带,壳写站按它交出的行判绝对目标;只在本层的形**覆盖行的判定形**时带上({@link WRITE_GUARD_ROWS_DOMAIN}):
|
|
186
|
+
* 真身层带;词法层不带(它的行与真身层是同一张模式表,带上只是同一组行判两遍)。这不是给某一形开的特例,是同一条
|
|
187
|
+
* 「成员描述它守得住的那部分」的读法;
|
|
190
188
|
* · `projection` / `pathRules` / `nameSets` —— 守卫集策略不带,本包装也不报(报了就是替它声称一张它没有的拒表)。
|
|
191
189
|
* 修前(core 7.33.x)这里是一只 `{ check }` 字面量,7.34.0 起那只字面量把真身层的守卫剥掉了 —— 沙箱 lane 的 shell 写站
|
|
192
190
|
* 因此看不见部署守卫集(`cp x .env` 在 acceptEdits 下被引擎 place 并答掉)。
|
|
@@ -253,7 +251,7 @@ export declare function buildOnlySensitiveBaselineWarning(config: Pick<Deploymen
|
|
|
253
251
|
* 本口不知道出身这件事,也不再有自己的折叠点。叶的顺序 = 修前折叠的顺序(真身层 → 词法层 → 誊本门),deny 优先 / 首问 / 成员合并
|
|
254
252
|
* 的读法因此不变。
|
|
255
253
|
*/
|
|
256
|
-
export declare function createDeploymentGovernanceInputs(config: DeploymentGovernanceConfigView, pathAdjudication: PathAdjudication
|
|
254
|
+
export declare function createDeploymentGovernanceInputs(config: DeploymentGovernanceConfigView, pathAdjudication: PathAdjudication): DeploymentGovernanceInputs;
|
|
257
255
|
/**
|
|
258
256
|
* 运维 allow 表 `APPROVAL_GRANT` 的**起服通告**载荷(纯数据 ⇒ `build*`;HTTP 腿与 run-local 腿各在装配时说一次,用 info 级)。规则不是秘密
|
|
259
257
|
* (它们是工具名 / 命令规则),所以原样列出;空表 ⇒ `undefined`(不打)。运维只读面上同一个事实另有一处:`GET /v1/diagnostics/wiring` 的
|
|
@@ -16,6 +16,7 @@ export function createDurableQuestionGate(live) {
|
|
|
16
16
|
},
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
|
+
export const SANDBOX_TREE_FAMILY = "posix";
|
|
19
20
|
function writeTargetFormOf(req) {
|
|
20
21
|
if (!isProtectedWrite(req))
|
|
21
22
|
return undefined;
|
|
@@ -23,11 +24,11 @@ function writeTargetFormOf(req) {
|
|
|
23
24
|
const target = pt === undefined ? undefined : pathTargetValue(req.args, pt);
|
|
24
25
|
if (typeof target !== "string" || target.length === 0)
|
|
25
26
|
return undefined;
|
|
26
|
-
if (req.cwd !== undefined || target.includes("\u0000") || isAbsoluteForFamily(
|
|
27
|
+
if (req.cwd !== undefined || target.includes("\u0000") || isAbsoluteForFamily(SANDBOX_TREE_FAMILY, target))
|
|
27
28
|
return "absolute-or-stamped";
|
|
28
29
|
return "unstamped-relative";
|
|
29
30
|
}
|
|
30
|
-
const
|
|
31
|
+
const WRITE_GUARD_ROWS_DOMAIN = "absolute-or-stamped";
|
|
31
32
|
export function scopedToWriteTargetForm(policy, form) {
|
|
32
33
|
return {
|
|
33
34
|
async check(req, signal) {
|
|
@@ -36,12 +37,12 @@ export function scopedToWriteTargetForm(policy, form) {
|
|
|
36
37
|
return { action: "allow" };
|
|
37
38
|
return policy.check(req, signal);
|
|
38
39
|
},
|
|
39
|
-
...(form ===
|
|
40
|
+
...(form === WRITE_GUARD_ROWS_DOMAIN && policy.writeGuardRows !== undefined ? { writeGuardRows: policy.writeGuardRows } : {}),
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
export class RelativeTargetLexicalEnv extends StubExecutionEnv {
|
|
43
44
|
absolutePath(path) {
|
|
44
|
-
if (path.length === 0 || path
|
|
45
|
+
if (path.length === 0 || isAbsoluteForFamily(SANDBOX_TREE_FAMILY, path) || path.includes("\u0000")) {
|
|
45
46
|
return Promise.resolve(err(new FileError("not_supported", "this guard layer only adjudicates RELATIVE write targets (absolute forms are adjudicated against the real sandbox filesystem)", path)));
|
|
46
47
|
}
|
|
47
48
|
return Promise.resolve(ok(posix.normalize(`/${path}`)));
|
|
@@ -83,16 +84,14 @@ export function buildOnlySensitiveBaselineWarning(config, seat) {
|
|
|
83
84
|
},
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
|
-
export function createDeploymentGovernanceInputs(config, pathAdjudication
|
|
87
|
+
export function createDeploymentGovernanceInputs(config, pathAdjudication) {
|
|
87
88
|
const sensitivePathLayers = config.sensitiveWritePatterns.length > 0
|
|
88
89
|
? (() => {
|
|
89
|
-
const dataRootOpt = roots.engineDataRoot !== undefined ? { dataRoot: roots.engineDataRoot } : {};
|
|
90
90
|
const configRootOpt = config.agentConfigDir !== undefined ? { agentConfigDir: config.agentConfigDir } : {};
|
|
91
91
|
const realTarget = createSensitivePathPolicy({
|
|
92
92
|
env: pathAdjudication.env,
|
|
93
93
|
patterns: config.sensitiveWritePatterns,
|
|
94
94
|
...(pathAdjudication.cwd !== undefined ? { rootPath: pathAdjudication.cwd } : {}),
|
|
95
|
-
...dataRootOpt,
|
|
96
95
|
...configRootOpt,
|
|
97
96
|
});
|
|
98
97
|
const transcriptGuard = config.localDataRoot !== undefined ? [createTranscriptIntegrityPolicy({ sessionsDirs: [join(config.localDataRoot, "sessions")] })] : [];
|
|
@@ -100,7 +99,7 @@ export function createDeploymentGovernanceInputs(config, pathAdjudication, roots
|
|
|
100
99
|
return [realTarget, ...transcriptGuard];
|
|
101
100
|
return [
|
|
102
101
|
scopedToWriteTargetForm(realTarget, "absolute-or-stamped"),
|
|
103
|
-
scopedToWriteTargetForm(createSensitivePathPolicy({ env: new RelativeTargetLexicalEnv(), patterns: config.sensitiveWritePatterns, ...
|
|
102
|
+
scopedToWriteTargetForm(createSensitivePathPolicy({ env: new RelativeTargetLexicalEnv(), patterns: config.sensitiveWritePatterns, ...configRootOpt }), "unstamped-relative"),
|
|
104
103
|
...transcriptGuard,
|
|
105
104
|
];
|
|
106
105
|
})()
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* · `example` 进拒句;
|
|
7
7
|
* · `multiTenant` = `REQUIRE_PRINCIPAL=true` 下名单作不作数 —— **只有服务进程读的旋钮有这一列**(姿态是服务进程的概念):
|
|
8
8
|
* - `LSP_ENV_ALLOW` ⇒ ignored:host 腿语言服务器在多租户姿态下本来就不起,名单无处作数,设了要说出来(S-699)。
|
|
9
|
-
* -
|
|
10
|
-
* 带外凭据(e2b / docker 车道本来就是多租户 fleet 的主形),与 LSP 那条「本机子进程」的形不同;多租户下起服说一句。
|
|
9
|
+
* - 三只沙箱名单(e2b / local-docker / k8s 各一只) ⇒ honored:S-713 照录修前语义(任何姿态下都转发),S-715 主会话裁定维持 —— 沙箱 env 是部署方为隔离沙箱显式配的
|
|
10
|
+
* 带外凭据(e2b / docker / k8s 车道本来就是多租户 fleet 的主形),与 LSP 那条「本机子进程」的形不同;多租户下起服说一句。
|
|
11
11
|
* · `BAKE_ENV_ALLOW`(S-684 残余,7.103.0)由 **bake-runner 进程**读(构建宿主守护进程:没有主体、没有租户 ⇒ 没有姿态列,
|
|
12
|
-
* 不进 {@link describeAllowlistPostures} 的姿态句)
|
|
12
|
+
* 不进 {@link describeAllowlistPostures} 的姿态句)。它与服务侧四只旋钮同一只解析器、同一只「点名放行」谓词、同一条「原文按凭据类」律。
|
|
13
13
|
* 表是 `Record<旋钮, …>`:闭集加一只旋钮而不补行 = 编译红;行形随读它的进程定(服务进程 ⇒ 必须写姿态列)。
|
|
14
14
|
*
|
|
15
15
|
* 🔴 **姿态列只在这里写一次**([ref];7.101.0 合并复审 O9):凡要对人说「多租户下哪只旋钮忽略、哪只照转发」的句子,一律取
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* 当场撒谎。为什么是纯叶:`config-catalog.ts` 被 `config.ts` 值引,表留在 `config.ts` 会成装载环。
|
|
19
19
|
*/
|
|
20
20
|
/** 服务进程(`config.ts` `loadConfig`)读的名单型旋钮 —— 有多租户姿态。 */
|
|
21
|
-
export type ServerEnvNameAllowlistKnob = "LSP_ENV_ALLOW" | "E2B_SANDBOX_ENV" | "DOCKER_SANDBOX_ENV";
|
|
21
|
+
export type ServerEnvNameAllowlistKnob = "LSP_ENV_ALLOW" | "E2B_SANDBOX_ENV" | "DOCKER_SANDBOX_ENV" | "K8S_SANDBOX_ENV";
|
|
22
22
|
/** bake-runner 进程(`bake-runner/main.ts` `loadEnv`)读的名单型旋钮 —— 构建宿主守护进程没有主体 / 租户,没有姿态。 */
|
|
23
23
|
export type RunnerEnvNameAllowlistKnob = "BAKE_ENV_ALLOW";
|
|
24
24
|
export type EnvNameAllowlistKnob = ServerEnvNameAllowlistKnob | RunnerEnvNameAllowlistKnob;
|
|
@@ -41,7 +41,7 @@ export type EnvNameAllowlistKnobTable = {
|
|
|
41
41
|
readonly [K in EnvNameAllowlistKnob]: K extends ServerEnvNameAllowlistKnob ? ServerEnvNameAllowlistKnobRow : RunnerEnvNameAllowlistKnobRow;
|
|
42
42
|
};
|
|
43
43
|
export declare const ENV_NAME_ALLOWLIST_KNOBS: EnvNameAllowlistKnobTable;
|
|
44
|
-
/** 名单型旋钮的全部名字(
|
|
44
|
+
/** 名单型旋钮的全部名字(五只;表键派生)—— 两处用:解析器的「点名名单型旋钮 = 形错」、剥除的「名单原文按凭据类」臂。 */
|
|
45
45
|
export declare const ENV_NAME_ALLOWLIST_KNOB_NAMES: ReadonlySet<string>;
|
|
46
46
|
/**
|
|
47
47
|
* 多租户姿态句 —— **由表派生**,不许在别处手写。形:`under REQUIRE_PRINCIPAL=true: <旋钮> is ignored; <旋钮> / <旋钮> are forwarded as configured`
|
|
@@ -5,6 +5,7 @@ export const ENV_NAME_ALLOWLIST_KNOBS = {
|
|
|
5
5
|
},
|
|
6
6
|
E2B_SANDBOX_ENV: { example: "E2B_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", multiTenant: { kind: "honored" } },
|
|
7
7
|
DOCKER_SANDBOX_ENV: { example: "DOCKER_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", multiTenant: { kind: "honored" } },
|
|
8
|
+
K8S_SANDBOX_ENV: { example: "K8S_SANDBOX_ENV=GIT_TOKEN,NPM_TOKEN", multiTenant: { kind: "honored" } },
|
|
8
9
|
BAKE_ENV_ALLOW: { example: "BAKE_ENV_ALLOW=REGISTRY_PASSWORD,NPM_TOKEN" },
|
|
9
10
|
};
|
|
10
11
|
export const ENV_NAME_ALLOWLIST_KNOB_NAMES = new Set(Object.keys(ENV_NAME_ALLOWLIST_KNOBS));
|
|
@@ -190,6 +190,18 @@ export declare function executionLaneOf(provider: string | undefined): Execution
|
|
|
190
190
|
* ③ `approval.ts` 的 `buildNoResponderBootWarns` —— 写门的 ask 只在「有手写本机盘」时才会发生。
|
|
191
191
|
*/
|
|
192
192
|
export declare function handsOnWorkerFilePlane(lane: ExecutionLane): boolean;
|
|
193
|
+
/**
|
|
194
|
+
* core 7.50.0 —— 「这条车道的执行环境能不能把一次读**绑到判过的那只对象**上」(`FileSystem.openBound`:开着并持有,叶链接不跟,
|
|
195
|
+
* 开后身份对拍)。LSP 会话的读口与路径附件只经它读;环境不实现 ⇒ 那两个读口在这条车道上一律拒。
|
|
196
|
+
*
|
|
197
|
+
* **一条律**:LSP 只在本谓词为真的车道挂(`boot/execution-env.ts` 的 LSP 管理器两臂都合取它;表的 `lsp` 位与之同向,
|
|
198
|
+
* 对拍钉 `test/host-env-open-bound.test.ts`:本谓词 ⟺ 适配器类原型上有 `openBound`)。
|
|
199
|
+
* · `host` —— `RemoteHostExecutionEnv.openBound` 委托 core `NodeExecutionEnv` 的实现(唯一属主),真;
|
|
200
|
+
* · `in-process` —— 没有手(core 落桩环境),无物可绑;
|
|
201
|
+
* · 其余车道(沙箱 / 远端 shell / 设备)—— 读走 exec / sftp / 设备协议,本版不实现绑定读,假。实现之日翻这一格,LSP 沙箱桥随之回来。
|
|
202
|
+
* 穷举 switch、无 default 臂:车道加词而此处不表态 = 编译红。
|
|
203
|
+
*/
|
|
204
|
+
export declare function laneBindsReads(lane: ExecutionLane): boolean;
|
|
193
205
|
/**
|
|
194
206
|
* S-281 —— 「这条车道的手在不在 OS 级隔离边界里」。**全仓唯一**的布尔判别式(读表 `isolation` 位,见该位头注的读者清单)。
|
|
195
207
|
* 穷举 switch、无 default 臂:`isolation` 的型只有两档,加档 = 编译红。
|
|
@@ -46,7 +46,7 @@ export function executionLaneCaps(lane) {
|
|
|
46
46
|
callerCwd: NO,
|
|
47
47
|
backgroundShell: YES,
|
|
48
48
|
scheduler: NO,
|
|
49
|
-
lsp:
|
|
49
|
+
lsp: NO,
|
|
50
50
|
sandboxSendUserFile: YES,
|
|
51
51
|
isolation: YES,
|
|
52
52
|
suspendable: YES,
|
|
@@ -56,7 +56,7 @@ export function executionLaneCaps(lane) {
|
|
|
56
56
|
memoryPersistenceCapable: NO,
|
|
57
57
|
hostFilePlane: NO,
|
|
58
58
|
coreRemoteExecutionEnv: YES,
|
|
59
|
-
canonicalPathAuthority:
|
|
59
|
+
canonicalPathAuthority: YES,
|
|
60
60
|
tenantSeparation: executionLaneRow(lane).tenantSeparation,
|
|
61
61
|
};
|
|
62
62
|
case "k8s":
|
|
@@ -64,7 +64,7 @@ export function executionLaneCaps(lane) {
|
|
|
64
64
|
callerCwd: NO,
|
|
65
65
|
backgroundShell: YES,
|
|
66
66
|
scheduler: NO,
|
|
67
|
-
lsp:
|
|
67
|
+
lsp: NO,
|
|
68
68
|
sandboxSendUserFile: YES,
|
|
69
69
|
isolation: YES,
|
|
70
70
|
suspendable: YES,
|
|
@@ -128,7 +128,7 @@ export function executionLaneCaps(lane) {
|
|
|
128
128
|
memoryPersistenceCapable: NO,
|
|
129
129
|
hostFilePlane: NO,
|
|
130
130
|
coreRemoteExecutionEnv: YES,
|
|
131
|
-
canonicalPathAuthority:
|
|
131
|
+
canonicalPathAuthority: YES,
|
|
132
132
|
tenantSeparation: executionLaneRow(lane).tenantSeparation,
|
|
133
133
|
};
|
|
134
134
|
case "device":
|
|
@@ -202,6 +202,20 @@ export function handsOnWorkerFilePlane(lane) {
|
|
|
202
202
|
const caps = executionLaneCaps(lane);
|
|
203
203
|
return caps.hostFilePlane === "supported" && caps.coreRemoteExecutionEnv === "supported";
|
|
204
204
|
}
|
|
205
|
+
export function laneBindsReads(lane) {
|
|
206
|
+
switch (lane) {
|
|
207
|
+
case "host":
|
|
208
|
+
return true;
|
|
209
|
+
case "in-process":
|
|
210
|
+
case "e2b":
|
|
211
|
+
case "k8s":
|
|
212
|
+
case "ssh":
|
|
213
|
+
case "adb":
|
|
214
|
+
case "device":
|
|
215
|
+
case "local-docker":
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
205
219
|
export function laneIsolated(lane) {
|
|
206
220
|
const isolation = executionLaneCaps(lane).isolation;
|
|
207
221
|
switch (isolation) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { redactSecrets } from "../trace/redact.js";
|
|
2
|
-
import { taskProgressEventData, toolStartEventData, toolEndEventData, textEndEventData } from "../trace/project.js";
|
|
2
|
+
import { taskProgressEventData, taskStartedEventData, toolStartEventData, toolEndEventData, textEndEventData } from "../trace/project.js";
|
|
3
|
+
import { liveMediaBytesOf, liveToolEndForBacklog } from "../trace/tool-output-media.js";
|
|
3
4
|
import { createReasoningSegments } from "../trace/model-segment.js";
|
|
4
5
|
const TAIL_QUEUE_CAP = 512;
|
|
5
6
|
export function projectTailFrame(e) {
|
|
@@ -7,6 +8,9 @@ export function projectTailFrame(e) {
|
|
|
7
8
|
if (t === "task_progress") {
|
|
8
9
|
return { type: "task_progress", ...taskProgressEventData(e) };
|
|
9
10
|
}
|
|
11
|
+
if (t === "task_started") {
|
|
12
|
+
return { type: "task_started", ...taskStartedEventData(e) };
|
|
13
|
+
}
|
|
10
14
|
if (t === "tool_start") {
|
|
11
15
|
const tsv = e;
|
|
12
16
|
return { type: "tool_start", ...toolStartEventData(tsv) };
|
|
@@ -80,10 +84,14 @@ export class SubagentTailBus {
|
|
|
80
84
|
if (sub.closed)
|
|
81
85
|
continue;
|
|
82
86
|
if (sub.queue.length >= TAIL_QUEUE_CAP) {
|
|
83
|
-
sub.queue.shift();
|
|
87
|
+
const oldest = sub.queue.shift();
|
|
88
|
+
if (oldest !== undefined)
|
|
89
|
+
sub.mediaBytes -= liveMediaBytesOf(oldest);
|
|
84
90
|
sub.dropped++;
|
|
85
91
|
}
|
|
86
|
-
|
|
92
|
+
const queued = frame.type === "tool_end" ? liveToolEndForBacklog(frame, sub.mediaBytes) : frame;
|
|
93
|
+
sub.mediaBytes += liveMediaBytesOf(queued);
|
|
94
|
+
sub.queue.push(queued);
|
|
87
95
|
sub.wake?.();
|
|
88
96
|
}
|
|
89
97
|
}
|
|
@@ -91,7 +99,7 @@ export class SubagentTailBus {
|
|
|
91
99
|
return (this.subs.get(bgAgentId)?.size ?? 0) > 0;
|
|
92
100
|
}
|
|
93
101
|
subscribe(bgAgentId) {
|
|
94
|
-
const sub = { queue: [], dropped: 0, closed: false };
|
|
102
|
+
const sub = { queue: [], dropped: 0, mediaBytes: 0, closed: false };
|
|
95
103
|
let set = this.subs.get(bgAgentId);
|
|
96
104
|
if (!set) {
|
|
97
105
|
set = new Set();
|
|
@@ -121,8 +129,10 @@ export class SubagentTailBus {
|
|
|
121
129
|
return { value: { type: "lagged", dropped }, done: false };
|
|
122
130
|
}
|
|
123
131
|
const head = sub.queue.shift();
|
|
124
|
-
if (head !== undefined)
|
|
132
|
+
if (head !== undefined) {
|
|
133
|
+
sub.mediaBytes -= liveMediaBytesOf(head);
|
|
125
134
|
return { value: head, done: false };
|
|
135
|
+
}
|
|
126
136
|
if (sub.closed)
|
|
127
137
|
return { value: undefined, done: true };
|
|
128
138
|
await new Promise((resolve) => {
|
|
@@ -43,16 +43,17 @@ export interface ParseHooksConfigResult {
|
|
|
43
43
|
* ⇒ **永不命中、一句话都没有**(post 两事件自 7.107.0 / core 7.36.0 起如此,PreToolUse 一直如此)。静默不命中 = 写的人以为在生效的 hook
|
|
44
44
|
* 其实没跑,硬破坏三句要求的「响亮」没有着落。7.112.0(S-924)只拒**字面**别名;同一个错误写成 `^ListPeers$` / `ListPeers.*` / `(ListPeers)` 照样 200(S-995)。
|
|
45
45
|
*
|
|
46
|
-
* 规则(一条;字面形是它的特例):{@link
|
|
46
|
+
* 规则(一条;字面形是它的特例):{@link toolMatcherIssue} 对 core 静态目录里**每一条退役别名**问「这只 matcher 选不选它 / 选不选它的正名」:
|
|
47
47
|
* matcher **命中别名 ∧ 不命中它的正名** ⇒ `400 request.field_invalid`(`admission.ts` fresh 门)。「选不选」**只有一只读法**:契约包的 `hookMatcherSelects`
|
|
48
48
|
* (名字表 / 空 / `*` / 正则三形都由它答;正则形**不锚定**,与壳同形;运行期 {@link hookMatcherMatches} 问的也是它,本仓不留副本)。按**一条顺序**判(两档共用,7.114.0 修复轮):
|
|
49
49
|
* ① **长度上限**:超 {@link MAX_MATCHER_EVAL_CHARS} 的 matcher 两档都不读 ⇒ 未判(reason = oversize);
|
|
50
50
|
* ② **形只问契约包的 `hookMatcherForm`**(与 `hookMatcherSelects` 同一只解析步,本仓不留形判),闭集三词、两档一张表:
|
|
51
51
|
* · `literal`(缺席 / 空 / `*` / 名字表形;契约不编、不跑调用方的正则)⇒ 两档都**直接问契约函数**、**不占求值预算**;
|
|
52
|
-
* · `regex` ⇒ **`"regex"` 档**(hooks 会被采纳的车道,`taskHooksHonored`)把**同一只契约函数**经 `node:vm` 的 `timeout`
|
|
52
|
+
* · `regex` ⇒ **`"regex"` 档**(hooks 会被采纳的车道,`taskHooksHonored`)把**同一只契约函数**经 `node:vm` 的 `timeout` 带**每次求值各一份固定预算**调用({@link matcherSelectsWithin};
|
|
53
|
+
* 预算**不共享**、不随同一受理里别的 matcher 耗尽、不读钟 —— S-1455);**超时 ⇒ 这只 matcher 是灾难回溯 ⇒ `400 request.field_invalid` 拒**(见下「预算与结局」);
|
|
53
54
|
* **`"literal"` 档**(多租户车道:hooks 整只被 resolveSpec 忽略)= **不适用**:该车道没有被守的对象(hooks 不装配),不判、不算未判、不登记 —— **零调用方正则执行**
|
|
54
55
|
* (7.112.0 的字面判保留:裸 `ListPeers` / `Read|ListPeers` 照旧 400);
|
|
55
|
-
* · `invalid`(编不过)⇒ `"regex"` 档 =
|
|
56
|
+
* · `invalid`(编不过)⇒ `"regex"` 档 = **`400 request.field_invalid` 拒**(判决 `invalid_regex`,见下「预算与结局」;不进求值 —— 形判已答「读不了」);`"literal"` 档 = 不适用(同上)。
|
|
56
57
|
* 形判在 `literal` 档也跑:契约的解析步对非名字表形**构造**(只解析、不执行)一次调用方的 pattern 以分出 regex / invalid —— 长度已被 ① 界住;执行恒为零。
|
|
57
58
|
* · **为什么两档**(codex r1 [high] + 主会话裁):受理面是**所有**车道,而运行期只有单用户车道跑 hooks。在受理线程上跑调用方的正则 = 给多租户加一个事件循环 DoS 面
|
|
58
59
|
* (实测:`(.*)*` ×10 + `X` 对 9 字符名字首次执行 1.7 s,18 字符嵌套形 15 s,24 字符 157 s;8 MiB 交替串编译 + 求值 9 s)—— 预算只界住一次请求、界不住「每个请求再拿一份」。
|
|
@@ -73,63 +74,116 @@ export interface ParseHooksConfigResult {
|
|
|
73
74
|
* · **不在本规则内**:两边都选不中的 matcher(大小写错 / 词内空白 / 纯错字;目录之外的 MCP / 嵌入方工具名同样「选不中目录里任何名」,受理面无从区分错字与它们)=
|
|
74
75
|
* **「选不到目录里任何名」另一类,候设计(台账另立号,主会话裁)**。
|
|
75
76
|
*
|
|
77
|
+
* 🔴 **预算与结局(S-1455;受理结局只取决于配置,不取决于机器忙闲)**:regex 档每一次求值(一只正则形 matcher 对一个名字的一次问)各拿**一份固定的墙钟预算**
|
|
78
|
+
* {@link ADMISSION_MATCHER_EVAL_BUDGET_MS}(vm `timeout`,从这次求值开始计)—— **不共享**(此前一次受理共用 100 ms,忙机上会被吃光 ⇒
|
|
79
|
+
* 同一份设置忙机偶尔被收下、闲机恒 400),不随同一受理里 matcher 的个数耗尽,判据里**没有时钟**(没有「截止线」可被调度停顿越过)。预算只防**灾难回溯**:
|
|
80
|
+
* 良性求值 ~0.1 ms,灾难形(指数级)吃满预算也跑不完 —— 两者相差数个数量级,取值给足余量(1 000 ms),让忙机上的调度停顿也跨不过这条线。
|
|
81
|
+
* **超时 ⇒ 确定拒绝**:`400 request.field_invalid`({@link OverBudgetMatcherIssue}),句子点名**哪一只 matcher**(事件 + 组下标,不回显原字节)与**预算**;**按配置顺序遇到的第一只超时 / 命中别名的 matcher 定结局**。
|
|
82
|
+
* 为什么是拒绝而不是放行:运行期 {@link hookMatcherMatches} 在**每次工具调用**里直接问同一只契约函数、**没有任何预算** —— 一只在受理面都跑不完的 matcher 放进去,
|
|
83
|
+
* 每次调用都会把事件循环卡住;放行 = 把一个确定的坏配置推迟成运行期的随机卡死。这条拒不是「越界即拒」的新检测面:被拒的恰是**无法被求值**的 matcher,与 `hook_matcher_invalid`(编不过 ⇒ 该组不跑)同属「这只 matcher 不可用」,
|
|
84
|
+
* 只是编不过的运行期自己安全地不跑它,跑不完的不行。
|
|
85
|
+
* 总用时的上界:首个超时即拒、不再往下求值;未超时的求值各自 < 预算。regex 档只在单用户车道(`taskHooksHonored`,hooks 会装配的那条;调用方就是进程属主,本来就能配任意 `command` 钩子)运行,
|
|
86
|
+
* 多租户车道走 literal 档、零调用方正则执行 —— 受理面的 DoS 面不因此重开。
|
|
87
|
+
*
|
|
88
|
+
* 🔴 **编不过的正则 = 确定的拒绝**(S-1455 收尾;与超预算同类 —— 确定性的坏配置,结局只取决于配置):`"regex"` 档遇契约 `hookMatcherForm` 答 `invalid`(或求值时契约函数答 `"invalid"`)⇒
|
|
89
|
+
* `400 request.field_invalid`({@link InvalidRegexMatcherIssue}),句子点名**哪一只 matcher**(事件 + 组下标 + 原文〔超 {@link MATCHER_ECHO_CHARS} 字符截断〕)与引擎的编译错误句;机读位 `detail` 只有闭集三键。
|
|
90
|
+
* 受理面与运行期问**同一只判**:契约把"编不过"答成 `invalid`,运行期 {@link hookMatcherMatches} 因此不跑那一组(并记 `hook_matcher_invalid`),受理面因此拒 —— 本仓不加第二个判官
|
|
91
|
+
* (编译错误句只是诊断文字,见 {@link matcherCompileSentence};拒不拒由契约函数一个人说了算)。为什么是拒绝而不是放行:放行 = 用户以为在生效的钩子(含会真拦的 PreToolUse deny 钩子)
|
|
92
|
+
* 在每次工具调用里都**悄悄不跑**,硬破坏三句要求的「响亮」没有着落;`"literal"` 档(多租户车道,hooks 不装配)= 不适用,与正则形同一行表。resume 重放不判(照旧采纳、该组不跑)。
|
|
93
|
+
* 🔴 **边界(如实披露)**:判据只守三个工具事件(`matcherReadsWireToolName`)—— 写在别的带 matcher 的事件(`StopFailure` 的 `error` 词 / `PreCompact`·`PostCompact` 的 `trigger` 词)上的坏 matcher 仍受理、运行期该组不跑并记 `hook_matcher_invalid`。
|
|
94
|
+
*
|
|
76
95
|
* 🔴 **「未判」臂过 `recordFailOpen`**(F 类 tag `MATCHER_UNJUDGED_TAG`;主会话裁,CLAUDE.md「合法 F 类回退走登记 tag」):一只 matcher 没能被判 ⇒ 照旧受理 + 登记一笔,
|
|
77
|
-
* detail = `event=… reason=… matcherChars=…`(**不带 matcher 原字节**,S-716 姿势)
|
|
78
|
-
* `oversize` —— 两档:matcher 超 {@link MAX_MATCHER_EVAL_CHARS} 字符不读(多租户车道上 hooks 不装配,这一笔只为让超长输入显形)
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* 放行最坏后果 = 那一只 matcher 没被这条判据守住、照旧永不命中,**不是安全闸**(受理面有效性判);反方向「越界即拒」会把负载抖动 / 病态但合法的 matcher 变成对合法请求的 400。
|
|
96
|
+
* detail = `event=… reason=… matcherChars=…`(**不带 matcher 原字节**,S-716 姿势)。现在只剩一种 reason:
|
|
97
|
+
* `oversize` —— 两档:matcher 超 {@link MAX_MATCHER_EVAL_CHARS} 字符不读(多租户车道上 hooks 不装配,这一笔只为让超长输入显形)。
|
|
98
|
+
* (`over_budget` 臂自 S-1455 起退役:它是「预算用尽 ⇒ 照旧受理」的随负载翻转的结局,现在是上面的确定拒绝;`invalid_regex` 臂自 S-1455 收尾起退役,同理。)
|
|
99
|
+
* 放行最坏后果 = 那一只 matcher 没被这条判据守住、照旧永不命中,**不是安全闸**(受理面有效性判)。
|
|
82
100
|
* 拒放集合相对 7.113.0 的一处放宽(披露在 CHANGELOG / MIGRATION):超过上限的字面别名 matcher 7.113.0 拒(当时字面判不设上限),自 7.114.0 两档都判未判、受理。
|
|
83
101
|
*
|
|
84
|
-
*
|
|
102
|
+
* 错误句:死别名与超预算两形只回显**目录里的**别名与正名 / 位置(闭集字符串与数字),不回显调用方的原字节(S-716 姿势);编不过一形**点名那只 matcher 的原文**(截断到 {@link MATCHER_ECHO_CHARS} 字符)与引擎的编译错误句 ——
|
|
103
|
+
* 调用方要改的就是这一串,且它本来就是调用方自己送来的;机读位 `detail` 仍不带这两段。
|
|
85
104
|
*
|
|
86
|
-
* 🔴 **判决是数据,句子与体的机读位同出一只铸点**(S-1025;client-core 请托,additive):{@link
|
|
87
|
-
* 而不是句子;{@link
|
|
88
|
-
*
|
|
105
|
+
* 🔴 **判决是数据,句子与体的机读位同出一只铸点**(S-1025;client-core 请托,additive):{@link toolMatcherIssue} 回 {@link ToolMatcherIssue}(闭集三形:{@link DeadToolMatcherIssue} 的 event / alias / canonical,
|
|
106
|
+
* {@link OverBudgetMatcherIssue} 的 event / groupIndex / budgetMs,{@link InvalidRegexMatcherIssue} 的 event / groupIndex〔+ 句子用的 matcher / compileError〕,以 `reason` 区分)而不是句子;{@link buildToolMatcherRefusal} 是**唯一**把它铸成拒句 + `field` + `detail` 的函数,
|
|
107
|
+
* 受理门只取它的返回、**不解析句子**。体上多出的两键让三端不必解析英文就能把这只拒与普通提交失败分流、提示用户改 matcher;死别名那一句逐字同 7.114.0、零新码。
|
|
89
108
|
*/
|
|
90
109
|
/** 超此长度的 matcher 不在受理面读(两档同一个上限;未判,reason = oversize)。与 {@link MAX_HOOK_COMMAND_CHARS} 同量纲的服务侧防线:真实 matcher(精确名 / 交替 / `mcp__.*`)远在其内;目录全部工具名交替 ~0.5 KiB。 */
|
|
91
110
|
export declare const MAX_MATCHER_EVAL_CHARS = 8192;
|
|
92
|
-
/**
|
|
93
|
-
|
|
111
|
+
/**
|
|
112
|
+
* regex 档**每一次正则形求值各一份**的墙钟预算(毫秒;S-1455)。**不共享、不随受理里 matcher 的个数耗尽、判据里不读钟**;字面形不占它。
|
|
113
|
+
* 良性求值 ~0.1 ms;灾难回溯(指数级)吃满它也跑不完 ⇒ 这只 matcher 被 400 拒。取值是「良性求值之上数个数量级」的余量 —— 小了,忙机上的调度停顿会把良性 matcher 读成灾难(受理结局随负载翻转,正是 S-1455 要根除的形)。
|
|
114
|
+
*/
|
|
115
|
+
export declare const ADMISSION_MATCHER_EVAL_BUDGET_MS = 1000;
|
|
116
|
+
/** 拒句里回显的 matcher 原文 / 引擎编译错误句各自的字符上限(截断记号 `…(总长)` 由 `clip` 铸;S-1455 收尾)。真实 matcher 远在其内;上限只防一只 8 KiB 的坏 matcher 把拒句撑成一屏。 */
|
|
117
|
+
export declare const MATCHER_ECHO_CHARS = 200;
|
|
94
118
|
/** 受理面判据的求值深度(见上头注):`"regex"` = 契约字面形直接问、正则形带预算问同一只契约函数;`"literal"` = 7.112.0 的字面判(只判契约字面形,零调用方正则执行;正则形 / 编不过的形不适用)。 */
|
|
95
119
|
export type MatcherEvalDepth = "regex" | "literal";
|
|
96
120
|
/**
|
|
97
|
-
* **仅供测试注入**的求值预算(生产调用点不传 ⇒
|
|
98
|
-
*
|
|
121
|
+
* **仅供测试注入**的求值预算(生产调用点不传 ⇒ 每次求值的预算 = {@link ADMISSION_MATCHER_EVAL_BUDGET_MS})。让「灾难形被拒」这类格子能用小额度(毫秒级)跑,不必等满生产预算。
|
|
122
|
+
* 只有预算额度、**没有时钟**:判据本身不读钟(S-1455),测试也就没有「在第几次读钟时预算已尽」可造 —— 求值次序、调度停顿都不改变结局。
|
|
99
123
|
*/
|
|
100
124
|
export interface MatcherEvalBudget {
|
|
101
125
|
readonly budgetMs?: number;
|
|
102
|
-
readonly now?: () => number;
|
|
103
126
|
}
|
|
104
|
-
/** 一条受理面判决(纯数据)
|
|
127
|
+
/** 一条受理面判决(纯数据)· 死别名:`event` 事件下的某只 matcher 选中了退役别名 `alias`、却选不中它的正名 `canonical`。`alias` / `canonical` 恒取自 core 静态目录(闭集字符串,不含调用方原字节)。 */
|
|
105
128
|
export interface DeadToolMatcherIssue {
|
|
129
|
+
readonly reason: "dead_alias";
|
|
106
130
|
readonly event: HookEventName;
|
|
107
131
|
readonly alias: string;
|
|
108
132
|
readonly canonical: string;
|
|
109
133
|
}
|
|
110
|
-
/**
|
|
111
|
-
export interface
|
|
134
|
+
/** 一条受理面判决(纯数据)· 求值超预算(S-1455):`event` 事件下第 `groupIndex` 组(从 0 起)的 matcher 单次求值没在 `budgetMs` 内结束(灾难回溯)。三键都是闭集 / 数字,不含调用方原字节。 */
|
|
135
|
+
export interface OverBudgetMatcherIssue {
|
|
136
|
+
readonly reason: "over_budget";
|
|
137
|
+
readonly event: HookEventName;
|
|
138
|
+
readonly groupIndex: number;
|
|
139
|
+
readonly budgetMs: number;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* 一条受理面判决(纯数据)· 正则编不过(S-1455 收尾):`event` 事件下第 `groupIndex` 组(从 0 起)的 matcher 在契约包的读法下答 `invalid`。
|
|
143
|
+
* `matcher` = 那只 matcher 的原文、`compileError` = 引擎的编译错误句(各自截到 {@link MATCHER_ECHO_CHARS} 字符):**只供铸拒句用**,机读位 `detail` 不带它们。
|
|
144
|
+
*/
|
|
145
|
+
export interface InvalidRegexMatcherIssue {
|
|
146
|
+
readonly reason: "invalid_regex";
|
|
147
|
+
readonly event: HookEventName;
|
|
148
|
+
readonly groupIndex: number;
|
|
149
|
+
readonly matcher: string;
|
|
150
|
+
readonly compileError: string;
|
|
151
|
+
}
|
|
152
|
+
/** 受理面判据的判决(闭集三形,`reason` 区分;每一形都是 400 拒):死别名 · 求值超预算 · 正则编不过。 */
|
|
153
|
+
export type ToolMatcherIssue = DeadToolMatcherIssue | OverBudgetMatcherIssue | InvalidRegexMatcherIssue;
|
|
154
|
+
/** {@link buildToolMatcherRefusal} 的返回(纯数据):拒句 + 400 体上的两个机读位。`field` 恒为字面 `"settings.hooks"`;`detail` 与 {@link ToolMatcherIssue} 同键(按 `reason` 分形,逐个挑出,不 spread)。 */
|
|
155
|
+
export interface ToolMatcherRefusal {
|
|
112
156
|
readonly message: string;
|
|
113
157
|
readonly field: "settings.hooks";
|
|
114
158
|
readonly detail: {
|
|
159
|
+
readonly reason: "dead_alias";
|
|
115
160
|
readonly event: HookEventName;
|
|
116
161
|
readonly alias: string;
|
|
117
162
|
readonly canonical: string;
|
|
163
|
+
} | {
|
|
164
|
+
readonly reason: "over_budget";
|
|
165
|
+
readonly event: HookEventName;
|
|
166
|
+
readonly groupIndex: number;
|
|
167
|
+
readonly budgetMs: number;
|
|
168
|
+
} | {
|
|
169
|
+
readonly reason: "invalid_regex";
|
|
170
|
+
readonly event: HookEventName;
|
|
171
|
+
readonly groupIndex: number;
|
|
118
172
|
};
|
|
119
173
|
}
|
|
120
174
|
/**
|
|
121
|
-
* 判决 → 拒句 +
|
|
122
|
-
*
|
|
175
|
+
* 判决 → 拒句 + 机读位。**拒句的唯一铸点**:死别名的句子逐字 = 7.114.0 的那一句(`test/hooks-alias-matcher-s995.test.ts` R7 冻结);受理门 `admission.ts` 用返回值填 400 体,
|
|
176
|
+
* 不从句子里反解字段。超预算的句子点名**哪一只**(事件 + 组下标 + `matcher`)与**预算**,不回显 matcher 原字节(S-716 姿势);`reason` 闭集穷举(多一形 = 这里编译红)。
|
|
123
177
|
*/
|
|
124
|
-
export declare function
|
|
178
|
+
export declare function buildToolMatcherRefusal(issue: ToolMatcherIssue): ToolMatcherRefusal;
|
|
125
179
|
/**
|
|
126
|
-
* fresh 提交面专用判据(S-924 / S-995)
|
|
127
|
-
* 拒句与 400 体的机读位由 {@link
|
|
180
|
+
* fresh 提交面专用判据(S-924 / S-995 / S-1455):配置里第一条「该拒」的工具事件 matcher 的判决数据({@link ToolMatcherIssue}):「永远打不中」(死别名)或「求值超预算」(灾难回溯);没有 ⇒ undefined。
|
|
181
|
+
* 拒句与 400 体的机读位由 {@link buildToolMatcherRefusal} 从这份数据铸(S-1025)。**按配置顺序(事件 → 组)遇到的第一条定结局**;结局只取决于配置,不取决于求值次序之外的任何东西(无共享预算、无时钟)。
|
|
128
182
|
* 入参是 {@link parseHooksConfig} 已校验过的配置;`depth` 由调用点按车道定(见头注:`taskHooksHonored(config) ? "regex" : "literal"`)。
|
|
129
183
|
* `budget` **仅供测试注入**({@link MatcherEvalBudget});生产调用点只传前两个实参。
|
|
130
|
-
* **只有 `admission.ts` 的 fresh 提交门调它** —— resume 重放不调(理由见上面的头注)。未判的 matcher 过 `recordFailOpen`(tag `MATCHER_UNJUDGED_TAG`)
|
|
184
|
+
* **只有 `admission.ts` 的 fresh 提交门调它** —— resume 重放不调(理由见上面的头注)。未判的 matcher 过 `recordFailOpen`(tag `MATCHER_UNJUDGED_TAG`);超预算的不是未判,是拒。
|
|
131
185
|
*/
|
|
132
|
-
export declare function
|
|
186
|
+
export declare function toolMatcherIssue(config: HooksConfig, depth: MatcherEvalDepth, budget?: MatcherEvalBudget): ToolMatcherIssue | undefined;
|
|
133
187
|
/**
|
|
134
188
|
* 把 wire 上的 untrusted `settings.hooks` 校验成契约 {@link HooksConfig} + 服务侧上限。
|
|
135
189
|
* 错误返回 error 字符串而不 throw——submit 路径 400 fail-loud、resume 防御路径 warn-drop,由调用方选。
|
|
@@ -139,7 +193,7 @@ export declare function parseHooksConfig(raw: unknown): ParseHooksConfigResult;
|
|
|
139
193
|
* 运行期的 matcher 读法席位:**问契约包的 `hookMatcherSelects`,别无其它**(壳与服务端都问这一只,谁都不留副本;读法全文见它的头注,这里不重述)。
|
|
140
194
|
* 三形(名字表 / 空 `*` 缺省 / 不锚定的 JS 正则)与「编不过 ⇒ `"invalid"`」都由它答;**对所有带 matcher 的事件同一只读法**(工具事件 / StopFailure 的 `error` 词 /
|
|
141
195
|
* PreCompact·PostCompact 的 `trigger` 词 / `if` 条件的名部),不按事件分档。`"invalid"` ⇒ 该组不跑(fail-closed 到「不跑」),由调用方记账一次(`hook_matcher_invalid`);
|
|
142
|
-
* 受理面({@link
|
|
196
|
+
* 受理面({@link toolMatcherIssue})问的是同一只函数。
|
|
143
197
|
*/
|
|
144
198
|
export declare function hookMatcherMatches(matcher: string | undefined, value: string): boolean | "invalid";
|
|
145
199
|
/** `if` 条目条件(CC-exact,对照 CC 2.1.187/198 实测行为核验的真语义,两版一致):
|
|
@@ -230,8 +284,8 @@ export type HookLlmFailureCode = "no_content" | "hard_timeout";
|
|
|
230
284
|
*/
|
|
231
285
|
export declare function buildHookContext(parts: readonly string[]): string | undefined;
|
|
232
286
|
/**
|
|
233
|
-
* 阶段三a:`http` 条目——契约语义 = POST hook 输入 JSON 到 `url`;headers 里的 `$NAME` 仅当 NAME 列在
|
|
234
|
-
* `allowedEnvVars` 才从
|
|
287
|
+
* 阶段三a:`http` 条目——契约语义 = POST hook 输入 JSON 到 `url`;headers 里的 `$NAME` / `${NAME}` 仅当 NAME 列在
|
|
288
|
+
* `allowedEnvVars` 才从 {@link hookEnv} 插值(配置本身绝不携带密钥值,契约同边界);读法只有契约包的 `interpolateHookEnvVars` 一只(见函数体)。
|
|
235
289
|
*
|
|
236
290
|
* 结果折算成伪 {@link CommandRunResult},让 9 事件的既有折叠逻辑零改动复用:
|
|
237
291
|
* - 2xx + JSON body → 同 exit-0-stdout-JSON(SyncHookOutput 决策面)。⚠️ 这是对 CC 行为的合理近似
|