@sema-agent/server 7.144.0 → 7.146.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 +621 -0
- package/README.md +3 -0
- package/README.zh-CN.md +1 -0
- package/USAGE.md +233 -54
- package/deploy/facts/CHANGES.json +25 -0
- package/deploy/facts/README.md +57 -0
- package/deploy/facts/lanes.json +54 -0
- package/deploy/facts/lanes.schema.json +57 -0
- package/deploy/facts/sandbox-rbac.json +113 -0
- package/deploy/facts/sandbox-rbac.schema.json +74 -0
- package/deploy/facts/sealed-key.json +9 -0
- package/deploy/facts/sealed-key.schema.json +52 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +19 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +47 -7
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +4 -0
- package/deploy/sema-up/chart/templates/server.yaml +4 -0
- package/deploy/sema-up/chart/values.yaml +7 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +30 -14
- package/dist/adoption/import-limits.d.ts +6 -0
- package/dist/adoption/import-limits.js +7 -0
- package/dist/adoption/import.d.ts +62 -0
- package/dist/adoption/import.js +107 -0
- package/dist/adoption/wire.d.ts +52 -0
- package/dist/adoption/wire.js +9 -0
- package/dist/approval-ask-machine.d.ts +2 -2
- package/dist/approval-card.d.ts +3 -12
- package/dist/approval-card.js +0 -4
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-gate-currency.js +1 -1
- package/dist/approval-reconciler.d.ts +1 -1
- package/dist/audit.d.ts +2 -21
- package/dist/audit.js +0 -9
- package/dist/boot/deployment-mods.d.ts +11 -1
- package/dist/boot/deployment-mods.js +15 -2
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +193 -21
- package/dist/boot/engine-lease.js +146 -20
- package/dist/boot/execution-env.d.ts +4 -0
- package/dist/boot/execution-env.js +12 -0
- package/dist/boot/exit-boundary.d.ts +50 -0
- package/dist/boot/exit-boundary.js +32 -0
- package/dist/boot/exit-last.d.ts +20 -4
- package/dist/boot/exit-last.js +21 -4
- package/dist/boot/governance-seams.js +1 -0
- package/dist/boot/memory-consolidation.d.ts +29 -17
- package/dist/boot/memory-consolidation.js +26 -15
- package/dist/boot/reapers.d.ts +12 -4
- package/dist/boot/reapers.js +39 -15
- package/dist/boot/resolve-spec.d.ts +2 -0
- package/dist/boot/resolve-spec.js +38 -15
- package/dist/boot/runner-deps.js +1 -1
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +6 -4
- package/dist/boot/shutdown.js +27 -9
- package/dist/boot/stage-01-config.js +1 -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 +3 -0
- package/dist/boot/stage-05-execution-env.js +3 -3
- package/dist/boot/stage-06-runners.d.ts +3 -0
- package/dist/boot/stage-06-runners.js +11 -10
- package/dist/boot/stage-07-capability-layer.d.ts +3 -0
- package/dist/boot/stage-07-capability-layer.js +7 -2
- package/dist/boot/stage-08-reapers.d.ts +3 -0
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +4 -1
- package/dist/boot/stage-10-http-server.d.ts +4 -1
- package/dist/boot/stage-10-http-server.js +4 -3
- package/dist/boot/stores.d.ts +1 -0
- package/dist/boot/stores.js +35 -19
- package/dist/boot/workflow-orchestration.d.ts +1 -1
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/capabilities/composite-members.d.ts +3 -1
- package/dist/capabilities/composite-members.js +3 -1
- package/dist/capabilities/scenarios.d.ts +2 -2
- package/dist/capability-facts.d.ts +18 -1
- package/dist/capability-facts.js +25 -7
- package/dist/checkpoint-ctx-seal-m28.d.ts +1 -1
- package/dist/config-catalog.js +13 -4
- package/dist/config-d-migration.d.ts +3 -2
- package/dist/config-provider.d.ts +2 -2
- package/dist/config-types.d.ts +43 -4
- package/dist/config.d.ts +6 -1
- package/dist/config.js +67 -11
- package/dist/deleted-session-ids.d.ts +19 -0
- package/dist/deleted-session-ids.js +26 -0
- package/dist/deploy-facts.d.ts +155 -0
- package/dist/deploy-facts.js +94 -0
- package/dist/device-ws-hub.d.ts +48 -3
- package/dist/device-ws-hub.js +48 -2
- package/dist/error-code-family.d.ts +35 -0
- package/dist/error-code-family.js +26 -0
- package/dist/fleet/drain-entry.d.ts +39 -3
- package/dist/fleet/drain-entry.js +6 -0
- package/dist/fleet/fleet-bus.d.ts +15 -4
- package/dist/fleet/fleet-bus.js +17 -3
- package/dist/hooks/branch-transcript.d.ts +1 -1
- package/dist/hooks/branch-transcript.js +1 -0
- package/dist/hooks/classic-stations.d.ts +25 -8
- package/dist/hooks/classic-stations.js +29 -3
- package/dist/hooks/hook-runner.d.ts +33 -16
- package/dist/hooks/hook-runner.js +166 -73
- package/dist/hooks/hook-source.d.ts +14 -2
- package/dist/hooks/hook-source.js +8 -0
- package/dist/http/active-run-conflict.d.ts +1 -1
- package/dist/http/active-run-conflict.js +1 -1
- package/dist/http/admission.js +13 -2
- package/dist/http/checkpoint-ctx.d.ts +60 -71
- package/dist/http/checkpoint-ctx.js +35 -40
- package/dist/http/dispatch.js +18 -2
- package/dist/http/durable-run-leg.d.ts +5 -0
- package/dist/http/durable-run-leg.js +8 -6
- package/dist/http/execution-context.d.ts +4 -0
- package/dist/http/execution-context.js +9 -0
- package/dist/http/health-self-report.d.ts +6 -2
- package/dist/http/health-self-report.js +3 -2
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
- package/dist/http/memory-compliance-failure-reply.js +2 -15
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +25 -0
- package/dist/http/memory-control-plane-corrupt-reply.js +19 -0
- package/dist/http/principal-gate.d.ts +35 -12
- package/dist/http/principal-gate.js +16 -12
- package/dist/http/request-guards.d.ts +1 -1
- package/dist/http/request-guards.js +5 -5
- package/dist/http/resume-legs.d.ts +22 -0
- package/dist/http/resume-legs.js +31 -20
- package/dist/http/route-ctx.d.ts +26 -10
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/adoption.d.ts +11 -0
- package/dist/http/routes/adoption.js +80 -6
- package/dist/http/routes/agents-roster.js +1 -0
- package/dist/http/routes/approvals-assistant.d.ts +20 -1
- package/dist/http/routes/approvals-assistant.js +29 -7
- package/dist/http/routes/background.js +1 -0
- package/dist/http/routes/capabilities.js +4 -1
- package/dist/http/routes/diagnostics.d.ts +9 -14
- package/dist/http/routes/diagnostics.js +10 -20
- package/dist/http/routes/engine.d.ts +31 -0
- package/dist/http/routes/engine.js +81 -0
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-consolidation.js +3 -5
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/memory-origin.js +2 -4
- package/dist/http/routes/memory-policy.js +5 -1
- package/dist/http/routes/observability.js +3 -6
- package/dist/http/routes/rules.d.ts +1 -1
- package/dist/http/routes/rules.js +5 -2
- package/dist/http/routes/runs.js +7 -3
- package/dist/http/routes/session-sync.js +24 -25
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.js +4 -0
- package/dist/http/routes/tasks.js +35 -14
- package/dist/http/routes/trace-usage.js +1 -1
- package/dist/http/run-concurrency-cap.d.ts +86 -0
- package/dist/http/run-concurrency-cap.js +54 -0
- package/dist/http/run-meta.d.ts +14 -7
- package/dist/http/run-meta.js +5 -2
- package/dist/http/server.d.ts +27 -16
- package/dist/http/server.js +21 -3
- package/dist/http/stored-body-replay.d.ts +9 -6
- package/dist/http/stored-body-replay.js +19 -5
- package/dist/http/submit-ctx.d.ts +12 -0
- package/dist/http/submit-ctx.js +23 -0
- package/dist/http/wire-types.d.ts +8 -3
- package/dist/json-body-limit.d.ts +8 -0
- package/dist/json-body-limit.js +2 -0
- package/dist/leader/diffout.d.ts +1 -1
- package/dist/local-data-root.d.ts +2 -2
- package/dist/memory-operator-faces.d.ts +9 -4
- package/dist/memory-scope-stores.d.ts +9 -7
- package/dist/memory-scope-stores.js +3 -14
- package/dist/memory-scope.d.ts +36 -0
- package/dist/memory-scope.js +32 -1
- package/dist/net-address.d.ts +53 -0
- package/dist/net-address.js +111 -0
- package/dist/observability/fail-open.d.ts +28 -12
- package/dist/observability/fail-open.js +28 -12
- package/dist/orchestration/workflow-notify-journal.js +2 -3
- package/dist/org-delivery-gate.js +1 -1
- package/dist/peer-directory.d.ts +6 -12
- package/dist/peer-directory.js +5 -1
- package/dist/plugins/approval-ask-store-file.d.ts +16 -2
- package/dist/plugins/approval-ask-store-file.js +21 -1
- package/dist/plugins/approval-ask-store-memory.d.ts +8 -2
- package/dist/plugins/approval-ask-store-memory.js +11 -8
- package/dist/plugins/caching-session-store.d.ts +6 -1
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/checkpoint-store-face.d.ts +426 -0
- package/dist/plugins/checkpoint-store-face.js +152 -0
- package/dist/plugins/file-run-store.d.ts +13 -7
- package/dist/plugins/file-run-store.js +12 -13
- package/dist/plugins/fork-routing-session-store.d.ts +6 -2
- package/dist/plugins/fork-routing-session-store.js +2 -2
- package/dist/plugins/imported-layer-root-retirement.d.ts +10 -8
- package/dist/plugins/local-checkpoint-store.d.ts +16 -5
- package/dist/plugins/local-checkpoint-store.js +25 -6
- package/dist/plugins/local-session-store.d.ts +80 -21
- package/dist/plugins/local-session-store.js +79 -22
- package/dist/plugins/memory-engine-pg.d.ts +29 -6
- package/dist/plugins/memory-engine-pg.js +96 -214
- package/dist/plugins/memory-engine-sql-apply.d.ts +121 -0
- package/dist/plugins/memory-engine-sql-apply.js +358 -0
- package/dist/plugins/memory-engine-tidb.d.ts +35 -9
- package/dist/plugins/memory-engine-tidb.js +97 -227
- package/dist/plugins/memory-key-guards.d.ts +1 -1
- package/dist/plugins/memory-origin-law.d.ts +3 -3
- package/dist/plugins/memory-run-store.d.ts +2 -0
- package/dist/plugins/memory-run-store.js +6 -0
- package/dist/plugins/one-time-migrations.d.ts +32 -56
- package/dist/plugins/one-time-migrations.js +27 -119
- package/dist/plugins/permission-rule-store-file.d.ts +17 -3
- package/dist/plugins/permission-rule-store-file.js +8 -1
- package/dist/plugins/pg-pool.js +1 -1
- package/dist/plugins/pg-session-storage.d.ts +17 -4
- package/dist/plugins/pg-session-storage.js +8 -4
- package/dist/plugins/run-store-sql.d.ts +4 -0
- package/dist/plugins/run-store-sql.js +5 -2
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/session-fork.d.ts +31 -9
- package/dist/plugins/session-fork.js +3 -2
- package/dist/plugins/session-placement.d.ts +4 -2
- package/dist/plugins/session-store.d.ts +1 -1
- package/dist/plugins/sql-json-column.d.ts +5 -1
- package/dist/plugins/store-backend.d.ts +11 -8
- package/dist/plugins/store-backend.js +8 -7
- package/dist/plugins/store-contracts.d.ts +1 -11
- package/dist/plugins/store-contracts.js +0 -9
- package/dist/plugins/store-sweep.d.ts +63 -0
- package/dist/plugins/store-sweep.js +48 -0
- package/dist/plugins/tidb-pool.js +1 -1
- package/dist/plugins/tidb-session-store.d.ts +16 -3
- package/dist/plugins/tidb-session-store.js +8 -4
- package/dist/prompt-screen.d.ts +18 -0
- package/dist/prompt-screen.js +5 -0
- package/dist/rules-consent.d.ts +56 -51
- package/dist/rules-consent.js +86 -14
- package/dist/run-acceptance.d.ts +40 -10
- package/dist/run-acceptance.js +38 -5
- package/dist/run-cancel-context.d.ts +4 -1
- package/dist/run-cancel-context.js +2 -1
- package/dist/runs.js +2 -2
- package/dist/sandbox-egress-policy.js +6 -11
- package/dist/sandbox-rbac-rules.d.ts +88 -0
- package/dist/sandbox-rbac-rules.js +80 -0
- package/dist/sealed-key-layout.d.ts +17 -0
- package/dist/sealed-key-layout.js +4 -0
- package/dist/sealed-key.js +5 -5
- package/dist/security.d.ts +48 -9
- package/dist/security.js +9 -2
- package/dist/session-agent.d.ts +39 -0
- package/dist/session-agent.js +16 -0
- package/dist/session-error-wire.d.ts +4 -4
- package/dist/session-notify-door.d.ts +5 -3
- package/dist/session-resident-background.d.ts +57 -0
- package/dist/session-resident-background.js +20 -0
- package/dist/session-sync-kernel.d.ts +53 -14
- package/dist/session-sync-kernel.js +70 -1
- package/dist/session-sync.d.ts +5 -3
- package/dist/session-workspace.d.ts +1 -0
- package/dist/session-workspace.js +1 -0
- package/dist/sighup-idle.d.ts +9 -7
- package/dist/sighup-idle.js +4 -5
- package/dist/spec-fields.d.ts +16 -0
- package/dist/spec-fields.js +7 -0
- package/dist/stored-request-env-credentials-m38.d.ts +3 -0
- package/dist/stored-request-env-credentials-m38.js +8 -0
- package/dist/stored-request-prompt-profile-m30.d.ts +1 -1
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.d.ts +33 -429
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.js +70 -209
- package/dist/{plugins → stores-sql}/mailbox-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/mailbox-store-sql.js +4 -4
- package/dist/{plugins → stores-sql}/roster-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/roster-store-sql.js +1 -1
- package/dist/{plugins → stores-sql}/tool-result-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/tool-result-store-sql.js +6 -6
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.d.ts +7 -12
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.js +3 -8
- package/dist/task-settings.d.ts +59 -4
- package/dist/task-settings.js +50 -4
- package/dist/tool-approval.d.ts +2 -2
- package/dist/trace/core-keyset-guard.d.ts +8 -7
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +6 -0
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/model-segment.d.ts +3 -2
- package/dist/trace/model-segment.js +16 -8
- package/dist/trace/project.js +9 -0
- package/dist/trace/redact.d.ts +79 -4
- package/dist/trace/redact.js +523 -123
- package/dist/trace/self-minted-wire.d.ts +391 -1
- package/dist/trace/self-minted-wire.js +145 -0
- package/dist/trace/wire-projection-faces.d.ts +1 -1
- package/dist/trace/wire-projection-faces.js +1 -1
- package/dist/usage-analytics.d.ts +4 -0
- package/package.json +12 -4
- package/scripts/drain-check-local.mjs +8 -29
- package/scripts/drain-check.mysql.sql +3 -24
- package/scripts/drain-check.pg.sql +3 -24
- package/skills/update-config.md +1 -1
- package/wire-changes/server@7.145.0.json +146 -0
- package/wire-changes/server@7.146.0.json +3221 -0
- package/dist/approval-batch-census.d.ts +0 -27
- package/dist/approval-batch-census.js +0 -27
|
@@ -92,7 +92,10 @@ kind: Service
|
|
|
92
92
|
metadata: { name: sema-minio, namespace: sema }
|
|
93
93
|
spec: { selector: { app: sema-minio }, ports: [{ name: s3, port: 9000 }, { name: console, port: 9001 }] }
|
|
94
94
|
---
|
|
95
|
-
# ── 沙箱 lane RBAC(k8s+kata
|
|
95
|
+
# ── 沙箱 lane RBAC(k8s+kata):pod 生命周期 / exec / log、出网自检的两只只读(本 ns 的 NetworkPolicy、集群的节点表)恒授;
|
|
96
|
+
# 缓存卷的 persistentvolumeclaims 与沙箱秘密座的 secrets create 只在对应引擎旋钮(WORKSPACE_CACHE=volume / K8S_SANDBOX_ENV)开着时授 ——
|
|
97
|
+
# 本清单的引擎 env 两个都没设,所以这两条规则渲成注释块,开了旋钮就取消注释。
|
|
98
|
+
# 「哪条规则由哪个开关决定」只写在 server 源码的规则表 src/sandbox-rbac-rules.ts;下面两个规则区由 scripts/gen-deploy-lanes.ts 从它生成,不要手改。────────────────────────────────
|
|
96
99
|
apiVersion: v1
|
|
97
100
|
kind: ServiceAccount
|
|
98
101
|
metadata: { name: sema-runner, namespace: sema-sandbox }
|
|
@@ -109,29 +112,38 @@ apiVersion: rbac.authorization.k8s.io/v1
|
|
|
109
112
|
kind: Role
|
|
110
113
|
metadata: { name: sema-runner, namespace: sema-sandbox }
|
|
111
114
|
rules:
|
|
115
|
+
# @generated-begin sandbox-role-rules
|
|
116
|
+
# 沙箱 pod 的生命周期:remote-env-k8s.ts#createPod 建(POST pods)并读就绪(GET pods/<名>)· remote-env-k8s.ts#listSandboxPods 按标签列(GET pods?labelSelector)· remote-env-k8s.ts#reconnect 读存活(GET pods/<名>)· remote-env-k8s.ts#deletePod 删(DELETE pods/<名>)
|
|
117
|
+
# 兼容保留:chart 一直授着,适配器没有 watch 调用
|
|
112
118
|
- apiGroups: [""]
|
|
113
119
|
resources: [pods]
|
|
114
120
|
verbs: [get, list, watch, create, delete]
|
|
121
|
+
# 在沙箱 pod 里执行命令:remote-env-k8s.ts#execUrl 拼 pods/<名>/exec 的连接地址
|
|
122
|
+
# 兼容保留:chart 一直授着,适配器没有 attach 调用
|
|
115
123
|
- apiGroups: [""]
|
|
116
124
|
resources: [pods/exec, pods/attach]
|
|
117
|
-
verbs: [
|
|
125
|
+
verbs: [get, create]
|
|
126
|
+
# 兼容保留:chart 一直授着,适配器没有读日志的调用
|
|
118
127
|
- apiGroups: [""]
|
|
119
128
|
resources: [pods/log]
|
|
120
129
|
verbs: [get]
|
|
121
|
-
#
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
#
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
#
|
|
130
|
+
# 按工作区空间的构建缓存卷:remote-env-k8s.ts#ensureCacheClaim 按名读、没有就建(GET / POST persistentvolumeclaims)· remote-env-k8s.ts#cacheClaimBound 按名读 · remote-env-k8s.ts#reclaimSpaceCache 空间结束按标签回收(DELETE persistentvolumeclaims?labelSelector = deletecollection);缺它 ⇒ 缓存卷拿不到,适配器按 fail-open 照起、不挂卷(计数 server.workspace-cache.unavailable)
|
|
131
|
+
# 兼容保留:chart 一直授着,适配器回收只发按标签的 deletecollection,没有按名 delete 的调用
|
|
132
|
+
# 默认不授(本清单的 server env 没有 WORKSPACE_CACHE=volume):设了它就取消下面三行的注释:
|
|
133
|
+
# - apiGroups: [""]
|
|
134
|
+
# resources: [persistentvolumeclaims]
|
|
135
|
+
# verbs: [get, create, delete, deletecollection]
|
|
136
|
+
# 沙箱秘密座:动词取自 SANDBOX_SECRET_SEAT_VERBS.env —— 起服门(boot/execution-env.ts ensureSandboxSecretSeat)问的与 remote-env-k8s.ts#createOwnedSecret 为 env Secret 真发的(POST secrets)是同一行;起服门只在有效转发集合非空(名单点到的键在服务进程环境里有值)时问:答 denied ⇒ server 起服拒,问不到 ⇒ 告警 sandbox_secret_seat_unverified 照起;名单非空而有效集合为空时本行是保守多授(安装器看不到服务进程的运行时环境,引擎此时既不问也不调)
|
|
137
|
+
# 默认不授(本清单的 server env 没有 K8S_SANDBOX_ENV=NAME,NAME):设了它就取消下面三行的注释:
|
|
138
|
+
# - apiGroups: [""]
|
|
139
|
+
# resources: [secrets]
|
|
140
|
+
# verbs: [create]
|
|
141
|
+
# 起服的出网自检读本 ns 的 NetworkPolicy 集合:remote-env-k8s.ts#egressPolicyGaps(GET .../networkpolicies)
|
|
142
|
+
# 兼容保留:chart 一直授着,适配器只读集合(list),没有按名 get
|
|
132
143
|
- apiGroups: [networking.k8s.io]
|
|
133
144
|
resources: [networkpolicies]
|
|
134
145
|
verbs: [get, list]
|
|
146
|
+
# @generated-end sandbox-role-rules
|
|
135
147
|
---
|
|
136
148
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
137
149
|
kind: RoleBinding
|
|
@@ -139,14 +151,18 @@ metadata: { name: sema-runner, namespace: sema-sandbox }
|
|
|
139
151
|
roleRef: { apiGroup: rbac.authorization.k8s.io, kind: Role, name: sema-runner }
|
|
140
152
|
subjects: [{ kind: ServiceAccount, name: sema-runner, namespace: sema-sandbox }]
|
|
141
153
|
---
|
|
142
|
-
# 出网自检读节点表(集群级对象 ⇒ ClusterRole
|
|
154
|
+
# 出网自检读节点表(集群级对象 ⇒ ClusterRole + Binding 给同一只服务账号)。与 chart 的 sandbox-rbac.yaml 读同一张规则表。
|
|
143
155
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
144
156
|
kind: ClusterRole
|
|
145
157
|
metadata: { name: sema-runner-nodes-sema-sandbox }
|
|
146
158
|
rules:
|
|
159
|
+
# @generated-begin sandbox-clusterrole-rules
|
|
160
|
+
# 出网自检读节点表(节点是集群级对象 ⇒ ClusterRole + Binding 给同一只服务账号):remote-env-k8s.ts#egressPolicyGaps(GET /api/v1/nodes)
|
|
161
|
+
# 兼容保留:chart 一直授着,适配器只读集合(list),没有按名 get
|
|
147
162
|
- apiGroups: [""]
|
|
148
163
|
resources: [nodes]
|
|
149
164
|
verbs: [get, list]
|
|
165
|
+
# @generated-end sandbox-clusterrole-rules
|
|
150
166
|
---
|
|
151
167
|
apiVersion: rbac.authorization.k8s.io/v1
|
|
152
168
|
kind: ClusterRoleBinding
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const ADOPTION_IMPORT_MAX_SESSIONS_DEFAULT = 100;
|
|
2
|
+
export declare const ADOPTION_IMPORT_MAX_SESSIONS_FLOOR = 1;
|
|
3
|
+
export declare const ADOPTION_IMPORT_MAX_SESSION_BYTES_DEFAULT: number;
|
|
4
|
+
export declare const ADOPTION_IMPORT_MAX_SESSION_BYTES_FLOOR: number;
|
|
5
|
+
export declare const ADOPTION_IMPORT_MAX_SESSION_BYTES_CEILING: number;
|
|
6
|
+
//# sourceMappingURL=import-limits.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MAX_JSON_BODY_BYTES } from "../json-body-limit.js";
|
|
2
|
+
export const ADOPTION_IMPORT_MAX_SESSIONS_DEFAULT = 100;
|
|
3
|
+
export const ADOPTION_IMPORT_MAX_SESSIONS_FLOOR = 1;
|
|
4
|
+
export const ADOPTION_IMPORT_MAX_SESSION_BYTES_DEFAULT = 6 * 1024 * 1024;
|
|
5
|
+
export const ADOPTION_IMPORT_MAX_SESSION_BYTES_FLOOR = 1024 * 1024;
|
|
6
|
+
export const ADOPTION_IMPORT_MAX_SESSION_BYTES_CEILING = MAX_JSON_BODY_BYTES - Buffer.byteLength(JSON.stringify({ sessions: [] }), "utf8");
|
|
7
|
+
//# sourceMappingURL=import-limits.js.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { AdoptionLogStore, AdoptionRow } from "../plugins/adoption-log-sql.js";
|
|
2
|
+
import { type ImportStagingStore } from "../session-sync-kernel.js";
|
|
3
|
+
import { type AdoptionImportCapability, type AdoptionImportResult } from "./wire.js";
|
|
4
|
+
/**
|
|
5
|
+
* 幂等键 → 云端会话 id(②)。sha256 的原像是 `JSON.stringify([域, adoptionId, clientSessionId])` —— JSON 数组的编码是**单射**的(拿分隔符拼接不是:
|
|
6
|
+
* 任一半里出现分隔符就能伪造另一对),取前 16 字节,版本半字节写 `8`(RFC 9562 自定义形)、变体写 `10`,铸成 canonical uuid。
|
|
7
|
+
* 会话 id 的形门(`security.ts` 的 `isUuidShape`)收任何版本的 canonical uuid,所以这一只 id 在每扇带会话 id 的门上都可达;
|
|
8
|
+
* 版本 8 也让它与 core 铸的 uuidv7 永不同形(不会撞上一只普通会话)。
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildAdoptionImportSessionId(adoptionId: string, clientSessionId: string): string;
|
|
11
|
+
/** 一条收编行对一位调用者的判(①;闭集四臂,门按臂穷举下发)。 */
|
|
12
|
+
export type AdoptionImportBinding = {
|
|
13
|
+
readonly kind: "bound";
|
|
14
|
+
readonly adoptionId: string;
|
|
15
|
+
readonly toPrincipal: string;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: "absent";
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: "not_source";
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: "not_adopted";
|
|
22
|
+
};
|
|
23
|
+
/** ① 的唯一判官:行不在 ⇒ `absent`;调用者不**逐字**等于源主体 ⇒ `not_source`(先于收编态:不是源主体的调用方读不出这一行走到了哪);
|
|
24
|
+
* 收编没走完 / 被拒 ⇒ `not_adopted`;否则 `bound`(目的地 = 行的目的主体)。 */
|
|
25
|
+
export declare function judgeAdoptionImportBinding(row: AdoptionRow | null, caller: string): AdoptionImportBinding;
|
|
26
|
+
/** 两只帽的当前值(配置 env 腿解析过的那一份;数字属主 `import-limits.ts`)。 */
|
|
27
|
+
export interface AdoptionImportLimits {
|
|
28
|
+
readonly adoptionImportMaxSessions: number;
|
|
29
|
+
readonly adoptionImportMaxSessionBytes: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 能力位 `adoptionImport` 的唯一铸点:部署半不在 / 没有已验身份 ⇒ 缺席;按调用者读它作为源主体的那一行(`from_principal` 唯一,恰一行或没有),
|
|
33
|
+
* 过 ① 的同一只判官,`bound` 才在场。读收编日志失败 ⇒ 缺席并走登记过的 F 类臂(能力面不为一次库抖动整只 500;缺席的方向是「入口藏起来」)。
|
|
34
|
+
*/
|
|
35
|
+
export declare function readAdoptionImportCapability(face: {
|
|
36
|
+
readonly available: false;
|
|
37
|
+
} | {
|
|
38
|
+
readonly available: true;
|
|
39
|
+
readonly backend: {
|
|
40
|
+
adoptionLog(): AdoptionLogStore;
|
|
41
|
+
};
|
|
42
|
+
}, caller: string | undefined, limits: AdoptionImportLimits): Promise<AdoptionImportCapability | undefined>;
|
|
43
|
+
/** 请求体的形(恰 `{sessions: [...]}`)。读不出 ⇒ `undefined`(路由答 400 `request.body_shape`)。 */
|
|
44
|
+
export declare function readAdoptionImportBody(raw: unknown): readonly unknown[] | undefined;
|
|
45
|
+
/** 导入要的会话店那几口:只有暂存导入核(「已导过」由提交的属主判答,不读头);`evict` 在场 ⇒ 提交后丢掉缓存层的热句柄(提交经原始店写,绕过了缓存 —— 第二阶段同理)。 */
|
|
46
|
+
export type AdoptionImportSessionStore = ImportStagingStore & {
|
|
47
|
+
evict?(sessionId: string): void;
|
|
48
|
+
};
|
|
49
|
+
export interface AdoptionImportTarget {
|
|
50
|
+
readonly adoptionId: string;
|
|
51
|
+
readonly toPrincipal: string;
|
|
52
|
+
readonly maxSessionBytes: number;
|
|
53
|
+
readonly sessionStorage: AdoptionImportSessionStore;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 逐元素跑一批(顺序跑:体已整只在内存里且 ≤ JSON 体上限,逐个落暂存 + 提交)。每个元素的判序固定:
|
|
57
|
+
* 信封形(`invalid_envelope`)→ 同批重复 id(`duplicate_client_session_id`:同批第一个读得出这个 id 的元素认领它,不论它自己的结局)
|
|
58
|
+
* → 字节帽(`too_large`)→ 导入(②③;条目日志没过 core 的导入门 ⇒ `invalid_envelope`)。
|
|
59
|
+
* 店故障原样上抛(整请求 5xx;已落的元素重投答 `already_imported`)。
|
|
60
|
+
*/
|
|
61
|
+
export declare function runAdoptionImport(target: AdoptionImportTarget, sessions: readonly unknown[]): Promise<AdoptionImportResult[]>;
|
|
62
|
+
//# sourceMappingURL=import.d.ts.map
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { SessionError } from "@sema-agent/core";
|
|
3
|
+
import { createStagedLogFeed, MalformedImportEntryError, newStagingToken, StagedCommitOwnerChangedError } from "../session-sync-kernel.js";
|
|
4
|
+
import { STAGED_IMPORT_INVALID_SENTENCE } from "../session-error-wire.js";
|
|
5
|
+
import { recordFailOpen } from "../observability/fail-open.js";
|
|
6
|
+
import { AdoptionImportBodySchema, AdoptionImportEnvelopeSchema, ADOPTION_IMPORT_CLIENT_SESSION_ID_MAX_CHARS } from "./wire.js";
|
|
7
|
+
export function buildAdoptionImportSessionId(adoptionId, clientSessionId) {
|
|
8
|
+
const b = Buffer.from(createHash("sha256").update(JSON.stringify(["sema.adoption-import", adoptionId, clientSessionId])).digest().subarray(0, 16));
|
|
9
|
+
b[6] = (b[6] & 0x0f) | 0x80;
|
|
10
|
+
b[8] = (b[8] & 0x3f) | 0x80;
|
|
11
|
+
const hex = b.toString("hex");
|
|
12
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
13
|
+
}
|
|
14
|
+
export function judgeAdoptionImportBinding(row, caller) {
|
|
15
|
+
if (row === null)
|
|
16
|
+
return { kind: "absent" };
|
|
17
|
+
if (row.fromPrincipal !== caller)
|
|
18
|
+
return { kind: "not_source" };
|
|
19
|
+
switch (row.state) {
|
|
20
|
+
case "adopted":
|
|
21
|
+
return { kind: "bound", adoptionId: row.adoptionId, toPrincipal: row.toPrincipal };
|
|
22
|
+
case "in_flight":
|
|
23
|
+
case "rejected":
|
|
24
|
+
return { kind: "not_adopted" };
|
|
25
|
+
default: {
|
|
26
|
+
const unknownState = row.state;
|
|
27
|
+
throw new Error(`adoption import: unknown adoption state ${JSON.stringify(unknownState)}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function readAdoptionImportCapability(face, caller, limits) {
|
|
32
|
+
if (!face.available || caller === undefined)
|
|
33
|
+
return undefined;
|
|
34
|
+
let row;
|
|
35
|
+
try {
|
|
36
|
+
row = await face.backend.adoptionLog().getByFrom(caller);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
recordFailOpen("server.capabilities.adoption-import-unreadable", err instanceof Error ? err.name : "non-error throw");
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const binding = judgeAdoptionImportBinding(row, caller);
|
|
43
|
+
return binding.kind === "bound" ? { adoptionId: binding.adoptionId, maxSessions: limits.adoptionImportMaxSessions, maxSessionBytes: limits.adoptionImportMaxSessionBytes } : undefined;
|
|
44
|
+
}
|
|
45
|
+
export function readAdoptionImportBody(raw) {
|
|
46
|
+
const parsed = AdoptionImportBodySchema.safeParse(raw);
|
|
47
|
+
return parsed.success ? parsed.data.sessions : undefined;
|
|
48
|
+
}
|
|
49
|
+
const INVALID_ENVELOPE_SHAPE = `a session envelope is exactly {clientSessionId, entries}: clientSessionId a string of 1-${ADOPTION_IMPORT_CLIENT_SESSION_ID_MAX_CHARS} characters, entries an array of session entries (oldest first) — no other keys`;
|
|
50
|
+
function envelopeBytes(raw) {
|
|
51
|
+
return Buffer.byteLength(JSON.stringify(raw), "utf8");
|
|
52
|
+
}
|
|
53
|
+
export async function runAdoptionImport(target, sessions) {
|
|
54
|
+
const claimed = new Set();
|
|
55
|
+
const results = [];
|
|
56
|
+
for (const raw of sessions) {
|
|
57
|
+
const parsed = AdoptionImportEnvelopeSchema.safeParse(raw);
|
|
58
|
+
if (!parsed.success) {
|
|
59
|
+
results.push({ outcome: "rejected", code: "invalid_envelope", detail: INVALID_ENVELOPE_SHAPE });
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const { clientSessionId, entries } = parsed.data;
|
|
63
|
+
if (claimed.has(clientSessionId)) {
|
|
64
|
+
results.push({ clientSessionId, outcome: "rejected", code: "duplicate_client_session_id" });
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
claimed.add(clientSessionId);
|
|
68
|
+
const bytes = envelopeBytes(raw);
|
|
69
|
+
if (bytes > target.maxSessionBytes) {
|
|
70
|
+
results.push({ clientSessionId, outcome: "rejected", code: "too_large", count: bytes, cap: target.maxSessionBytes });
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
results.push(await importOne(target, clientSessionId, entries));
|
|
74
|
+
}
|
|
75
|
+
return results;
|
|
76
|
+
}
|
|
77
|
+
async function importOne(target, clientSessionId, entries) {
|
|
78
|
+
const sessionId = buildAdoptionImportSessionId(target.adoptionId, clientSessionId);
|
|
79
|
+
const store = target.sessionStorage;
|
|
80
|
+
const handle = store.beginImportStaging(sessionId, newStagingToken());
|
|
81
|
+
try {
|
|
82
|
+
const feed = createStagedLogFeed(handle);
|
|
83
|
+
for (const e of entries)
|
|
84
|
+
await feed.push(e);
|
|
85
|
+
await feed.finish();
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
await handle.abort().catch(() => undefined);
|
|
89
|
+
if (e instanceof MalformedImportEntryError)
|
|
90
|
+
return { clientSessionId, outcome: "rejected", code: "invalid_envelope", detail: e.message };
|
|
91
|
+
if (e instanceof SessionError && e.code === "invalid_session")
|
|
92
|
+
return { clientSessionId, outcome: "rejected", code: "invalid_envelope", detail: STAGED_IMPORT_INVALID_SENTENCE };
|
|
93
|
+
throw e;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
await handle.commit(target.toPrincipal, { expectedOwner: undefined });
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
await handle.abort().catch(() => undefined);
|
|
100
|
+
if (e instanceof StagedCommitOwnerChangedError)
|
|
101
|
+
return { clientSessionId, outcome: "already_imported", sessionId };
|
|
102
|
+
throw e;
|
|
103
|
+
}
|
|
104
|
+
store.evict?.(sessionId);
|
|
105
|
+
return { clientSessionId, outcome: "imported", sessionId };
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=import.js.map
|
package/dist/adoption/wire.d.ts
CHANGED
|
@@ -253,4 +253,56 @@ export declare const AdoptionRequestSchema: z.ZodObject<{
|
|
|
253
253
|
fromPrincipal: z.ZodString;
|
|
254
254
|
toPrincipal: z.ZodString;
|
|
255
255
|
}, z.core.$strict>;
|
|
256
|
+
/** 请求体:恰一键 `sessions`(会话信封数组)。`.strict()` —— 写面纪律;请求体里**没有**点名目的地的位置(目的地 = 收编行的目的主体)。 */
|
|
257
|
+
export declare const AdoptionImportBodySchema: z.ZodObject<{
|
|
258
|
+
sessions: z.ZodArray<z.ZodUnknown>;
|
|
259
|
+
}, z.core.$strict>;
|
|
260
|
+
/** `clientSessionId` 的长度上界(调用方本地 id;不进任何列 —— 它只进派生 id 的哈希原像,并在结局里原样回显)。 */
|
|
261
|
+
export declare const ADOPTION_IMPORT_CLIENT_SESSION_ID_MAX_CHARS = 255;
|
|
262
|
+
/**
|
|
263
|
+
* 一个会话信封 = 调用方本地的一只会话:`clientSessionId`(它的本地 id,幂等键的一半)+ `entries`(会话的条目日志,最老在前 —— 与会话同步
|
|
264
|
+
* 推送面逐行流的同一种条目,由 core 的导入门判)。恰这两键:多一个不认识的键 ⇒ 整个元素 `rejected` / `invalid_envelope`(不静默跳过)。
|
|
265
|
+
*/
|
|
266
|
+
export declare const AdoptionImportEnvelopeSchema: z.ZodObject<{
|
|
267
|
+
clientSessionId: z.ZodString;
|
|
268
|
+
entries: z.ZodArray<z.ZodUnknown>;
|
|
269
|
+
}, z.core.$strict>;
|
|
270
|
+
export type AdoptionImportEnvelope = z.infer<typeof AdoptionImportEnvelopeSchema>;
|
|
271
|
+
/** `rejected` 的具名码**闭集**(三词,穷举;消费方按码给用户话):超字节 / 信封形不认识(含条目日志没过 core 的导入门)/ 同一批里第二个带同一 id 的元素。
|
|
272
|
+
* 跨批重投同一 id 不是 `duplicate_client_session_id` —— 那是 `already_imported`(幂等)。 */
|
|
273
|
+
export declare const ADOPTION_IMPORT_REJECT_CODES: readonly ["too_large", "invalid_envelope", "duplicate_client_session_id"];
|
|
274
|
+
export type AdoptionImportRejectCode = (typeof ADOPTION_IMPORT_REJECT_CODES)[number];
|
|
275
|
+
/**
|
|
276
|
+
* 一个元素的结局(结果数组与请求的 `sessions` **按位对应**:N 个进 ⇒ N 个出)。`clientSessionId` 在信封读得出时回显(信封形不认识时缺席 —— 位置就是对应关系)。
|
|
277
|
+
* · `imported` / `already_imported`:带云端 `sessionId`(= `(adoptionId, clientSessionId)` 的纯函数,两次答同一个);
|
|
278
|
+
* · `rejected` + `too_large`:带量到的信封字节 `count` 与当时的帽 `cap`;
|
|
279
|
+
* · `rejected` + `invalid_envelope`:带一句 `detail`(固定句,不回显条目内容);
|
|
280
|
+
* · `rejected` + `duplicate_client_session_id`:同批第一个带这个 id 的元素认领它,之后的都拒(不静默去重 —— 「提交了 N 条」与「云上有 N-1 条」对不上账)。
|
|
281
|
+
*/
|
|
282
|
+
export type AdoptionImportResult = {
|
|
283
|
+
readonly clientSessionId: string;
|
|
284
|
+
readonly outcome: "imported" | "already_imported";
|
|
285
|
+
readonly sessionId: string;
|
|
286
|
+
} | {
|
|
287
|
+
readonly clientSessionId: string;
|
|
288
|
+
readonly outcome: "rejected";
|
|
289
|
+
readonly code: "too_large";
|
|
290
|
+
readonly count: number;
|
|
291
|
+
readonly cap: number;
|
|
292
|
+
} | {
|
|
293
|
+
readonly clientSessionId: string;
|
|
294
|
+
readonly outcome: "rejected";
|
|
295
|
+
readonly code: "duplicate_client_session_id";
|
|
296
|
+
} | {
|
|
297
|
+
readonly clientSessionId?: string;
|
|
298
|
+
readonly outcome: "rejected";
|
|
299
|
+
readonly code: "invalid_envelope";
|
|
300
|
+
readonly detail: string;
|
|
301
|
+
};
|
|
302
|
+
/** 能力位 `adoptionImport` 的值(present-iff 调用者是一条已收编行的源主体):导入口的 id + 两只帽的**当前值**(客户端据此分批,不撞 400 再收缩)。 */
|
|
303
|
+
export interface AdoptionImportCapability {
|
|
304
|
+
readonly adoptionId: string;
|
|
305
|
+
readonly maxSessions: number;
|
|
306
|
+
readonly maxSessionBytes: number;
|
|
307
|
+
}
|
|
256
308
|
//# sourceMappingURL=wire.d.ts.map
|
package/dist/adoption/wire.js
CHANGED
|
@@ -77,4 +77,13 @@ export const AdoptionRequestSchema = z
|
|
|
77
77
|
toPrincipal: z.string().min(1).max(190),
|
|
78
78
|
})
|
|
79
79
|
.strict();
|
|
80
|
+
export const AdoptionImportBodySchema = z.object({ sessions: z.array(z.unknown()) }).strict();
|
|
81
|
+
export const ADOPTION_IMPORT_CLIENT_SESSION_ID_MAX_CHARS = 255;
|
|
82
|
+
export const AdoptionImportEnvelopeSchema = z
|
|
83
|
+
.object({
|
|
84
|
+
clientSessionId: z.string().min(1).max(ADOPTION_IMPORT_CLIENT_SESSION_ID_MAX_CHARS),
|
|
85
|
+
entries: z.array(z.unknown()),
|
|
86
|
+
})
|
|
87
|
+
.strict();
|
|
88
|
+
export const ADOPTION_IMPORT_REJECT_CODES = ["too_large", "invalid_envelope", "duplicate_client_session_id"];
|
|
80
89
|
//# sourceMappingURL=wire.js.map
|
|
@@ -36,8 +36,8 @@ export declare function canAskTransition(from: AskState, to: AskState): boolean;
|
|
|
36
36
|
export declare function canBatchTransition(from: BatchState, to: BatchState): boolean;
|
|
37
37
|
/**
|
|
38
38
|
* `AskRequest.boundInputHash` 的**边界窄读**(唯一一只):ask 身份第四轴的入参那一半与行上 `bound_input_hash` 列(收敛器判据 1 的对账键)读的都是它。
|
|
39
|
-
* core 在闸站铸值(`onAsk({ ...bare, boundInputHash:
|
|
40
|
-
* `
|
|
39
|
+
* core 在闸站铸值(`onAsk({ ...bare, boundInputHash: exactBoundInputHashOf(req.toolName, presented.value), … })`,core 5.15.0 起每一只经 `resolveAsk` 的问都带;
|
|
40
|
+
* 7.63.0 起摘的是 `{ tool, input }`,此前只摘入参);`exactBoundInputHashOf` 不在 core 的公开导出面上(包 `exports` 只有 `.` / `./bench` / `./fixtures`),本服务既算不出也不该算 —— 只原样读。
|
|
41
41
|
* 非字符串 / 空串一律按缺席:一个形不对的摘要比没有摘要更危险(它会让「硬相等」这道门在一个垃圾值上偶然成立)。
|
|
42
42
|
* 钉:`test/stream-approval-on-e2e.test.ts` 件4(正控 / 缺席 / 空串三臂)。
|
|
43
43
|
*/
|
package/dist/approval-card.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ export declare const MAX_RULE_OFFER_BATCH_MEMBERS = 8;
|
|
|
54
54
|
/**
|
|
55
55
|
* **一条**「不再询问」OFFER 的形(core 5.58.0 / [ref] §3.1 —— **BREAKING**,取代退役的
|
|
56
56
|
* `RuleSuggestion`)。同步腿(`ApprovalCardSchema.ruleOffers` / `card_json`)与耐久腿(durable park 行的
|
|
57
|
-
* `PendingCheckpoint.ruleOffers`,由 `plugins/checkpoint-store-
|
|
57
|
+
* `PendingCheckpoint.ruleOffers`,由 `plugins/checkpoint-store-face.ts` 的 `boundedRuleOffers` 窄读)**共用这一份**。
|
|
58
58
|
*
|
|
59
59
|
* 🔴 单一属主(宪法 [ref]「schema 单一属主禁复制」):两条腿投的是 core 的**同一个** `RuleOffer`
|
|
60
60
|
* (同步腿 = `AskRequest.ruleOffers`,耐久腿 = `PendingAction.ruleOffers`,core
|
|
@@ -138,7 +138,7 @@ export interface ReadRuleOffer {
|
|
|
138
138
|
readonly offer: RuleOffer;
|
|
139
139
|
}
|
|
140
140
|
/**
|
|
141
|
-
* **规则提议列表的唯一读者**(core 7.55.0 [ref] P1 阶段二)—— 两条腿同调:耐久腿(`checkpoint-store-
|
|
141
|
+
* **规则提议列表的唯一读者**(core 7.55.0 [ref] P1 阶段二)—— 两条腿同调:耐久腿(`checkpoint-store-face.ts` `boundedRuleOffers`:铸行落列、回读列、LOCAL 孪生读寄存行)
|
|
142
142
|
* 与同步腿(`tool-approval.ts` `boundRuleOfferTexts`:活 ask 的 `AskRequest.ruleOffers`)。判官是 core 的 `readRuleOffers`:逐元素判、保原始下标、多余键逐级剥、
|
|
143
143
|
* 闭集词(offer / 成员的 `kind`、`match`)不认 ⇒ 整只丢(batch 不拆成员)、无 `kind` 的存量成员读作 command、明细座不是「每个计数段一行」⇒ 只丢座。
|
|
144
144
|
* 修前本仓自己一份不限长 zod 形,前面垫两只预筛(无 `kind` 成员的回填、明细座的座级筛)—— 读的是 core 铸的形,读法却是本仓一份;core 对两者的 76 种形逐一对过,不同的三种是本仓的明细座行数帽(留在这里)与两种非 JSON 值(数组带属性、类实例)。
|
|
@@ -149,15 +149,6 @@ export interface ReadRuleOffer {
|
|
|
149
149
|
* 缺席(`undefined`)= 没有提议,答空、不计。展示帽(条数、成员前缀、扫描窗)、脱敏与截长归调用方 —— 它们是各腿的展示纪律,不是读法。
|
|
150
150
|
*/
|
|
151
151
|
export declare function readRuleOfferList(raw: unknown): readonly ReadRuleOffer[];
|
|
152
|
-
/**
|
|
153
|
-
* 一份(已解码的)规则提议列表里,**带着无 `kind` 存量成员**的 batch offer 有几只 —— 判官是 core `readRuleOffers` 给每只读出的 offer 打的 `kindlessForm` 记号
|
|
154
|
-
* (「这一只 batch 里至少一个成员是经无 `kind` 的存量形读的」;与 {@link readRuleOfferList} 同一只读者,不是本仓自己再写一遍「成员没有 `kind` 键」)。
|
|
155
|
-
* 起服普查(`approval-batch-census.ts`)用它给存量行记数:读者那条存量臂退役的前提是「零行还靠它读」。
|
|
156
|
-
*
|
|
157
|
-
* **只数,不落任何痕迹**:读不出的元素(`dropped`)与整只值不是列表(`problem`)是 {@link readRuleOfferList} 的计数口径(`server.rule-offers.offer-dropped`),这里不重复记,
|
|
158
|
-
* 它们也不是「靠存量臂读出来」的 —— 一个读不出的无 `kind` 成员(缺文本键)退役前后同样被丢,不改变任何一行的读法,所以不计入。
|
|
159
|
-
*/
|
|
160
|
-
export declare function countKindlessBatchOffers(raw: unknown): number;
|
|
161
152
|
/**
|
|
162
153
|
* 卡面/帧面共用的 offer **投影型**(= {@link RuleOfferSchema} 的输出形)。判别位 `kind` 上闭集,
|
|
163
154
|
* 消费端(SDK/cli 渲染)按 core 契约分臂;`batch.rules` 成员是判别联合(`command` | `directoryRead`),
|
|
@@ -518,7 +509,7 @@ export declare function parkRowFacts(stored: unknown): ParkRowFacts;
|
|
|
518
509
|
* 本仓**不重算哈希**(core 的 `boundInputHashOf` 不在公开导出面上,清单校验读口 `readBoundBinding` 同样不导出),所以**不许**拿寄存行 `pendingAction` 上的原清单直接投 ——
|
|
519
510
|
* 原值上的清单是未经哈希校验的(这正是它此前不上队列行的原因,见 `trace/core-keyset-guard.ts` ⑧b 记账的旧注)。两只店各自拿到「这一行的摘要」的办法不同
|
|
520
511
|
* (LOCAL 孪生本来就握着 core 对同一行投的摘要;SQL 孪生在判官要的那一次整行读里调 core 的 `summarizeCheckpoint` —— 两位与 `rowVerdict` 同一次读、
|
|
521
|
-
* 同一份按字节摘要的记忆,见 `
|
|
512
|
+
* 同一份按字节摘要的记忆,见 `stores-sql/checkpoint-store-sql.ts` 的 `storedRowProjections`),
|
|
522
513
|
* 但投影只有这一只:OMIT 契约 —— 缺席即缺席,恒不铸 `undefined` 值的键。
|
|
523
514
|
*
|
|
524
515
|
* `boundGrants` 是**部署文本**(技能名、清单条目):本函数不脱敏、不转义,与收件箱行逐字同口径 —— 渲染按上下文转义是客户端的事(契约同句)。
|
package/dist/approval-card.js
CHANGED
|
@@ -64,10 +64,6 @@ export function readRuleOfferList(raw) {
|
|
|
64
64
|
reading.dropped.forEach((d) => recordOfferDropped(d.problem, d.index));
|
|
65
65
|
return reading.offers.map(withDetailSeatBounded);
|
|
66
66
|
}
|
|
67
|
-
export function countKindlessBatchOffers(raw) {
|
|
68
|
-
const reading = readRuleOffers(raw);
|
|
69
|
-
return "problem" in reading ? 0 : reading.offers.filter((o) => o.kindlessForm === true).length;
|
|
70
|
-
}
|
|
71
67
|
function withoutOverCapDetailSeat(item, index) {
|
|
72
68
|
if (typeof item !== "object" || item === null)
|
|
73
69
|
return item;
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
* (时刻与方向两处自 core 7.56.0 [ref] 起由筛判:I10 / I11。trace 投影读同一种记录、经同一只筛,零改即得 I10 —— 坏时刻在两个读者那里是同一个答法。)
|
|
66
66
|
*/
|
|
67
67
|
import { type Checkpoint, type CheckpointToken, type SettlementKind } from "@sema-agent/core";
|
|
68
|
-
import { type PendingRowBinding } from "./plugins/checkpoint-store-
|
|
68
|
+
import { type PendingRowBinding } from "./plugins/checkpoint-store-face.js";
|
|
69
69
|
import { type ParkedGateRead } from "./tool-approval.js";
|
|
70
70
|
/**
|
|
71
71
|
* 决断方回显的「我看到的那道门」—— 门的两个身份面之一(两面的来历与读法见模块头注「`approval_stale` 律」)。
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { REOPEN_REASONS, checkpointRevOf, screenGateOutcome } from "@sema-agent/core";
|
|
2
|
-
import { approvalDecisionOfWinner } from "./plugins/checkpoint-store-
|
|
2
|
+
import { approvalDecisionOfWinner } from "./plugins/checkpoint-store-face.js";
|
|
3
3
|
import {} from "./tool-approval.js";
|
|
4
4
|
import { APPROVAL_GATE_KINDS } from "./approval-content-kind.js";
|
|
5
5
|
import { trustedCheckpointId } from "./checkpoint-identity.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AskRow, ApprovalAskStore } from "./plugins/approval-ask-store-sql.js";
|
|
2
2
|
import type { UnattendedApprovalPolicy } from "./tool-approval.js";
|
|
3
3
|
import type { BatchState } from "./approval-ask-machine.js";
|
|
4
|
-
import type { CheckpointAskCandidate } from "./plugins/checkpoint-store-
|
|
4
|
+
import type { CheckpointAskCandidate } from "./plugins/checkpoint-store-face.js";
|
|
5
5
|
import { type RunRecord } from "./plugins/store-contracts.js";
|
|
6
6
|
import type { Logger } from "./observability/logger.js";
|
|
7
7
|
import type { Metrics } from "./observability/metrics.js";
|
package/dist/audit.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type StoredPromptEpoch } from "@sema-agent/core";
|
|
2
2
|
import type { Pool } from "mysql2/promise";
|
|
3
3
|
import type { Pool as PgPool } from "pg";
|
|
4
4
|
import { type LocalSessionRows } from "./plugins/local-session-window.js";
|
|
@@ -30,31 +30,12 @@ export interface SessionAudit {
|
|
|
30
30
|
* the key entirely (undefined). */
|
|
31
31
|
promptEpoch?: StoredPromptEpoch;
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
34
|
-
* 会话视图体顶层 additive 键 `agent` —— **这只会话是哪只委派子代的转录**(`GET /v1/sessions/:id`;读法:终端侧链投影方按 fleet 帧的 `transcriptId`
|
|
35
|
-
* 读同一只会话读面,从体上拿到子代身份,不必再回头翻 fleet 行 —— 行一离场就没有了)。
|
|
36
|
-
*
|
|
37
|
-
* 只投影**存下来的 placement 元组**(`session_meta` 的 `placement_*` 列,首写不可变;店的 `placementOf` 一行 PK 探针),**不另铸**:
|
|
38
|
-
* · `id` = 元组里的 `handle` —— 耐久 agent 行的 `a…` 键,与 fleet 行的 `id`、`GET /v1/agents/roster` 的 `handle` 是同一个串(core 铸元组时 `handle: taskId`);
|
|
39
|
-
* · `parentSessionId` / `rootSessionId` = 元组里的同名格(派它的会话 / 委派树的根会话);
|
|
40
|
-
* · 元组缺哪一格这里就缺哪一格(present-iff;不铸空串);元组的 `scope`(租户键)/ `placedAt` / `kind` 不上 wire。
|
|
41
|
-
* 键在场 = 这是一只委派子代的转录(哪怕元组只存了 `kind`,那时 `agent` 是 `{}`);键缺席 = 普通会话,**或这台部署的店不存 placement 元组**
|
|
42
|
-
* (local 后端:子代转录停驻前住私有短 TTL 店、停驻时拷进来的那一份是普通会话行 —— 事实没存就不报,消费方在 fleet 行 / `GET /v1/agents/roster` 上本就有 `id`)。
|
|
43
|
-
* 元组由引擎在**后台**委派子代(带耐久 agent 行、店声明了 placements)建会话时铸;同步委派的子代转录不落宿主店,没有元组。
|
|
44
|
-
*/
|
|
45
|
-
export interface SessionAgent {
|
|
46
|
-
id?: string;
|
|
47
|
-
parentSessionId?: string;
|
|
48
|
-
rootSessionId?: string;
|
|
49
|
-
}
|
|
50
|
-
/** {@link SessionAgent} 的唯一投影:店答出的 placement 元组 → 体上的 `agent` 值;`undefined`(普通会话 / 店没有这一面)⇒ 调用方不铸键。 */
|
|
51
|
-
export declare function sessionAgentOf(placement: SessionPlacementRecord | undefined): SessionAgent | undefined;
|
|
52
33
|
/**
|
|
53
34
|
* 用户消息行的**回退手柄**表:用户条目 id → 回退时交给 `resumeAt` 的那个 `event_id`(R8 用户消息锚按 run 的 taskId 键入)。
|
|
54
35
|
* 真源 = `resume_anchor`(锚店 `listBySession` 的读数),本表只是它对**一位读者**的一次投影。
|
|
55
36
|
*/
|
|
56
37
|
export type RewindHandles = ReadonlyMap<string, string>;
|
|
57
|
-
/** 会话视图读口(`ServiceDeps.sessionAudit`)的读者参数:`reader` = 读这张视图的**已验身份**(无身份 = `null`)。给了 ⇒ 这是一次**视图读**:用户消息行投回退手柄、体顶层投 `agent`(
|
|
38
|
+
/** 会话视图读口(`ServiceDeps.sessionAudit`)的读者参数:`reader` = 读这张视图的**已验身份**(无身份 = `null`)。给了 ⇒ 这是一次**视图读**:用户消息行投回退手柄、体顶层投 `agent`(`session-agent.ts` 的 `readSessionAgent`);
|
|
58
39
|
* 不给(只要归属的调用方:memory-status / 自助抹除)⇒ 两样投影的读都不付。 */
|
|
59
40
|
export interface SessionAuditReadOpts {
|
|
60
41
|
readonly reader: string | null;
|
package/dist/audit.js
CHANGED
|
@@ -6,15 +6,6 @@ import { redactModelText } from "./observability/run-terminal.js";
|
|
|
6
6
|
import { redactDeepWith } from "./trace/redact.js";
|
|
7
7
|
import { projectToolStructured } from "./trace/tool-output-media.js";
|
|
8
8
|
import { INJECTED_BLOCK_RE, isAttachmentFrame } from "./user-authored-text.js";
|
|
9
|
-
export function sessionAgentOf(placement) {
|
|
10
|
-
if (placement === undefined)
|
|
11
|
-
return undefined;
|
|
12
|
-
return {
|
|
13
|
-
...(placement.handle !== undefined ? { id: placement.handle } : {}),
|
|
14
|
-
...(placement.parentSessionId !== undefined ? { parentSessionId: placement.parentSessionId } : {}),
|
|
15
|
-
...(placement.rootSessionId !== undefined ? { rootSessionId: placement.rootSessionId } : {}),
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
9
|
export function buildRewindHandles(anchors, reader) {
|
|
19
10
|
const byEntry = new Map();
|
|
20
11
|
for (const a of anchors) {
|
|
@@ -40,11 +40,21 @@ export interface LoadedModPackage {
|
|
|
40
40
|
/** 读包者交回的三件字节摘要(`ModPackageRegistration.digest`,按给值记)—— 认得出「装的是哪几份字节」,不是代码完整性凭据。 */
|
|
41
41
|
readonly digest: string;
|
|
42
42
|
}
|
|
43
|
-
/** 装配的结果:部署座的注册(自铸在前、声明在后,整列已过引擎准入)
|
|
43
|
+
/** 装配的结果:部署座的注册(自铸在前、声明在后,整列已过引擎准入)、装上的声明包(只数声明的包,自铸的不算)与部署座的链站点式样。 */
|
|
44
44
|
export interface DeploymentModsAssembly {
|
|
45
45
|
readonly registrations: readonly ModRegistration<EngineDollar>[];
|
|
46
46
|
readonly loaded: readonly LoadedModPackage[];
|
|
47
|
+
/** 部署座在**任务座之下**挂了链成员(不是观察者)的站点式样 —— 引擎这一次准入的记录读出({@link belowTaskChainPatternsOf})。读者:请求 `settings.hooks` 托管车道的只许收紧判据(`hooks/hook-runner.ts` 的 `managedTightenOnlyOn`)。 */
|
|
48
|
+
readonly belowTaskChainPatterns: readonly string[];
|
|
47
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* 部署座在**任务座之下**挂了链成员的站点式样(去重,按准入序)。「之下」按引擎的跑序读:先按档(`MOD_TIERS` 的序),同档里部署座在任务座之前 ⇒
|
|
52
|
+
* 只有档排在任务座档之后的部署注册(今天是 `append`)在任务座之下;`prepend` 与同档 `user` 的部署注册在任务座之上(它们先判、再在答回来的结果上判,运维 handler 恒在请求钩子之上)。
|
|
53
|
+
* 每张准入了的、站在任务座之下的部署注册取 `events`(引擎记下的、它真挂了 handler 的式样)减去 `observe`(那张注册在该式样上只挂了观察者)。
|
|
54
|
+
* 读的是引擎的准入记录,不是注册自报的 `uses` —— 一处事实一个读法。式样的文法(精确站名或 `<前缀>.*`)由读者按引擎的定义读(`hooks/hook-runner.ts` 的 `chainsBelowTaskOn`)。
|
|
55
|
+
* 是**上界**:记录不带匹配器,带匹配器的 handler 在不中的那一次派发里不进链(引擎按派发取链)⇒ 读者只拿它收紧、从不拿它换挂法或放宽。
|
|
56
|
+
*/
|
|
57
|
+
export declare function belowTaskChainPatternsOf(records: readonly ModAdmissionRecord[]): readonly string[];
|
|
48
58
|
/** 部署座的唯一装配口(两只起服入口同调;三段与失败见文件头注)。 */
|
|
49
59
|
export declare function assembleDeploymentMods(input: {
|
|
50
60
|
readonly metrics: Pick<Metrics, "inc">;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { realpathSync, statSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, relative, sep } from "node:path";
|
|
3
|
-
import { admitModChain, KERNEL_CONTRACT_VERSION, loadModPackage } from "@sema-agent/core";
|
|
3
|
+
import { admitModChain, KERNEL_CONTRACT_VERSION, loadModPackage, MOD_TIERS } from "@sema-agent/core";
|
|
4
4
|
import { createBrandIdentityRegistration } from "../capabilities/brand-identity.js";
|
|
5
5
|
import { createPermissionDeniedMeter, createToolTracer } from "../observability/tool-trace.js";
|
|
6
6
|
import { errorCodeOf, errorText } from "../observability/err-text.js";
|
|
@@ -14,6 +14,19 @@ export function createDeploymentMods(input) {
|
|
|
14
14
|
...(input.brandIdentity === true ? [createBrandIdentityRegistration()] : []),
|
|
15
15
|
].map((registration) => ({ ...registration, provenance: MOD_PROVENANCE.minted }));
|
|
16
16
|
}
|
|
17
|
+
const TASK_SEAT_TIER = "user";
|
|
18
|
+
export function belowTaskChainPatternsOf(records) {
|
|
19
|
+
const out = new Set();
|
|
20
|
+
const taskTier = MOD_TIERS.indexOf(TASK_SEAT_TIER);
|
|
21
|
+
for (const r of records) {
|
|
22
|
+
if (r.seat !== "deployment" || "refusedBy" in r || MOD_TIERS.indexOf(r.tier) <= taskTier)
|
|
23
|
+
continue;
|
|
24
|
+
for (const p of r.events)
|
|
25
|
+
if (!(r.observe ?? []).includes(p))
|
|
26
|
+
out.add(p);
|
|
27
|
+
}
|
|
28
|
+
return [...out];
|
|
29
|
+
}
|
|
17
30
|
export async function assembleDeploymentMods(input) {
|
|
18
31
|
const minted = createDeploymentMods(input);
|
|
19
32
|
const resolved = resolveDeclaredPackages(input.declaration);
|
|
@@ -25,7 +38,7 @@ export async function assembleDeploymentMods(input) {
|
|
|
25
38
|
const loaded = resolved.map(({ pkg }, i) => ({ name: pkg.name, tier: admittedRecordOf(records, pkg.name).tier, contract: KERNEL_CONTRACT_VERSION, digest: declared[i].digest }));
|
|
26
39
|
for (const row of loaded)
|
|
27
40
|
input.logger.info("mods_package_loaded", { name: sanitizeWireText(row.name), tier: row.tier, contract: row.contract, digest: row.digest });
|
|
28
|
-
return { registrations, loaded };
|
|
41
|
+
return { registrations, loaded, belowTaskChainPatterns: belowTaskChainPatternsOf(records) };
|
|
29
42
|
}
|
|
30
43
|
function fsCauseOf(e) {
|
|
31
44
|
const code = errorCodeOf(e);
|
package/dist/boot/device-lane.js
CHANGED
|
@@ -30,12 +30,14 @@ export function createDeviceLane(ctx) {
|
|
|
30
30
|
...(knobs?.reconnectGraceMs != null ? { reconnectGraceMs: knobs.reconnectGraceMs } : {}),
|
|
31
31
|
...(knobs?.maxInflightPerDevice != null ? { maxInflightPerDevice: knobs.maxInflightPerDevice } : {}),
|
|
32
32
|
...(knobs?.maxPreAuthPerRemote !== undefined ? { maxPreAuthConnectionsPerRemote: knobs.maxPreAuthPerRemote } : {}),
|
|
33
|
+
...(knobs?.trustedProxyCidrs !== undefined ? { trustedProxyCidrs: knobs.trustedProxyCidrs } : {}),
|
|
33
34
|
...(knobs?.supersede ? { supersede: knobs.supersede } : {}),
|
|
34
35
|
});
|
|
35
36
|
logger.info("device_lane_enabled", {
|
|
36
37
|
replicaId,
|
|
37
38
|
maxInflightPerDevice: knobs?.maxInflightPerDevice ?? 4,
|
|
38
39
|
maxPreAuthPerRemote: knobs?.maxPreAuthPerRemote ?? 8,
|
|
40
|
+
trustedProxyCidrs: knobs?.trustedProxyCidrs?.length ?? 0,
|
|
39
41
|
enrollRateLimit: `${DEVICE_ENROLL_RATE_POLICY.limit}/${DEVICE_ENROLL_RATE_POLICY.windowMs / 1000}s per caller identity (per replica; independent of RATE_LIMIT_RPM)`,
|
|
40
42
|
});
|
|
41
43
|
return { store, enrollment, hub, seat };
|